fix: noverify + типы для правил провеки

This commit is contained in:
origami11@yandex.ru 2025-01-21 19:33:33 +03:00
parent 9680409ba9
commit 90cbd3b2b6
10 changed files with 319 additions and 300 deletions

View file

@ -95,7 +95,7 @@ class Component
public function getView($name) public function getView($name)
{ {
if ($this->output == 'json') { if ($this->output === 'json') {
return new FakeTemplate($name); return new FakeTemplate($name);
} }
@ -126,7 +126,7 @@ class Component
} }
$tpl->stripComments(true); $tpl->stripComments(true);
$tpl->addPreFilter(new PHPTAL_PreFilter_Normalize()); $tpl->addPreFilter(new \PHPTAL_PreFilter_Normalize());
$tpl->set('common', Path::join($this->config->get('system', 'web'), '../', 'common')); $tpl->set('common', Path::join($this->config->get('system', 'web'), '../', 'common'));
$tpl->set('script', Path::join($this->config->get('system', 'web'), 'js')); $tpl->set('script', Path::join($this->config->get('system', 'web'), 'js'));
@ -152,7 +152,7 @@ class Component
$registry = $this->config; $registry = $this->config;
// Брать настройки из куков если есть // Брать настройки из куков если есть
$template = ($this->template) ? $this->template : $this->getTemplateName($registry); $template = ($this->template) ? $this->template : $this->getTemplateName($registry);
foreach ($this->viewPath as $index => $viewPath) { foreach ($this->viewPath as $index => $_) {
if(is_dir(Path::join($this->viewPath[$index], 'templates', $template))) { if(is_dir(Path::join($this->viewPath[$index], 'templates', $template))) {
return Path::join($this->viewPath[$index], 'templates', $template, $name); return Path::join($this->viewPath[$index], 'templates', $template, $name);
} }

View file

@ -1,192 +1,202 @@
<?php <?php
namespace { namespace {
if(!function_exists('sqliteLower')){ if (!function_exists('sqliteLower')) {
function sqliteLower($str) { function sqliteLower($str)
{
return mb_strtolower($str, 'UTF-8'); return mb_strtolower($str, 'UTF-8');
} }
} }
} }
namespace ctiso { namespace ctiso {
use PDO, use PDO,
ctiso\Database\Statement, ctiso\Database\Statement,
ctiso\Database\PDOStatement, ctiso\Database\PDOStatement,
ctiso\Database\IdGenerator; ctiso\Database\IdGenerator;
/**
* Класс оболочка для PDO для замены Creole
*/
class Database extends PDO
{
public $dsn;
public function __construct($dsn, $username = null, $password = null)
{
parent::__construct($dsn, $username, $password);
$this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$this->setAttribute(PDO::ATTR_STATEMENT_CLASS, [PDOStatement::class, []]);
}
function prepare(string $sql, array $options = []): PDOStatement|false {
$result/*: PDOStatement*/ = parent::prepare($sql, $options);
return $result;
}
public function getDSN()
{
return $this->dsn;
}
public function isPostgres(){
return ($this->dsn["phptype"] == "pgsql");
}
/** /**
* Создает соединение с базой данных * Класс оболочка для PDO для замены Creole
*/ */
static function getConnection(array $dsn) class Database extends PDO
{ {
$connection = null; public $dsn;
if ($dsn['phptype'] == 'pgsql' || $dsn['phptype'] == 'mysql') { public function __construct($dsn, $username = null, $password = null)
$port = (isset($dsn['port'])) ? "port={$dsn['port']};" : ""; {
$connection/*: Database*/ = new self("{$dsn['phptype']}:host={$dsn['hostspec']}; $port dbname={$dsn['database']}", $dsn['username'], $dsn['password']); parent::__construct($dsn, $username, $password);
if ($dsn['phptype'] == 'pgsql') { $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$connection->query('SET client_encoding="UTF-8"'); $this->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
} $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, [PDOStatement::class, []]);
if (isset($dsn['schema'])) {
$connection->query('SET search_path TO ' . $dsn['schema']);
}
} elseif ($dsn['phptype'] == 'sqlite::memory') {
$connection = new self("{$dsn['phptype']}:");
$connection->sqliteCreateFunction('LOWER', 'sqliteLower', 1);
} elseif ($dsn['phptype'] == 'sqlite') {
$connection/*: Database*/ = new self("{$dsn['phptype']}:{$dsn['database']}");
$connection->setAttribute(PDO::ATTR_TIMEOUT, 5);
$mode = defined('SQLITE_JOURNAL_MODE') ? SQLITE_JOURNAL_MODE : 'WAL';
$connection->query("PRAGMA journal_mode=$mode");
$connection->sqliteCreateFunction('LOWER', 'sqliteLower', 1);
} }
$connection->dsn = $dsn;
return $connection;
}
public function executeQuery($query, $values=null): PDOStatement|bool function prepare(string $sql, array $options = []): PDOStatement|false
{ {
$stmt = $this->prepare($query); $result/*: PDOStatement*/ = parent::prepare($sql, $options);
return $result;
}
$stmt->execute($values); public function getDSN()
$stmt->cache = $stmt->fetchAll(PDO::FETCH_ASSOC); {
return $stmt; return $this->dsn;
} }
public function isPostgres()
{
return ($this->dsn["phptype"] == "pgsql");
}
/**
* Создает соединение с базой данных
*/
static function getConnection(array $dsn)
{
public function prepareStatement($query) $connection = null;
{ if ($dsn['phptype'] == 'pgsql' || $dsn['phptype'] == 'mysql') {
return new Statement($query, $this); $port = (isset($dsn['port'])) ? "port={$dsn['port']};" : "";
} $connection/*: Database*/ = new self("{$dsn['phptype']}:host={$dsn['hostspec']}; $port dbname={$dsn['database']}", $dsn['username'], $dsn['password']);
if ($dsn['phptype'] == 'pgsql') {
$connection->query('SET client_encoding="UTF-8"');
}
// Для совместимости со старым представлением баз данных CIS if (isset($dsn['schema'])) {
/** $connection->query('SET search_path TO ' . $dsn['schema']);
* Извлекает из базы все элементы по запросу }
*/ } elseif ($dsn['phptype'] == 'sqlite::memory') {
public function fetchAllArray($query, $values = null) $connection = new self("{$dsn['phptype']}:");
{ $connection->sqliteCreateFunction('LOWER', 'sqliteLower', 1);
$sth = $this->prepare($query); } elseif ($dsn['phptype'] == 'sqlite') {
$prep = $this->prepareValues($values); $connection/*: Database*/ = new self("{$dsn['phptype']}:{$dsn['database']}");
$sth->execute($prep); $connection->setAttribute(PDO::ATTR_TIMEOUT, 5);
return $sth->fetchAll(PDO::FETCH_ASSOC); $mode = defined('SQLITE_JOURNAL_MODE') ? SQLITE_JOURNAL_MODE : 'WAL';
} $connection->query("PRAGMA journal_mode=$mode");
$connection->sqliteCreateFunction('LOWER', 'sqliteLower', 1);
}
$connection->dsn = $dsn;
return $connection;
}
/** public function executeQuery($query, $values = null): PDOStatement|bool
* Извлекает из базы первый элемент по запросу {
*/ $stmt = $this->prepare($query);
public function fetchOneArray($query, $values = null)
{
$sth = $this->prepare($query);
$prep = $this->prepareValues($values);
$sth->execute($prep);
return $sth->fetch(PDO::FETCH_ASSOC);
}
private function prepareValues($values) $stmt->execute($values);
{ $stmt->cache = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (!$values) { return $stmt;
}
public function prepareStatement($query)
{
return new Statement($query, $this);
}
// Для совместимости со старым представлением баз данных CIS
/**
* Извлекает из базы все элементы по запросу
*/
public function fetchAllArray($query, $values = null)
{
$sth = $this->prepare($query);
$prep = $this->prepareValues($values);
$sth->execute($prep);
return $sth->fetchAll(PDO::FETCH_ASSOC);
}
/**
* Извлекает из базы первый элемент по запросу
*/
public function fetchOneArray($query, $values = null)
{
$sth = $this->prepare($query);
$prep = $this->prepareValues($values);
$sth->execute($prep);
return $sth->fetch(PDO::FETCH_ASSOC);
}
private function prepareValues($values)
{
if (!$values) {
return null;
}
$pg = $this->isPostgres();
$prep = [];
foreach ($values as $key => $value) {
$result = null;
if (is_bool($value)) {
if ($pg) {
$result = $value ? 'true' : 'false';
} else {
$result = $value ? 1 : 0;
}
} else {
$result = $value;
}
$prep[":" . $key] = $result;
}
return $prep;
}
/**
* Создает INSERT запрос
*/
function insertQuery($table, array $values, $return_id = false, $index = null)
{
$prep = $this->prepareValues($values);
$sql = "INSERT INTO $table (" . implode(",", array_keys($values))
. ") VALUES (" . implode(",", array_keys($prep)) . ")";
if ($return_id) {
if ($this->isPostgres()) {
$sql .= " RETURNING $index";
}
}
$stmt = $this->prepare($sql);
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$stmt->execute($prep);
$result = $stmt->fetch();
if ($return_id) {
if ($this->isPostgres()) {
return $result[$index];
} else {
$result = $this->fetchOneArray("SELECT $index AS lastid FROM $table WHERE OID = last_insert_rowid()");
return $result['lastid'];
}
}
}
/**
* Создает UPDATE запрос
*/
function updateQuery($table, array $values, $cond)
{
$prep = $this->prepareValues($values);
$sql = "UPDATE $table SET " . implode(
",",
array_map(function ($k, $v) {
return $k . "=" . $v; }, array_keys($values), array_keys($prep))
) . " WHERE $cond";
$stmt = $this->prepare($sql);
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$stmt->execute($prep);
}
function getIdGenerator()
{
return new IdGenerator($this);
}
/**
* Замечание: Только для Postgres SQL
* @param string $seq Имя последовательности для ключа таблицы
* @return int Идентефикатор следующей записи
*/
function getNextId($seq)
{
$result = $this->fetchOneArray("SELECT nextval('$seq')");
return $result['nextval'];
}
function close()
{
return null; return null;
} }
$pg = $this->isPostgres();
$prep = [];
foreach ($values as $key => $value) {
$result = null;
if(is_bool($value)) {
if ($pg) {
$result = $value ? 'true' : 'false';
} else {
$result = $value ? 1 : 0;
}
} else {
$result = $value;
}
$prep[":" . $key] = $result;
}
return $prep;
} }
/** }
* Создает INSERT запрос
*/
function insertQuery($table, array $values, $return_id = false, $index = null)
{
$prep = $this->prepareValues($values);
$sql = "INSERT INTO $table (" . implode(",", array_keys($values))
. ") VALUES (" . implode(",", array_keys($prep)). ")";
if ($return_id) {
if ($this->isPostgres()){
$sql .= " RETURNING $index";
}
}
$stmt = $this->prepare($sql);
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$stmt->execute($prep);
$result = $stmt->fetch();
if ($return_id) {
if ($this->isPostgres()) {
return $result[$index];
} else {
$result = $this->fetchOneArray("SELECT $index AS lastid FROM $table WHERE OID = last_insert_rowid()");
return $result['lastid'];
}
}
}
/**
* Создает UPDATE запрос
*/
function updateQuery($table, array $values, $cond)
{
$prep = $this->prepareValues($values);
$sql = "UPDATE $table SET " . implode(",",
array_map(function($k,$v){return $k."=".$v;}, array_keys($values), array_keys($prep))) . " WHERE $cond";
$stmt = $this->prepare($sql);
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$stmt->execute($prep);
}
function getIdGenerator() {
return new IdGenerator($this);
}
/**
* Замечание: Только для Postgres SQL
* @param string $seq Имя последовательности для ключа таблицы
* @return int Идентефикатор следующей записи
*/
function getNextId($seq) {
$result = $this->fetchOneArray("SELECT nextval('$seq')");
return $result['nextval'];
}
function close() {
return null;
}
}}

View file

@ -33,7 +33,7 @@ class JsonInstall {
} }
function missingTables($tables) { function missingTables($tables) {
$actual_tables = $this->db_manager->GetAllTableNames(); $actual_tables = $this->db_manager->getAllTableNames();
$missingTables = []; $missingTables = [];
foreach ($tables as $table) { foreach ($tables as $table) {
if (!in_array($table, $actual_tables)) if (!in_array($table, $actual_tables))
@ -118,7 +118,7 @@ class JsonInstall {
//Выполнение действий //Выполнение действий
foreach ($actions as $action) { foreach ($actions as $action) {
$this->db_manager->ExecuteAction($action, $dbfill_file_path); $this->db_manager->executeAction($action, $dbfill_file_path);
} }
} else { } else {
echo "Invalid dbfill.json"; echo "Invalid dbfill.json";
@ -133,13 +133,13 @@ class JsonInstall {
$pg = $this->db_manager->db->isPostgres(); $pg = $this->db_manager->db->isPostgres();
if ($pg) { if ($pg) {
foreach ($this->serialColumns as $serialColumn) { foreach ($this->serialColumns as $serialColumn) {
$this->db_manager->UpdateSerial($serialColumn["table"], $serialColumn["column"]); $this->db_manager->updateSerial($serialColumn["table"], $serialColumn["column"]);
} }
foreach ($initActions as $action) { foreach ($initActions as $action) {
if ($action["type"] == "alterReference") { if ($action["type"] == "alterReference") {
$this->db_manager->ExecuteAction($action); $this->db_manager->executeAction($action);
} }
} }
} }

View file

@ -1,13 +1,13 @@
<?php <?php
/** /**
* Класс оболочка для PDOStatement для замены Creole * Класс оболочка для PDOStatement для замены Creole
*/ */
namespace ctiso\Database; namespace ctiso\Database;
use PDO, use PDO,
ctiso\Database; ctiso\Database;
class Statement class Statement
{ {
protected $limit = null; protected $limit = null;
protected $offset = null; protected $offset = null;
@ -16,12 +16,12 @@ class Statement
protected $conn; protected $conn;
protected $query; protected $query;
function __construct($query, $conn/*: Database*/) { function __construct($query, $conn/*: Database*/) {
$this->query = $query; $this->query = $query;
$this->conn = $conn; $this->conn = $conn;
} }
function setInt($n, $value) { function setInt($n, $value) {
$this->binds [] = [$n, $value, PDO::PARAM_INT]; $this->binds [] = [$n, $value, PDO::PARAM_INT];
} }

View file

@ -17,21 +17,21 @@ class Document {
} }
/** /**
* Добавление стиля к документу * Добавление стиля к документу
* @param $name string Имя стиля * @param string $name string Имя стиля
* @param $values array Параметры стиля * @param array $values array Параметры стиля
* @param $type Тип стиля * @param string $type Тип стиля
*/ */
function setStyle ($name, array $values, $type = 'Interior') function setStyle ($name, array $values, $type = 'Interior')
{ {
if(!isset($this->styles[$name])) { if(!isset($this->styles[$name])) {
$this->styles[$name] = []; $this->styles[$name] = [];
} }
$this->styles[$name][$type] = $values; $this->styles[$name][$type] = $values;
} }
/** /**
* Генерация стилей * Генерация стилей
*/ */
private function createStyles (XMLWriter $doc) { private function createStyles (XMLWriter $doc) {
$doc->startElement('Styles'); $doc->startElement('Styles');
@ -43,7 +43,6 @@ class Document {
if ($type == 'Borders') { if ($type == 'Borders') {
$doc->startElement('Borders'); $doc->startElement('Borders');
foreach ($s as $border) { foreach ($s as $border) {
$border/*: array*/ = $border;
$doc->startElement('Border'); $doc->startElement('Border');
foreach ($border as $key => $value) { foreach ($border as $key => $value) {
$doc->writeAttribute('ss:' . $key, $value); $doc->writeAttribute('ss:' . $key, $value);
@ -72,8 +71,8 @@ class Document {
return strtr($s, ["\n" => "&#10;"]); return strtr($s, ["\n" => "&#10;"]);
} }
/** /**
* Сохраняет таблицу в формате Office 2003 XML * Сохраняет таблицу в формате Office 2003 XML
* http://en.wikipedia.org/wiki/Microsoft_Office_XML_formats * http://en.wikipedia.org/wiki/Microsoft_Office_XML_formats
*/ */
@ -90,7 +89,7 @@ class Document {
$doc->writeAttribute('xmlns:ss', self::$ns); $doc->writeAttribute('xmlns:ss', self::$ns);
$this->createStyles($doc); $this->createStyles($doc);
foreach ($this->table as $table) { foreach ($this->table as $table) {
if ($table instanceof Table) { if ($table instanceof Table) {
$table->createTable($doc); $table->createTable($doc);

View file

@ -1,14 +1,14 @@
<?php <?php
/** /**
* Клетка таблицы * Клетка таблицы
*/ */
namespace ctiso\Excel; namespace ctiso\Excel;
use XMLWriter, use XMLWriter,
ctiso\Excel\DateTime as Excel_DateTime, ctiso\Excel\DateTime as Excel_DateTime,
ctiso\Excel\Number as Excel_Number; ctiso\Excel\Number as Excel_Number;
class TableCell class TableCell
{ {
public $style = false; public $style = false;
public $value; public $value;
@ -21,27 +21,27 @@ class TableCell
} }
/** /**
* Ряд таблицы * Ряд таблицы
*/ */
class TableRow class TableRow
{ {
public $style = false; public $style = false;
public $cells = array(); public $cells = array();
public $height = false; public $height = false;
function setCell($y, $value) function setCell($y, $value)
{ {
$this->cells[$y] = new TableCell($value); $this->cells[$y] = new TableCell($value);
} }
function setCellStyle($y, $name) function setCellStyle($y, $name)
{ {
$this->cells[$y]->style = $name; $this->cells[$y]->style = $name;
} }
} }
/** /**
* Таблица * Таблица
*/ */
class Table class Table
{ {
@ -59,7 +59,7 @@ class Table
} }
/** /**
* Записать значение в клетку с заданными координатами * Записать значение в клетку с заданными координатами
*/ */
function setCell($x, $y, $value) function setCell($x, $y, $value)
{ {
@ -116,7 +116,7 @@ class Table
* Обьединяет клетки в строке * Обьединяет клетки в строке
* @param $row Номер ряда * @param $row Номер ряда
* @param $cell Номер столбца * @param $cell Номер столбца
* @param $merge Количество клеток для обьединения * @param $merge Количество клеток для обьединения
*/ */
function setCellMerge($x, $cell, $merge) function setCellMerge($x, $cell, $merge)
{ {
@ -129,9 +129,9 @@ class Table
/** /**
* Устанавливает стиль для клеток ряда * Устанавливает стиль для клеток ряда
* @param $row integer Номер ряда * @param int $row Номер ряда
* @param $y integer Номер столбца * @param int $y Номер столбца
* @parma $name string Имя стиля * @param string $name Имя стиля
*/ */
function setCellStyle ($row, $y, $name) function setCellStyle ($row, $y, $name)
{ {
@ -141,41 +141,41 @@ class Table
/** /**
* Добавляет строку к таблице * Добавляет строку к таблице
*/ */
function addRow($index = 1, array $data = [""]) function addRow($index = 1, array $data = [""])
{ {
assert(is_numeric($index) && $index > 0); assert(is_numeric($index) && $index > 0);
$offset = $this->getRows() + 1; $offset = $this->getRows() + 1;
$this->setRow($offset, $index, $data); $this->setRow($offset, $index, $data);
return $offset; return $offset;
} }
/** /**
* Количество строк в таблице * Количество строк в таблице
* *
* @return int * @return int
*/ */
function getRows() function getRows()
{ {
$keys/*: array*/ = array_keys($this->rows); $keys/*: array*/ = array_keys($this->rows);
return max($keys); return max($keys);
} }
/** /**
* Количество столбцов в строке * Количество столбцов в строке
* *
* @return int * @return int
*/ */
function getRowCells(TableRow $row) function getRowCells(TableRow $row)
{ {
$keys/*: array*/ = array_keys($row->cells); $keys/*: array*/ = array_keys($row->cells);
return max($keys); return max($keys);
} }
/** /**
* Разделяет таблицу на две части по вертикали * Разделяет таблицу на две части по вертикали
* @param $n integer Количество столбцов слева * @param int $n Количество столбцов слева
*/ */
function splitVertical($n) { function splitVertical($n) {
$this->_splitVertical = $n; $this->_splitVertical = $n;
@ -183,7 +183,7 @@ class Table
/** /**
* Разделяет таблицу на две части по горизонтали * Разделяет таблицу на две части по горизонтали
* @param $n integer Количество столбцов сверху * @param int $n Количество столбцов сверху
*/ */
function splitHorizontal($n) { function splitHorizontal($n) {
$this->_splitHorizontal = $n; $this->_splitHorizontal = $n;
@ -192,9 +192,9 @@ class Table
/** /**
* Количество столбцов в таблице * Количество столбцов в таблице
* *
* @return int * @return int
*/ */
function getColumns() { function getColumns() {
return max(array_map([$this, 'getRowCells'], $this->rows)); return max(array_map([$this, 'getRowCells'], $this->rows));
} }
@ -228,21 +228,21 @@ class Table
$doc->text($value->getString()); $doc->text($value->getString());
} else if ($value instanceof Excel_Number) { } else if ($value instanceof Excel_Number) {
$doc->writeAttribute('ss:Type', "Number"); $doc->writeAttribute('ss:Type', "Number");
$doc->text($value->getString()); $doc->text($value->getString());
} else { } else {
if (is_string($value)) { if (is_string($value)) {
$doc->writeAttribute('ss:Type', "String"); $doc->writeAttribute('ss:Type', "String");
} else { } else {
$doc->writeAttribute('ss:Type', "Number"); $doc->writeAttribute('ss:Type', "Number");
} }
$doc->writeCdata($this->encode($value)); $doc->writeCdata($this->encode($value));
} }
$doc->endElement();
$doc->endElement(); $doc->endElement();
$doc->endElement();
} }
/** /**
* Генерация таблицы * Генерация таблицы
*/ */
public function createTable (XMLWriter $doc) { public function createTable (XMLWriter $doc) {
$doc->startElement('Worksheet'); $doc->startElement('Worksheet');
@ -271,19 +271,19 @@ class Table
// Флаг индикатор подстановки номера столбца // Флаг индикатор подстановки номера столбца
$setIndex = false; $setIndex = false;
for ($j = 1; $j <= $columns; $j++) { for ($j = 1; $j <= $columns; $j++) {
$value = null; $value = null;
if (isset($nrow->cells[$j])) { if (isset($nrow->cells[$j])) {
$value = $nrow->cells[$j]->value; $value = $nrow->cells[$j]->value;
} }
if (!empty($value)) { if (!empty($value)) {
$this->createCell($nrow->cells[$j], $doc, $j, $value, $setIndex); $this->createCell($nrow->cells[$j], $doc, $j, $value, $setIndex);
$setIndex = false; $setIndex = false;
} else { } else {
$setIndex = true; $setIndex = true;
} }
} }
} }
$doc->endElement(); $doc->endElement();
} }
@ -293,7 +293,7 @@ class Table
} }
protected function splitPane (XMLWriter $doc) { protected function splitPane (XMLWriter $doc) {
$doc->startElement('WorksheetOptions'); $doc->startElement('WorksheetOptions');
$doc->writeAttribute('xmlns', 'urn:schemas-microsoft-com:office:excel'); $doc->writeAttribute('xmlns', 'urn:schemas-microsoft-com:office:excel');
$doc->writeElement('FrozenNoSplit'); $doc->writeElement('FrozenNoSplit');

View file

@ -73,6 +73,12 @@ class Form extends View {
return '_form_edit'; return '_form_edit';
} }
/**
* Добавление конструкторя для поля формы
* @param string $name Краткое название поля
* @param class-string<Field> $class
* @return void
*/
public function addFieldClass($name, $class) public function addFieldClass($name, $class)
{ {
$this->constructor [$name] = $class; $this->constructor [$name] = $class;
@ -80,6 +86,7 @@ class Form extends View {
/** /**
* Добавляет одно поле ввода на форму * Добавляет одно поле ввода на форму
* @return Field
*/ */
public function addField(array $init, $factory = null) public function addField(array $init, $factory = null)
{ {

View file

@ -8,13 +8,13 @@
namespace ctiso; namespace ctiso;
class Path class Path
{ {
const SEPARATOR = "/"; const SEPARATOR = "/";
protected $path = array(); protected $path = array();
protected $url = array(); protected $url = array();
protected $absolute = false; protected $absolute = false;
public function __construct($path = '') public function __construct($path = '')
{ {
@ -24,7 +24,7 @@ class Path
if (isset($this->url['path'])) { if (isset($this->url['path'])) {
$path = $this->url['path']; $path = $this->url['path'];
// $path = preg_replace('/\/{2,}/', '/', $path); // $path = preg_replace('/\/{2,}/', '/', $path);
$list = $this->listFromString($path); $list = self::listFromString($path);
if (isset($this->url['scheme']) && !isset($this->url['host'])) { if (isset($this->url['scheme']) && !isset($this->url['host'])) {
$this->absolute = false; $this->absolute = false;
@ -32,9 +32,9 @@ class Path
$this->absolute = true; $this->absolute = true;
} }
$this->path = $this->optimize($list); $this->path = self::optimize($list);
} }
} }
static function factory($path) { static function factory($path) {
return new Path($path); return new Path($path);
@ -87,14 +87,14 @@ class Path
* *
* @param string $fileName Имя файла * @param string $fileName Имя файла
* *
* @return string * @return string
*/ */
static function skipExtension($fileName) static function skipExtension($fileName)
{ {
assert(is_string($fileName)); assert(is_string($fileName));
$path = pathinfo($fileName); $path = pathinfo($fileName);
if ($path['dirname'] == ".") { if ($path['dirname'] === ".") {
return $path['filename']; return $path['filename'];
} else { } else {
return self::join($path['dirname'], $path['filename']); return self::join($path['dirname'], $path['filename']);
@ -134,22 +134,22 @@ class Path
} }
/** /**
* Преобразует относительный путь в абсолютный * Преобразует относительный путь в абсолютный
*/ */
public static function optimize($path) // public static function optimize($path) //
{ {
$result = []; $result = [];
foreach ($path as $n) { foreach ($path as $n) {
switch ($n) { switch ($n) {
// Может быть относительным или абсолютным путем // Может быть относительным или абсолютным путем
case "": break; case "": case ".": break;
case ".": break;
case "..": case "..":
if (count($result) > 0 && $result[count($result) - 1] != '..') { if (count($result) > 0 && $result[count($result) - 1] != '..') {
array_pop($result); break; array_pop($result); break;
} }
break;
default: default:
array_push($result, $n); $result[] = $n;
} }
} }
return $result; return $result;
@ -162,7 +162,7 @@ class Path
if ($count == count($path->path)) { if ($count == count($path->path)) {
for ($i = 0; $i < $count; $i++) { for ($i = 0; $i < $count; $i++) {
if ($this->path[$i] != $path->path[$i]) { if ($this->path[$i] != $path->path[$i]) {
return false; return false;
} }
} }
return true; return true;
@ -170,16 +170,16 @@ class Path
return false; return false;
} }
public static function makeUrl($path) public static function makeUrl($path)
{ {
$slash = (isset($path['host']) && (strlen($path['path']) > 0) && ($path['path'][0] != '/')) ? '/' : ''; $slash = (isset($path['host']) && (strlen($path['path']) > 0) && ($path['path'][0] != '/')) ? '/' : '';
return (isset($path['scheme']) ? $path['scheme'] . ':/' : '') return (isset($path['scheme']) ? $path['scheme'] . ':/' : '')
. (isset($path['host']) ? ('/' . (isset($path['host']) ? ('/'
. (isset($path['user']) ? $path['user'] . (isset($path['pass']) ? ':' . $path['pass'] : '') . '@' : '') . (isset($path['user']) ? $path['user'] . (isset($path['pass']) ? ':' . $path['pass'] : '') . '@' : '')
. $path['host'] . $path['host']
. (isset($path['port']) ? ':' . $path['port'] : '')) : '') . (isset($path['port']) ? ':' . $path['port'] : '')) : '')
. $slash . $slash
. $path['path'] . $path['path']
. (isset($path['query']) ? '?' . $path['query'] : '') . (isset($path['query']) ? '?' . $path['query'] : '')
. (isset($path['fragment']) ? '#' . $path['fragment'] : ''); . (isset($path['fragment']) ? '#' . $path['fragment'] : '');
@ -188,7 +188,7 @@ class Path
/** /**
* Преобразует путь в строку * Преобразует путь в строку
* *
* @return string * @return string
*/ */
public function __toString() public function __toString()
{ {
@ -200,13 +200,13 @@ class Path
/** /**
* Проверяет является ли папка родительской для другой папки * Проверяет является ли папка родительской для другой папки
* *
* @parma Path $path * @parma Path $path
* *
* @return boolean * @return boolean
*/ */
public function isParent($path/*: Path*/) public function isParent($path/*: Path*/)
{ {
if (isset($this->url['host']) && isset($path->url['host']) if (isset($this->url['host']) && isset($path->url['host'])
&& ($this->url['host'] != $path->url['host'])) return false; && ($this->url['host'] != $path->url['host'])) return false;
$count = count($this->path); $count = count($this->path);
@ -226,11 +226,11 @@ class Path
$path = new Path($path1); $path = new Path($path1);
return $path->isParent(new Path($path2)); return $path->isParent(new Path($path2));
} }
/** /**
* Находит путь относительно текущего путя * Находит путь относительно текущего путя
* *
* @param string $name Полный путь к файлу * @param string $name Полный путь к файлу
* *
* @return string Относительный путь к файлу * @return string Относительный путь к файлу
*/ */
@ -257,10 +257,10 @@ class Path
$result = []; $result = [];
$count = count($list_path); $count = count($list_path);
for ($i = 0; $i < $count; $i++) { for ($i = 0; $i < $count; $i++) {
if (($i >= count($self_path)) || $list_path[$i] != $self_path[$i]) { if (($i >= count($self_path)) || $list_path[$i] != $self_path[$i]) {
break; break;
} }
} }
$list_count = count($list_path); $list_count = count($list_path);
for($j = $i; $j < $list_count; $j++) { for($j = $i; $j < $list_count; $j++) {
array_push($result, '..'); array_push($result, '..');
@ -281,7 +281,7 @@ class Path
/** /**
* Обьединяет строки в Path соединяя необходимым разделителем * Обьединяет строки в Path соединяя необходимым разделителем
* fixme не обрабатывает параметры урла, решение Path::join(SITE_WWW_PATH) . '?param=pampam' * fixme не обрабатывает параметры урла, решение Path::join(SITE_WWW_PATH) . '?param=pampam'
* @return string * @return string
*/ */
static function fromJoin($_rest) { static function fromJoin($_rest) {
$args = func_get_args(); $args = func_get_args();
@ -295,7 +295,7 @@ class Path
} }
// При обьединении ссылок можно обьеденить path, query, fragment // При обьединении ссылок можно обьеденить path, query, fragment
$path = implode(self::SEPARATOR, self::optimize(call_user_func_array('array_merge', $result))); $path = implode(self::SEPARATOR, self::optimize(call_user_func_array('array_merge', $result)));
$parts0->url['path'] = ($parts0->isAbsolute()) ? '/' . $path : $path; $parts0->url['path'] = ($parts0->isAbsolute()) ? '/' . $path : $path;
return $parts0; return $parts0;
} }
@ -303,7 +303,7 @@ class Path
/** /**
* Обьединяет строки в строку пути соединяя необходимым разделителем * Обьединяет строки в строку пути соединяя необходимым разделителем
* fixme не обрабатывает параметры урла, решение Path::join(SITE_WWW_PATH) . '?param=pampam' * fixme не обрабатывает параметры урла, решение Path::join(SITE_WWW_PATH) . '?param=pampam'
* @return string * @return string
*/ */
static function join($_rest) static function join($_rest)
{ {
@ -324,11 +324,11 @@ class Path
return ((($ch >= ord('a')) && ($ch <= ord('z'))) || (strpos('-._', $char) !== false) || (($ch >= ord('0')) && ($ch <= ord('9')))); return ((($ch >= ord('a')) && ($ch <= ord('z'))) || (strpos('-._', $char) !== false) || (($ch >= ord('0')) && ($ch <= ord('9'))));
} }
// Проверка имени файла // Проверка имени файла
static function isName($name) { static function isName($name) {
if (strlen(trim($name)) == 0) { if (strlen(trim($name)) == 0) {
return false; return false;
} }
for ($i = 0; $i < strlen($name); $i++) { for ($i = 0; $i < strlen($name); $i++) {
if (!self::isCharName($name[$i])) { if (!self::isCharName($name[$i])) {
return false; return false;
@ -363,13 +363,13 @@ class Path
} }
/** /**
* Список файлов в директории * Список файлов в директории
* *
* @param array $allow массив расширений для файлов * @param array $allow массив расширений для файлов
* @param array $ignore массив имен пааок которые не нужно обрабатывать * @param array $ignore массив имен пааок которые не нужно обрабатывать
* *
* @returnarray * @returnarray
*/ */
public function getContent($allow = null, $ignore = []) public function getContent($allow = null, $ignore = [])
{ {
@ -379,12 +379,12 @@ class Path
/** /**
* Обьединяет строки в путь соединяя необходимым разделителем * Обьединяет строки в путь соединяя необходимым разделителем
* *
* @param array $allow массив расширений разрешеных для файлов * @param array $allow массив расширений разрешеных для файлов
* @param array $ignore массив имен пааок которые не нужно обрабатывать * @param array $ignore массив имен пааок которые не нужно обрабатывать
* *
* @return array * @return array
*/ */
function getContentRec($allow = null, $ignore = []) function getContentRec($allow = null, $ignore = [])
{ {
$result = []; $result = [];
@ -406,7 +406,7 @@ class Path
if (! in_array($file, $ignore)) { if (! in_array($file, $ignore)) {
$isDir = is_dir(Path::join($base, $file)); $isDir = is_dir(Path::join($base, $file));
if ($isDir || ($allow == null) || in_array(self::getExtension($file), $allow)) { if ($isDir || ($allow == null) || in_array(self::getExtension($file), $allow)) {
$result[] = $file; $result[] = $file;
} }
} }
continue; continue;
@ -418,7 +418,7 @@ class Path
// При обьединении ссылок можно обьеденить path, query, fragment // При обьединении ссылок можно обьеденить path, query, fragment
return $result; return $result;
} }
protected static function fileListAll(&$result, $base, &$allow, &$ignore) protected static function fileListAll(&$result, $base, &$allow, &$ignore)
{ {
$files = self::fileList($base, $allow, $ignore); $files = self::fileList($base, $allow, $ignore);
@ -453,11 +453,11 @@ class Path
/** /**
* Обновить относительную ссылку при переносе файла * Обновить относительную ссылку при переносе файла
* *
* @param string $relativePath - относительная ссылка до переноса * @param string $relativePath - относительная ссылка до переноса
* @param string $srcFile - абсолютный путь к папке содержащей файл со ссылкой до переноса * @param string $srcFile - абсолютный путь к папке содержащей файл со ссылкой до переноса
* @param string $dstFile - абсолютный путь к папке содержащей файл со ссылкой после переноса * @param string $dstFile - абсолютный путь к папке содержащей файл со ссылкой после переноса
* *
* @return string * @return string
*/ */
static function updateRelativePathOnFileMove($relativePath, $srcFile, $dstFile) { static function updateRelativePathOnFileMove($relativePath, $srcFile, $dstFile) {
@ -467,12 +467,12 @@ class Path
/** /**
* Обновить относительную ссылку в файле при переносе папки * Обновить относительную ссылку в файле при переносе папки
* *
* @param string $relativePath относительная ссылка до переноса * @param string $relativePath относительная ссылка до переноса
* @param string $fileDir абсолютный путь к директории файла содержащего ссылку до переноса * @param string $fileDir абсолютный путь к директории файла содержащего ссылку до переноса
* @param string $srcDir абсолютный путь к переносимой директории до переноса * @param string $srcDir абсолютный путь к переносимой директории до переноса
* @param string $dstDir абсолютный путь к переносимой директории после переноса * @param string $dstDir абсолютный путь к переносимой директории после переноса
* *
* @return string * @return string
*/ */
static function updateRelativePathOnDirectoryMove($relativePath, $fileDir, $srcDir, $dstDir) { static function updateRelativePathOnDirectoryMove($relativePath, $fileDir, $srcDir, $dstDir) {

View file

@ -10,20 +10,14 @@ use ctiso\Validator\Rule\AbstractRule,
class Email extends AbstractRule class Email extends AbstractRule
{ {
public function getErrorMsg() public function getErrorMsg()
{ {
return "Неверный формат электронной почты"; return "Неверный формат электронной почты";
} }
public function isValid(Collection $container, $status = null) public function isValid(Collection $container, $status = null)
{ {
$user = '[a-zA-Z0-9_\-\.\+\^!#\$%&*+\/\=\?\|\{\}~\']+';
$doIsValid = '(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9]\.?)+';
$ipv4 = '[0-9]{1,3}(\.[0-9]{1,3}){3}';
$ipv6 = '[0-9a-fA-F]{1,4}(\:[0-9a-fA-F]{1,4}){7}';
$emails = explode(",", $container->get($this->field)); $emails = explode(",", $container->get($this->field));
foreach ($emails as $email) { foreach ($emails as $email) {
// if (! preg_match("/^$user@($doIsValid|(\[($ipv4|$ipv6)\]))$/", $email)) return false;
if (! filter_var($email, FILTER_VALIDATE_EMAIL)) return false; if (! filter_var($email, FILTER_VALIDATE_EMAIL)) return false;
} }

View file

@ -12,24 +12,29 @@ use Exception,
class Validator class Validator
{ {
protected $chain = array(); // Массив правил protected $chain = []; // Массив правил
protected $errorMsg = array(); // Массив ошибок protected $errorMsg = []; // Массив ошибок
protected $type = array(
'date' => 'ctiso\\Validator\\Rule\\Date', /**
'email' => 'ctiso\\Validator\\Rule\\Email', * Поля по умолчанию
'emaillist'=> 'ctiso\\Validator\\Rule\\EmailList', * @var array<string, class-string<Rule\AbstractRule>>
'match' => 'ctiso\\Validator\\Rule\\MatchRule', */
'time' => 'ctiso\\Validator\\Rule\\Time', protected $type = [
'alpha' => 'ctiso\\Validator\\Rule\\Alpha', 'date' => Rule\Date::class,
'require' => 'ctiso\\Validator\\Rule\\Notnull', 'email' => Rule\Email::class,
'numeric' => 'ctiso\\Validator\\Rule\\Numeric', 'emaillist'=> Rule\EmailList::class,
'unique' => 'ctiso\\Validator\\Rule\\Unique', 'match' => Rule\MatchRule::class,
'filename' => 'ctiso\\Validator\\Rule\\FileName', 'time' => Rule\Time::class,
'count' => 'ctiso\\Validator\\Rule\\Count', 'alpha' => Rule\Alpha::class,
'isfile' => 'ctiso\\Validator\\Rule\\IsFile', 'require' => Rule\Notnull::class,
'code' => 'ctiso\\Validator\\Rule\\Code', 'numeric' => Rule\Numeric::class,
'reg' => 'ctiso\\Validator\\Rule\\PregMatch', 'unique' => Rule\Unique::class,
); 'filename' => Rule\FileName::class,
'count' => Rule\Count::class,
'isfile' => Rule\IsFile::class,
'code' => Rule\Code::class,
'reg' => Rule\PregMatch::class,
];
function __construct($rules = []) { function __construct($rules = []) {
$this->addRuleList($rules); $this->addRuleList($rules);
@ -98,13 +103,17 @@ class Validator
return false; return false;
} }
function reset() {
$this->errorMsg = [];
}
public function validate(Collection $container, $rule = null, $status = null) public function validate(Collection $container, $rule = null, $status = null)
{ {
$fields = []; $fields = [];
if ($rule) { if ($rule) {
$this->chain = $rule; $this->chain = $rule;
} }
$this->errorMsg = []; // $this->errorMsg = [];
foreach ($this->chain as $rule) { foreach ($this->chain as $rule) {
//echo $key; //echo $key;
if (!in_array($rule->field, $fields) && !$this->skip($rule, $container) && !$rule->isValid($container, $status)) { if (!in_array($rule->field, $fields) && !$this->skip($rule, $container) && !$rule->isValid($container, $status)) {