Александр Наумов

Александр Наумов

С нами с 15 декабря 2012; Место в рейтинге пользователей: #103
Наумов Алексей
04 августа 2021, 13:49
1
+6
Даже я отвечу: конечно можно, переписываете вот этот файл без сторонних библиотек и все будет работать
github.com/bezumkin/AjaxForm/blob/master/assets/components/ajaxform/js/default.js
Fi1osof
12 апреля 2021, 09:25
2
+2
Александр, если докером еще интересуетесь, можно с этим поиграться: github.com/MODX-Club/docker-lnmp
Здесь все необходимое для запуска MODX-3 (ну, просто он там в зависимостях, но можно и другие добавить в app/www).

Сам по себе докер (именно как один отдельно взятый контейнер) не очень интересно. Интересна возможность именно создания нескольких контейнеров, и чтобы они между собой взаимодействовали. Здесь у нас php-fpm, nginx, mysql, PhpMyAdmin и сам MODX. Но MODX пока не удалось запустить на полном автомате (мне лень было это копать без особой мотивации). Тем не менее, контейнер под него подготовлен, в том числе и устанавливается composer github.com/MODX-Club/docker-lnmp/blob/master/php-fpm/Dockerfile#L36

Только клонировать проект надо с субмодулями
git clone --recursive github.com/MODX-Club/docker-lnmp docker-modx
cd docker-modx

После этого проверяем, директория должна быть не пустой app/www/modx3

И вот чего не автоматизировал — это создание modx3/core/packages/core.transport.zip
По идее его должна быть возможность как-то билдить через CLI, но я с наскока не нашел. Если найдете, то в связке с общей установкой MODX через CLI можно полностью автоматизировать установку и запуск.
docs.modx.com/3.x/en/getting-started/installation/cli

Пока же приходится качать этот пакет с оффсайта и закидывать туда, иначе установка не может быть завершена.

Запуск

Копируем .env
copy .sample.env .env

Может затем отредактировать его и установить рет-пароль для мускула.

Для надежности сначала запускаем mysql и pma
docker-compose up -d --build mysql pma

Затем php-fpm
docker-compose up -d --build php-fpm

После запуска надо собрать MODX (я забыл это прописать в Dockerfile).
Заходим в контейнер php-fpm
docker exec -it modx-docker_php-fpm_1 bash (имя контейнера может отличаться, ищем актуальное docker ps или docker-compose ps).
Заходим в папку modx3 и выполняем
composer install

Ну и в конце nginx
Только хост подправить при необходимости: github.com/MODX-Club/docker-lnmp/blob/master/nginx/conf.d/modx3.local.conf

docker-compose up -d --build nginx

После запуска идет modx3.local/setup и устанавливаем.
Fi1osof
08 апреля 2021, 10:55
1
+3
Есть решения на nodejs, но тут сталкиваемся с тем, что тогда нужен сервер, либо нужно мириться с своеобразными решениями хостингов.
Нет, это сильно не так. Сейчас появляются специализированные хостинги, например https://vercel.com. Заходишь в панель, указываешь ссылку на гитхаб-проект, даешь к нему доступ и все. Далее при каждом коммите в мастер-ветку он сам стягивает исходники с гитхаба, собирает все и разворачивает на сервере. Ты вообще ничего не делаешь.

Я им не пользуюсь, но морок все равно не много. Я захожу на digitalocean и создаю сервер из готового образа с докером: marketplace.digitalocean.com/apps/docker
Далее просто затягиваю гит-проект, подправляю .env (если надо) и все, запускаю проект. При чем использую caddy-server, который даже ssl сертификаты в Let's Encript заказывает, даже крон-службы никакие не надо настраивать. Так что все далеко не так плохи и сложно как кажется.

В связи с чем появляется вопрос, а чем можно заменить modx в современных реалиях?
Вот если говорить просто как про замену MODX в классическом виде, то есть про готовую CMS, которая и сервер и фронт, все в одном, под сайты-визитки и небольшие магазины, то скорее всего нечем (во всяком случае на JS/TS). Нюанс только заключается в том, что сейчас спроса на простые и маленькие практически нет. Точнее сейчас практически не остается того маленького в том виде, как это было раньше. Даже маленькое сейчас стараются делать по современным методикам. Аналогию можно наверно такую провести: это как писали раньше на чистом JS и мучились с поддержкой разных браузеров, а потом появился jQuery и практически все стали писать на нем (хотя справедливости ради стоит отметить, что сначала появились prototype и mootools, но все же именно jQuery стал первой столь массовой библиотекой). Или как писали чистый CSS, а потом появились Less, Sass и т.п. и говорили «На чистом CSS писать легко. Но большие проекты на чистом CSS писать сложно». Так же и здесь. Появляется множество инструментов, используемых еще на этапе разработки и конечный продукт без использования оных всерьез не воспринимается.

