<?xml version='1.0' encoding='UTF-8'?>
<rss version='2.0'>
	<channel>
		<title>Lily Software</title>
		<link>https://lily-software.com</link>
		<description>Создание интернет сайтов в Краснодаре, web дизайн, web консалтинг</description>
		<generator>Cotonti</generator>
		<language>ru</language>
		<pubDate>Sat, 11 Apr 2026 21:46:29 +0300</pubDate>

		<item>
			<title>File System</title>
			<description><![CDATA[<p style="text-align:justify;">Компонент для работы с файловыми хранилищами на основе <a href="https://flysystem.thephpleague.com" target="_blank" rel="nofollow noreferrer noopener">Flysystem</a>.<br />
Он позволяет работать как с локальной файловой системой, так и с удаленными хранилищами  используя единый интерфейс. Например с Amazon AWS S3, Azure Blob Storage, Yandex Objet Storage, BunnyCdn, Google Cloud Storage, WebDav, FTP, SFTP и др.</p>

<p>Класс для работы с локальной файловой системой входит в состав <strong>Cotonti Lib</strong> и не требует доплнительной установки других библиотек. Его интерфейс совместим с <code>\League\Flysystem\FilesystemOperator</code> и они взаимозаменяемы.</p>

<p>Для подключения другой (удаленной) файловой системы нужно установить <a href="https://flysystem.thephpleague.com/docs/" target="_blank" rel="nofollow noreferrer noopener">Flysystem и нужный адаптер</a>.</p>

<p>Для этого в <code>composer.json</code> нужно добавить строки:</p>

<pre class="brush:plain;">
"league/flysystem": "^3.0",
"league/flysystem-aws-s3-v3": "^3.0"</pre>

<p>В этом примере мы добавили адаптер для файловых хранилищ, поддерживающий AWS S3.</p>

<p>И выполнить в командной строке:</p>

<pre class="brush:bash;">
composer update</pre>

<p>Composer для Windows имеет баг который может в файле <code>lib/composer/autoload_static.php</code> сделать что то такое:</p>

<pre class="brush:php;">
public static $fallbackDirsPsr4 = array (
  0 =&gt; 'C:\\OpenServerData\\domains\\my-site.loc\\public_html\\lib',
);
</pre>

<p>Надо вернуть как было:</p>

<pre class="brush:php;">
public static $fallbackDirsPsr4 = array (
  0 =&gt; DIR . '/../..' . '/lib',
);</pre>

<p>Теперь адатер файловой системы готов к использованию в коде Ваших расширений.</p>

<p> </p>

<p style="text-align:justify;">Для создания экземпляра можно воспользоваться инструкцией к соотвествующему <a href="https://flysystem.thephpleague.com/docs/" target="_blank" rel="nofollow noreferrer noopener">адаптеру</a> или воспользоваться <strong>"фабрикой"</strong> из <strong>Cotonti Lib</strong>.<br />
Использование фабрики является предпочтительным при создании расширений т.к. позволяет конфигурировать подключения к файловым системам и использовать нужные в зависимости от конфигурации.</p>

<p> </p>

<h3>Конфигурирование файловых систем.</h3>

<p> </p>

<p>В файл <code>datas/config.php</code> нужно добавить элемент такого вида:</p>

<pre class="brush:php;">
$cfg['filesystem'] = [
	
    // Подключение к Yandex Object Storage
    'Yandex.Cloud' =&gt; [
        'adapter' =&gt; '\League\Flysystem\AwsS3V3\AwsS3V3Adapter',
        'config' =&gt; [
            //'version' =&gt; 'latest', // Optional
            'endpoint' =&gt; 'https://storage.yandexcloud.net',
            'region' =&gt; 'ru-central1',
            'bucket' =&gt; 'my-bucket-name',
            'accessKey' =&gt; 'MyAccessKey',
            'secretKey' =&gt; 'MySecretKey',

            // install: composer require league/flysystem-path-prefixing:^3.3 to use prefix
            //'pathPrefix' =&gt; 'a/path/prefix',
        ],
    ],
	
    // Подключение к другому серверу по FTP
    'FTP' =&gt; [
        'adapter' =&gt; '\League\Flysystem\Ftp\FtpAdapter',
        'config' =&gt; [
            'client' =&gt; [
                'host' =&gt; 'my-pretty-host.tld',
                'root' =&gt; '/var/www/files/storage/here',
                'username' =&gt; 'server-user',
                'password' =&gt; 'someThingReallySecret',
            ],

            // install: composer require league/flysystem-path-prefixing:^3.3 to use prefix
            //'pathPrefix' =&gt; 'a/path/prefix',
        ],
    ],
	
    // Подключение к BunnyCDN
    'BunnyCDN' =&gt; [
        'adapter' =&gt; '\PlatformCommunity\Flysystem\BunnyCDN\BunnyCDNAdapter',
        'config' =&gt; [
            'storageZoneName' =&gt; 'test-files',
            'apiKey' =&gt; 'my-api-key',
            'pullZoneUrl' =&gt; 'https://test-files.b-cdn.net',
            //'region' =&gt; 'de', // optional

            // install composer require league/flysystem-path-prefixing:^3.3 to use prefix
            //'pathPrefix' =&gt; 'a/path/prefix',
        ],
    ],
];	
</pre>

<p>В этом примере мы сконфигурировали подключение к <strong>Yandex Object Storage</strong> и к удаленному серверу по <strong>FTP</strong>.</p>

<p><strong>Ключ массива</strong> - это название подключения, может быть любым.</p>

<p style="text-align:justify;"><strong>'adapter'</strong> - имя класса адаптера. Поддерживаются и псевдонимы. Например вместо <code>'\League\Flysystem\AwsS3V3\AwsS3V3Adapter'</code> можно использовать <code>'Aws'</code> или <code>'AwsS3'</code>. Фабрика их поймет.</p>

<p><strong>'config'</strong> - конфигурация подключения. Т.к. файловые системы имют очень разные API и способы подключения, то для каждого адаптера 'config' свой.<br />
За подробностями можно обратиться к описанию самого <a href="https://flysystem.thephpleague.com/docs/" target="_blank" rel="nofollow noreferrer noopener">адаптера</a> и в код <a href="https://github.com/Alex300/cotonti-lib/blob/master/lib/filesystem/FilesystemFactory.php" target="_blank" rel="nofollow noreferrer noopener">файла фабрики</a>.</p>

<p style="text-align:justify;">Если вы хотите добавить в фабрику подключение адаптера, которого в ней нет или создать подключение с более специфичной конфигурацией, то это можно сделать либо через хук <code>filesystem.getFilesystem</code> либо определив функцию <code>cot_getFilesystem($fileSystemName, $pathPrefix)</code>.</p>

<p> </p>

<p>Пример использования:</p>

<pre class="brush:php;">
use \filesystem\FilesystemFactory;

// Получить экземпляр класса файловой системы по имени подлючения из конфига выше
$filesystem = FilesystemFactory::getFilesystem('Yandex.Cloud');

// Запись в файл
$filesystem-&gt;write($path, $contents);</pre>

<p> </p>

<p>Методы класса <code>\League\Flysystem\Filesystem</code> описаны в <a href="https://flysystem.thephpleague.com/docs/usage/filesystem-api/" target="_blank" rel="nofollow noreferrer noopener">документации</a>.</p>
]]></description>
			<pubDate>Tue, 24 Oct 2023 18:38:00 +0300</pubDate>
			<link><![CDATA[https://lily-software.com/free-scripts/cotonti-lib/file-system]]></link>
		</item>
		<item>
			<title>Image bundle</title>
			<description><![CDATA[<p>Компонент для работы с изображениями. Работает как с библиотекой <a href="https://www.php.net/manual/ru/book.image.php" target="_blank" rel="nofollow noreferrer noopener">GD</a>, так и с <a href="https://www.php.net/manual/ru/book.imagick.php" target="_blank" rel="nofollow noreferrer noopener">ImageMagick</a>. Последняя поддерживает большее количество форматов изображений, в т.ч. HEIC/HEIF, которые используются в смартфонах iPhone от Apple.</p>

<p>По умолчанию, если устанвлена ImageMagick, то используется она.</p>

<p>Чтобы использовать этот компонент в Ваших расширениях, добавте в начало php-файла</p>

<pre class="brush:php;">
&lt;?php

use image\Image;</pre>

<p> </p>

<p>Получить используемый драйвер:</p>

<pre class="brush:php;">
$driver = Image::currentDriver();</pre>

<p>Метод возвращает одну из констант: <code>Image::DRIVER_IMAGICK</code> или <code>Image::DRIVER_GD</code> или <code>null</code>, если ни одна из библиотек недоступна и обработка изображений невозможна.</p>

<p> </p>

<p>Получить список поддерживаемых форматов в виде массива:</p>

<pre class="brush:php;">
$supportedFormats = Image::supportedFormats();</pre>

<p> </p>

<p>Загрузка изображения для дальнейшей обработки:</p>

<pre class="brush:php;">
$image = Image::load($path, ?array $options = null);</pre>

<p>в <code>$path</code> можно передать<br />
- строку с путем к файлу или URL удаленного файла<br />
- ресурс, полученный от <a href="https://www.php.net/manual/ru/function.fopen.php" target="_blank" rel="nofollow noreferrer noopener"><code>fopen()</code></a><br />
- строку с бинарными данными, содержащими избражение или строку закодированную в <strong>base64</strong> c бинарными данными изображения<br />
- <a href="https://ru.wikipedia.org/wiki/Data:_URL" target="_blank" rel="nofollow noreferrer noopener">data URL</a></p>

<p>в <code>$options</code> можно указать какой именно использовать, например:</p>

<pre class="brush:php;">
$image = Image::load('/path/to/file', ['driver' =&gt; Image::DRIVER_GD]);</pre>

<p>Этот метод возвращает экземпляр класса <code>\image\imagick\Image</code> или <code>\image\gd\Image</code>, которые являются наследниками класса <code>\image\AbstractImage</code>. Или будет выброшено исключение в случае неудачи.</p>

<p> </p>

<h3>Методы класса для работы с изображениями:</h3>

<p> </p>

<p>Можно получить экземпляр класса <code>\Imagick</code> или <code>\GdImage</code>|<code>resource</code> (в зависимости от используемой библиотеки) и работать с ними напрямую:</p>

<pre class="brush:php;">
$image-&gt;getData();</pre>

<p> </p>

<p>Сохранить изображение:</p>

<pre class="brush:php;">
$image-&gt;save(?string $fileName = null, ?int $quality = null, ?string $format = null);</pre>

<p><code>$fileName</code> - полный путь и имя файла для сохранения. Если не указано, то изменения будут сохранены в ранее загруженный файл. Иначе будет создан новый файл, а старый останется без изменений.</p>

<p><code>$quality</code> - качество. Используется только если формат сохраняемого файла поддерживает этот параметр.</p>

<p><code>$format</code> - формат сохраняемого изображения. Если не указано, будет использовано расширение файла.</p>

<p> </p>

<p>Кодирование формата в указанный формат:</p>

<pre class="brush:php;">
$image-&gt;encode(string $format, ?int $quality = null, ?string $fileName = null);</pre>

<p><code>$format</code> - формат изображения. Например: 'jpeg', 'png', 'heif'. Или 'data-url' для кодирования изображения в data Url;</p>

<p><code>$quality</code> - качество. Используется только если формат сохраняемого файла поддерживает этот параметр.</p>

<p><code>$fileName</code> - Имя файла для сохранения изображения. Если <code>null</code> - изображение будет возвращено в виде строки бинарных данных.</p>

<p> </p>

<pre class="brush:php;">
$image-&gt;crop(int $width, int $height, ?int $x = null, ?int $y = null);</pre>

<p>Обрезает изображение.</p>

<p>Параметры <code>$x</code> и <code>$y</code> координаты правого верхнего угла области для нового изображения.</p>

<p><code>$width</code> и <code>$height</code> - ширина и высота области нового изображения.</p>

<p> </p>

<pre class="brush:php;">
$image-&gt;fixOrientation();</pre>

<p>Поворачивает изображение в соотвествии с данными об ориентации из EXIF</p>

<p> </p>

<pre class="brush:php;">
$image-&gt;flipHorizontally();
$image-&gt;flipVertically();</pre>

<p>Отразить изображение горизонтально или вертикально соотвественно</p>

<p> </p>

<pre class="brush:php;">
$image-&gt;getWidth();
$image-&gt;getHeight();</pre>

<p>Возвращают ширину и высоту изображения.</p>

<p> </p>

<pre class="brush:php;">
$image-&gt;getOrientation();</pre>

<p>Возвращает ориентацию изображения из EXIF.</p>

<p> </p>

<pre class="brush:php;">
$image-&gt;paste(AbstractImage $image, $x, $y, $alpha = 100);</pre>

<p>Вставляет одно изображение в другое. Может использоваться для наложения "водяного знака" или создания коллажей.</p>

<p><code>$image</code> - вставляемое изображение. Экземпляр класса <code>\image\imagick\Image</code> или <code>\image\gd\Image</code>,</p>

<p><code>$x</code>, <code>$y</code> - координаты левого верхнего угла вставляемого изображения</p>

<p><code>$alpha</code> - прозрачность вставляемого изображения. 0 - полностью прозрачное. 100 - полностью непрозрачное.</p>

<p> </p>

<pre class="brush:php;">
$image-&gt;removeAnimation()</pre>

<p>Удаление анимации. <strong>Gd</strong> и так не поддерживает анимацию. При использовании <strong>Imagick</strong>, в изображении будет оставлен только первый кадр.</p>

<p> </p>

<pre class="brush:php;">
$image-&gt;resize($width = null, $height = null, string $filter = Image::FILTER_UNDEFINED)</pre>

<p>Изменение размера изображения.</p>

<p><code>$width</code>, <code>$height</code> - новые ширина и высота изображения. Могут указываться как целое число в пикселях (1920) или процент ('80%'). Если ширина или высота не указана (null), то ее значение будет расчитано пропорционально.</p>

<p><code>$filter</code> - фильтр применяемый для масштабирования. Одна из констант <code>\image\Image::FILTER_XXX</code>. <strong>GD</strong> не поддерживает фильтров и игнорирует этот параметер.</p>

<p> </p>

<pre class="brush:php;">
$image-&gt;rotate($angle, $background = null)</pre>

<p>Поворачивает изображение на указанное количество градусов</p>

<p> </p>

<pre class="brush:php;">
$image-&gt;strip()</pre>

<p>Удаляет EXIF данные из изображения. <strong>Gd</strong> удаляет эти данные в любом случае.</p>

<p> </p>

<pre class="brush:php;">
$image-&gt;thumbnail(
    $width, 
    $height, 
    string $resize = Image::THUMBNAIL_OUTBOUND, 
    bool $upscale = false, 
    string $filter = Image::FILTER_LANCZOS
)</pre>

<p>Создает миниатюру изображения</p>

<p><code>$width</code>, <code>$height</code> - новые ширина и высота изображения. Могут указываться как целое число в пикселях (1920) или процент ('80%'). Если ширина или высота не указана (null), то ее значение будет расчитано пропорционально.</p>

<p><code>$resize</code> - как создавать миниатюру. Одна из констант:</p>

<ul>
	<li><code>\image\Image::THUMBNAIL_OUTBOUND</code> - масштабирует изображение пропорционально таким образом, чтобы его ширина и высота были не меньшне указанных размеров. Если вторая сторона при этом превышает указанное значение - она обрезается.</li>
	<li><code>\image\Image::THUMBNAIL_INSET</code> - Исходное изображение масштабируется таким образом, чтобы оно полностью умещалось в размерах миниатюры (соотношение ширины и высоты изображения не меняется).    </li>
	<li><code>\image\Image::THUMBNAIL_HEIGHT</code> - Миниатюра масштабируется так, чтобы ее высота равнялась желаемой высоте (соотношение ширины и высоты изображения не меняется).    </li>
	<li><code>\image\Image::THUMBNAIL_WIDTH</code> - Миниатюра масштабируется так, чтобы ее ширина равнялась желаемой ширине (соотношение ширины и высоты изображения не меняется).</li>
</ul>

<p><code>$upscale</code> - увеливать изображение, если оно меньше указанных размеров.</p>

<p><code>$filter</code> - фильтр применяемый для масштабирования. Одна из констант <code>\image\Image::FILTER_XXX</code>. <strong>GD</strong> не поддерживает фильтров и игнорирует этот параметер.</p>

<p> </p>

<p> </p>

<p>Пример использования. Сделаем из исходного изображения миниатюру 160x160 и сохраним ее в формате jpeg:</p>

<pre class="brush:php;">
$image = Image::load('/path/to/image.heic');

// Сделаем миниатюру
$image-&gt;thumbnail(160, 160, Image::THUMBNAIL_OUTBOUND);

// Сохраним в формате JPEG
$image-&gt;save('/path/to/image_160x160.jpg', 80);

// Выгрузим изображение из памяти:
unset($image);</pre>

<p> </p>
]]></description>
			<pubDate>Tue, 24 Oct 2023 12:48:00 +0300</pubDate>
			<link><![CDATA[https://lily-software.com/free-scripts/cotonti-lib/image-bundle]]></link>
		</item>
		<item>
			<title>Cotonti - Files</title>
			<description><![CDATA[<p style="text-align:justify;">Модуль для <a href="https://lily-software.com/go.php?cotonti.com" target="_blank" rel="noreferrer noopener">CMF Cotonti</a>.</p>

<p style="text-align:justify;"><em>тип:</em> <strong>модуль</strong><br />
<em>Версия модуля</em>: <strong>2.1.0</strong><br />
<em>Совместимость</em>: <strong>Siena</strong></p>

<p style="text-align:justify;">GitHub: <a href="https://lily-software.com/go.php?https://github.com/Alex300/files" target="_blank" rel="noreferrer noopener">https://github.com/Alex300/files</a></p>

<p style="text-align:justify;"><br />
Модуль организует управление вложениями к страницам, постам и любым другим объектам, создание фотогалерей на страницах и постах. А также совмещает в себе персональное файловое хранилище пользователей, файловое хранилище сайта для администраторов, управление аватарами и альбомами пользователей.<br />
Он является заменой модуля PFS, плагина «User images», входящих в «коробку» Cotonti и плагина «Attach2».</p>

<p> </p>

<p style="text-align:justify;"><strong>1. Особенности</strong></p>

<ul>
	<li style="text-align:justify;">Хранение файлов как в локальной файловой системе на сервере, так и в удаленных файловых хранилищах, таких как Amazon AWS S3, Azure Blob Storage, Yandex Objet Storage, BunnyCdn, Google Cloud Storage, WebDav, FTP, SFTP и др.</li>
	<li style="text-align:justify;">Современный механизм загрузки основанный на <a href="https://lily-software.com/go.php?https://github.com/blueimp/jQuery-File-Upload" target="_blank" rel="noreferrer noopener">jQuery File Upload</a></li>
	<li style="text-align:justify;">Поддержка мультизагрузки.</li>
	<li style="text-align:justify;">Петаскивание файлов мышью прямо на форму загрузки.</li>
	<li style="text-align:justify;">Загрузка файлов по-частям («Чанками») позволяет обойти ограничение на загрузку файла через $_POST в 2 мб.</li>
	<li style="text-align:justify;">Использование для обработки изображений как библиотеки <a href="https://www.php.net/manual/ru/book.image.php" target="_blank" rel="nofollow noreferrer noopener">GD</a>, так и <a href="https://www.php.net/manual/ru/book.imagick.php" target="_blank" rel="nofollow noreferrer noopener">ImageMagick</a>. Последняя поддерживает большее количество форматов изображений, в т.ч. HEIC/HEIF, которые используются в смартфонах iPhone от Apple.</li>
	<li style="text-align:justify;">Уменьшение больших изображений до указанных размеров при загрузке.</li>
	<li style="text-align:justify;">Использование водяного знака (watermark) для изображений.</li>
	<li style="text-align:justify;">Простая интергация через обратный вызов функций из шаблона.</li>
	<li style="text-align:justify;">Загрузки подсчитываются и происходят с оригинальным именем файла.</li>
	<li style="text-align:justify;">Создание изображений для предпросмотра (thumbnail) и простая его настройка.</li>
	<li style="text-align:justify;">Поддержка экстраполей.</li>
	<li style="text-align:justify;">Специальные ББкоды для вставки изображений и галлерей в текст страниц вне зависимости от выбранного парсера.</li>
	<li style="text-align:justify;">Поддерживаемые форматы изображений библиотекой GD: .avif, .bmp, .gif, .jpg, .png, .tga, .tpic, .wbmp, .webp, .xbm</li>
	<li style="text-align:justify;">Поддерживаемые <a href="https://imagemagick.org/script/formats.php" target="_blank" rel="nofollow noreferrer noopener">форматы изображений библиотекой Imagick</a>.</li>
</ul>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><strong>2. Системные требования и ограничения:</strong></p>

<ul>
	<li style="text-align:justify;">Установленная Cotonti Siena версии не ниже 0.9.24 beta. (Files v. 1.0.8 совместим с Cotonti Siena 0.9.18)</li>
	<li style="text-align:justify;">PHP версии 7.4 и выше. (Files v. 1.0.8 совместим с PHP v 5.4)<br />
	<strong>.bmp</strong> библиотекой GD поддерживается на PHP &gt;= 7.2,<br />
	<strong>.tga</strong> библиотекой GD загрузка поддерживается на PHP &gt;= 7.4, уменьшенные копии изображений создаются в JPEG<br />
	<strong>.avif</strong> библиотекой GD поддерживается на PHP &gt;= 8.1</li>
	<li style="text-align:justify;">Для использования удаленного файлового хранилища требуется установленная <a href="https://flysystem.thephpleague.com" rel="nofollow">Flysystem</a> и соотвествующий адаптер.</li>
	<li style="text-align:justify;">jQuery File Upload выводит превью при загрузке изображений  не для всех указанных форматов.</li>
	<li style="text-align:justify;">Наличие на Вашем сайте установленной <a href="https://lily-software.com/free-scripts/cotonti-lib">библиотеки Cotonti Lib</a> <strong>версии 2.2.x</strong></li>
	<li style="text-align:justify;">Модуль <strong>не совместим</strong> с модулем PFS и плагином «User images». Их не следует устанавливать, если Вы собираетесь использовать модуль «Files».</li>
	<li style="text-align:justify;">Шаблоны "в коробке" расчитаны на использование темы, реализованной на фреймворке <a href="https://lily-software.com/go.php?getbootstrap.com" target="_blank" rel="noreferrer noopener">Bootstrap</a> v3 (Устанавливается отдельно)</li>
</ul>

<p style="text-align:justify;">   <em>Замечание</em>. В силу значительно отличающейся структуры БД и способа хранения файлов, модуль «Files» не подхватит автоматически присутсвующие на сайте файлы из модуля «PFS» и плагинов «User images» и «Attach2».</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><strong>2.1 Перенос данных из модуля «PFS» и плагинов «User images» и «Attach2».</strong></p>

<p style="text-align:justify;">Если Вы хотите использовать модуль «Files» для уже существующего сайта, Вам следует использовать конвертер для переноса данных между модулями. Вы можете <a href="https://lily-software.com/contact">заказать его здесь</a>. В настоящий момент существует конвертер для переноса данных из этих трех расширений, т.к. они одни из самых часто используемых. Но можно сделать конвертер для любого другого модуля или плагина.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><strong>3. Установка</strong></p>

<ul>
	<li style="text-align:justify;">Загрузить архив и распаковать в папку с модулями вашего сайта.</li>
	<li style="text-align:justify;">В меню «Управление сайтом &gt; Расширения» произвести установку нажав <strong>«установить»</strong>.</li>
	<li style="text-align:justify;">В настройках модуля выберите подходящие Вам установки.</li>
	<li style="text-align:justify;">В шаблонах панели управления <strong>«admin.users.tpl»</strong> и <strong>«admin.users.tpl»</strong> а также в некоторых других создайте теги в соотвествии с рекомендациями на настранице модуля в панели управления. (https://&lt;ваш_домен&gt;/admin/extensions?a=details&amp;mod=files)</li>
	<li style="text-align:justify;">При необходимости на странице редактирования групп пользователей установите ограничения на размер загружаемого файла, общее файловое пространство пользователя и максимальное количество вложений для одного объекта. Для каждой группы пользователей могут действовать свои разрешения.<br />
	Обратите внимание, что размеры указываются <strong>в байтах</strong>, ноль означает «безлимит», а -1 - запрет.</li>
	<li style="text-align:justify;">Создайте <strong>каталог для файлов</strong> на вашем сервере (по умолчанию используется <strong>«datas/files»</strong>) и установите права на запись для PHP (например CHMOD 775 или CHMOD 777).</li>
	<li style="text-align:justify;">Используйте в Вашей теме <strong>Resources::setAlias() </strong>для объявления алиясов для файлов Bootstrap, если Вы планируете его использовать и он установлен в папку, отличную от объавленной в классе <strong>Resources</strong>.</li>
</ul>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><strong>3.1 Загрузка файлов в удаленное хранилище</strong></p>

<p style="text-align:justify;">Для хранения файлов можно использовать как локальную файловую систему на сервере с сайтом, так и в удаленные файловые хранилища, такие как Amazon AWS S3, Azure Blob Storage, Yandex Objet Storage, BunnyCdn, Google Cloud Storage, WebDav, FTP, SFTP и др.</p>

<p style="text-align:justify;">Для использования локальной файловой системы ничего дополнительно устанавливать и настраивать не нужно.</p>

<p style="text-align:justify;">Для использования удаленного файлового хранилища требуется установленная <a href="https://flysystem.thephpleague.com" rel="nofollow">Flysystem</a> и соотвествующий адаптер. Как установить и сконфигуририровать подключение к нужному файловому хранилищу читайте в <a href="https://lily-software.com/free-scripts/cotonti-lib/file-system">соотвествующей статье</a>.</p>

<p style="text-align:justify;">После этого нужно настроить использование файловых систем модулем файлов. Если вы хотите использовать по-умолчанию удаленное файловое хранилище вместо локального или использовать одно удаленное файловое хранилище для хранения всех файлов, то на предыдущем этапе нужно сконфигурировать подключение с именем <code>default</code>. Например, в <strong>datas/config.php</strong> добавте:</p>

<pre class="brush:php;">
$cfg['filesystem'] = [
    // Подключение к Yandex Object Storage будет использоваться по-умолчанию
    'default' =&gt; [
        'adapter' =&gt; '\League\Flysystem\AwsS3V3\AwsS3V3Adapter',
        'config' =&gt; [
            //'version' =&gt; 'latest', // Optional
            'endpoint' =&gt; 'https://storage.yandexcloud.net',
            'region' =&gt; 'ru-central1',
            'bucket' =&gt; 'my-bucket-name',
            'accessKey' =&gt; 'MyAccessKey',
            'secretKey' =&gt; 'MySecretKey',
 
            // install: composer require league/flysystem-path-prefixing:^3.3 to use prefix
            //'pathPrefix' =&gt; 'a/path/prefix',
        ],
    ],
];</pre>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;">Кроме подключения по-умолчанию вы можете настроить файловые хранилища для отдельных обдектв (страниц, постов, галерей и т.п.). Например, в <strong>datas/config.php</strong> добавте:</p>

<pre class="brush:php;">
$cfg['files']['storages'] = [

    // Файлы с source='page' загружать на Google.Drive
    'Google.Drive' =&gt; ['page'],

    // Или можно указать и так
    'Yandex.Cloud' =&gt; [
        ['source' =&gt; 'page'],
    ],

    // А файлы галерей, прикрепленные к страницам (с source='page' и source_field='gallery')
    // загружать на BunnyCDN.
    'BunnyCDN' =&gt; [
        ['source' =&gt; 'page', 'field' =&gt; 'gallery'],
        ['source' =&gt; 'page', 'field' =&gt; ['gallery', 'someField']], // Так тоже можно
    ],
];</pre>

<p style="text-align:justify;">Здесь <strong>ключ массива</strong> - это название подключения, которое указали при <a href="https://lily-software.com/free-scripts/cotonti-lib/file-system">конфигурировании подключений</a>. Для использованя локальной файловой системы укажите <code>'local'</code> (имеет смысл только если подключение по-умолчанию - не локальное франилище).<br />
<strong>source</strong> и <strong>field</strong> будут объяснены ниже.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><strong>4. Использование</strong></p>

<p style="text-align:justify;">Этот раздел рассказывает об основных моментах использования модуля на страницах (pages) c  минимальными изменениями сайта. Аналогично можно настроить его для применения с другими разделам сайта, как например темы форума или комментарии.</p>

<p style="text-align:justify;">Большинство примеров указаны для темы оформления c подключенным <strong><a href="https://lily-software.com/go.php?getbootstrap.com/" target="_blank" rel="noreferrer noopener">Bootstrap</a></strong>, т.к. его использует jQuery File Upload, но Вы всегда можете сделать свои CSS стили не используя bootstrap. Вы можете переопределить шаблоны для решения Ваших задач.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><strong><em>4.1  Личное файловое хранилище</em>. Альбомы пользователей.</strong></p>

<p style="text-align:justify;">Модуль Файлов предоставляет пользователям персональное файловое хранилище ( и файловое хранилище сайта для администраторов ). Файлы можно хранить по папкам и альбомам. Публичные папки и альбомы пользователя доступны для просмотра другим пользователям. Также Вы можете вставить на страницу, точнее прямо в редактор (CKEditor или MarkitUp или другой), ссылку на файл, изображение, его миниатюру или весь альбом в виде галереи.</p>

<p style="text-align:justify;">Чтобы иметь возможность вставлять файлы в редактор из личного файлового хранилища или файлового хранилища сайта,  на форме редактирования страницы нужно добавить теги <code>{PAGEEDIT_FORM_PFS}</code> <code>{PAGEEDIT_FORM_SFS}</code> - в форму редактирования и <code>{PAGEADD_FORM_PFS}</code> <code>{PAGEADD_FORM_SFS}</code> в форму добавления страницы.</p>

<p>Также мои файлы доступны на отдельной странице: <strong>https://&lt;ваш_домен&gt;/files?m=pfs</strong> - можно добавить ее в меню пользователя как "Мои файлы"</p>

<p>Файловый архив сайта: <strong>https://&lt;ваш_домен&gt;/files?m=pfs&amp;uid=0</strong></p>

<p> </p>

<p>Публичные файлы и альбомы пользователя другим пользователям доступны  по ссылкам:<br />
<strong>https://&lt;ваш_домен&gt;/files?a=files&amp;uid=&lt;id_пользователя&gt;</strong> - файлы<br />
<strong>https://&lt;ваш_домен&gt;/files?a=album&amp;uid=&lt;id_пользователя&gt;</strong> - альбомы</p>

<p>Можно добавить их в профиль пользователя.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><em><strong>4.2  Аватары пользователей</strong></em></p>

<p style="text-align:justify;">В стандартных шаблонах модуля пользователей Cotonti - <strong>users.profile.tpl</strong> и <strong>users.edit.tpl</strong> уже есть теги <code>{USERS_PROFILE_AVATAR}</code> и  <code>{USERS_EDIT_AVATAR}</code> соотвественно. Модуль на их место выводит форму загрузки аватара пользователя. А тегом<code>{USERS_DETAILS_AVATAR}</code> (или <code>{PAGE_OWNER_AVATAR}</code> или {ЛЮБОЙ_ПРЕФИКС_AVATAR}, если тег генерируется функцией <code>cot_generate_usertags()</code>) аватар выводится в шаблон. Кроме того, для вывода аватара в шаблон Вы можете использовать например такую конструкцию:</p>

<pre class="brush:php;">
&lt;img src="https://lily-software.com/{PHP.usr.profile.user_avatar|cot_filesUserAvatarUrl($this)}" alt="{PHP.usr.profile.user_name}" /&gt;</pre>

<p style="text-align:justify;">или</p>

<pre class="brush:php;">
&lt;img src="https://lily-software.com/{PHP.urr.user_avatar|cot_filesUserAvatarUrl($this, 200, 140, 'outbound')}"  /&gt;</pre>

<p style="text-align:justify;">Функция</p>

<pre class="brush:php;">
cot_filesUserAvatarUrl($fileId, $width = 0, $height = 0, string $frame = ''): string</pre>

<p style="text-align:justify;">как видите принимает 4 параметра, из которых обязательным является только первый - id файла - аватара. Также Вы можете указать длину, ширину и способ кадрирования, если Вы не хотите использовать настройки модуля по-умолчанию.</p>

<p style="text-align:justify;">Также для вывода аватаров доступна функция</p>

<pre class="brush:php;">
cot_filesUserAvatar($file_id = 0, $urr = 0, $width = 0, $height = 0, $frame = ''): string</pre>

<p style="text-align:justify;">в отличие от <code>cot_filesUserAvatarUrl()</code>, она возвращает полный html код аватара включая тег <code>&lt;IMG&gt;</code> и если у пользователя не установлен аватар, она выводит аватар по-умолчанию.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><em><strong>4.3  Вложения</strong></em></p>

<p style="text-align:justify;">Это самая сложная, самая гибкая и самая интересная возможность использования этого модуля. На ней стоит остановиться подробнее. Модуль Файлов позволяет не только вставлять ссылки и миниатюры в редактор, как это было описано выше, но и позволяет прикреплять к любым объектам, например страницам или постам на форуме, вложения, файлы для скачивания и галереи изображений. Кроме того, модуль умеет загружать файлы к еще пока не существующим объектам, например к странице, которая только создается. И не стоит беспокоиться о том, что останутся бесхозные файлы, если пользователь так и не сохранит страницу, система уборки вычистит файлы, если объекты для которых они предназначались, так и не были созданы.</p>

<p style="text-align:justify;">При удалении страницы или поста на форуме модуль также сам удалит все прикрепленные к ним файлы. А вот для любых других объектов (а также если Вы используете модуль в своих модулях или плагинах) <strong>при удалении объектов, нужно позаботиться об удалении и прикрепленных к нему файлов</strong>. Но эта процедура крайне проста. Можно действовать по аналогии со скриптом <strong>files.page.delete.php</strong>, который удаляет все вложения при удалении страницы.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;">Прежде, чем мы сможем использовать вложения, нам нужно их добавить. Сделать это можно несколькими способами:</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><em><strong>4.3.1 Добавление элемента загрузки файла на форму создания/редактирования объекта</strong></em></p>

<p style="text-align:justify;">В шаблон <strong>page.add.tpl</strong> добавте код</p>

<pre class="brush:php;">
{PHP|cot_filesFileBox('page', 0)}</pre>

<p style="text-align:justify;">А в шаблон <strong>page.edit.tpl</strong></p>

<pre class="brush:php;">
{PAGEEDIT_FORM_ID|cot_filesFileBox('page', $this)}</pre>

<p style="text-align:justify;">Для  добавления вложений к страницам <strong>этого достаточно</strong>. На месте тегов будет выведен загрузчик как на иллюстрации ниже.  Хотите большего? Тогда дочитайте этот параграф до конца.</p>

<p style="text-align:justify;">ID пока несуществующих (новых) объектов всегда указывается равным 0.</p>

<p style="text-align:justify;">Функция</p>

<pre class="brush:php;">
function cot_filesFileBox(
    string $source,
    $item,
    string $name = '',
    string $type = 'all',
    $limit = -1,
    string $tpl = 'files.filebox',
    $standalone = 0,
    $userId = null
): string</pre>

<p style="text-align:justify;">Принимает следующие параметры:</p>

<ul>
	<li style="text-align:justify;"><strong>$source</strong> - тип объекта или имя модуля. Например: page</li>
	<li style="text-align:justify;"><strong>$item</strong> - id объекта. К примеру, это ID страницы, ID поста на форуме или ID комментария. Ключевое слово шаблонизатора CoTemplate  <code>$this</code> позволяет передать в этот параметр значение тега.</li>
	<li style="text-align:justify;"><strong>$name</strong> - имя поля. Можно оставить пустым. Но мы можем для одной страници прикреплять отдельно логотип, отдельно остальные файлы. Или придумать более замысловатую схему прикрепления вложений.</li>
	<li style="text-align:justify;"><strong>$type</strong> - тип загружаемых файлов. 'all' - все сайлы или 'file' или 'image'</li>
	<li style="text-align:justify;"><strong>$limit</strong> - Ограничение на количество загружаемых файлов. Если указан -1 - то будут использованы ограничения, действующие для группы, которой принадлежит пользователь. 0 - не ограничено.</li>
	<li style="text-align:justify;"><strong>$tpl</strong> - шаблон виджета загрузки файлов.</li>
</ul>

<p style="text-align:justify;"><em>Обратите внимание</em>. Шаблон виджета по умолчанию использует библиотеку <strong>Bootstrap</strong> но сам его не загружает. Вы должны подключить bootstrap самостоятельно. Или добавте свои CSS стили. По своему усмотрению.</p>

<p style="text-align:justify;"><img alt="Загрузка файлов в форму" src="https://lily-software.com/public/files/sfs/35/file_395.jpg" style="height:442px;width:680px;" /></p>

<p style="text-align:justify;">На этой иллюстрации на форме редактирования страницы присутствует два загрузчика файлов. Первый для загрузки картинки для вывода в списках страниц (логотипа с параметром $name = 'logo'), а второй для формирования галери с названием поля - 'gallery'. Конечно для вывода в списки страниц можно было взять первую (или последнюю) картину из поля 'gallery' и обойтись одним загрузчиком. Но нужно было иметь возможность поставить в качестве логотипа произвольное изображение.</p>

<p style="text-align:justify;">Вот как это реализовано:</p>

<p>В шаблон page.add.tpl добавлен код:</p>

<pre class="brush:xml;">
{PHP|cot_filesFileBox('page', 0, 'logo')}
{PHP|cot_filesFileBox('page', 0, 'gallery')}</pre>

<p>а в шаблон page.edit.tpl</p>

<pre class="brush:xml;">
{PAGEEDIT_FORM_ID|cot_filesFileBox('page', $this, 'logo')}
{PAGEEDIT_FORM_ID|cot_filesFileBox('page', $this, 'gallery')}</pre>

<p style="text-align:justify;">Картинку из первого загрузчика можно выводить, например в списках страниц или сверху страницы:</p>

<pre class="brush:xml;">
&lt;!-- IF {LIST_ROW_ID|cot_filesCount('page', $this, 'logo', 'images')} &gt; 0 --&gt;
&lt;div class="pull-left marginright10 marginbottom10"&gt;
    &lt;a href="https://lily-software.com/{LIST_ROW_URL}" title="{LIST_ROW_SHORTTITLE}" rel="bookmark" class="thumbnail"&gt;&lt;img
       alt="{LIST_ROW_SHORTTITLE}" src="https://lily-software.com/{LIST_ROW_ID|cot_filesGet('page', $this, 'logo')|cot_filesThumbnailUrl($this, 195, 130, 'outbound')}" /&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;!-- ENDIF --&gt;</pre>

<p style="text-align:justify;">а со второго - использовать как галерею на самой странице:</p>

<pre class="brush:xml;">
&lt;!-- IF {PAGE_ID|cot_filesCount('page', $this, 'gallery', 'images')} &gt; 0 --&gt;
{PAGE_ID|cot_filesGallery('page', $this, 'gallery')}
&lt;!-- ENDIF --&gt;</pre>

<p style="text-align:justify;">Интерфейс загрузчика файлов достаточно стандартен и понятен. Он позволяет выбрать один или несколько файлов за 1 раз, загрузить их, позволяет удалять загруженные, заменять файлы и редактировать описания посредством. Для настройки необходимой последовательности файлов просто перетаците соответствующую строку (Drag &amp; Drop).</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><strong>И еще один важный момент</strong>. Возможность загружать файлы к создаваемому объекту не будет работать при "массовом создании" объетов. Только одна форма создания одного объекта на странице. Это не относится к массовому редактированию объектов.</p>

<p style="text-align:justify;">Если Вы используете <strong>модуль Файлов </strong>с дугими объектами (или в своих модулях / плагинах) и используете загрузку файлов к пока не существующим объектам, Вам нужно сразу после сохранения объекта и до любого редиректа вызвать метод</p>

<pre class="brush:php;">
\cot\modules\files\services\FileService::linkFiles($source, $item)</pre>

<p style="text-align:justify;">Он выполняет привязку уже загруженных файлов к только что созданому объекту. Принимает 2 параметра:</p>

<p style="text-align:justify;"><strong>$source</strong> - тот же $source, что был передан для функции <code>cot_filesFileBox()</code>,<br />
<strong>$item</strong> - id только что созданного объекта</p>

<p style="text-align:justify;">Для модуля страниц вызывать <code>FileService::linkFiles($source, $item)</code> не нужно. Это уже сделано в файле<strong> files.page.add.add.done.php</strong>. С другими объектами следует действовать по аналогии с ним.</p>

<p style="text-align:justify;">При сохранении существующих объектов после редактирования (объектов у которых уже есть свой id, который передавался в функцию <code>cot_filesFileBox()</code>) вызывать <code>FileService::linkFiles($source, $item)</code> также не нужно. Файлы к таким объектам «привязываются» сразу, в момент загрузки.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><em><strong>4.3.2 Добавление загрузчика в iframe</strong></em></p>

<p style="text-align:justify;">В шаблон <strong>page.edit.tpl</strong></p>

<pre class="brush:php;">
{PAGEEDIT_FORM_ID|cot_filesWidget('page', $this)}</pre>

<p style="text-align:justify;">Это добавит iframe с загрузчиком файлов для существующего объекта.</p>

<p style="text-align:justify;">Функция</p>

<pre class="brush:php;">
cot_filesWidget(string $source, $item, string $field = '', string $tpl = 'files.widget', $width = '100%', $height = '300'): string</pre>

<p>Эта функция используется для создания виждета прикрепления файлов. Давайте взглянем на параметры:</p>

<ul>
	<li style="text-align:justify;"><strong>$source</strong> - определяет тип содержимого к которому прикрепляются файлы или код модуля или плагина. Например 'page', 'forums', 'comments', и т.п..</li>
	<li style="text-align:justify;"><strong>$item</strong> - ID объекта, к которому прикрепляются файлы.</li>
	<li style="text-align:justify;"><strong>$field</strong> - имя поля. Можно оставить пустым. Позволяет к одному объекту прирепить несколько групп файлов.</li>
	<li style="text-align:justify;"><strong>$tpl</strong> - Код шаблона, содержащего html код виджета. Например, если Вы укажете 'files.my_widget', система попытается срендерить файл «themes/your_theme/modules/files/files.my_widget.tpl». Шаблоны по умолчанию можно найти в папке «modules/files/tpl», Вы можете использовать их как образец. «files.widget» вставляет диалог в iframe, а «attach2.link» (см. далее) добавляет ссылку на всплывающий диалог с загрузчиком.</li>
	<li style="text-align:justify;"><strong>$width</strong> - Ширина iframe.</li>
	<li style="text-align:justify;"><strong>$height</strong> - Высота iframe.</li>
</ul>

<p><img alt="Загрузка файлов в iframe" src="https://lily-software.com/public/files/sfs/35/file_394.jpg" style="height:390px;width:680px;" /></p>

<p style="text-align:justify;"><em>Замечание</em>. Т.к. подключаемый виджет содержится в iframe, то хоть он по умолчанию и использует Bootstrap, но на дизайне Вашего сайта это никак не скажется, если Вы Bootstrap не используете. Виджет сам подключает Bootstrap, так что никаких дополнительных действий предпринимать не требуется</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><em><strong>4.3.3 Добавление ссылки и диалога загрузки файлов.</strong></em></p>

<p style="text-align:justify;">Модуль позволяет добавлять файлы не только во время редактирования объекта, но и прямо во время просмотра.</p>

<p style="text-align:justify;">Добавим ссылку "Прикрепить файлы" в меню администрирования страницы, в шаблон <strong>page.tpl</strong></p>

<p><img alt="Ссылка на загрузчик файлов" src="https://lily-software.com/public/files/sfs/35/file_396.jpg" /></p>

<pre class="brush:xml;">
&lt;!-- IF {PHP|cot_auth('files', 'a', 'W')} --&gt;
&lt;li&gt;{PAGE_ID|cot_filesWidget('page', $this, '', 'files.link')}&lt;/li&gt;
&lt;!-- ENDIF --&gt;</pre>

<p style="text-align:justify;">Эта ссылка будет видна только тем пользователям, которые имеют права на прикрепление файлов (которое определяется правом «записи» (Write access) в настойках прав этого модуля).</p>

<p style="text-align:justify;">Если нажать на ссылку "Прикрепить файлы", откроется окно следующего окно:</p>

<p style="text-align:justify;"><img alt="Виджет загрузки файлов" src="https://lily-software.com/public/files/sfs/35/file_397.jpg" style="height:453px;width:680px;" /></p>

<p style="text-align:justify;">После того как вы загрузили все необходиомое и написали описания нажмите «закрыть», после чего содержимое страницы обновится и вы увидите результат.</p>

<p style="text-align:justify;">Также среди шаблонов по умолчанию в папке модуля «modules/files/tpl» есть шаблон виджета «files.link.bootstrap.tpl», который открывает загрузчик в модальном окне Bootstrap. По аналогии очень легко сделать так, чтобы загрузчик открывался в диалоговом окне jQuery.UI.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><em><strong>4.3.4. Просмотр прикрепленных файлов</strong></em></p>

<p style="text-align:justify;">Самый простой способ вывода прикрепленных к странице файлов это использовать виджет <code>cot_filesDisplay()</code> в шаблоне «page.tpl»:</p>

<pre class="brush:xml;">
&lt;!-- IF {PAGE_ID|cot_filesCount('page', $this)} &gt; 0 --&gt;
&lt;div class="block"&gt;
    &lt;h3&gt;{PHP.L.files_attachments}&lt;/h3&gt;
    {PAGE_ID|<code>cot_filesDisplay</code>('page', $this)}
&lt;/div&gt;
&lt;!-- ENDIF --&gt;</pre>

<p style="text-align:justify;">Который отобразит примерно следующее:</p>

<p style="text-align:justify;"><img alt="Модуль файлов - показ файлов" src="https://lily-software.com/public/files/sfs/35/file_398.jpg" style="height:307px;width:680px;" /></p>

<p style="text-align:justify;"> </p>

<p><em><strong>4.3.5.  Добавление простой галереи</strong></em></p>

<p>Для добавления простой галереи на страницу, вы можете включить в шаблон «page.tpl» следующий код:</p>

<pre class="brush:xml;">
&lt;!-- IF {PAGE_ID|cot_filesCount('page', $this, '', 'images')} &gt; 0 --&gt;
&lt;div class="block"&gt;
    {PAGE_ID|cot_filesGallery('page', $this)}
&lt;/div&gt;
&lt;!-- ENDIF --&gt;</pre>

<p>Он добавит галерею на страницу:</p>

<p><img alt="Модуль файлов - галерея" src="https://lily-software.com/public/files/sfs/35/file_399.jpg" style="height:486px;width:680px;" /></p>

<p>Для красивого открытия изображений во всплывающем окне, Вы можете использовать любой подходящий JavaScript. Например FancyBox.</p>

<p><br />
<em><strong>4.3.6. Добавление списка файлов для скачивания</strong></em></p>

<p style="text-align:justify;">Еще одной растространненной задачей является добавление на страницу списка файлов для скачивания. Используйте функцию <strong>cot_filesDownloads()</strong> в своем шаблоне(«page.tpl»):</p>

<pre class="brush:xml;">
&lt;!-- IF {PAGE_ID|cot_filesCount('page',$this,'','files')} &gt; 0 --&gt;
&lt;div class="block"&gt;
    &lt;h3&gt;{PHP.L.files_downloads}&lt;/h3&gt;
    {PAGE_ID|cot_filesDownloads('page',$this)}
&lt;/div&gt;
&lt;!-- ENDIF --&gt;</pre>

<p>Стандартный блок выглядит так:</p>

<p><img alt="Список файлов для загрузки" src="https://lily-software.com/public/files/sfs/35/file_400.jpg" /></p>

<p> </p>

<p><em><strong>4.4 Экстраполя</strong></em></p>

<p style="text-align:justify;">Как и большинство модулей и плагинов Cotonti, модуль файлов позволяет добавлять и использовать экстраполя для файлов и папкок (альбомов). Экстраполя типа "Файл" не поддерживаются. Для редактирования их значений через Ajax элементы формы экстраполей должны иметь класс «file-edit». Просто добавте атрибут <strong>«class»</strong> со значением <strong>«file-edit»</strong> в панеле управления - на странице редактирования экстраполей в поле «HTML-код поля» .</p>

<p> </p>

<p><em><strong>4.5 Расширенные возможности</strong></em></p>

<p>Для решения большинства задач по выводу вложений этого достаточно. Хотите большего? Тогда этот раздел для Вас.</p>

<p><em><strong>4.5.1 Вызов функций (виджетов) из TPL шаблонов и их параметры.</strong></em></p>

<p style="text-align:justify;">Прикрепление файлов не ограничивается только модулем страниц и стандартными шаблонами. Вы легко можете настроить прикрепление файлов и к другим объектам системы и настроить соответствующие им шаблоны. Ниже будет описанино какие функции плагин предоставляет для использования в шаблонах и какие параметры им нужно передавать.</p>

<p> </p>

<p><strong>cot_filesDisplay</strong></p>

<pre class="brush:php;">
/**
 * Renders attached items on page
 * @param string $source Target module/plugin code
 * @param int|int[] $item Target item id
 * @param string $field
 * @param string $tpl Template code
 * @param string $type Attachment type filter: 'files', 'images'. By default includes all attachments.
 * @param int $limit
 * @param string $order
 * @return string Rendered output
 */
function cot_filesDisplay(
    string $source,
    $item,
    string $field = '',
    string $tpl = 'files.display',
    string $type = 'all',
    $limit = 0,
    string $order = ''
): string</pre>

<p style="text-align:justify;">Этот виджет используется для отображения прикрепленых к объекту файлов. Он может выводить как все файлы, так отдельно изображения, отдельно файлы, не являющиеся изображениями. Упомянутые выше функции <code>cot_filesGallery</code> и <code>cot_filesDownloads</code> по сути являются «обертками» для этой функции. Принимаемые параметры схожи с функциями, рассмотренными выше:</p>

<ul>
	<li style="text-align:justify;"><strong>$source</strong> - определяет тип содержимого к которому прикреплены изображения. Аналогично соотвествующему параметру <code>cot_filesFilebox()</code> и <code>cot_filesWidget()</code>. Например 'page',  'forums',  'comments', и т.п...</li>
	<li style="text-align:justify;"><strong>$item</strong> - ID объекта, файлы которого мы выводим.</li>
	<li style="text-align:justify;"><strong>$field</strong> - имя поля.</li>
	<li style="text-align:justify;"><strong>$tpl</strong> - Код шаблона, содержащего html код виджета.</li>
	<li style="text-align:justify;"><strong>$type</strong> - тип. Этот параметр используется при необходимости вывода только изображений или только файлов, не не являющихся изображениями.</li>
</ul>

<p style="text-align:justify;">Стандартные шаблоны Вы можете найти в папке «modules/files/tpl». Используйте их как образец.<br />
<strong>«files.display.tpl»</strong> и <strong>«files.downloads.tpl»</strong> представляют собой разные стили отображения файлов.<br />
<strong>«files.gallery.tpl»</strong> - шаблон галереи.<br />
<strong>«files.bootstrap-carousel_gallery.tpl»</strong> - Слайдшоу - <a href="https://lily-software.com/go.php?getbootstrap.com/javascript/#carousel">карусель на базе bootstrap</a>.</p>

<p style="text-align:justify;">Обратите внимание, на то, что параметр <strong>$tpl</strong> функции принимает имя файла без расширения. (.tpl на конце указывать не нужно)</p>

<p style="text-align:justify;">Пример ниже отобразит все файлы, прикрепленые к посту на форуме. Код следует разместить в шаблоне «<strong>forums.posts.tpl</strong>» в блоке <strong>FORUMS_POSTS_ROW</strong>:</p>

<pre class="brush:xml;">
{FORUMS_POSTS_ROW_ID|cot_filesDisplay('forums', $this)}</pre>

<p> </p>

<p><strong>cot_filesCount</strong></p>

<pre class="brush:xml;">
/**
 * Returns number of attachments for a specific item.
 * @param string $source Target module/plugin code
 * @param int $sourceId Target item id
 * @param string $sourceField Target item field
 * @param string $type Attachment type filter: 'files', 'images'. By default includes all attachments.
 * @return int Number of attachments
 */
function cot_filesCount($source, $sourceId, $sourceField = '', $type = 'all')</pre>

<p style="text-align:justify;">Возвращает количество файлов, присоединенных к объекту. Параметры аналогичны cot_filesDisplay(), за исключением того, что параметр <strong>$field</strong> может принимать значение '_all_'. В этом случае фукнция вернет общее количество файлов, прикрепленных к объекту (ко всем «полям»)</p>

<p>Например, выводим список файлов, прикрепленных к посту на форуме только если хотя бы один файл был прикреплен:</p>

<pre class="brush:xml;">
&lt;!-- IF {FORUMS_POSTS_ROW_ID|cot_filesCount('forums', $this)} &gt; 0 --&gt;
&lt;div class="block"&gt;
    {FORUMS_POSTS_ROW_ID|cot_filesGallery('forums', $this)}
&lt;/div&gt;
&lt;!-- ENDIF --&gt;</pre>

<p> </p>

<p><strong>cot_filesGallery</strong></p>

<pre class="brush:php;">
/**
 * Renders images only as a gallery.
 * @param string $source Target module/plugin code
 * @param int|int[] $item Target item id
 * @param string $field
 * @param string $tpl Template code
 * @param int $limit
 * @param string $order
 * @return string Rendered output
 */
function cot_filesGallery(string $source, $item, string $field = '', string $tpl = 'files.gallery', $limit = 0, string $order = ''): string</pre>

<p style="text-align:justify;">Функция обертка для <strong>cot_filesDisplay()</strong> с параметром <strong>$type</strong> установленном в 'images' и c кодом шаблона по умолчанию '<strong>files.gallery</strong>'.</p>

<p> </p>

<p><strong>cot_filesDownloads</strong></p>

<pre class="brush:php;">
/**
 * Renders files only as downloads block.
 * @param string $source Target module/plugin code
 * @param int|int[] $item Target item id
 * @param string $field
 * @param string $tpl Template code
 * @param int $limit
 * @param string $order
 * @return string Rendered output
 */
function cot_filesDownloads(string $source, $item, string $field = '', string $tpl = 'files.downloads', $limit = 0, string $order = ''): string</pre>

<p style="text-align:justify;">Функция обертка для <strong>cot_filesDisplay()</strong> с параметром <strong>$type</strong> установленном в 'files' и c кодом шаблона по умолчанию '<strong>files.downloads</strong>'.</p>

<p>Обычно используется для организации блоков файлов для скачивания.</p>

<p> </p>

<p><strong>cot_filesThumbnailUrl</strong></p>

<pre class="brush:php;">
/**
 * Returns file's thumbnail url. Generates the thumbnail first if it does not exist.
 * Can be used in template files as callback
 * @param File|int $id File ID or instance of File.
 * @param int|string $width Thumbnail width absolute in pixels (int) or percent (string: '10%')
 * @param int|string $height Thumbnail height absolute in pixels (int) or percent (string: '10%')
 * @param string $frame Framing mode: one of \image\Image::THUMBNAIL_XXX constants (for backwards compatibility 'auto' and 'crop' also supported)
 * @param bool $watermark - set watermark if Cot::$cfg['files']['thumb_watermark'] not empty?
 * @param bool $lastMod Include last file modification time as GET parameter
 * @return string Thumbnail path on success or null on error
 *
 * @see ThumbnailService::thumbnail()
 */
function cot_filesThumbnailUrl($id, $width = 0, $height = 0, string $frame = '', $watermark = true, $lastMod = null): string</pre>

<p>Генерирует миниатюру для изображения и возвращает ее URL.</p>

<p>Принимаемые параметры:</p>

<ul>
	<li style="text-align:justify;"><strong>$id</strong> - id файла или экземпляр класса<code>\cot\modules\files\models\File</code></li>
	<li style="text-align:justify;"><strong>$width</strong> - ширина миниатюры</li>
	<li style="text-align:justify;"><strong>$height</strong> - высота миниатюры</li>
	<li style="text-align:justify;"><strong>$frame</strong> - режим кадрирования. Может принимать следующие значения<br />
	- '<strong>width</strong>' заполняет миниатюру по ширине и сохраняет соотношение сторон.<br />
	- '<strong>height</strong>' заполняет миниатюру по высоте и сохраняет соотношение сторон.<br />
	- '<strong>inset</strong>' (по-умолчанию) сохраняет соотношение сторон уменьшая изображение таком образом, чтобы его размеры не превысили заданых.<br />
	- '<strong>outbound</strong>' уменьшает изображение сохраняя соотношение сторон и обрезает изображение так, чтобы оно полностью заполнило указаные размеры. <em>На примере галереи выше использован именно этот режим</em>.</li>
</ul>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><strong>cot_filesGet</strong></p>

<pre class="brush:php;">
/**
 * Fetches a single attachment object for a given item.
 * @param string $source Target module/plugin code.
 * @param int $sourceId Target item id.
 * @param string $sourceField Target item field
 * @param string $column Empty string to return full row, one of the following to return a single value: 'id',
 *                              'user_id', 'path', 'file_name', 'original_name', 'ext', 'is_img', 'size', 'title', 'downloads_count'
 * @param string $number Attachment number within item, or one of these values: 'first', 'rand' or 'last'. Defines which image is selected.
 * @return File|int|string|null Scalar column value, File object or NULL if no attachments found.
 */
function cot_filesGet($source, $sourceId, $sourceField = '', $column = '', $number = 'first')</pre>

<p style="text-align:justify;">Служит для получения информации об одном файле, прикрепленном к объекту. Очень часто эта функция используется для вывода обложки страницы на списках страниц.</p>

<p style="text-align:justify;">Параметры:</p>

<ul>
	<li style="text-align:justify;"><strong>$source</strong> - определяет тип содержимого к которому прикреплены изображения. Аналогично соотвествующему параметру <strong>cot_filesDisplay().</strong></li>
	<li style="text-align:justify;"><strong>$item</strong> - ID объекта.</li>
	<li style="text-align:justify;"><strong>$field</strong> - аналогично соотвествующему параметру <strong>cot_filesDisplay()</strong>.</li>
	<li style="text-align:justify;"><strong>$column</strong> - если не передано, то возвращает экземпляр класса <code>\cot\modules\files\models\File</code>, иначе вернет значение указанного поля этого объекта.</li>
	<li style="text-align:justify;"><strong>$number</strong> - Порядковый номер вложения или '<strong>first</strong>' для вывода первого файла, '<strong>rand</strong>' - для случайного или '<strong>last</strong>' для последнего.</li>
</ul>

<p style="text-align:justify;">Пример вывода обложки страницы в шаблоне page.list.tpl:</p>

<pre class="brush:xml;">
&lt;!-- IF {LIST_ROW_ID|cot_filesCount('page', $this, '', 'images')} &gt; 0 --&gt;
&lt;div class="pull-left"&gt;
    &lt;a href="https://lily-software.com/{LIST_ROW_URL}" title="{LIST_ROW_SHORTTITLE}" class="thumbnail marginright10 no-ico"&gt;&lt;img alt="{LIST_ROW_SHORTTITLE}" src="https://lily-software.com/{LIST_ROW_ID|cot_filesGet('page', $this)|cot_filesThumbnailUrl($this, 195, 130, 'outbound')}" /&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;!-- ENDIF --&gt;</pre>

<p style="text-align:justify;">Как видите, результат работы этой функции можно передать в <code>cot_filesThumbnailUrl()</code>.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><em><strong>4.5.2 BB-коды для вставки в контент</strong></em></p>

<p style="text-align:justify;">Изображения и их миниатюры и даже пупбличные папки из файлового хранилища могут быть вставлены прямо в текст страницы, комментария, поста на форуме и т.п.</p>

<p>Для этого необходимо знать id файла (или папки). Синтаксис параметров bb-кода схож со строкуой URL запроса. Доступные bb-коды:</p>

<p>[files_thumb] - вставляет только миниатюру в тег &lt;img/&gt;.<br />
[files_image] - вставляет a кликабельную миниатюру с ссылкой на большое изображение.<br />
[pfs_gallery] - вставляет галерею, генереруемую из публичной папки файлового хранилища.</p>

<p>Пример использования:</p>

<pre class="brush:xml;">
[ files_thumb?id=15]
[ files_image?id=11&amp;width=320&amp;height=240&amp;alt=Picture description&amp;class=foo]
[ pfs_gallery?f=5&amp;tpl=files.bootstrap-carousel_gallery]</pre>

<p style="text-align:justify;">Эти bb-коды работают независимо от парсера, включая HTML и Markdown. Если Вы хотите их отключить, просто приостановите выполнение части «parser» этого модуля в панели управления «Управление сайтом / Расширения / Files».</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><strong>История версий</strong></p>

<p style="text-align:justify;"><strong>v. 2.0.1</strong></p>

<ul>
	<li style="text-align:justify;">Cовместимость с Cotonti 0.9.25</li>
</ul>

<p style="text-align:justify;"><strong>v. 2.0.0</strong></p>

<ul>
	<li style="text-align:justify;">Использование <a href="https://lily-software.com/free-scripts/cotonti-lib/image-bundle">Image bundle</a> из библиотеки <a href="https://lily-software.com/free-scripts/cotonti-lib">Cotonti Lib</a> для обработки изображений.</li>
	<li style="text-align:justify;">Использование <a href="https://lily-software.com/free-scripts/cotonti-lib/file-system">File System</a> из библиотеки <a href="https://lily-software.com/free-scripts/cotonti-lib">Cotonti Lib</a> и <a href="https://flysystem.thephpleague.com" target="_blank" rel="nofollow noreferrer noopener">Flysystem</a> для хранения файлов и операций с ними.</li>
	<li style="text-align:justify;">Обфускация имен файлов.</li>
	<li style="text-align:justify;">Уменьшение загружаемых изображений в браузере, если возможно.</li>
	<li style="text-align:justify;">Рефакторинг кода. Функции переименованы по шаблону <code>cot_filesFunctionName()</code>.</li>
</ul>

<p><strong>v. 1.0.8</strong></p>

<ul>
	<li>Добавлена поддержка удаления пользователей, страниц и постов на форуме в корзину. При удалении этих элементов файлы не удаляются и после восстановления элемента из корзины, файлы остаются привязными к этим элементам. При удалении элементов из корзины, связанные файлы тоже удаляются.</li>
</ul>

<p><strong>v 1.0.7</strong></p>

<ul>
	<li>Добавлена поддержка графических форматов: avif, bmp, gd2, gd, tga, tpic, wbmp, webp, xbm</li>
	<li>jQuery File Upload обновлен до версии 10.32.0</li>
	<li>Совместимость с PHP 8.1</li>
	<li>Исправлены некоторые ошибки</li>
</ul>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;">GitHub: <a href="https://lily-software.com/go.php?https://github.com/Alex300/files">https://github.com/Alex300/files</a></p>
]]></description>
			<pubDate>Tue, 16 Aug 2022 08:17:00 +0300</pubDate>
			<link><![CDATA[https://lily-software.com/free-scripts/cotonti-files]]></link>
		</item>
		<item>
			<title>Cotonti - Рассылки</title>
			<description><![CDATA[<p>Модуль рассылок для CMF Cotonti.</p>

<p><em>Тип</em>: <strong>Модуль</strong><br /><em>Версия<strong>: 1.0</strong></em><br /><em>Совместимость</em>: <strong>Siena</strong></p>

<p style="text-align:justify;"><em>GitHub:</em> <a href="https://lily-software.com/go.php?https://github.com/Alex300/subscribe">https://github.com/Alex300/subscribe</a></p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;">Это расширение позволяет организовать рассылки на Вашем сайте под управлением Cotonti. Рассылки можно создать вручную, либо организовать автоматические подписки на страницах сайта. Это могут быть последние новости, новинки Вашего интернет магазина и т.п.</p>

<p style="text-align:justify;"> </p>

<p><strong>Системные требования и ограничения:</strong></p>

<ul><li>Наличие на Вашем сайте установленной <a href="https://lily-software.com/sozdanie-internet-sajtov/free-scripts/cotonti-lib">библиотеки cotonti-lib</a> <strong>версии <a href="https://github.com/Alex300/cotonti-lib/releases/tag/v1.5" target="_blank">1.5</a></strong> (именно 1.5 а не 2)</li>
	<li>В качестве шаблонизатора используется <a href="https://lily-software.com/sozdanie-internet-sajtov/free-scripts/cotonti-lib/view">View</a></li>
	<li>Административная часть модуля сделана под панель управления <a href="https://lily-software.com/sozdanie-internet-sajtov/free-scripts/cpanel">Cpanel</a>. Если Вы используете стандартную панель администратора Cotonti, Вам нужно переопределить соотвествующие шаблоны.</li>
</ul><p> </p>

<p><strong>Установка:</strong><br />
- Скопировать модуль на сервер или склонировать репозиторий в папку <strong>modules/subscribe</strong><br />
- Установить модуль из панели администратора<br />
- В папке <strong>inc</strong> установить права на запись на файл '<strong>queue.txt</strong>'<br />
- Создать рассылки в панели администратора<br />
- Создать задание для <strong>cron</strong> для отправки писем (см. ниже)</p>

<p> </p>

<p style="text-align:justify;"><strong>Возможности:</strong><br />
   - Создание различных рассылок на Вашем сайте<br />
   - Ручное и автоматическое создание контента рассылки<br />
   - Ручное добавление подписчиков администратором<br />
   - Форма подписки на любую рассылку на Вашем сайте для пользователей<br />
   - Использование очереди отправки, чтобы распределить нагрузку на сервер при выполнении рассылки<br />
   - Подтверждение электронного адреса для незарегистрированных пользователей</p>

<p> </p>

<p style="text-align:justify;"><strong>Создание рассылки:</strong><br />
Рассылки создаются в панели управления. Вы можете настроить получение контента по некоторому URL-адресу (если какой то из установленных у Вас модулей предоставляет соответствующий функционал) или добавить контент вручную.</p>

<p style="text-align:justify;">Также Вы можете настроить шаблон для каждой рассылки. Это дает большие возможности по формированию контента рассылки. В шаблонах Вы можете использовать любые виджеты, например <strong>pagelist. </strong></p>

<p style="text-align:justify;">Шаблоны именуются по такому принципу: <strong>subscribe.mail.&lt;alias&gt;.php</strong>, где alias - это алиас, назначенный данной рассылке.</p>

<p> </p>

<p>Пример фрагмента шаблона ежедневной рассылки новостей:</p>

<pre class="brush:php;">
$begin = strtotime(date('Y-m-d 00:00:01', cot::$sys['now'])); // Начало суток
$condition = "page_state=0 AND page_begin &gt;= {$begin} AND (page_expire = 0 OR page_expire &gt; ".
    cot::$sys['now'].")"

?&gt;
&lt;div style="width: 800px; margin: 0 auto 20px auto"&gt;
    &lt;h1 style="font-size: 36px"&gt;
        &lt;a href="https://lily-software.com/&lt;?=cot::$cfg['mainurl']?&gt;"&gt;&lt;img src="https://lily-software.com/&lt;?=cot::$cfg['mainurl']?&gt;/themes/your-theme/img/logo-small.png"&gt;&lt;/a&gt;
        Новости от &lt;?=cot::$cfg['maintitle']?&gt;
    &lt;/h1&gt;
    &lt;div style="margin-top: 20px"&gt;
        &lt;?=pagelist('pagelist.subscribe.daily_news', 0, 'page_begin DESC',  $tools_condition)?&gt;
    &lt;/div&gt;
    &lt;?php 

    // Выводим тект рассылки, добавленный в админке
    echo $this-&gt;text;?&gt;
&lt;/div&gt;</pre>

<p style="text-align:justify;">В этом примере используется виджет плагина <strong>pagelist</strong> для формирования списка новостей за день. А ниже выводится текст, добавленный в админке.</p>

<p> </p>

<p style="text-align:justify;"><strong>Создание заданий Cron:</strong><br />
Рассылки могут рассылаться пользователям как за "один раз" так и при помощи очереди. Последний вариант предпочтительнее т.к. при большом количестве получателей позволяет распределить нагрузку на сервер в течение дня.</p>

<p style="text-align:justify;">Указывая в настройках модуля количество писем, отправляемых из очереди за один раз ставьте такое значение, чтобы в конце суток у Вас очередь оказалась пустой. Иначе письма в очереди станут накапливаться.</p>

<p style="text-align:justify;">Независимо от выбранного способа отправки Вам необходимо в cron добавить следующее задание:</p>

<pre class="brush:bash;">
# Выполняется в 0:10, 2:10, 4:10 и т. д.
10 */2 * * *  php /path/to/your/site/cli.php --a subscribe.main.run &gt; /path/to/your/site/log/subscribe.log</pre>

<p style="text-align:justify;">Пути к файлам следует изменить на нужные.</p>

<p style="text-align:justify;">Сделать это можно из консоли, выполнив следующую команду:</p>

<pre class="brush:bash;">
crontab -e</pre>

<p style="text-align:justify;">Если на Вашем хостинге нет доступа к командной строке, то используйте те инструменты, которые предоставляет Ваш хостер.</p>

<p> </p>

<p>Для запуска обработчика очереди, добавьте в <strong>cron</strong> задание:</p>

<pre class="brush:bash;">
# Выполняется каждые 30 минут
*/30 * * * *  php /path/to/your/site/cli.php --a subscribe.main.runQueue &gt; /path/to/your/site/log/subscribeQueue.log</pre>

<p> </p>

<p><strong>Разное:</strong></p>

<p><strong>http://&lt;ваш_домен&gt;/subscribe</strong> - активные периодические рассылки. Авторизованные пользователи могут на них подписаться</p>

<p><strong>cot_url('subscribe', array('m'=&gt;'user'))</strong> - мои подписки пользователя<br /><strong>cot_url('subscribe', array('m'=&gt;'user', 'uid'=1))</strong> - подписки пользователя с id=1</p>

<p> </p>

<p style="text-align:justify;">GitHub: <a href="https://lily-software.com/go.php?https://github.com/Alex300/subscribe">https://github.com/Alex300/subscribe</a></p>
]]></description>
			<pubDate>Mon, 20 Jul 2015 10:34:00 +0300</pubDate>
			<link><![CDATA[https://lily-software.com/free-scripts/subscribe]]></link>
		</item>
		<item>
			<title>Cotonti - Banners</title>
			<description><![CDATA[<p style="text-align:justify;">Модуль предназначен для показа рекламных баннеров на сайте (т.н. "баннерокрутилка").</p>

<p><em>тип:</em> <strong>модуль</strong><br /><em>Версия плагина:</em> <strong>2.0.1</strong><br /><em>Совместимость:</em> <strong>Siena</strong></p>

<p>GitHub: <a href="https://lily-software.com/go.php?https://github.com/Alex300/brs">https://github.com/Alex300/brs</a></p>

<p> </p>

<p><strong>Системные требования и ограничения:</strong></p>

<ul><li>Наличие на Вашем сайте установленной <a href="https://lily-software.com/sozdanie-internet-sajtov/free-scripts/cotonti-lib">библиотеки Cotonti Lib</a> <strong>версии 2.0.x</strong></li>
	<li>Административная часть плагина расчитана на альтернативную <a href="https://lily-software.com/sozdanie-internet-sajtov/free-scripts/cpanel">тему панели управления cpanel</a>.</li>
	<li>В качестве шаблонизатора используется <a href="https://lily-software.com/sozdanie-internet-sajtov/free-scripts/cotonti-lib/view">View</a></li>
</ul><p> </p>

<p><strong>Описание:</strong></p>

<p style="text-align:justify;">Баннеры разделяются по категориям и в каждую рекламную позицию на сайте можно вывести баннеры из одной или нескольких категорий. Вывод баннеров, ротация, осуществляется по порядку или случайным образом.<br />
Для каждого баннера ведется статистика показов и кликов. Возможно ведение почасовой статистики, но это вызовет дополнительную нагрузку на сервер.</p>

<p style="text-align:justify;">Поддерживаются изображения и флеш. Так же есть возможность установки произвольного кода баннера, например со сторонней рекламной системы.</p>

<p style="text-align:justify;">Для удобства ведения рекламных кампаний, баннеры можно разбивать по клиентам. Это позволяет получать статистику показов и кликов по баннеру для  каждого клиента.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><strong>Возможности:</strong><br />
- отображение и автоматическая ротация баннеров на вашем сайте<br />
- упорядоченная или случайная ротация баннеров<br />
- поддерживаемые форматы: jpeg, png, gif, bmp и swf<br />
- возможность установки произвольного кода баннера<br />
- неограниченное количество категорий (баннерных позиций)<br />
- неограниченное количество баннеров в категрии и в целом<br />
- статистика показов и кликов<br />
- почасовая статистика показов и кликов<br />
- отчет о показах и кликах с фильтрами по периоду, категориям и клиентам<br />
- привязка баннеров к клиентам</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><strong>Установка:</strong><br />
- Скопировать модуль на сервер в папку <strong>modules/brs</strong><br />
- В папке <strong>datas</strong> cоздать папку <strong>brs</strong> и установить на нее права на запись<br />
- Установить планин в панели управления<br />
- Создать нужные категории и баннеры<br />
- В нужное место файла шаблона добавить вызов виджета: <strong>&lt;?=brs_controller_Widget::banner('category', 2)?&gt;</strong> (параметры см. ниже)</p>

<p style="text-align:justify;"><br /><strong>Параметры виджета:</strong><br />
Виджет вызывается со следующими параметрами</p>

<pre class="brush:php;">
brs_controller_Widget::banner($cat, $cnt = 1, $tpl = 'brs.banner', $order = 'order', $client = false, $subcats = false)</pre>

<p style="text-align:justify;">где:</p>

<p style="text-align:justify;"><strong>$cat</strong> - категория баннеров или список категорий, разделенный символом ';'</p>

<p style="text-align:justify;"><em>Остальные параметры не обязательные</em></p>

<p style="text-align:justify;"><strong>$cnt</strong> - количество выводимых баннеров. При выводе нескольких баннеров подряд, следует использовать этот параметр вместо нескольких вывозовов этой функции, т.к. каждый отдельный вывозов совершает обращения в базе данных<br /><strong>$tpl</strong> = tpl - файл<br /><strong>$order</strong> - порядок показа. Допустимые значения <strong>'order'</strong> - по порядку, <strong>'rand'</strong> - случайно<br /><strong>$client</strong> - данный параметр пока не используется<br /><strong>$subcats</strong> - выводить баннеры из вложенных категорий</p>

<p style="text-align:justify;">Однако, в отличие от шаблонизатора <strong>View</strong>, встроенный шаблонизатор <strong>CoTemplate</strong> не умеет работать с объектами (как ни странно). Для использования в <strong>tpl-шаблонах</strong> пользуйтесь call-back функцией:</p>

<pre class="brush:php;">
banner_widget($cat, $cnt = 1, $tpl = 'banners', $order = 'order', $client = false, $subcats = false)</pre>

<p>Она является оберткой для <strong>brs_controller_Widget::banner.</strong></p>

<p> </p>

<p><strong><u>История изменений:</u></strong></p>

<p style="text-align:justify;"><strong>Версия v2.0.1</strong></p>

<ul><li>Совместимость с Cotonti Lib v2.0.</li>
</ul><p style="text-align:justify;"><strong>Версия v2.0.0</strong></p>

<ul><li>Расширение теперь <strong>полноценный модуль</strong>. Раньше оно было плагином.</li>
	<li>Переход на <a href="https://lily-software.com/sozdanie-internet-sajtov/free-scripts/cotonti-lib">Cotonti Lib</a>. Это дало унификацию API и повышение производительности.</li>
	<li style="text-align:justify;">Изменен код расширения и название папки на сервере. ADBlocker'ы не любили название banners :)</li>
</ul><p><strong>     Обратите внимание!</strong> Автоматическое обновление плагина (версии 1) до модуля (версии 2) невозможно.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;">GitHub: <a href="https://lily-software.com/go.php?https://github.com/Alex300/brs">https://github.com/Alex300/brs</a></p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;">Версия 1: <a href="https://lily-software.com/go.php?https://github.com/Alex300/banners">https://github.com/Alex300/banners</a></p>
]]></description>
			<pubDate>Wed, 08 Jul 2015 23:09:00 +0300</pubDate>
			<link><![CDATA[https://lily-software.com/free-scripts/cotonti-banners]]></link>
		</item>
		<item>
			<title>Cotonti - Доска объявлений</title>
			<description><![CDATA[<p>Модуль доски объявлений для CMF Cotonti.</p>

<p><em>Тип</em>: <strong>Модуль</strong><br /><em>Версия<strong>: 3.0.3</strong></em><br /><em>Совместимость</em>: <strong>Siena</strong></p>

<p style="text-align:justify;"><em>GitHub:</em> <a href="https://lily-software.com/go.php?https://github.com/Alex300/advboard">https://github.com/Alex300/advboard</a></p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;">Это расширение позволяет организовать доску объявлений на Вашем сайте под управлением Cotonti. Оно является полноценным модулем со своей таблицей объявлений в БД с поддержкой экстраполей и своей структурой категорий.</p>

<p style="text-align:justify;"> </p>

<p><strong>Системные требования и ограничения:</strong></p>

<ul><li>Наличие на Вашем сайте установленной <a href="https://lily-software.com/free-scripts/cotonti-lib">библиотеки Cotonti Lib</a> версии <strong>2.0.1 - 2.0.3</strong></li>
	<li>В качестве шаблонизатора используется <a href="https://lily-software.com/free-scripts/cotonti-lib/view">View</a></li>
</ul><p> </p>

<p><strong>Установка:</strong><br />
- Скопировать модуль на сервер или склонировать репозиторий в папку <strong>modules/advboard</strong><br />
- Установить модуль из панели администратора<br />
- В папке <strong>inc</strong> установить права на запись на файл '<strong>send.txt</strong>'</p>

<p> </p>

<p style="text-align:justify;"><strong>Возможности:</strong><br />
   - подача объявлений на сайт<br />
   - опциональное автоутверждение объявлений или премодерация для каждой категории<br />
   - уведомление пользователя о новых комментариях к своему объявлению на e-email<br />
   - уведомление пользователя об истечении срока публикации объявления на свой e-email<br />
   - редактирование пользователем своих объявлений<br />
   - незарегистрированные пользователи могут редактировать объявление в пределах сессии<br />
   - "Мои объявления" в профиле пользователя<br />
   - Список объявлений пользователя на странице его профиля<br />
   - "Прилепленные" объявления выводятся сверху списка<br />
   - Вывод списка последних объявлений<br />
   - Виджет объявлений<br />
   - Сравнение объявлений</p>

<p style="text-align:justify;"> </p>

<p><strong>Права пользователей:</strong><br />
Права пользователей зависят от прав на категории доски объявлений.<br />
Дополнительные права:<br />
1 - загрузка файлов<br />
2 - автоутверждение объявлений.</p>

<p>Загрузка файлов используется в шаблоне редактирования объявления. Если пользователь обладает этим правом, то вы можете отобразить для него виджет загрузки модуля файлов.</p>

<p>Если пользователь не обладает правом 2 (Автоутверждение объявлений), то его объявления попадают на модерацию и без подверждения администратора не будут показаны другим пользователям.</p>

<p> </p>

<p style="text-align:justify;"><strong>Виджет объявлений:</strong><br />
Для вывода списка в произвольное место используется виджет <strong>advboard_controller_Widget::widget()</strong>. Объявлен в файле: modules/advboard/controller/Widget.php</p>

<p style="text-align:justify;">Сам виджет имеет вид:</p>

<pre class="brush:php;">
public static function widget($condition = array(), $tpl = 'advboard.widget.list', $items = 0, $order = '', $onlyActive = true, $pagination = 'pld', $params = array())</pre>

<p style="text-align:justify;">где:</p>

<p><strong>$condition</strong> - SQL запрос для запроса объявлений<br /><strong>$tpl</strong> - файл шаблона для вывода<br /><strong>$items</strong>  - количество элементов для вывода<br /><strong>$order</strong> - порядок сортировки по правилам SQL<br /><strong>$onlyActive</strong> - Выводить только активные объявления<br /><strong>$pagination</strong> - параметр для постраничной навигации, если будет использоваться</p>

<p>Обратите внимание на то что в качестве шаблонизатора виджет использует <strong>View</strong> из Cotonti Lib а не coTemplate.</p>

<p style="text-align:justify;">Подробнее понять его работу можно посмотрев код виджета.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;">Если Вы хотите вывести список в tpl-файле, то CoTemplate, в отличии от <a href="https://lily-software.com/free-scripts/cotonti-lib/view">View</a> не умеет работать с класами. В этом случае используйте виджет-обертку для этого метода <strong>advboard_widget()</strong>. см. modules/advboard/inc/advboard.functions.php</p>

<p style="text-align:justify;"> </p>

<p><strong>Письма с уведомлениями:</strong><br />
Если в настройках включено уведомление администратора о новых объявлениях, то он получает уведомления о всех добавленых или измененных объявлениях, иначе только если объявление попало на модерацию.</p>

<p><br />
Вы можете создавать шаблоны уведомлений именуя файлы следующим образом: <strong>advboard.notify_admin_new.&lt;lang&gt;.&lt;category&gt;.php</strong></p>

<p> </p>

<p><strong>Разное:</strong></p>

<p><strong>http://&lt;ваш_домен&gt;/advboard/unvalidated</strong> - объявления на модерации<br /><strong>http://&lt;ваш_домен&gt;/advboard/saved-drafts</strong> - неопубликованные (черновики)</p>

<p>Мои объявления:<strong> cot_url('advboard', array('m' =&gt; 'user'))</strong><br />
Объявления пользователя: <strong>cot_url('advboard', array('m' =&gt; 'user', 'uid' =&gt; $user_id))</strong><br />
Количество объявлений пользователя: <strong>cot_user_ads_count($user_id)</strong></p>

<p>RSS лента: <strong>cot_url('advboard', 'm=rss&amp;c=&lt;код_категории&gt;')</strong></p>

<p>Если пользователю создать екстраполя <strong>phone</strong> и <strong>city</strong> (city_name), то он может использовать их, чтобы не заполнять в объявлениях одну и ту же информацию.</p>

<p> </p>

<p style="text-align:justify;"><strong><u>История изменений:</u></strong></p>

<p style="text-align:justify;"><strong>Версия v.3.0.3</strong></p>

<ul><li>Исправление ошибок в работе виджета объявлений</li>
</ul><p style="text-align:justify;"><strong>Версия v.3.0.2</strong></p>

<ul><li>Настраиваемый заголовок для главной страницы доски объявлений и первого элемента хлебных крошек.</li>
	<li>Улучшен виджет сравнения</li>
	<li>Совместимость с Cotonti Lib v2.0.1</li>
</ul><p style="text-align:justify;"><strong>Версия v.3.0.1</strong></p>

<ul><li>Совместимость с Cotonti Lib v2.0.0</li>
</ul><p style="text-align:justify;"><strong>Версия v.3.0.0</strong></p>

<ul><li>Расширение теперь <strong>полноценный модуль</strong>. Раньше оно было плагином.</li>
	<li>Добавлен функционал сравнения объявлений.</li>
	<li>Добавлен виджет для вывода обяъвлений в любых шаблонах сайта.</li>
</ul><p><strong>     Обратите внимание!</strong> Автоматическое обновление плагина (версии 2) до модуля (версии 3) невозможно.</p>

<p style="text-align:justify;"><strong>Версия v.2.0.0</strong></p>

<ul><li>Совместимость с Cotoni Siena.</li>
</ul><p> </p>

<p style="text-align:justify;">GitHub: <a href="https://lily-software.com/go.php?https://github.com/Alex300/advboard">https://github.com/Alex300/advboard</a></p>

<p> </p>

<p style="text-align:justify;"><a href="https://lily-software.com/free-scripts/cotonti-doska-obyavlenij">Плагин версии 2</a></p>
]]></description>
			<pubDate>Wed, 17 Jun 2015 22:34:00 +0300</pubDate>
			<link><![CDATA[https://lily-software.com/free-scripts/advboard]]></link>
		</item>
		<item>
			<title>Cotonti - Dictionary.</title>
			<description><![CDATA[<p>Плагин для <a href="https://lily-software.com/go.php?cotonti.com" target="_blank">CMF Cotonti</a>.</p>

<p>Плагин словарей и номенклатуры для Cotonti Siena.</p>

<p><em>тип:</em> <strong>плагин</strong><br /><em>Версия</em>: <strong>1.0.1</strong><br /><em>Совместимость</em>: <strong>Siena</strong></p>

<p>GitHub: <a href="https://lily-software.com/go.php?https://github.com/Alex300/dictionary">https://github.com/Alex300/dictionary</a></p>

<p> </p>

<p><strong>Системные требования и ограничения:</strong></p>

<ul><li>Наличие на Вашем сайте установленной <a href="https://lily-software.com/sozdanie-internet-sajtov/free-scripts/cotonti-lib">библиотеки Cotonti Lib</a> <strong>версии 2.0.x</strong></li>
	<li>Административная часть плагина расчитана на альтернативную <a href="https://lily-software.com/sozdanie-internet-sajtov/free-scripts/cpanel">тему панели управления cpanel</a>.</li>
</ul><p> </p>

<p><strong>Установка:</strong><br />
- Скопировать плагин на сервер в папку <strong>plugins/dictionary</strong><br />
- Установить плагин из панели администратора</p>

<p> </p>

<p>Плагин позволяет организовать номенклатуру на сайте под управлением Cotonti. А именно - создать словари с наборами 'Ключ' =&gt; 'Значение'. Т.е. каждому слову в словаре сопрставляется уникальный ID, которые можно использовать в других расширениях. Например это могут быть марки или модели авто, типы товаров, должности сотрудников и т.п.</p>

<p>Словари можно использовать для хранения вариантов выбора для экстраполей типа <strong>«select»</strong>.</p>

<p>Словари можно использовать как связанные данные для <a href="https://lily-software.com/sozdanie-internet-sajtov/free-scripts/cotonti-lib/som">других моделей</a>.</p>

<p> </p>

<p>Этот пример заполнит варианты выбора экстраполей значениями из словарей:</p>

<pre class="brush:php;">
$conf = array(
	array(
		'location' =&gt; cot::$db-&gt;advert,
		'field' =&gt; 'brand',
		'dictionary' =&gt; 2,
		'condition' =&gt; "id IN (1,2,3)",
	),
	array(
		'location' =&gt; cot::$db-&gt;advert,
		'field' =&gt; 'model',
		'dictionary' =&gt; 3,
		'parent' =&gt; cot_import_buffered('brand', $advert-&gt;brand, 0),
	),
);

dic_loadExtraFieldData($conf);</pre>

<p>параметры конфигурации:</p>

<p>- <strong>location</strong> и <strong>field</strong> - таблица и экстраполе соотвественно<br />
- <strong>dictionar</strong>y - id словаря, от куда брать значения<br />
- <strong>condition</strong> <em>(необязательно)</em> - условия выборки значений. Если не указано то выбираются все значения указанного словаря.<br />
- <strong>parent</strong> <em>(необязательно)</em> - значение родительского словаря.</p>

<p> </p>

<p>Плагин может быть полезен прежде всего разработчикам. Вы в своих таблицах можете хранить id значений словарей, получая сами значения только при необходимости. Это позволяет избежать ошибок при многократном написании самих значений. А исправление внесенное в словарь сразу отразится на всех связанных данных. Также возможно организовать поиск по таким полям.<br />
Напрмер: <em>выбрать все модели автомобилей марки BMW.</em></p>

<p> </p>

<p>Программно получить список "ключ" =&gt; "значение" метод <strong>dictionary_model_Value::keyValPairs()</strong>, например:</p>

<pre class="brush:php;">
dictionary_model_Value::keyValPairs(array(array('dictionary', 3)));</pre>

<p>выберет все значения для словаря с id=3.</p>

<p> </p>

<p><strong>Родительский словарь</strong></p>

<p>Словарь может иметь родителя. Например модель автомобиля - марку, а город относится к определенному региону. <strong>dic_loadExtraFieldData()</strong> организует элементы <strong>select</strong> так, что после выбора значения родительского словаря (например произволителя авто) пользвателю будет предложен выбор соотвествующих значений словаря - потомка (напрмер: марки авто этого производителя)</p>

<p> </p>

<p>Упрощенным и частным случаем этого плагина является плагин <a href="https://lily-software.com/sozdanie-internet-sajtov/free-scripts/cotonti-region-city-ajax-selector">Region-City</a>.</p>

<p> </p>

<p><strong><u>История изменений:</u></strong></p>

<p><strong>Версия v1.0.1</strong></p>

<ul><li>Совместимость с Cotonti Lib v2.0.</li>
</ul>]]></description>
			<pubDate>Tue, 16 Jun 2015 23:15:00 +0300</pubDate>
			<link><![CDATA[https://lily-software.com/free-scripts/dictionary]]></link>
		</item>
		<item>
			<title>Cotonti - cPanel.</title>
			<description><![CDATA[<p>Современная и удобная панель управления для CMF Cotonti.</p>

<p style="text-align:justify;"><em>тип:</em> <strong>тема и модуль</strong><br />
<em>Версия модуля</em>: <strong>1.0.0</strong><br />
<em>Совместимость</em>: <strong>Siena</strong></p>

<p style="text-align:justify;">GitHub: <a href="https://lily-software.com/go.php?https://github.com/Alex300/cotonti-cpanel">https://github.com/Alex300/cotonti-cpanel</a></p>

<p style="text-align:justify;">Панель управления, использующая фреймворк <strong><a href="https://lily-software.com/go.php?getbootstrap.com" target="_blank" rel="noreferrer noopener">Bootstrap3</a></strong> в качестве каркаса для верстки и <a href="https://lily-software.com/go.php?fontawesome.io" target="_blank" rel="noreferrer noopener"><strong>Font Awesome</strong></a> для иконок. В состав входит модуль cpanel, который расшряет возможности стандартной панели администратора Cotonti.</p>

<p> </p>

<p><strong>Установка:</strong></p>

<p style="text-align:justify;">- Скопировать тему <strong>cpanel</strong> на сервер в папку <strong>themes/admin</strong><br />
- Скопировать модуль <strong>cpanel</strong> на сервер в папку <strong>modules</strong><br />
- Скачать и установить <strong>Bootstrap</strong> и <strong>Font Awesome</strong> в папку <strong>lib</strong> Вашего сайта.<br />
- Установить модуль из панели администратора<br />
- В файле <strong>datas/config.php</strong> установить <strong>$cfg['admintheme'] = 'cpanel';</strong></p>

<p style="text-align:justify;"> </p>

<h2 style="text-align:justify;">Для разработчиков:</h2>

<p style="text-align:justify;">Вы можете в полной мере использовать возможности разметки, которые предоставляет Bootstrap.</p>

<p style="text-align:justify;">Конетент Вашего расширения будет выводиться в панель по-умолчанию. Вы можете отключить такое поведение при необходимости.</p>

<p style="text-align:justify;"> </p>

<p><strong>Добавление пунктов меню в панели управления:</strong></p>

<p>Модули и плагины могут добавлять свои пункты в меню панели управления.</p>

<p>Для этого необходимо создать файл расшиения с хуком <strong>header.tags</strong> который внесет нужные изменения в массивы элементов меню:</p>

<p><strong>cpanel::$menu['top']</strong>  - Верхнее меню<br />
<strong>cpanel::$menu['side']</strong> - Боковое меню<br />
<strong>cpanel::$menu['user']</strong> - Меню пользователя</p>

<p><strong>cpanel::$useDefaultPanel = true;</strong> - выводить панель-по умолчанию при выводе контента<br />
<strong>cpanel::$panelTitle;</strong> - свое название для панели по-умолчанию</p>

<p> </p>

<p>Пример кода:</p>

<pre class="brush:php;">
if (!COT_AJAX &amp;&amp; defined('COT_ADMIN') &amp;&amp; $cfg['admintheme'] == 'cpanel') {
    cpanel::$menu['side'][] = [
        'title' =&gt; 'My Cool Module',
        'url' =&gt; cot_url('admin', ['m' =&gt; 'my_cool_module']),
        'icon_class' =&gt; 'fa fa-times-circle',
    ];
}</pre>

<p> </p>

<p style="text-align:justify;"><strong><u>История изменений:</u></strong></p>

<p style="text-align:justify;"><strong>Версия v.1.0.0</strong></p>

<ul>
	<li style="text-align:justify;">Совместимость с Cotonti 0.9.25</li>
</ul>

<p style="text-align:justify;"><strong>Версия v.0.0.5-0.0.6</strong></p>

<ul>
	<li style="text-align:justify;">Совместимость с Cotonti Siena 0.9.22-0.9.23</li>
</ul>

<p style="text-align:justify;"><strong>Версия v.0.0.4</strong></p>

<p style="text-align:justify;">Совместимость с PHP 8.1</p>

<p style="text-align:justify;"><strong>Версия v.0.0.3</strong></p>

<ul>
	<li>Панель «по-умолчанию»</li>
	<li>Улучшено левое меню.</li>
</ul>

<p style="text-align:justify;"><strong>Версия v.0.0.2</strong></p>

<ul>
	<li>Добавлены еще шаблоны «коробочных» расширений Cotonti.</li>
	<li>Загрузка JS и CSS-файлов доверена системному классу Resources.</li>
</ul>

<p> </p>

<h3>Скриншоты:</h3>
]]></description>
			<pubDate>Fri, 02 Jan 2015 17:35:00 +0300</pubDate>
			<link><![CDATA[https://lily-software.com/free-scripts/cpanel]]></link>
		</item>
		<item>
			<title>Cotonti - Работа.</title>
			<description><![CDATA[<p>Модуль поиска работы и подбора персонала для Cotonti.</p>

<p style="text-align:justify;"><em>тип:</em> <strong>модуль</strong><br /><em>Версия модуля</em>: <strong>1.0.1</strong><br /><em>Совместимость</em>: <strong>Siena</strong></p>

<p style="text-align:justify;">GitHub: <a href="https://lily-software.com/go.php?https://github.com/Alex300/personal">https://github.com/Alex300/personal</a></p>

<p style="text-align:justify;">Модуль позовляет пользователям Вашего сайта на Cotonti создавать и размещать резюме, вакансии и информацию компаниях работодателях.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><strong>Системные требования и ограничения:</strong></p>

<ul><li style="text-align:justify;">PHP версии 5.3 и выше. Работа с PHP версии 5.2.х и ниже невозможна.</li>
	<li style="text-align:justify;">Наличие на Вашем сайте установленной <a href="https://lily-software.com/sozdanie-internet-sajtov/free-scripts/cotonti-lib">библиотеки Cotonti Lib</a> <strong>версии 2.0.x</strong></li>
	<li style="text-align:justify;">Наличие на Вашем сайте установленного плагина <a href="https://lily-software.com/sozdanie-internet-sajtov/free-scripts/cotonti-region-city-ajax-selector">Region-City ajax selector</a></li>
	<li style="text-align:justify;">Наличие в папке /lib Java Script библиотеки <a href="https://lily-software.com/go.php?http://ivaynberg.github.io/select2/">Select2</a> (для поиска города по первым буквам)</li>
</ul><p style="text-align:justify;"> </p>

<p style="text-align:justify;"><strong>Установка:</strong><br />
- Скопировать папку <strong>personal</strong> на сервер в папку <strong>modules</strong><br />
- Установить модуль из панели администратора<br />
- Создать категории для вакансий/резюме.<br />
- Установить Select2 в папку /lib. Структура папок должна получиться следующая</p>

<pre class="brush:xml;">
lib
    select2
        css
        js</pre>

<p style="text-align:justify;"><br />
 </p>

<p style="text-align:justify;"><strong>Рекомендации:</strong><br />
- Вы можете использовать <a href="https://lily-software.com/sozdanie-internet-sajtov/free-scripts/cotonti-files">модуль Файлов</a> чтобы организовать вложения к вакансиям и резюме.</p>

<p style="text-align:justify;">Для вакансий используйте параметр source: "<strong>personal_vacancy</strong>", а для резюме - "<strong>personal_resume</strong>". В этом случае вложения будут автоматически привязываться к вновь создаваемым объектам и корректно удаляться при их удалении.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><strong><u>История изменений:</u></strong></p>

<p style="text-align:justify;"><strong>Версия v.1.0.1</strong></p>

<ul><li>Совместимость с MySQL 5.7 и Cotonti Lib 2.0.</li>
</ul>]]></description>
			<pubDate>Sat, 25 Oct 2014 11:59:00 +0300</pubDate>
			<link><![CDATA[https://lily-software.com/free-scripts/personal]]></link>
		</item>
		<item>
			<title>View. PHP-шаблонизатор.</title>
			<description><![CDATA[<p style="text-align:justify;">Исторически сложилось так, что Cotonti использует шаблонизатор CoTemplate, что накладывает значительные ограничения на возможности самих шаблонов, даже несмотря на то, что за последние годы он стал намного удобнее.</p>

<p style="text-align:justify;">Но мы знаем, что PHP сконструирован специально<strong> для ведения Web-разработок</strong> и его код <strong>может внедряться непосредственно в HTML</strong>.<br />
PHP — сам по себе является не только очень мощьным языком программирования, но и самодостаточным шаблонизатором, позволяющим делать качественные шаблоны без ущерба для логики приложения.</p>

<p style="text-align:justify;">Такой стиль шаблонизации на PHP называют «pure-шаблонизация», т.е. чистая шаблонизация, основанная на возможностях самого PHP.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;">Класс <strong>View</strong> позволяет использовать шаблоны на чистом PHP.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><strong>Преимущества:</strong></p>

<p style="text-align:justify;">- Чистый PHP будет работать быстрее шаблонизаторов (интрепретаторов), написанных на PHP, т.к. нет программной "прослойки" между PHP и шаблоном, выполнение которой, как ни крути, а требует рессурсов. Хотя, многие современные шаблонизаторы компилируют шаблоны в PHP код.</p>

<p style="text-align:justify;">- PHP и есть шаблонизатор и в шаблоне доступны все его возможности.</p>

<p style="text-align:justify;">- Не нужно изучать дополнительный синтаксис. Знания HTML и шести - десяти конструкций на PHP вполне достаточно для верстки шаблона почти любой сложности.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><strong>Недостатки:</strong></p>

<p style="text-align:justify;">- Кто то считает, что «ужасный синтаксис». По-моему - это весьма субъективно и зависит от личных предпочтений. В моделях и контроллерах он уже не выглядит настолько ужасным )</p>

<p style="text-align:justify;">- Слишком много лишнего текста в шаблонах. Тоже зависит от личных предпочтений и субъективно.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;">Итак к делу.</p>

<p style="text-align:justify;">По существу применение <strong><span class="classname">View</span></strong> состоит из двух шагов:</p>

<p style="text-align:justify;">1. Ваш скрипт контроллера создает экземпляр <span class="classname">View</span> и объявляет переменные этого экземпляра.</p>

<p style="text-align:justify;">2. Контроллер приказывает <span class="classname">View</span> воспроизвести данный вид используя шаблон.</p>

<p style="text-align:justify;"> </p>

<p><strong>Скрипт контроллера</strong></p>

<p>В качестве простого примера предположим, что ваш контроллер имеет список данных по книгам, который нужно вывести пользователю. Скрипт контроллера может выглядеть примерно так:</p>

<pre class="brush:php;">
// Для наглядности, у нас есть массив с данными о книгах
$data = array(
	array(
	    'author' =&gt; 'Hernando de Soto',
	    'title' =&gt; 'The Mystery of Capitalism'
	),
	array(
	    'author' =&gt; 'Henry Hazlitt',
	    'title' =&gt; 'Economics in One Lesson'
	),
	array(
	    'author' =&gt; 'Milton Friedman',
	    'title' =&gt; 'Free to Choose'
	)
);

// теперь присваиваем данные по книгам экземпляру View
$view = new View();
$view-&gt;books = $data;

// и выполняем скрипт вида "booklist.php"
echo $view-&gt;render('library.booklist.php');</pre>

<p> </p>

<p><strong>Скрипт шаблона:</strong></p>

<p style="text-align:justify;">Теперь нам нужен сопутствующий скрипт шаблона "library.booklist.php". Это такой же скрипт PHP, как и остальные, за одним исключением: он выполняется в области видимости экземпляра View, это означает, что $this ссылается на экземпляр View. Переменные, присваиваемые в контроллере для скрипта вида, являются открытыми свойствами экземпляра View. Таким образом, базовый скрипт вида может выглядеть следующим образом:</p>

<pre class="brush:xml;">
&lt;p&gt;Список книг&lt;/p&gt;
&lt;?php if ($this-&gt;books): ?&gt;

&lt;!-- Таблица из нескольких книг. --&gt;
&lt;table&gt;
    &lt;tr&gt;
        &lt;th&gt;Author&lt;/th&gt;
        &lt;th&gt;Title&lt;/th&gt;
    &lt;/tr&gt;

    &lt;?php foreach ($this-&gt;books as $key =&gt; $val): ?&gt;
    &lt;tr&gt;
        &lt;td&gt;&lt;?=htmlspecialchars($val['author']) ?&gt;&lt;/td&gt;
        &lt;td&gt;&lt;?=htmlspecialchars($val['title']) ?&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;?php endforeach; ?&gt;

&lt;/table&gt;

&lt;?php else: ?&gt;

&lt;p&gt;Нет книг для отображения.&lt;/p&gt;

&lt;?php endif; ?&gt;</pre>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;">Класс View также подерживает присваивание переменных в стиле CoTemplate:</p>

<pre class="brush:php;">
$view-&gt;assign(array(
    'PAGE_TITLE'  =&gt;  $title,
    'BREADCRUMBS' =&gt;  cot_breadcrumbs($crumbs, cot::$cfg['homebreadcrumb']),
));</pre>

<p style="text-align:justify;">что аналогично:</p>

<pre class="brush:php;">
$view-&gt;PAGE_TITLE = $title;
$view-&gt;BREADCRUMBS = cot_breadcrumbs($crumbs, cot::$cfg['homebreadcrumb']);</pre>

<p style="text-align:justify;"> </p>

<h4>Основные методы класса <strong>View</strong>:</h4>

<p> </p>

<p><strong>render($viewFile, $type = 'module', $admin = null, $return = true)</strong></p>

<p>Рендерит  HTML код из шаблона и полученных данных.Принимает следующие параметры:</p>

<p><strong>$viewFile</strong> - имя файла шаблона. Если не указано расширение или оно не входит в свойство класса <strong>$_extensions</strong>, будет использовано <strong>".php".<br />
$type </strong>- тип расширения. Может быть 'plug', 'module' or 'core'<br /><strong>$admin - </strong>использовать файл admin-темы, если возможно. По умолчанию эту опцию метод пытается определить исходя из параметра <strong>$viewFile</strong><br /><strong>$return </strong>- Вернуть готовый HTML-код в виде строки (если TRUE) или выполнить require($viewFile)</p>

<p>Файл шаблона ищется по тем же правилам, что и при использовании функции <strong>cot_tplfile()</strong> для CoTemplate.</p>

<p> </p>

<p> </p>

<p><strong>addScriptPath($path, $prepend = true)</strong></p>

<p>Добавить дополнительный путь для поиска шаблонов.</p>

<p><strong>$path</strong> - Путь к папке с шаблонами. <br /><strong>$prepend </strong>- Поместить путь в начало стека.</p>

<p> </p>

<p> </p>

<p><strong>scriptFile($base, $type = 'module', $admin = null)</strong></p>

<p>Ищет и возвращает полый путь к файлу шаблона или <strong>false</strong>, если шаблон не найден. Параметры аналогичны методу <strong>render();</strong></p>
]]></description>
			<pubDate>Sat, 13 Sep 2014 23:21:00 +0300</pubDate>
			<link><![CDATA[https://lily-software.com/free-scripts/cotonti-lib/view]]></link>
		</item>
		<item>
			<title>SOM. (Simple Object Manipulation)</title>
			<description><![CDATA[<h4>Общие сведения</h4>

<p style="text-align:justify;"><strong>SOM (Simple Object Manipulation)</strong> - это простая ORM, позволяющая работать с записями в базе данных посредством моделей, объектов, обладающих определенным набором методов, свойств и связями с другими моделями.</p>

<p style="text-align:justify;">SOM является логическим продолжением <a href="https://lily-software.com/go.php?https://github.com/trustmaster/cot-factory/blob/master/system/orm.php" target="_blank"><strong>ORM</strong></a> из <strong><a href="https://lily-software.com/go.php?https://github.com/trustmaster/cot-factory" target="_blank">cot-factory</a></strong> и представляет собой усовершенствованную и доработанную ORM из упомянутой библиотеки. Спасибо <a href="https://lily-software.com/go.php?https://github.com/ghengeveld" target="_blank">Gert Hengeveld</a> и <a href="https://lily-software.com/go.php?https://github.com/trustmaster" target="_blank">Владимиру Сибирову</a> (trastmaster) за их труд над <strong>cot-factory</strong>.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;">Модели данных создаются в рамках паттерна MVC и соответствуют его концепции. Модели инкапсулируют основные операции с базой данных и позволяют абстрагироваться от непосредственной работы с ней и сосредоточится на программировании.</p>

<h4> </h4>

<h4>Требования</h4>

<p>Для правильной работы необходим php не ниже версии 5.3</p>

<p> </p>

<h4>Использование нескольких соединений с бд</h4>

<p style="text-align:justify;">Иногда бывает необходимо использовать несколько соединений с базой данных. Например когда Вы используете данные, которые хранятся в разных БД или пишите конвертер для переноса данных из одной БД в другую. SOM предоставляет Вам такую возможность.</p>

<p>Для этого в файл <strong>datas/config.php</strong> вашего сайта добавте описание нужных соединений:</p>

<pre class="brush:php;">
$cfg['db_connect_name'] = array(
      'adapter' =&gt; 'mysql',   // 'pgsql' or 'mongo'
      'host' =&gt; '127.0.0.1',
      'port' =&gt; null,
      'username' =&gt; '12345',
      'password' =&gt; '6789',
      'dbname' =&gt; 'my_data_base',
 );</pre>

<p>Поддерживаются базы данных <strong>MySql</strong> и <strong>PostgreSQL</strong>. <strong>Mongo</strong> - эксперементально.</p>

<p>Чтобы установить соединение вызовите фабричный метод:</p>

<pre class="brush:php;">
$db_my_conn = Som::getAdapter('db_connect_name');</pre>

<p style="text-align:justify;">который вернет объект <strong>Som_Model_Mapper</strong> нужного типа. После этого можно отправлять ему запросы обычным образом:</p>

<pre class="brush:php;">
$db_my_conn-&gt;query("SELECT * FROM `cot_some_table` ORDER BY id ASC");</pre>

<p style="text-align:justify;">Также Вы можете передавать имена соединений моделям при инициализации, если необходимо использовать соединения, отличные от системного в Cotonti.</p>

<p style="text-align:justify;">Соединения кешируются на период выполнения. Это значит, что Вы можете вызывать метод <strong>Som::getAdapter</strong> с одним и тем же параметром столько - сколько Вам нужно. Объект соединения с БД не будет создаваться каждый раз заново, а будет возвращаться ссылка на один раз созданный объект.</p>

<p> </p>

<h4>Создание моделей</h4>

<p>Конкретная модель создается классом, который наследуется от класса <strong>Som_Model_Abstract</strong>. Соотвественно, он насследует все его методы. В создаваемом классе модели обязательно должны быть определены следующие свойства:</p>

<pre class="brush:php;">
protected static $_db;
protected static $_tbname = 'katalogshop_sale';
</pre>

<p>и опционально</p>

<pre class="brush:php;">
protected static $_primary_key = 'prod_id';</pre>

<p><strong>$_db хранит</strong> ссылку на объект базы данных<br /><strong>$_tbname</strong> - имя таблицы в БД. Указывается явно при объявлении.<br /><strong>$_primary_key</strong> - название поля - первичный ключ таблицы. Если не указано, то используется поле 'id'.</p>

<p style="text-align:justify;">В конце файла класса модели необходимо вызвать статический метод этого класса <strong>_init()</strong>. По умолчанию будет выполнен соотвествующий метод родительского класса. Это т.н. «статический конструктор», который выполняет начальную инициализацию модели, заполняет свойства $_db и загружает экстраполя.<br />
 </p>

<p>пример модели расписания для группы ВУЗА:</p>

<pre class="brush:php;">
&lt;?php
defined('COT_CODE') or die('Wrong URL.');

/**
 * Модель Schedule
 *
 * Расписание
 *
 * @method static vuz_model_Schedule getById($pk);
 * @method static vuz_model_Schedule fetchOne($conditions = array(), $order = '');
 * @method static vuz_model_Schedule[] find($conditions = array(), $limit = 0, $offset = 0, $order = '');
 *
 * @property int    $id
 * @property string $title         Заголовок
 * @property string $description   Описание
 * @property string $text          Текст
 * @property string $begin         Дата начала
 * @property string $end           Дата окончания
 * @property string $created       Дата создания
 * @property string $created_by    Кем создано
 * @property string $updated       Дата обновления
 * @property string $updated_by    Кем обновлено
 *
 * @property vuz_model_Group $sgroup
 *
 * @property string $displayTitle
 */
class vuz_model_Schedule extends Som_Model_Abstract
{
    /**
     * @var Som_Model_Mapper_Abstract
     */
    protected  static $_db = null;
    protected  static $_tbname = '';
    protected  static $_primary_key = 'id';

    /**
     * Static constructor
     */
    public static function __init($db = 'db'){
        global $db_soc_groups_schedule;

        static::$_tbname = $db_soc_groups_schedule;
        parent::__init($db);
    }

    /**
     * Привязывает файлы из модуля Files
     */
    protected function afterInsert(){
        cot_files_linkFiles('sgrp_schedule', $this-&gt;_data['id']);
    }

    /**
     * @return bool
     */
    public function delete(){

        // Remove all files and images
        $files = files_model_File::find(array(
            array('file_source', 'sgrp_schedule'),
            array('file_item', $this-&gt;_data['id'])
        ));
        if(!empty($files)){
            foreach($files as $fileRow){
                $fileRow-&gt;delete();
            }
        }

         return parent::delete();
    }

    public static function fieldList() {
        return array(
            'id'  =&gt;
                array(
                    'type'    =&gt; 'bigint',
                    'primary' =&gt; true,
                    'description' =&gt; 'id'
                ),
            'title'  =&gt;
                array(
                    'type'      =&gt; 'varchar',
                    'length'    =&gt; '255',
                    'description' =&gt; 'Заголовок'
                ),
            'description'  =&gt;
                array(
                    'type'      =&gt; 'varchar',
                    'nullable'  =&gt; true,
                    'default'   =&gt; '',
                    'length'    =&gt; '255',
                    'description' =&gt; 'Краткое описание'
                ),
            'text' =&gt;
                array(
                    'type'      =&gt; 'text',
                    'nullable'  =&gt; true,
                    'default'   =&gt; '',
                    'description' =&gt; 'Текст'
                ),
            'begin'  =&gt;
                array(
                    'type'      =&gt; 'datetime',
                    'default'   =&gt; date('Y-m-d H:i:s', cot::$sys['now']),
                    'description' =&gt; 'Дата начала'
                ),
            'end'  =&gt;
                array(
                    'type'      =&gt; 'datetime',
                    'description' =&gt; 'Дата окончания'
                ),
            'created'  =&gt;
                array(
                    'type'      =&gt; 'datetime',
                    'safe'      =&gt; true,
                    'description' =&gt; 'Дата создания'
                ),
            'created_by'  =&gt;
                array(
                    'type'      =&gt; 'bigint',
                    'safe'      =&gt; true,
                    'description' =&gt; 'Кем создано'
                ),
            'updated'  =&gt;
                array(
                    'type'      =&gt; 'datetime',
                    'safe'      =&gt; true,
                    'description' =&gt; 'Дата обновления'
                ),
            'updated_by'  =&gt;
                array(
                    'type'      =&gt; 'bigint',
                    'safe'      =&gt; true,
                    'description' =&gt; 'Кем обновлено'
                ),
            'sgroup' =&gt;
                array(
                    'type' =&gt; 'link',
                    'description' =&gt; 'Группа Вуза',
                    'link' =&gt;
                        array(
                            'model'    =&gt; 'vuz_model_Group',
                            'relation' =&gt; Som::TO_ONE_NULL,
                            'label' =&gt; 'sgrp_title',
                        ),
                ),
        );
    }

    // === Методы для работы с шаблонами ===
    /**
     * Returns all Group tags for coTemplate
     *
     * @param vuz_model_Schedule|int $item vuz_model_Vuz object or ID
     * @param string $tagPrefix Prefix for tags
     * @param array $urlParams
     * @param int $textlength
     * @param bool $cacheitem Cache tags
     * @return array|void
     */
    public static function generateTags($item, $tagPrefix = '', $urlParams = array(), $textlength = 500, $cacheitem = true){

        static $extp_first = null, $extp_main = null;
        static $cacheArr = array();

        if (is_null($extp_first)){
            $extp_first = cot_getextplugins('vuz.schedule.tags.first');
            $extp_main  = cot_getextplugins('vuz.schedule.tags.main');
        }

        /* === Hook === */
        foreach ($extp_first as $pl){
            include $pl;
        }
        /* ===== */

        if(empty($urlParams)) $urlParams = array();
        if(empty($urlParams['m'])) $urlParams['m'] = 'group';
        if(empty($urlParams['a'])) $urlParams['a'] = 'schedule';

        if ( ($item instanceof vuz_model_Schedule) &amp;&amp; is_array($cacheArr[$item-&gt;id]) ) {
            $temp_array = $cacheArr[$item-&gt;id];
        }elseif (is_int($item) &amp;&amp; is_array($cacheArr[$item])){
            $temp_array = $cacheArr[$item];
        }else{
            if (is_int($item) &amp;&amp; $item &gt; 0){
                $item = vuz_model_Schedule::getById($item);
            }
            /** @var vuz_model_Schedule $item  */
            if ($item){

                // Права
                // Задание может править автор или староста
                $scheduleAuth['isadmin'] = cot_auth('vuz', 'a', 'A');
                if($scheduleAuth['isadmin']){
                    $scheduleAuth['auth_write'] = true;

                }elseif(cot::$usr['id'] == $item-&gt;created_by){
                    $scheduleAuth['auth_write'] = true;

                }else{
                    $grpAuth['isLeader'] = $item-&gt;sgroup-&gt;isLeader(cot::$usr);
                    if($grpAuth['isLeader']) $taskAuth['auth_write'] = true;

                }

                if(empty($urlParams['gid']) &amp;&amp; !empty($grpIds)) $urlParams['gid'] = $item-&gt;sgroup-&gt;sgrp_id;
                $urlParams['sid'] = $item-&gt;id;

                $itemUrl = cot_url('vuz', $urlParams);
                $itemEditUrl = '';
                if($scheduleAuth['auth_write']){
                    $editUrlParams = $urlParams;
                    $editUrlParams['a'] = 'editSchedule';
                    $itemEditUrl = cot_url('vuz', $editUrlParams);
                }

                $itemDelUrl = '';
                if($scheduleAuth['auth_write']){
                    $editUrlParams = $urlParams;
                    $editUrlParams['a'] = 'deleteSchedule';
                    $itemDelUrl  = cot_confirm_url(cot_url('vuz', $editUrlParams),  'vuz', 'shedule_deleteConfirm');
                }

                $text = cot_parse($item-&gt;text);
                $text_cut = cot_cut_more($text);
                if ($textlength &gt; 0 &amp;&amp; mb_strlen($text_cut) &gt; $textlength){
                    $text_cut = cot_string_truncate($text_cut, $textlength);
                }
                $cutted = (mb_strlen($text) &gt; mb_strlen($text_cut)) ? true : false;

                $date_format = 'datetime_medium';
                $date_format = 'date_fulltext';
                $beginStamp = strtotime($item-&gt;begin);
                $endStamp = !empty($item-&gt;end) ? strtotime($item-&gt;end) : 0;
                $temp_array = array(
                    'URL' =&gt; $itemUrl,
                    'EDIT_URL' =&gt; $itemEditUrl,
                    'DELETE_URL' =&gt; $itemDelUrl,
                    'ID' =&gt; (int)$item-&gt;id,
                    'TITLE' =&gt; htmlspecialchars($item-&gt;TITLE),
                    'DISTPLAY_TITLE' =&gt; htmlspecialchars($item-&gt;displayTitle),
                    'DESC' =&gt; htmlspecialchars($item-&gt;description),
                    'BEGIN' =&gt; cot_date($date_format, $beginStamp),
                    'BEGIN_RAW' =&gt; $beginStamp,
                    'END' =&gt; cot_date($endStamp, $beginStamp),
                    'END_RAW' =&gt; $endStamp,
                    'TEXT' =&gt; $item-&gt;text,
                    'TEXT_CUT' =&gt; $text_cut,
                    'TEXT_IS_CUT' =&gt; $cutted,

                    'CREATED' =&gt; $item-&gt;created,
                    'CREATE_DATE' =&gt; cot_date($date_format, strtotime($item-&gt;created)),
                    'CREATED_RAW' =&gt; strtotime($item-&gt;created),

                    'UPDATED' =&gt; $item-&gt;updated,
                    'UPDATE_DATE' =&gt; cot_date($date_format, strtotime($item-&gt;updated)),
                    'UPDATED_RAW' =&gt; strtotime($item-&gt;updated),
                );

                /* === Hook === */
                foreach ($extp_main as $pl)
                {
                    include $pl;
                }
                /* ===== */
                $cacheitem &amp;&amp; $cacheArr[$item-&gt;id] = $temp_array;
            }else{

            }
        }

        $return_array = array();
        foreach ($temp_array as $key =&gt; $val){
            $return_array[$tagPrefix . $key] = $val;
        }

        return $return_array;
    }

}

vuz_model_Schedule::__init();</pre>

<p style="text-align:justify;">Здесь очень важным является метод <strong>fieldList()</strong>, возвращающий массив с описанием полей в таблице. Обратите внимание на то, что модель не проверяет физическое наличие полей в таблице БД, а наивно доверяет возвращаемому массиву.<br />
 Ключом массива является имя поля, а значением массив с описанием в формате ключ=&gt;значение и может содержать следующие данные:</p>

<p style="text-align:justify;"><strong>'name'</strong> - название поля<br /><strong>'primary'</strong> - может быть только у одного поля. Значение <strong>true </strong>указывает на то, что поле явлается первичным ключом таблицы.<br /><strong>'type'</strong> - тип поля. Это SQL тип или 'link', если это поле является связью с другой моделью.<br /><strong>'length'</strong> - необязательно. Длина значения, например для <strong>varchar</strong><br /><strong>'nullable'</strong> - необязательно. 'nullable' =&gt; false указывает на то, что поле не может принимать пустое значение.<br /><strong>'default'</strong> - необязательно. Значение по умолчанию. При создании нового экземпляра модели поле будет проинициализировано этим значением. Однако при получении существующего объекта, поле будет проинициализировано данными из БД.<br /><strong>'description'</strong> - необязательно. Описание поля.<br /><strong>'safe'</strong> - необязательно. Если <strong>TRUE</strong> , то поле является «защищенным» при заполнении модели данными методом <strong>setData()</strong>, при попытке заполнения этого поля выбросит исключение, если пользователь не является администратором или действие просходит не в панели управления.</p>

<p>Обращаться к полям модели можно как к обычным свойствам объекта.</p>

<p>Например:</p>

<pre class="brush:php;">
$sсhedule = vuz_model_Schedule::getById(15);   // Получить существующий объект
$endStamp = !empty($sсhedule-&gt;end) ? strtotime($sсhedule-&gt;end) : 0;</pre>

<p> </p>

<h4>Связи между моделями</h4>

<p style="text-align:justify;">Модель может содержать связи с другими моделями. Поддерживаются связи <strong>один-ко-многим</strong> и <strong>многие-ко-многим</strong>. Например, наше расписание принадлежит конкретной группе ВУЗ'а реализованной моделью <strong>vuz_model_Group</strong>. Эта связь описывается так:</p>

<pre class="brush:php;">
'sgroup' =&gt;
    array(
        'name' =&gt; 'sgroup',
        'type' =&gt; 'link',
        'description' =&gt; 'Группа Вуза',
        'link' =&gt;
            array(
                'model'    =&gt; 'vuz_model_Group',
                'relation' =&gt; Som::TO_ONE_NULL,
                'label' =&gt; 'title',
            ),
        ),</pre>

<p>Здесь в массив с описанием доля добавляется элемент <strong>'link'</strong>, описывающий связь:</p>

<p><strong>'model' </strong>- имя класса связываемой модели<br /><strong>'relation'</strong> - тип связи. Возможные значения (константы класса Som):<br />
    - Som::TO_ONE  - один ко многим<br />
    - Som::TO_ONE_NULL  - один ко многим, разрешено пустое значение<br />
    - Som::TO_MANY - многие ко многим<br />
    - Som::TO_MANY_NULL - многие ко многим, разрешено пустое значение<br /><strong>'label'</strong> - необязательно. Свойство связываемого класса которое можно использовать для автоматического вывода связанных объектов. Напрмер <strong>'title'</strong>.<br /><strong>'localkey'</strong> - необязательно. Имя поля в данной модели (а точнее в таблице БД), где хранится id связанного объекта. Используется только для связей <strong>один-ко-многим</strong> т.к. для хранения связей многие-ко-многим необходима отдельная таблица в БД, которая при необходимости создается автоматически.<br />
Если параметр <strong>localkey</strong> не указан, то будет использовано само поле в котором описана связь. В данном случае - <em>sgroup</em>. <strong>Обратите внимание</strong>, что поле должно существовать в таблице в БД.</p>

<p>При обращении к полю связанному с другой моделью получим ссылку на объект этой модели. Например:</p>

<pre class="brush:php;">
$prod = Product::getById(2);
echo $prod-&gt;topic-&gt;name; // Выведет поле name экземпляра класса «ProductTopic» (для один-ко-многим)
</pre>

<p>или</p>

<pre class="brush:php;">
$prod = Product::getById(2);
// Это сработает, если у нас для поля $topics объявлена связь многие-ко-многим
foreach ($prod-&gt;topics as $topic){
    // do something ...
    echo $topic-&gt;name;
}
</pre>

<p>Запрос к базе данных на получение связанного объекта происходит только по необходимости. Т.е. в момент обращения</p>

<p>Полю со связью один-ко-многим можно присвоить id связанного объекта или сам объект</p>

<p>Например:</p>

<pre class="brush:php;">
$prod = Product::getById(5);
$topic = ProductTopic::getById(2);

$prod-&gt;topic = 2;      // Присвоили id
$prod-&gt;topic = $topic; // Присвоили экземпляр класса ProductTopic(). По сути эти действия идентичны.
</pre>

<p>Присваивать можно либо самому объявленному полю, либо полю из БД, указанному в localkey</p>

<p>Присвоить можно только экземпляр того класса, каким объявлена связь.</p>

<p>Присваивание значений полям со связями многие-ко-многим аналогично с той разницей, что помимо id или самого объекта допускается присваивание содержащего их массива.</p>

<p> </p>

<h4>Основные методы класса Som_Model_Abstract</h4>

<p><strong>static _init($db = 'db')</strong></p>

<p>Статический конструктор. Должен вызываться при включении файла конкретного класса модели. Выполняет начальную инициализацию модели, заполняет свойства $_db и $_columns. Он принимает один единственный необязательный параметр $db - тип базы данных, по-умолчанию используется соединение с БД Cotonti.</p>

<p> </p>

<p><strong>__construct($data = null)</strong></p>

<p>Конструктор экземпляра. Автоматически вызывается при создании экземпляра модели.</p>

<p>Может принимать в качестве параметра другой экземпляр той же модели или массив (ключ-значение). В этом случае поля объекта будут инициализированы соответствующими значениями.</p>

<p> </p>

<p><strong>protected function afterDelete()</strong></p>

<p>Выполняется после удаления объекта. По умолчанию метод ничего не делает, но Вы можете переопределить его для выполнения неких действий, спецефичных для Вашей модели.</p>

<p> </p>

<p><strong>protected function afterInsert()</strong></p>

<p>Выполняется после добавления нового объекта в БД. По умолчанию метод ничего не делает, но Вы можете переопределить его для выполнения неких действий, спецефичных для Вашей модели.</p>

<p> </p>

<p><strong>protected function afterSave()</strong></p>

<p>Выполняется после сохранения объекта независимо от того, есть соотвествующая запись в БД или нет. По умолчанию метод ничего не делает, но Вы можете переопределить его для выполнения неких действий, спецефичных для Вашей модели.</p>

<p> </p>

<p><strong>protected function afterSetData($data)</strong></p>

<p>Выполняется после заполнения модели данными методом <strong>setData()</strong>; По умолчанию метод ничего не делает, но Вы можете переопределить его для выполнения неких действий, спецефичных для Вашей модели.</p>

<p> </p>

<p><strong>protected function afterUpdate()</strong></p>

<p>Выполняется после существующего объекта. По умолчанию метод ничего не делает, но Вы можете переопределить его для выполнения неких действий, спецефичных для Вашей модели.</p>

<p> </p>

<p><strong>protected function beforeDelete()</strong></p>

<p style="text-align:justify;">Выполняется перед удалением объекта. По умолчанию метод возвращает TRUE, но Вы можете переопределить его для выполнения неких действий, спецефичных для Вашей модели. Если метод вернет FALSE, удаление не произойдет и метод <strong>afterDelete()</strong> выполнен не будет.</p>

<p> </p>

<p><strong>protected function beforeInsert()</strong></p>

<p style="text-align:justify;">Выполняется перед сохранением нового объекта. По умолчанию метод возвращает TRUE, но Вы можете переопределить его для выполнения неких действий, спецефичных для Вашей модели. Если метод вернет FALSE, добавления объекта в БД не произойдет и метод <strong>afterInsert()</strong> выполнен не будет.</p>

<p> </p>

<p><strong>protected function beforeSave($data)</strong></p>

<p style="text-align:justify;">Выполняется перед сохранением объекта независимо от того, есть соотвествующая запись в БД или нет. По умолчанию метод возвращает TRUE, но Вы можете переопределить его для выполнения неких действий, спецефичных для Вашей модели. Если метод вернет FALSE, сохранение не произойдет и метод <strong>afterSave()</strong> выполнен не будет.</p>

<p> </p>

<p><strong>protected function beforeSetData($data)</strong></p>

<p style="text-align:justify;">Выполняется перед заполнением модели данными методом <strong>setData()</strong>; По умолчанию метод возвращает TRUE, но Вы можете переопределить его для выполнения неких действий, спецефичных для Вашей модели. Если метод вернет FALSE, заполнение данными не произойдет и метод <strong>afterSetData()</strong> выполнен не будет.</p>

<p> </p>

<p><strong>protected function beforeUpdate()</strong></p>

<p style="text-align:justify;">Выполняется перед сохранением существующего объекта. По умолчанию метод возвращает TRUE, но Вы можете переопределить его для выполнения неких действий, спецефичных для Вашей модели. Если метод вернет FALSE, сохранение объекта не произойдет и метод <strong>afterUpdate()</strong> выполнен не будет.</p>

<p> </p>

<p><strong>static count($conditions) </strong></p>

<p>Возвращает количество элементов, соотвествующих условию, переданному в параметре $conditions</p>

<p> </p>

<p><strong>dec($pair = array(), $conditions = '')</strong></p>

<p>Декремент. Уменьшает заданные поля на заданные значения. Запись в БД производится сразу при вызове метода.</p>

<p> </p>

<p><strong>delete()</strong></p>

<p>Удалить данных объект из базы данных</p>

<p> </p>

<p><strong>protected static fetch($conditions = array(), $limit = 0, $offset = 0, $order = '')</strong></p>

<p style="text-align:justify;">Защищенный Метод. Он осуществляет выборку объектов из БД. Возвращает массив экземпляров класса, если объект существует или null если ничего не найдено. Публичные методы <strong>getById()</strong>, <strong>fetchOne()</strong> и <strong>find()</strong> являются по сути обертками для этого метода и делегируют запрос ему.</p>

<p style="text-align:justify;">Хоть этот метод и нельзя вызвать извне, но его полезно переопределять для создания выборок, специфичных для конкретной модели. В этом случае методы getById(), fetchOne() и find() будут делегировать запрос переопределенному методу, даже если сами они и не переопределены.</p>

<p> </p>

<p><strong>static fetchOne($conditions, $order = null)</strong></p>

<p>Получить объект по заданным условиям. Возвращает экземпляр класса, если объект существует или null в противном случае.</p>

<p>где:</p>

<p><strong>$conditions</strong> - условия<br /><strong>$order</strong> - условие для сортировки - поле или поля чере запятую. В последнем случае для каждого поля можено указать порядок сортировки (ASC или DESC). Также может принимать массив условий, элементами которого являются массивы, ключи которых - поля, а значения - порядок сортировки.</p>

<p>Получаемый объект кешируется на время выполнения аналогично методу <strong>getById()</strong>.</p>

<p> </p>

<p><strong>static find($conditions, $limit = 0, $offset = 0, $order = '')</strong></p>

<p>Найти объекты по заданным условиям. Возвращает массив экземпляров класса, если объект существует или null если ничего не найдено.</p>

<p>где:</p>

<p><strong>$conditions</strong> - условия<br /><strong>$limit</strong> - Количество выбираемых элементов<br /><strong>$offset</strong> - Смещение выборки от начально элемента<br /><strong>$order</strong> - условие для сортировки - поле или поля чере запятую. В последнем случае для каждого поля можено указать порядок сортировки (ASC или DESC). Также может принимать массив условий, элементами которого являются массивы, ключи которых - поля, а значения - порядок сортировки.</p>

<p> </p>

<p><strong>static getById($pk, $staticCache = true)</strong></p>

<p style="text-align:justify;">Получить объект по первичному ключу. Возвращает экземпляр класса, если объект существует или null в противном случае. Если параметр $staticCache - true, то результат работы кешируется на время жизни скрипта. Т.е. если для конкретной модели вызывать несколько раз этот метод с одним и тем же параметром, запрос к БД выполняется только один раз, потом возвращается ссылка на объект из кеша. При сохранении/удалении объекта кеш сбрасывается.</p>

<p>Кеширование нужно отключить, если используется несколько объектов с одним первичным ключом и разными наборами опций.</p>

<p> </p>

<p><strong>static getDbConfig()</strong></p>

<p>Возвращает настройки БД для данного объекта в виде массива.</p>

<p> </p>

<p><strong>static fields()</strong></p>

<p>Возвращает массив полей, описанных в модели, с типами данных и связей.</p>

<p> </p>

<p><strong>getId()</strong></p>

<p>Возвращает значение первичного ключа объекта</p>

<p> </p>

<p><strong>getValidators($field = null) </strong></p>

<p>Возвращает валидаторы для указанного поля объекта или все валидаторы объекта. Валидаторы используются для проверки данных объекта при его сохранении.</p>

<p> </p>

<p><strong>inc($pair = array(), $conditions = '')</strong></p>

<p>Инкремент. Увеличивает заданные поля на заданные значения. Запись в БД производится сразу при вызове метода.</p>

<p> </p>

<p><strong>static primaryKey()</strong></p>

<p>Возвращает название поля первичного ключа модели.</p>

<p> </p>

<p><strong>rawValue($column)</strong></p>

<p>Возвращает значение поля $column «как есть». Никакие преобразования не производятся. Для связей "ко многим" связанные объекты из БД не выбираются, возвращается массив значений первичного ключа связанных объектов (массив их id)</p>

<p> </p>

<p><strong>save($data = null)</strong></p>

<p>Сохранить текущий объект. качестве аргумента можно передать массив (ключ-значение). В этом случае перед сохранением поля объекта будут перезаписаны данными из массива.</p>

<p> </p>

<p><strong>setData($data, $safe=true)</strong></p>

<p>Безопасное заполнение модели данными. Принимает следующие параметры:</p>

<p><strong>$data</strong> - массив данных в формате имя_поля =&gt; значение. Например $_POST.<br /><strong>$safe </strong>- Если параметр установлен в TRUE и при этом действие происходит не в панели управления и пользователь не администратор ($usr['isadmin'] != TRUE), то при попытке передать в массиве $data имя_поля, которое в описании в моделе имеет элемент 'safe' =&gt; TRUE, будет выброшено исключение.</p>

<p style="text-align:justify;">Данные при установке значений проходят проверку на соотвествие типам данных. Вам не нужно заботиться о рутинной проверке вводимых пользователями данных.</p>

<p> </p>

<p><strong>setValidator($field, $validators)</strong></p>

<p>Устанавливает валидатор(ы) для заданного поля объекта</p>

<p> </p>

<p><strong>toArray()</strong></p>

<p>Возвращает поля текущего объекта в виде массива.</p>

<p> </p>

<p><strong>static updateRows($data, $condition = '')</strong></p>

<p>Обновить все записи в таблице, соотвествующие условию $condition.</p>

<p>Принимает следующие параметры:<br /><strong>$data</strong> - массив данных в формате имя_поля =&gt; значение.<br /><strong>$condition </strong>- Любое допустимое условие для выборки</p>

<p> </p>

<p><strong>validate($fields = null)</strong></p>

<p>Проверяет модель на наличие ошибок. Если в качестве параметра передан массив, то проверяет только те поля, которые перечислены в массиве. Проверка осуществляется при помощи установленных для данного объекта валидаторов. Также поля проверяются на соответствие типу данных.</p>

<p>Этот метод полезно переопределять для создания проверок спецефичных для конкретной модели</p>

<p> </p>

<h4>Получение объектов</h4>

<p>Получение объектов осуществляется описанными выше методами <strong>getById()</strong>, <strong>fetchOne()</strong> и <strong>find()</strong></p>

<p> </p>

<h4>Условия для выборки</h4>

<p>Условия для выборки передаются через параметр <strong>$conditions</strong> методов<strong> fetchOne()</strong> и <strong>find()</strong>.</p>

<p>Рассмотрим синтаксис этого параметра:</p>

<p>Он может быть:</p>

<p><strong>Cтрока, соотвествующая SQL - синтаксису WHERE</strong></p>

<p>Например:</p>

<pre class="brush:php;">
$productArr = Product::find('id &gt; 2 AND id_rasdel = 2');</pre>

<p style="text-align:justify;">В этом случае синтаксис зависит от типа БД и применять его стоит только в крайнем случае, т.к. может ограничить переносимость скрипта между разными типами БД. К тому же это не безопасно. Тут надо проверять передаваемые условия, чтобы исключить возможность sql инъекций, экранировать строковые значения.</p>

<p style="text-align:justify;"> </p>

<p><strong>Массив </strong></p>

<p><strong>Элемент массива строка</strong></p>

<p><em><strong>1. строка соотвествует формату &lt;колонка&gt; &lt;оператор (&lt;, &gt;, =, больше или равно, меньше или равно, не равно)&gt; &lt;значение&gt;</strong></em></p>

<p>Например:</p>

<pre class="brush:php;">
$products = Product::find(array('id &gt;= 2', 'id &lt; 5'));</pre>

<p>Строковые значения в этом случае экранируются автоматически.</p>

<p>Будьте внимательны! Выборка</p>

<pre class="brush:php;">
$this-&gt;item = Unittest_Model_Item::find(array('uti_id=1 OR uti_id=3'));</pre>

<p>будет интерпретирована как</p>

<pre class="brush:php;">
SELECT `unittest_item`.* FROM `unittest_item` WHERE (uti_id = '1 OR uti_id=3')</pre>

<p>а это, скорее всего, не то чего Вы ожидали. Для правильной работы подобных запросов используйте массив массивов в качестве параметра</p>

<p> </p>

<p><em><strong>2. Строка не соответствует указанному формату </strong></em></p>

<p>Например:</p>

<pre class="brush:php;">
$products = Product::find(array('id IN(1,2,5)'));</pre>

<p>В этом случае условие принимается 'как есть' и добавляется к предложению WHERE, по аналогии с Cтрока, соотвествующая SQL - синтаксису WHERE Элементы массива добавляются к предложению WHERE с добавлением AND между ними.</p>

<p>Нарпимер:</p>

<pre class="brush:php;">
$products = Product::find(array('id &gt;= 2', 'id &lt; 5'));</pre>

<p>Соотвествует условию:</p>

<pre class="brush:php;">
WHERE katalogshop_sale.id &gt;= 2 AND katalogshop_sale.id &lt; 5</pre>

<p> </p>

<p><strong>Элемент массива - массив</strong></p>

<p>Массив может состоять из 4-х элементов, из которых первые два являются обязательными.</p>

<p>Нарпимер:</p>

<pre class="brush:php;">
$products = Product::find(array(
    array('id', '2'),
    array('id', '5', '&lt;','OR')
));
</pre>

<p>Расмотрим элементы массива:</p>

<p>1-ый - поле в БД<br />
2-ой - значение<br />
3-ий - операнд (&lt; &gt; = больше или равно, меньше или равно, не равно и т.п.), если не указано, то принимается равным '='<br />
4-ый - Условие объединения (AND ИЛИ OR), если не указано, то принимается равным 'AND'</p>

<p>Так приведенный пример соотвествует условию:</p>

<pre class="brush:php;">
WHERE katalogshop_sale.id = 2 OR katalogshop_sale.id &lt; 5</pre>

<p>Если перый элемент массива равен 'RAW' или 'SQL' то к предложению WHERE добавляется второй элемент (значение) «Как есть», по аналогии с <strong><em>Cтрока, соотвествующая SQL - синтаксису WHERE </em></strong></p>

<p><strong>Значение может быть массивом</strong></p>

<p>Например:</p>

<pre class="brush:php;">
$cats = array(1, 2, 4);
$prod = Product::find(array(
    array('id_rasdel', $cats)
));
</pre>

<p>Будет соответствовать:</p>

<pre class="brush:php;">
WHERE katalogshop_sale.id_rasdel IN (1,2,4);</pre>

<p>а</p>

<pre class="brush:php;">
$cats = array(1, 2, 4);
$prod = Product::find(array(
    array('id_rasdel', $cats, '&lt;&gt;')
));
</pre>

<p>Будет соответствовать условию:</p>

<pre class="brush:php;">
WHERE katalogshop_sale.id_rasdel NOT IN (1,2,4);
</pre>

<p>Строковые значения в переданном массиве экранируются.</p>

<p><strong>Значение может быть NULL</strong></p>

<p>Например:</p>

<pre class="brush:php;">
$prod = Product::find(array(
    array('id_rasdel', null)
));
</pre>

<p>Будет соответствовать:</p>

<pre class="brush:php;">
WHERE katalogshop_sale.id_rasdel IS NULL;
</pre>

<p>а</p>

<pre class="brush:php;">
$prod = Product::find(array(
    array('id_rasdel', null, '&lt;&gt;')
));

Будет соответствовать условию:
</pre>

<pre class="brush:php;">
WHERE katalogshop_sale.id_rasdel IS NOT NULL; </pre>

<p> </p>

<p><strong>Построение LIKE условий</strong></p>

<p>Если значение содержит '*', то в предложение WHERE будет добавлено LIKE</p>

<p>Например:</p>

<pre class="brush:php;">
$prod = Product::find(array(
    array('name', '*водонагреватель*')
));
</pre>

<p>Будет соответствовать условию:</p>

<pre class="brush:php;">
WHERE katalogshop_sale.name LIKE '%водонагреватель%';
</pre>

<p>Так, к примеру для MySql <strong>'*'</strong> заменяется на <strong>'%'</strong></p>

<p>Строковые значения экранируются.</p>

<p> </p>

<p> </p>

<h4>Валидаторы. Проверка объектов.</h4>

<p>Как уже отмечалось ранее, при сохранении объекта, его данные проходят проверку на соответствие типу данных, указанному в описании поля.</p>

<p>Дополнительную проверку данных можно обеспечить при помощи валидаторов.</p>

<p>Поддерживается 2 типа валидаторов:</p>

<p> </p>

<p><strong>Строковые валидаторы </strong></p>

<p style="text-align:justify;">В качестве строки выступает название типа данных: <strong>int, integer, bool, boolean, double, float, isnull, notnull, empty, notempty</strong>. Последние 4 - не являются типами данных и осуществляют проверку на соотвествие значения 'NULL' и на пустое значение.</p>

<p> </p>

<p><strong>Callback функции </strong></p>

<p>В качестве валидатора можно передать функцию. Она должна по результатом проверки возвращать 'true' или строку с описанием ошибки.</p>

<p><em>Передача имени функции</em></p>

<p>Пример:</p>

<pre class="brush:php;">
function myFunction($value){
// some validation
return true;
}
$prod = Product::getById(2);
$prod-&gt;setValidator('description', 'myFunction');
</pre>

<p> </p>

<p><em>Использование анонимных функций </em></p>

<p>Пример:</p>

<pre class="brush:php;">
$prod-&gt;setValidator('description', function($value){
    if(mb_strlen($value) &gt; 30)  return true;
    return "Описание слишком короткое";
});
</pre>

<p> </p>

<p><em>Использование методов классов </em></p>

<p>Пример:</p>

<pre class="brush:php;">
class MyClass{
    public static function test($value)    {
        // some validation
        return true;
    }
}
$prod-&gt;setValidator('description', array('MyClass', 'test'));
</pre>

<p>Для нестатичного метода класса определение валидатора схоже с примером выше, с той разницей, что перед установкой валидатора нужно создать экземпляр класса и потом уже создать массив:</p>

<pre class="brush:php;">
class MyClass {
    public function myMethod($value){
        // some validation
        return true;
    }
}
$object = new MyClass;
$prod-&gt;setValidator('description', array($object, 'myMethod'));
</pre>

<p>И, наконец, Вы можете определить в своем классе магический метод _invoke(). В этом случае в качестве валидатора просто передайте экземпляр класса.</p>

<pre class="brush:php;">
class MyClass{
    public function __invoke($value) {
        // some validation
        return true;
    }
}

$object = new MyClass();
$prod-&gt;setValidator('description', $object);
</pre>

<p> </p>

<p><strong>Установка валидаторов </strong></p>

<p>Валидаторы можно установить на стадии проектирования модели или в период выполнения в контроллере.</p>

<p>Для установки валидатора в классе модели следует переопределить метод <strong>validators()</strong>. Например:</p>

<pre class="brush:php;">
protected function validators() {
    return array(
        array('specialization,birthdate,city,category,staff,skills,education', 'required'),
        array('staff', function ($value) {
            // Сделать невозможным указание одновременно уровней в штатном расписании «Стажер» c любым другим уровнем
            if(!empty($value) &amp;&amp; in_array(5, $value) &amp;&amp; count($value) &gt; 1) {
                return 'Нельзя указать «Стажер» одновременно с другими уровнями в штатном расписании';
            }
            $ret = (count($value) &lt; 3) ? true : 'Можно использовать не более двух уровней в штатном расписании';

            return $ret;
        }),
    );
}</pre>

<p> </p>

<p style="text-align:justify;">Во время выполнения установить валидатор для поля объекта можно методом <strong>setValidator($field, $validators)</strong> Он принимает в качестве параметров имя поля и валидатор любого из перечисленных типов.</p>

<p>Например:</p>

<pre class="brush:php;">
$prod = Product::getById(2);
$prod-&gt;setValidator('description', 'notempty');
$prod-&gt;setValidator('description', function($value){
    if(mb_strlen($value) &gt; 30)  return true;
    return "Описание слишком короткое";
});
</pre>

<p> </p>

<p><strong>Получение списка валидаторов </strong></p>

<p>получить валидаторы можно методом <strong>getValidators($field = null)</strong> Он возвращает массив валидаторов, установленных для заданного поля или все валидаторы объекта, если параметр опущен.</p>

<p> </p>

<h4>Сеттеры и Геттеры</h4>

<p style="text-align:justify;">Как и указывалось выше, доступ к полям записи в БД, представленной объектом производится через его свойства. Однако Вы можете переопределить стандартное поведение для некоторых полей или даже добавить объекту новые свойства, не привязанные к полям в БД.</p>

<p style="text-align:justify;">Делается это при помощи волшебных методов - сеттеров и геттеров.</p>

<p style="text-align:justify;">Например вы в классе модели можете добавить новое динамическое поле:</p>

<pre class="brush:php;">
setMyField($val){
    $this-&gt;_myField = $val;
}

getMyField(){
    return $val;
}</pre>

<p style="text-align:justify;">Как видим формат имени метода: <strong>set&lt;имя_поля_с_большой_буквы&gt;</strong>. Префикс «set» используется для сеттера, а «get» - для геттера.</p>

<p style="text-align:justify;">После этого мы можем обращаться к этим полям:</p>

<pre class="brush:php;">
$object = module_model_Object::getById(2);

$object-&gt;myField = 15;
echo $object-&gt;myField;</pre>

<p style="text-align:justify;">Данный пример очень простой. Вы можете создать более сложную логику для своих сеттеров и геттеров. Переопределение сеттеров и геттеров для существующих полей происходит аналогично. Просто создайте метод с названием <strong>set&lt;имя_существующего_поля_с_большой_буквы&gt;</strong>.</p>

<p style="text-align:justify;">Обратите внимание на то, что <strong>сеттер должен принимать значение</strong>.</p>
]]></description>
			<pubDate>Tue, 13 May 2014 07:42:00 +0300</pubDate>
			<link><![CDATA[https://lily-software.com/free-scripts/cotonti-lib/som]]></link>
		</item>
		<item>
			<title>Loader. Загрузчик</title>
			<description><![CDATA[<p style="text-align:justify;">Этот компонент <strong>устарел </strong>и используется только для обратной совместимости. Используйте вместо него встроенный в Cotonti автозагрузчик Composer'a.<br />
<br />
Класс <strong>«Loader»</strong>, объявленный в файле «Loader.php» предназначен для автоматической загрузки описаний классов и интерфейсов. Автозагрузка происходит в момент первого обращения к классу и Вам не нужно беспокоиться о том, подключили Вы php-файл, содержащий описание класса или нет.</p>

<p>Для регистрации автозагрузчика в стэке <strong>__autoload</strong> служит статический метод <strong>register()</strong>. Вызывается так:</p>

<pre class="brush:php;">
// Автозагрузка
require_once './lib/Loader.php';
Loader::register();</pre>

<p style="text-align:justify;">Регистрация автозагрузчика происходит в плагине cotonti-lib, так что Вам не нужно заботиться о подключении автозагрузчика в своих расширениях.</p>

<p style="text-align:justify;">Метод регистрирует автозагрузчик только один раз. По этому даже если Вы его подключаете явно, ничего плохого не случится.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;">Как происходит автозагрузка:</p>

<p style="text-align:justify;">Строка, задающая класс, согласно стандарта кодирования <strong>psr-0 </strong>(<a href="https://lily-software.com/go.php?https://gist.github.com/Thinkscape/1234504">https://gist.github.com/Thinkscape/1234504</a>)<strong>, </strong> преобразуется в относительный путь посредством замены знаков подчеркивания разделителями директорий, используемыми в вашей ОС, и добавления расширения «.php». Например, для класса «files_model_File» на Windows будет использоваться путь «files\model\File.php».</p>

<p style="text-align:justify;">Затем полученный файл ищется в папках «modules», «plugins», «lib» и папках заданных в настройке конфигурации include_path. Будет загружен первый встретившийся файл.</p>

<p style="text-align:justify;">Так, если у Вас установлен <a href="https://lily-software.com/sozdanie-internet-sajtov/free-scripts/cotonti-files">модуль Файлов - «Files»</a>, то при первом обращении к упомянотому выше классу  «files_model_File» будет загружен файл «modules/files/model/File.php»</p>
]]></description>
			<pubDate>Tue, 06 May 2014 22:11:00 +0300</pubDate>
			<link><![CDATA[https://lily-software.com/free-scripts/cotonti-lib/loader]]></link>
		</item>
		<item>
			<title>Cotonti. Alpha Filters</title>
			<description><![CDATA[<p style="text-align:justify;"><em>тип:</em> <strong>плагин</strong><br />
<em>Версия плагина:</em> <strong>5.0</strong><br />
<em>Совместимость:</em> <strong>Siena</strong></p>

<p> </p>

<p>Авторы: <a href="https://www.cotonti.com/users/esclkm" target="_blank" rel="nofollow noreferrer noopener">esclkm</a>, <a href="https://lily-software.com/users/Alex">Kalnov Alexey</a>, <a href="https://www.cotonti.com" target="_blank" rel="nofollow noreferrer noopener">Cotonti Team</a></p>

<p>Github: <a href="https://github.com/Alex300/cotonti-alphafilters" target="_blank" rel="nofollow noreferrer noopener">https://github.com/Alex300/cotonti-alphafilters</a></p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><strong>Описание:</strong></p>

<p>Плагин «Alpha Filters» предоставляет гибкие возможности по фильтрации списков страниц и пользователей по буквам, цифрам или комбинациям символов. Вы можете назначить свои стили элементам фильтра (тег: «span»).</p>

<p> </p>

<h2>Установка</h2>

<ul>
	<li>Распаковать плагин в папку <strong>plugins</strong></li>
	<li>Установить плагин в панели администратора</li>
	<li>Add tags to <strong>page.list.tpl</strong> and/or <strong>users.tpl</strong></li>
	<li>При необходимости можно установить свои настройки</li>
</ul>

<p> </p>

<p>Пример для шаблона users.tpl:</p>

<pre class="brush:xml;">
&lt;!-- IF {PHP|cot_plugin_active('alphafilters')} AND {PHP.cfg.plugin.alphafilters.turnOnUsers} == 1 --&gt;
&lt;div class="margin10 small text-center"&gt;
     {PHP.L.alphafilters_byFirstLetter}:
     {ALPHAFILTER_1} {ALPHAFILTER_2}
     &lt;!-- IF {ALPHAFILTER_3} --&gt;&lt;br /&gt;{ALPHAFILTER_3}&lt;!-- ENDIF --&gt;
     {ALPHAFILTER_RESET}
&lt;/div&gt;
&lt;!-- ENDIF --&gt;</pre>

<p> </p>

<p>Пример плагина:</p>

<p><img alt="" src="https://user-images.githubusercontent.com/1021886/235350669-1ae221e6-5489-4fda-ae8c-27470b96bbbf.png" /></p>
]]></description>
			<pubDate>Thu, 13 Feb 2014 12:17:00 +0300</pubDate>
			<link><![CDATA[https://lily-software.com/free-scripts/cotonti-alpha-filters]]></link>
		</item>
		<item>
			<title>7. Экстраполя</title>
			<description><![CDATA[<p style="text-align:justify;">Модуль <strong>интернет магазина</strong> для Cotonti позволяет добавлять и использовать дополнительные экстраполя <strong>товаров</strong>, <strong>информации о пользователе</strong> и <strong>заказов</strong>.</p>

<p style="text-align:justify;">На странице настроек магазина ( <strong>&lt;ваш домен&gt;/admin/config?n=edit&amp;o=module&amp;p=shop</strong> ) Вы видите какие поля создаются для работы модуля.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><strong>Экстраполя товаров</strong>:</p>

<p style="text-align:justify;">При сохранении заказа вместе с заказом сохраняются поля "<strong>Артикул</strong>" и "<strong>Не применять скидку по купону</strong>". Но вы можете добавить свои поля к товару ( <strong>cot_pages - Модуль Pages</strong> ). Чтобы они сохранялись вместе с заказом, необходимо добавить поля с такими же названиями в<strong> cot_shop_order_items - Модуль «Shop»</strong>.</p>

<p style="text-align:justify;">Если имена экстраполей для таблиц <strong>cot_pages</strong> и <strong>cot_shop_order_items</strong> совпадают, то их значения сохраняются при формировании заказа автоматически.</p>

<p style="text-align:justify;"><br /><strong>Экстраполя пользователя</strong>:</p>

<p style="text-align:justify;">Модуль использует данные профиля пользователя (экстраполя добавляются <strong>cot_users - Модуль Users</strong>) и адреса доставки пользователя (<strong>cot_shop_userinfo - Модуль «Shop»</strong>).</p>

<p style="text-align:justify;">По аналогии с товарами для сохранения дополнительных данных с заказом, нужно добавить экстраполя в <strong>cot_shop_order_userinfo - Модуль «Shop»</strong></p>

<p style="text-align:justify;">При совпадении названий полей они будут сохранены с заказом ("<strong>Информация о покупателе</strong>" или "<strong>Адрес доставки</strong>" соотвественно).</p>

<p style="text-align:justify;"><br /><strong>Экстраполя заказа:</strong></p>

<p style="text-align:justify;">Добавляются в <strong>cot_shop_orders - Модуль «Shop»</strong>. Позволяют пользователю или администратору магазина сохранять с заказом дополнительную информацию.</p>

<p style="text-align:justify;">Для добавления этих полей на страницу корзины, их следует добавить в шаблон <strong>shop.cart.tpl</strong> в форму оформления заказа. Она в этом файле помечена соотвествующим комментарием.</p>

<p style="text-align:justify;">Теги для вставки полей в эту форму имеют формат: <strong>{ORDER_FORM_XXXXX}</strong> и <strong>{ORDER_FORM_XXXXX_TITLE}</strong></p>

<p style="text-align:justify;">Значения этих полей можно вывести в списке заказов, при просмотре заказа, или в письме уведомлении о заказе. Для этого нужно их теги добавить в соотвествующий шаблон. Названия тегов можно получить на странице редактирования экстраполя из всплывающей подсказки к названию поля.</p>

<p style="text-align:justify;">Администратор в панели управления при просмотре/редактировании заказа может изменять значения этих экстраполей. Это может быть полезно, если, например, администратору нужно вести какие-то заметки к заказу.</p>

<p style="text-align:justify;">Теги для вставки редактируемых экстраполей в шаблоне <strong>shop.admin.order.tpl</strong> аналогичны тегам для шаблона shop.cart.tpl.</p>
]]></description>
			<pubDate>Wed, 14 Aug 2013 17:35:00 +0300</pubDate>
			<link><![CDATA[https://lily-software.com/free-scripts/cotonti-shop/shop-documentation/ekstrapolya]]></link>
		</item>
		<item>
			<title>6. Производители</title>
			<description><![CDATA[<p style="text-align:justify;">Для добавления производителей в панели управления сайтом в разделе: "<strong>Управление сайтом / Расширения / Pages / Структура</strong>" создайте категорию для производителей. Она не должна быть вложенной в магазин. Создайте ее отдельно. Укажите ее код в настройках модуля "Магазин".</p>

<p style="text-align:justify;">Созданные в ней страницы и будут страницами производителей.</p>

<p style="text-align:justify;">Страницы производителей могут содержать краткую или подробную информацию об изготовителе товаров, его контактную информацию, информацию о гарантиях, предоставляемых производителем и т.д.</p>

<p style="text-align:justify;">Страницы производителей привязываются к товарам, что избавляет Вас от ввода однотипных данных при каждом добавлении товара. Кроме того, заполненное поле "<strong>Производитель</strong>" у товара позволяет организовать фильтр по этому полю и поиск всех товаров заданного производителя.</p>

<p style="text-align:justify;"><em>Замечение: поиск и фильтр реализуются отдельными плагинами, такими как "List Filter"</em></p>

<p style="text-align:justify;">В шаблон страницы <strong>page.shop.tpl</strong> вывести производителя можно напрмер так:</p>

<pre class="brush:xml;">
&lt;!-- manufacturers --&gt;
&lt;!-- IF {PAGE_PROD_MANUFACTURER_NAME} != '' --&gt;
&lt;p&gt;
    &lt;strong&gt;{PHP.L.shop.manufacturer}:&lt;/strong&gt;
    &lt;a href="https://lily-software.com/{PAGE_PROD_MANUFACTURER_URL}"&gt;{PAGE_PROD_MANUFACTURER_NAME}&lt;/a&gt;
&lt;/p&gt;
&lt;!-- ENDIF --&gt;
&lt;!-- /manufacturers --&gt;</pre>

<p style="text-align:justify;">Если для Вашего интернет магазина страницы роизводителей не нужны - то не создавайте их. Их наличие не обязательно для сработы модуля.</p>

<p style="text-align:justify;"> </p>
]]></description>
			<pubDate>Sun, 21 Jul 2013 11:52:00 +0300</pubDate>
			<link><![CDATA[https://lily-software.com/free-scripts/cotonti-shop/shop-documentation/proizvoditeli]]></link>
		</item>
		<item>
			<title>4. Валюта</title>
			<description><![CDATA[<p style="text-align:justify;">Модуль "Магазин" является мультивалютным. Вы можете устанавливать цены на товары в разных валютах. Покупатели могут просматривать цены тоже в разных валютах. Цена сначала конвертируется в алюту продавца, а затем уже в валюту, выбранную пользователем.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><strong>Автоматический курс валют</strong></p>

<p style="text-align:justify;">Модуль автоматически конвертирует валюты. По умолчанию используется курс по Европейскому Центробанку. Возможно установить свой конвертер. Модуль может сконвертировать валюту, только если такая возможность есть у конвертера.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><strong>Создание и редактирование валют</strong></p>

<p style="text-align:justify;">Для редактирования валют пройдите в панели администратора: "<strong>Управление сайтом / Расширения / Shop / Администрирование /  Валюта</strong>".</p>

<p style="text-align:justify;">Если вы хотите установить свой обменный курс для валюты установите в поле "<strong>Обменный курс</strong>" значение, отличное от нуля. В этом случае при преобразовании валюты будет учитываться именно это значение. Значение следует устанавливать относительно основной валюты.</p>

<p style="text-align:justify;">Вы можете установить формат отображения для выбранной валюты и ее символ.</p>

<p style="text-align:justify;">Также Вы можете создавать свои собственные валюты, например "Бонус за репутацию", "Клики", "Золото" и т.п.<br />
Вы даже можете установить свою валюту как "Основную" для магазина и назначить для других других валют курс относительно ее.</p>
]]></description>
			<pubDate>Mon, 15 Jul 2013 15:34:00 +0300</pubDate>
			<link><![CDATA[https://lily-software.com/free-scripts/cotonti-shop/shop-documentation/valyuta]]></link>
		</item>
		<item>
			<title>5. Налогоги и правила расчета цен</title>
			<description><![CDATA[<p style="text-align:justify;">Вы можете создавать свои правила расчета, которые будут учитываться при формировании окончательной цены на товар и стоимости заказа. Это могут быть налоги, наценки и скидки, которые можно назначать разным группам покупателей, например оптовикам, своим сотрудникам и т.п. Они могут применяться для всех товаров или для отдельных категорий, быть постоянными или временными.</p>

<p style="text-align:justify;">Для добавления нового правила, в панели администратора "<strong>Управление сайтом / Расширения / Shop / Администрирование / Налоги и правила расчета</strong>" нажмите "<strong>Добавить</strong>".</p>

<p style="text-align:justify;">Заполните необходимые поля и сохраните.</p>

<p style="text-align:justify;">Рассмотрим некотрые поля подробнее:</p>

<p style="text-align:justify;"><br /><strong>Вид расчета</strong></p>

<p style="text-align:justify;">Указывается тип расчета.<br />
Возможные варианты:<br />
- <em>Постоянная наценка/скидка (размер прибыли)</em><br />
- <em>Налог на товар</em><br />
- <em>Изменение цены до или после удержания налога</em><br />
- <em>Налог на стоимость заказа</em><br />
- <em>Изменение цены до или после удержания налога на стоимость заказа</em></p>

<p style="text-align:justify;">'<em>Постоянная наценка/скидка (размер прибыли)</em>' применяется к цене (себестоимости) при расчете основной цены товара. Остальные правила применяются к основной цене.</p>

<p style="text-align:justify;">При установке налога, посоветуйтесь с бухгалтером, если Вы сомневаетесь в правильности выбора. Как правило используется налог на товар.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;">"<strong>Арифметическое действие</strong>" и "<strong>Значение</strong>" устанавливают величину, на которую изменяется цена. Например<br />
Арифметическое действие: "<strong>+%</strong>"<br />
Значение: "<strong>20</strong>"<br />
Означают, что цену нужно увеличить на 20 процентов.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;">Поля "<strong>Категории</strong>", "<strong>Группы</strong>" и "<strong>Страны</strong>" позволяют установить данное правило для соотвествующей категории товаров, группы покупателей (пользователей) и стран.</p>

<p style="text-align:justify;">"<strong>Опубликовано с</strong>" и "<strong>Опубликовано по</strong>" ограничивают действие правила во времени.</p>

<p style="text-align:justify;">Если какое-то из полей "Категории", "Группы", "Страны", "Опубликовано с" или "Опубликовано по" не заполнено, то соотвествующее ограничение не накладывается.</p>

<p style="text-align:justify;"><br />
"<strong>Опубликовано</strong>". Если стоит "<strong>нет</strong>", то данное правило системой не применяется</p>

<p style="text-align:justify;"> </p>
]]></description>
			<pubDate>Mon, 15 Jul 2013 15:14:00 +0300</pubDate>
			<link><![CDATA[https://lily-software.com/free-scripts/cotonti-shop/shop-documentation/nalogogi-i-pravila-rascheta-cen]]></link>
		</item>
		<item>
			<title>Cotonti. Region-City ajax selector</title>
			<description><![CDATA[<p style="text-align:justify;">Плагин для Выбора страны, региона и города.</p>

<p style="text-align:justify;"><em>тип:</em> <strong>плагин</strong><br />
<em>Версия плагина:</em> <strong>1.0.7</strong><br />
<em>Совместимость:</em> <strong>Siena</strong></p>

<p style="text-align:justify;">GitHub: <a href="https://lily-software.com/go.php?https://github.com/Alex300/RegionCity/" target="_blank" rel="noreferrer noopener">https://github.com/Alex300/RegionCity/</a></p>

<p style="text-align:justify;">Плагин позволяет добавить на Ваш сайт на Cotonti возможность выбора страны, региона и города из выпадающих списков при помощи Ajax.</p>

<p style="text-align:justify;">Это может быть полезным для доски объявлений или интернет магазинов т.к. пользователь не вводит название города самостоятельно, а выбирает из предложенного плагином списка, что исключает неправильный ввод.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><strong><u>Системные требования и ограничения</u>:</strong></p>

<ul>
	<li style="text-align:justify;">  Наличие на Вашем сайте установленной <a href="https://lily-software.com/sozdanie-internet-sajtov/free-scripts/cotonti-lib">библиотеки Cotonti Lib</a> <strong>версии 2.0.x</strong></li>
</ul>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;">Плагин выводит теги для выбора страны, региона и города в соотвествии со своими настройками на странице регистрации нового пользователя, в профиле и странице редактирования пользователя. А также выводит теги для фильтров на странице списка пользователей.</p>

<p style="text-align:justify;">Вы можете использовать этот плагин из своих модулей и плагинов. Для этого используется функция генерерующая теги выбора страны, региона и города:</p>

<pre class="brush:php;">
function rec_select_location($counName = 'country', $regName = 'region', $cityName = 'city', $country = '', $region = 0, $city = 0);</pre>

<p style="text-align:justify;">В качестве первых трех параметров принимаются названия полей для страны, региона и города соотвественно. Или массивы, первым элементом которого является имя элемента формы, а вторым имя тега, который его выводит.</p>

<p style="text-align:justify;">Четвертый, пятый и шестой параметры - это код страны и id региона и города.</p>

<p> </p>

<p>Пример использования:</p>

<pre class="brush:php;">
$t-&gt;assign(rec_select_location(
    array('recf_country', 'USERS_TOP_FILTERS_COUNTRY'),
    array('recf_region',  'USERS_TOP_FILTERS_REGION'),
    array('recf_city',    'USERS_TOP_FILTERS_CITY'),
    'ru',  4052, 4079)
);</pre>

<p style="text-align:justify;">Сгенерированные этой функции элементы передадут не только <strong>ID</strong> города и региона, но и их названия. Названия передаются в полях "<strong>&lt;имя_поля&gt;_name</strong>". Например, форма из примера выше передаст id региона в поле "<strong>recf_region</strong>" а его название в поле "<strong>recf_region_name</strong>". Id и название города будут переданы соотвественно в полях: "<strong>recf_city</strong>" и "<strong>recf_city_nam</strong>e"</p>

<p> </p>

<p>Также, если на Вашем сайте установлена библиотека <a href="https://lily-software.com/go.php?https://select2.github.io" target="_blank" rel="noreferrer noopener">Select2</a>, Вы можете выводить выбор города одним выпадающим списком с поиском по названию. Для этого используется функция</p>

<pre class="brush:php;">
/**
 * Renders a Select2 city dropdown
 *
 * Select2 must be installed on your site
 * @see http://ivaynberg.github.io/select2/
 *
 * @param string $name Dropdown name
 * @param int array|int $chosen Seleced value (or values array for mutli-select)
 * @param bool $add_empty Allow empty choice
 * @param mixed $attrs Additional attributes as an associative array or a string
 * @param string $custom_rc Custom resource string name
 * @return string
 */
function rec_select2_city($name, $chosen = 0, $add_empty = true, $attrs = array(), $custom_rc = '' )</pre>

<p>Например:</p>

<pre class="brush:php;">
$t-&gt;assign(array(
    //...
    'FORM_CITY' =&gt; rec_select2_city('city', $vacancy-&gt;city),
));</pre>

<p>выводить отдельно выбор страны и региона в этом случае не нужно.</p>

<p> </p>

<p style="text-align:justify;"><strong><u>История изменений:</u></strong></p>

<p style="text-align:justify;"><u>Версия v.1.0.7</u></p>

<ul>
	<li style="text-align:justify;">Совместимость с Cotonti 0.9.25</li>
</ul>

<p style="text-align:justify;"><u>Версия v.1.0.5</u></p>

<ul>
	<li style="text-align:justify;">  Совместимость с Cotonti Lib v.2.0.</li>
</ul>

<p style="text-align:justify;"><u>Версия v.1.0.4</u></p>

<ul>
	<li style="text-align:justify;">  Профили пользователя могут иметь несколько групп полей («Страна», «Регион», «Город»). Например домашний и рабочий адреса.</li>
</ul>

<p style="text-align:justify;"><u>Версия v.1.0.3</u></p>

<ul>
	<li style="text-align:justify;">  Городам добавлено поле 'sort' для сортировки. Сортировка осуществляется по-убыванию. Города с одинаковым значением этого поля сортируются по алфавиту</li>
	<li style="text-align:justify;">Изменены поля таблиц в БД и моделях на более читабельные. (обратите внимание на этот момент при обновлении)</li>
</ul>

<p style="text-align:justify;"><u>Версия v.1.0.2</u></p>

<ul>
	<li style="text-align:justify;">  Виджет rec_select2_city() теперь использует Select2 v.4</li>
</ul>

<p style="text-align:justify;"><u>Версия v.1.0.1</u></p>

<ul>
	<li style="text-align:justify;">  Использование моделей из <a href="http://sozdanie-internet-sajtov/free-scripts/cotonti-lib" rel="nofollow">библиотеки Cotonti Lib</a> вместо собственных. Это сделано в целях унификации API и оптимизации потребления системных рессурсов</li>
	<li style="text-align:justify;">Выпадающий список на основе <strong>Select2</strong> для выбора города с поиском по введенным буквам</li>
</ul>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;">GitHub: <a href="https://lily-software.com/go.php?https://github.com/Alex300/RegionCity/" target="_blank" rel="noreferrer noopener">https://github.com/Alex300/RegionCity/</a></p>
]]></description>
			<pubDate>Sun, 14 Jul 2013 23:11:00 +0300</pubDate>
			<link><![CDATA[https://lily-software.com/free-scripts/cotonti-region-city-ajax-selector]]></link>
		</item>
		<item>
			<title>3. Редактирование товара</title>
			<description><![CDATA[<p style="text-align:justify;">Для облегчения работы по созданию шаблонов добавления / редактирования страниц-товаров в модуль "Магазин" для Cotonti включены образцы <a href="https://lily-software.com/go.php?https://github.com/Alex300/cotonti-shop/tree/master/themes/your-theme/modules" target="_blank">https://github.com/Alex300/cotonti-shop/tree/master/themes/your-theme/modules</a></p>

<p style="text-align:justify;"><strong>page.add.shop.tpl</strong> и <strong>page.edit.shop.tpl</strong></p>

<p style="text-align:justify;">в которых форма редактирования товара разбита на вкладки при помощи <em>Twitter bootstrap</em>.</p>

<p style="text-align:justify;">Рассмотрим эти вкладки подробнее:</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><u><strong>Информация / описание</strong></u>.</p>

<p style="text-align:justify;">Эта вкладка содержит стандартные поля редактирования страниц Cotonti.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><strong><u>Стоимость.</u></strong></p>

<p style="text-align:justify;">На этой вкладке задается цена товара.</p>

<p style="text-align:justify;"><a href="http://portal30.ru/public/files/sfs/34/file_391.jpg" title="Редактирование цены"><img alt="Редактирование цены" src="http://portal30.ru/public/files/_thumbs/391/file_391-180x107-crop.jpg" /></a></p>

<p style="text-align:justify;"><strong>"Цена (себестоимость)"</strong> позволяет ввести цену на товар и валюту, в которой указана цена.</p>

<p style="text-align:justify;"><strong>"Основная цена"</strong> и <strong>"Окончательная цена"</strong> будут расчитаны системой автоматически.</p>

<p style="text-align:justify;"><strong>"Основная цена"</strong> - это <strong>"Цена (себестоимость)"</strong> преобразованная в валюту продавца и расчитанная с учетом наценки, если она применяется к данному товару.</p>

<p style="text-align:justify;">Наценки и другие правила расчета цены можно увидеть в панели администратора "<strong>Управление сайтом / Расширения / Shop / Администрирование / Налоги и правила расчета</strong>". Подробнее о них читайте в соответствующем разделе руководства.</p>

<p style="text-align:justify;"><strong>"Окончательная цена"</strong> - это <strong>"Основная цена"</strong> расчитанная со всеми правилами, применимыми к данному товару. Это та цена, которую необходимо оплатить покупателю при заказе данного  товара.</p>

<p style="text-align:justify;"><br /><em><strong>Расчет поля "Цена (себестоимость)" на основе окончательной цены.</strong></em></p>

<p style="text-align:justify;">Вы можете устанавливать окончательную цену на товар (вместо себестоимости). При этом поля "Цена (себестоимость)" и "Основная цена" будут расчитаны системой автоматически с учетом всех правил расчета.</p>

<p style="text-align:justify;">Для этого нужно заполнить поле "Окончательная цена" и отметить "Расчет себестоимости".</p>

<p style="text-align:justify;"><br /><em><strong>Переопределение цены</strong></em></p>

<p style="text-align:justify;">Позволяет назначить временную скидку или наценку на конкретный товар. Вы можете переопределить основную или окончательныу цену выбрав "Переопределение до удержания налога" или "Переопределение окончательной цены" соотвечтвенно.</p>

<p style="text-align:justify;">Если выбрано "Не применять скидку по купону" то при расчете стоимости заказа на данный товар не будет распространяться скидка по купону. Имеет смысл использовать, если цена на товар и так уже указана со скидкой (нарпимер товар участвует в акции), либо если на данный товар скидок нет.</p>

<p style="text-align:justify;"><strong>Дополнительные цены</strong></p>

<p style="text-align:justify;">Позволяют задать стоимоть товара с учетом группу покупателя, а также в зависимости от количества приобретаемого товара. Например для группы пользователей "Оптовик", цена возможно будет ниже, чем для Members.</p>

<p style="text-align:justify;">Обратите внимание, что скидки, которые зависят от группы пользователя Вы можете назначать для всех товаров или для отдельных катерий на странице "Управление сайтом / Расширения / Shop / Администрирование / Налоги и правила расчета"</p>

<p style="text-align:justify;"><strong>Правила расчета цены</strong></p>

<p style="text-align:justify;">Отображают текущие правила (налоги и скидки), применяемые к расчету цены на товар.<br />
Вы можете отключить правила для данного товара, выбрать какое-то одно правило или оставить по-умолчанию</p>

<p style="text-align:justify;"><br /><u><strong>Статус / покупатели</strong></u></p>

<p style="text-align:justify;">На этой вкладке можно установить или увидеть сколько данного товара имеется в наличии, сколько зарезервированно заказами.<br />
Когда товар на складе заканчивается, то в зависимости от настроек магазина, покупателю может быть отказано в покупке данного товара.</p>

<p style="text-align:justify;">Минимальное и максимальное количество для заказа - накладывают ограничения на возможное количество приобретаемого товара.</p>

<p style="text-align:justify;"><strong>Шаг</strong> (по умолчанию 1) позволяет ограничить количество приобретаемого товара только значениями крантыми данному.</p>

<p style="text-align:justify;">"<strong>Разрешить заказывать дробное кол-во</strong>" позволяет заказывать дробное количество товара (Например: 5,5 кг картофеля или 30,6 м2 ламината)</p>

<p style="text-align:justify;"><em><strong>Список покупателей, которые приобрели</strong></em></p>

<p style="text-align:justify;">Появится в следующих версиях. Список покупателей, заказавших этот товар.</p>

<p style="text-align:justify;"><em><strong>Список ожидающих покупателей</strong></em></p>

<p style="text-align:justify;">Список покупетелей, подписавшихся на уведомление о поступлении товара на склад.<br />
Работает, если в настройках магазина указано если товара нет на складе - "Показывать 'Уведомить меня' вместо кнопки 'Добавить в корзину'"</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><u><strong>Габариты / вес</strong></u></p>

<p style="text-align:justify;">На этой вкладке настраиваются габариты, товара, его вес, количество в упаковке и т.п.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><u><strong>Изображения / файла</strong></u></p>

<p style="text-align:justify;">Тут рекомендуется использовать плагин Attachments 2 для добавления изображений товара.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"> </p>
]]></description>
			<pubDate>Sun, 14 Jul 2013 17:13:00 +0300</pubDate>
			<link><![CDATA[https://lily-software.com/free-scripts/cotonti-shop/shop-documentation/redaktirovanie-tovara]]></link>
		</item>
		<item>
			<title>2. Способы оплаты и доставки</title>
			<description><![CDATA[<p>В модуль магазина "<strong>Shop</strong>" уже включает в себя по одному стандартному плагину оплаты и доставки. Это "<strong>Shop - Payment plugin Standard</strong>", "<strong>Shop - Shipment, By weight, ZIP and countries</strong>"</p>

<p>Также возможна установка дополнительных плагинов.</p>

<p>Работа со способами оплаты и доставки схожа.</p>

<p>Рассмотрим добавление способа оплаты более подробно.</p>

<p>Перейдем в панель управления: <strong>Управление сайтом / Расширения / Shop / Администрирование</strong><br />
Выберем "<strong>Способы оплаты</strong>". "<strong>Добавить</strong>"</p>

<p>Заполняем поля. Выбираем нужный плагин из списка. Выберем "Shop - Payment plugin Standard".<br />
Если выбрать группы пользователей, то он будет доступен только для этих групп.</p>

<p>Нажмем "<strong>Отправить</strong>" для сохранения.</p>

<p>После сохранения система автоматически перейдет к редактированию вновь созданного способа.<br />
И под формой, которую мы только что заполнили появится форма конфигурации с настройками, спецефичными уже для выбранного плагина.</p>

<p>Плагин "<strong>Shop - Payment plugin Standard</strong>" в числе прочих содержит настройки: "<strong>Страны</strong>", "<strong>Минимальная сумма заказа</strong>", "<strong>Максимальная сумма заказа</strong>", которые могут ограничить применение данного способа.</p>

<p>Например, если добавить страну "Россия", то этот способ оплаты можно будет использовать только, если в адресе доставки покупателя при оформлении заказа указана "россия".</p>

<p>Если "Минимальная сумма заказа" установлено в 1000, то данных способ оплаты нельзя будет выбрать при сумме заказа ниже 1000 рублей.</p>

<p>Если эти поля не настроены, то никаких ограничений не накладывается.</p>

<p>Также этот плагин позволяет назначить сумму, которая будет прибавляться к стоимости заказа за использование данного метода. Сумму можно указать как абсолютную, так и в процентах от стоимости заказа.</p>

<p><br />
Заполняем необходимые поля. Сохраняем.</p>

<p> </p>

<p>Работа с плагинм доставки "<strong>Shop - Shipment, By weight, ZIP and countries</strong>" происходит аналогично. Вы лекго можете добавить способ доставки, скажем "Курьером" стоимостью 300 рублей.</p>
]]></description>
			<pubDate>Fri, 12 Jul 2013 16:36:00 +0300</pubDate>
			<link><![CDATA[https://lily-software.com/free-scripts/cotonti-shop/shop-documentation/sposoby-oplaty-i-dostavki]]></link>
		</item>
		<item>
			<title>1. Установка</title>
			<description><![CDATA[<p style="text-align:justify;">Скачайте последнюю версию с <em>GitHub:</em> <a href="http://portal30.ru/go.php?https://github.com/Alex300/cotonti-shop" target="_blank">https://github.com/Alex300/cotonti-shop</a></p>

<p style="text-align:justify;">Содержимое папок «<strong>modules</strong>» и «<strong>plugins</strong>» скопируйте в соотвествующие папки на Вашем сайте.</p>

<p style="text-align:justify;">На файл «<strong>modules/shop/cache/convertECB_daily.xml</strong>» установите права на запись.</p>

<p style="text-align:justify;">Установите модуль «<strong>Shop</strong>» и плагины «<strong>Shop - Payment plugin Standard</strong>», «<strong>Shop - Shipment, By weight, ZIP and countries</strong>» из панели администратора.</p>

<p style="text-align:justify;">Плагины «<strong>Shop - Payment plugin Standard</strong>» и «<strong>Shop - Shipment, By weight, ZIP and countries</strong>» это стандартные плагины оплаты и доставки.</p>

<p style="text-align:justify;">В файл «<strong>admin.users.add.tags</strong>» в формы добавления и редактирования группы пользователей добавте теги <strong>{ADMIN_USERS_NGRP_MIN_PURCHASE}</strong> и <strong>{ADMIN_USERS_NGRP_VENDOR_CURRENCY}</strong>, соответсвенно. Это добавит возможность устанавливать минимальную сумму заказа для группы пользователей.</p>

<p>Например для формы редактирования:</p>

<pre class="brush:xml;">
&lt;tr&gt;
    &lt;td&gt;{PHP.L.shop.order_min_total}:&lt;/td&gt;
    &lt;td&gt;{ADMIN_USERS_EDITFORM_GRP_MIN_PURCHASE} {ADMIN_USERS_EDITFORM_GRP_VENDOR_CURRENCY}&lt;/td&gt;
&lt;/tr&gt;</pre>

<p>Чтобы при обновлении Cotonti эти изменения не потерялись, можно этот файл скопировать в папку: <strong>themes/&lt;ваша_тема&gt;/admin</strong></p>

<p style="text-align:justify;">Настройте магазин нажав кнопку "Конфигурация" на странице модуля в панели администратора.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><strong>Автоматическое создание экстраполей страниц и пользователя.</strong></p>

<p style="text-align:justify;">Для работы модуля необходимо создать некоторые экстраполя для страниц и пользователей. Сделать это можно на странице настройки самого модуля в разделах "Экстраполя страниц" и "Экстраполя пользователей (Реквизиты)". Тут можно указать свои экстраполя или оставить те, что предлагаются по-умолчанию. Когда все поля указаны, после нажатие кнопки "Создать все экстраполя" они будут созданы автоматически. Данная процедура только создает новые поля. Существующие не затрагиваются.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><strong>Настройки магазина</strong></p>

<p style="text-align:justify;">Когда настройки модуля магазина закончены и сохранены, перейтиде в раздел Администрирования модуля. Там перейдите в раздел "Магазин", кликнув по соотвествующей кнопке. Заполните название и выберите валюту магазина, а также валюты, которые будут доступны пользователю при просмотре магазина.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><strong>Способы оплаты и доставки</strong></p>

<p style="text-align:justify;">В разделе Администрирования модуля перейдите на страницу "Способы оплаты". Добавте и сохраните способ оплаты. После сохранения можно настроить дополнительные параметры. Подробнее читайте в соотвествующем разделе документации.</p>

<p style="text-align:justify;">Тоже самое сделайте для способа доставки.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><strong>Шаблоны</strong></p>

<p style="text-align:justify;">Для облегчения настройки шаблонов отображения и редактирования товаров в репизитории на <em>GitHub:</em> <a href="http://portal30.ru/go.php?https://github.com/Alex300/cotonti-shop/tree/master/themes/your-theme">https://github.com/Alex300/cotonti-shop/tree/master/themes/your-theme</a> есть образцы шаблонов для списка страниц, самой страницы товара и страниц добавления / редактирования товара. Обратие внимание: магазин для хранения товаров использует модуль страниц.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><strong>Добавление в шаблоны вывода корзины и выбора валюты</strong></p>

<p style="text-align:justify;">Корзину и выбор валюты можно вывести в любой шаблон. В зависимости от настроек магазина корзина будет отображаться только в магазине или на всем сайте.</p>

<p style="text-align:justify;">Корзина выводится тегом: <strong>{PHP|minicart}</strong></p>

<p style="text-align:justify;">Например:</p>

<pre class="brush:xml;">
&lt;div&gt;{PHP|minicart}&lt;/div&gt;</pre>

<p style="text-align:justify;">Выбор валюты выводится тегом: <strong>{PHP.currencySelect}</strong></p>

<p style="text-align:justify;">Например:</p>

<pre class="brush:xml;">
&lt;!-- IF {PHP.currencySelect} --&gt;
&lt;!-- Выбор валюты --&gt;
 {PHP.L.shop.currency_select}:&lt;br /&gt;
&lt;div class="currency-select"&gt;{PHP.currencySelect}&lt;/div&gt;
&lt;!-- ENDIF --&gt;</pre>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><strong>Добавление разделов и товаров</strong>.</p>

<p style="text-align:justify;">В панели управления сайтом в разделе: <strong>Управление сайтом / Расширения / Pages / Структура</strong> создайте категорию магазина и при необходимости подкатегории. Код корневой категории следует указать в настройках модуля магазина.</p>

<p style="text-align:justify;">Можно добавлять товары.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><strong>Производители</strong></p>

<p style="text-align:justify;">Для товаров можно создать страницы производителей. Для этого в панели управления сайтом в разделе: <strong>Управление сайтом / Расширения / Pages / Структура</strong> создайте категорию для производителей. Она не должна быть вложенной в магазин. Создайте ее отдельно. Укажите ее код в настройках модуля. Созданные в ней страницы и будут страницами производителей.</p>

<p style="text-align:justify;">При редактировании товара можно выбирать произволителя из этой категории.</p>
]]></description>
			<pubDate>Fri, 12 Jul 2013 12:44:00 +0300</pubDate>
			<link><![CDATA[https://lily-software.com/free-scripts/cotonti-shop/shop-documentation/ustanovka]]></link>
		</item>
		<item>
			<title>Cotonti. Онлайн-консультант.</title>
			<description><![CDATA[<p style="text-align:justify;">Модуль <strong>«Онлайн-консультант</strong>». Позволяет организовать на Вашем сайте на Cotonti онлайн-консультирование, поддержку пользователей, техническую поддержку и т.д. Вы и Ваши сотрудники могут общаться в one-to-one чате с посетителями Вашего сайта, оказывая им оперативную поддержку и увеличивая объем продаж. Общение происходит прямо в браузере.</p>

<p> </p>

<p> </p>

<p><em>Тип</em>: <strong>модуль</strong><br /><em>Версия<strong>: 1.2.1</strong></em><br /><em>Совместимость</em>: <strong>Siena</strong></p>

<p style="text-align:justify;">Модуль будет полезен для сайтов, в работе которых важна обратная связь с клиентами, например для интернет магазинов. Вы сможете общаться с вашими посетителями в реальном времени и предложить им именно то, что им нужно.</p>

<p style="text-align:justify;">В отличие от многих подобных продкутов не требует для работы каких-нибудь дополнительных сервисов.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;">После установки модуля добавте тег <strong>{PHP.oC_button}</strong> в нужное место в шаблоне для вывода кнопки начала диалога.</p>

<p style="text-align:justify;">На файл <strong>/modules/oconsultant/inc/procesed.txt</strong> поставте права на запись.</p>

<p style="text-align:justify;">Операторами являются пользователи имеющие права на запись на этот модуль и (опционально) администраторы.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><strong>Возможности:</strong></p>

<p><u>Основные возможности</u><br />
   - Чат в реальном времени (без перезагрузки страниц)<br />
   - Неограниченное количество операторов, чатов и пользователей<br />
   - Выполняется на вашем сервере и домене с сайтом на Cotonti<br />
   - Шаблоны и файлы рессурсов позволяют легко адаптировать дизайн</p>

<p><u>Открытие диалога</u><br />
    - Отображение кнопки в зависимости от присутствия операторов<br />
    - Возможность оставить офф-лайн сообщение при отсутствии операторов в онлайне<br />
    - Капча для защиты от спама</p>

<p><u>Окно диалога</u><br />
   - Возможность запросить дополнительную информацию перед началом чата<br />
   - Уведомление о наборе текста собеседником<br />
   - Аватар оператора и пользователя в окне диалога<br />
   - Возможность отправки истории диалога себе на email<br />
   - Звуковые и визуальные оповещения о новогых сообщениях<br />
   - Отключение звукового оповещения в чате<br />
   - Активные ссылки в окне чата<br />
   - Автоматическое восстановление соединения с сервером</p>

<p><u>Возможности операторов</u><br />
    - Веб-интерфейс для обслуживания посетителей<br />
    - Режим "Отошел от компьютера" для оператора<br />
    - Шаблоны сообщений для быстрого ответа<br />
    - Отображение с какой страницы пришел посетитель<br />
    - История сообщений с поиском<br />
    - История диалогов<br />
    - Информация о пользователях в очереди: первое сообщение, IP, браузер<br />
    - Информация обо всех пользователях он-лайн<br />
    - Возможность самому начать диалог с любым пользователем<br />
    - Перенаправление во время чата посетителя на любую страницу Вашего сайта<br />
    - Просмотр текущих диалогов администратором сайта<br />
    - Перехват диалогов администратором сайта<br />
    - Статистика</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><strong>Что в планах:</strong></p>

<p style="text-align:justify;">- деление операторов по группам (например по отделам в организации)<br />
- просмотр пользователем полной истории диалога</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><strong>Условия использоания:</strong></p>

<p style="text-align:justify;">В диалоговых окнах модуля обязательно указание автора в виде прямой, незакрытой от индексации поисковыми системами ссылки на эту страницу ( http://portal30.ru/sozdanie-internet-sajtov/free-scripts/cotonti-onlajn-konsultant ) с текстом «powered by portal30». Либо Вы можете внести свой вклад в развитие проекта. Не обязательно деньгами. Можно, например переводом модуля на английский язык и составлением английского описания, улучшением функционала ))</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><em>GitHub:</em> <a href="https://lily-software.com/go.php?https://github.com/Alex300/Online-Consultant">https://github.com/Alex300/Online-Consultant</a></p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;">Вопросы пожалуйста <a href="https://lily-software.com/forums?m=topics&amp;s=cotonti">задавайте на форуме</a>.</p>
]]></description>
			<pubDate>Wed, 22 May 2013 13:00:00 +0300</pubDate>
			<link><![CDATA[https://lily-software.com/free-scripts/cotonti-onlajn-konsultant]]></link>
		</item>
		<item>
			<title>Cotonti - SecurImage CAPTCHA (Каптча)</title>
			<description><![CDATA[<p><em>Тип</em>: <strong>плагин</strong><br />
<em>Версия плагина<strong>: 2.03</strong></em><br />
<em>Версия Securimage</em>: <strong>4.0.2</strong><br />
<em>Совместимость</em>: <strong>Siena</strong></p>

<p>Использует класс <a href="https://github.com/dapphp/securimage" target="_blank" rel="nofollow noreferrer noopener">Securimage</a> (от <a href="https://github.com/dapphp" target="_blank" rel="nofollow noreferrer noopener">Drew Phillips</a>)<br />
Для изменения настроек изображения отредактируйте файл <strong>/inc/imageshow.php</strong> (шрифт, кегль, фоновое изображение, шумы и т. д.)<br />
<br />
<em><strong>Возможности:</strong></em><br />
- Вы можете использовать данную капчу везде, где она применяется на Вашем сайте: в форме регистрации, комментариях, обратной связи и т.п.<br />
- Изображение можно обновить не перезагружая страницу<br />
- Те, кто не может прочитать код, могут прослушать голосовой код<br />
<br />
<em><strong>Образец работы</strong></em> каптчи можно посмотреть например в <a href="https://lily-software.com/users?m=register">форме регистрации данного сайта</a>.</p>

<p><em><strong>Установка:</strong></em><br />
- скопировать папку <strong>captcha</strong> из архива в папку <strong>plugins</strong> на Вашем хостинге<br />
- установить плагин в панели управления<br />
- в настройках сайта в разделе Конфигурация -&gt; Безопасность -&gt; Captcha по умолчанию выбрать <strong>«Captcha</strong>»</p>

<p><br />
<em><strong>Использования каптчи в своих плагинах: </strong></em><br />
Аналогично использованию любой другой капчи.</p>

<p><em>GitHub:</em>  <a href="https://lily-software.com/go.php?https://github.com/Alex300/SecurImageCaptcha-for-Cotonti">https://github.com/Alex300/SecurImageCaptcha-for-Cotonti</a></p>

<p><img alt="" src="https://private-user-images.githubusercontent.com/1021886/371828036-3c3fbf59-e17d-4047-8df1-52e30aa9ed5d.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mjc4ODM4NTcsIm5iZiI6MTcyNzg4MzU1NywicGF0aCI6Ii8xMDIxODg2LzM3MTgyODAzNi0zYzNmYmY1OS1lMTdkLTQwNDctOGRmMS01MmUzMGFhOWVkNWQucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI0MTAwMiUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNDEwMDJUMTUzOTE3WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9YzczOWE0YzljNDQzZGIyZDkzZjg5YzRjZjg1YmM3ODFhNmY4N2MyOGQ2YTUwYmMxZmI0ZTJmZDE2NDU4ZDBiZiZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.SAKec6p2dlSu5gkEKo5y-Zz87zUaCZDFr3T3iliHjHE" /></p>

<p><a href="https://lily-software.com/archive/cotonti_securImage_captcha">Версия 1.0 для Cotonti Genoa</a></p>
]]></description>
			<pubDate>Thu, 02 May 2013 15:04:00 +0300</pubDate>
			<link><![CDATA[https://lily-software.com/free-scripts/cotonti-securImage-captcha]]></link>
		</item>
		<item>
			<title>Joomla module. AN Carousel.</title>
			<description><![CDATA[<p style="text-align: right;">
	<img alt="Совместимо с Joomla 1.5.x Native" height="16" src="https://lily-software.com/User_Files/a-n_Files/image/illustratcii/icons/compat_J_15_native.png" width="75" /></p>
<p style="text-align: justify;">
	Этот модуль позволяет прокручивать графическую и текстовую информацию на Joomla! сайте. Прокручиваемыми элементами могут быть небольшие части материалов из указанной категории, к примеру краткие новости или категории товаров интернет магазина Virtuemat. В последнем случае, чтобы попасть в &quot;прокрутку&quot; категория должна иметь изображение и/или описание. При клике на прокручиваемом элементе пользователь перейдет на соответствующую страницу сайта. Прокрутка может быть как горизонтальной, так и вертикальной.</p>
<p>
	&nbsp;</p>
<p>
	Версия модуля: <em><strong>1.0.0</strong></em> от 18.11.2010</p>
<p>
	&nbsp;</p>
<p>
	Язык: русский, english</p>
<p>
	&nbsp;</p>
<p>
	Примеры работы:</p>
<p>
	<a href="https://lily-software.com/go.php?asttorgtech.ru" target="_blank">Астторгтех</a> .</p>
<p>
	&nbsp;</p>
<p>
	Скриншуты:</p>
<p>
	<a href="https://lily-software.com/User_Files/a-n_Files/image/illustratcii/web/an_carousel.jpg"><img alt="Категории магазина AN Virtuemart Accordion" border="0" height="88" src="https://lily-software.com/User_Files/a-n_Files/image/illustratcii/web/ico/an_carousel.jpg" width="300" /></a></p>
<p>
	&nbsp;</p>
<p>
	<strong>Что такое VirtueMart?:</strong></p>
<p style="text-align: justify;">
	Cкрипт интернет-магазина VirtueMart - одно из самых популярных в мире решений в области <strong>электронной коммерции</strong>. VirtueMart &ndash; это полностью готовое приложение для профессиональных компаний, при этом оно может быть адаптировано именно под ваши нужды на 100%.</p>
<p style="text-align: justify;">
	VirtueMart является компонентом системы управления контентом Joomla! (Mambo) и не может использоваться без нее. Каждый, кто использует этот компонент, может продавать свой товар покупателям, не вникая в технические подробности интернет-торговли!</p>
<p style="text-align: justify;">
	&nbsp;</p>
<p style="text-align: justify;">
	<strong>Что такое Joomla! ?:</strong></p>
<p style="text-align: justify;">
	<strong>Joomla!</strong> &mdash; (читается &quot;Джумла&quot;) система управления содержанием (CMS), написанная на языках PHP и JavaScript, использующая в качестве хранилища содержания базу данных MySQL. Joomla! является свободным программным обеспечением, защищённым лицензией <a href="https://lily-software.com/go.php?ru.wikipedia.org/wiki/GPL">GPL</a>. Одной из главных особенностей Joomla! является относительная простота управления при практически безграничных возможностях и гибкости при изготовлении сайтов.<br />
	CMS Joomla! включает в себя различные инструменты для изготовления веб-сайта. Важной особенностью системы является минимальный набор инструментов при начальной установке, который обогащается по мере необходимости. Это снижает загромождение административной панели ненужными элементами, а также снижает нагрузку на сервер и экономит место на хостинге.</p>]]></description>
			<pubDate>Thu, 18 Nov 2010 20:39:00 +0300</pubDate>
			<link><![CDATA[https://lily-software.com/free-scripts/joomla-module-an-carousel]]></link>
		</item>
		<item>
			<title>Joomla module. VirtueMart. AN VM Accordion</title>
			<description><![CDATA[<p style="text-align: right">
	<img alt="Совместимо с Joomla 1.5.x Native" height="16" src="https://lily-software.com/User_Files/a-n_Files/image/illustratcii/icons/compat_J_15_native.png" width="75" /></p>
<p>
	Этот модуль выводит все категории компонента интернет магазина Viruemart Mart в виде раскрывающегося списка (Аккордиона).</p>
<p>
	&nbsp;</p>
<p>
	Версия модуля: <em><strong>1.0.1</strong></em> от 16.11.2010</p>
<p>
	&nbsp;</p>
<p>
	Язык: русский.</p>
<p>
	&nbsp;</p>
<p>
	Примеры работы:</p>
<p>
	<a href="https://lily-software.com/go.php?portal-ycheba.ru" target="_blank">Торговый дом портал</a>, <a href="https://lily-software.com/go.php?firm.test-trail.com" target="_blank">Астторгтех</a> .</p>
<p>
	&nbsp;</p>
<p>
	Скриншуты:</p>
<p>
	<a href="https://lily-software.com/User_Files/a-n_Files/image/illustratcii/web/an_vm_accordion_1.jpg"><img alt="Категории магазина AN Virtuemart Accordion" border="0" height="210" src="https://lily-software.com/User_Files/a-n_Files/image/illustratcii/web/ico/an_vm_accordion_1.jpg" width="151" /></a> <a href="https://lily-software.com/User_Files/a-n_Files/image/illustratcii/web/an_vm_accordion_2.jpg"><img alt="Категории магазина AN Virtuemart Accordion" src="https://lily-software.com/User_Files/a-n_Files/image/illustratcii/web/ico/an_vm_accordion_2.jpg" style="width: 151px; height: 210px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid" /></a></p>
<p>
	&nbsp;</p>
<p>
	<strong>Что такое VirtueMart?:</strong></p>
<p style="text-align: justify">
	Cкрипт интернет-магазина VirtueMart - одно из самых популярных в мире решений в области <strong>электронной коммерции</strong>. VirtueMart &ndash; это полностью готовое приложение для профессиональных компаний, при этом оно может быть адаптировано именно под ваши нужды на 100%.</p>
<p style="text-align: justify">
	VirtueMart является компонентом системы управления контентом Joomla! (Mambo) и не может использоваться без нее. Каждый, кто использует этот компонент, может продавать свой товар покупателям, не вникая в технические подробности интернет-торговли!</p>
<p style="text-align: justify">
	&nbsp;</p>
<p style="text-align: justify">
	<strong>Что такое Joomla! ?:</strong></p>
<p style="text-align: justify">
	<strong>Joomla!</strong> &mdash; (читается &quot;Джумла&quot;) система управления содержанием (CMS), написанная на языках PHP и JavaScript, использующая в качестве хранилища содержания базу данных MySQL. Joomla! является свободным программным обеспечением, защищённым лицензией <a href="https://lily-software.com/go.php?ru.wikipedia.org/wiki/GPL">GPL</a>. Одной из главных особенностей Joomla! является относительная простота управления при практически безграничных возможностях и гибкости при изготовлении сайтов.<br />
	CMS Joomla! включает в себя различные инструменты для изготовления веб-сайта. Важной особенностью системы является минимальный набор инструментов при начальной установке, который обогащается по мере необходимости. Это снижает загромождение административной панели ненужными элементами, а также снижает нагрузку на сервер и экономит место на хостинге.</p>]]></description>
			<pubDate>Tue, 16 Nov 2010 21:51:00 +0300</pubDate>
			<link><![CDATA[https://lily-software.com/free-scripts/joomla-virtuemart-an-vm-accordion]]></link>
		</item>
		<item>
			<title>Cotonti. Blogger.</title>
			<description><![CDATA[<p>Плагин пользовательских блогов для CMF Cotonti.</p>

<p><em>Тип</em>: <strong>плагин</strong><br /><em>Версия плагина<strong>: 1.5.0</strong></em><br /><em>Совместимость</em>: <strong>Siena</strong></p>

<p style="text-align:justify;"><strong>Описание:</strong></p>

<p style="text-align:justify;">Плагин расширяет функционал модуля страниц и позволяет пользователям, которым разрешено ведение блога (<strong>у этой группы есть право на запись W на данный плагин</strong>) создать свой блог – категория вложенная в корневую категорию блога. У них автоматически создается право на создание страниц в этой категории, а также (опционально), создание вложенных категорий. Автор блога может выбрать оформление для своего блога. Он имееет возможность получать уведомления о комментариях своих страниц на свой e-email.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><strong>Основные возможности:</strong><br />
- Темы оформления для каждого блога<br />
- Категории внутри блогов<br />
- Возможность премодерации публикаций<br />
- Комментарии<br />
- RSS лента<br />
- Уведомления пользователя о новых комментариях.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;">Если на сайте включено автоутверждение страниц и пользователь имеет права <strong>'2'</strong> на этот плагин, то добавляемые им записи (страницы) утверждаются автоматически.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;">Поскольку плагин работает на стандартных категориях и страницах движка, то никаких дополнений для карты сайта и ЧПУ. Также он легко подхватится поиском, RSS и другими модулями / плагинами.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;">образец работы можно посмотреть тут: <a href="http://xn--80aacclg0b0c.xn--p1ai/blogs" target="_blank">Ваши свадебные сайты</a>.</p>

<p style="text-align:justify;"><br /><strong>Установка</strong>: стандартна.<br />
- распаковать архив<br />
- папку <strong>blogger</strong> скопировать на сервер в папку "<strong>plugins</strong>"<br />
- установить и настроить в панеле управления.<br />
- в файл скина <strong>page.list.tpl</strong> или <strong>users.details.tpl</strong> добавить необходимые теги.</p>

<p>Также прилагается образец файла файла page.list.tpl с тегами, специфичными для данного плагина</p>

<p> </p>

<p><em><strong>Старая версия плагина 1.0.0</strong></em> для Cotonti Genoa.0.6.x (от 14.01.2011): <a href="https://lily-software.com/User_Files/a-n_Files/file/cotonti_plugins/an_bloger_genoa.0.6.x.zip">Скачать</a></p>

<p> </p>

<p style="text-align:justify;"><em>GitHub:</em> <a href="https://lily-software.com/go.php?https://github.com/Alex300/Blogger" target="_blank">https://github.com/Alex300/Blogger</a></p>
]]></description>
			<pubDate>Wed, 27 Oct 2010 21:49:00 +0300</pubDate>
			<link><![CDATA[https://lily-software.com/free-scripts/cotonti-blogger]]></link>
		</item>
		<item>
			<title>Cotonti. Print, PDF Version, E-mail to friend</title>
			<description><![CDATA[<p style="text-align:justify;">Плагин для Cotonti, позволяющий для страниц, категорий (списков) и форумов вывести в новом окне <strong>версию для печати</strong> (содержимое страницы без оформления), <strong>PDF версию</strong>, и форму для отправки <strong>ссылки на текущую страницу по e-mail</strong> (отправить другу). Опционально для форму отправки по e-mail можно использовать капчу. Для использования этой возможности должен быть установлен <a href="https://lily-software.com/go.php?www.cotonti.com/downloads/plugins/miscellaneous/captcha_manager">плагин CAPTCHA Manager</a> и одна из капчей.</p>

<p> </p>

<p><em><strong>Версия плагина: 1.0.0</strong></em></p>

<p><strong>Язык:</strong> русский, english</p>

<p> </p>

<p><strong>Требования:</strong><br />
    - jQuery</p>

<p> </p>

<p><strong>Установка:</strong><br />
    - распаковать архив<br />
    - папку <strong>«an_ppve»</strong> скопировать на сервер в папку <strong>«plugins»</strong><br />
    - установить и настроить в панеле администратора.<br />
    - в файлы скина «page.tpl», «list.tpl» и «forums.posts.tpl» добавить теги {PPVE_PRINT_VERSION},{PPVE_PDF_VERSION},{PPVE_EMAIL_TO_FRIEND}</p>

<p> </p>

<p>Плагин тестировался с Cotonti Genoa 0.6.9</p>

<p>Образец работы Вы можете видеть на этом сайте.</p>

<p> </p>

<p><a href="https://lily-software.com/forums">Обсудить на форуме</a>.</p>
]]></description>
			<pubDate>Sun, 18 Jul 2010 19:35:00 +0300</pubDate>
			<link><![CDATA[https://lily-software.com/free-scripts/cotonti_an_ppve]]></link>
		</item>
		<item>
			<title>Cotonti. Плагин прогноза погоды.</title>
			<description><![CDATA[<p><img align="left" alt="Плагин для Cotonti. Прогноз погоды." border="0" height="256" hspace="5" src="https://lily-software.com/User_Files/a-n_Files/image/illustratcii/weather.jpg" vspace="3" width="205" /></p>

<p style="text-align:justify;">Плагин прогноза погоды для CMF Cotonti. Он использует Google Weather API. Позволяет выводить текущую погоду и прогноз на 4 дня для выбранного города. Пользователь может выбрать любой город. Допускается ввод данных как на русском, так и на английском языке. Возможно отображение температуры воздуха как в градусах по Цельсию ( °С ), так и по Фаренгейту ( °F ). Выбранный пользователем город запоминается, и при следующем посещении пользователем сайта, ему отобразится прогноз для этого города.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><strong>Основные функции плагина:</strong><br />
- Вывод текущей погоды для указанного города<br />
- Погодный информер на сайте<br />
- Прогноз на 4 дня на отдельной странице.<br />
- Город по-умолчанию указывается в настройках плагина в панели управления.<br />
- В настройках плагина указывается отображать ли влажность, скорость ветра<br />
- Кеширование данных<br />
- Обновление данных в информере через Ajax</p>

<p> </p>

<p><em><strong>Версия плагина: 1.0.2   </strong>от 3 августа 2010 г.</em></p>

<p><strong>Язык: </strong>русский, english</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><em>Отличия от версии 1.0.1</em>:<br />
 - Исправлена ошибка, возникающая при использовании плагина в топиках форума</p>

<p style="text-align:justify;"><em>Отличия от версии 1.0.0:</em><br />
- Совместимость с PHP 5.3<br />
- Исправлена ошибка: на некоторых хостах не в url не ставился слеш после доменного имени.</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><strong>Требования:</strong><br />
- jQuery<br />
- PHP библиотека CURL должна быть установлена на Вашем сервере</p>

<p style="text-align:justify;"> </p>

<p style="text-align:justify;"><strong>Установка:</strong><br />
- распаковать архив<br />
- папку <strong>«weather»</strong> скопировать на сервер в папку <strong>«plugins»</strong><br />
- установить и настроить в панеле администратора.<br />
- в файл скина <strong>«header.tpl» </strong>или <strong>«footer.tpl» </strong>добавить тег<strong> {WEATHER}</strong></p>

<p> </p>

<p>Плагин тестировался с Cotonti Genoa 0.6.7</p>

<p> </p>

<p><a href="https://lily-software.com/forums">Обсудить на форуме</a>.</p>
]]></description>
			<pubDate>Fri, 02 Apr 2010 22:14:00 +0300</pubDate>
			<link><![CDATA[https://lily-software.com/free-scripts/cotonti_weather]]></link>
		</item>
		<item>
			<title>Cotonti. Права на создание страниц</title>
			<description><![CDATA[<p style="text-align: justify;">
	Данный плагин позволяет <strong>отделить права на создание страниц</strong> от прав на их редактирование. <br />
	<br />
	Этот плагин анализирует в правах пользователя опцию &quot;<strong>Extra 3</strong>&quot; установленную для категорий. Если включено, то пользователи этой группы могут добавлять новые страницы в данную категорию. Вы можете настраивать это для каждой категории в разделе настройки прав пользователя, пройдя по ссылке &quot;<strong>подробно</strong>&quot; внизу страницы.<br />
	<br />
	Если в данной категории создание страниц для пользователя не разрешено, то дабы не смущать его такой возможностью, ему не будет показана ссылка &quot;<strong>Создать новую страницу</strong>&quot;.<br />
	<br />
	Например, страницы может создавать только администратор сайта, но он может их назначить другим пользователям, и каждый может редактировать только свои страницы.<br />
	<br />
	<strong>Установка</strong> стандартна:<br />
	- распаковать архив<br />
	- скопировать папку &quot;<strong>an_PageAddRights</strong>&quot; на сервер в папку &quot;<strong>plugins</strong>&quot;<br />
	- установить из панели администратора<br />
	<br />
	Опционально вы можете добавить строку в файл skins/your_skin/your_skin.ru.lang.php<br />
	<br />
	<strong>$skinlang[&#39;admin&#39;][&#39;addPage&#39;] = &#39;Добавлять страницу (для страниц)&#39;;&nbsp;&nbsp;&nbsp; // by Alex</strong><br />
	<br />
	в файле <strong>skins/your_skin/admin/admin.rightsbyitem.inc.tpl</strong> найти строку 66:<br />
	<br />
	<strong>&lt;img src=https://lily-software.com/&quot;images/admin/auth_3.gif&quot; alt=&quot;&quot; /&gt; : {PHP.L.Custom} #3&lt;br /&gt;</strong><br />
	<br />
	заменить на:<br />
	<br />
	<strong>&lt;img src=https://lily-software.com/&quot;images/admin/auth_3.gif&quot; alt=&quot;&quot; /&gt; : {PHP.skinlang.admin.addPage}&lt;br /&gt;</strong><br />
	<br />
	и в файле <strong>skins/your_skin/admin/admin.rights.inc.tpl</strong> найти строку 196:<br />
	<br />
	<strong>&lt;img src=https://lily-software.com/&quot;images/admin/auth_3.gif&quot; alt=&quot;&quot; /&gt; : {PHP.L.Custom} #3&lt;br /&gt;</strong><br />
	<br />
	заменить на:<br />
	<br />
	<strong>&lt;img src=https://lily-software.com/&quot;images/admin/auth_3.gif&quot; alt=&quot;&quot; /&gt; : {PHP.skinlang.admin.addPage}&lt;br /&gt;</strong></p>
<p style="text-align: justify;">
	Страница плагина на <a href="https://lily-software.com/go.php?www.cotonti.com/downloads/plugins/pages-lists/Page_Add_Rights" target="_blank">официальном сайте Cotonti</a>.</p>
<p style="text-align: justify;">
	&nbsp;</p>
<p style="text-align: justify;">
	<strong>Что такое Cotonti?<br />
	</strong></p>
<p>
	&nbsp;</p>
<p>
	<strong>Cotonti</strong> &mdash; это расширяемая CMS/CMF на базе<strong> PHP/MySQL</strong>.<br />
	C одной стороны это система управления сайтом ( CMS ) с готовой структурой под типовой сайт, с другой стороны &mdash; очень простой и функциональный фреймворк ( CMF ).<br />
	Cotonti является преемником <a href="https://lily-software.com/go.php?neocrome.ru">Seditio CMS</a>, которая была создана на базе системы <strong>Land Down Under</strong>. В настоящее время она динамично развивается и совершенствуется, позволяя Web-мастерам решать самые разнообразные задачи.<br />
	<br />
	Основные преимущества Cotonti:<br />
	- открытый исходный код<br />
	- скорость и безопасность<br />
	- низкая нагрузка на сервер.<br />
	- модульность и расширяемость при помощи плагинов.<br />
	<br />
	Скачать последнюю версию можно на <a href="https://lily-software.com/go.php?cotonti.com" target="_blank">официальном сайте</a>.</p>]]></description>
			<pubDate>Sat, 26 Dec 2009 03:16:00 +0300</pubDate>
			<link><![CDATA[https://lily-software.com/free-scripts/cotonti_page_add_rights]]></link>
		</item>
	</channel>
</rss>