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

Антон
23 января 2021, 11:29
0
Сделал ЛК по аналогии с вашей инструкцией. Для Загрузки изображений к тикету сделал проверку на количество загружаемых фото меньше 3х нелзя. Проверяю сам, проверка работает. Но иногда проскакивают тикеты с количеством изображений меньше 3х. Голову уже сломал, в чем проблема. В логах висит ошибка:
core/cache/includes/elements/modsnippet/33.include.cache.php	87
Ошибка при загрузке файла. Код ошибки: 4
Сниппет 33 строка 87
<?php
// Получить профиль пользователя
$profile = $modx->user->getOne('Profile');
// Получить значение поля photo
$pathToPhoto = $profile->get('photo');
// Установить полю photo текущее значение
$hook->setValue('photo',$pathToPhoto);

// Запрос на удаление картинки (глобальный массив POST имеет ключ delete-photo-btn со значением отличным от NULL)
if (isset($_POST['delete-photo-btn'])) {
  // Если поле photo не пустое, то..
  if ($pathToPhoto) {
    // Сформировать полный путь к файлу (фото)
    $fullPathToPhoto = $modx->config['base_path'].$pathToPhoto;
    // Если файл (фото) есть, то удалить его
    if(file_exists($fullPathToPhoto))
      unlink($fullPathToPhoto);
    // Установить полю photo пустое значение
    $hook->setValue('photo','');
  }
}

// Запрос на обновление (глобальный массив POST имеет ключ login-updprof-btn со значением отличным от NULL)
if (isset($_POST['login-updprof-btn'])) {
  // Допустимые расширения (jpg, png, jpeg)
  $validExt = array('jpg', 'png', 'jpeg');
  // Директория для хранения фото пользователей
  $pathToPhoto = $modx->config['base_path'] . 'assets/photouser/';
  // Имя файла пользователя 
  $nameFile = $_FILES['photo']['name'];
  // Получить расширение загруженного пользователем файла в нижнем регистре
  $extFile = mb_strtolower(pathinfo($nameFile, PATHINFO_EXTENSION));
  // Временное имя, с которым принятый файл был сохранён на сервере
  $tmpFile = $_FILES['photo']['tmp_name'];
  // Если файл загружен посредством HTTP POST и ошибок в процессе загрузке не возникло, то...
  if ((is_uploaded_file($tmpFile)) && !($_FILES['photo']['error'])) {
    // Проверям соответствует ли расширение файла допустимому. Если всё хорошо, то...
    if(in_array($extFile, $validExt)) {
      // Формируем имя файлу (фото)
      $nameFilePhoto = 'user'.$modx->user->get('id'). '_'. time(). '.'. $extFile;
      // Получаем полное имя файла (фото)
      $fullNameFilePhoto = $pathToPhoto . $nameFilePhoto;
      // Перемещаем временный файл на новое место $fullNameFilePhoto. Если всё прошло успешно, то...
      if (move_uploaded_file($tmpFile, $fullNameFilePhoto)) {
        // если файл phpthumb.class.php не был подключён, то включить его
        require_once MODX_CORE_PATH.'model/phpthumb/phpthumb.class.php';
        // Создать новый экземпляр класса phpThumb
        $phpThumb = new phpThumb();
        // Указываем исходное изображение
        $phpThumb->setSourceFilename($fullNameFilePhoto);
        // Устанавливаем ширину изображению
        $phpThumb->setParameter('w', 245);
        // Устанавливаем высоту изображению
        $phpThumb->setParameter('h', 336);
        // Задаём тип обрезки
        $phpThumb->setParameter('zc', '1');
        // Задём качество изображения
        $phpThumb->setParameter('q', '90');
        // Генерируем уменьшенное изображение. Если действие прошло успешно, то...
        if ($phpThumb->GenerateThumbnail()) {
          // Сохраняем изображение в файл $fullNameFilePhoto. Если данное действие завершилось успехом, то..
          if ($phpThumb->RenderToFile($fullNameFilePhoto)) {
            // Устанавливаем в поле photo путь к файлу 
            $hook->setValue('photo',$modx->getOption('assets_url'). 'photouser/' . $nameFilePhoto);
          }
          else {
            $modx->log(modX::LOG_LEVEL_ERROR, 'Ошибка при сохрании изображения в файл '.$fullNameFilePhoto);
          }
        }
        else {
          // Записываем полученую ошибку в журнал MODX
          $modx->log(modX::LOG_LEVEL_ERROR, print_r($phpThumb->debugmessages, 1));
        }
      }
      else {
        // Записываем в журнал что произошла ошибка при перемещении файла на новое место
        $modx->log(modX::LOG_LEVEL_ERROR, 'Ошибка при перемещении временного файла '.$tmpFile.' на новое место '.$fullNameFilePhoto);
      }
    } 
    else {
      // Записываем в журнал сообщение о том, что расширение файла не соответствует разрешённому
      $modx->log(modX::LOG_LEVEL_ERROR, 'Изображение имеет недопустимое расширение');
    }
  }
  else {
    // Записываем в журнал что произошла ошибка при загрузке файла
    $modx->log(modX::LOG_LEVEL_ERROR, 'Ошибка при загрузке файла. Код ошибки: '.$_FILES['photo']['error']);
  }
}
return true;
Сам сниппет проверки количества фото:
<?php
$tid = (int)$_POST['tid']; //replaces the line $tid = (int)$value;
//Query the amount of images in the database table modx_tickets_files
$q = $modx->newQuery('TicketFile');
$q->where(array('class' => 'Ticket'));
$q->andCondition(array('parent' => $tid, 'deleted' => 0, 'createdby' => $modx->user->id), null, 1);
$img_count = $modx->getCount('TicketFile', $q);