Сейчас же пишут в основном API-first CMS и Headless CMS. И хотя не все могут сразу перейти полностью на новые технологии, очень часто делают так: бэк старый оставляют и прикручивают новый на новых технологиях. Посмотрите список поддерживаемых CMS у того же gatsby или next-js. Я же пишу свой велосипед, который прям все в одном в плане и бэк и фронт. github.com/prisma-cms/nextjs
Сделал на нем уже несколько сайтов. Докручиваю только более удобную админку ему. Уверен, появятся и другие сторонние решения «под ключ» и более удобные, чем у меня. Это всего лишь вопрос времени.
Баха Волков
15 июля 2018, 09:01
4
0
Ссылку получать нужно так:

[[~id ресурса]]
{id ресурса | url}

// Прямое указание id ресурса
[[~2]]
{2 | url}

//  Динамичное указание id ресурса
[[~[[+id]]]]
{$id | url}
[[~[[*id]]]]    // Вдруг нужна циклическая ссылка :)
{$_modx->resource.id | url}    // Вдруг нужна циклическая ссылка :)

// ну а если ваш плейсхолдер [[!+gl.current.data.resource]] возвращает именно id, то
[[~[[!+gl.current.data.resource]]]]
{var $myplace = $_modx->getPlaceholder('gl.current.data.resource')}    // Вдруг еще понадобится
{$myplace | url}

