Библиотека с открытым исходным кодом.
👉 Compass - это библиотека, предназначенная для работы с URL-адресами и путями к файлам на жестком диске. В ее состав входят инструменты для упрощения манипуляций с этими данными. Цель библиотеки - облегчить работу с URL-адресами и данными о расположении файлов.
Compass может быть использован в различных PHP-приложениях для обработки путей к файлам и URL-адресов. Он включает в
себя два основных компонента: Compass\Path
и Compass\Url
. Оба этих компонента представляют собой отдельные объекты
и предлагают набор методов для простого манипулирования данными. Compass\Path
предоставляет инструменты для работы с
директориями, включая поиск, замену и проверку наличия директорий в строке пути, а также изменение их порядка. В свою
очередь, Compass\Url
обеспечивает возможности для работы с URL, позволяя создавать, получать и изменять различные
части URL-адреса.
Оба компонента работают по схожему принципу, сначала собирают необходимые параметры, а затем применяют их к результату с
помощью специального метода updateSource()
.
Предпочтительный способ установки - через composer.
Запустите команду
php composer require vinogradsoft/compass "^1.0"
Требуется PHP 8.0 или новее.
<?php
require_once dirname(__DIR__, 1) . '/vendor/autoload.php';
use \Compass\Url;
$url = Url::createBlank();
$url->setScheme('http')->setUser('grigor')->setPassword('password')->setHost('vinograd.soft')
->setPort('8080')->setPath('/path/to/resource')->setSuffix('.json')
->setArrayQuery(['query' => 'value',])->setFragment('fragment');
$url->updateSource();
echo '<br><br><b>Authority:</b> ', $url->getAuthority();
echo '<br><b>Base Url:</b> ', $url->getBaseUrl();
echo '<br><b>Relative Url:</b> ', $url->getRelativeUrl();
echo '<br><b>Absolute Url:</b> ', $url->getSource(), '<br>';
echo '<br><b>Scheme:</b> ', $url->getScheme();
echo '<br><b>User:</b> ', $url->getUser();
echo '<br><b>Password:</b> ', $url->getPassword();
echo '<br><b>Host:</b> ', $url->getHost();
echo '<br><b>Port:</b> ', $url->getPort();
echo '<br><b>Path:</b> ', $url->getPath();
echo '<br><b>Suffix:</b> ', $url->getSuffix();
echo '<br><b>Query:</b> ', $url->getQuery();
echo '<br><b>Fragment:</b> ', $url->getFragment();
$url->setSource('http://россия.рф');
$url->setConversionIdnToAscii(true)->updateSource();
echo '<br><br><b>new URL:</b> ',$url; #http://xn--h1alffa9f.xn--p1ai
Объект класса Compass\Url
может быть создан путем вызова статического метода createBlank()
, либо с помощью
оператора new
. Метод createBlank
примечателен тем, что в своей работе применяет клонирование своего же
прототипа. У данного метода есть два необязательных параметра: $isIdnToAscii
, $updateStrategy
- они определяют,
будет ли происходить преобразование хоста в punycode
, и какую стратегию обновления URL применять.
Первый параметр, $isIdnToAscii
- определяет необходимость преобразования хоста. Если он принимает значение true
,
хост преобразуется, если же false
- преобразование хоста не происходит.
Второй параметр, $updateStrategy
- определяет стратегию обновления URL. Стратегия включает в себя методы создания
составляющих URL-адреса.
Чтобы создать новый экземпляр класса Compass\Url
с помощью оператора new
необходимо передать один
обязательный параметр - это исходный URL в виде строки.
Параметры можно устанавливать с помощью:
- конструктора
- метода
$url->setSource(string $src);
- метода
$url->setAll(array $parts);
- методов отвечающих за конкретную часть Url (как показано в быстром старте).
$url = new Url('http://grigor:[email protected]:8080/path/to/resource?query=value#fragment');
$url->setSource('http://grigor:[email protected]:8080/path/to/resource?query=value#fragment');
$url->setAll([
':host' => 'host.ru',
':scheme' => 'http',
':user' => 'user',
':password' => 'password',
':port' => '80',
':path' => ['path', 'to', 'resource'],
'?' => ['key' => 'value', 'key2' => 'value2'],
'#' => 'fragment',
':suffix' => '.json',
]);
$url->setScheme('http')->setUser('grigor')->setPassword('password')->setHost('vinograd.soft')
->setPort('8080')->setPath('/path/to/resource')->setSuffix('.json')
->setArrayQuery(['query' => 'value',])->setFragment('fragment');
В первых двух вариантах суффикс не распознается. В таких случаях суффикс необходимо установить отдельным методом
$url->setSuffix(.json);
, только так вы сможете им управлять.
❗ Суффикс не анализируется, так как он может быть любой строкой, и не обязательно начинаться с точки. Если вы передаете URL с суффиксом, то он становится частью path.
Чтобы измененные параметры вступили в силу, необходимо вызвать метод $url->updateSource()
. Этот метод имеет два
необязательных аргумента - $updateAbsoluteUrl
и $suffix
. Значение аргумента $updateAbsoluteUrl
определяет, будет
ли обновляться весь URL-адрес или только его относительная часть. По умолчанию его значение равно true
, другими
словами, по умолчанию будет пытаться обновить весь URL. Параметр $suffix
имеет тип string
и позволяет установить
суффикс в моменте обновления.
После того как параметры были применены, вы можете получить обновленный результат, методом $url->getSource()
.
📢 Стратегия обновления - это объект, который объединяет все входные данные для создания итогового URL-адреса. Этот объект должен быть реализацией интерфейса
Compass\UrlStrategy
. В системе, класс, который выполняет эту функцию, называетсяCompass\DefaultUrlStrategy
.
Стратегия придумана, для того, чтобы контролировать процесс создания URL. Она содержит набор методов по одному
на каждый участок URL-адреса, в которых происходит склеивание параметров. Какие методы будут участвовать в
обновлении определяется в объекте Compass\Url
на основе состояний участков. Есть некие флаги которые говорят какие
участки нужно пересоздать. Для простоты восприятия можно провести аналогию с дорогой поделенной на какое-то количество
участков "A", "B", "C", "D" и дорожной компанией которая за нее ответственна. В идеале дорога должна быть всегда ровная.
Когда на дороге повреждается какой-нибудь участок, например "С", ремонтная бригада выезжает на этот участок и
ремонтирует его. Так же можно представить и URL-адрес, где дорога это строка у которой есть логические части - участки.
Ремонтные бригады - это методы в стратегии обновления. Дорожная компания - это объект Compass\Url
.
У стратегии есть шесть методов в которых создаются части URL-адреса:
updateAuthority()
updateBaseUrl()
updateQuery()
updatePath()
updateRelativeUrl()
updateAbsoluteUrl()
.
Устанавливая какой-либо параметр для URL, система меняет состояние участка, как бы, повреждает тот
участок для которого был передан параметр. После вызова метода $url->updateSource();
в работу включаются
соответствующие методы стратегии.
❗ Важно запомнить, что в объекте
Compass\Url
хранятся исходные части, которые передал пользователь и результаты работы каждого метода стратегии.
Выполнение методов можно поделить условно на три уровня.
УРОВЕНЬ 3
|--------------------------------updateAbsoluteUrl()---------------------------------|
| |
| УРОВЕНЬ 2 |
|---------------updateBaseUrl()-----------|------------updateRelativeUrl()-----------|
| | |
| УРОВЕНЬ 1 |
| updateAuthority() | updatePath() updateQuery() |
| /‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾\|/‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾\ /‾‾‾‾‾‾‾‾\ |
|http://grigor:[email protected]:8080/path/to/resource.json?query=value#fragment|
Метод третьего уровня updateAbsoluteUrl()
выполняется всегда, в нем соединяются сохраненные результаты работы методов
второго уровня. Методы второго уровня updateBaseUrl()
и updateRelativeUrl()
соединяют результаты работы первого
уровня. На первом уровне updateAuthority()
, updatePath()
и updateQuery()
склеивают исходные части каждый в своей
области.
Состояния хранятся в нескольких полях класса Compass\Url
. $authoritySate
, $relativeUrlState
и $schemeState
.
$authoritySate
и $relativeUrlState
имеют тип int
, $schemeState
- bool
. Управление состояниями $authoritySate
и $relativeUrlState
осуществляются битовыми операциями. Вот пример кода, который показывает их значения по умолчанию
когда состояние неповрежденное:
const USER_STATE = 1 << 0;
const PASSWORD_STATE = 1 << 1;
const HOST_STATE = 1 << 2;
const PORT_STATE = 1 << 3;
const PATH_STATE = 1 << 0;
const QUERY_STATE = 1 << 1;
const FRAGMENT_STATE = 1 << 2;
const AUTHORITY_WHOLE = self::USER_STATE | self::PASSWORD_STATE | self::HOST_STATE | self::PORT_STATE;
const RELATIVE_URL_WHOLE = self::PATH_STATE | self::QUERY_STATE | self::FRAGMENT_STATE;
/**
* current states
*/
protected int $authoritySate = self::AUTHORITY_WHOLE;
protected int $relativeUrlState = self::RELATIVE_URL_WHOLE;
protected bool $schemeState = true;
Если мы хотим повредить состояние $relativeUrlState
в области query
, то мы можем воспользоваться побитовыми
операторами:
$relativeUrlState &= ~Url::QUERY_STATE;
Остальными участками можно манипулировать аналогичным способом, исключением является только $schemeState
ему нужно
присвоить булево значение.
При построении своего процесса обновления URL, иногда требуется, чтобы выполнился метод который на основе текущего
состояния не выполниться. В таких случаях используется дополнительный метод forceUnlockMethod(...)
в котором можно
изменить текущее состояние определенного участка, тем самым заставить систему выполнить нужный метод.
Это лучше понять на примере. Представим, что нам нужно генерировать URL для реферальных ссылок. Создадим стратегию в
которой будет добавляться для всех URL с доменом another.site
параметр refid
равный 40
.
Код стратегии:
<?php
namespace <your\namespace>;
use Compass\DefaultUrlStrategy;
use Compass\Url;
class ReferralUrlStrategy extends DefaultUrlStrategy
{
private bool $isAllowInsertParam = false;
/**
* @inheritDoc
*/
public function updateQuery(array $items): string
{
if ($this->isAllowInsertParam) {
$items['refid'] = 40;
$this->isAllowInsertParam = false;
}
return http_build_query($items, '', '&', PHP_QUERY_RFC3986);
}
/**
* @inheritDoc
*/
public function forceUnlockMethod(
bool &$schemeState,
int &$authoritySate,
int &$relativeUrlState,
array $items,
array $pathItems,
array $queryItems,
bool $updateAbsoluteUrl,
?string $suffix = null
): void
{
if ($items[Url::HOST] === 'another.site') {
$this->isAllowInsertParam = true;
}
$relativeUrlState &= ~Url::QUERY_STATE;
}
}
Теперь установим стратегию и выведем два URL, один из которых будет целевым, с доменом another.site
:
$url = Url::createBlank();
$url->setUpdateStrategy(new ReferralUrlStrategy());
$url->setSource('https://another.site');
$url->updateSource();
echo $url->getSource(), '<br>'; # https://another.site/?refid=40
$url->setHost('vinograd.soft');
$url->updateSource();
echo $url->getSource(); # https://vinograd.soft
На первый взгляд может показаться, что изменение состояния ($relativeUrlState &= ~Url::QUERY_STATE;
) нужно было
написать внутри if
конструкции, но это не так. После того как мы установили хост vinograd.soft
, вызов
метода updateSource()
не привел бы к выполнению метода updateQuery
нашей стратегии, поскольку не было добавлено ни
одного параметра штатным способом, который мог бы изменить состояние этого участка. В результате состояние осталось бы
не поврежденным, обновился бы только участок baseurl
и сохраненный параметр refid=40
с прошлого раза, был бы склеен
с новым baseurl
который содержит хост vinograd.soft
.
Этот пример показывает, что вы не ограничены только штатными методами установки частей URL. Используя стратегии можно делать пост обработку результата, например когда нужно экранировать результат для HTML-атрибутов содержащих URL (href, src и другие атрибуты этого типа).
👉 Compass\Path
можно охарактеризовать как объектное представление пути к файлу. Он оперирует строкой пути не
опираясь на реальную файловую систему. Компонент так же как и Compass\Url
имеет стратегию обновления, которая включает
в себя один метод updatePath()
. Важно отметить, что этот компонент не имеет состояний.
<?php
use Compass\Path;
require_once dirname(__DIR__, 1) . '/vendor/autoload.php';
$path = new Path('/__NAME__/__NAME__Scanner/__NAME2__Driver', '/');
$path->replaceAll([
'__NAME__' => 'User',
'__NAME2__' => 'Filesystem',
]);
$path->updateSource();
echo '<br>', $path; # /User/UserScanner/FilesystemDriver
$path->setAll(['path', 'to', 'file.txt']);
$path->updateSource();
echo '<br>', $path; # path/to/file.txt
$path->set(1, 'newTo');
$path->updateSource();
echo '<br>', $path; # path/newTo/file.txt
$path->setBy('path', 'newPath');
$path->updateSource();
echo '<br>', $path; # newPath/newTo/file.txt
echo '<br>', $path->dirname(); # newPath/newTo
$path->setSuffix('.v');
$path->updateSource();
echo '<br>', $path; # newPath/newTo/file.txt.v
$path->setSource('newPath/newTo/file');
$path->setSuffix('.v');
$path->updateSource();
echo '<br>', $path; # newPath/newTo/file.v
$path->replace('newPath','path');
$path->updateSource();
echo '<br>', $path; # path/newTo/file.v
echo '<br>', $path->getLast(); # file.v
php composer tests
Пожалуйста, смотрите ВКЛАД для получения подробной информации.
Лицензия MIT (MIT). Пожалуйста, смотрите файл лицензии для получения дополнительной информации.