if ($img_count < 3) {
    //Less than 3 images found
    $validator->addError($key,'You must submit at least 3 photos!');
    return false;
}
return true;
Артур Шевченко
23 января 2021, 11:11
+1
<?php
if(!$order_id){return false;}
$pdoTools = $modx->getService('pdoTools');
$orderFields = array('id','num', 'createdon', 
                    'updatedon', 'cart_cost', 
                    'delivery_cost', 'comment', 
                    'status', 'cost');
$orderProductFields = array('id','product_id', 
                            'name', 'count', 
                            'price', 'cost', 'options');
                        
$addressFields = array('city', 'street',
                        'receiver', 'phone',
                        'comment');
$output = array(
    'meta' => [],
    'address' => [],
    'products' => []
    );

$order = $modx->getObject('msOrder', $order_id);
if($order){        
    //заполняем массив основных данных заказа
    for($i = 0; $i < count($orderFields); $i++){
        $output['meta'][$orderFields[$i]] = $order->get($orderFields[$i]); 
    }
    
    //вычисляем срок выполнения заказа
    $output['meta']['duration'] = ceil($output['meta']['cost'] / $modx->getOption('base_cost'));
            
    //заполняем адрес и дополнительные данные
    $address = $order->getOne('Address');
    $properties = $address->get('properties');
    for($i = 0; $i < count($addressFields); $i++){
        if($addressFields[$i] != 'properties'){
            $output['address'][$addressFields[$i]] = $address->get($addressFields[$i]); 
        }else{
            foreach($properties as $name => $prop){
                $output['address'][$name] = $prop; 
            }
        }
    }
    //заполняем продукты
    $products = $order->getMany('Products');
    if($products){
        foreach($products as $key => $product){
            for($i = 0; $i < count($orderProductFields); $i++){
                $output['products'][$key][$orderProductFields[$i]] = $product->get($orderProductFields[$i]); 
            }
        }  
    }
    
    
    //$modx->log(1, 'OUTPUT getUserOrder ' . print_r($output, 1));
    
    if($tpl){
        return $pdoTools->getChunk($tpl, $output);
    }
    //$modx->log(1, print_r($output,1));
    return $output;
}else{
    return false;
}


