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

Николай Савин
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 выводит уже все три языка… Переводы все есть. Кэш чистил несколько раз. Сайт включен. А проблема не исчезает. Пытался найти ответ на других форумах, там предлагают использовать для переключения сторонние плагины только. Только не хочется использовать для этого костыли, когда есть стандартное готовое решение.
Артур Шевченко
05 марта 2022, 09:48
+1
Непосредственно html-тэги нельзя отправить, но можно сделать так
<htm>
    <body>
        <form>
            <p>Some text</p>
            <input type="hidden" name="service">
        </form>  
        <script>
            let  form = document.querySelector('form');
            form.addEventListener('submit', function(e){
            e.preventDefault();
            let par = document.querySelector('p'),
                input = document.querySelector('input[name="service"]');
            input.value = par.innerText;
            });
        </script>
    </body>
</html>
Евгений Webinmd
04 марта 2022, 16:29
+1
Создаете новую папку с ключем языка в папке с лексиконами минишопа, копируете туда английский или русский вариант и меняете там нужные вам надписи