Библиотека Publisher
Библиотека Publisher предоставляет средства для копирования файлов в проекте с использованием надежного обнаружения и проверки ошибок.
Загрузка библиотеки
Поскольку экземпляры Publisher специфичны для своего источника и назначения, эта библиотека недоступна через Services, но должна быть создана или расширена напрямую. Например:
Концепция и использование
Publisher решает ряд распространённых проблем при работе с бэкенд-фреймворком:
- Как поддерживать ресурсы проекта с зависимостями версий?
- Как управлять загрузками и другими «динамическими» файлами, которые должны быть доступны через веб?
- Как обновить проект при изменении фреймворка или модулей?
- Как компоненты могут вставлять новый контент в существующие проекты?
В самом простом виде публикация сводится к копированию файлов в проект. Publisher расширяет FileCollection для реализации цепочки команд в стиле fluent для чтения, фильтрации и обработки входных файлов, а затем копирует или объединяет их в целевое место назначения. Вы можете использовать Publisher по требованию в своих контроллерах или других компонентах, или вы можете подготовить публикации, расширив класс и используя его обнаружение с помощью spark publish.
По требованию
Получите доступ к Publisher напрямую, создав новый экземпляр класса:
$publisher = new \CodeIgniter\Publisher\Publisher();
По умолчанию источник и место назначения будут установлены в ROOTPATH и FCPATH соответственно, что даёт Publisher лёгкий доступ для копирования любого файла из вашего проекта и размещения его в веб-доступе. В качестве альтернативы вы можете передать новый источник или источник и место назначения в конструктор:
use CodeIgniter\Publisher\Publisher;
$vendorPublisher = new Publisher(ROOTPATH . 'vendor');
$filterPublisher = new Publisher('/path/to/module/Filters', APPPATH . 'Filters');
// Once the source and destination are set you may start adding relative input files
$frameworkPublisher = new Publisher(ROOTPATH . 'vendor/codeigniter4/codeigniter4');
// All "path" commands are relative to $source
$frameworkPublisher->addPath('app/Config/Cookie.php');
// You may also add from outside the source, but the files will not be merged into subdirectories
$frameworkPublisher->addFiles([
'/opt/mail/susan',
'/opt/mail/ubuntu',
]);
$frameworkPublisher->addDirectory(SUPPORTPATH . 'Images');
После подготовки всех файлов используйте одну из команд вывода (copy() или merge()) для обработки подготовленных файлов в их место назначения(я):
// Place all files into $destination $frameworkPublisher->copy(); // Place all files into $destination, overwriting existing files $frameworkPublisher->copy(true); // Place files into their relative $destination directories, overwriting and saving the boolean result $result = $frameworkPublisher->merge(true);
Полное описание доступных методов см. в Справочнике по библиотеке.
Автоматизация и обнаружение
Вы можете иметь задачи публикации, встроенные в развертывание или обслуживание вашего приложения. Publisher использует мощный Autoloader для поиска всех дочерних классов, подготовленных к публикации:
use CodeIgniter\CLI\CLI;
use CodeIgniter\Publisher\Publisher;
foreach (Publisher::discover() as $publisher)
{
$result = $publisher->publish();
if ($result === false)
{
CLI::error(get_class($publisher) . ' failed to publish!', 'red');
}
}
По умолчанию discover() будет искать папку «Publishers» во всех именованных пространствах, но вы можете указать другую папку, и она вернёт все найденные дочерние классы:
$memePublishers = Publisher::discover('CatGIFs');
В большинстве случаев вам не нужно обрабатывать обнаружение самостоятельно, просто используйте предоставленную команду «publish»:
> php spark publish
По умолчанию при расширении класса publish() добавит все файлы из $source и объединит их в место назначения, перезаписывая при столкновениях.
Безопасность
Чтобы предотвратить внедрение вредоносного кода модулями в ваши проекты, Publisher содержит конфигурационный файл, определяющий разрешённые каталоги и шаблоны файлов в качестве мест назначения. По умолчанию файлы могут быть опубликованы только в ваш проект (чтобы предотвратить доступ к остальной файловой системе), а папка public/ (FCPATH) будет получать только файлы с указанными расширениями: * Веб-ресурсы: css, scss, js, map * Неисполняемые веб-файлы: htm, html, xml, json, webmanifest * Шрифты: tff, eot, woff * Изображения: gif, jpg, jpeg, tiff, png, webp, bmp, ico, svg
Если вам нужно добавить или изменить безопасность для вашего проекта, измените свойство $restrictions объекта Config\Publisher.
Примеры
Вот несколько примеров вариантов использования и их реализации, которые помогут вам начать работу с публикацией.
Пример синхронизации файлов
Вы хотите отобразить изображение «Фото дня» на своей домашней странице. У вас есть лента ежедневных фотографий, но вам нужно поместить сам файл в доступную по веб-адресу локацию в вашем проекте в public/images/daily_photo.jpg. Вы можете настроить Настраиваемую команду для ежедневного запуска, которая будет обрабатывать это за вас:
<?php
namespace App\Commands;
use CodeIgniter\CLI\BaseCommand;
use CodeIgniter\Publisher\Publisher;
use Throwable;
class DailyPhoto extends BaseCommand
{
protected $group = 'Publication';
protected $name = 'publish:daily';
protected $description = 'Publishes the latest daily photo to the homepage.';
public function run(array $params)
{
$publisher = new Publisher('/path/to/photos/', FCPATH . 'assets/images');
try
{
$publisher->addPath('daily_photo.jpg')->copy(true); // `true` to enable overwrites
}
catch (Throwable $e)
{
$this->showError($e);
}
}
}
Теперь, выполняя spark publish:daily, вы будете поддерживать изображение на домашней странице в актуальном состоянии. А что, если фото поступает из внешнего API? Вы можете использовать addUri() вместо addPath() для загрузки удалённого ресурса и публикации его вместо этого:
$publisher->addUri('https://example.com/feeds/daily_photo.jpg')->copy(true);
Пример зависимостей ресурсов
Вы хотите интегрировать фронтенд-библиотеку «Bootstrap» в свой проект, но частые обновления затрудняют отслеживание. Вы можете создать определение публикации в своём проекте для синхронизации фронтенд-ресурсов, расширив Publisher в своём проекте. Таким образом, app/Publishers/BootstrapPublisher.php может выглядеть следующим образом:
<?php
namespace App\Publishers;
use CodeIgniter\Publisher\Publisher;
class BootstrapPublisher extends Publisher
{
/**
* Tell Publisher where to get the files.
* Since we will use Composer to download
* them we point to the "vendor" directory.
*
* @var string
*/
protected $source = 'vendor/twbs/bootstrap/';
/**
* FCPATH is always the default destination,
* but we may want them to go in a sub-folder
* to keep things organized.
*
* @var string
*/
protected $destination = FCPATH . 'bootstrap';
/**
* Use the "publish" method to indicate that this
* class is ready to be discovered and automated.
*
* @return boolean
*/
public function publish(): bool
{
return $this
// Add all the files relative to $source
->addPath('dist')
// Indicate we only want the minimized versions
->retainPattern('*.min.*')
// Merge-and-replace to retain the original directory structure
->merge(true);
}
}
Теперь добавьте зависимость через Composer и вызовите spark publish для запуска публикации:
> composer require twbs/bootstrap > php spark publish
… и вы получите что-то вроде этого:
public/.htaccess
public/favicon.ico
public/index.php
public/robots.txt
public/
bootstrap/
css/
bootstrap.min.css
bootstrap-utilities.min.css.map
bootstrap-grid.min.css
bootstrap.rtl.min.css
bootstrap.min.css.map
bootstrap-reboot.min.css
bootstrap-utilities.min.css
bootstrap-reboot.rtl.min.css
bootstrap-grid.min.css.map
js/
bootstrap.esm.min.js
bootstrap.bundle.min.js.map
bootstrap.bundle.min.js
bootstrap.min.js
bootstrap.esm.min.js.map
bootstrap.min.js.map
Пример развертывания модуля
Вы хотите предоставить разработчикам, использующим ваш популярный модуль аутентификации, возможность расширения стандартного поведения миграций, контроллеров и моделей. Вы можете создать собственную команду модуля «publish» для вставки этих компонентов в приложение для использования:
<?php
namespace Math\Auth\Commands;
use CodeIgniter\CLI\BaseCommand;
use CodeIgniter\Publisher\Publisher;
use Throwable;
class AuthPublish extends BaseCommand
{
protected $group = 'Auth';
protected $name = 'auth:publish';
protected $description = 'Publish Auth components into the current application.';
public function run(array $params)
{
// Use the Autoloader to figure out the module path
$source = service('autoloader')->getNamespace('Math\\Auth');
$publisher = new Publisher($source, APPATH);
try
{
// Add only the desired components
$publisher->addPaths([
'Controllers',
'Database/Migrations',
'Models',
])->merge(false); // Be careful not to overwrite anything
}
catch (Throwable $e)
{
$this->showError($e);
return;
}
// If publication succeeded then update namespaces
foreach ($publisher->getPublished() as $file)
{
// Replace the namespace
$contents = file_get_contents($file);
$contents = str_replace('namespace Math\\Auth', 'namespace ' . APP_NAMESPACE, );
file_put_contents($file, $contents);
}
}
}
Теперь, когда пользователи вашего модуля запускают php spark auth:publish, они получат следующее дополнение в свой проект:
app/Controllers/AuthController.php app/Database/Migrations/2017-11-20-223112_create_auth_tables.php.php app/Models/LoginModel.php app/Models/UserModel.php
Справочник по библиотеке
Примечание
Publisher является расширением FileCollection, поэтому имеет доступ ко всем этим методам для чтения и фильтрации файлов.
Поддерживающие методы
[static] discover(string $directory = ‘Publishers’): Publisher[]
Обнаруживает и возвращает все Publisher в указанном каталоге пространства имён. Например, если существуют как app/Publishers/FrameworkPublisher.php, так и myModule/src/Publishers/AssetPublisher.php, и оба являются расширениями Publisher, то Publisher::discover() вернёт экземпляр каждого из них.
publish(): bool
Обрабатывает полную цепочку вход-обработка-вывод. По умолчанию это эквивалентно вызову addPath($source) и merge(true), но дочерние классы, как правило, предоставляют собственную реализацию. publish() вызывается для всех обнаруженных Publisher при запуске spark publish. Возвращает результат успешного или неудачного выполнения.
getScratch(): string
Возвращает временную рабочую область, создавая её при необходимости. Некоторые операции используют промежуточное хранилище для подготовки файлов и изменений, и это предоставляет путь к временной, записываемой папке, которую вы также можете использовать.
getErrors(): array<string,Throwable>
Возвращает все ошибки из последней операции записи. Ключи массива — это файлы, вызвавшие ошибку, а значения — пойманные исключения Throwable. Используйте getMessage() на исключении Throwable, чтобы получить сообщение об ошибке.
addPath(string $path, bool $recursive = true) addPaths(array $path, bool $recursive = true)
Добавляет все файлы, указанные относительными путями. Пути — это ссылки на реальные файлы или каталоги, относительные к $source. Если относительный путь разрешается на каталог, то $recursive будет включать подкаталоги.
addUri(string $uri) addUris(array $uris)
Загружает содержимое URI с помощью CURLRequest во временную рабочую область, а затем добавляет полученный файл в список.
Примечание
Выполняемый запрос CURL является простым GET и использует тело ответа для содержимого файла. Для некоторых удалённых файлов может потребоваться настроить специальный запрос для правильной обработки.
Вывод файлов
wipe()
Удаляет все файлы, каталоги и подкаталоги из $destination.
Важно
Используйте с осторожностью.
copy(bool $replace = true): bool
Копирует все файлы в $destination. Структура каталогов не воссоздаётся, поэтому каждый файл из текущего списка окажется в одном и том же каталоге назначения. Использование $replace приведёт к перезаписи файлов, когда уже существует файл с таким же именем. Возвращает результат успешного или неудачного выполнения, используйте getPublished() и getErrors() для устранения неполадок. Имейте в виду потенциальные коллизии с одинаковыми базовыми именами, например:
$publisher = new Publisher('/home/source', '/home/destination');
$publisher->addPaths([
'pencil/lead.png',
'metal/lead.png',
]);
// This is bad! Only one file will remain at /home/destination/lead.png
$publisher->copy(true);
merge(bool $replace = true): bool
Копирует все файлы в $destination в соответствующих относительных подкаталогах. Любые файлы, соответствующие $source будут помещены в аналогичные каталоги в $destination, эффективно выполняя операцию «зеркального отображения» или «rsync». Использование $replace приведёт к перезаписи файлов, когда уже существует файл; так как каталоги объединяются, это не повлияет на другие файлы в месте назначения. Возвращает результат успешного или неудачного выполнения, используйте getPublished() и getErrors() для устранения неполадок.
Пример:
$publisher = new Publisher('/home/source', '/home/destination');
$publisher->addPaths([
'pencil/lead.png',
'metal/lead.png',
]);
// Results in "/home/destination/pencil/lead.png" and "/home/destination/metal/lead.png"
$publisher->merge();
© 2014–2020 British Columbia Institute of Technology
Licensed under the MIT License.
https://codeigniter.com/user_guide/libraries/publisher.html