ФРОНТ
{set $order = '!getOrder' | snippet:[
    'order_id' => $.get.order_id
]}

{if $order}
<p class="h-6"><span class="text-orange">Номер заказа:</span> {$order['meta']['num']}</p>
<p class="h-6"><span class="text-orange">Дата заказа:</span> {$order['meta']['createdon'] | date: 'd.m.Y H:i:s'}</p>
<p class="h-6"><span class="text-orange">Имя заказчика:</span> {$order['address']['receiver']}</p>
{if $_modx->isAuthenticated('mgr') || $.get.admin}
<p class="h-6"><span class="text-orange">Телефон заказчика:</span> <a class="service-link" href="tel:{$order['address']['phone'] | replace:'-':'' }">{$order['address']['phone'] | replace:'-':'' }</a></p>
{/if}
<p class="h-6"><span class="text-orange">Общая стоимость:</span> <span class="jsTotalOrderCost">{$order['meta']['cost']}</span> руб.</p>
<p class="h-6"><span class="text-orange">Срок выполнения:</span> <span class="jsOrderDuration">{$order['meta']['duration']}</span> дн.</p>
<p class="h-6 mb-0"><span class="text-orange">Перечень включенных в состав услуг <small class="small">(в стоимость услуг входит стоимость платных дополнений)</small>:</span></p>
    {if $_modx->isAuthenticated('mgr') || $.get.admin}
        <div class="pl-0" id="productList">
        {set $i = 1}    
        {foreach $order['products'] as $key => $product}
            {set $description = $product['product_id'] | resource: 'desc'}
            {set $introtext = $product['product_id'] | resource: 'introtext'}
            {set $add_cost = $product['product_id'] | resource: 'add_cost'}
            {set $weight = $product['product_id'] | resource: 'weight'}
            {$_modx->parseChunk('@FILE chunks/shop/editOrderProduct.html', [
                'description' => $product['options']['desc']?:$description,
                'introtexxt' => $introtext,
                'index' => $i,
                'add_cost' => $add_cost,
                'price' => $product['price'],
                'weight' => $weight,
                'count' => $product['count'],
                'name' => $product['options']['name']?:$product['name'],
                'cost' => $product['cost'],
                'id' => $product['id'],
                'options' => $product['options'],
                'order_id' => $.get.order_id,
                'total_cost' => $order['meta']['cost'],
                'product_id' => $product['product_id']
            ])}
            {set $i = $i + 1}
        {/foreach}
        </div>
        <form class="row py-3 jsProductRow border-gray-bottom jsAddForm">
            <p class="h-5">Добавить услугу</p>
            <input type="hidden" name="weight" value="1">
            <input type="hidden" name="order_id" value="{$.get.order_id}">
            <input type="hidden" name="total_cost" value="{$order['meta']['cost']}">
            <input type="hidden" name="action" value="editOrder">
            <input type="hidden" name="product_id" value="130">
            <div class="col-lg-7 col-md-5 col-6 d-flex flex-column justify-content-center align-items-start">
                <label class="label-text par mb-0 w-100">
                    <input type="text" class="input pr-1" name="name" placeholder="{130 | resource: 'pagetitle'}" value="" required>
                </label>
            </div>
            <div class="col-lg-1 col-md-1 col-6 d-flex justify-content-center align-items-center">
                <label class="label-text par mb-0">
                    <input type="number" class="input pr-1" min="1" name="count" value="1">
                </label>
            </div>
            <div class="col-lg-2 col-md-3 col-6 d-flex justify-content-center align-items-center">
                <label class="label-text par mb-0">
                    <input type="text" class="input pr-1" name="price" placeholder="Цена" value="" required>
                </label>
            </div>
            <div class="col-lg-2 col-md-3 col-6 d-flex justify-content-center align-items-center">
                <button class="btn btn-orange btn-cart" type="submit">
                    <i class="fa fa-cart-plus"></i>
                </button>
            </div>
            <div class="col-12 order-5 mt-3">
                <label class="label-text par mb-0">
                    <textarea name="options[desc]" class="textarea w-100" rows="4" placeholder="Описание"></textarea>
                </label>
            </div>
        </form>
    {else}
     <ul class="pl-0">
    {foreach $order['products'] as $key => $product}
        {set $description = $product['product_id'] | resource: 'description'}
        {set $introtext = $product['product_id'] | resource: 'introtext'}
        {set $add_cost = $product['product_id'] | resource: 'add_cost'}
        <li class="row py-3 jsProductRow border-gray-bottom">
            <input type="hidden" name="id" value="{$id}">
            <div class="col-lg-7 col-md-5 col-6 d-flex flex-column justify-content-center align-items-start">
                <span class="par service-link mb-3">{$product['options']['name']?:$product['name']}</span>
                <small class="small">{$product['options']['desc']?:$description}</small>
                {if $add_cost}
                    <small class="small text-orange">Добавочная стоимость: {$add_cost} руб.</small>
                {/if}
            </div>
            <div class="col-lg-1 col-md-1 col-6 d-flex justify-content-center align-items-center">
                <span class="price text-orange h-6">{$product['count']} шт.</span>
            </div>
            <div class="col-lg-2 col-md-3 col-6 d-flex justify-content-center align-items-center">
                    <span class="text-orange h-6">{$product['price']} руб.</span>
            </div>
            <div class="col-lg-2 col-md-3 col-6 d-flex justify-content-center align-items-center">
                <span class="text-orange h-6">{$product['cost']} руб.</span>
            </div>
        </li>
    {/foreach}
    </ul>
    {/if}
{else}
<p class="h-4 text-center">Заказ с id = {$.get.order_id} не существует в системе</p>
{/if}
<div class="row">
        <div class="col-lg-3 offset-lg-3 col-sm-6 mt-3">
        <div class="btn-wrap">
            <a href="/" class="btn btn-no-bg w-100">На Главную</a>
        </div>
    </div>
    <div class="col-lg-3 col-sm-6 mt-3">
        <div class="btn-wrap">
            <a href="{9 | url}" class="btn btn-no-bg w-100">К Услугам</a>
        </div>
    </div>