// Кстати, для получения полей есть еще FastField
[[#id ресурса.поле или даже тв которое нужно вывести]]
{id ресурса | resource : 'поле или даже тв которое нужно вывести'}

// Пример
[[#1.pagetitle]]    // Получить pagetitle у ресурса с id = 1
{1 | resource : 'pagetitle'}

Как получить родителя по id?
[[*parent]]    // На странице ресурса
{$_modx->resource.parent}
[[+parent]]    // В чанках вывода
{$parent}
[[#[[!+gl.current.data.resource]].parent]]    // Тот случай когда нужно получить id по плейсхолдеру
{$_modx->getPlaceholder('gl.current.data.resource') | resource : 'parent'}
[[pdoField? &id=`[[!+gl.current.data.resource]]` &field=`parent`]]    // Ну или через pdoField
{var $myplace = $_modx->getPlaceholder('gl.current.data.resource')}
{$myplace | resource : 'parent'}

Для корректности, вашем случае нужно поступить вот так:
[[~[[#[[!+gl.current.data.resource]].parent]]]]
{$_modx->getPlaceholder('gl.current.data.resource') | resource : 'parent' | url}
// или
[[~[[pdoField? &id=`[[!+gl.current.data.resource]]` &field=`parent`]]]]
{var $myplace = $_modx->getPlaceholder('gl.current.data.resource')}
{$myplace | resource : 'parent' | url}

UPD
Забыл совсем про uri
Если, что в поле uri хранится ссылка на страницу, но никак не в alias
Володя
15 мая 2018, 15:10
4
+1
как минимум переделать так
<?php


if ($modx->event->name === 'OnDocFormSave') {
   
    if($mode == 'new'){
        $modx->log(1, 'Новый');
        
        if (!$user = $modx->getAuthenticatedUser('web')) {
            // не получен пользователь
            return;
        }
        
        $user_id = $user->get('id');
        if (!$user_money_profile = $modx->getObject('msCustomerProfile', $user_id)) {
            // не получе профиль пользователя
            return;
        }
        
        $balance = (float)$user_money_profile->get('account');
       
        if (!empty($_POST['pricetpl'])){
            if ($balance >= 100) {
                $new_balance = $balance - 100;
                $user_money_profile->set('account', $new_balance);
                $user_money_profile->save();
                $modx->log(1, 'Списал баланс');
            }else { $modx->log(1, 'Недостаточно средств');}
        }
    }
}
Александр
27 декабря 2017, 14:33
1
0
Не грузится из-за того, что не может определить размеры картинки. Разработчик Минишоп добавь в файл
core/components/minishop2/processors/mgr/gallery/upload.class.php
после строки 64
if($extension == 'svg'){
	$data['properties']['width'] = 512; //Размеры можно вытащить из svg при желании, или указать любые
        $data['properties']['height'] = 512;
}
Ну и в разрешениях файлового источника надо прописать svg
Максим Кузнецов
07 ноября 2017, 12:29
5
+6
На fenom-е посимпатичнее будет:

{foreach $_modx->resource.pagetitle | split : ' ' as $pagetitle_word}
	{if $pagetitle_word | length > 3}
		{var $words[] = $pagetitle_word}
	{/if}
{/foreach}

{set $random_word_position = rand(1, $words| length)}
{set $random_word = $words[$random_word_position - 1]}

{$_modx->runSnippet('!msProducts', [
	'parent' => $_modx->resource.parent,
	'resources' => -$_modx->resource.id,
	'where' => '{
		"pagetitle:LIKE": "%' ~ $random_word ~ '%"
	}',
	...
])}
Сергей Водолагин
19 июня 2017, 18:43
8
+1
Вот друзья помогли (так как глубина от родителей до нужных ресурсов от 1 до 5 вот решение)
[[pdoResources?
    &parents=`4`
    &limit=`100`
    &sortby=`{ "pm5":"ASC","pm4":"ASC", "pm3":"ASC", "pm2":"ASC", "pm1":"ASC" }`
    &where=`{ "template": 10 }`
    &tpl=`tplSklad`
    &leftJoin=`{
        "p1": {
            "class": "modResource",
            "on": "p1.id = modResource.id"
        },
        "p2": {
            "class": "modResource",
            "on": "p2.id = p1.parent"
        },
        "p3": {
            "class": "modResource",
            "on": "p3.id = p2.parent"
        },
        "p4": {
            "class": "modResource",
            "on": "p4.id = p3.parent"
        },
        "p5": {
            "class": "modResource",
            "on": "p5.id = p4.parent"
        }
    }`
    &select=`{
        "modResource": "*",
        "p1": "COALESCE(p1.menuindex, 999999999) as pm1",
        "p2": "COALESCE(p2.menuindex, 999999999) as pm2",
        "p3": "COALESCE(p3.menuindex, 999999999) as pm3",
        "p4": "COALESCE(p4.menuindex, 999999999) as pm4",
        "p5": "COALESCE(p5.menuindex, 999999999) as pm5"
    }`
]]
Андрей
15 июня 2017, 17:32
2
0
Надо плагин сделать для минишопа как описано тут.

Работает это с версии минишоп 2.4 как я понимаю.

1. В папке /core/components/minishop2/custom/cart/ создаете файл mascarthandlerstatus.class.php который будет расширять класс корзины

2. В этом файле пишете
<?php

if(!class_exists('msCartInterface')) {
    require_once dirname(dirname(dirname(__FILE__))) . '/model/minishop2/mscarthandler.class.php';
}

class msCartHandlerStatus extends msCartHandler implements msCartInterface{

    public function status($data = array())
    {
        $status = array(
            'total_count' => 0,
            'total_count_position' => 0,
            'total_cost' => 0,
            'total_weight' => 0
        );

        foreach ($this->cart as $item) {
            if (empty($item['ctx']) || $item['ctx'] == $this->ctx) {
                $status['total_count_position'] += 1;
                $status['total_count'] += $item['count'];
                $status['total_cost'] += $item['price'] * $item['count'];
                $status['total_weight'] += $item['weight'] * $item['count'];
            }
        }

        return array_merge($data, $status);
    }
}

3. В плагине Console (если его нет, то надо поставить) выполняем следующий код
if ($miniShop2 = $modx->getService('miniShop2')) {
    $miniShop2->addService('cart', 'msCartHandlerStatus',
        '{core_path}components/minishop2/custom/cart/mascarthandlerstatus.class.php'
    );
}
Таким образом мы добавляем новый обработчик корзины

4. Далее идем в Системные настройки -> mimishop2 -> Класс обработчик корзины и указываем там msCartHandlerStatus

5. Теперь в плейсхолдере total_count_position будет отображаться количество позиций в корзине

6. Что бы все это и по аяксу обновлялось, в js в ваших скриптах или просто в конце страницы (главное что бы он был после подключения скрипта от минишопа) добавляем такой код
miniShop2.Cart.status = function (status) {
  if (status['total_count'] < 1) {
      location.reload();
  }
  else {
      var $miniCart = $(miniShop2.Cart.miniCart);
      if (status['total_count'] > 0 && !$miniCart.hasClass(miniShop2.Cart.miniCartNotEmptyClass)) {
          $miniCart.addClass(miniShop2.Cart.miniCartNotEmptyClass);
      }
      $(miniShop2.Cart.totalWeight).text(miniShop2.Utils.formatWeight(status['total_weight']));
      $(miniShop2.Cart.totalCount).text(status['total_count']);
      $(miniShop2.Cart.totalCost).text(miniShop2.Utils.formatPrice(status['total_cost']));
      $('.ms2_total_count_position').text(status['total_count_position']);
      if ($(miniShop2.Order.orderCost, miniShop2.Order.order).length) {
          miniShop2.Order.getcost();
      }
  }
};

7. Теперь в миникорзине или корзине можно писать так
<span class="ms2_total_count_position">{$total_count_position}</span>
Максим Кузнецов
06 июня 2017, 11:56
1
+3
1. одноразовый алерт, оповещающий о сборе персональных данных (продолжая пользоваться данным сайтом, вы соглашаетесь с нашей политикой конфиденциальности)
2. чекбоксы «я согласен на обработку моих персональных данных/подтверждая форму, я соглашаюсь с правилами сайта» на объемных формах — регистрация/оформления заказа
3. страница с политикой конфиденциальности + ссылка в подвале
4. modhost.pro