success++; } else { $this->failed++; } } $path = realpath($cfg['Path']['data'].'tmp/'); $objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST); $folders = []; foreach ($objects as $path => $object) { $folder_name = substr($path, strrpos($path, '/') + 1, strlen($path)); if (ctype_digit($folder_name) && strlen($folder_name) == 1) { $folders[] = $path; } } $folders = array_reverse($folders); foreach ($folders as $folder) { @rmdir($folder); } } public function handleImageVersionUpgrade() { $dbcfg = Settings::getDefault(); $lastImageVersion = $dbcfg->loadValue('image_version'); $dbcfg->saveValue('image_version', $lastImageVersion ? $lastImageVersion + 1 : 2); $dbcfg->clearCache(); $this->success++; } public function handleCacheSections() { clearCache('sections', true); $this->success++; } public function handleCacheRuntime() { clearCache('', true); $this->success++; } public function handleCacheTemplates() { global $cfg; foreach (glob($cfg['Path']['data'].'tmp/templates/*') as $file) { if (@unlink($file)) { $this->success++; } else { $this->failed++; } } } public function handleCacheFeeds() { global $cfg; foreach (glob($cfg['Path']['data'].'tmp/feed_*_*') as $file) { if (@unlink($file)) { $this->success++; } else { $this->failed++; } } } public function handleCacheSitemap() { $cfg = Config::get(); foreach (glob($cfg['Path']['data'].'tmp/sitemap*') as $file) { if (@unlink($file)) { $this->success++; } else { $this->failed++; } } } public function handleCacheStatic() { global $cfg; foreach (glob($cfg['Path']['data'].'tmp/cache/*') as $file) { if (@unlink($file)) { $this->success++; } else { $this->failed++; } } $this->handleCacheRuntime(); } // Photos public function getImagesUnused() { $SQL = sqlQuery('SELECT id FROM photos p LEFT JOIN photos_products_relation ppr ON p.id = ppr.id_photo LEFT JOIN photos_articles_relation ppa ON p.id = ppa.id_photo LEFT JOIN photos_menu_relation par ON p.id = par.id_photo LEFT JOIN photos_blocks_relation blo ON p.id = blo.id_photo LEFT JOIN photos_blocks_new_relation bln ON p.id = bln.id_photo LEFT JOIN photos_sections_relation psr ON p.id = psr.id_photo WHERE ppr.id_product IS NULL AND ppa.id_art IS NULL AND par.id_menu IS NULL AND blo.id_block IS NULL AND bln.id_block IS NULL AND psr.id_section IS NULL'); $files = sqlFetchAll($SQL); return $files; } public function handleCacheImagesType() { if (($type = getVal('type')) !== null) { $this->clearImageTypeCache($type); } } // clear cache only of defined photo type public function clearImageTypeCache($type) { $cfg = Config::get(); if (!isset($cfg['Photo']['id_to_type'][$type])) { return; } foreach (glob($cfg['Path']['data'].'tmp/'.$type.'/*/*.*') as $file) { if (@unlink($file)) { $this->success++; } else { $this->failed++; } } $path = realpath($cfg['Path']['data'].'tmp/'.$type.'/'); $objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST); $folders = []; foreach ($objects as $path => $object) { $folder_name = substr($path, strrpos($path, '/') + 1, strlen($path)); if (ctype_digit($folder_name) && strlen($folder_name) == 1) { $folders[] = $path; } } $folders = array_reverse($folders); foreach ($folders as $folder) { @rmdir($folder); } } public function handleImagesUnused() { $files = $this->getImagesUnused(); $img = new Photos('product'); foreach ($files as $file) { if ($img->erasePhoto($file['id'])) { $this->success++; } else { $this->failed++; } } } public function getImagesFiles() { global $cfg; $dir = $cfg['Path']['photos']; $dirIterator = new RecursiveDirectoryIterator($dir, FilesystemIterator::KEY_AS_PATHNAME | FilesystemIterator::CURRENT_AS_PATHNAME | FilesystemIterator::SKIP_DOTS); $dirIterator = new RecursiveCallbackFilterIterator($dirIterator, function ($current, $key, $iterator) use ($dir) { // Avoid sliders folder if ($key === $dir.'sliders') { return false; } return true; }); $files = iterator_to_array(new RecursiveIteratorIterator($dirIterator)); $db_images = sqlQuery('SELECT CONCAT(:dir, source, image_2) AS path FROM `photos`', ['dir' => $dir]); $db_images = sqlFetchAll($db_images, ['path' => 'path']); $files = array_filter($files, function ($file) use ($db_images) { return !isset($db_images[$file]); }); return $files; } public function handleImagesFiles() { $files = $this->getImagesFiles(); foreach ($files as $file) { if (@unlink($file)) { $this->success++; } else { $this->failed++; } } } public function handleImagesCorrupted() { global $cfg; $db_images = sqlQuery('SELECT CONCAT(:dir, source, image_2) AS path, id FROM `photos`', ['dir' => $cfg['Path']['photos']]); $corrupted_id = []; foreach ($db_images as $file) { if (!file_exists($file['path']) || filesize($file['path']) <= 0/* && wpj_open_image($source) */) { $corrupted_id[] = $file['id']; $this->success++; } } if (!empty($corrupted_id)) { sqlQuery('DELETE FROM `photos` WHERE id IN ('.join(', ', $corrupted_id).')'); } } public function getImagesMissingMain() { return sqlFetchAll(sqlQuery('SELECT id_product FROM photos_products_relation GROUP BY id_product HAVING MAX(show_in_lead)=\'N\''), 'id_product'); } public function handleImagesMissingMain() { $IDs = $this->getImagesMissingMain(); foreach ($IDs as $id_product => $_) { Photos::checkLeadPhoto('photos_products_relation', 'id_product', $id_product); } } // Products public function handleProductsAll() { $this->success = $this->deleteSQL('products', ['1' => '1']); } public function handleProductsAnnotation() { foreach (sqlQuery('SELECT id, short_descr FROM products') as $product) { $product['short_descr'] = trim(html_entity_decode(strip_tags($product['short_descr']))); $this->success += $this->updateSQL('products', $product, ['id' => $product['id']], ['id']); } if (findModule(\Modules::TRANSLATIONS)) { foreach (sqlQuery('SELECT id, short_descr FROM products_translations') as $product) { $product['short_descr'] = trim(html_entity_decode(strip_tags($product['short_descr']))); $this->success += $this->updateSQL('products_translations', $product, ['id' => $product['id']], ['id']); } } } public function handleProductsDescriptions() { foreach (sqlQuery('SELECT id, short_descr, long_descr FROM products') as $product) { $product['short_descr'] = trim(html_entity_decode(strip_tags($product['short_descr']))); $product['long_descr'] = trim(html_entity_decode(strip_tags($product['long_descr']))); $this->success += $this->updateSQL('products', $product, ['id' => $product['id']], ['id']); } } // Parameters public function handleParameters() { $this->success = $this->deleteSQL('parameters', ['1' => '1']); } public function handleParametersValues() { $this->success = $this->deleteSQL('parameters_list', ['1' => '1']); } // Sections public function handleSections() { $this->success = $this->deleteSQL('sections', ['(id = 0)' => 'FALSE']); clearCache('sections', true); } public function handleSectionsEmpty() { $SQL = sqlQuery('DELETE s FROM sections s LEFT JOIN products_in_sections ps ON ps.id_section = s.id LEFT JOIN sections_relation sr ON sr.id_topsection = s.id WHERE ps.id_product IS NULL AND sr.id_section IS NULL AND s.id <> 0 '); $this->success = sqlNumRows($SQL); MenuSectionTree::invalidateCache(); clearCache('sections', true); } // Producers public function handleProducers() { $this->success = $this->deleteSQL('producers', ['1' => '1']); } // Orders public function handleOrders() { $this->success = $this->deleteSQL('orders', ['1' => '1']); } // Articles public function handleArticles() { $this->success = $this->deleteSQL('articles', ['1' => '1']); } // Users public function handleUsers() { $this->success = $this->deleteSQL('users', ['1' => '1']); } // Variations public function handleVariationsDuplicates() { $duplicates = sqlQuery('SELECT t.id_product, GROUP_CONCAT(t.id ORDER BY t.id SEPARATOR \',\') id_variations FROM ( SELECT pv.id, pv.id_product, GROUP_CONCAT(pvc.id_value ORDER BY pvc.id_value SEPARATOR \'-\') vals FROM products_variations pv JOIN products_variations_combination pvc ON pv.id = pvc.id_variation GROUP BY pv.id ) AS t GROUP BY t.id_product, t.vals HAVING COUNT(*) > 1'); foreach ($duplicates as $duplicate) { $variations = explode(',', $duplicate['id_variations']); array_shift($variations); $this->success += sqlQueryBuilder()->delete('products_variations')->where(\Query\Operator::inIntArray($variations, 'id'))->execute(); } } public function handleRegenerateVariationsTitles() { Variations::updateTitle(); } public function handleFulltextUpdate() { $fulltext = ServiceContainer::getService(FulltextInterface::class); $contextManager = ServiceContainer::getService(ContextManager::class); $languages = $fulltext->getFulltextLanguages(); if ($lang = getVal('fulltext_language')) { $languages = [$lang => $languages[$lang]]; } foreach ($languages as $language => $_) { $contextManager->activateContexts([LanguageContext::class => $language], function () use ($fulltext) { $fulltext->updateIndex(getVal('fulltext_index')); $this->success++; }); } } // Reviews public function handleReviewsImport() { $reviews = ServiceContainer::getService(\KupShop\CatalogBundle\Util\ReviewsUtil::class); $this->success = $reviews->importReviews(); if ($reviews->getError()) { $this->returnError($reviews->getError()); } } public function handleReviewsAutoConfirm() { $reviews = ServiceContainer::getService(\KupShop\CatalogBundle\Util\ReviewsUtil::class); $this->success = $reviews->autoConfirm(); } public function handleCronFrequent() { $this->handleCron('FREQUENT'); } public function handleCronNormal() { $this->handleCron('NORMAL'); } public function handleCronExpensive() { $this->handleCron('EXPENSIVE'); } protected function handleCron(string $type) { /** @var \Symfony\Component\EventDispatcher\EventDispatcher $dispatcher */ $dispatcher = ServiceContainer::getService('event_dispatcher'); $event = new CronEvent($type); $dispatcher->dispatch($event, constant('KupShop\KupShopBundle\Event\CronEvent::RUN_'.$type)); } public function handleRunScript() { $script = getVal('script'); if ($script) { ServiceContainer::getService(ScriptLocator::class)->runScript($script, getVal('script_parameters')); exit("\n============ DONE =============="); } } public function getCounts() { global $cfg; $counts = []; // Cache $counts['cacheImages'] = ['count' => count(glob($cfg['Path']['data'].'tmp/*/*/*.*'))]; $counts['cacheSections'] = ['count' => 1]; $counts['cacheTemplates'] = ['count' => count(glob($cfg['Path']['data'].'tmp/templates/*'))]; $counts['cacheStatic'] = ['count' => count(glob($cfg['Path']['data'].'tmp/cache/*'))]; // Photos $files = $this->getImagesUnused(); $counts['imagesUnused'] = ['count' => count($files), 'links' => array_map(function ($file) { return "javascript:nw('photos', {$file['id']})"; }, array_slice($files, 0, 10, true) + array_slice($files, -10, 10, true))]; $files = $this->getImagesFiles(); $counts['imagesFiles'] = ['count' => count($files), 'links' => array_slice($files, 0, 10, true) + array_slice($files, -10, 10, true)]; $images = $this->getImagesMissingMain(); $counts['imagesMissingMain'] = ['count' => count($images)]; return $counts; } public function get_vars() { $vars = parent::get_vars(); if (getVal('calculate')) { $vars['counts'] = $this->getCounts(); } $vars['scripts'] = ServiceContainer::getService(ScriptLocator::class)->getScripts(); $indexes = ServiceContainer::getService(FulltextInterface::class)->getIndexTypes(); $vars['fulltext']['indexes'] = array_combine($indexes, $indexes); return $vars; } public function handle() { ini_set('max_execution_time', 600); ini_set('memory_limit', '512M'); parent::handle(); if (getVal('acn') != 'edit' && getVal('acn') != 'add') { $this->returnOK("Upraveno {$this->success} položek. Selhalo {$this->failed} položek"); } } // Do not try to handle exceptions - hides some DB errors public function handleException($e) { throw $e; } public function hasRights($name = null) { switch ($name) { case Window::RIGHT_SAVE: case Window::RIGHT_DELETE: case Window::RIGHT_DUPLICATE: return false; default: return parent::hasRights($name); } } public function handleDiscounts() { $SQL = sqlQuery('DELETE FROM discounts WHERE condition_type != \'generate_coupon\''); $this->success = sqlNumRows($SQL); } public function handleAllDiscounts() { $this->success = $this->deleteSQL('discounts', ['1' => '1']); } // Variation labels public function handleLabels() { $this->success = $this->deleteSQL('products_variations_choices_labels', ['1' => '1']); } public function handleLabelsEmpty() { $SQL = sqlQuery('DELETE vl FROM products_variations_choices_labels vl LEFT JOIN products_variations_combination pvc ON pvc.id_label = vl.id WHERE pvc.id_variation IS NULL'); $this->success = sqlNumRows($SQL); } }