Всего 125 964 комментария

Дима Сайт old см. профиль
07 марта 2022, 16:21
0
Привет! Отличная штука!
Вопрос: на какое событие срабатывает сканирование директорий, предполагаю что на загрузку страницы админки. Тогда вопрос, если я отключу настройку автосканирования, это снимет всю «создаваемую нагрузку» на файловую систему?

И ещё: бывает надо переместить статичный файл (чанк например) из одной директории в другую, предполагаю что плагин создаст дубликат в этом случае? Или эта ситуация как-то обрабатывается?
Николай Савин
07 марта 2022, 16:20
0
Общепринятые правила написания кода.
Николай Савин
07 марта 2022, 16:19
0
А я не смотрел оригинальный файл. По логике если есть success должен быть и error
Success выводит уведомления об успешных транзакциях $ajaxForm->success()
Error соответственно в случае $ajaxForm->error()
Артур Шевченко
07 марта 2022, 16:07
0
1. Логику из конструктора хорошо бы вынести в отдельный метод.
Переписал конструктор.
Артур Шевченко
07 марта 2022, 16:04
0
3. Я бы заменил XHR на fetch.
Может быть когда-нибудь потом)))
Артур Шевченко
07 марта 2022, 15:35
0
2. Старайся использовать const вместо let
А это зачем?
Артур Шевченко
07 марта 2022, 15:31
0
4. А разве не должно быть метода error для работы с ошибками?
Может быть и должен быть, но в оригинальном скрипте не было, вроде бы. Расскажи подробнее, что должен делать метод, я постараюсь его написать.
Николай Савин
07 марта 2022, 15:03
+1
1. Логику из конструктора хорошо бы вынести в отдельный метод.
2. Старайся использовать const вместо let
3. Я бы заменил XHR на fetch.
4. А разве не должно быть метода error для работы с ошибками?
Артур Шевченко
07 марта 2022, 15:00
+1
Наконец-то дошли руки. Переписал. Если будет минутка — посмотри в репозитории код.
Vladimir
07 марта 2022, 12:49
0
Решил заглянуть в настройки fastupload, и сделал так prnt.sc/rdJHQmrb7yh4 и нет проблем, странно что автоматом не проверяется это, типо если установлен плагин translit или нет.
Vladimir
07 марта 2022, 09:43
0
Но что-то мне подсказывает проблема в этом плагине, когда его отключаешь всё работает, пытался установить phpthumb с включенном этим плагином не получилось.
<?php
/**

 * Generate Webp image format
 * 
 * Uses either Imagick or imagewebp to generate webp image
 * 
 * @param string $file Path to image being converted.
 * @param int $compression_quality Quality ranges from 0 (worst quality, smaller file) to 100 (best quality, biggest file).
 * 
 * @return false|string Returns path to generated webp image, otherwise returns false.
 */


if(
	$modx->event->name == 'OnSiteRefresh' ||
	$modx->event->name == 'OnTemplateSave' ||
	$modx->event->name == 'OnChunkSave' ||
	$modx->event->name == 'OnPluginSave' ||
	$modx->event->name == 'OnTemplateVarSave' ||
	$modx->event->name == 'OnDocFormSave' ||
	$modx->event->name == 'OnSnippetSave'
) {
	$options= [xPDO::OPT_CACHE_KEY=>'webp_on_page']; // Clear webp modx cache
	$modx->cacheManager->clean($options);
}

function jcphp01_modx_custom_generate_webp_image($file, $compression_quality = 80)
{
    
    
    $fileWithBasePath = preg_replace("~\/(?!.*\/)(.*)~", '', MODX_BASE_PATH) . $file;
    
    // check if file exists
    if (!file_exists($fileWithBasePath)) {
        return false;
    }

    // If output file already exists return path
    $output_file = $file . '.webp';
    $outputFileWithBasePath = $fileWithBasePath . '.webp';
    
    if (file_exists($outputFileWithBasePath)) {
        return $output_file;
    }
    
    
    $file_type = strtolower(pathinfo($fileWithBasePath, PATHINFO_EXTENSION));

    if (function_exists('imagewebp')) {
        
        switch ($file_type) {
            case 'jpeg':
            case 'jpg':
                $image = imagecreatefromjpeg($fileWithBasePath);
                break;

            case 'png':
                $image = imagecreatefrompng($fileWithBasePath);
                imagepalettetotruecolor($image);
                imagealphablending($image, true);
                imagesavealpha($image, true);
                break;

            case 'gif':
                $image = imagecreatefromgif($fileWithBasePath);
                break;
            default:
                return false;
        }

        // Save the image
        $result = imagewebp($image, $outputFileWithBasePath, $compression_quality);
        if (false === $result) {
            return false;
        }

        // Free up memory
        imagedestroy($image);

        return $output_file;
    } elseif (class_exists('Imagick')) {
        $image = new Imagick();
        $image->readImage($fileWithBasePath);

        if ($file_type === 'png') {
            $image->setImageFormat('webp');
            $image->setImageCompressionQuality($compression_quality);
            $image->setOption('webp:lossless', 'true');
        }

        $image->writeImage($outputFileWithBasePath);
        return $output_file;
    }

    return false;
}





