550 lines
16 KiB
PHP
550 lines
16 KiB
PHP
<?php
|
|
|
|
use KupShop\AdminBundle\Util\Script\ScriptLocator;
|
|
use KupShop\CatalogBundle\Search\FulltextInterface;
|
|
use KupShop\KupShopBundle\Config;
|
|
use KupShop\KupShopBundle\Context\ContextManager;
|
|
use KupShop\KupShopBundle\Context\LanguageContext;
|
|
use KupShop\KupShopBundle\Event\CronEvent;
|
|
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
|
|
|
|
$main_class = 'Cleaning';
|
|
|
|
class Cleaning extends Window
|
|
{
|
|
public $success = 0;
|
|
public $failed = 0;
|
|
|
|
// Cache
|
|
public function handleCacheImages()
|
|
{
|
|
global $cfg;
|
|
|
|
foreach (glob($cfg['Path']['data'].'tmp/[0-9]*/*/*.*') as $file) {
|
|
if (@unlink($file)) {
|
|
$this->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);
|
|
}
|
|
}
|