</div>
Сергей Карпович
23 января 2021, 10:53
0
Добавил проверку на группу:
$modx->user->isMember('Administrator')
Все заработало, как и хотел
Артур Шевченко
23 января 2021, 10:51
1
0
Править исходники плохо.
Лучше написать свой сниппет, примерно такой
$order=$modx->getObject('msOrder', $id);
//Тут как-то обрабатыааете
Вызов такой
[[customGetOrder?id=17]]
Как в синтаксисе pHx получить get параметр не помню, погуглите, а лучше используйте fenom.
Сергей Карпович
23 января 2021, 10:45
0
В сниппете msGetOrder, за показ информации отвечает вот эта конструкция:
$canView = (!empty($_SESSION['minishop2']['orders']) && in_array($id, $_SESSION['minishop2']['orders'])) ||
    $order->get('user_id') == $modx->user->id || $modx->user->hasSessionContext('mgr') || !empty($scriptProperties['id']);
if (!$canView) {
    return '';
}
Тут, как я понимаю, идет проверка, если ID сессии совпадает с ID пользователя оформившего заказ — показываем,
Также показываем если пользователь авторизован в адмике.

Осталось понять как добавить сюда, если пользователь в группе Администраторы
Сергей Карпович
23 января 2021, 10:40
0
Показывает успешно оформленный заказ после оформления заказа
Сергей Карпович
23 января 2021, 10:31
0
Не то, это мы просто показываем доступ запрещен, если не админ.
А нужно иметь возможность админу смотреть заказы других пользователей, переходя по ссылке
Dmytro Lukianenko
23 января 2021, 10:16
+5
Evolution CMS 3.0 Online Presentation
23.01.2021 12:00 (GMT +2)