function check_image_file_for_webp_converter_custom($img_real, &$webp_on_page){
	static $uniq_imgs= [];
	

	$img_real= trim($img_real);
	if(in_array($img_real, $uniq_imgs)) return;
	$uniq_imgs[]= $img_real;
	
	$ext= strtolower(pathinfo($img_real, PATHINFO_EXTENSION));
	if(
		$ext == 'jpg' ||
		$ext == 'jpeg' ||
		$ext == 'png' 
	) {
		$abs= jcphp01_modx_custom_generate_webp_image($img_real);
		$abs_base= str_replace('//', '/', MODX_BASE_PATH.$abs);

		if( file_exists($abs_base)){
			$webp_on_page[$img_real]= $abs;
		}
	}
}


try{

    if( // replace jpg and png images to webp
    	$modx->event->name == 'OnWebPagePrerender' && 
    	stripos($_SERVER['HTTP_ACCEPT'], 'image/webp') !== false
    ){
        
    	if($disable_replacing_for_logged_user && $modx->user->hasSessionContext('mgr')) return ''; 
    	
    	$options= [xPDO::OPT_CACHE_KEY=>'webp_on_page'];
    	$cache_key= md5(MODX_SITE_URL.$_SERVER['REQUEST_URI']);
    
    	$cached_webp_on_page= $modx->cacheManager->get($cache_key, $options);
    	$output= &$modx->resource->_output;
    
        
    
    	if( empty($cached_webp_on_page) ){
    		$webp_on_page= [];
    		
    		preg_match_all('/<img[^>]+>/i', $output, $result);
    		
    		if(count($result)){ // Search images in img tag
    			foreach($result[0] as $img_tag)	{
    				$img_tag= str_replace("'", '"', $img_tag); // src
    				preg_match('/(src)=("[^"]*")/i', $img_tag, $img[$img_tag]);						
    				$img_real= str_replace('"', '', $img[$img_tag][2]);
    				check_image_file_for_webp_converter_custom($img_real, $webp_on_page);
    				
    				preg_match('/(data-src)=("[^"]*")/i', $img_tag, $img[$img_tag]); // data-src					
    				$img_real= str_replace('"', '', $img[$img_tag][2]);
    				check_image_file_for_webp_converter_custom($img_real, $webp_on_page);
    				
    				preg_match('/(srcset)=("[^"]*")/i', $img_tag, $img[$img_tag]); // srcset
    				$srcset= explode(',', str_replace('"', '', $img[$img_tag][2]));
    				foreach($srcset as $src_item){
    				    $src_a= explode(' ', $src_item);
    				    if(isset($src_a[0]) && !empty($src_a[0])) {
    				        check_image_file_for_webp_converter_custom($src_a[0], $webp_on_page);
    				    } else {
    				        if(isset($src_a[1]) && !empty($src_a[1])) {
    				            check_image_file_for_webp_converter_custom($src_a[1], $webp_on_page);
    				        }
    				    }
    				}
    			}
    		}
    
    		preg_match_all('/url\(([^)]*)"?\)/iu', $output, $result);
    		if(count($result)){ // Search images in url css rules
    			foreach($result[1] as $img_tag)	{
    				if(stripos($img_real, 'data:')) continue;
    				$img_real= str_replace(['"',"'"], '', $img_tag);
    				check_image_file_for_webp_converter_custom($img_real, $webp_on_page);
    			}
    		}
    		
    		$webp_on_page['/webp/webp/']= '/webp/';
    		$webp_on_page['//webp/']= '/webp/';
    		$webp_on_page['.webp.webp']= '.webp';
    		
    		if(count($webp_on_page)) $output= str_replace(array_keys($webp_on_page), array_values($webp_on_page), $output);
    		$modx->cacheManager->set($cache_key, serialize($webp_on_page), 0, $options);
    	} else {
    		$webp_on_page= unserialize($cached_webp_on_page);
    		if(count($webp_on_page)){
    			$output= str_replace(array_keys($webp_on_page), array_values($webp_on_page), $output);
    		}
    	}
    	return '';
    }
    
} catch (Exception $e){
    $modx->log(1, 'Та самая бредовая ошибка из-за которой не сохраняются товары');
    $modx->log(1, $e);
}
Vladimir
07 марта 2022, 06:36
0
1)500
2)Пусто
3)Уже не стал смотреть
4)Да нормально
5)Удалил этот плагин и сделал как снипет
<?php
$currentResourceCacheName = "reviews".$modx->resource->id;

