• Установка

    Это альфа-версия Angiv CMF

    • Возможный вариант быстрой установки локального веб-сервера - это Open Server Panel:
      Install server
    • Скачайте архив со всеми файлами Angiv CMF и разархивируйте его в папку "c:\OpenServer\domains":
      Install run
    • Angiv CMF содержит автоматическую установку, которая поможет быстро настроить систему. После установки вы можете удалить папку "\app\installer":
      Install
    • Конфигурация Angiv CMF хранится в файле "\angiv\config\config.env":
      Configuration
  • Директории


    • Структура каталогов Angiv CMF:
      
      ┌── angiv/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Пользовательские компоненты Angiv CMF
      │   ├── asset/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Статические ресурсы
      │   │   ├── font/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Шрифты
      │   │   ├── image/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Изображения
      │   │   ├── language/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Переводы
      │   │   └── lib/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Пользовательские стили, скрипты
      │   ├── config/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Конфигурация
      │   │   ├── config.env₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Файл конфигурации Angiv CMF
      │   │   └── container.php₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Файл конфигурации PHP-DI контейнера
      │   ├── helper/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Пользовательские вспомогательные функции
      │   ├── middleware/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Пользовательское промежуточное ПО
      │   │
      │   ├── plugin/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Пользовательские плагины
      │   │   └── .../₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Название плагина
      │   │      ├── css/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Стили
      │   │      ├── image/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Изображения
      │   │      ├── js/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Скрипты
      │   │      ├── src/controller/₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Контроллеры
      │   │      ├── view/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Представления
      │   │      ├── index.php₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Файл конфигурации
      │   │      ├── icon.png₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Файл иконки
      │   │      └── scriptdatabase.php₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Скрипт базы данных
      │   │
      │   ├── storage/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Хранилище файлов
      │   ├── theme/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Шаблон
      │   │   ├── css/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Стили
      │   │   ├── js/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Скрипты
      │   │   ├── page/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Страница 401, 403, 404
      │   │   └── template.php₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Страница шаблона
      │   └── tmp/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Временные файлы (лог, кэш)
      │       ├── cache/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Cache компиляции контейнера
      │       ├── log/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Журналирование событий
      │       └── session/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Пользовательские сессии
      │
      │
      ├── app/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Системные компоненты Angiv CMF - содержимое не рекомендуется изменять
      │   ├── admin/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Панель управления
      │   │   ├── theme/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Шаблон
      │   │   │   ├── css/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Стили
      │   │   │   ├── js/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Скрипты
      │   │   │   └── template.php₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Страница шаблона
      │   │   ├── view/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Страницы панели управления
      │   │   ├── route.php₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Первичная обработка
      │   │   ├── routeauth.php₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Обработка авторизации
      │   │   ├── routeadmin.php₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Обработка страниц панели управления
      │   │   └── routeuser.php₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Обработка страниц сайта
      │   ├── asset/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Статические ресурсы
      │   │   ├── font/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Шрифты
      │   │   ├── image/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Изображения
      │   │   └── lib/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Системные стили, скрипты
      │   ├── config/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Конфигурация PHP-DI контейнера
      │   ├── helper/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Вспомогательные функции
      │   ├── installer/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Плагин автоматической установки Angiv CMF
      │   ├── middleware/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Промежуточное программное обеспечение
      │   ├── response/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Вспомогательный http-ответ
      │   ├── vendor/₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Сторонние управляющие пакеты
      │   └── bootstrap.php₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Файл начальной загрузки
      ├── public/index.php₋₋₋₋₋₋₋₋₋₋₋₋ Единая точка входа
      ├── .htaccess₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Правила перенаправления Apache
      ├── composer.json₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Описание сторонних управляющих пакетов
      ├── robots.txt₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Директивы поисковых роботов
      ├── sitemap.xml₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Карта сайта
      └── favicon.ico₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋₋ Файл иконки Angiv CMF
      
  • Ознакомьтесь с примерами плагинов в папке "\angiv\plugin"
    Рекомендуется изучить документацию, перейдя по ссылкам на главной странице
    Для тестирования API рекомендуется использовать POSTMAN или ADVANCED REST CLIENT

    Мой плагин

    В связи с будущими обновлениями не вносите изменения в системные файлы папки "app"

    • В "\angiv\plugin" создайте папку по названию плагина, к примеру, "twosliders". Внутри новой папки создайте конфигурационный файл "index.php" и файл иконки плагина "icon.png":
      Two sliders folder
    • Начните заполнять файл "index.php":
      <?php
      
      return [
      // --------------- ПАРАМЕТРЫ ПЛАГИНА ---------------
          'name' => 'Two sliders', // наименование
          'icon' => 'icon.png', // иконка
          'version' => 0.1, // версия
          //'tags' => ['nohome', 'alwaysuse', 'nodelete'], // признаки
      ];
      
      Параметр tags позволяет управлять дополнительными настройками плагина.
      - nohome: плагин не содержит домашней страницы
      - alwaysuse: плагин всегда включен
      - nodelete: плагин без возможности удаления через панель управления
    • Откройте панель управления. В навигации выберите подраздел "Плагины". Нажмите кнопку "Обновить". В системе отобразится новый плагин. Измените его статус. Вы создали свой первый плагин, но в нем пока нет страниц:
      Two sliders update
    • Добавьте страницу панели управления в файл "index.php":
      <?php
      
      return [
      // --------------- ПАРАМЕТРЫ ПЛАГИНА ---------------
          'name' => 'Two sliders', // наименование
          'icon' => 'icon.png', // иконка
          'version' => 0.1, // версия
          //'tags' => ['nohome', 'alwaysuse', 'nodelete'], // признаки
      // --------------- ПАНЕЛЬ УПРАВЛЕНИЯ (ADMIN) ---------------
          'cssadmin' => [], // стили плагина
          'jsadmin' => [], // скрипты плагина
          'ajaxadmin' => [], // ajax-запросы плагина
          'pagesadmin' => [ // страницы плагина
              // ----- СТРАНИЦА SLIDER -----
              [
                  'title' => 'Page slider', // название страницы
                  'url' => 'adminpageslider', // url-адрес страницы
                  'controller' => 'src/controller/admin/pagesliderController.php', // контроллер страницы
                  'page' => 'view/admin/pageslider.php', // представление страницы
                  'css' => [], // стили страницы
                  'js' => [] // скрипты страницы
              ],
          ]
      ];
      
    • Создайте контроллер страницы панели управления, файл "\angiv\plugin\twosliders\src\controller\admin\pagesliderController.php":
      <?php
      
      namespace Plugin\twosliders\src\controller\admin;
      
      use Slim\Psr7\{
          Request,
          Response
      };
      use DI\Container;
      
      class pagesliderController
      {
          protected $container;
      
          public function __construct(Container $container)
          {
              $this->container=$container;
          }
      
          public function __invoke(Request $request, Response $response) {
              // -----данные
              $phpdata=['slider1.jpg', 'slider2.jpg', 'slider3.jpg', 'slider4.jpg', 'slider5.jpg'];
      
              // -----результат
              $renderer=$this->container->get('viewadmin'); // макет страницы
              return $renderer->render($response, $renderer->getAttribute('currentpage'), ['phpdata' => $phpdata]); // шаблон страницы
          }
      }
      
    • Создайте представление страницы панели управления, файл "\angiv\plugin\twosliders\view\admin\pageslider.php":
      <div class="uk-container">
          <div uk-slider>
              <ul class="uk-slider-items uk-child-width-1-2 uk-child-width-1-3@s uk-child-width-1-4@m uk-light">
                  <?php foreach ($phpdata ?? [] as $key => $item) { ?>
                      <li class="uk-transition-toggle" tabindex="0">
                          <img src="/angiv/plugin/twosliders/image/<?= $item ?>" alt="">
                          <div class="uk-position-center uk-panel"><h1 class="uk-transition-slide-bottom-small"><?= __('Slide') . ' ' . ($key + 1) ?></h1></div>
                      </li>
                  <?php } ?>
              </ul>
              <ul class="uk-slider-nav uk-dotnav uk-flex-center uk-margin"></ul>
          </div>
      </div>
      
    • Скопируйте файлы изображений в папку: "\angiv\plugin\twosliders\image\". Добавьте необходимые php-переводы в файл: "\angiv\asset\language\xx_XX\server.php".
    • Результат:
      Two sliders result
      Two sliders result
    • Правила объявления css-стилей и js-скриптов в файле "index.php":
      'css' => [
          // -----системные css ("/system/" = "\app\asset\lib\")
          '/system/uikit/css/uikit.min.css',
          // -----пользовательские css ("/custom/" = "\angiv\asset\lib\")
          '/custom/lightgallery/css/lightgallery.css',
          // -----css заданного пути (если не '/system/', '/custom/' и начинается с '/')
          '/test.css',
          // -----css страницы (путь - "\angiv\plugin\twosliders\")
          'css/user/test.css'
      ],
      'js' => [
          // -----системные js ("/system/" = "\app\asset\lib\")
          '/system/jquery/jquery.min.js',
          // -----пользовательские js ("/custom/" = "\angiv\asset\lib\")
          '/custom/lightgallery/js/lightgallery.min.js',
          // -----js заданного пути (если не '/system/', '/custom/' и начинается с '/')
          '/test.js',
          // -----js страницы (путь - "\angiv\plugin\twosliders\")
          'js/user/test.js'
      ]
      
      К примеру:
      '/system/uikit/css/uikit.min.css' - преобразуется в - <link rel="stylesheet" type="text/css" href="/app/asset/lib/uikit/css/uikit.min.css">
      '/custom/lightgallery/css/lightgallery.css' - преобразуется в - <link rel="stylesheet" type="text/css" href="/angiv/asset/lib/lightgallery/css/lightgallery.css">
      '/test.css' - преобразуется в - <link rel="stylesheet" type="text/css" href="/test.css">
      'css/user/test.css' - преобразуется в - <link rel="stylesheet" type="text/css" href="/angiv/plugin/hello/css/user/test.css">
      
      '/system/jquery/jquery.min.js' - преобразуется в - <script type="text/javascript" src="/app/asset/lib/jquery/jquery.min.js"></script>
      '/custom/lightgallery/js/lightgallery.min.js' - преобразуется в - <script type="text/javascript" src="/angiv/asset/lib/lightgallery/js/lightgallery.min.js"></script>
      '/test.js' - преобразуется в - <script type="text/javascript" src="/test.js"></script>
      'js/user/test.js' - преобразуется в - <script type="text/javascript" src="/angiv/plugin/twosliders/js/user/test.js"></script>
      
      Css-стили и js-скрипты допускается объявлять в виде массива:
      <!-- массив css -->
      ['href' => 'test.css'] - преобразуется в - <link rel="stylesheet" type="text/css" href="/angiv/plugin/hello/css/user/test.css">
      ['href' => '/system/uikit/css/uikit.min.css', 'attr' => 'async'] - преобразуется в - <link rel="stylesheet" type="text/css" href="/app/asset/lib/uikit/css/uikit.min.css" media="none" onload="if(media!='all'){media='all';this.onload=null;}"><noscript><link rel="stylesheet" type="text/css" href="/app/asset/lib/uikit/css/uikit.min.css"></noscript>
      
      <!-- массив js -->
      ['src' => 'test.js'] - преобразуется в - <script type="text/javascript" src="test.js"></script>
      ['src' => 'test.js', 'attr' => 'defer'] - преобразуется в - <script type="text/javascript src="test.js" defer></script>
      ['src' => 'test.js', 'attr' => 'async'] - преобразуется в - <script type="text/javascript src="test.js" async></script>
      ['type' => 'module', 'src' => 'test.js'] - преобразуется в - <script type="module" src="test.js"></script>
      ['type' => 'module', 'src' => 'test.js', 'attr' => 'async'] - преобразуется в - <script type="module" src="test.js" async></script>
      
    • Способ добавления страницы сайта в файл "index.php" вы можете изучить на примере плагинов "twosliders", "hello", "guide".
    • Поисковая оптимизация seo. Для каждой страницы сайта (кроме страниц панели управления) в файле "index.php" возможно указать настройки seo:
      <?php
      
      return [
      // --------------- САЙТ (USER) ---------------
          'cssuser' => [], // стили плагина
          'jsuser' => [], // скрипты плагина
          'ajaxuser' => [], // ajax-запросы плагина
          'pagesuser' => [ // страницы плагина
              // ----- СТРАНИЦА SLIDER -----
              [
                  'title' => 'Page slider', // название страницы
                  'url' => 'userpageslider', // url-адрес страницы
                  'controller' => 'src/controller/user/pagesliderController.php', // контроллер страницы
                  'page' => 'view/user/pageslider.php', // представление страницы
                  'css' => [], // стили страницы
                  'js' => [], // скрипты страницы
                  'seo' => [, // поисковая оптимизация
                      'description' => '', // описание
                      'keywords' => '', // ключевые слова
                      'canonicalurl' => '', // канонический url
                  ],
                  'ogseo' => [, // open graph поисковая оптимизация
                      'ogsitename' => '', // расширенное название
                      'ogdescription' => '', // описание
                      'ogtype' => '', // тип содержимого
                      'ogurl' => '', // канонический url
                      'ogimage' => '', // изображение публикации
                  ]
              ],
          ]
      ];
      
  • Рекомендуется изучить документацию medoo php database framework
    Пример приведен в плагине "\angiv\plugin\hello\src\controller\admin\pagedatabaseController.php"

    База данных


    • Настройка подключения к базе данных в Angiv CMF:
      1) В файле "\angiv\config\config.env" настраиваются основные параметры подключения к базе данных:
      Configuration database
      2) Дополнительные параметры можно указать в файле "\angiv\config\container.php", где выполняется инициализация подключения к базе данных:
      <?php
      'database' => function (Container $container) {
          return (envbool('APP_DATABASE_USE') === true) ? ( // если использование базы данных
              new Medoo([
                  'type' => 'mysql', // тип базы данных
                  'host' => env('APP_DATABASE_HOST', 'localhost'), // имя сервера или ip-адрес
                  'database' => env('APP_DATABASE_NAME', 'angiv'), // имя базы данных
                  'username' => env('APP_DATABASE_USER', 'username'), // имя пользователя
                  'password' => env('APP_DATABASE_PASSWORD', 'userpassword'), // пароль пользователя
                  'prefix' => env('APP_DATABASE_PREFIX', 'ang_'), // префикс таблиц
                  'charset' => 'utf8', // кодировка
                  'error' => PDO::ERRMODE_EXCEPTION, // тип обработки ошибок(https://medoo.in/api/error)
                  //'logging' => true // ведение журнала логирования всех sql-запросов
              ])
          ) : null;
      }
      
    • В файле "index.php" можно указать специальный скрипт базы данных:
      <?php
      
      return [
      // --------------- ПАРАМЕТРЫ ПЛАГИНА ---------------
          'name' => 'Two sliders', // наименование
          'icon' => 'icon.png', // иконка
          'version' => 0.1, // версия
          //'tags' => ['nohome', 'alwaysuse', 'nodelete'], // признаки
          'scriptdatabase' => 'scriptdatabase.php', // Скрипт базы данных
      
      Пример файла "scriptdatabase.php":
      <?php
      
      namespace Plugin\hello;
      
      use Slim\Psr7\Response;
      use App\response\customResponse;
      
      class scriptdatabase
      {
          // --------------- СКРИПТ БАЗЫ ДАННЫХ ---------------
          public static function executescriptdatabase(Response $response) {
              $res=false; $msg='';
      
              // --------------- СОЗДАНИЕ ТАБЛИЦЫ ---------------
              if (!empty($db=$GLOBALS['app']->getContainer()->get('database'))) { // подключение к базе данных
                  $tablename=str_replace('"', '', $db->tableQuote('hello')); // название таблицы
                  //$tablename=env('APP_DATABASE_PREFIX', 'ang_') . 'hello';
                  if ($db->query("SHOW TABLES LIKE '{$tablename}'")->fetchColumn() === false) { // проверка существования таблицы
                      //$db->drop('hello');
                      $db->create('hello', [
                          // -----поля
                          'id' => ['integer', 'unsigned', 'auto_increment', 'not null', "comment 'id client'"],
                          'name' => ['varchar(255)', 'not null', 'collate utf8mb4_general_ci', "comment 'name client'"],
                          'age' => ['integer', 'unsigned', 'default null', "comment 'age client'"],
                          // -----первичный ключ
                          'primary key (...)',
                          // -----уникальные индексы
                          'unique (...)',
                          // -----индексы
                          'index (...)'
                      ]);
                      $res=true;
                  } else {$msg=sprintf(__('Table "%s" already exists'), $tablename);}
              } else {$msg=__('Connection to database failed');}
      
              // -----результат
              return customResponse::json($response, ['res' => $res, 'msg' => $msg]);
          }
      }
      
      Для запуска файла "scriptdatabase.php" откройте панель управления. В навигации выберите подраздел "Плагины". Нажмите иконку :
      Configuration database
  • Рекомендуется изучить документацию Axios
    Пример приведен в плагине "\angiv\plugin\feedback"

    Ajax-запрос


    • В файле "view\user\widgetfeedback.php" приведена форма обратной связи. Кнопка отправки ajax-запроса:
      Widget feedback
      ...
      <button class="ang-button ang-margin-left10" @click.prevent="sendmessage()">{{ $t('Send') }}</button>
      ...
      
    • В файле "js\user\widgetfeedback.js" реализована отправка ajax-запроса:
      sendmessage: function() {
          axios.post('/feedback/savemessagetext', {'messagetext': vm.messagetext})
              .then(function(response) {
                  if (response.data.res === true) {
                      //ajax-request successfully
                  } else {
                      //ajax-request warning
                  }
              })
              .catch(function(error) {
                  //ajax-request error
              });
      },
      
    • В файле "src\controller\user\ajaxwidgetController.php" реализовано сохранение текстового сообщения в базу данных:
      <?php
          public static function savemessagetext(Request $request, Response $response) {
              $data=$request->getParsedBody();
      
              try {
                  $res=false; $msg='';
                  if (!empty($db=$GLOBALS['app']->getContainer()->get('database'))) {
                      $tablename=str_replace('"', '', $db->tableQuote('feedback'));
                      if ($db->query("SHOW TABLES LIKE '{$tablename}'")->fetchColumn() !== false) {
                          $phpjwtdata=null;
                          if (!empty($request->getAttribute('jwtdata'))) {
                              $phpjwtdata=$request->getAttribute('jwtdata');
                          } else {
                              if (isset($_COOKIE['accesstoken'])) {
                                  $phpjwtdata=JWT::decode($_COOKIE['accesstoken'], new Key(env('APP_AUTH_SECRET', ''), 'HS256'));
                              }
                          }
      
                          if (!empty($phpjwtdata)) {
                              if (!empty($currentlogin=$phpjwtdata->data->authlogin)) {$data['petitioner']=strtolower($currentlogin);}
                          }
      
                          $db->insert('feedback', $data);
      
                          if (!$db->error) {$res=true;}
                      } else {$msg=__('Connection to database failed');}
                  } else {$msg=__('Connection to database failed');}
      
                  return customResponse::json($response, ['res' => $res, 'msg' => $msg]);
              } catch (\Exception $e) {
                  return customResponse::abort($e->getMessage(), $request);
              }
          }
      
  • Виджет


    • Представление виджета:
      "\plugin\hello\view\user\widgetuikit.php" или "\plugin\feedback\view\user\widgetfeedback.php"
    • Скрипт виджета:
      "\plugin\hello\js\user\widgetuikit.js" или "\plugin\feedback\js\user\widgetfeedback.js"
    • Стили виджета:
      "\plugin\hello\css\user\widgetuikit.css" или "\plugin\feedback\css\user\widgetfeedback.css"
    • Инициализация виджета на странице плагина:
      "\plugin\hello\view\user\pageuikit.php"
      ...
      <?= $this->fetch('/hello/view/user/widgetuikit.php') ?>
      
      "\plugin\guide\view\user\pagecomplicity.php"
      ...
      <?= $this->fetch('/feedback/view/user/widgetfeedback.php') ?>
      
  • Рекомендуется изучить документацию tuupola slim jwt authentication

    Авторизация


    • Применение авторизации:
      1) В файле "\angiv\config\config.env" настраиваются параметры авторизации:
      Configuration database
      - url-адрес страницы авторизации: "https://имя домена/auth/welcome"
      - логин: admin
      - пароль: admin
      - логин: guest
      - пароль: qwerty
    • Реализация авторизации в Angiv CMF (для ознакомления):
      1) Инициализация авторизации: "\angiv\app\config\container.php", "\angiv\app\admin\route.php", "\app\admin\routeadmin.php", "\app\admin\routeuser.php";
      2) Контроллер страницы авторизации: "\angiv\app\admin\routeauth.php";
      3) Страница авторизации: "\angiv\plugin\auth\view\user\pageauth.php";
      4) Контроллер ajax-запросов страницы авторизации (проверка имени пользователя и пароля, сохранение токена в cookies): "\angiv\plugin\auth\src\controller\ajaxauthController.php";
      5) Страница обработки отказа в доступе: "\angiv\theme\page\401.php".
    • Добавление пользователя:
      1) В файл "\angiv\config\config.env" добавьте нового пользователя newuser и вручную создайте пароль при помощи (phppasswordhash):
      Configuration database
      2) Откройте панель управления. В навигации выберите подраздел "Пользователи". Проверьте результат добавления нового пользователя:
      Users
      3) Нового пользователя можно добавить в базу данных. Если настроено подключение к базе данных, тогда на странице "Пользователи" будет доступна кнопка "Добавить":
      Users
      Управление пользователями реализовано в плагине "\angiv\plugin\users\", который вы всегда можете изменить с учетом собственных требований.
    • Добавление разрешения:
      В файле "\angiv\config\config.env" создайте новое разрешение или назначьте пользователя newuser в имеющееся разрешение:
      Configuration database
    • Применение разрешений:
      1.1) Для ограничения доступа к странице сайта: откройте конфигурационный файл плагина, например "\angiv\plugin\hello\index.php" и добавьте параметр access в раздел pageuser.
      В параметре access укажите зарезервированное значение auth (доступ разрешен только авторизованным пользователям) или название роли из файла "\angiv\config\config.env".
      Если параметр access не указан, тогда страница сайта будет доступна всем пользователям:
      'pagesadmin' => [
              [
                  'title' => 'Page vue',
                  'url' => 'adminpagevue',
                  'controller' => 'src/controller/user/pageuikitController.php',
                  'page' => 'view/user/pageuikit.php',
                  //'access' => ['auth', 'hello_page_view'],
                  'css' => [],
                  'js' => []
              ],
      
      1.2) Для ограничения доступа к ajax-запросу сайта: откройте контроллер ajax-запросов плагина. Добавьте параметр access в аннотацию @route соответствующего ajax-запроса, пример файла "\angiv\plugin\hello\src\controller\user\ajaxuserController.php":
      class ajaxuserController
      {
          /**
           * @route({"url": "getusertext[/{id}]", "methods": ["post"], "csrf": true, "access": ["hello_ajax_exec"]})
           */
          public static function getusertext(Request $request, Response $response, $id = '') {
              $params=$request->getQueryParams();
              $data=$request->getParsedBody();
      
              try {
                  //$container=$GLOBALS['app']->getContainer();
                  $res=['res' => true, 'text user' => __('Example text'), 'id' => $id, 'params' => $params, 'data' => $data];
                  return customResponse::json($response, $res);
              } catch (\Exception $e) {
                  return customResponse::abort($e->getMessage(), $request);
              }
          }
      }
      
      Обратите внимание, что доступ к страницам и ajax-запросам панели управления разрешен только авторизованным пользователям с ролью APP_PERM_ROLE_control_panel.
      Если пользователю ограничен доступ, тогда будет выполнена переадресация на страницу "\angiv\theme\page\403.php":
      Configuration database
    • Блокировка по ip-адресу:
      В файле "\angiv\config\config.env" заполните список разрешенных и запрещенных ip-адресов:
      Blocking by ip-address
  • Рекомендуется изучить документацию RKA Slim Session Middleware

    Сессия


    • Настройка сессии:
      В файле "\angiv\config\container.php" настраиваются параметры сессии:
      <?php
      'session' => function () {
          $session=new SessionMiddleware([
              'name' => 'sessiondata', // имя сессии
              'lifetime' => 31536000, // время истечения срока действия cookie (0 - при закрытии браузера)
              'path' => '/', // url из которого будут доступны cookie
              //'domain' => 'angiv', // домен, которому принадлежит cookie
              'httponly' => true, // запрет доступа для клиентских скриптов
              'secure' => true, // отправление только через https
              'cache_limiter' => 'nocache' // режим кеширования
          ]);
          $session->start();
          return $session;
      },
      
      Файлы сессий пользователей хранятся в папке "\angiv\tmp\session"
  • Рекомендуется изучить документацию Slim Framework CSRF Protection

    Csrf защита


    • Применение csrf защиты:
      Для управления csrf требуемого ajax-запроса сайта откройте контроллер ajax-запросов сайта соответствующего плагина. Добавьте параметр "csrf": true в аннотацию @route, пример файла "\angiv\plugin\hello\src\controller\user\ajaxuserController.php":
      <?php
      
      namespace Plugin\hello\src\controller\user;
      
      use Slim\Psr7\{
          Request,
          Response
      };
      use App\response\customResponse;
      
      class ajaxuserController
      {
          /**
           * @route({"url": "getusertext[/{id}]", "methods": ["post"], "csrf": true, "access": ["hello_ajax_exec"]})
           */
          public static function getusertext(Request $request, Response $response, $id = '') {
              $params=$request->getQueryParams();
              $data=$request->getParsedBody();
      
              try {
                  //$container=$GLOBALS['app']->getContainer();
                  $res=['res' => true, 'text user' => __('Example text'), 'id' => $id, 'params' => $params, 'data' => $data];
                  return customResponse::json($response, $res);
              } catch (\Exception $e) {
                  return customResponse::abort($e->getMessage(), $request);
              }
          }
      }
      
    • Реализация csrf защиты в Angiv CMF (для ознакомления):
      1) Функция $pagereg файла "\app\admin\route.php" служит для первоначального создания и передачи csrf в шаблон страницы:
      $pagereg = function ($plugin, $page, $view) use ($app, $container) {
          ...
          // -----промежуточное ПО
          $route->add($container->get('csrf')); // 3) csrf защита
          ...
          $route->add(new rendererMiddleware($container, $view, $plugin, $page)); // 4) предварительный рендеринг шаблона
      };
      
      2) Подключение csrf защиты выполняется в файле "\angiv\app\admin\routeuser.php":
      ...
      if ($method['csrf'] === true) {$route->add($container->get('csrf'));}
      ...
      
      3) Созданный csrf-токен передается в шаблон страницы сайта при помощи промежуточного ПО предварительного рендеринга шаблона "\app\middleware\rendererMiddleware.php":
      public function __invoke(Request $request, RequestHandler $handler) {
          ...
          // -----csrf
          $phpcsrf=(!empty($request) ? $request->getAttribute('csrf_name', '') . '|' . $request->getAttribute('csrf_value', '') : '|'); // получение csrf
          $renderer->addAttribute('phpcsrf', '"' . (($phpcsrf == '|') ? '' : $phpcsrf) . '"');
          ...
      }
      
      4) В шаблоне страницы сайта "\angiv\theme\template.php" используется javascript-переменная window.$csrf для хранения csrf:
      <head>
          ...
          <script>window.$csrf=<?= $phpcsrf ?>;</script>
          <script type="text/javascript" src="/app/asset/lib/axios/axios.min.js"></script>
          <script type="text/javascript" src="/app/asset/lib/axios/axios-advanced.js"></script>
          ...
      </head>
      
      5) В файле "\app\asset\lib\axios\axios-advanced.js" реализована синхронизация csrf и параметра заголовка запроса/ответа сервера:
      // --------------- ПЕРЕХВАТ ЗАПРОСА ---------------
      axios.interceptors.request.use(function (request) {
          if (!!window.$csrf) {request['headers']['csrf']=window.$csrf;} // передача csrf
      });
      // --------------- ПЕРЕХВАТ ОТВЕТА ---------------
      axios.interceptors.response.use(
          function (response) {
              ...
              if (!!response['headers']['csrf']) {window.$csrf=response['headers']['csrf'];} // получение (обновление) csrf
              ...
          },
          function (error) {
              ...
              if (!!error.response.data.csrf) {window.$csrf=error.response.data.csrf;} // получение (обновление) csrf
              ...
          }
      );
      
      6) Файлы, связанные с работой csrf:
      "\app\asset\lib\axios\axios-advanced.js"
      "\app\response\customResponse.php"
      "\app\vendor\slim\csrf\src\Guard.php"
      "\app\vendor\slim\slim\Slim\Error\Renderers\JsonErrorRenderer.php"
      "\app\bootstrap.php"

      "\angiv\plugin\auth\view\user\pageauth.php"
      "\app\config\container.php"
      "\app\admin\route.php"
      "\app\admin\routeadmin.php"
      "\app\admin\routeauth.php"
      "\app\admin\routeuser.php"
      "\app\helper\functions.php"
      "\app\middleware\rendererMiddleware.php"
      "\angiv\theme\template.php"
      "\app\admin\theme\template.php"
  • Рекомендуется изучить документацию Symfony Mailer
    Пример приведен в плагине "\angiv\plugin\hello\src\controller\admin\ajaxadminController.php"

    Почта


    • Работа с почтой
      В файле "\angiv\config\config.env" настраиваются параметры для работы с почтой:
      Configuration database