На русском:
youtu.be/YhbLiL3lT_4

In english:
youtu.be/xDIdfZrlCgk

Afterparty for all 16:00 (GMT +2):
meet.google.com/qdq-etsc-zca
Dmytro Lukianenko
23 января 2021, 10:16
+2
Нужно установить DocLister и FormLister и будет все ок.

В 3.0 их убрали из ядра, и в целом все дополнения можно будет ставить через Composer с зависимостями.

Это самый ближайшие планы, в ядре все готово уже но нужно немного поправить дополнения
Max
Max
23 января 2021, 09:46
0
Разобрался!
Обращался к TV полю неверно, вместо "$_modx->resource.icons" а просто «icons»
{set $rows = json_decode($_modx->resource.icons, true)}
            {foreach $rows as $row}
            <h3>{$row.title}</h3>
            <img src="{$row.img}" />
            {/foreach}
Осталось теперь только понять, почему на других проектах этого не требовалось, сборки одинаковые, сейчас глянул другие сайты, там обращаюсь без $_modx->resource.value, все работает
PS Все, тоже разобрался, там я уже с переменной работаю, которую получаю из условия {if}, поэтому обращение к классу modx не требуется, оно было ранее.
Нормально сам с собой в субботу пообщался =))))
Max
Max
23 января 2021, 09:40
0
Я столкнулся сегодня на одном из новых сайтах, разработку веду на одинаковых сборках, использую siteExtra, но на последнем сайте migx ни чего не выводит, var_dump(json_decode($value)) дает NULL.
Через getImageList выводит, нифига не пойму что где отвалилось.
Вы нашли причину?
Андрей
23 января 2021, 02:09
0
Либо написать свой сниппет для выборки заказов, либо править msGetOrder, там есть проверка вывода по id юзера, и админу чужие заказы не покажет.
Артем
23 января 2021, 01:30
+3
Понял. а если сделать проверку типа
Тогда остается доступ к произвольным *.tpl, *.html и *.php файлам. В общем, это довольно скользкая штука и рано или поздно может аукнуться. Хорошей практикой будет просто указывать этот шаблон на сервере и не париться о всяких проверках.
Тем более, в твоем примере просто проверяется наличие '@FILE' в строке, а не на первой позиции. Это я к тому, что накосячить с этим гораздо проще, чем кажется.

А если $_REQUEST['minQuery'] будет равна 'три'
То она просто скастуется до 0 через (int), а затем будет взято 3. В общем, в этой переменной всегда будет число и ошибки не будет. Максимум — условие не пройдет, если передать отрицательный minQuery.
Артур Шевченко
23 января 2021, 00:39
0
Потому что value="@CODE {$modx->removeCollection('modResource')}"
Понял. а если сделать проверку типа
if(strpos($_POST['tpl'], '@FILE') !== false){
$tpl = $_POST['tpl'];
}
достаточно просто
А если $_REQUEST['minQuery'] будет равна 'три', тут
if(mb_strlen(str_replace(' ', '', $query)) < $minQuery){
    $res = ['success' => false, 'message' => 'Количество символов в запросе должно быть больше ' . $minQuery];
    return json_encode($res);
}
будет ошибка, нет?
Артур Шевченко
23 января 2021, 00:18
0
[[+modx.user.id:ismember=`Administrator`:then=`
[[!msGetOrder? &tpl=`tpl-get-order`]]
`:else=`Доступ запрещён`]]
Sergey
23 января 2021, 00:11
0
Так нигде не написано, что она невидимая и как она отличается от второй. Теперь ясно, почему не всплывает)