if ($modx->cacheManager->get($currentResourceCacheName)) {
    $output = $modx->cacheManager->get($currentResourceCacheName);
}else{

    $activeReviews = 0;
    $totalActiveRating = 0;    
    $avgRating = 0;

    try {
        $reviews = json_decode($modx->resource->getTVValue('reviews'), true);
        
        if($reviews){
            foreach($reviews as $key => $value){
                if($value['is_active'] == '1'){
                    $activeReviews += 1;
                    $totalActiveRating += $value['rating'];
                }
            }
            
            $avgRating = $totalActiveRating / $activeReviews;                        
        }
        
    } catch(Exception $e) {
        $modx->log(1, 'Бред 0');
        $modx->log(1, $e);
    }



    $output = strval($activeReviews).','.strval($avgRating);
    $modx->cacheManager->set($currentResourceCacheName, $output, 36000);
}

return $output;
Сергей Шлоков
06 марта 2022, 11:33
0
Просто не будет элемента meta. В следующей версии сделаю возможность выводить свой формат данных.
Николай Савин
06 марта 2022, 10:58
0
Блок meta можно отключить в системной настройке zoomx_include_request_info
Тогда data напрямую в корень будет выводиться или просто минус один элемент массива на выходе?
Сергей Шлоков
06 марта 2022, 08:56
+4
Сделаю несколько пояснений.

pdoTools никакого отношения к теме статьи не имеет и для ZoomX не нужен. Я использую его лишь для того, чтобы работать с разметкой шаблона через IDE.
Это только для тех, кто хочет работать с шаблонизатором Fenom. Если есть желание работать в режиме фреймворка, то можно работать с шаблонизатором Smarty, который идёт с MODX из коробки. Я много раз уже говорил, что Fenom в pdoTools — это костыль, который вроде как добавляет возможности нормального шаблонизатора, но работает по правилам MODX шаблонизатора — многократный парсинг и компиляция контента, который ему подсовывает MODX шаблонизатор. В правильном режиме php шаблонизатор парсит страницу один раз, компилирует её в php файл и использует его при следующих запросах, не тратя время на повторный парсинг и компиляцию.

Если в роуте не указан метод контроллера, запрос всегда обращается к главному методу index()
Сначала проверяется наличие магического метода __invoke. Если его нет, то будет вызван метод index.

Метод jsonx всегда возвращает объект с тремя блоками.
Блок meta можно отключить в системной настройке zoomx_include_request_info
Александр Мельник
06 марта 2022, 08:52
+3
Дмитрий, вы очень плохо описываете свой вопрос. Два предложения и даже они почти бессмысленные.
Честь и хвала Артуру, что ему хватает нервов и времени попытаться разобраться и найти хоть крупицу логики, написать вам ответ. А потом вы вдруг все переворачиваете с ног на голову, говоря про админку.
Если бы вы описали задачу кратко, но полностью — вероятность что вам бы помогли была бы больше.

Артур вам правильно написал, formit это лишь программа для отправки форм, а форма передает информацию, данные, а не теги. Есть множество способов передать данные в форму. К примеру используя возможности javascript работать с DOM деревом, как описал Артут. Либо можно просто информацию которую лежит у вас в теге p продублировать уже в виде тега input type=hidden value=название категории name=categoryName
Если этот тег будет размешен внутри формы, то название категории отправится.
Если вы хотите чтобы отправляемые пользователем данные просто сохранялись в админке, то ознакомьтесь с документацией на formit
docs.modx.com/current/en/extras/formit/index
и особенно
docs.modx.com/current/en/extras/formit/formit.hooks/formitsaveform
Дмитрий
06 марта 2022, 00:08
0
мне надо, чтобы это ещё в админке выводилось
Mish
05 марта 2022, 22:33
0
Спасибо за ответ! Прописываю вот так: {$cvet}/{$razmer}, все равно выводит название родительской :(
Артур Шевченко
05 марта 2022, 22:22
0
Очень легко: нужно под каждую комбинацию опций создать отдельное правило SEO. Под две опции, нужно 3 правила
1. {$option1}
2. {$option2}
3. {$option1}/{$option2}
Для трех опций нужно 7 правил
1. {$option1}
2. {$option2}
3. {$option3}
4. {$option1}/{$option2}
5. {$option1}/{$option2}/{$option3}
6. {$option1}/{$option3}
7. {$option2}/{$option3}
И так далее
Дмитрий Бородин
05 марта 2022, 20:09
0
Столкнулся с такой же проблемой. BabelLinks не выводит ссылки в меню в контексте web. Если добавить параметр &showCurrent=`1`, показывает только основной язык (русский). Также на сайте добавлен английский и французский языки в указанном порядке. Если вручную перейти на английскую версию сайта, то BabelLinks выводит ссылку на русскую и английскую версии только. Если вручную перейти на французскую версию сайта, тогда BabelLinks выводит уже все три языка… Переводы все есть. Кэш чистил несколько раз. Сайт включен. А проблема не исчезает. Пытался найти ответ на других форумах, там предлагают использовать для переключения сторонние плагины только. Только не хочется использовать для этого костыли, когда есть стандартное готовое решение.