Array ('subitem' => true), 'OnCleanResizedImages' => Array ('subitem' => true), ); $this->permMapping = array_merge($this->permMapping, $permissions); } function mapEvents() { parent::mapEvents(); // ensure auto-adding of approve/decine and so on events $image_events = Array( 'OnAfterCopyToTemp'=>'ImageAction', 'OnBeforeDeleteFromLive'=>'ImageAction', 'OnBeforeCopyToLive'=>'ImageAction', 'OnBeforeItemDelete'=>'ImageAction', 'OnAfterClone'=>'ImageAction', ); $this->eventMethods = array_merge($this->eventMethods, $image_events); } /** * Get's special of main item for linking with subitem * * @param kEvent $event * @return string */ function getMainSpecial(&$event) { if ($event->Special == 'list' && !$this->Application->isAdmin) { // ListImages aggregated tag uses this special return ''; } return parent::getMainSpecial($event); } function customProcessing(&$event, $type) { $object =& $event->GetObject(); switch ($type) { case 'before' : if ($object->GetDBField('LocalImage')) { $object->SetDBField('Url', ''); } else { $object->SetDBField('LocalPath', ''); } if ($object->GetDBField('LocalThumb')) { $object->SetDBField('ThumbUrl', ''); } else { $object->SetDBField('ThumbPath', ''); } if ($object->GetDBField('SameImages')) { $object->SetDBField('LocalImage', 1); $object->SetDBField('LocalPath', ''); $object->SetDBField('Url', ''); } break; case 'after' : if ($object->GetDBField('DefaultImg') ) { $sql = 'UPDATE '.$object->TableName.' SET DefaultImg=0 WHERE ResourceId='. $object->GetDBField('ResourceId').' AND ImageId<>'. $object->GetId(); $res = $this->Conn->Query($sql); } break; default: } } function ImageAction(&$event) { $id = $event->getEventParam('id'); $object =& $this->Application->recallObject($event->Prefix.'.-item', $event->Prefix, Array ('skip_autoload' => true)); /* @var $object kDBItem */ if (in_array($event->Name, Array('OnBeforeDeleteFromLive','OnAfterClone')) ) { $object->SwitchToLive(); } elseif ($event->Name == 'OnBeforeItemDelete') { // keep current table } else { $object->SwitchToTemp(); } $object->Load($id); $fields = Array('LocalPath' => 'LocalImage', 'ThumbPath' => 'LocalThumb'); foreach ($fields as $a_field => $mode_field) { $file = $object->GetField($a_field); if (!$file) continue; $source_file = FULL_PATH.$file; switch ($event->Name) { // Copy image files to pending dir and update corresponding fields in temp record // Checking for existing files and renaming if nessessary - two users may upload same pending files at the same time! case 'OnAfterCopyToTemp': $new_file = IMAGES_PENDING_PATH . $this->ValidateFileName(FULL_PATH.IMAGES_PENDING_PATH, basename($file)); $dest_file = FULL_PATH.$new_file; copy($source_file, $dest_file); $object->SetFieldOption($a_field, 'skip_empty', false); $object->SetDBField($a_field, $new_file); break; // Copy image files to live dir (checking if fileexists and renameing if nessessary) // and update corresponding fields in temp record (which gets copied to live automatically) case 'OnBeforeCopyToLive': if ( $object->GetDBField($mode_field) ) { // if image is local // rename file if it exists in live folder $new_file = IMAGES_PATH . $this->ValidateFileName(FULL_PATH.IMAGES_PATH, basename($file)); $dest_file = FULL_PATH.$new_file; rename($source_file, $dest_file); } else { // if image is remote url - remove local file (if any), update local file field with empty value if (file_exists($source_file)) @unlink($source_file); $new_file = ''; } $object->SetFieldOption($a_field, 'skip_empty', false); $object->SetDBField($a_field, $new_file); break; case 'OnBeforeDeleteFromLive': // Delete image files from live folder before copying over from temp case 'OnBeforeItemDelete': // Delete image files when deleteing Image object @unlink(FULL_PATH.$file); break; case 'OnAfterClone': // Copy files when cloning objects, renaming it on the fly $path_info = pathinfo($file); $new_file = $path_info['dirname'].'/'.$this->ValidateFileName(FULL_PATH.$path_info['dirname'], $path_info['basename']); $dest_file = FULL_PATH . $new_file; copy($source_file, $dest_file); $object->SetFieldOption($a_field, 'skip_empty', false); $object->SetDBField($a_field, $new_file); break; } } if ( in_array($event->Name, Array('OnAfterClone', 'OnBeforeCopyToLive', 'OnAfterCopyToTemp')) ) { $object->Update(null, true); } } function ValidateFileName($path, $name) { $parts = pathinfo($name); $ext = '.'.$parts['extension']; $filename = mb_substr($parts['basename'], 0, -mb_strlen($ext)); $new_name = $filename.$ext; while ( file_exists($path.'/'.$new_name) ) { if ( preg_match('/('.preg_quote($filename, '/').'_)([0-9]*)('.preg_quote($ext, '/').')/', $new_name, $regs) ) { $new_name = $regs[1].($regs[2]+1).$regs[3]; } else { $new_name = $filename.'_1'.$ext; } } return $new_name; } /** * Enter description here... * * @param kEvent $event */ function OnSetPrimary(&$event) { $object =& $event->getObject(); $object->SetDBField('DefaultImg', 1); $object->Update(); } /** * Enter description here... * * @param kEvent $event */ function OnBeforeItemUpdate(&$event) { $object =& $event->getObject(); // $parent_info = $object->getLinkedInfo(); $id = $object->GetDBField('ResourceId'); // $id = $parent_info['ParentId'] ? $parent_info['ParentId'] : $this->Application->GetVar('p_id'); $sql = 'SELECT ImageId FROM '.$object->TableName.' WHERE ResourceId='.$id.' AND DefaultImg=1'; if(!$this->Conn->GetOne($sql)) { $object->SetDBField('DefaultImg', 1); } if($object->GetDBField('DefaultImg') && $object->Validate()) { $sql = 'UPDATE '.$object->TableName.' SET DefaultImg = 0 WHERE ResourceId = '.$id.' AND ImageId <> '.$object->GetDBField('ImageId'); $this->Conn->Query($sql); $object->SetDBField('Enabled', 1); } } function OnAfterItemCreate(&$event) { $event->CallSubEvent('OnBeforeItemUpdate'); $object =& $event->getObject(); $object->Update(); } /** * Deletes all selected items. * Automatically recurse into sub-items using temp handler, and deletes sub-items * by calling its Delete method if sub-item has AutoDelete set to true in its config file * * @param kEvent $event */ function OnMassDelete(&$event) { if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) { $event->status = kEvent::erFAIL; return; } $event->status=kEvent::erSUCCESS; $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler'); $event->setEventParam('ids', $this->StoreSelectedIDs($event) ); $this->customProcessing($event, 'before'); $ids = $event->getEventParam('ids'); $object =& $event->getObject(); $sql = 'SELECT ImageId FROM '.$object->TableName.' WHERE DefaultImg=1'; $primary = $this->Conn->GetOne($sql); if( $primary && ($key = array_search($primary, $ids)) ) { $sql = 'SELECT ImageId FROM '.$object->TableName.' WHERE DefaultImg=0'; $res = $this->Conn->Query($sql); if($res) { unset($ids[$key]); } } if($ids) { $temp->DeleteItems($event->Prefix, $event->Special, $ids); } $this->clearSelectedIDs($event); } /*function OnAfterItemLoad(&$event) { $object =& $event->getObject(); if ( $object->GetDBField('ThumbPath') || $object->GetDBField('SameImages') ) { // return local image or url $path = $object->GetDBField('LocalThumb') ? PROTOCOL.SERVER_NAME.BASE_PATH.$object->GetDBField('ThumbPath') : $object->GetDBField('ThumbUrl'); if ( $object->GetDBField('LocalThumb') && !file_exists(FULL_PATH.$object->GetDBField('ThumbPath')) ) $path = ''; } else { // if we need full which is not the same as thumb $path = $object->GetDBField('LocalImage') ? PROTOCOL.SERVER_NAME.BASE_PATH.$object->GetDBField('LocalPath') : $object->GetDBField('Url'); if ( $object->GetDBField('LocalImage') && !file_exists(FULL_PATH.$object->GetDBField('LocalPath')) ) $path = ''; } $object->SetDBField('ImageUrl', $path); }*/ function SetCustomQuery(&$event) { parent::SetCustomQuery($event); $object =& $event->getObject(); /* @var $object kDBList */ if (!$this->Application->isAdminUser) { $object->addFilter('active', '%1$s.Enabled = 1'); } $product_id = $event->getEventParam('product_id'); if ($product_id) { $object->removeFilter('parent_filter'); $sql = 'SELECT ResourceId FROM '.$this->Application->getUnitOption('p', 'TableName').' WHERE ProductId = '.$product_id; $resource_id = (int) $this->Conn->GetOne($sql); $object->addFilter('product_images', '%1$s.ResourceId = '.$resource_id); } /********************************************/ $search_helper =& $this->Application->recallObject('SearchHelper'); /* @var $search_helper kSearchHelper */ $types = $event->getEventParam('types'); $except_types = $event->getEventParam('except'); $type_clauses = $this->getTypeClauses($event); $search_helper->SetComplexFilter($event, $type_clauses, $types, $except_types); } /** * Return type clauses for list bulding on front * * @param kEvent $event * @return Array */ function getTypeClauses(&$event) { $type_clauses = Array (); $type_clauses['additional']['include'] = '%1$s.DefaultImg != 1'; $type_clauses['additional']['except'] = '%1$s.DefaultImg = 1'; $type_clauses['additional']['having_filter'] = false; return $type_clauses; } /** * [AGENT] Remove unused images from "/system/images" and "/system/images/pending" folders * * @param kEvent $event */ function OnCleanImages(&$event) { // 1. get images, that are currently in use $active_images = $this->_getActiveImages( $this->Application->getUnitOption('img', 'TableName') ); $active_images[] = 'noimage.gif'; // 2. get images on disk $this->_deleteUnusedImages(FULL_PATH . IMAGES_PATH, $active_images); // 3. get images in use from "images/pending" folder $active_images = $this->_getPendingImages(); // 4. get image on disk $this->_deleteUnusedImages(FULL_PATH . IMAGES_PENDING_PATH, $active_images); } /** * Gets image filenames (no path) from given table * * @param string $image_table * @return Array */ function _getActiveImages($image_table) { $sql = 'SELECT LocalPath, ThumbPath FROM ' . $image_table . ' WHERE COALESCE(LocalPath, "") <> "" OR COALESCE(ThumbPath) <> ""'; $images = $this->Conn->Query($sql); $active_images = Array (); foreach ($images as $image) { if ($image['LocalPath']) { $active_images[] = basename($image['LocalPath']); } if ($image['ThumbPath']) { $active_images[] = basename($image['ThumbPath']); } } return $active_images; } /** * Gets active images, that are currently beeing edited inside temporary tables * * @return Array */ function _getPendingImages() { $tables = $this->Conn->GetCol('SHOW TABLES'); $mask_edit_table = '/'.TABLE_PREFIX.'ses_(.*)_edit_' . TABLE_PREFIX . 'Images/'; $active_images = Array (); foreach ($tables as $table) { if (!preg_match($mask_edit_table, $table)) { continue; } $active_images = array_unique( array_merge($active_images, $this->_getActiveImages($table)) ); } return $active_images; } /** * Deletes all files in given path, except of given $active_images * * @param string $path * @param Array $active_images */ function _deleteUnusedImages($path, &$active_images) { $images = glob($path . '*.*'); if ($images) { $images = array_map('basename', $images); // delete images, that are on disk, but are not mentioned in Images table $delete_images = array_diff($images, $active_images); foreach ($delete_images as $delete_image) { unlink($path . $delete_image); } } } /** * [AGENT] Remove all images from "/system/images/resized" and "/system/images/pending/resized" folders * * @param kEvent $event */ function OnCleanResizedImages(&$event) { $images = glob(FULL_PATH . IMAGES_PATH . 'resized/*.*'); if ($images) { foreach ($images as $image) { unlink($image); } } $images = glob(FULL_PATH . IMAGES_PENDING_PATH . 'resized/*.*'); if ($images) { foreach ($images as $image) { unlink($image); } } } }