Всего 125 970 комментариев

Андрей Шевяков
07 марта 2022, 19:09
0
Спасибо огромное! Куда задонатить на дальнейшее развитие?
Тут нет ссылок(((
Отправить донат с карты
Отправить донат на Яндекс. Деньги
Отправить донат на Qiwi
Дима Сайт old см. профиль
07 марта 2022, 17:24
0
1. Класс
2. Лучше уж пусть дубликат создаёт чем по названию сверяет. Было бы неприятно потерять код в случае нестыковок.

Вот бы ещё решение для однократного сканирования.
У меня вот разработка всегда на тестовой копии, и там я включу автосканирование. Сделал изменения, залил в гит.

А вот уже потом на продакшене сделал pull и в админке нажал бы кнопочку (ну и привязал ресурсы к новым шаблонам, если надо)

Если компонент не создает пункт меню с кнопочкой «просканировать», то может подскажешь быстрый способ создать её руками? Нет ли коннектора который можно пнуть чтобы он там провернул шестеренки под капотом ?)))

P.S. возможно мне стоило бы использовать gitify и он такое умеет, но я не использую(
Николай Савин
07 марта 2022, 16:49
0
Скорее всего ты чего-то не знаешь.
Смотри jquery ajax() подписывает свои запросы заголовком X-Requested-With со значением XMLHttpRequest

И многие компоненты, в том числе упомянутый modhelpers просто проверяют наличие заголовка
if (empty($_SERVER['HTTP_X_REQUESTED_WITH']) || $_SERVER['HTTP_X_REQUESTED_WITH'] != 'XMLHttpRequest') {return;}
Выходит Чтобы все серверные скрипты сработали — достаточно передать этот заголовок

В конкретно этом ajaxForm за авторством Артура сделано вот так
request.setRequestHeader("X-Requested-With", "XMLHttpRequest");
Fetch работает точно так же. Нужно передать заголовок. Просто синтаксис чуть другой будет
const headers = {'X-Requested-With':XMLHttpRequest}
Prihod
07 марта 2022, 16:39
0
1. Да
2. Ничего не будет происходить так как если элемент с таким названием есть то он игнорируется, возможно в новую версию добавлю опцию которая позволит для статических элементов проверять наличие файлов в указанном пути и если его нет но есть файл с таким названием где то в другом месте то использовать его
Артур Шевченко
07 марта 2022, 16:37
0
Я не знаю, но я точно знаю, что завести компонент с Fetch у меня не получилось, а разбираться в причинах не охота.
Дима Сайт old см. профиль
07 марта 2022, 16:30
0
А вот если смотреть со стороны сервера, то XHR можно задетектить по заголовкам (типа is_ajax() в modhelpers, а Fetch-запрос вроде никак не спалить (и если он хочет, чтобы его узнали, то должен сам «представиться», передав ещё параметр например). Строго говоря, с точки зрения обработки запроса на стороне сервера, у XHR здесь преимущество перед Fetch.

Или я чего-то не знаю?
Дима Сайт 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 напрямую в корень будет выводиться или просто минус один элемент массива на выходе?