From 541520fa4aef50411ee3a9fe161fafba79355502 Mon Sep 17 00:00:00 2001 From: origami11 Date: Thu, 9 Feb 2017 14:21:47 +0300 Subject: [PATCH 01/13] =?UTF-8?q?=D0=A2=D0=B8=D0=BF=20=D1=81=D0=BE=D0=B4?= =?UTF-8?q?=D0=B5=D1=80=D0=B6=D0=B0=D0=BD=D0=B8=D1=8F=20=D0=B4=D0=BB=D1=8F?= =?UTF-8?q?=20=D0=BF=D0=BE=D1=87=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/database_pdo.php | 1 + core/mail.php | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/core/database_pdo.php b/core/database_pdo.php index 21c1285..0bf3999 100644 --- a/core/database_pdo.php +++ b/core/database_pdo.php @@ -201,6 +201,7 @@ class PDODatabaseStatement extends PDOStatement implements IteratorAggregate { protected $cursorPos = 0; public $cache = array(); + public $fields; function getIterator() { diff --git a/core/mail.php b/core/mail.php index 53fa161..3bd2ef1 100644 --- a/core/mail.php +++ b/core/mail.php @@ -17,6 +17,7 @@ class Mail protected $attachment = array (); protected $uniqid; + protected $type = "text/plain"; function __construct() { $this->setEncoding("UTF-8"); @@ -70,6 +71,11 @@ class Mail $this->content = $text; } + function setType($type) + { + $this->type = $type; + } + /** * Кодировка текста в письме */ @@ -134,7 +140,7 @@ class Mail function getMessage() { $message = "--".$this->uniqid . PHP_EOL; - $message .= $this->mimeTag("Content-Type", "text/plain", array ('charset' => $this->encoding)); + $message .= $this->mimeTag("Content-Type", $this->type, array ('charset' => $this->encoding)); $message .= $this->mimeTag("Content-Transfer-Encoding", "8bit"); $message .= PHP_EOL . $this->content . PHP_EOL . PHP_EOL; From b5641db6074d0dda1dec7b32e33a89fe67de7a10 Mon Sep 17 00:00:00 2001 From: origami11 Date: Thu, 9 Feb 2017 14:57:40 +0300 Subject: [PATCH 02/13] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B5=D0=B4=D0=B5?= =?UTF-8?q?=D0=BB=D0=BA=D0=B0=20=D0=B4=D0=BB=D1=8F=20composer=20autoload?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composer.json | 6 +- core/connection/all.php | 4 - core/database.php | 16 ---- core/drivers/database.mysql.php | 50 ------------- core/drivers/database.odbc.php | 54 -------------- core/drivers/database.pgsql.php | 74 ------------------- core/drivers/db.php | 50 ------------- core/safecollection.php | 35 --------- {core => src}/adapter.php | 2 +- {core => src}/arr.php | 0 {core => src}/collection.php | 0 {core => src}/config.php | 0 {core => src}/connection/httpconnection.php | 3 +- .../connection/httpconnectionresponse.php | 2 +- {core => src}/connection/idna_convert.php | 0 .../controller/action.php | 10 --- {core => src}/controller/component.php | 4 +- {core => src}/controller/controller.php | 4 +- .../controller/front.php | 0 {core => src}/controller/installer.php | 4 +- {core => src}/controller/state.php | 2 +- {core => src}/data/areas.php | 0 {core => src}/data/city-short.php | 0 {core => src}/data/city.php | 0 {core => src}/data/mime.php | 0 {core => src}/data/okato.php | 0 {core => src}/data/regions.php | 0 {core => src}/data/states.php | 0 core/database_pdo.php => src/database.php | 0 {core => src}/error.php | 0 {core => src}/file.php | 0 {core => src}/filter/actionaccess.php | 0 {core => src}/filter/actionlogger.php | 0 {core => src}/filter/filterbase.php | 2 +- {core => src}/filter/filterlogin.php | 2 +- .../filter.php => src/filter/useraccess.php | 0 {core => src}/form/form.php | 0 {core => src}/form/viewstate.php | 0 {core => src}/formats/dot.php | 0 {core => src}/formats/helix.php | 0 {core => src}/functions.php | 0 {core => src}/geometry/point.php | 0 {core => src}/geometry/rectangle.php | 0 {core => src}/httprequest.php | 3 - {core => src}/layout/layout.php | 0 {core => src}/mail.php | 0 {core => src}/mapper/factory.php | 0 {core => src}/mapper/mapper.php | 0 {core => src}/mapper/pathmapper.php | 0 {core => src}/markup/simple_bb_code.php | 0 {core => src}/numbers.php | 0 {core => src}/path.php | 0 {core => src}/primitive.php | 2 - {core => src}/query/meta.php | 0 {core => src}/query/query.php | 0 {core => src}/query/table.php | 0 {core => src}/registry.php | 1 - {search => src/search}/htmlhelper.php | 0 {search => src/search}/index.php | 0 {search => src/search}/lexer.php | 0 {search => src/search}/search.php | 0 {search => src/search}/searcher.php | 0 {search => src/search}/stemmer.php | 0 {core => src}/session.php | 0 {core => src}/settings.php | 2 - {core => src}/setup.php | 5 -- {core => src}/shortcut.php | 0 {core => src}/sort.php | 0 {core => src}/spell.php | 2 - {core => src}/tabletree.php | 0 {core => src}/tales.php | 0 {core => src}/tools/drawing.php | 0 {core => src}/tools/exceltable.php | 0 {core => src}/tools/image.php | 0 {core => src}/tools/password.php | 0 {core => src}/tools/string.php | 0 {core => src}/tools/tableview.php | 0 {core => src}/tools/templateimage.php | 0 {core => src}/tools/translit.php | 0 {core => src}/tree/database.php | 0 {core => src}/tree/dbtree.php | 0 {core => src}/tree/sort.php | 0 {core => src}/validator/rule/abstract.php | 0 {core => src}/validator/rule/all.php | 0 {core => src}/validator/rule/alpha.php | 0 {core => src}/validator/rule/code.php | 0 {core => src}/validator/rule/count.php | 0 {core => src}/validator/rule/date.php | 0 {core => src}/validator/rule/email.php | 0 {core => src}/validator/rule/emaillist.php | 0 {core => src}/validator/rule/isfile.php | 0 {core => src}/validator/rule/match.php | 0 {core => src}/validator/rule/notnull.php | 0 {core => src}/validator/rule/numeric.php | 0 {core => src}/validator/rule/time.php | 0 {core => src}/validator/rule/unique.php | 0 {core => src}/validator/validator.php | 0 {core => src}/view/compositeview.php | 0 {core => src}/view/view.php | 0 {core => src}/zipfile.php | 0 100 files changed, 14 insertions(+), 325 deletions(-) delete mode 100644 core/connection/all.php delete mode 100644 core/database.php delete mode 100644 core/drivers/database.mysql.php delete mode 100644 core/drivers/database.odbc.php delete mode 100644 core/drivers/database.pgsql.php delete mode 100644 core/drivers/db.php delete mode 100644 core/safecollection.php rename {core => src}/adapter.php (90%) rename {core => src}/arr.php (100%) rename {core => src}/collection.php (100%) rename {core => src}/config.php (100%) rename {core => src}/connection/httpconnection.php (98%) rename {core => src}/connection/httpconnectionresponse.php (98%) rename {core => src}/connection/idna_convert.php (100%) rename core/controller/admincontroller.php => src/controller/action.php (97%) rename {core => src}/controller/component.php (99%) rename {core => src}/controller/controller.php (99%) rename core/controller/frontcontroller.php => src/controller/front.php (100%) rename {core => src}/controller/installer.php (98%) rename {core => src}/controller/state.php (98%) rename {core => src}/data/areas.php (100%) rename {core => src}/data/city-short.php (100%) rename {core => src}/data/city.php (100%) rename {core => src}/data/mime.php (100%) rename {core => src}/data/okato.php (100%) rename {core => src}/data/regions.php (100%) rename {core => src}/data/states.php (100%) rename core/database_pdo.php => src/database.php (100%) rename {core => src}/error.php (100%) rename {core => src}/file.php (100%) rename {core => src}/filter/actionaccess.php (100%) rename {core => src}/filter/actionlogger.php (100%) rename {core => src}/filter/filterbase.php (96%) rename {core => src}/filter/filterlogin.php (98%) rename core/filter/filter.php => src/filter/useraccess.php (100%) rename {core => src}/form/form.php (100%) rename {core => src}/form/viewstate.php (100%) rename {core => src}/formats/dot.php (100%) rename {core => src}/formats/helix.php (100%) rename {core => src}/functions.php (100%) rename {core => src}/geometry/point.php (100%) rename {core => src}/geometry/rectangle.php (100%) rename {core => src}/httprequest.php (97%) rename {core => src}/layout/layout.php (100%) rename {core => src}/mail.php (100%) rename {core => src}/mapper/factory.php (100%) rename {core => src}/mapper/mapper.php (100%) rename {core => src}/mapper/pathmapper.php (100%) rename {core => src}/markup/simple_bb_code.php (100%) rename {core => src}/numbers.php (100%) rename {core => src}/path.php (100%) rename {core => src}/primitive.php (99%) rename {core => src}/query/meta.php (100%) rename {core => src}/query/query.php (100%) rename {core => src}/query/table.php (100%) rename {core => src}/registry.php (92%) rename {search => src/search}/htmlhelper.php (100%) rename {search => src/search}/index.php (100%) rename {search => src/search}/lexer.php (100%) rename {search => src/search}/search.php (100%) rename {search => src/search}/searcher.php (100%) rename {search => src/search}/stemmer.php (100%) rename {core => src}/session.php (100%) rename {core => src}/settings.php (99%) rename {core => src}/setup.php (94%) rename {core => src}/shortcut.php (100%) rename {core => src}/sort.php (100%) rename {core => src}/spell.php (99%) rename {core => src}/tabletree.php (100%) rename {core => src}/tales.php (100%) rename {core => src}/tools/drawing.php (100%) rename {core => src}/tools/exceltable.php (100%) rename {core => src}/tools/image.php (100%) rename {core => src}/tools/password.php (100%) rename {core => src}/tools/string.php (100%) rename {core => src}/tools/tableview.php (100%) rename {core => src}/tools/templateimage.php (100%) rename {core => src}/tools/translit.php (100%) rename {core => src}/tree/database.php (100%) rename {core => src}/tree/dbtree.php (100%) rename {core => src}/tree/sort.php (100%) rename {core => src}/validator/rule/abstract.php (100%) rename {core => src}/validator/rule/all.php (100%) rename {core => src}/validator/rule/alpha.php (100%) rename {core => src}/validator/rule/code.php (100%) rename {core => src}/validator/rule/count.php (100%) rename {core => src}/validator/rule/date.php (100%) rename {core => src}/validator/rule/email.php (100%) rename {core => src}/validator/rule/emaillist.php (100%) rename {core => src}/validator/rule/isfile.php (100%) rename {core => src}/validator/rule/match.php (100%) rename {core => src}/validator/rule/notnull.php (100%) rename {core => src}/validator/rule/numeric.php (100%) rename {core => src}/validator/rule/time.php (100%) rename {core => src}/validator/rule/unique.php (100%) rename {core => src}/validator/validator.php (100%) rename {core => src}/view/compositeview.php (100%) rename {core => src}/view/view.php (100%) rename {core => src}/zipfile.php (100%) diff --git a/composer.json b/composer.json index a187ad9..8c45455 100644 --- a/composer.json +++ b/composer.json @@ -7,5 +7,9 @@ "email": "phedor@edu.yar.ru" } ], - "require": {} + "require": { + "psr-0": { + "": "src/" + } + } } diff --git a/core/connection/all.php b/core/connection/all.php deleted file mode 100644 index 3bc9748..0000000 --- a/core/connection/all.php +++ /dev/null @@ -1,4 +0,0 @@ - \ No newline at end of file diff --git a/core/database.php b/core/database.php deleted file mode 100644 index 52eca1a..0000000 --- a/core/database.php +++ /dev/null @@ -1,16 +0,0 @@ -connect($dsn); - return $database; - } -} diff --git a/core/drivers/database.mysql.php b/core/drivers/database.mysql.php deleted file mode 100644 index 99eb601..0000000 --- a/core/drivers/database.mysql.php +++ /dev/null @@ -1,50 +0,0 @@ -db = $db); - } - - public function close() - { - return mysql_close($this->db); - } - - public function query($query) - { - $res = mysql_query($this->db, $query) - or die("Error: wrong SQL query #$query#"); - return $res; - } - - public function fetchAllArray($query) - { - $res = $this->query($query); - - while ($row = mysql_fetch_array ($res)) - $rows[] = $row; - mysql_free_result($res); - return ($rows) ? $rows : array(); - } - - public function fetchOneArray($query) - { - $res = $this->query($query); - $row = mysql_fetch_array($res); - mysql_free_result($res); - return ($row) ? $row : array(); - } -} - -?> \ No newline at end of file diff --git a/core/drivers/database.odbc.php b/core/drivers/database.odbc.php deleted file mode 100644 index cb166bf..0000000 --- a/core/drivers/database.odbc.php +++ /dev/null @@ -1,54 +0,0 @@ -db = $db); - } - - public function close() - { - return odbc_close($this->db); - } - - public function query($query) - { - $res = odbc_exec($this->db, $query) - or die("Error: wrong SQL query #$query#"); - return $res; - } - - public function fetchAllArray($query) - { - $res = $this->query($query); - $to = odbc_num_fields($res); - while (odbc_fetch_row($res)) { - for ($i = 1; $i <= $to; $i++) { - $row [odbc_field_name($res, $i)] = trim(odbc_result($res, $i)); - } - $rows[] = $row; - } - return ($rows)? $rows : array(); - } - - public function fetchOneArray($query) - { - $res = $this->query($query); - if (!odbc_fetch_row($res)) return array (); - $to = odbc_num_fields($res); - for ($i = 1; $i <= $to; $i++) { - $row [odbc_field_name($res, $i)] = trim(odbc_result($res, $i)); - } - return $row; - } -} - -?> \ No newline at end of file diff --git a/core/drivers/database.pgsql.php b/core/drivers/database.pgsql.php deleted file mode 100644 index 64de93f..0000000 --- a/core/drivers/database.pgsql.php +++ /dev/null @@ -1,74 +0,0 @@ -db = $db); - } - - public function close() - { - return pg_close($this->db); - } - - public function query($query) - { - $res = pg_query($this->db, $query) - or die("Error: wrong SQL query #$query#"); - return $res; - } - - public function fetchAllArray($query, $type = PGSQL_ASSOC) - { - $res = $this->query($query); - - $rows = array(); - while ($row = pg_fetch_array($res, NULL, $type)) { - $rows[] = $this->clean($row); - } - pg_free_result($res); - return ($rows) ? $rows : array(); - } - - public function affectedRows() - { - return pg_affected_rows($this->db); - } - - private function clean($row) - { - foreach ($row as $key => $value) { - $row[$key] = trim($value); - } - return $row; - } - - public function fetchOneArray($query, $type = PGSQL_ASSOC) - { - $res = $this->query($query); - $row = pg_fetch_array($res, NULL, $type); - pg_free_result($res); - return ($row) ? $this->clean($row) : array(); - } - - function getNextId($seq) - { - $result = $this->fetchOneArray("SELECT nextval('$seq')"); - return $result['nextval']; - } -} diff --git a/core/drivers/db.php b/core/drivers/db.php deleted file mode 100644 index 3e5014d..0000000 --- a/core/drivers/db.php +++ /dev/null @@ -1,50 +0,0 @@ -query("INSERT INTO $table (" . implode(",", array_keys($values)) - . ") VALUES (" . implode(",", array_map(array('self', 'quote'), array_values($values))) . ")"); - } - - function update($table, array $values, $cond) - { - return $this->query("UPDATE $table SET " . implode(",", - array_map(array('self', 'assign_quote'), array_keys($values), array_values($values))) . " WHERE $cond"); - } - - function check_text($text) - { - if(strlen($text) > self::limit) $text = substr($text, 0, self::limit); - $text = htmlspecialchars(trim($text)); - return $text; - } -} - -?> \ No newline at end of file diff --git a/core/safecollection.php b/core/safecollection.php deleted file mode 100644 index df5529d..0000000 --- a/core/safecollection.php +++ /dev/null @@ -1,35 +0,0 @@ -data = $this->_stripSlashes($this->data); - } - $this->data = $this->data; - } - - function import(array $data) - { - parent::import($data); - $this->_clean(); - } - - /** - * Strip slashes code from php.net website. - * - * @param mixed $value - * @return array - */ - protected function _stripSlashes($value) - { - if(is_array($value)) { - return array_map(array($this,'_stripSlashes'), $value); - } else { - return stripslashes($value); - } - } -} diff --git a/core/adapter.php b/src/adapter.php similarity index 90% rename from core/adapter.php rename to src/adapter.php index 39af4c2..42bd4ab 100644 --- a/core/adapter.php +++ b/src/adapter.php @@ -14,7 +14,7 @@ class Adapter public function get($name) { if (is_array ($this->adaptee)) { - return $this->adaptee [$name]; + return $this->adaptee[$name]; } else { return $this->adaptee->$name; } diff --git a/core/arr.php b/src/arr.php similarity index 100% rename from core/arr.php rename to src/arr.php diff --git a/core/collection.php b/src/collection.php similarity index 100% rename from core/collection.php rename to src/collection.php diff --git a/core/config.php b/src/config.php similarity index 100% rename from core/config.php rename to src/config.php diff --git a/core/connection/httpconnection.php b/src/connection/httpconnection.php similarity index 98% rename from core/connection/httpconnection.php rename to src/connection/httpconnection.php index b2b25f3..534be58 100644 --- a/core/connection/httpconnection.php +++ b/src/connection/httpconnection.php @@ -1,7 +1,6 @@ value; } } - -?> \ No newline at end of file diff --git a/core/query/meta.php b/src/query/meta.php similarity index 100% rename from core/query/meta.php rename to src/query/meta.php diff --git a/core/query/query.php b/src/query/query.php similarity index 100% rename from core/query/query.php rename to src/query/query.php diff --git a/core/query/table.php b/src/query/table.php similarity index 100% rename from core/query/table.php rename to src/query/table.php diff --git a/core/registry.php b/src/registry.php similarity index 92% rename from core/registry.php rename to src/registry.php index 661dad5..862a3d4 100644 --- a/core/registry.php +++ b/src/registry.php @@ -5,7 +5,6 @@ * http://www.patternsforphp.com/wiki/Singleton * http://www.phppatterns.com/docs/design/the_registry?s=registry */ -require_once 'core/settings.php'; class Registry extends Settings { diff --git a/search/htmlhelper.php b/src/search/htmlhelper.php similarity index 100% rename from search/htmlhelper.php rename to src/search/htmlhelper.php diff --git a/search/index.php b/src/search/index.php similarity index 100% rename from search/index.php rename to src/search/index.php diff --git a/search/lexer.php b/src/search/lexer.php similarity index 100% rename from search/lexer.php rename to src/search/lexer.php diff --git a/search/search.php b/src/search/search.php similarity index 100% rename from search/search.php rename to src/search/search.php diff --git a/search/searcher.php b/src/search/searcher.php similarity index 100% rename from search/searcher.php rename to src/search/searcher.php diff --git a/search/stemmer.php b/src/search/stemmer.php similarity index 100% rename from search/stemmer.php rename to src/search/stemmer.php diff --git a/core/session.php b/src/session.php similarity index 100% rename from core/session.php rename to src/session.php diff --git a/core/settings.php b/src/settings.php similarity index 99% rename from core/settings.php rename to src/settings.php index 35de901..3566c89 100644 --- a/core/settings.php +++ b/src/settings.php @@ -1,7 +1,5 @@ \ No newline at end of file diff --git a/core/shortcut.php b/src/shortcut.php similarity index 100% rename from core/shortcut.php rename to src/shortcut.php diff --git a/core/sort.php b/src/sort.php similarity index 100% rename from core/sort.php rename to src/sort.php diff --git a/core/spell.php b/src/spell.php similarity index 99% rename from core/spell.php rename to src/spell.php index bc45a0d..43b0ce8 100644 --- a/core/spell.php +++ b/src/spell.php @@ -96,5 +96,3 @@ class Spell return false; } } - -?> \ No newline at end of file diff --git a/core/tabletree.php b/src/tabletree.php similarity index 100% rename from core/tabletree.php rename to src/tabletree.php diff --git a/core/tales.php b/src/tales.php similarity index 100% rename from core/tales.php rename to src/tales.php diff --git a/core/tools/drawing.php b/src/tools/drawing.php similarity index 100% rename from core/tools/drawing.php rename to src/tools/drawing.php diff --git a/core/tools/exceltable.php b/src/tools/exceltable.php similarity index 100% rename from core/tools/exceltable.php rename to src/tools/exceltable.php diff --git a/core/tools/image.php b/src/tools/image.php similarity index 100% rename from core/tools/image.php rename to src/tools/image.php diff --git a/core/tools/password.php b/src/tools/password.php similarity index 100% rename from core/tools/password.php rename to src/tools/password.php diff --git a/core/tools/string.php b/src/tools/string.php similarity index 100% rename from core/tools/string.php rename to src/tools/string.php diff --git a/core/tools/tableview.php b/src/tools/tableview.php similarity index 100% rename from core/tools/tableview.php rename to src/tools/tableview.php diff --git a/core/tools/templateimage.php b/src/tools/templateimage.php similarity index 100% rename from core/tools/templateimage.php rename to src/tools/templateimage.php diff --git a/core/tools/translit.php b/src/tools/translit.php similarity index 100% rename from core/tools/translit.php rename to src/tools/translit.php diff --git a/core/tree/database.php b/src/tree/database.php similarity index 100% rename from core/tree/database.php rename to src/tree/database.php diff --git a/core/tree/dbtree.php b/src/tree/dbtree.php similarity index 100% rename from core/tree/dbtree.php rename to src/tree/dbtree.php diff --git a/core/tree/sort.php b/src/tree/sort.php similarity index 100% rename from core/tree/sort.php rename to src/tree/sort.php diff --git a/core/validator/rule/abstract.php b/src/validator/rule/abstract.php similarity index 100% rename from core/validator/rule/abstract.php rename to src/validator/rule/abstract.php diff --git a/core/validator/rule/all.php b/src/validator/rule/all.php similarity index 100% rename from core/validator/rule/all.php rename to src/validator/rule/all.php diff --git a/core/validator/rule/alpha.php b/src/validator/rule/alpha.php similarity index 100% rename from core/validator/rule/alpha.php rename to src/validator/rule/alpha.php diff --git a/core/validator/rule/code.php b/src/validator/rule/code.php similarity index 100% rename from core/validator/rule/code.php rename to src/validator/rule/code.php diff --git a/core/validator/rule/count.php b/src/validator/rule/count.php similarity index 100% rename from core/validator/rule/count.php rename to src/validator/rule/count.php diff --git a/core/validator/rule/date.php b/src/validator/rule/date.php similarity index 100% rename from core/validator/rule/date.php rename to src/validator/rule/date.php diff --git a/core/validator/rule/email.php b/src/validator/rule/email.php similarity index 100% rename from core/validator/rule/email.php rename to src/validator/rule/email.php diff --git a/core/validator/rule/emaillist.php b/src/validator/rule/emaillist.php similarity index 100% rename from core/validator/rule/emaillist.php rename to src/validator/rule/emaillist.php diff --git a/core/validator/rule/isfile.php b/src/validator/rule/isfile.php similarity index 100% rename from core/validator/rule/isfile.php rename to src/validator/rule/isfile.php diff --git a/core/validator/rule/match.php b/src/validator/rule/match.php similarity index 100% rename from core/validator/rule/match.php rename to src/validator/rule/match.php diff --git a/core/validator/rule/notnull.php b/src/validator/rule/notnull.php similarity index 100% rename from core/validator/rule/notnull.php rename to src/validator/rule/notnull.php diff --git a/core/validator/rule/numeric.php b/src/validator/rule/numeric.php similarity index 100% rename from core/validator/rule/numeric.php rename to src/validator/rule/numeric.php diff --git a/core/validator/rule/time.php b/src/validator/rule/time.php similarity index 100% rename from core/validator/rule/time.php rename to src/validator/rule/time.php diff --git a/core/validator/rule/unique.php b/src/validator/rule/unique.php similarity index 100% rename from core/validator/rule/unique.php rename to src/validator/rule/unique.php diff --git a/core/validator/validator.php b/src/validator/validator.php similarity index 100% rename from core/validator/validator.php rename to src/validator/validator.php diff --git a/core/view/compositeview.php b/src/view/compositeview.php similarity index 100% rename from core/view/compositeview.php rename to src/view/compositeview.php diff --git a/core/view/view.php b/src/view/view.php similarity index 100% rename from core/view/view.php rename to src/view/view.php diff --git a/core/zipfile.php b/src/zipfile.php similarity index 100% rename from core/zipfile.php rename to src/zipfile.php From 6b412f5d6faae99163e1a63d1b9b9f39186611d3 Mon Sep 17 00:00:00 2001 From: origami11 Date: Thu, 9 Feb 2017 15:29:58 +0300 Subject: [PATCH 03/13] fix autoload --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 8c45455..de9a023 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "email": "phedor@edu.yar.ru" } ], - "require": { + "autoload": { "psr-0": { "": "src/" } From f2938b13531177fb44a91235ad9c455fb97eef00 Mon Sep 17 00:00:00 2001 From: origami11 Date: Thu, 9 Feb 2017 17:14:11 +0300 Subject: [PATCH 04/13] =?UTF-8?q?=D0=A1=D0=B8=D0=BD=D1=85=D1=80=D0=BE?= =?UTF-8?q?=D0=BD=D0=B8=D0=B7=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BB=20=D1=87?= =?UTF-8?q?=D0=B0=D1=81=D1=82=D0=B8=D1=87=D0=BD=D0=BE=20=D1=81=20CMS2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + src/collection.php | 7 +- src/controller/action.php | 648 ++++++++---------- src/controller/controller.php | 341 --------- src/controller/front.php | 14 +- src/controller/model.php | 426 ++++++++++++ src/controller/state.php | 15 +- src/filter/actionlogger.php | 2 - src/filter/{filterbase.php => filter.php} | 0 src/filter/{filterlogin.php => login.php} | 8 +- src/filter/useraccess.php | 5 +- src/form/form.php | 10 +- src/functions.php | 52 +- src/httprequest.php | 69 +- src/layout/{layout.php => manager.php} | 22 +- src/layout/none.php | 11 + src/mail.php | 62 +- .../{simple_bb_code.php => simplebbcode.php} | 4 +- src/numbers.php | 2 +- src/path.php | 419 ++++++----- src/registry.php | 2 + src/session.php | 2 +- src/settings.php | 35 +- src/setup.php | 218 +++++- src/shortcut.php | 19 +- src/tales.php | 50 +- src/tools/drawing.php | 8 +- src/view/composite.php | 40 ++ src/view/{compositeview.php => top.php} | 41 +- src/zipfile.php | 13 +- 30 files changed, 1447 insertions(+), 1099 deletions(-) create mode 100644 .gitignore delete mode 100644 src/controller/controller.php create mode 100644 src/controller/model.php rename src/filter/{filterbase.php => filter.php} (100%) rename src/filter/{filterlogin.php => login.php} (94%) rename src/layout/{layout.php => manager.php} (82%) create mode 100644 src/layout/none.php rename src/markup/{simple_bb_code.php => simplebbcode.php} (97%) create mode 100644 src/view/composite.php rename src/view/{compositeview.php => top.php} (89%) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7664704 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.bak \ No newline at end of file diff --git a/src/collection.php b/src/collection.php index 5ab61ec..467175e 100644 --- a/src/collection.php +++ b/src/collection.php @@ -1,8 +1,7 @@ data[$key] = $value; } @@ -54,7 +53,7 @@ class Collection implements ArrayAccess */ public function get($key, $default = null) { - return isset($this->data[$key]) ? $this->data[$key] : $default; + return isset($this->data[$key]) && $this->data[$key] != '' ? $this->data[$key] : $default; } public function getInt($key, $default = 0) diff --git a/src/controller/action.php b/src/controller/action.php index 24d8eb1..42eb674 100644 --- a/src/controller/action.php +++ b/src/controller/action.php @@ -1,423 +1,339 @@ table->setHeader - */ - public $tableSchema = null; - public $formSchema = array(); +/** + * Контроллер страниц + */ +class Controller_Action +{ - public $menu; + const TEMPLATE_EXTENSION = ".html"; // Расширение для шаблонов + const ACTION_PREFIX = "action"; // Префикс для функций действий + + public $jsPath; // Глобальный путь к скриптам + public $themePath; // Глобальный путь к текущей теме + + // Параметры устанавливаются при создании контроллера + public $name; // Имя модуля + public $viewPath = null; // Путь к шаблонам контроллера + public $db; // Соединение с базой данных + + // Фильтры + public $access = null; // Обьект хранит параметры доступа + public $logger = null; // Обьект для ведения лога + + private $factory = null; // Ссылка на обьект создания модели + private $helpers = array(); // Помошники для действий + public $param = array(); // Параметры для ссылки + + public /*.Registry.*/$_registry; // Ссылка на реестр + public $_shortcut; + public $modulePrefix = ''; + public $iconPath = ''; public $path; - public $table; - public function __construct() + public function __construct () { - $this->path = new PathMenu(); - $this->menu = new PageMenu(); - $this->table = new ListTable(); + // } - /** - */ - function setUp() + public function setUp () { - $this->table->addMenuItem($this->aUrl('delete'), 'удалить', false, 'all', 'warning'); - //$this->table->addMenuItem($this->nUrl('form'), 'редактировать', 'edit-24.png'); + // override this } - function saveParameters($args, $list) - { - foreach ($list as $item) { - $args->session()->set(array($this, $item), $args->get($item)); - } - } - - protected function getJSONList(/*Mapper*/ $model, Collection $request) - { - $result = array(); - $this->saveParameters($request, array('size','page','desc', 'key')); - - $result['list'] = $model->findAll($request, $request->get('ref')); - $result['size'] = $model->getCount($request, $request->get('ref')); - return json::encode($result); - } - - /** - * Удаление сторк из таблицы - */ - public function actionDelete(HttpRequest $request) - { - $model = $this->getModel($this->useModel); - // Почему table_item ??? - $list = ($request->get('table_item')) ? $request->get('table_item'): $request->get('id'); - $model->deleteList($list); - - return $this->getJSONList($model, $request); - } - - /** - * Ответ на запрос по поиску - */ - public function actionSearch(HttpRequest $request) - { - $model = $this->getModel($this->useModel); - $model->addFilter($model->requestToSQL($request, $this->formSchema)); - - return $this->getJSONList($model, $request); - } - - /** - * Список элементов - */ - public function actionList(HttpRequest $request) - { - $model = $this->getModel($this->useModel); - return $this->getJSONList($model, $request); - } - - - private function setFormSchema() - { - require_once 'core/mapper/uimapper.php'; - - $model = $this->getModel($this->useModel); - $ui = new UIMapper($model); - - $this->formSchema = $ui->getFormSchema(); - } - - /** - * Сохранение формы - */ - function beforeSave(/*Model*/ $item, Collection $request) - { - if (empty($this->formSchema)) { - $this->setFormSchema(); - } - // Сделать отображение Формы в обьект и обратно <-- Убрать в beforeSave - foreach ($this->formSchema as $key => $conv) { - list($value, $type) = $conv; - $item->$value = call_user_func(array('Cast', 'to_' . $type), $request->get($key)); // Здесть нужно преобразовывать тип значения - } - } - - /** - * Обновление формы - */ - function formUpdate(TForm $form, Collection $request) - { - } - - /** - * Загрузка формы - */ - function beforeLoad(/*Model*/ $item, TForm $form) - { - if (empty($this->formSchema)) { - $this->setFormSchema(); - } - // Вставка значений из данных в форму - // Отображение обьекта в поля формы - $form->fill($item, $this->formSchema); - } - - // Проверка ввода - protected function validate($validator, $request) - { - } - - /** - * Действие для проверки формы - */ - public function actionValidate($request) - { - require_once "core/validator/validator.php"; - $validator = new Validator(); - $validator->addRuleList($this->schema); - - // Действия до проверки формы - $this->validate($validator, $request); // <--| - $validator->validate($request); // --| - // Проверка формы - if (!$validator->isValid()) { - return json::encode($validator->getErrorMsg()); - } - return json::encode(true); - } - - /** - * Инициализация формы - */ - protected function formSetup($form, $id = null, $ref = null) - { - if (empty($this->schema)) { - $model = $this->getModel($this->useModel); - $ui = new UIMapper($model); - $schema = $ui->getEditSchema(); - - $form->addFieldList($schema); + public function loadConfig($name) { + $filename = Shortcut::getUrl('config', $name); + if (file_exists($filename)) { + include($filename); } else { - $form->addFieldList($this->schema); + throw new Exception('Невозможно загрузить файл настроек ' . $name); + } + return $settings; + } + + public function getConnection() + { + return $this->db; + } + + public function installPath($name) + { + return Path::join(CMS_PATH, "modules", $name, "install"); + } + + public function addSuggest($view, $name) + { + $suggest = array(); + $file = Path::join($this->viewPath, 'help', $name . '.suggest'); + if (file_exists($file) && include($file)) { + $view->addScriptRaw("add_suggest(".json::encode($suggest).");\n"); } } - /** - * Добавление пользователя - */ - public function actionAdd(HttpRequest $request) + function findIcon($icon, $size) { - require_once "core/validator/validator.php"; - // {{{ тоже может быть один ref или несколько - $ref = $request->get('ref'); - $this->addParameter('ref', $ref); // Добавляет параметр в url - /// }}} - - if ($this->checkPageId($request, $request->get('page'))) { - // Проверка - $validator = new Validator(); - $validator->addRuleList($this->schema); + return Path::join($this->iconPath, $size . 'x' . $size, $icon . '.png'); + } - // Действия до проверки формы - $this->validate($validator, $request); // <--| - $validator->validate($request); // --| - // Проверка формы - if (!$validator->isValid()) { - $request->setAction('form'); - $this->getActionPath($request); - - $form = new TForm(); - $this->formSetup($form, $request->get('id'), $request->get('ref')); // Инициализация формы - - $form->setValues($request); // <-- Убрать в formUpdate - $this->formUpdate($form, $request); - - $form->setError($validator); // Установка ошибок для формы - - $tpl = $this->formPage($form, $request); - $id = $request->get('id'); - if ($id) { // Редактирование - $tpl->action = forceUrl($this->nUrl('add', array('id' => $id, 'page' => $this->getPageId($request)))); // action Совйство формы - } - return $tpl /*->execute()*/; - } - - // Нужен тест для формы - $model = $this->getModel($this->useModel); - $className = $model->className; - $item = new $className(); - - // Сохраняем значение в базе данных - $item->id = $request->get('id'); - // Если таблица связана с другой таблицей - if ($request->get('ref') && $model->reference[1]) { - $ref_id = $model->reference[1]; - $item->$ref_id = $request->get('ref'); - } - - // Подготовка к сохранению - $this->beforeSave($item, $request); // Сюдаже и истрия переходов - // nextId ??? или выход или новая форма для создания новости - $model->saveDB($item, $request); - } - - // Для страницы со списком id -> идентефикатор родительской таблицы !!?? -// $request->set('id', $request->get('ref')); - if ($request->get('apply')) { - $request->setAction('form'); - return $this->forward('actionForm', $request); - } - return $this->forward('actionIndex', $request); - } - /** - * Заголовок + * Создает представление + * @param string $file + * @return template */ - private function setTitlePath($ref) + public function getView($name) { - if ($ref) { - $model = $this->getModel($this->useModel); - if (is_array($model->reference) && $model->reference[0]) { - $refmodel = $this->getModel($model->reference[0]); - try { - $parent = $refmodel->findById($ref); - $this->path->addTitle($parent->getTitle()); // Заголовок к подписям путей - } catch (Exception $e) { - // Не найден заголовок потому что неправильно определен родительский элемент - } - } + $file = $name . self::TEMPLATE_EXTENSION; + // Список возможных директорий для поиска файла шаблона + $theme = $this->_registry->readKey(array('system', 'theme')); + $icon_theme = $this->_registry->readKey(array('system', 'icon_theme')); + $list = array( + Path::join($this->viewPath, TEMPLATES) => Path::join(WWW_PATH, "modules", $this->name, TEMPLATES), + PHPTAL_TEMPLATE_REPOSITORY => ""); + + + // Поиск файла для шаблона + foreach($list as $ospath => $path) { + $template = Path::join($ospath, $file); + if(file_exists($template)) { break; } } - } - - /** - * Форма для редактирования - */ - public function actionForm(HttpRequest $request) - { - $this->getActionPath($request); - $ref = $request->get('ref'); - $this->addParameter('ref', $ref); // Добавляет параметр в url - $this->setTitlePath($ref); - $model = $this->getModel($this->useModel); - $form = new TForm(); // Показываем форму - $form->header = 'Редактирование записи'; - $this->formSetup($form, $request->get('id'), $request->get('ref')); // Инициализация формы + $tpl = new View_Composite($template); + $tpl->icons = $this->iconPath; // Путь к файлам текущей темы + $tpl->media = $this->themePath; // Путь к файлам текущей темы + $tpl->script = $this->jsPath; // Путь к файлам скриптов + $tpl->template = $path; // Путь к файлам текущего шаблона + $tpl->setAlias(array( + '${icons}' => $this->iconPath, + '${media}' => $this->themePath, + '${script}' => $this->jsPath, + '${template}' => $path)); - $list = $request->get('table_item'); - $id = ($list[0]) ? $list[0] : $request->get('id'); + $tpl->loadImports(Path::skipExtension($template) . ".import"); - $tpl = $this->formPage ($form, $request); - if ($id) { // Редактирование - $form->action = forceUrl($this->nUrl('add', array('id' => $id, 'page' => $this->getPageId($request)))); // action Свойство формы - $item = $model->findById($id); - // Загрузка формы - $this->beforeLoad($item, $form); - /// - } + $this->addSuggest($tpl, $name); return $tpl; } - /** - */ - function tableSetup($table, $id = null, $ref = null) + public function getModel($name) { - // FIXME: После замены везде $tableSchema -> table->setHeader удалить! - if ($this->tableSchema) { - $table->setHeader($this->tableSchema); - } else { - // Настройка таблицы отображения по схеме данных - require_once 'core/mapper/uimapper.php'; - $model = $this->getModel($this->useModel); - $ui = new UIMapper($model); - $schema = $ui->getTableSchema(); - $schema[0]['action'] = $table->getFirstItem(); - - $table->setHeader($schema); + if (!$this->factory) { + $this->factory = new ModelFactory($this->db, $this->_registry, $this->_shortcut); } + return $this->factory->getModel($name); } /** + * Выбор действия + * Т.к действия являются методами класса то + * 1. Можно переопределить действия + * 2. Использовать наследование чтобы добавить к старому обработчику новое поведение + * @param $request Обьект запроса */ - public function actionIndex(HttpRequest $request) + public function execute1(HTTPRequest $request) { - $this->getActionPath($request, 'index'); - // Такое мета действие наверное можно вынести в отдельный класс - return $this->metaActionIndex($request, array($this, 'tableSetup'), $this->aUrl('list')); + $action = self::ACTION_PREFIX . ucfirst($request->getAction()); + if (method_exists($this, $action)) { + return $this->forward($action, $request); + } else { + return $this->forward("actionIndex", $request); + } + } + + public function execute(HTTPRequest $request) + { + $result = $this->execute1($request); + if ($result) { + $this->view = $result; + } + return $this->render(); + } + + public function forward($action, HTTPRequest $args) + { + // Действия до вызова основного обработчика + /*foreach($this->_aspect as $aspect) { + if (isset($aspect->before[$action])) { + call_user_func ($aspect->before[$action], $action, $args); + } + }*/ + return call_user_func(array($this, $action), $args); } /** * Страница по умолчанию */ - public function metaActionIndex(HttpRequest $request, $setup, $list) + public function actionIndex(HttpRequest $request) { - // может быть одно ref или несколько - // {{{ история переходов - $ref = null; - if ($request->get('ref')) { - $ref = $request->get('ref'); - } else if ($request->session()->get('ref')) { - $ref = $request->session()->get('ref'); + return ""; + } + + public function postUrl($name, $param) + { + return "?" . http_build_query( + array_merge(array('module' => strtolower(get_class($this)), "action" => $name), + $this->param, $param)); + } + + /** + * Генерация ссылки c учетом прав пользователя на ссылки + * + * @parma string $name Действие + * @parma string $param Дополнительные параметры + */ + public function nUrl($name, array $param = array()) + { + if (!$this->access || $this->access->checkAction($name)) { + return lcurry(array($this, 'postUrl'), $name, $param); } + return null; + } - $request->session->set('ref', $ref); - $this->addParameter('ref', $ref); - // }}} - $this->setTitlePath($ref); - - $tpl = $this->getView('list'); - - // Помошники действий - $this->callHelpers($request); - // Таблица - if ($request->session()->get(strtolower(get_class($this)))) { - $session = $request->session()->get(strtolower(get_class($this))); - if (isset($session['view'])) { - $this->table->setView($session['view']); - } - $this->table->setData('state', array( - 'page' => $session['page'], - 'size' => $session['size'], - 'desc' => $session['desc'])); - - $this->table->setData('sorter', $session['key']); - if (isset($session['desc'])) { - $this->table->setData('desc', $session['desc']); - } - } - - call_user_func($setup, $this->table, $request->get('id'), $ref);// --> Эквивалент formSetup - $this->table->setAction($list); - // - $tpl->menu_path = $this->path->getItems(); - - // Поиск - $search = new SearchDialog(); - $search->setTitle('Поиск'); - $search->setAction($this->aUrl('search')); - $search->setFriend($this->table); - $search->addFields($this->schemaSearch); - - // Настройки - $setup = new SetupDialog(); - $setup->setTitle('Настройки'); - $setup->setAction($this->nUrl('setup')); - $setup->setFriend($this->table); - - // Меню - $this->menu->addMenuItem('?menu=toggle&id=' . $search->getName(), 'поиск', 'actions/system-search'); // Стандартный размер для иконок 22-24px - $this->menu->addMenuItem('?menu=toggle&id=' . $setup->getName(), 'настройки', 'categories/applications-system'); - // Добавление компонентов - $this->addChild('menu', $this->menu); - $this->addChild('search', $search); - $this->addChild('setup', $setup); - $this->addChild('table', $this->table); - // - return $tpl; + public function fUrl($name, array $param = array()) + { + return forceUrl($this->nUrl($name, $param)); } /** + * Добавляет параметр для всех ссылок создаваемых функцией nUrl, aUrl */ - public function actionSetup($request) + public function addParameter($name, $value) { - $left = explode(",", $request->get('left')); - $right = explode(",", $request->get('right')); - - $$request->session()->set(strtolower(get_class($this)), - array('view' => array('left' => $left, 'right' => $right))); - - return $this->forward('actionIndex', $request); + if ($value) { + $this->param [$name] = $value; + } } /** + * Генерация ссылки на действие контроллера + * Ajax определяется автоматически mode = ajax используется для смены layout */ - private function formPage($form, $request) + public function aUrl($name, array $param = array()) { - $view = $this->getView('form'); - $view->setView('form', $form); - $view->action = forceUrl($this->nUrl('add', array('page' => $this->getPageId($request)))); // Действие для формы - - $view->menu_path = $this->path->getItems(); - $view->back = $this->path->getPrev(); - return $view; + return $this->nUrl($name, array_merge(array('mode' => 'ajax'), $param)); // FIXME } - // Тоже убрать в метод Controller_Model - function getActionPath(HttpRequest $request/*, $action = false*/) + /** + * Добавление помошника контроллера + */ + public function addHelper($class) { - require_once 'state.php'; - $this->_getActionPath()->getPath($this, ($action) ? $action : $request->getAction()); - } + $this->helpers [] = $class; + } + + /** + * Вызов помошников контроллера + */ + public function callHelpers(HttpRequest $request) + { + $action = self::ACTION_PREFIX . $request->getAction(); + foreach ($this->helpers as $helper) { + if (method_exists($helper, $action)) { + return call_user_func(array($helper, $action), $request, $this); + } else { + return $helper->actionIndex($request, $this); // Вместо return response ??? + } + } + } + + /** + * Загрузка файла класса + */ + public function loadClass($path, $setup = null) + { + if (file_exists($path)) { + require_once ($path); + $class = pathinfo($path, PATHINFO_FILENAME); + return new $class($setup); + } + return null; + } + + public function loadSettings($path) + { + $result = new Settings($path); + $result->read(); + return $result->export(); + } + + // Для Widgets + public $view = null; + public $childNodes = array(); + public $childViews = array(); + + public function setView($name) + { + $this->view = $this->getView($name); + } + + /** + * Установка заголовка для отображения + */ + public function setTitle($title) + { + $this->view->setTitle($title); + } + + /** + * Добавление widget к отображению + */ + public function addChild(/*Widget*/ $section, $node) + { + $this->childNodes[$section] = $node; + } + + /** + * Добавление дочернего отображения к текущему отображению + */ + public function addView(/*CompositeView*/ $section, $node) + { + $this->childViews[$section] = $node; + } + + /** + * Генерация содержания + * Путаница c execute и render + */ + public function render() + { + foreach ($this->childNodes as $name => $node) { + $node->make($this); + $this->view->setView($name, $node->view); + } + foreach ($this->childViews as $name => $node) { + $this->view->setView($name, $node); + } + return $this->view; + } + + function getPageId($request) + { + $pageId = time(); + $request->session()->set('page', $pageId); + return $pageId; + } + + function checkPageId($request, $page) + { + $_page = $request->session()->get('page'); + $result = ($_page && $_page == $page); + $request->session()->clean('page'); + return $result; + } + + function redirect($action) { + header('location: ' . $this->fUrl($action)); + exit(); + } } + diff --git a/src/controller/controller.php b/src/controller/controller.php deleted file mode 100644 index 2072006..0000000 --- a/src/controller/controller.php +++ /dev/null @@ -1,341 +0,0 @@ -db; - } - - public function installPath($name) - { - return Path::join(CMS_PATH, "modules", $name, "install"); - } - - public function addSuggest($view, $name) - { - $suggest = array(); - $file = Path::join($this->viewPath, 'help', $name . '.suggest'); - if (file_exists($file) && include($file)) { - $view->addScriptRaw("add_suggest(".json::encode($suggest).");\n"); - } - } - - function findIcon($icon, $size) - { - return Path::join($this->iconPath, $size . 'x' . $size, $icon . '.png'); - } - - /** - * Создает представление - * @param string $file - * @return template - */ - public function getView($name) - { - require_once "core/view/compositeview.php"; - - $file = $name . self::TEMPLATE_EXTENSION; - // Список возможных директорий для поиска файла шаблона - $theme = $this->_registry->readKey(array('system', 'theme')); - $icon_theme = $this->_registry->readKey(array('system', 'icon_theme')); - $list = array( - Path::join($this->viewPath, TEMPLATES) => Path::join(WWW_PATH, "modules", $this->name, TEMPLATES), - PHPTAL_TEMPLATE_REPOSITORY => ""); - - - // Поиск файла для шаблона - foreach($list as $ospath => $path) { - $template = Path::join($ospath, $file); - if(file_exists($template)) { break; } - } - - $tpl = new View_Composite($template); - $tpl->icons = $this->iconPath; // Путь к файлам текущей темы - $tpl->media = $this->themePath; // Путь к файлам текущей темы - $tpl->script = $this->jsPath; // Путь к файлам скриптов - $tpl->template = $path; // Путь к файлам текущего шаблона - $tpl->setAlias(array( - '${icons}' => $this->iconPath, - '${media}' => $this->themePath, - '${script}' => $this->jsPath, - '${template}' => $path)); - - $tpl->loadImports(Path::skipExtension($template) . ".import"); - - $this->addSuggest($tpl, $name); - return $tpl; - } - - public function getModel($name) - { - if (!$this->factory) { - $this->factory = new ModelFactory($this->db, $this->_registry, $this->_shortcut); - } - return $this->factory->getModel($name); - } - - /** - * Выбор действия - * Т.к действия являются методами класса то - * 1. Можно переопределить действия - * 2. Использовать наследование чтобы добавить к старому обработчику новое поведение - * @param $request Обьект запроса - */ - public function execute1(HTTPRequest $request) - { - $action = self::ACTION_PREFIX . ucfirst($request->getAction()); - if (method_exists($this, $action)) { - return $this->forward($action, $request); - } else { - return $this->forward("actionIndex", $request); - } - } - - public function execute(HTTPRequest $request) - { - $result = $this->execute1($request); - if ($result) { - $this->view = $result; - } - return $this->render(); - } - - public function forward($action, HTTPRequest $args) - { - // Действия до вызова основного обработчика - /*foreach($this->_aspect as $aspect) { - if (isset($aspect->before[$action])) { - call_user_func ($aspect->before[$action], $action, $args); - } - }*/ - return call_user_func(array($this, $action), $args); - } - - /** - * Страница по умолчанию - */ - public function actionIndex(HttpRequest $request) - { - return ""; - } - - public function postUrl($name, $param) - { - return "?" . http_build_query( - array_merge(array('module' => strtolower(get_class($this)), "action" => $name), - $this->param, $param)); - } - - /** - * Генерация ссылки c учетом прав пользователя на ссылки - * - * @parma string $name Действие - * @parma string $param Дополнительные параметры - */ - public function nUrl($name, array $param = array()) - { - if (!$this->access || $this->access->checkAction($name)) { - return lcurry(array($this, 'postUrl'), $name, $param); - } - return null; - } - - public function fUrl($name, array $param = array()) - { - return forceUrl($this->nUrl($name, $param)); - } - - /** - * Добавляет параметр для всех ссылок создаваемых функцией nUrl, aUrl - */ - public function addParameter($name, $value) - { - if ($value) { - $this->param [$name] = $value; - } - } - - /** - * Генерация ссылки на действие контроллера - * Ajax определяется автоматически mode = ajax используется для смены layout - */ - public function aUrl($name, array $param = array()) - { - return $this->nUrl($name, array_merge(array('mode' => 'ajax'), $param)); // FIXME - } - - /** - * Добавление помошника контроллера - */ - public function addHelper($class) - { - $this->helpers [] = $class; - } - - /** - * Вызов помошников контроллера - */ - public function callHelpers(HttpRequest $request) - { - $action = self::ACTION_PREFIX . $request->getAction(); - foreach ($this->helpers as $helper) { - if (method_exists($helper, $action)) { - return call_user_func(array($helper, $action), $request, $this); - } else { - return $helper->actionIndex($request, $this); // Вместо return response ??? - } - } - } - - /** - * Загрузка файла класса - */ - public function loadClass($path, $setup = null) - { - if (file_exists($path)) { - require_once ($path); - $class = pathinfo($path, PATHINFO_FILENAME); - return new $class($setup); - } - return null; - } - - public function loadSettings($path) - { - $result = new Settings($path); - $result->read(); - return $result->export(); - } - - // Для Widgets - public $view = null; - public $childNodes = array(); - public $childViews = array(); - - public function setView($name) - { - $this->view = $this->getView($name); - } - - /** - * Установка заголовка для отображения - */ - public function setTitle($title) - { - $this->view->setTitle($title); - } - - /** - * Добавление widget к отображению - */ - public function addChild(/*Widget*/ $section, $node) - { - $this->childNodes[$section] = $node; - } - - /** - * Добавление дочернего отображения к текущему отображению - */ - public function addView(/*CompositeView*/ $section, $node) - { - $this->childViews[$section] = $node; - } - - /** - * Генерация содержания - * Путаница c execute и render - */ - public function render() - { - foreach ($this->childNodes as $name => $node) { - $node->make($this); - $this->view->setView($name, $node->view); - } - foreach ($this->childViews as $name => $node) { - $this->view->setView($name, $node); - } - return $this->view; - } - - function getPageId($request) - { - $pageId = time(); - $request->session()->set('page', $pageId); - return $pageId; - } - - function checkPageId($request, $page) - { - $_page = $request->session()->get('page'); - $result = ($_page && $_page == $page); - $request->session()->clean('page'); - return $result; - } - - function redirect($action) { - header('location: ' . $this->fUrl($action)); - exit(); - } -} - -class Controller_Action extends Controller {} - diff --git a/src/controller/front.php b/src/controller/front.php index c88d74e..badcf43 100644 --- a/src/controller/front.php +++ b/src/controller/front.php @@ -1,30 +1,24 @@ _registry = $_registry; $this->_shortcut = $_shortcut; $this->db = Database::getConnection($registry->readKey(array('system', 'dsn'))); - $this->installer = new Installer($_registry); } @@ -36,8 +30,6 @@ class Controller_Front extends Controller */ public function loadModule($name, Collection $request) { - $this->installer->setUp($this->db, array($this, 'installPath')); - $this->installer->doUpdates($name); // ModuleLoader (1) $moduleFile = Shortcut::getUrl($this->shortcut, $name); // ModuleLoader (2) $module = $this->loadClass($moduleFile); @@ -59,10 +51,10 @@ class Controller_Front extends Controller $module->db = $this->db; // Не для всех приложений нужно вести лог действий // Ведение лога - $logger = $this->loadClass(FRAMEWORK_PATH . '/core/filter/actionlogger.php', $module); + $logger = $this->loadClass(FRAMEWORK_PATH . '/src/filter/actionlogger.php', $module); $logger->before = $this->loadSettings(Shortcut::getUrl('logger', $name)); // Управление доступом - $module->access = $this->loadClass(FRAMEWORK_PATH . '/core/filter/actionaccess.php', $logger); + $module->access = $this->loadClass(FRAMEWORK_PATH . '/src/filter/actionaccess.php', $logger); $module->access->access = $this->loadSettings(Shortcut::getUrl('access', $name)); $module->setUp(); diff --git a/src/controller/model.php b/src/controller/model.php new file mode 100644 index 0000000..9c4dab7 --- /dev/null +++ b/src/controller/model.php @@ -0,0 +1,426 @@ +table->setHeader + */ + public $tableSchema = null; + public /*.array.*/$formSchema = array(); + + public $menu; + public $table; + + protected /*.string.*/$useModel; + protected /*.string.*/$itemModel; + + public function __construct() + { + $this->path = new PathMenu(); + $this->menu = new PageMenu(); + $this->table = new ListTable(); + } + + /** + */ + function setUp() + { + $this->table->addMenuItem($this->aUrl('delete'), 'удалить', false, 'all', 'warning'); + //$this->table->addMenuItem($this->nUrl('form'), 'редактировать', 'edit-24.png'); + } + + function saveParameters($args, $list) + { + foreach ($list as $item) { + $args->session()->set(array($this, $item), $args->get($item)); + } + } + + protected function getJSONList(/*Mapper*/ $model, Collection $request) + { + $result = array(); + $this->saveParameters($request, array('size','page','desc', 'key')); + + $result['list'] = $model->findAll($request, $request->get('ref')); + $result['size'] = $model->getCount($request, $request->get('ref')); + return json::encode($result); + } + + /** + * Удаление сторк из таблицы + */ + public function actionDelete(HttpRequest $request) + { + $model = $this->getModel($this->useModel); + // Почему table_item ??? + $list = ($request->get('table_item')) ? $request->get('table_item'): $request->get('id'); + $model->deleteList($list); + + return $this->getJSONList($model, $request); + } + + /** + * Ответ на запрос по поиску + */ + public function actionSearch(HttpRequest $request) + { + $model = $this->getModel($this->useModel); + $model->addFilter($model->requestToSQL($request, $this->formSchema)); + + return $this->getJSONList($model, $request); + } + + /** + * Список элементов + */ + public function actionList(HttpRequest $request) + { + $model = $this->getModel($this->useModel); + return $this->getJSONList($model, $request); + } + + + private function setFormSchema() + { + require_once 'core/mapper/uimapper.php'; + + $model = $this->getModel($this->useModel); + $ui = new UIMapper($model); + + $this->formSchema = $ui->getFormSchema(); + } + + /** + * Сохранение формы + */ + function beforeSave(/*Model*/ $item, Collection $request) + { + if (empty($this->formSchema)) { + $this->setFormSchema(); + } + // Сделать отображение Формы в обьект и обратно <-- Убрать в beforeSave + foreach ($this->formSchema as $key => $conv) { + list($value, $type) = $conv; + $item->$value = call_user_func(array('Cast', 'to_' . $type), $request->get($key)); // Здесть нужно преобразовывать тип значения + } + } + + /** + * Обновление формы + */ + function formUpdate(TForm $form, Collection $request) + { + } + + /** + * Загрузка формы + */ + function beforeLoad(/*Model*/ $item, TForm $form) + { + if (empty($this->formSchema)) { + $this->setFormSchema(); + } + // Вставка значений из данных в форму + // Отображение обьекта в поля формы + $form->fill($item, $this->formSchema); + } + + // Проверка ввода + protected function validate($validator, $request) + { + } + + /** + * Действие для проверки формы + */ + public function actionValidate($request) + { + require_once "core/validator/validator.php"; + $validator = new Validator(); + $validator->addRuleList($this->schema); + + // Действия до проверки формы + $this->validate($validator, $request); // <--| + $validator->validate($request); // --| + // Проверка формы + if (!$validator->isValid()) { + return json::encode($validator->getErrorMsg()); + } + return json::encode(true); + } + + /** + * Инициализация формы + */ + protected function formSetup($form, $id = null, $ref = null) + { + if (empty($this->schema)) { + $model = $this->getModel($this->useModel); + $ui = new UIMapper($model); + $schema = $ui->getEditSchema(); + + $form->addFieldList($schema); + } else { + $form->addFieldList($this->schema); + } + } + + /** + * Добавление пользователя + */ + public function actionAdd(HttpRequest $request) + { + require_once "core/validator/validator.php"; + // {{{ тоже может быть один ref или несколько + $ref = $request->get('ref'); + $this->addParameter('ref', $ref); // Добавляет параметр в url + /// }}} + + if ($this->checkPageId($request, $request->get('page'))) { + // Проверка + $validator = new Validator(); + $validator->addRuleList($this->schema); + + // Действия до проверки формы + $this->validate($validator, $request); // <--| + $validator->validate($request); // --| + // Проверка формы + if (!$validator->isValid()) { + $request->setAction('form'); + $this->getActionPath($request); + + $form = new TForm(); + $this->formSetup($form, $request->get('id'), $request->get('ref')); // Инициализация формы + + $form->setValues($request); // <-- Убрать в formUpdate + $this->formUpdate($form, $request); + + $form->setError($validator); // Установка ошибок для формы + + $tpl = $this->formPage($form, $request); + $id = $request->get('id'); + if ($id) { // Редактирование + $tpl->action = forceUrl($this->nUrl('add', array('id' => $id, 'page' => $this->getPageId($request)))); // action Совйство формы + } + return $tpl /*->execute()*/; + } + + // Нужен тест для формы + $model = $this->getModel($this->useModel); + $className = $model->className; + $item = new $className(); + + // Сохраняем значение в базе данных + $item->id = $request->get('id'); + // Если таблица связана с другой таблицей + if ($request->get('ref') && $model->reference[1]) { + $ref_id = $model->reference[1]; + $item->$ref_id = $request->get('ref'); + } + + // Подготовка к сохранению + $this->beforeSave($item, $request); // Сюдаже и истрия переходов + // nextId ??? или выход или новая форма для создания новости + $model->saveDB($item, $request); + } + + // Для страницы со списком id -> идентефикатор родительской таблицы !!?? +// $request->set('id', $request->get('ref')); + if ($request->get('apply')) { + $request->setAction('form'); + return $this->forward('actionForm', $request); + } + return $this->forward('actionIndex', $request); + } + + /** + * Заголовок + */ + private function setTitlePath($ref) + { + if ($ref) { + $model = $this->getModel($this->useModel); + if (is_array($model->reference) && $model->reference[0]) { + $refmodel = $this->getModel($model->reference[0]); + try { + $parent = $refmodel->findById($ref); + $this->path->addTitle($parent->getTitle()); // Заголовок к подписям путей + } catch (Exception $e) { + // Не найден заголовок потому что неправильно определен родительский элемент + } + } + } + } + + /** + * Форма для редактирования + */ + public function actionForm(HttpRequest $request) + { + $this->getActionPath($request); + $ref = $request->get('ref'); + $this->addParameter('ref', $ref); // Добавляет параметр в url + $this->setTitlePath($ref); + + $model = $this->getModel($this->useModel); + $form = new TForm(); // Показываем форму + $form->header = 'Редактирование записи'; + $this->formSetup($form, $request->get('id'), $request->get('ref')); // Инициализация формы + + $list = $request->get('table_item'); + $id = ($list[0]) ? $list[0] : $request->get('id'); + + $tpl = $this->formPage ($form, $request); + if ($id) { // Редактирование + $form->action = forceUrl($this->nUrl('add', array('id' => $id, 'page' => $this->getPageId($request)))); // action Свойство формы + $item = $model->findById($id); + // Загрузка формы + $this->beforeLoad($item, $form); + /// + } + return $tpl; + } + + /** + */ + function tableSetup($table, $id = null, $ref = null) + { + // FIXME: После замены везде $tableSchema -> table->setHeader удалить! + if ($this->tableSchema) { + $table->setHeader($this->tableSchema); + } else { + // Настройка таблицы отображения по схеме данных + require_once 'core/mapper/uimapper.php'; + $model = $this->getModel($this->useModel); + $ui = new UIMapper($model); + $schema = $ui->getTableSchema(); + $schema[0]['action'] = $table->getFirstItem(); + + $table->setHeader($schema); + } + } + + /** + */ + public function actionIndex(HttpRequest $request) + { + $this->getActionPath($request, 'index'); + // Такое мета действие наверное можно вынести в отдельный класс + return $this->metaActionIndex($request, array($this, 'tableSetup'), $this->aUrl('list')); + } + + /** + * Страница по умолчанию + */ + public function metaActionIndex(HttpRequest $request, $setup, $list) + { + // может быть одно ref или несколько + // {{{ история переходов + $ref = null; + if ($request->get('ref')) { + $ref = $request->get('ref'); + } else if ($request->session()->get('ref')) { + $ref = $request->session()->get('ref'); + } + + $request->session->set('ref', $ref); + $this->addParameter('ref', $ref); + // }}} + $this->setTitlePath($ref); + + $tpl = $this->getView('list'); + + // Помошники действий + $this->callHelpers($request); + // Таблица + if ($request->session()->get(strtolower(get_class($this)))) { + $session = $request->session()->get(strtolower(get_class($this))); + if (isset($session['view'])) { + $this->table->setView($session['view']); + } + $this->table->setData('state', array( + 'page' => $session['page'], + 'size' => $session['size'], + 'desc' => $session['desc'])); + + $this->table->setData('sorter', $session['key']); + if (isset($session['desc'])) { + $this->table->setData('desc', $session['desc']); + } + } + + call_user_func($setup, $this->table, $request->get('id'), $ref);// --> Эквивалент formSetup + $this->table->setAction($list); + // + $tpl->menu_path = $this->path->getItems(); + + // Поиск + $search = new SearchDialog(); + $search->setTitle('Поиск'); + $search->setAction($this->aUrl('search')); + $search->setFriend($this->table); + $search->addFields($this->schemaSearch); + + // Настройки + $setup = new SetupDialog(); + $setup->setTitle('Настройки'); + $setup->setAction($this->nUrl('setup')); + $setup->setFriend($this->table); + + // Меню + $this->menu->addMenuItem('?menu=toggle&id=' . $search->getName(), 'поиск', 'actions/system-search'); // Стандартный размер для иконок 22-24px + $this->menu->addMenuItem('?menu=toggle&id=' . $setup->getName(), 'настройки', 'categories/applications-system'); + // Добавление компонентов + $this->addChild('menu', $this->menu); + $this->addChild('search', $search); + $this->addChild('setup', $setup); + $this->addChild('table', $this->table); + // + return $tpl; + } + + /** + */ + public function actionSetup($request) + { + $left = explode(",", $request->get('left')); + $right = explode(",", $request->get('right')); + + $$request->session()->set(strtolower(get_class($this)), + array('view' => array('left' => $left, 'right' => $right))); + + return $this->forward('actionIndex', $request); + } + + /** + */ + private function formPage($form, $request) + { + $view = $this->getView('form'); + $view->setView('form', $form); + $view->action = forceUrl($this->nUrl('add', array('page' => $this->getPageId($request)))); // Действие для формы + + $view->menu_path = $this->path->getItems(); + $view->back = $this->path->getPrev(); + return $view; + } + + // Тоже убрать в метод Controller_Model + function getActionPath(HttpRequest $request/*, $action = false*/) + { + require_once 'state.php'; + $this->_getActionPath()->getPath($this, ($action) ? $action : $request->getAction()); + } +} diff --git a/src/controller/state.php b/src/controller/state.php index 00db7f0..aafff35 100644 --- a/src/controller/state.php +++ b/src/controller/state.php @@ -13,7 +13,7 @@ class Controller_State static function make($action) { - return new State($action); + return new Controller_State($action); } public function addTitle($name, $url = array()) @@ -22,7 +22,7 @@ class Controller_State return $this; } - public function addState(State $state) + public function addState(Controller_State $state) { $this->states [$state->getAction()] = $state; return $this; @@ -49,7 +49,7 @@ class Controller_State return false; } - function makeTitle($module) + function makeTitle(Controller_Action $module) { foreach ($this->titles as $item) { $module->path->addMenuItem($module->nUrl($this->action, $item[1]), $item[0]); @@ -68,12 +68,3 @@ class Controller_State } } } - - -/* -$path = State::make('index') - ->addState(State::make('form')) - ->addState(State::make('view')); - -$path->getPath(0, 'form'); -*/ diff --git a/src/filter/actionlogger.php b/src/filter/actionlogger.php index fce3ef5..c92d37c 100644 --- a/src/filter/actionlogger.php +++ b/src/filter/actionlogger.php @@ -1,7 +1,5 @@ getConnection(); - UserAccess::setUp($db); // Соединение + Filter_UserAccess::setUp($db); // Соединение switch ($request->getAction()) { // Авторизация по постоянному паролю case 'login': $login = $request->get('login'); $password = $request->get('password'); - $result = UserAccess::getUserByLogin($login); // Поиск по логину + $result = Filter_UserAccess::getUserByLogin($login); // Поиск по логину if ($result) { if (md5($password) == $result->getString('password')) { // password $this->enter($db, $result); diff --git a/src/filter/useraccess.php b/src/filter/useraccess.php index 126b21d..8fac5e0 100644 --- a/src/filter/useraccess.php +++ b/src/filter/useraccess.php @@ -1,10 +1,7 @@ {$key}; + } + return $result; +} + function assoc_key_values($key, $value, $array) { $result = array(); foreach ($array as $item) { @@ -245,7 +254,7 @@ function assoc_key($key, $array) { return $result; } -function _get($key, $value, $array) { +function _get($key, /*.any.*/$value, /*.array.*/$array) { foreach ($array as $item) { if ($item[$key] == $value) return $item; } @@ -265,7 +274,7 @@ function _get_key($key, $value, $array) { * @return bool */ function every(array $array, $callback) { - foreach ($array as $key => $value) { + foreach ($array as $value) { if (call_user_func($callback, $value) === false) { return false; } @@ -337,10 +346,33 @@ if (!function_exists('hash_key')) { }; } -function array_merge1($x, $y) { - $result = $x; - foreach ($y as $k => $v) { - $result [$k] = $v; +/** + * Выбирает все сроки из таблицы с уникальными значениями ключа + * @param $name Имя ключа + * @param $table Двухмерный массив + * @example + * key_unique_values ('name', array (array ('name' => 1), array ('name' => 2), array ('name' => 1))) + => array (1, 2) + * @end example + */ +function key_unique_values ($name, $table) { + // Ищем уникальные значения для заданного ключа + $keys = array (); + foreach ($table as $row) { + if (!in_array ($row[$name], $keys)) + $keys[] = $row[$name]; } - return $result; + return $keys; +} + +/** + * Сортировка двумерного массива по заданному ключу + * @param $array Массив + * @param $key Имя ключа по значению которого будет идти сравнение + * @return Отсортированный массив + */ +function sortOn($array, $key, $fn = '__cmp') { + usort ($array, rcurry($fn, $key)); + //usort ($array, create_function ('$x,$y', 'return __cmp ($x, $y, "'.$key.'");')); + return $array; } diff --git a/src/httprequest.php b/src/httprequest.php index 836cc89..7693177 100644 --- a/src/httprequest.php +++ b/src/httprequest.php @@ -10,6 +10,8 @@ class WrongRequestException extends Exception // HTTPRequest = ArrayAccess class HttpRequest extends Collection implements ArrayAccess { + + public $_session; /** * Constructor * Stores "request data" in GPC order. @@ -24,9 +26,8 @@ class HttpRequest extends Collection implements ArrayAccess $ajax = $this->isAjax(); foreach ($list as $key => $value) { - $data = new SafeCollection(); + $data = new Collection(); $data->import($value); - parent::set($key, $data); } @@ -35,50 +36,32 @@ class HttpRequest extends Collection implements ArrayAccess parent::set('files', $data); } - function get($key, $default = null) - { - return parent::get('data')->get($key, $default); - } - - function session($value = false) - { - if ($value) { - $this->session = $value; - } - return $this->session; - } - - function set($key, $value) - { - return parent::get('data')->set($key, $value); - } - - function _get($key) { return parent::get($key); } - function export() + function get($key, $default = null) { - return parent::get('data')->export(); + return parent::get('data')->get($key, $default); + } + + function session(Session $value = null) + { + if ($value) { + $this->_session = $value; + } + return $this->_session; } - /* Array Acces Interface */ - function offsetExists($offset) + function set($key, /*.any.*/$value) { + return parent::get('data')->set($key, $value); } - function offsetGet($offset) - { - } - - function offsetSet($offset, $value) - { - } - - function offsetUnset($offset) + function export($key = 'data') { + return parent::get($key)->export(); } function clear() @@ -125,4 +108,22 @@ class HttpRequest extends Collection implements ArrayAccess { return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && ($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest'); } + + public function redirect($url) { + header('location: ' . $url); + exit(); + } + + + public function offsetSet($key, $value) { + } + + public function offsetExists($key) { + } + + public function offsetUnset($key) { + } + + public function offsetGet($key) { + } } diff --git a/src/layout/layout.php b/src/layout/manager.php similarity index 82% rename from src/layout/layout.php rename to src/layout/manager.php index 7c13029..5107e36 100644 --- a/src/layout/layout.php +++ b/src/layout/manager.php @@ -1,13 +1,13 @@ 'personal'), 'personal') * addConditionGet(array('module' => 'login'), 'login') */ - public function addConditionGet($get, Filter $layout) + public function addConditionGet($get, Filter_Filter $layout) { $this->addCondition(rcurry(array($this, 'checkGet'), $get), $layout); } @@ -28,7 +28,7 @@ class LayoutManager extends Filter /** * Условие для аякс запросов. Тоже самое что и addConditionGet но еще проверяется является ли запрос ajax */ - public function addConditionXHR($get, Filter $layout) + public function addConditionXHR($get, Filter_Filter $layout) { $this->addCondition(rcurry(array($this, 'checkXHR'), $get), $layout); } @@ -51,11 +51,11 @@ class LayoutManager extends Filter } /** - * Добавляет есловие в общем виде + * Добавляет условие в общем виде * @parma $get function(HttpRequest) Функция * @parma $layout Layout Макет */ - public function addCondition($get, Filter $layout) + public function addCondition($get, Filter_Filter $layout) { $this->condition [] = array($get, $layout); } @@ -81,13 +81,3 @@ class LayoutManager extends Filter } } -/** - * Самый простой макет - */ -class LayoutNone extends Filter -{ - function execute(HttpRequest $request) - { - return $this->processor->execute($request); - } -} diff --git a/src/layout/none.php b/src/layout/none.php new file mode 100644 index 0000000..ed02085 --- /dev/null +++ b/src/layout/none.php @@ -0,0 +1,11 @@ +processor->execute($request); + } +} diff --git a/src/mail.php b/src/mail.php index 3bd2ef1..c1de6fe 100644 --- a/src/mail.php +++ b/src/mail.php @@ -6,14 +6,14 @@ */ class Mail { - public $from; - public $to; - public $subject; + public $_from; + public $_to; + public $_subject; public $content; public $copy; private $encoding; - private $notify= false; + private $_notify = null; protected $attachment = array (); protected $uniqid; @@ -22,8 +22,6 @@ class Mail function __construct() { $this->setEncoding("UTF-8"); $this->uniqid = strtoupper(uniqid(time())); // Идентефикатор разделителя - -// $this->mime } /** @@ -31,7 +29,7 @@ class Mail */ function from($name) { - $this->from = $name; + $this->_from = $name; } /** @@ -39,7 +37,7 @@ class Mail */ function to($name) // recipient { - $this->to = $name; + $this->_to = $name; } /** @@ -52,7 +50,7 @@ class Mail function notify($notify) { - $this->notify = $notify; + $this->_notify = $notify; } /** @@ -60,7 +58,7 @@ class Mail */ function subject($subject) { - $this->subject = $subject; + $this->_subject = $subject; } /** @@ -70,12 +68,7 @@ class Mail { $this->content = $text; } - - function setType($type) - { - $this->type = $type; - } - + /** * Кодировка текста в письме */ @@ -93,11 +86,18 @@ class Mail if(file_exists($filename)) { // assert ?? $file = fopen($filename, "rb"); - $data = fread($file, filesize($filename)); - $this->attachment [] = ($name) ? array($data, $name) : array($data, basename($filename)); + if (is_resource($file)) { + $data = fread($file, filesize($filename)); + $this->attachment [] = ($name) ? array($data, $name) : array($data, basename($filename)); + } } } + function setType($type) + { + $this->type = $type; + } + /** * Добавление вложения из строки с указанием имени файла */ @@ -115,7 +115,7 @@ class Mail /** * Общий формат тегов MIME - * http://tools.ietf.org/html/rfc2045 + * @see http://tools.ietf.org/html/rfc2045 */ function mimeTag($name, $value, array $args = array()) { @@ -127,7 +127,7 @@ class Mail /** * - * http://tools.ietf.org/html/rfc2047 + * @see http://tools.ietf.org/html/rfc2047 */ function encodedWord($text, $encoding = 'B') { @@ -144,16 +144,16 @@ class Mail $message .= $this->mimeTag("Content-Transfer-Encoding", "8bit"); $message .= PHP_EOL . $this->content . PHP_EOL . PHP_EOL; - /** + /* * Вложения * http://tools.ietf.org/html/rfc2046#section-5.1.3 */ foreach ($this->attachment as $value) { list($data, $name) = $value; $message .= "--" . $this->uniqid . PHP_EOL; - $message .= $this->mimeTag("Content-Type", "application/octet-stream", array ('name' => $name)); + $message .= $this->mimeTag("Content-Type", "application/octet-stream", array ('name' => basename($name))); $message .= $this->mimeTag("Content-Transfer-Encoding", "base64"); - $message .= $this->mimeTag("Content-Disposition", "attachment", array ('filename' => $name)); + $message .= $this->mimeTag("Content-Disposition", "attachment", array ('filename' => basename($name))); $message .= PHP_EOL . chunk_split(base64_encode($data)) . PHP_EOL; } @@ -166,11 +166,11 @@ class Mail function getHeader() { $head = $this->mimeTag("MIME-Version", "1.0"); - $head .= $this->mimeTag("From", $this->from); - $head .= $this->mimeTag("X-Mailer", "CIS Tool"); - $head .= $this->mimeTag("Reply-To", $this->from); - if ($this->notify) { - $head .= $this->mimeTag("Disposition-Notification-To", "\"" . $this->notify . "\" <" . $this->from . ">"); + $head .= $this->mimeTag("From", $this->_from); + $head .= $this->mimeTag("X-Mailer", "CMS Tool"); + $head .= $this->mimeTag("Reply-To", $this->_from); + if (is_string($this->_notify)) { + $head .= $this->mimeTag("Disposition-Notification-To", "\"" . $this->_notify . "\" <" . $this->_from . ">"); } $head .= $this->mimeTag("Content-Type", "multipart/mixed", array ("boundary" => $this->uniqid)); if ($this->copy) { @@ -182,7 +182,7 @@ class Mail function getSubject() { - return $this->encodedWord($this->subject); + return $this->encodedWord($this->_subject); } /** @@ -190,7 +190,7 @@ class Mail */ function eml() { - return "To: " . $this->to . PHP_EOL . "Subject: {$this->getSubject()}" . PHP_EOL . $this->getHeader() . $this->getMessage(); + return "To: " . $this->_to . PHP_EOL . "Subject: {$this->getSubject()}" . PHP_EOL . $this->getHeader() . $this->getMessage(); } /** @@ -198,7 +198,7 @@ class Mail */ function send() { - $result = mail($this->to, $this->getSubject(), $this->getMessage(), $this->getHeader()); + $result = mail($this->_to, $this->getSubject(), $this->getMessage(), $this->getHeader()); if(! $result) { throw new Exception('Невозможно отправить почту'); // require_once "core/path.php"; diff --git a/src/markup/simple_bb_code.php b/src/markup/simplebbcode.php similarity index 97% rename from src/markup/simple_bb_code.php rename to src/markup/simplebbcode.php index 3bb16f3..b21a845 100644 --- a/src/markup/simple_bb_code.php +++ b/src/markup/simplebbcode.php @@ -20,7 +20,7 @@ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. **/ -class Simple_BB_Code{ +class Markup_SimpleBBCode{ //General Tags var $tags = array('b' => 'strong','i' => 'em','u' => 'span style="text-decoration:underline"','quote' => 'blockquote','s' => 'span style="text-decoration: line-through"', 'list' => 'ul','\*' => 'li'); //Tags that must be mapped to diffierent parts @@ -38,7 +38,7 @@ class Simple_BB_Code{ var $auto_links = true; //Internal Storage var $_code = ''; - function Simple_BB_Code($new=true,$parse=true,$links=true){ + function __construct($new=true,$parse=true,$links=true){ $this->convert_newlines = $new; $this->parse_smilies = $parse; $this->auto_links = $links; diff --git a/src/numbers.php b/src/numbers.php index bd0adea..c0a39c7 100644 --- a/src/numbers.php +++ b/src/numbers.php @@ -12,7 +12,7 @@ class Numbers return $i; } - static function prefix($prefix, array $array) + static function prefix($prefix, array $array, $key = false) { $result = array(); for ($i = 0; $i < count($array); $i++) { diff --git a/src/path.php b/src/path.php index 70e83c0..1a74881 100644 --- a/src/path.php +++ b/src/path.php @@ -1,33 +1,58 @@ path = $this->fromString($path); - $this->optimize(); - } + $this->url = parse_url($path); + + if (isset($this->url['path'])) { + $path = $this->url['path']; +// $path = preg_replace('/\/{2,}/', '/', $path); + $this->path = self::optimize($this->fromString($path)); + } + } static function factory($path) { return new Path($path); } + public function getParts() + { + return $this->path; + } + + public static function normalize($pathName) + { + $path = new Path($pathName); + return $path->__toString(); + } + + /** + * Базовое имя + * @param $path + * @return mixed + */ + public static function basename($path) + { + $list = preg_split('#\\\\|/#s', $path); + return end($list); + } + /** * Возвращает расширение файла * @@ -35,13 +60,22 @@ class Path * * @return string */ - static function getExtension ($fileName) + static function getExtension($fileName) { - assert(is_string($fileName)); + assert(is_string($fileName) || is_null($fileName)); return pathinfo($fileName, PATHINFO_EXTENSION); } + static function isType($fileName, $extension) + { + if (is_array($extension)) { + return in_array(pathinfo($fileName, PATHINFO_EXTENSION), $extension); + } else { + return (pathinfo($fileName, PATHINFO_EXTENSION) == $extension); + } + } + /** * Полное имя файла без расширения * @@ -49,7 +83,7 @@ class Path * * @return string */ - static function skipExtension ($fileName) + static function skipExtension($fileName) { assert(is_string($fileName)); @@ -68,118 +102,13 @@ class Path * * @return string */ - static function getFileName ($fileName) + static function getFileName($fileName) { assert(is_string($fileName)); return pathinfo($fileName, PATHINFO_FILENAME); } - /** - * Список файлов в директории - * - * @param array $allow массив расширений для файлов - * @param array $ignore массив имен пааок которые не нужно обрабатывать - * - * @return array - */ - public function getContent ($allow = null, $ignore = array()) - { - $ignore = array_merge(array (".", "..", $ignore)); - return self::fileList($this->__toString(), $allow, $ignore); - } - - // Использовать SPL ??? - protected function fileList ($base, &$allow, &$ignore) - { - $result = array (); - if ($handle = opendir($base)) { - while (false !== ($file = readdir($handle))) { - if (! in_array ($file, $ignore)) { - $isDir = is_dir (Path::join ($base, $file)); - if ($isDir || ($allow == null) || in_array (self::getExtension($file), $allow)) { - $result[] = $file; - } - } - } - closedir($handle); - } - return $result; - } - - protected function fileListAll (&$result, $base, &$allow, &$ignore) - { - $files = self::fileList($base, $allow, $ignore); - foreach ($files as $name) { - $fullname = self::join($base, $name); - if (is_dir($fullname)) { - self::fileListAll($result, $fullname, $allow, $ignore); - } else { - array_push ($result, $fullname); - } - } - } - - /** - * Список файлов в директориии и ее поддиректорий - * - * @param array $allow массив расширений разрешеных для файлов - * @param array $ignore массив имен пааок которые не нужно обрабатывать - * - * @return array - */ - function getContentRec ($allow = null, $ignore = array()) - { - $result = array (); - $ignore = array_merge(array (".", ".."), $ignore); - self::fileListAll($result, $this->__toString(), $allow, $ignore); - return $result; - } - - - /** - * Рекурсивно копирует директорию - * - * @param string $source Папка из которой копируется - * @param string $target Папка в которую копируется - */ - public static function copy ($source, $target) - { - if (is_dir($source)) { - if (! file_exists($target)) mkdir ($target); - $path = new Path($source); - $files = $path->getContent(); - foreach ($files as $file) { - $entry = self::join($source, $file); - if (is_dir($entry)) { - self::copy($entry, Path::join($target, $file)); - } else { - copy($entry, Path::join($target, $file)); - } - } - } - } - - /** - * Рекурсивно удаляет директорию - * - * @param string $path Папка - */ - public static function delete ($path) - { - assert(is_string($path)); - - if (is_dir($path)) { - foreach(glob($path . '/*') as $sf) { - if (is_dir($sf) && !is_link($sf)) { - self::delete($sf); - } else { - unlink($sf); - } - } - rmdir($path); - } - } /** * Преобразует строку путя в массив @@ -192,28 +121,60 @@ class Path { assert(is_string($path)); - $list = preg_split("/[\/\\\\]/", $path); + $list = preg_split('#\\\\|/#s', $path); + if (isset($this->url['scheme']) && !isset($this->url['host'])) { + $this->absolute = false; + } else if ($list[0] == '' && count($list) > 1) { + $this->absolute = true; + } + return $list; } /** * Преобразует относительный путь в абсолютный */ - public function optimize () + public static function optimize($path) // { - $result = array(current($this->path)); - while (next($this->path) !== false) { - $n = current ($this->path); + $result = array(); + foreach ($path as $n) { switch ($n) { + // Может быть относительным или абсолютным путем case "": break; case ".": break; - case "..": if (count($result) > 0) array_pop($result); break; + case "..": + if (count($result) > 0) { array_pop($result); break; } default: array_push($result, $n); } - } - reset($this->path); - $this->path = $result; + } + return $result; + } + + // Сравнение двух путей на равентство + public function equal(/*.Path.*/ $path) + { + if (count($this->path) == count($path->path)) { + for ($i = 0; $i < count($this->path); $i++) { + if ($this->path[$i] != $path->path[$i]) { + return false; + } + } + return true; + } + return false; + } + + public static function makeUrl($path) + { + return (isset($path['scheme']) ? $path['scheme'] . ':/' : '') + . (isset($path['host']) ? ('/' + . (isset($path['user']) ? $path['user'] . (isset($path['pass']) ? ':' . $path['pass'] : '') . '@' : '') + . $path['host'] + . (isset($path['port']) ? ':' . $path['port'] : '')) : '') + . $path['path'] + . (isset($path['query']) ? '?' . $path['query'] : '') + . (isset($path['fragment']) ? '#' . $path['fragment'] : ''); } /** @@ -221,10 +182,11 @@ class Path * * @return string */ - public function __toString () + public function __toString() { - $result = implode($this->path, self::SEPARATOR); - return $result; + $result = (($this->absolute) ? '/' : '') . implode(self::SEPARATOR, $this->path); + $this->url['path'] = $result; + return self::makeUrl($this->url); } /** @@ -234,8 +196,11 @@ class Path * * @return boolean */ - public function isParent ($path) + public function isParent(/*.Path.*/ $path) { + if (isset($this->url['host']) && isset($path->url['host']) + && ($this->url['host'] != $path->url['host'])) return false; + if (count($path->path) > count($this->path)) { for ($i = 0; $i < count($this->path); $i++) { if ($path->path[$i] != $this->path[$i]) { @@ -246,6 +211,12 @@ class Path } return false; } + + public static function _isParent($path1, $path2) + { + $path = new Path($path1); + return $path->isParent(new Path($path2)); + } /** * Находит путь относительно текущего путя @@ -254,34 +225,97 @@ class Path * * @return string Относительный путь к файлу */ - public function relPath ($name) + public function relPath($name) { - $path = new Path ($name); + $path = new Path($name); + unset($path->url['scheme']); +// $this->absolute = false; + $path->absolute = false; foreach ($this->path as $n) { array_shift($path->path); } return $path->__toString(); } - public function append ($path) + // Вычисляет относительный путь в виде строки + static function relative($rpath, $lpath) { + // Нужно проверять диск!! + $self = new Path($rpath); + $list = new Path($lpath); + $self_path = $self->getParts(); + $list_path = $list->getParts(); + + $result = array(); + for ($i = 0; $i < count($list_path); $i++) { + if (($i >= count($self_path)) || $list_path[$i] != $self_path[$i]) { + break; + } + } + for($j = $i; $j < count($list_path); $j++) { + array_push($result, '..'); + } + for($j = $i; $j < count($self_path); $j++) { + array_push($result, $self_path[$j]); + } + return implode("/", $result); + } + + public function append($path) { $base = $this->__toString(); return self::join($base, $path); - } + } + /** - * Создает недастающие папки для записи файла - * - * @param string $dst Полное имя файла - * - * @return void + * Обьединяет строки в путь соединяя необходимым разделителем + * fixme не обрабатывает параметры урла, решение Path::join(SITE_WWW_PATH) . '?param=pampam' + * @return string */ - static function prepare ($dst) + static function join($_rest) { - $path_dst = pathinfo($dst, PATHINFO_DIRNAME); - if (! file_exists($path_dst)) { - mkdir($path_dst, 0700, true); + $args = func_get_args(); + $result = array(); + $parts0 = new Path(array_shift($args)); + $result [] = $parts0->getParts(); + foreach ($args as $file) { + $parts = new Path($file); + $result [] = $parts->getParts(); } + // При обьединении ссылок можно обьеденить path, query, fragment + $path = implode(self::SEPARATOR, call_user_func_array('array_merge', $result)); + $parts0->url['path'] = ($parts0->isAbsolute()) ? '/' . $path : $path; + return self::makeUrl($parts0->url); + } + + // Проверка структуры имени файла + static function checkName($name, $extension) + { + return (strlen(pathinfo($name, PATHINFO_FILENAME)) > 0) && (pathinfo($name, PATHINFO_EXTENSION) == $extension); + } + + static function isCharName($char) + { + $ch = ord($char); + return ((($ch >= ord('a')) && ($ch <= ord('z'))) || (strpos('-._', $char) !== false) || (($ch >= ord('0')) && ($ch <= ord('9')))); + } + + // Проверка имени файла + static function isName($name) { + if (strlen(trim($name)) == 0) { + return false; + } + for ($i = 0; $i < strlen($name); $i++) { + if (!self::isCharName($name[$i])) { + return false; + } + } + return true; + } + + public function isAbsolute() + { + return $this->absolute; } /** @@ -291,7 +325,7 @@ class Path * * @return string Новое имя файла */ - static function resolveFile ($dst) + static function resolveFile($dst) { $i = 0; $file = self::skipExtension($dst); @@ -304,14 +338,93 @@ class Path return $temp; } + + /** + * Список файлов в директории + * + * @param array $allow массив расширений для файлов + * @param array $ignore массив имен пааок которые не нужно обрабатывать + * + * @returnarray + */ + public function getContent($allow = null, $ignore = array()) + { + $ignore = array_merge(array(".", ".."), $ignore); + return self::fileList($this->__toString(), $allow, $ignore); + } + /** * Обьединяет строки в путь соединяя необходимым разделителем * - * @return string - */ - static function join () + * @param array $allow массив расширений разрешеных для файлов + * @param array $ignore массив имен пааок которые не нужно обрабатывать + * + * @return array + */ + function getContentRec($allow = null, $ignore = array()) { - $args = func_get_args(); - return implode(self::SEPARATOR, $args); + $result = array (); + $ignore = array_merge(array (".", ".."), $ignore); + self::fileListAll($result, $this->__toString(), $allow, $ignore); + return $result; + } + + // Использовать SPL ??? + protected static function fileList($base, &$allow, &$ignore) + { + if ($base == '') $base = '.'; + $result = array (); + $handle = opendir($base); + if (is_resource($handle)) { + while (true) { + $file = readdir($handle); + if (is_string($file)) { + if (! in_array($file, $ignore)) { + $isDir = is_dir(Path::join($base, $file)); + if ($isDir || ($allow == null) || in_array(self::getExtension($file), $allow)) { + $result[] = $file; + } + } + continue; + } + break; + } + closedir($handle); + } + // При обьединении ссылок можно обьеденить path, query, fragment + return $result; + } + + protected static function fileListAll(&$result, $base, &$allow, &$ignore) + { + $files = self::fileList($base, $allow, $ignore); + foreach ($files as $name) { + $fullname = self::join($base, $name); + if (is_dir($fullname)) { + self::fileListAll($result, $fullname, $allow, $ignore); + } else { + array_push($result, $fullname); + } + } + } + + /** + * Создает недастающие папки для записи файла + * + * @param string $dst Полное имя файла + * + * @return void + */ + static function prepare($dst, $filename = true) + { + if ($filename) { + $path_dst = pathinfo($dst, PATHINFO_DIRNAME); + } else { + $path_dst = $dst; + } + if (! file_exists($path_dst)) { + mkdir($path_dst, 0777, true); + } } } + diff --git a/src/registry.php b/src/registry.php index 862a3d4..f2b7673 100644 --- a/src/registry.php +++ b/src/registry.php @@ -1,5 +1,7 @@ + /** * http://www.patternsforphp.com/wiki/Registry * http://www.patternsforphp.com/wiki/Singleton diff --git a/src/session.php b/src/session.php index 2d2b666..43ec665 100644 --- a/src/session.php +++ b/src/session.php @@ -26,7 +26,7 @@ class Session function start() { - session_start(); + @session_start(); } function stop() diff --git a/src/settings.php b/src/settings.php index 3566c89..ee1fc2d 100644 --- a/src/settings.php +++ b/src/settings.php @@ -12,23 +12,31 @@ class Settings extends Collection { protected $file; + protected $format = 'php'; + public function __construct ($file = null) { + $this->format = pathinfo($file, PATHINFO_EXTENSION); $this->file = $file; } /** * Чтение настроек из файла - * - * @param File $file - * * @return Boolean */ public function read() { - if ( !file_exists ($this->file)) return false; + if (!file_exists ($this->file)) { + return false; + } // Не include_once т.к читать настройки можно несколько раз - include($this->file); + $settings = array(); + if ($this->format == 'json') { + $settings = json_decode(file_get_contents($this->file), true); + } else { + include ($this->file); + } + if (!is_array($settings)) { throw new Exception($this->file); } @@ -51,7 +59,9 @@ class Settings extends Collection // assert(count($key) == 1); $name = array_shift($key); if (is_array($value)) { - if (! isset($data[$name])) $data[$name] = array(); + if (!isset($data[$name])) { + $data[$name] = array(); + } $this->merge($data[$name], $value); } else { $data[$name] = $value; @@ -107,7 +117,7 @@ class Settings extends Collection * Чтение ключа из реестра (Собирает все ключи с определенным значением во всех модулях) * @param $key Путь к значению ключа внутри модуля */ - public function readKeyList() + public function readKeyList($_rest) { $key = func_get_args(); $result = array(); @@ -149,10 +159,15 @@ class Settings extends Collection * * @return void */ - public function write($file = false) + public function write($file = null) { - $result = var_export ($this->data, true); - file_put_contents (($file) ? $file : $this->file, ""); + if ($this->format == 'json') { + $result = json_encode($this->data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); + } else { + $result = var_export($this->data, true); + $result = ""; + } + file_put_contents (($file) ? $file : $this->file, $result); } /** diff --git a/src/setup.php b/src/setup.php index a925103..c3c754c 100644 --- a/src/setup.php +++ b/src/setup.php @@ -1,54 +1,212 @@ + * $setup = new Setup('test.xml'); + * $setup->set('target', 'dst'); + * $setup->executeActions('install'); + * + */ class Setup { - /** - * Содержимое PHP файла - */ - static function fileContent($file, array $tpl) + protected $actions = array(); + public $context = array(); + protected $file; + protected $action; + protected $node; + protected $stack = array(); + + public $zip; + public $target; + + public function __construct($file) { - ob_start(); - include $file; - $result = ob_get_contents(); - ob_clean(); - return $result; + $this->file = $file; + $this->node = simplexml_load_file($file); + + $this->target = ''; + $this->zip = new ZipArchive(); + $this->zip->open(strtr($file, array('.xml' => '.zip'))); + + + array_push($this->stack, $this->node); + + $this->registerAction('copy', array($this, 'copyFile')); + $this->registerAction('make-directory', array($this, 'makeDirectory')); + $this->registerAction('make-link', array($this, 'makeLink')); + $this->registerAction('include', array($this, 'includeFile')); + $this->registerAction('when', array($this, 'testWhen')); } /** - * Копирует файлы шаблонной директории + * Регистрация новых действия для установки */ - static function copyTemplatePath($srcPath, $dstPath, array $tpl, $tplFile = 'tpl') + public function registerAction($name, $action) { - $out = new Path($srcPath); - $path = new Path($dstPath); - $files = $path->getContentRec(null, array(".svn")); + $this->actions[$name] = $action; + } - foreach ($files as $file) { - if (Path::getExtension($file) == $tplFile) { - // Шаблон - $dst = $out->append($path->relPath (Path::skipExtension($file))); - Path::prepare($dst); - file_put_contents($dst, self::fileContent($file, $tpl)); - } else { - // Обычный файл - $dst = $out->append($path->relPath ($file)); - Path::prepare($dst); - copy($file, $dst); - } + /** + * Установка переменных для шаблона + */ + public function set($name, $value) + { + $this->context[$name] = $value; + } + + function replaceFn($matches) { + if (isset($this->context[$matches[2]])) { + $v = $this->context[$matches[2]]; + } else { + $v = $matches[2]; + } + + if ($matches[1] == '*') { + return addslashes($v); + } + return $v; + } + + public function fileContent($file, array $tpl) + { + $result = $this->zip->getFromName($file); + $result = preg_replace_callback('/\{\{\s*(\*?)(\w+)\s*\}\}/', array($this, 'replaceFn'), $result); + return $result; + } + + function callAction($name, array $attributes) + { + if(isset($this->actions[$name])) { + call_user_func_array($this->actions[$name], $attributes); + } + } + + /** + * Заменяет переменные на их значения в строке + */ + function replaceVariable(array $match) + { + if (isset($this->context[$match[1]])) { + return $this->context[$match[1]]; + } + return $match[0]; + } + + /** + * Для всех аттрибутов заменяет переменные на их значения + */ + function resolve($attributes) + { + $result = array(); + foreach ($attributes as $key => $value) { + $result [$key] = preg_replace_callback("/\\\${(\w+)}/", array($this, 'replaceVariable'), $value); + } + return $result; + } + + /** + * Выполняет список действий если для действия не указан аттрибут when то оно выполняется всегда + * + * @param $action специальное действие + */ + function executeActions($action = "install") + { + $this->action = $action; + if ($this->stack[count($this->stack) - 1] === false) { + return; + } + + /*.SimpleXMLElement.*/$item = $this->stack[count($this->stack) - 1]; + $root = $item->children(); + foreach ($root as $node) + { + $attributes = $node->attributes(); + array_push($this->stack, $node); + $this->callAction($node->getName(), array($this->resolve($attributes))); + array_pop($this->stack); + } + } + + /** + * Копирования файла + * @param preserve Не переписывать файл если он существует + * @param template Файл является шаблоном подставить параметры до копирования + * @param src Исходный файл + * @param dst Новый файл + */ + public function copyFile(array $attributes) + { + $path = $this->targetPath($attributes['dst']); + + if (!(file_exists($path) && isset($attributes['preserve']))) { + file_put_contents($path, $this->fileContent($attributes['src'], $this->context)); + } + } + + /** + * Создает символическую ссылку на папку/файл + * @param dst Имя папки + */ + public function makeLink(array $attributes) + { + if (function_exists('symlink')) { + symlink($attributes['target'], $attributes['link']); + } + } + + /** + * Подключение файла установки + * @param file Имя подключаемого файла + */ + public function includeFile(array $attributes) + { + $file = basename($this->file) . "/" . $attributes['file']; + + $setup = new Setup($file); + $setup->context = $this->context; + $setup->executeActions(); + } + + function targetPath($s) { + return $this->target . '/' . $s; + } + + /** + * Создает новую папку + * @param dst Имя папки + */ + public function makeDirectory(array $attributes) + { + $path = $this->targetPath($attributes['dst']); + if (!file_exists($path)) { + mkdir($path); + } + } + + function testWhen(array $attributes) + { + if (!isset($attributes['test']) || $attributes['test'] == $this->action) { + $this->executeActions($this->action); } } /** * Выполнение Списка SQL команд */ - static function batchSQL(Connection $conn, $file) + function batchSQLZip(/*.Database.*/ $conn, $file) { - $stmtList = SQLStatementExtractor::extractFile ($file); + $stmtList = Tools_SQLStatementExtractor::extract($this->zip->getFromName($file)); + foreach ($stmtList as $stmt) { + $conn->executeQuery ($stmt); + } + } + + static function batchSQL(/*.Database.*/ $conn, $file) + { + $stmtList = Utils_SQLStatementExtractor::extractFile($file); foreach ($stmtList as $stmt) { $conn->executeQuery ($stmt); } } } + diff --git a/src/shortcut.php b/src/shortcut.php index a80e5f5..4e24046 100644 --- a/src/shortcut.php +++ b/src/shortcut.php @@ -10,7 +10,7 @@ class Shortcut public $list = array(); // Singleton pattern - static public function getInstance () + static public function getInstance() { if (self::$instance == null) { self::$instance = new Shortcut(); @@ -24,7 +24,7 @@ class Shortcut */ public function addUrl($prefix, $path) { - $this->list [$prefix] = $path; + $this->list[$prefix] = $path; } /** @@ -38,9 +38,10 @@ class Shortcut /** * Возвращает путь по имени ярлыка */ - static function getUrl ($prefix, $name = null, $name1 = false) + static function getUrl($prefix, $name = null, $name1 = null) { $shortcut = self::getInstance(); + $names = $shortcut->variables; if ($name) { $names['$name'] = $name; @@ -48,10 +49,18 @@ class Shortcut if ($name1) { $names['$name1'] = $name1; } + if (isset($shortcut->list[$prefix])) { return strtr($shortcut->list[$prefix], $names); } - return false; + return null; } -} + static function expand($path) + { + $shortcut = self::getInstance(); + $names = $shortcut->variables; + return strtr($path, $names); + } + +} diff --git a/src/tales.php b/src/tales.php index e474ad6..2b411f7 100644 --- a/src/tales.php +++ b/src/tales.php @@ -2,33 +2,61 @@ /** * Расширения для PHPTAL для отображения времени и даты - * package utils */ class DateTime_Tales implements PHPTAL_Tales { - static public function date ($expression, $nothrow = false) + static public function date($expression, $nothrow = false) { - return "phptal_date(".PHPTAL_TalesInternal::path ($expression).")"; + return "phptal_date(".PHPTAL_Php_TalesInternal::path ($expression).")"; } - static public function time ($expression, $nothrow = false) + static public function time($expression, $nothrow = false) { - return "phptal_time(".PHPTAL_TalesInternal::path ($expression).")"; + return "phptal_time(".PHPTAL_Php_TalesInternal::path ($expression).")"; } } -/* Регистрация нового префикса для подключения компонента */ -$registry = PHPTAL_TalesRegistry::getInstance(); -$registry->registerPrefix('date', array('DateTime_Tales', 'date')); -$registry->registerPrefix('time', array('DateTime_Tales', 'time')); + +/** + * TALES для подключения компонентов + * component:name?param1=value1¶m2=value2 + */ +class Component_Tales implements PHPTAL_Tales +{ + static public function component($expression, $nothrow = false) + { + $s = PHPTAL_Php_TalesInternal::string($expression); + return "phptal_component(" . $s . ")"; + } +} function phptal_date ($e) { - return date ("d.m.Y", $e); + return date("d.m.Y", $e); } function phptal_time ($e) { - return date ("H:i", $e); + return date("H:i", $e); } + +/** + * Функция подключения компонента + */ +function phptal_component ($expression) { + global $db, $registry; // Нужно как-то передавать параметры + + $component = Controller_Component::loadComponent($expression, $db, $registry); + $req = new HttpRequest(); + + return $component->execute($req); +} + + +/* Регистрация нового префикса для подключения компонента */ +$tales = PHPTAL_TalesRegistry::getInstance(); +$tales->registerPrefix('component', array('Component_Tales', 'component')); +$tales->registerPrefix('date', array('DateTime_Tales', 'date')); +$tales->registerPrefix('time', array('DateTime_Tales', 'time')); + diff --git a/src/tools/drawing.php b/src/tools/drawing.php index b0cf247..85cbdfa 100644 --- a/src/tools/drawing.php +++ b/src/tools/drawing.php @@ -2,7 +2,6 @@ class Drawing { - const ALIGN_LEFT = "left"; const ALIGN_TOP = "top"; const ALIGN_BOTTOM = "bottom"; @@ -26,7 +25,6 @@ class Drawing static function imagettftextbox(&$image, $size, $angle, $left, $top, $color, $font, $text, $max_width, $max_height, $align, $valign) { -// echo var_dump($font); // echo $left,"\n", $top, "\n"; // echo $max_width,"\n", $max_height, "\n"; // self::drawrectnagle($image, $left, $top, $max_width, $max_height, array(0xFF,0,0)); @@ -44,7 +42,6 @@ class Drawing $last_width = 0; for ($i = 0; $i < count($words); $i++) { $item = $words[$i]; -// echo "->", $font, "\n"; $dimensions = imagettfbbox($size, $angle, $font, $current_line . ($first_word ? '' : ' ') . $item); $line_width = $dimensions[2] - $dimensions[0]; $line_height = $dimensions[1] - $dimensions[7]; @@ -75,6 +72,7 @@ class Drawing } // vertical align + $top_offset = 0; if ($valign == self::ALIGN_CENTER) { $top_offset = ($max_height - $largest_line_height * count($lines)) / 2; } elseif ($valign == self::ALIGN_BOTTOM) { @@ -84,17 +82,15 @@ class Drawing $top += $largest_line_height + $top_offset; $i = 0; - fb($lines); - fb($line_widths); foreach ($lines as $line) { // horizontal align + $left_offset = 0; if ($align == self::ALIGN_CENTER) { $left_offset = ($max_width - $line_widths[$i]) / 2; } elseif ($align == self::ALIGN_RIGHT) { $left_offset = ($max_width - $line_widths[$i]); } -// echo $font, "\n"; imagettftext($image, $size, $angle, $left + $left_offset, $top + ($largest_line_height * $i), $color, $font, $line); $i++; } diff --git a/src/view/composite.php b/src/view/composite.php new file mode 100644 index 0000000..e9427a6 --- /dev/null +++ b/src/view/composite.php @@ -0,0 +1,40 @@ +tal = new PHPTAL($file); + $this->tal->stripComments(true); + } + + function set($key, $val) + { + if ($key == 'title') { + $this->setTitle($val); + } + $this->tal->set($key, $val); + } + + function __set($key, $val) + { + $this->tal->set($key, $val); + } + + function setTranslator($tr) + { + $this->tal->setTranslator($tr); + } + + function execute() + { + parent::execute(); + // postProcess + return $this->tal->execute(); + } +} diff --git a/src/view/compositeview.php b/src/view/top.php similarity index 89% rename from src/view/compositeview.php rename to src/view/top.php index 890fed2..5e3477f 100644 --- a/src/view/compositeview.php +++ b/src/view/top.php @@ -1,6 +1,6 @@ tal = new PHPTAL($file); - $this->tal->setEncoding('WINDOWS-1251'); // PHP_TAL_DEFAULT_ENCODING !! - $this->tal->stripComments(true); - } - - function set($key, $val) - { - if ($key == 'title') { - $this->setTitle($val); - } - $this->tal->set($key, $val); - } - - function __set($key, $val) - { - $this->tal->set($key, $val); - } - - function setTranslator($tr) - { - $this->tal->setTranslator($tr); - } - - function execute() - { - parent::execute(); - // postProcess - return $this->tal->execute(); - } -} diff --git a/src/zipfile.php b/src/zipfile.php index e55c100..49c4ddd 100644 --- a/src/zipfile.php +++ b/src/zipfile.php @@ -5,21 +5,28 @@ */ class ZipFile extends ZipArchive { + private $ignore = array('.', '..'); + + public function addIgnore($name) + { + $this->ignore [] = $name; + } + private function addDirDo($location, $name) { assert(is_string($location) && is_string($name)); $name .= '/'; $location .= '/'; + $file = null; // Read all Files in Dir $dir = opendir($location); while (($file = readdir($dir)) !== false) { - if ($file === '.' || $file === '..') continue; - + if (in_array($file, $this->ignore)) continue; // Rekursiv, If dir: FlxZipArchive::addDir(), else ::File(); - $call = (is_dir($file)) ? 'addDir' : 'addFile'; + $call = (is_dir($location . $file)) ? 'addDir' : 'addFile'; call_user_func(array($this, $call), $location . $file, $name . $file); } } From 4fd0187ea6dfac690674cd52bffbe7ef59094339 Mon Sep 17 00:00:00 2001 From: origami11 Date: Thu, 9 Feb 2017 18:02:14 +0300 Subject: [PATCH 05/13] =?UTF-8?q?=D0=A3=D0=B1=D1=80=D0=B0=D0=BB=20=D0=BF?= =?UTF-8?q?=D0=BE=D0=B2=D1=82=D0=BE=D1=80=D1=8F=D1=8E=D1=89=D0=B8=D0=B5?= =?UTF-8?q?=D1=81=D1=8F=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/tabletree.php | 36 +----------------------------------- 1 file changed, 1 insertion(+), 35 deletions(-) diff --git a/src/tabletree.php b/src/tabletree.php index 4f63c71..5433815 100644 --- a/src/tabletree.php +++ b/src/tabletree.php @@ -4,41 +4,7 @@ * Преобразование дерева из модели Plain в массив массивов (Adjacency List) */ -require_once 'core/functions.php'; - -define (SORT_DESC, 0); // descending -define (SORT_ASC, 1); // ascending - -/** - * Выбирает все сроки из таблицы с уникальными значениями ключа - * @param $name Имя ключа - * @param $table Двухмерный массив - * @example - * key_unique_values ('name', array (array ('name' => 1), array ('name' => 2), array ('name' => 1))) - => array (1, 2) - * @end example - */ -function key_unique_values ($name, $table) { - // Ищем уникальные значения для заданного ключа - $keys = array (); - foreach ($table as $row) { - if (!in_array ($row[$name], $keys)) - $keys[] = $row[$name]; - } - return $keys; -} - -/** - * Сортировка двумерного массива по заданному ключу - * @param $array Массив - * @param $key Имя ключа по значению которого будет идти сравнение - * @return Отсортированный массив - */ -function sortOn($array, $key, $fn = '__cmp') { - usort ($array, rcurry($fn, $key)); - //usort ($array, create_function ('$x,$y', 'return __cmp ($x, $y, "'.$key.'");')); - return $array; -} +require_once 'src/functions.php'; /** From c8958cbee0a6b49b3f599dcc29179753e7896cfe Mon Sep 17 00:00:00 2001 From: origami11 Date: Thu, 16 Feb 2017 10:14:36 +0300 Subject: [PATCH 06/13] =?UTF-8?q?=D0=A0=D0=B5=D0=B3=D0=B8=D1=81=D1=82?= =?UTF-8?q?=D1=80=20=D1=84=D0=B0=D0=B9=D0=BB=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/{adapter.php => Adapter.php} | 0 src/{arr.php => Arr.php} | 0 src/{collection.php => Collection.php} | 0 .../HttpConnection.php} | 0 .../HttpConnectionResponse.php} | 0 .../idna_convert.php | 0 .../action.php => Controller/Action.php} | 0 .../Component.php} | 0 .../front.php => Controller/Front.php} | 0 .../Installer.php} | 0 .../model.php => Controller/Model.php} | 0 .../state.php => Controller/State.php} | 0 src/{database.php => Database.php} | 0 src/{error.php => Error.php} | 0 src/{file.php => File.php} | 0 .../ActionAccess.php} | 0 .../ActionLogger.php} | 0 src/{filter/filter.php => Filter/Filter.php} | 0 src/{filter/login.php => Filter/Login.php} | 0 .../useraccess.php => Filter/UserAccess.php} | 0 src/{form/form.php => Form/Form.php} | 0 .../viewstate.php => Form/ViewState.php} | 0 src/{formats/dot.php => Formats/Dot.php} | 0 src/{formats/helix.php => Formats/Helix.php} | 0 .../point.php => Geometry/Point.php} | 0 .../rectangle.php => Geometry/Rectangle.php} | 0 src/{httprequest.php => HttpRequest.php} | 0 .../manager.php => Layout/Manager.php} | 0 src/{layout/none.php => Layout/None.php} | 0 src/{mail.php => Mail.php} | 0 .../factory.php => Mapper/Factory.php} | 0 src/{mapper/mapper.php => Mapper/Mapper.php} | 0 .../pathmapper.php => Mapper/PathMapper.php} | 0 .../SimpleBBCode.php} | 0 src/{numbers.php => Numbers.php} | 0 src/{path.php => Path.php} | 0 src/{primitive.php => Primitive.php} | 0 src/{query => Query}/meta.php | 0 src/{query => Query}/query.php | 0 src/{query => Query}/table.php | 0 src/{registry.php => Registry.php} | 0 src/{search => Search}/htmlhelper.php | 0 src/{search => Search}/index.php | 0 src/{search => Search}/lexer.php | 0 src/{search => Search}/search.php | 0 src/{search => Search}/searcher.php | 0 src/{search => Search}/stemmer.php | 0 src/{session.php => Session.php} | 0 src/{settings.php => Settings.php} | 0 src/{setup.php => Setup.php} | 0 src/{shortcut.php => Shortcut.php} | 0 src/{sort.php => Sort.php} | 0 src/{spell.php => Spell.php} | 0 src/{tools/drawing.php => Tools/Drawing.php} | 0 .../exceltable.php => Tools/ExcelTable.php} | 0 src/{tools/image.php => Tools/Image.php} | 0 .../password.php => Tools/Password.php} | 0 src/{tools/string.php => Tools/String.php} | 0 .../tableview.php => Tools/TableView.php} | 0 .../TemplateImage.php} | 0 .../translit.php => Tools/Translit.php} | 0 src/{tree/dbtree.php => Tree/DBtree.php} | 0 src/{tree/database.php => Tree/Database.php} | 0 src/{tree/sort.php => Tree/Sort.php} | 0 .../Rule/Abstract.php} | 2 +- .../alpha.php => Validator/Rule/Alpha.php} | 4 +-- .../rule/code.php => Validator/Rule/Code.php} | 4 +-- .../count.php => Validator/Rule/Count.php} | 4 +-- .../rule/date.php => Validator/Rule/Date.php} | 4 +-- .../email.php => Validator/Rule/Email.php} | 4 +-- .../Rule/EmailList.php} | 4 +-- .../isfile.php => Validator/Rule/IsFile.php} | 4 +-- .../match.php => Validator/Rule/Match.php} | 4 +-- .../Rule/Notnull.php} | 4 +-- .../Rule/Numeric.php} | 4 +-- .../rule/time.php => Validator/Rule/Time.php} | 4 +-- .../unique.php => Validator/Rule/Unique.php} | 4 +-- .../validator.php => Validator/Validator.php} | 26 +++++++++---------- .../composite.php => View/Composite.php} | 0 src/{view/top.php => View/Top.php} | 0 src/{view/view.php => View/View.php} | 0 src/{zipfile.php => ZipFile.php} | 0 src/validator/rule/all.php | 2 -- 83 files changed, 25 insertions(+), 53 deletions(-) rename src/{adapter.php => Adapter.php} (100%) rename src/{arr.php => Arr.php} (100%) rename src/{collection.php => Collection.php} (100%) rename src/{connection/httpconnection.php => Connection/HttpConnection.php} (100%) rename src/{connection/httpconnectionresponse.php => Connection/HttpConnectionResponse.php} (100%) rename src/{connection => Connection}/idna_convert.php (100%) rename src/{controller/action.php => Controller/Action.php} (100%) rename src/{controller/component.php => Controller/Component.php} (100%) rename src/{controller/front.php => Controller/Front.php} (100%) rename src/{controller/installer.php => Controller/Installer.php} (100%) rename src/{controller/model.php => Controller/Model.php} (100%) rename src/{controller/state.php => Controller/State.php} (100%) rename src/{database.php => Database.php} (100%) rename src/{error.php => Error.php} (100%) rename src/{file.php => File.php} (100%) rename src/{filter/actionaccess.php => Filter/ActionAccess.php} (100%) rename src/{filter/actionlogger.php => Filter/ActionLogger.php} (100%) rename src/{filter/filter.php => Filter/Filter.php} (100%) rename src/{filter/login.php => Filter/Login.php} (100%) rename src/{filter/useraccess.php => Filter/UserAccess.php} (100%) rename src/{form/form.php => Form/Form.php} (100%) rename src/{form/viewstate.php => Form/ViewState.php} (100%) rename src/{formats/dot.php => Formats/Dot.php} (100%) rename src/{formats/helix.php => Formats/Helix.php} (100%) rename src/{geometry/point.php => Geometry/Point.php} (100%) rename src/{geometry/rectangle.php => Geometry/Rectangle.php} (100%) rename src/{httprequest.php => HttpRequest.php} (100%) rename src/{layout/manager.php => Layout/Manager.php} (100%) rename src/{layout/none.php => Layout/None.php} (100%) rename src/{mail.php => Mail.php} (100%) rename src/{mapper/factory.php => Mapper/Factory.php} (100%) rename src/{mapper/mapper.php => Mapper/Mapper.php} (100%) rename src/{mapper/pathmapper.php => Mapper/PathMapper.php} (100%) rename src/{markup/simplebbcode.php => Markup/SimpleBBCode.php} (100%) rename src/{numbers.php => Numbers.php} (100%) rename src/{path.php => Path.php} (100%) rename src/{primitive.php => Primitive.php} (100%) rename src/{query => Query}/meta.php (100%) rename src/{query => Query}/query.php (100%) rename src/{query => Query}/table.php (100%) rename src/{registry.php => Registry.php} (100%) rename src/{search => Search}/htmlhelper.php (100%) rename src/{search => Search}/index.php (100%) rename src/{search => Search}/lexer.php (100%) rename src/{search => Search}/search.php (100%) rename src/{search => Search}/searcher.php (100%) rename src/{search => Search}/stemmer.php (100%) rename src/{session.php => Session.php} (100%) rename src/{settings.php => Settings.php} (100%) rename src/{setup.php => Setup.php} (100%) rename src/{shortcut.php => Shortcut.php} (100%) rename src/{sort.php => Sort.php} (100%) rename src/{spell.php => Spell.php} (100%) rename src/{tools/drawing.php => Tools/Drawing.php} (100%) rename src/{tools/exceltable.php => Tools/ExcelTable.php} (100%) rename src/{tools/image.php => Tools/Image.php} (100%) rename src/{tools/password.php => Tools/Password.php} (100%) rename src/{tools/string.php => Tools/String.php} (100%) rename src/{tools/tableview.php => Tools/TableView.php} (100%) rename src/{tools/templateimage.php => Tools/TemplateImage.php} (100%) rename src/{tools/translit.php => Tools/Translit.php} (100%) rename src/{tree/dbtree.php => Tree/DBtree.php} (100%) rename src/{tree/database.php => Tree/Database.php} (100%) rename src/{tree/sort.php => Tree/Sort.php} (100%) rename src/{validator/rule/abstract.php => Validator/Rule/Abstract.php} (95%) rename src/{validator/rule/alpha.php => Validator/Rule/Alpha.php} (82%) rename src/{validator/rule/code.php => Validator/Rule/Code.php} (96%) rename src/{validator/rule/count.php => Validator/Rule/Count.php} (91%) rename src/{validator/rule/date.php => Validator/Rule/Date.php} (87%) rename src/{validator/rule/email.php => Validator/Rule/Email.php} (92%) rename src/{validator/rule/emaillist.php => Validator/Rule/EmailList.php} (92%) rename src/{validator/rule/isfile.php => Validator/Rule/IsFile.php} (94%) rename src/{validator/rule/match.php => Validator/Rule/Match.php} (88%) rename src/{validator/rule/notnull.php => Validator/Rule/Notnull.php} (88%) rename src/{validator/rule/numeric.php => Validator/Rule/Numeric.php} (81%) rename src/{validator/rule/time.php => Validator/Rule/Time.php} (90%) rename src/{validator/rule/unique.php => Validator/Rule/Unique.php} (81%) rename src/{validator/validator.php => Validator/Validator.php} (85%) rename src/{view/composite.php => View/Composite.php} (100%) rename src/{view/top.php => View/Top.php} (100%) rename src/{view/view.php => View/View.php} (100%) rename src/{zipfile.php => ZipFile.php} (100%) delete mode 100644 src/validator/rule/all.php diff --git a/src/adapter.php b/src/Adapter.php similarity index 100% rename from src/adapter.php rename to src/Adapter.php diff --git a/src/arr.php b/src/Arr.php similarity index 100% rename from src/arr.php rename to src/Arr.php diff --git a/src/collection.php b/src/Collection.php similarity index 100% rename from src/collection.php rename to src/Collection.php diff --git a/src/connection/httpconnection.php b/src/Connection/HttpConnection.php similarity index 100% rename from src/connection/httpconnection.php rename to src/Connection/HttpConnection.php diff --git a/src/connection/httpconnectionresponse.php b/src/Connection/HttpConnectionResponse.php similarity index 100% rename from src/connection/httpconnectionresponse.php rename to src/Connection/HttpConnectionResponse.php diff --git a/src/connection/idna_convert.php b/src/Connection/idna_convert.php similarity index 100% rename from src/connection/idna_convert.php rename to src/Connection/idna_convert.php diff --git a/src/controller/action.php b/src/Controller/Action.php similarity index 100% rename from src/controller/action.php rename to src/Controller/Action.php diff --git a/src/controller/component.php b/src/Controller/Component.php similarity index 100% rename from src/controller/component.php rename to src/Controller/Component.php diff --git a/src/controller/front.php b/src/Controller/Front.php similarity index 100% rename from src/controller/front.php rename to src/Controller/Front.php diff --git a/src/controller/installer.php b/src/Controller/Installer.php similarity index 100% rename from src/controller/installer.php rename to src/Controller/Installer.php diff --git a/src/controller/model.php b/src/Controller/Model.php similarity index 100% rename from src/controller/model.php rename to src/Controller/Model.php diff --git a/src/controller/state.php b/src/Controller/State.php similarity index 100% rename from src/controller/state.php rename to src/Controller/State.php diff --git a/src/database.php b/src/Database.php similarity index 100% rename from src/database.php rename to src/Database.php diff --git a/src/error.php b/src/Error.php similarity index 100% rename from src/error.php rename to src/Error.php diff --git a/src/file.php b/src/File.php similarity index 100% rename from src/file.php rename to src/File.php diff --git a/src/filter/actionaccess.php b/src/Filter/ActionAccess.php similarity index 100% rename from src/filter/actionaccess.php rename to src/Filter/ActionAccess.php diff --git a/src/filter/actionlogger.php b/src/Filter/ActionLogger.php similarity index 100% rename from src/filter/actionlogger.php rename to src/Filter/ActionLogger.php diff --git a/src/filter/filter.php b/src/Filter/Filter.php similarity index 100% rename from src/filter/filter.php rename to src/Filter/Filter.php diff --git a/src/filter/login.php b/src/Filter/Login.php similarity index 100% rename from src/filter/login.php rename to src/Filter/Login.php diff --git a/src/filter/useraccess.php b/src/Filter/UserAccess.php similarity index 100% rename from src/filter/useraccess.php rename to src/Filter/UserAccess.php diff --git a/src/form/form.php b/src/Form/Form.php similarity index 100% rename from src/form/form.php rename to src/Form/Form.php diff --git a/src/form/viewstate.php b/src/Form/ViewState.php similarity index 100% rename from src/form/viewstate.php rename to src/Form/ViewState.php diff --git a/src/formats/dot.php b/src/Formats/Dot.php similarity index 100% rename from src/formats/dot.php rename to src/Formats/Dot.php diff --git a/src/formats/helix.php b/src/Formats/Helix.php similarity index 100% rename from src/formats/helix.php rename to src/Formats/Helix.php diff --git a/src/geometry/point.php b/src/Geometry/Point.php similarity index 100% rename from src/geometry/point.php rename to src/Geometry/Point.php diff --git a/src/geometry/rectangle.php b/src/Geometry/Rectangle.php similarity index 100% rename from src/geometry/rectangle.php rename to src/Geometry/Rectangle.php diff --git a/src/httprequest.php b/src/HttpRequest.php similarity index 100% rename from src/httprequest.php rename to src/HttpRequest.php diff --git a/src/layout/manager.php b/src/Layout/Manager.php similarity index 100% rename from src/layout/manager.php rename to src/Layout/Manager.php diff --git a/src/layout/none.php b/src/Layout/None.php similarity index 100% rename from src/layout/none.php rename to src/Layout/None.php diff --git a/src/mail.php b/src/Mail.php similarity index 100% rename from src/mail.php rename to src/Mail.php diff --git a/src/mapper/factory.php b/src/Mapper/Factory.php similarity index 100% rename from src/mapper/factory.php rename to src/Mapper/Factory.php diff --git a/src/mapper/mapper.php b/src/Mapper/Mapper.php similarity index 100% rename from src/mapper/mapper.php rename to src/Mapper/Mapper.php diff --git a/src/mapper/pathmapper.php b/src/Mapper/PathMapper.php similarity index 100% rename from src/mapper/pathmapper.php rename to src/Mapper/PathMapper.php diff --git a/src/markup/simplebbcode.php b/src/Markup/SimpleBBCode.php similarity index 100% rename from src/markup/simplebbcode.php rename to src/Markup/SimpleBBCode.php diff --git a/src/numbers.php b/src/Numbers.php similarity index 100% rename from src/numbers.php rename to src/Numbers.php diff --git a/src/path.php b/src/Path.php similarity index 100% rename from src/path.php rename to src/Path.php diff --git a/src/primitive.php b/src/Primitive.php similarity index 100% rename from src/primitive.php rename to src/Primitive.php diff --git a/src/query/meta.php b/src/Query/meta.php similarity index 100% rename from src/query/meta.php rename to src/Query/meta.php diff --git a/src/query/query.php b/src/Query/query.php similarity index 100% rename from src/query/query.php rename to src/Query/query.php diff --git a/src/query/table.php b/src/Query/table.php similarity index 100% rename from src/query/table.php rename to src/Query/table.php diff --git a/src/registry.php b/src/Registry.php similarity index 100% rename from src/registry.php rename to src/Registry.php diff --git a/src/search/htmlhelper.php b/src/Search/htmlhelper.php similarity index 100% rename from src/search/htmlhelper.php rename to src/Search/htmlhelper.php diff --git a/src/search/index.php b/src/Search/index.php similarity index 100% rename from src/search/index.php rename to src/Search/index.php diff --git a/src/search/lexer.php b/src/Search/lexer.php similarity index 100% rename from src/search/lexer.php rename to src/Search/lexer.php diff --git a/src/search/search.php b/src/Search/search.php similarity index 100% rename from src/search/search.php rename to src/Search/search.php diff --git a/src/search/searcher.php b/src/Search/searcher.php similarity index 100% rename from src/search/searcher.php rename to src/Search/searcher.php diff --git a/src/search/stemmer.php b/src/Search/stemmer.php similarity index 100% rename from src/search/stemmer.php rename to src/Search/stemmer.php diff --git a/src/session.php b/src/Session.php similarity index 100% rename from src/session.php rename to src/Session.php diff --git a/src/settings.php b/src/Settings.php similarity index 100% rename from src/settings.php rename to src/Settings.php diff --git a/src/setup.php b/src/Setup.php similarity index 100% rename from src/setup.php rename to src/Setup.php diff --git a/src/shortcut.php b/src/Shortcut.php similarity index 100% rename from src/shortcut.php rename to src/Shortcut.php diff --git a/src/sort.php b/src/Sort.php similarity index 100% rename from src/sort.php rename to src/Sort.php diff --git a/src/spell.php b/src/Spell.php similarity index 100% rename from src/spell.php rename to src/Spell.php diff --git a/src/tools/drawing.php b/src/Tools/Drawing.php similarity index 100% rename from src/tools/drawing.php rename to src/Tools/Drawing.php diff --git a/src/tools/exceltable.php b/src/Tools/ExcelTable.php similarity index 100% rename from src/tools/exceltable.php rename to src/Tools/ExcelTable.php diff --git a/src/tools/image.php b/src/Tools/Image.php similarity index 100% rename from src/tools/image.php rename to src/Tools/Image.php diff --git a/src/tools/password.php b/src/Tools/Password.php similarity index 100% rename from src/tools/password.php rename to src/Tools/Password.php diff --git a/src/tools/string.php b/src/Tools/String.php similarity index 100% rename from src/tools/string.php rename to src/Tools/String.php diff --git a/src/tools/tableview.php b/src/Tools/TableView.php similarity index 100% rename from src/tools/tableview.php rename to src/Tools/TableView.php diff --git a/src/tools/templateimage.php b/src/Tools/TemplateImage.php similarity index 100% rename from src/tools/templateimage.php rename to src/Tools/TemplateImage.php diff --git a/src/tools/translit.php b/src/Tools/Translit.php similarity index 100% rename from src/tools/translit.php rename to src/Tools/Translit.php diff --git a/src/tree/dbtree.php b/src/Tree/DBtree.php similarity index 100% rename from src/tree/dbtree.php rename to src/Tree/DBtree.php diff --git a/src/tree/database.php b/src/Tree/Database.php similarity index 100% rename from src/tree/database.php rename to src/Tree/Database.php diff --git a/src/tree/sort.php b/src/Tree/Sort.php similarity index 100% rename from src/tree/sort.php rename to src/Tree/Sort.php diff --git a/src/validator/rule/abstract.php b/src/Validator/Rule/Abstract.php similarity index 95% rename from src/validator/rule/abstract.php rename to src/Validator/Rule/Abstract.php index 06189ec..cc5548f 100644 --- a/src/validator/rule/abstract.php +++ b/src/Validator/Rule/Abstract.php @@ -1,6 +1,6 @@ 'Rule_Date', - 'email' => 'Rule_Email', - 'emaillist'=> 'Rule_EmailList', - 'match' => 'Rule_Match', - 'time' => 'Rule_Time', - 'alpha' => 'Rule_Alpha', - 'require' => 'Rule_Notnull', - 'numeric' => 'Rule_Numeric', - 'unique' => 'Rule_Unique', - 'count' => 'Rule_Count', - 'isfile' => 'Rule_IsFile', - 'code' => 'Rule_Code' + 'date' => 'Validator_Rule_Date', + 'email' => 'Validator_Rule_Email', + 'emaillist'=> 'Validator_Rule_EmailList', + 'match' => 'Validator_Rule_Match', + 'time' => 'Validator_Rule_Time', + 'alpha' => 'Validator_Rule_Alpha', + 'require' => 'Validator_Rule_Notnull', + 'numeric' => 'Validator_Rule_Numeric', + 'unique' => 'Validator_Rule_Unique', + 'count' => 'Validator_Rule_Count', + 'isfile' => 'Validator_Rule_IsFile', + 'code' => 'Validator_Rule_Code' ); // Разбор правила проверки diff --git a/src/view/composite.php b/src/View/Composite.php similarity index 100% rename from src/view/composite.php rename to src/View/Composite.php diff --git a/src/view/top.php b/src/View/Top.php similarity index 100% rename from src/view/top.php rename to src/View/Top.php diff --git a/src/view/view.php b/src/View/View.php similarity index 100% rename from src/view/view.php rename to src/View/View.php diff --git a/src/zipfile.php b/src/ZipFile.php similarity index 100% rename from src/zipfile.php rename to src/ZipFile.php diff --git a/src/validator/rule/all.php b/src/validator/rule/all.php deleted file mode 100644 index 47006d7..0000000 --- a/src/validator/rule/all.php +++ /dev/null @@ -1,2 +0,0 @@ - Date: Thu, 16 Feb 2017 11:48:41 +0300 Subject: [PATCH 07/13] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=BD=D0=B0=D0=B7=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F?= =?UTF-8?q?=20=D0=BA=D0=BB=D0=B0=D1=81=D1=81=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Filter/ActionAccess.php | 2 +- src/Filter/ActionLogger.php | 2 +- src/Form/Form.php | 2 +- src/Form/ViewState.php | 2 +- src/Formats/Dot.php | 4 +- src/Geometry/Point.php | 2 +- src/Geometry/Rectangle.php | 4 +- src/Mapper/Mapper.php | 2 - src/Mapper/PathMapper.php | 4 -- src/Query/query.php | 3 -- src/Search/index.php | 4 -- src/Search/search.php | 3 +- src/Search/searcher.php | 4 -- src/Tools/Drawing.php | 2 +- src/Tools/Image.php | 2 +- src/Tools/String.php | 84 ++++++++++++++++++++++--------------- src/Tools/TemplateImage.php | 4 +- src/Tools/Translit.php | 14 ------- src/Tree/DBtree.php | 2 +- src/Tree/Database.php | 2 +- src/Tree/Sort.php | 2 +- 21 files changed, 64 insertions(+), 86 deletions(-) delete mode 100644 src/Tools/Translit.php diff --git a/src/Filter/ActionAccess.php b/src/Filter/ActionAccess.php index a44721b..7504a86 100644 --- a/src/Filter/ActionAccess.php +++ b/src/Filter/ActionAccess.php @@ -3,7 +3,7 @@ /** * Фильтр действий */ -class ActionAccess +class Filter_ActionAccess { public $access = array(); diff --git a/src/Filter/ActionLogger.php b/src/Filter/ActionLogger.php index c92d37c..2d6c395 100644 --- a/src/Filter/ActionLogger.php +++ b/src/Filter/ActionLogger.php @@ -1,6 +1,6 @@ \ No newline at end of file diff --git a/src/Geometry/Point.php b/src/Geometry/Point.php index 61254e6..0e11934 100644 --- a/src/Geometry/Point.php +++ b/src/Geometry/Point.php @@ -1,6 +1,6 @@ reference = $id; $base = $this->basePath (); @@ -75,4 +72,3 @@ class PathMapper } } -?> \ No newline at end of file diff --git a/src/Query/query.php b/src/Query/query.php index 3e4b395..e93e7e5 100644 --- a/src/Query/query.php +++ b/src/Query/query.php @@ -1,8 +1,5 @@ 0) { // already in sub-array? - $subarr[$in_subarr][] = $tok; - if ('}' === substr($tok, -1, 1)) { // check to see if we just added last component - $res[] = $this->strToArray(implode(',', $subarr[$in_subarr])); - $in_subarr--; - } - } elseif ($tok{0} === '{') { // we're inside a new sub-array - if ('}' !== substr($tok, -1, 1)) { - $in_subarr++; - // if sub-array has more than one element - $subarr[$in_subarr] = array(); - $subarr[$in_subarr][] = $tok; - } else { - $res[] = $this->strToArray($tok); - } - } else { // not sub-array - $val = trim($tok, '"'); // remove " (surrounding strings) - // perform type castng here? - $res[] = $val; - } - } - - return $res; +class Tools_String { + // from creole + static function strToArray($str) + { + $str = substr($str, 1, -1); // remove { } + $res = array(); + + $subarr = array(); + $in_subarr = 0; + + $toks = explode(',', $str); + foreach($toks as $tok) { + if ($in_subarr > 0) { // already in sub-array? + $subarr[$in_subarr][] = $tok; + if ('}' === substr($tok, -1, 1)) { // check to see if we just added last component + $res[] = $this->strToArray(implode(',', $subarr[$in_subarr])); + $in_subarr--; + } + } elseif ($tok{0} === '{') { // we're inside a new sub-array + if ('}' !== substr($tok, -1, 1)) { + $in_subarr++; + // if sub-array has more than one element + $subarr[$in_subarr] = array(); + $subarr[$in_subarr][] = $tok; + } else { + $res[] = $this->strToArray($tok); + } + } else { // not sub-array + $val = trim($tok, '"'); // remove " (surrounding strings) + // perform type castng here? + $res[] = $val; + } + } + + return $res; + } + + + static function translit($st) { + $st = strtr($st,"абвгдеёзийклмнопрстуфхъыэ !№", "abvgdeeziyklmnoprstufh_ie__#"); + $st = strtr($st,"АБВГДЕЁЗИЙКЛМНОПРСТУФХЪЫЭ", "ABVGDEEZIYKLMNOPRSTUFH_IE"); + $st = strtr($st, array( + "ж"=>"zh", "ц"=>"ts", "ч"=>"ch", "ш"=>"sh", + "щ"=>"shch","ь"=>"", "ю"=>"yu", "я"=>"ya", + "Ж"=>"ZH", "Ц"=>"TS", "Ч"=>"CH", "Ш"=>"SH", + "Щ"=>"SHCH","Ь"=>"", "Ю"=>"YU", "Я"=>"YA", + "ї"=>"i", "Ї"=>"Yi", "є"=>"ie", "Є"=>"Ye" + )); + return $st; + } } diff --git a/src/Tools/TemplateImage.php b/src/Tools/TemplateImage.php index 302678e..31bdfcc 100644 --- a/src/Tools/TemplateImage.php +++ b/src/Tools/TemplateImage.php @@ -1,11 +1,9 @@ 'jpeg', 'gif' => 'gif', 'png' => 'png', 'bmp' => 'wbmp'); static $listfonts = array( diff --git a/src/Tools/Translit.php b/src/Tools/Translit.php deleted file mode 100644 index 1ca001c..0000000 --- a/src/Tools/Translit.php +++ /dev/null @@ -1,14 +0,0 @@ -"zh", "ц"=>"ts", "ч"=>"ch", "ш"=>"sh", - "щ"=>"shch","ь"=>"", "ю"=>"yu", "я"=>"ya", - "Ж"=>"ZH", "Ц"=>"TS", "Ч"=>"CH", "Ш"=>"SH", - "Щ"=>"SHCH","Ь"=>"", "Ю"=>"YU", "Я"=>"YA", - "ї"=>"i", "Ї"=>"Yi", "є"=>"ie", "Є"=>"Ye" - )); - return $st; -} diff --git a/src/Tree/DBtree.php b/src/Tree/DBtree.php index ad83ab3..1a5792f 100644 --- a/src/Tree/DBtree.php +++ b/src/Tree/DBtree.php @@ -86,7 +86,7 @@ function _inside($a, $x, $y) { return " " . $a . " > " . $x . " AND " . $a . " < " . $y; } -class CDBTree +class Tree_DBTree { var $db; // CDatabase class to plug to var $table; // Table with Nested Sets implemented diff --git a/src/Tree/Database.php b/src/Tree/Database.php index c9c8133..9c29f18 100644 --- a/src/Tree/Database.php +++ b/src/Tree/Database.php @@ -15,7 +15,7 @@ // Note: For best viewing of the code Tab size 4 is recommended //**************************************************************************** -class CDatabase +class Tree_Database { var $link; var $db; diff --git a/src/Tree/Sort.php b/src/Tree/Sort.php index cefd3e3..7cf4477 100644 --- a/src/Tree/Sort.php +++ b/src/Tree/Sort.php @@ -9,7 +9,7 @@ * $sort = new NestedSetSort(); * $data = $sort->sortBy($data, 'name'); */ -class NestedSetSort { +class Tree_Sort { private $data = array(); private $result = array(); private $sortBy = ''; From 90f0ebde7bcb03fc6cd7e31e70c882d22f35f110 Mon Sep 17 00:00:00 2001 From: origami11 Date: Fri, 17 Feb 2017 14:56:15 +0300 Subject: [PATCH 08/13] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=BD=D0=B0=D0=B7=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F?= =?UTF-8?q?=20=D0=BA=D0=BB=D0=B0=D1=81=D1=81=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Form/ViewState.php | 4 ++-- src/Tools/Drawing.php | 2 +- src/Tools/Image.php | 2 +- src/Tools/TemplateImage.php | 2 -- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Form/ViewState.php b/src/Form/ViewState.php index c2ecaab..777618b 100644 --- a/src/Form/ViewState.php +++ b/src/Form/ViewState.php @@ -4,7 +4,7 @@ * http://www.alternateinterior.com/2006/09/a-viewstate-for-php.html * Управление состоянием между страницами */ -class ViewState // extends Collection +class Form_ViewState // extends Collection { private $values = array(); @@ -13,7 +13,7 @@ class ViewState // extends Collection $this->values[$name] = $value; } - function get() + function get($_rest) { $args = func_get_args(); $result = $this->values; diff --git a/src/Tools/Drawing.php b/src/Tools/Drawing.php index 85cbdfa..e13a323 100644 --- a/src/Tools/Drawing.php +++ b/src/Tools/Drawing.php @@ -1,6 +1,6 @@ Date: Fri, 17 Feb 2017 15:08:12 +0300 Subject: [PATCH 09/13] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D0=BD=D0=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{HttpConnection.php => HttpRequest.php} | 0 ...onnectionResponse.php => HttpResponse.php} | 0 src/Database.php | 310 +++--------------- src/Database/IdGenerator.php | 26 ++ src/Database/JsonInstall.php | 143 ++++++++ src/Database/Manager.php | 211 ++++++++++++ src/Database/PDOStatement.php | 97 ++++++ src/Database/Statement.php | 61 ++++ src/Database/StatementIterator.php | 46 +++ src/Validator/Rule/Notnull.php | 2 +- src/{Connection => }/idna_convert.php | 0 11 files changed, 626 insertions(+), 270 deletions(-) rename src/Connection/{HttpConnection.php => HttpRequest.php} (100%) rename src/Connection/{HttpConnectionResponse.php => HttpResponse.php} (100%) create mode 100644 src/Database/IdGenerator.php create mode 100644 src/Database/JsonInstall.php create mode 100644 src/Database/Manager.php create mode 100644 src/Database/PDOStatement.php create mode 100644 src/Database/Statement.php create mode 100644 src/Database/StatementIterator.php rename src/{Connection => }/idna_convert.php (100%) diff --git a/src/Connection/HttpConnection.php b/src/Connection/HttpRequest.php similarity index 100% rename from src/Connection/HttpConnection.php rename to src/Connection/HttpRequest.php diff --git a/src/Connection/HttpConnectionResponse.php b/src/Connection/HttpResponse.php similarity index 100% rename from src/Connection/HttpConnectionResponse.php rename to src/Connection/HttpResponse.php diff --git a/src/Database.php b/src/Database.php index 15ac15e..c4cd264 100644 --- a/src/Database.php +++ b/src/Database.php @@ -1,23 +1,24 @@ +require_once "database/pdostatement.php"; /** - * @package system.db * Класс оболочка для PDO для замены Creole */ class Database extends PDO { - public function __construct($dsn, $username = false, $password = false) + + 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_STATEMENT_CLASS, array('PDODatabaseStatement', array())); + $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('Database_PDOStatement', array())); } public function getDSN() { return $this->dsn; } - public function isPostgres(){ return ($this->dsn["phptype"] == "pgsql"); } @@ -26,30 +27,43 @@ class Database extends PDO */ static function getConnection(array $dsn) { + if ($dsn['phptype'] == 'pgsql' || $dsn['phptype'] == 'mysql') { $port = (isset($dsn['port'])) ? "port={$dsn['port']};" : ""; - $connection = new Database("{$dsn['phptype']}:host={$dsn['hostspec']}; $port dbname={$dsn['database']}", $dsn['username'], $dsn['password']); - $connection->query('SET client_encoding = "UTF-8"'); + /*.Database.*/$connection = new static("{$dsn['phptype']}:host={$dsn['hostspec']}; $port dbname={$dsn['database']}", $dsn['username'], $dsn['password']); + if ($dsn['phptype'] == 'pgsql') { + $connection->query('SET client_encoding="UTF-8"'); + } } if ($dsn['phptype'] == 'sqlite') { - $connection = new Database("{$dsn['phptype']}:{$dsn['database']}"); + /*.Database.*/$connection = new static("{$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"); + + if(!function_exists('sqliteLower')){ + function sqliteLower($str) { + return mb_strtolower($str, 'UTF-8'); + } + $connection->sqliteCreateFunction('LOWER', 'sqliteLower', 1); + } } $connection->dsn = $dsn; return $connection; } - public function executeQuery($query) + public function executeQuery($query, $values=null) { - $stmt = $this->prepare($query); - $stmt->setFetchMode(PDO::FETCH_ASSOC); - $stmt->execute(); - $stmt->cache = $stmt->fetchAll(); - return $stmt;//$sth->fetchAll(); + /*.Database_PDOStatement.*/$stmt = $this->prepare($query); + + $stmt->execute($values); + $stmt->cache = $stmt->fetchAll(PDO::FETCH_ASSOC); + return $stmt; } public function prepareStatement($query) { - return new DatabaseStatement($query, $this); + return new Database_Statement($query, $this); } // Для совместимости со старым представлением баз данных CIS @@ -58,7 +72,7 @@ class Database extends PDO */ public function fetchAllArray($query,$values=null) { - $sth = $this->prepare($query); + /*.Database_PDOStatement.*/$sth = $this->prepare($query); $prep = $this->prepareValues($values); $sth->execute($prep); return $sth->fetchAll(PDO::FETCH_ASSOC); @@ -69,13 +83,13 @@ class Database extends PDO */ public function fetchOneArray($query,$values=null) { - $sth = $this->prepare($query); + /*.Database_PDOStatement.*/$sth = $this->prepare($query); $prep = $this->prepareValues($values); $sth->execute($prep); return $sth->fetch(PDO::FETCH_ASSOC); } - private function assignQuote($x, $y) + private static function assignQuote($x, $y) { return $x . "=" . $this->quote($y); } @@ -136,12 +150,17 @@ class Database extends PDO */ function updateQuery($table, array $values, $cond) { - return $this->query("UPDATE $table SET " . implode(",", - array_map(array($this, 'assignQuote'), array_keys($values), array_values($values))) . " WHERE $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); + return new Database_IdGenerator($this); } /** @@ -149,8 +168,7 @@ class Database extends PDO * @param string $seq Имя последовательности для ключа таблицы * @return int Идентефикатор следующей записи */ - function getNextId($seq) - { + function getNextId($seq) { $result = $this->fetchOneArray("SELECT nextval('$seq')"); return $result['nextval']; } @@ -160,249 +178,3 @@ class Database extends PDO return null; } } - -class IdGenerator { - private $db; - - function __construct($db) { - $this->db = $db; - } - - function isBeforeInsert() { - return false; - } - - function isAfterInsert() { - return true; - } - - function getId($seq) { - $result = $this->db->fetchOneArray("SELECT nextval('$seq')"); - return $result['nextval']; -// $result = $this->db->fetchOneArray("SELECT last_insert_rowid() AS nextval"); -// return $result['nextval']; - } -} - -class PDODatabaseStatementIterator implements Iterator -{ - - private $result; - private $pos = 0; - private $fetchmode; - private $row_count; - private $rs; - - - /** - * Construct the iterator. - * @param PgSQLResultSet $rs - */ - public function __construct($rs) - { - $this->result = $rs; - $this->row_count = $rs->getRecordCount(); - } - - function rewind() - { - $this->pos = 0; - } - - function valid() - { - return ($this->pos < $this->row_count); - } - - function key() - { - return $this->pos; - } - - function current() - { - if (!isset($this->result->cache[$this->pos])) { - $this->result->cache[$this->pos] = $this->result->fetch(PDO::FETCH_ASSOC); - } - return $this->result->cache[$this->pos]; - } - - function next() - { - $this->pos++; - } - - function seek ( $index ) - { - $this->pos = $index; - } - - function count ( ) { - return $this->row_count; - } -} - -class PDODatabaseStatement extends PDOStatement implements IteratorAggregate -{ - protected $cursorPos = 0; - public $cache = array(); - public $fields; - - function getIterator() - { - return new PDODatabaseStatementIterator($this); - } - - protected function __construct() { - } - - function rewind() - { - $this->cursorPos = 0; - } - - public function seek($rownum) - { - if ($rownum < 0) { - return false; - } - - // PostgreSQL rows start w/ 0, but this works, because we are - // looking to move the position _before_ the next desired position - $this->cursorPos = $rownum; - return true; - } - - function valid() - { - return ( true ); - } - - - public function first() - { - if($this->cursorPos !== 0) { $this->seek(0); } - return $this->next(); - } - - function next() - { - if ($this->getRecordCount() > $this->cursorPos) { - if (!isset($this->cache[$this->cursorPos])) { - $this->cache[$this->cursorPos] = $this->fetch(PDO::FETCH_ASSOC); - } - $this->fields = $this->cache[$this->cursorPos]; - - $this->cursorPos++; - return true; - } else { - $this->fields = null; - return false; - } - } - - function key() { - return $this->cursorPos; - } - - function current() - { - return $this->result->fetch(PDO::FETCH_ASSOC); - } - - function getRow() - { - return $this->fields; - } - - function getInt($name) - { - return intval($this->fields[$name]); - } - - function getBlob($name) - { - return $this->fields[$name]; - } - - function getString($name) - { - return $this->fields[$name]; - } - - function getBoolean($name) - { - return (bool)$this->fields[$name]; - } - - function get($name) - { - return $this->fields[$name]; - } - - function getRecordCount() - { - return count($this->cache); - } -} - - -/** - * Класс оболочка для PDOStatement для замены Creole - */ -class DatabaseStatement -{ - protected $limit = null; - protected $offset = null; - protected $statement = null; - protected $binds = array(); - protected $conn; - protected $query; - - function __construct($query, $conn) { - $this->query = $query; - $this->conn = $conn; - } - - function setInt($n, $value) - { - $this->binds [] = array($n, $value, PDO::PARAM_INT); - } - - function setString($n, $value) - { - $this->binds [] = array($n, $value, PDO::PARAM_STR); - } - - function setBlob($n, $value) - { - $this->binds [] = array($n, $value, PDO::PARAM_LOB); - } - - function setLimit($limit) - { - $this->limit = $limit; - } - - function setOffset($offset) - { - $this->offset = $offset; - } - - function executeQuery() - { - if ($this->limit) { - $this->query .= " LIMIT {$this->limit} OFFSET {$this->offset}"; - } - $stmt = $this->conn->prepare($this->query); - foreach ($this->binds as $bind) { - list($n, $value, $type) = $bind; - $stmt->bindValue($n, $value, $type); - } - $stmt->setFetchMode(PDO::FETCH_ASSOC); - $stmt->execute(); - $stmt->cache = $stmt->fetchAll(); - - return $stmt; - } -} diff --git a/src/Database/IdGenerator.php b/src/Database/IdGenerator.php new file mode 100644 index 0000000..f7ebfee --- /dev/null +++ b/src/Database/IdGenerator.php @@ -0,0 +1,26 @@ +db = $db; + } + + function isBeforeInsert() { + return $this->db->isPostgres(); + } + + function isAfterInsert() { + return !$this->db->isPostgres(); + } + + function getId($seq) { + if ($this->db->isPostgres()) { + $result = $this->db->fetchOneArray("SELECT nextval('$seq') AS nextval"); + } else { + $result = $this->db->fetchOneArray("SELECT last_insert_rowid() AS nextval"); + } + return intval($result['nextval']); + } +} diff --git a/src/Database/JsonInstall.php b/src/Database/JsonInstall.php new file mode 100644 index 0000000..ee62cf3 --- /dev/null +++ b/src/Database/JsonInstall.php @@ -0,0 +1,143 @@ +db_manager = $db_manager; + } + + function install($dbinit_path, $dbfill_path = null) { + $dbinit_file = file_get_contents($dbinit_path); + if (is_string($dbinit_file)) { + $initActions = json_decode($dbinit_file, true); + if (!$initActions) { + echo "Invalid dbinit.json ".$dbinit_file; + return 0; + } + } else { + echo "No dbinit.json"; + return 0; + } + + $this->initDataBase($initActions, $dbinit_path); + if ($dbfill_path) { + $this->fillDataBase($dbfill_path); + } + $this->makeConstraints($initActions); + } + + function missingTables($tables) { + $actual_tables = $this->db_manager->GetAllTableNames(); + $missingTables = []; + foreach ($tables as $table) { + if (!in_array($table, $actual_tables)) + $missingTables[] = $table; + } + return $missingTables; + } + + //Создать таблицы + function initDataBase(/*.array.*/$initActions, $dbinit_path) { + $pg = $this->db_manager->db->isPostgres(); + if (!$pg) { + $refs = []; + //В sqlite нет alter reference. Референсы надо создавать при создании таблицы. + foreach ($initActions as $action) { + if ($action["type"] == "alterReference") { + if (!isset($refs[$action["table"]])) + $refs[$action["table"]] = []; + $refs[$action["table"]][]=$action;//добавить к списку референсов для таблицы + } + } + } + + foreach ($initActions as $action) { + if (!$pg) { + if ($action["type"] == "createTable") { + $table_name = $action["table_name"]; + if (isset($refs[$table_name])) { + foreach ($refs[$table_name] as $value) { + $action['fields'][$value['column']]['references'] = + $value['refTable']."(".$value['refColumn'].")"; + } + } + + } + } + if ($action["type"] != "alterReference") { + $this->db_manager->ExecuteAction($action, $dbinit_path); + } + } + + //Запомнить все колонки serial + $this->serialColumns = []; + if ($pg) { + foreach ($initActions as $action) { + if ($action["type"] == "createTable") { + foreach ($action["fields"] as $name => $field) { + if ($field["type"]=="serial") { + $this->serialColumns[] = [ + "table"=>$action["table_name"], + "column"=>$name + ]; + } + } + } + } + } + } + + //Заполнить данными + function fillDataBase($dbfill_file_path) { + $dbfill_file = file_get_contents($dbfill_file_path); + if (is_string($dbfill_file)) { + $actions = json_decode($dbfill_file,true); + if ($actions) { + + //Проверка что упоминаемые в списке действий таблицы уже есть в базе + $affected_tables = []; + foreach ($actions as $action) { + if ($action["table_name"]) { + $affected_tables[$action["table_name"]] = 1; + } + } + + $missing = $this->missingTables(array_keys($affected_tables)); + if (!empty($missing)) { + echo "dbfill error. Missing tables: ".implode(" ", $missing); + return; + } + + //Выполнение действий + foreach ($actions as $action) { + $this->db_manager->ExecuteAction($action, $dbfill_file_path); + } + } else { + echo "Invalid dbfill.json"; + } + } else { + echo "No dbfill.json"; + } + } + + //Обновить ключи serial и создать ограничения + function makeConstraints($initActions) { + $pg = $this->db_manager->db->isPostgres(); + if ($pg) { + foreach ($this->serialColumns as $serialColumn) { + $this->db_manager->UpdateSerial($serialColumn["table"], $serialColumn["column"]); + } + + + foreach ($initActions as $action) { + if ($action["type"] == "alterReference") { + $this->db_manager->ExecuteAction($action); + } + } + } + } + +} \ No newline at end of file diff --git a/src/Database/Manager.php b/src/Database/Manager.php new file mode 100644 index 0000000..11b8dbc --- /dev/null +++ b/src/Database/Manager.php @@ -0,0 +1,211 @@ +db = $db; + } + + public function ExecuteAction(/*.array.*/$action, $db_file = "") { + switch($action["type"]) { + case "dropTable": + $this->DropTableQuery($action["table_name"], true); + break; + case "createTable": + $constraints = isset($action["constraints"]) ? $action["constraints"] : NULL; + $this->CreateTableQuery($action["table_name"], $action["fields"], $constraints); + break; + case "addColumn": + $this->AddColumn($action["table_name"], $action["column_name"], $action["field"]); + break; + case "insert": + $this->db->insertQuery($action["table_name"], $action["values"]); + break; + case "alterReference": + $this->AlterReference($action["table"], $action["column"], $action["refTable"], $action["refColumn"]); + break; + case "renameColumn": + $this->RenameColumn($action["table"], $action["old_name"], $action["new_name"]); + break; + case "executeFile": + if ($this->db->isPostgres() && isset($action["pgsql"])) { + $file = $action["pgsql"]; + } else { + $file = $action["source"]; + } + + $stmtList = Tools_SQLStatementExtractor::extractFile(Path::join(dirname($db_file), $file)); + foreach($stmtList as $stmt) { + $this->db->executeQuery($stmt); + } + + break; + default: + throw new Exception("unknown action ". $action["type"] . PHP_EOL); + } + } + + public function DropTableQuery($table, $cascade=false) { + $statement = "DROP TABLE IF EXISTS ".$table; + if ($this->db->isPostgres()&&$cascade) { + $statement = $statement." CASCADE"; + } + $this->db->query($statement); + } + + public function AlterReference($table,$column,$refTable,$refColumn) { + $this->db->query("ALTER TABLE ".$table." ADD CONSTRAINT ".$table."_".$column."fk"." FOREIGN KEY (".$column.") REFERENCES ".$refTable." (".$refColumn.")"); + } + + //Извлечение информации о полях таблицы + public function TableInfo($table) { + $pg = $this->db->isPostgres(); + if ($pg) { + throw new Exception("Not implemented for postgres"); + } else { + $results = $this->db->fetchAllArray("PRAGMA table_info(".$table.");"); + if (empty($results)) { + return null; + } + $fields = []; + foreach ($results as $result) { + $fields[$result["name"]] = [ + "type"=> $result["type"], + "not_null"=> boolval($result["notnull"]), + "constraint"=> ((boolean) $result["pk"]) ? "PRIMARY KEY" : null + ]; + } + return $fields; + } + } + + public function RenameColumn($table, $old_name, $new_name) { + $pg = $this->db->isPostgres(); + if ($pg) { + $this->db->query("ALTER TABLE ".$table." RENAME COLUMN ".$old_name." TO ".$new_name); + } else { + $tmp_table = "tmp_" . $table; + $this->DropTableQuery($tmp_table); + $table_info = $this->TableInfo($table); + + if (isset($table_info[$new_name])) { + return; + } + + /*.array.*/$data = $this->DumpTable($table); + + $this->db->query("ALTER TABLE ".$table." RENAME TO ".$tmp_table.";"); + $table_info[$new_name] = $table_info[$old_name]; + unset($table_info[$old_name]); + $this->CreateTableQuery($table,$table_info,null); + + foreach ($data as $row) { + $values = $row['values']; + $values[$new_name] = $values[$old_name]; + unset($values[$old_name]); + $this->db->insertQuery($table, $values); + } + $this->DropTableQuery($tmp_table); + } + } + + //Обновление ключа serial после ручной вставки + public function UpdateSerial($table,$column) { + $this->db->query("SELECT setval(pg_get_serial_sequence('".$table."', '".$column."'), coalesce(max(".$column."),0) + 1, false) FROM ".$table); + } + + public function Column_Definition($name,$data,$pg){ + $constraint = isset($data['constraint'])?" ".$data['constraint']:""; + $references = ""; + if (isset($data['references'])) { + $references = " REFERENCES ".$data['references']; + } + if (isset($data["not_null"])&&$data["not_null"]) + $constraint .=" NOT NULL"; + $type = $data['type']; + if (!$pg) { + if (strtolower($type)=="serial") + $type = "integer"; + //if (strtolower($type)=="boolean") + // $type = "integer"; + } + return $name." ".$type.$references.$constraint; + } + + public function AddColumn($table_name,$column_name,$field){ + $pg = $this->db->isPostgres(); + $q = "ALTER TABLE ".$table_name." ADD COLUMN ". + $this->Column_Definition($column_name, $field, $pg); + $this->db->query($q); + } + + //CreateTableQuery('users',['id'=>['type'=>'integer','constraint'=>'PRIMARY KEY']]) + public function CreateTableQuery($table, $fields, $constraints) { + $pg = $this->db->isPostgres(); + if ($constraints) { + $constraints = ", " . $constraints; + } + + $statement = "CREATE TABLE $table (" . implode(",", + array_map(function($name,$data) use ($pg) { + return $this->Column_Definition($name,$data,$pg); + }, array_keys($fields), array_values($fields)) + ) . " " . $constraints . ")"; + $this->db->query($statement); + } + + public function DumpTable($table_name) { + $pg = $this->db->isPostgres(); + + /*.array.*/$result = array(); + /*.array.*/$data = $this->db->fetchAllArray("SELECT * FROM ".$table_name.";"); + + if (!$pg) { + $table_fields = $this->TableInfo($table_name); + foreach ($table_fields as $name => $value) { + $type = strtolower($value['type']); + if ($type == "boolean") { + foreach ($data as &$row) { + /*.array.*/$row = $row; + if (isset($row[$name])) { + $row[$name] = boolval($row[$name]); + } + } + } + } + } + foreach ($data as $r) { + $result[] = array( + "type" => "insert", + "table_name" => $table_name, + "values" => $r + ); + } + return $result; + } + + public function GetAllTableNames() { + $result = []; + if ($this->db->isPostgres()) { + $query = "SELECT table_name as name FROM information_schema.tables WHERE table_schema='public'"; + } else { + $query = "SELECT * FROM sqlite_master WHERE type='table'"; + } + $tables = $this->db->fetchAllArray($query); + foreach ($tables as $table) { + $result[] = $table['name']; + } + return $result; + } + + public function DumpInserts() { + $table_names = $this->GetAllTableNames(); + $result = array(); + foreach ($table_names as $table_name) { + $result = array_merge($result, $this->DumpTable($table_name)); + } + return $result; + } +} \ No newline at end of file diff --git a/src/Database/PDOStatement.php b/src/Database/PDOStatement.php new file mode 100644 index 0000000..971afb8 --- /dev/null +++ b/src/Database/PDOStatement.php @@ -0,0 +1,97 @@ +cursorPos = 0; + } + + public function seek($rownum) { + if ($rownum < 0) { + return false; + } + + // PostgreSQL rows start w/ 0, but this works, because we are + // looking to move the position _before_ the next desired position + $this->cursorPos = $rownum; + return true; + } + + function valid() { + return true; + } + + + public function first() { + if($this->cursorPos !== 0) { $this->seek(0); } + return $this->next(); + } + + function next() { + if ($this->getRecordCount() > $this->cursorPos) { + if (!isset($this->cache[$this->cursorPos])) { + $this->cache[$this->cursorPos] = $this->fetch(PDO::FETCH_ASSOC); + } + $this->fields = $this->cache[$this->cursorPos]; + + $this->cursorPos++; + return true; + } else { + $this->fields = null; + return false; + } + } + + function key() { + return $this->cursorPos; + } + + function current() { + return $this->cache[$this->cursorPos]; + } + + function getRow() { + return $this->fields; + } + + function getInt($name) { + return intval($this->fields[$name]); + } + + function getBlob($name) { + return $this->fields[$name]; + } + + function getString($name) { + return $this->fields[$name]; + } + + function getBoolean($name) { + return (bool)$this->fields[$name]; + } + + function get($name) { + return $this->fields[$name]; + } + + function getArray($name) { + return strToArray($this->fields[$name]); + } + + function getRecordCount() { + return count($this->cache); + } +} diff --git a/src/Database/Statement.php b/src/Database/Statement.php new file mode 100644 index 0000000..80b77da --- /dev/null +++ b/src/Database/Statement.php @@ -0,0 +1,61 @@ +query = $query; + $this->conn = $conn; + } + + function setInt($n, $value) + { + $this->binds [] = array($n, $value, PDO::PARAM_INT); + } + + function setString($n, $value) + { + $this->binds [] = array($n, $value, PDO::PARAM_STR); + } + + function setBlob($n, $value) + { + $this->binds [] = array($n, $value, PDO::PARAM_LOB); + } + + function setLimit($limit) + { + $this->limit = $limit; + } + + function setOffset($offset) + { + $this->offset = $offset; + } + + function executeQuery() + { + if ($this->limit) { + $this->query .= " LIMIT {$this->limit} OFFSET {$this->offset}"; + } + /*.Database_PDOStatement.*/$stmt = $this->conn->prepare($this->query); + foreach ($this->binds as $bind) { + list($n, $value, $type) = $bind; + $stmt->bindValue($n, $value, (int) $type); + } + + $stmt->execute(); + $stmt->cache = $stmt->fetchAll(PDO::FETCH_ASSOC); + + return $stmt; + } +} diff --git a/src/Database/StatementIterator.php b/src/Database/StatementIterator.php new file mode 100644 index 0000000..cc2cc05 --- /dev/null +++ b/src/Database/StatementIterator.php @@ -0,0 +1,46 @@ +result = $rs; + $this->row_count = $rs->getRecordCount(); + } + + function rewind() { + $this->pos = 0; + } + + function valid() { + return ($this->pos < $this->row_count); + } + + function key() { + return $this->pos; + } + + function current() { + if (!isset($this->result->cache[$this->pos])) { + $this->result->cache[$this->pos] = $this->result->fetch(PDO::FETCH_ASSOC); + } + return $this->result->cache[$this->pos]; + } + + function next() { + $this->pos++; + } + + function seek($index) { + $this->pos = $index; + } + + function count() { + return $this->row_count; + } +} diff --git a/src/Validator/Rule/Notnull.php b/src/Validator/Rule/Notnull.php index a3f27f2..2b0c3cb 100644 --- a/src/Validator/Rule/Notnull.php +++ b/src/Validator/Rule/Notnull.php @@ -1,6 +1,6 @@ Date: Fri, 17 Feb 2017 15:28:36 +0300 Subject: [PATCH 10/13] =?UTF-8?q?=D0=95=D1=89=D0=B5=20=D1=80=D0=B5=D1=84?= =?UTF-8?q?=D0=B0=D0=BA=D1=82=D0=BE=D1=80=D0=B8=D0=BD=D0=B3=20=D0=B8=D0=BC?= =?UTF-8?q?=D0=B5=D0=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Connection/HttpRequest.php | 2 +- src/Connection/HttpResponse.php | 5 ++++- src/Controller/Action.php | 10 +++++----- src/{idna_convert.php => IdnaConvert.php} | 2 +- src/Validator/Validator.php | 2 +- src/View/Top.php | 4 ++-- src/View/View.php | 2 +- 7 files changed, 15 insertions(+), 12 deletions(-) rename src/{idna_convert.php => IdnaConvert.php} (99%) diff --git a/src/Connection/HttpRequest.php b/src/Connection/HttpRequest.php index 534be58..6a98719 100644 --- a/src/Connection/HttpRequest.php +++ b/src/Connection/HttpRequest.php @@ -1,6 +1,6 @@ viewPath, 'help', $name . '.suggest'); if (file_exists($file) && include($file)) { - $view->addScriptRaw("add_suggest(".json::encode($suggest).");\n"); + $view->addScriptRaw("add_suggest(".json_encode($suggest).");\n"); } } @@ -140,7 +140,7 @@ class Controller_Action * 2. Использовать наследование чтобы добавить к старому обработчику новое поведение * @param $request Обьект запроса */ - public function execute1(HTTPRequest $request) + public function execute1(HttpRequest $request) { $action = self::ACTION_PREFIX . ucfirst($request->getAction()); if (method_exists($this, $action)) { @@ -150,7 +150,7 @@ class Controller_Action } } - public function execute(HTTPRequest $request) + public function execute(HttpRequest $request) { $result = $this->execute1($request); if ($result) { @@ -159,7 +159,7 @@ class Controller_Action return $this->render(); } - public function forward($action, HTTPRequest $args) + public function forward($action, HttpRequest $args) { // Действия до вызова основного обработчика /*foreach($this->_aspect as $aspect) { diff --git a/src/idna_convert.php b/src/IdnaConvert.php similarity index 99% rename from src/idna_convert.php rename to src/IdnaConvert.php index 6d5acbe..8f9b07c 100644 --- a/src/idna_convert.php +++ b/src/IdnaConvert.php @@ -53,7 +53,7 @@ * @changelog since 0.5.1 class updated to PHP5/6 style should be compatible to PHP 4.3+ * - added a missing replace mapping for THAI CHARACTER SARA AM */ -class idna_convert +class IdnaConvert { // NP See below diff --git a/src/Validator/Validator.php b/src/Validator/Validator.php index 4e0be40..8feebe6 100644 --- a/src/Validator/Validator.php +++ b/src/Validator/Validator.php @@ -3,7 +3,7 @@ /** * Проверка коллекции */ -class Validator +class Validator_Validator { protected $chain = array(); // Массив правил protected $errorMsg = array(); // Массив ошибок diff --git a/src/View/Top.php b/src/View/Top.php index 5e3477f..776d6d4 100644 --- a/src/View/Top.php +++ b/src/View/Top.php @@ -29,12 +29,12 @@ class View_Top // AbstractCompositeView public function jGrowl($message, $args) { - $this->addScriptRaw('$.jGrowl("' . $message . '", ' . json::encode($args) . ");\n", true); + $this->addScriptRaw('$.jGrowl("' . $message . '", ' . json_encode($args) . ");\n", true); } public function setGlobal($name, $args) { - $this->addScriptRaw("var " . $name . " = " . json::encode($args) . ";\n", false); + $this->addScriptRaw("var " . $name . " = " . json_encode($args) . ";\n", false); } /** diff --git a/src/View/View.php b/src/View/View.php index bacc54e..979cae0 100644 --- a/src/View/View.php +++ b/src/View/View.php @@ -3,7 +3,7 @@ // Класс отображения // CompositeView !! Composite pattern -class View +class View_View { protected $document; protected $values; From b26e52165710dd61c850e32700f5f0d59413f07b Mon Sep 17 00:00:00 2001 From: origami11 Date: Fri, 17 Feb 2017 16:22:44 +0300 Subject: [PATCH 11/13] =?UTF-8?q?=D0=A7=D0=B0=D1=81=D1=82=D0=B8=D1=87?= =?UTF-8?q?=D0=BD=D0=B0=D1=8F=20=D1=81=D0=B8=D0=BD=D1=85=D1=80=D0=BE=D0=BD?= =?UTF-8?q?=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F=20=D1=81=20CMS?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Connection/HttpRequest.php | 31 +- src/Connection/HttpResponse.php | 2 +- src/Controller/Request.php | 16 + src/Controller/Service.php | 64 + src/Database/IdGenerator.php | 4 +- src/Error.php | 86 - src/File.php | 80 - src/Filter/ActionAccess.php | 12 +- src/Filter/ActionLogger.php | 10 +- src/Filter/Authorization.php | 52 + src/Filter/Filter.php | 6 +- src/Filter/UserAccess.php | 6 +- src/Formats/Dot.php | 50 - src/Formats/Helix.php | 85 - src/Geometry/Point.php | 12 - src/Geometry/Rectangle.php | 49 - src/IdnaConvert.php | 2707 --------------------------- src/Layout/Empty.php | 13 + src/Layout/Manager.php | 3 +- src/Layout/None.php | 11 - src/Mail.php | 5 +- src/Mapper/Factory.php | 28 - src/Mapper/Mapper.php | 265 --- src/Mapper/PathMapper.php | 74 - src/Markup/SimpleBBCode.php | 113 -- src/Query/meta.php | 9 - src/Query/query.php | 202 -- src/Query/table.php | 14 - src/Search/htmlhelper.php | 82 - src/Search/index.php | 80 - src/Search/lexer.php | 91 - src/Search/search.php | 96 - src/Search/searcher.php | 97 - src/Search/stemmer.php | 180 -- src/{Sort.php => SortRecord.php} | 4 + src/Spell.php | 98 - src/Tools/ExcelTable.php | 66 +- src/Tools/Image.php | 1 - src/Tools/Password.php | 32 - src/Tools/SQLStatementExtractor.php | 164 ++ src/Tools/TableView.php | 94 - src/Tree/DBtree.php | 636 ------- src/Tree/Database.php | 135 -- src/Tree/Sort.php | 79 - src/UTF8.php | 12 + src/Validator/Rule/FileName.php | 14 + src/Validator/Validator.php | 5 +- src/View/Page.php | 73 + src/View/Plain.php | 48 + src/View/View.php | 205 +- src/View/list.php | 13 + src/data/areas.php | 26 - src/data/city-short.php | 14 - src/data/city.php | 14 - src/data/mime.php | 196 -- src/data/okato.php | 35 - src/data/regions.php | 91 - src/data/states.php | 32 - src/process.php | 41 + src/security.php | 33 + src/tabletree.php | 17 +- src/tales.php | 6 +- 62 files changed, 827 insertions(+), 5992 deletions(-) create mode 100644 src/Controller/Request.php create mode 100644 src/Controller/Service.php delete mode 100644 src/Error.php delete mode 100644 src/File.php create mode 100644 src/Filter/Authorization.php delete mode 100644 src/Formats/Dot.php delete mode 100644 src/Formats/Helix.php delete mode 100644 src/Geometry/Point.php delete mode 100644 src/Geometry/Rectangle.php delete mode 100644 src/IdnaConvert.php create mode 100644 src/Layout/Empty.php delete mode 100644 src/Layout/None.php delete mode 100644 src/Mapper/Factory.php delete mode 100644 src/Mapper/Mapper.php delete mode 100644 src/Mapper/PathMapper.php delete mode 100644 src/Markup/SimpleBBCode.php delete mode 100644 src/Query/meta.php delete mode 100644 src/Query/query.php delete mode 100644 src/Query/table.php delete mode 100644 src/Search/htmlhelper.php delete mode 100644 src/Search/index.php delete mode 100644 src/Search/lexer.php delete mode 100644 src/Search/search.php delete mode 100644 src/Search/searcher.php delete mode 100644 src/Search/stemmer.php rename src/{Sort.php => SortRecord.php} (96%) delete mode 100644 src/Spell.php delete mode 100644 src/Tools/Password.php create mode 100644 src/Tools/SQLStatementExtractor.php delete mode 100644 src/Tools/TableView.php delete mode 100644 src/Tree/DBtree.php delete mode 100644 src/Tree/Database.php delete mode 100644 src/Tree/Sort.php create mode 100644 src/UTF8.php create mode 100644 src/Validator/Rule/FileName.php create mode 100644 src/View/Page.php create mode 100644 src/View/Plain.php create mode 100644 src/View/list.php delete mode 100644 src/data/areas.php delete mode 100644 src/data/city-short.php delete mode 100644 src/data/city.php delete mode 100644 src/data/mime.php delete mode 100644 src/data/okato.php delete mode 100644 src/data/regions.php delete mode 100644 src/data/states.php create mode 100644 src/process.php create mode 100644 src/security.php diff --git a/src/Connection/HttpRequest.php b/src/Connection/HttpRequest.php index 6a98719..28d0515 100644 --- a/src/Connection/HttpRequest.php +++ b/src/Connection/HttpRequest.php @@ -8,18 +8,23 @@ class Connection_HttpRequest private $param = array(); // Параметры запроса public $data = null; // Содержание public $url; // Адресс - public $method = self::GET; // Метод + public $method; // Метод public $port = 80; public $host = ""; - public $proxy_host = false; - public $proxy_port = false; + public $proxy_host = null; + public $proxy_port = null; + public $http_version = 'HTTP/1.1'; + + function __construct() { + $this->method = self::GET; + } /** * Возвращает заголовок соединения */ public function getHeader() { - $result = $this->method . " " . $this->url . " HTTP/1.1\r\n"; + $result = $this->method . " " . $this->url . " " . $this->http_version . "\r\n"; $result .= "Host: ". $this->host ."\r\n"; foreach ($this->param as $key => $value) { $result .= $key . ": " . $value . "\r\n"; @@ -74,10 +79,10 @@ class Connection_HttpRequest { $host = ($this->proxy_host) ? $this->proxy_host : $this->host; $port = ($this->proxy_port) ? $this->proxy_port : $this->port; + $errno = 0; + $errstr = ''; $socket = fsockopen($host, $port, $errno, $errstr, 30); - if (! $socket) { - return null; // Exception - } else { + if (is_resource($socket)) { $header = $this->getHeader(); fwrite($socket, $header); @@ -90,5 +95,17 @@ class Connection_HttpRequest } return null; } + + static function getJSON($url, $data) { + $c = new Connection_HttpRequest(); + $c->http_version = "HTTP/1.0"; + + $query = http_build_query($data); + $c->setUrl($q = $url . '?' . $query); + $page = $c->getPage(); + + $response = new Connection_HttpResponse($page); + return json_decode((string) preg_replace('/[\x00-\x09\x0B\x0C\x0E-\x1F\x7F]/', '', $response->getData()), true); + } } diff --git a/src/Connection/HttpResponse.php b/src/Connection/HttpResponse.php index fedce5f..9e94c9f 100644 --- a/src/Connection/HttpResponse.php +++ b/src/Connection/HttpResponse.php @@ -9,8 +9,8 @@ class Connection_HttpResponse private $param = array (); private $code; public $response; - public $data; public $version; + public $data; public function __construct($response) { diff --git a/src/Controller/Request.php b/src/Controller/Request.php new file mode 100644 index 0000000..01822e1 --- /dev/null +++ b/src/Controller/Request.php @@ -0,0 +1,16 @@ +r = $request; + $this->id = $id; + } + + function get($name) { + $v = $this->r->get($name); + if ($id && is_array($v)) { + return isset($v[$id]) ? $v[$id] : $def; + } + return $v; + } +} diff --git a/src/Controller/Service.php b/src/Controller/Service.php new file mode 100644 index 0000000..87aa3bd --- /dev/null +++ b/src/Controller/Service.php @@ -0,0 +1,64 @@ +getInstance + public $template; + public $templatePath; + public $COMPONENTS_WEB; + + public function getTemplatePath($name) + { + return Path::join($this->viewPath[0], 'templates', 'modern', $name); + } + + public function getTemplateWebPath() + { + return Path::join($this->webPath[0], strtolower(get_class($this)), 'templates', 'modern'); + } + + /** + * @param $name Имя модели + */ + private function getModelPath($name) + { + return Path::join (CMS_PATH, "model", $name . ".php"); + } + + /** + * Создает модель + * @param string $name + * @return model + */ + public function getModel($name) + { + require_once 'mapper/mapper.php'; + + require_once ($this->getModelPath ($name)); + $modelName = $name . "Mapper"; + $model = new $modelName (); + $model->db = $this->db; + return $model; + } + + public function options($key, $val, $res) { + $result = array(); + while($res->next()) { + $result[] = array('value' => $res->getInt($key), 'name' => $res->getString($val)); + } + return $result; + } + + public function optionsPair($list, $selected = false) { + $result = array(); + foreach ($list as $key => $value) { + $result [] = array('value' => $key, 'name' => $value, 'selected' => $key == $selected); + } + return $result; + } +} + diff --git a/src/Database/IdGenerator.php b/src/Database/IdGenerator.php index f7ebfee..045ec86 100644 --- a/src/Database/IdGenerator.php +++ b/src/Database/IdGenerator.php @@ -8,11 +8,11 @@ class Database_IdGenerator { } function isBeforeInsert() { - return $this->db->isPostgres(); + return false; } function isAfterInsert() { - return !$this->db->isPostgres(); + return true; } function getId($seq) { diff --git a/src/Error.php b/src/Error.php deleted file mode 100644 index de256bb..0000000 --- a/src/Error.php +++ /dev/null @@ -1,86 +0,0 @@ - 'E_ERROR', - 2 => 'E_WARNING', - 4 => 'E_PARSE', - 8 => 'E_NOTICE', - 16 => 'E_CORE_ERROR', - 32 => 'E_CORE_WARNING', - 64 => 'E_COMPILE_ERROR', - 128 => 'E_COMPILE_WARNING', - 256 => 'E_USER_ERROR', - 512 => 'E_USER_WARNING', - 1024 => 'E_USER_NOTICE', - 2048 => 'E_STRICT', - 4096 => 'E_RECOVERABLE_ERROR', - 8192 => 'E_DEPRECATED', - 16384 => 'E_USER_DEPRECATED', - 30719 => 'E_ALL'); - return $names[$id]; -} - - -function send_error($description) { - $message = "request: " . "http://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'] . "\n"; - $message .= "from: " . $_SERVER['REMOTE_ADDR'] . "\n"; - if(isset($_SERVER['HTTP_REFERER'])) $message .= "referer: " . $_SERVER['HTTP_REFERER'] . "\n"; - $message .= "post:" . var_export($_POST, true) . "\n"; - $message .= "description: " . $description; - -// error_log($message, ERROR_TYPE, ERROR_FILE); - return false; -} - -function error_handler($errno, $errstr, $errfile, $errline) { - $message = "request: " . "http://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'] . "\n"; - $message .= "from: " . $_SERVER['REMOTE_ADDR'] . "\n"; - if(isset($_SERVER['HTTP_REFERER'])) $message .= "referer: " . $_SERVER['HTTP_REFERER'] . "\n"; - $message .= "post:" . var_export($_POST, true) . "\n"; - $message .= "type: " . get_error_name($errno) . "\n" - . "error: " . $errstr . "\n" - . "line: " . $errline . "\n" - . "file: " . $errfile; - -// error_log($message, ERROR_TYPE, ERROR_FILE); - return false; -} - -function shutdown() { - $error = error_get_last(); - $message = "request: " . "http://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'] . "\n"; - $message .= "from: " . $_SERVER['REMOTE_ADDR'] . "\n"; - if(isset($_SERVER['HTTP_REFERER'])) $message .= "referer: " . $_SERVER['HTTP_REFERER'] . "\n"; - if (is_array($error)) { - foreach ($error as $info => $string) { - $message .= "{$info}: {$string}\n"; - } - } - - error_log($message, ERROR_TYPE, ERROR_FILE); -} - -function exception_handler($exception) { - $message = "request: " . "http://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'] . "\n"; - $message .= "from: " . $_SERVER['REMOTE_ADDR'] . "\n"; - if(isset($_SERVER['HTTP_REFERER'])) $message .= "referer: " . $_SERVER['HTTP_REFERER'] . "\n"; - $message .= - "file: " . $exception->getFile() . "\n" - . "line: " . $exception->getLine() . "\n" - . "message: " . $exception->getMessage() . "\n" - . "trace: " . $exception->getTraceAsString(); - error_log($message, ERROR_TYPE, ERROR_FILE); - return true; -} - -set_exception_handler('exception_handler'); -set_error_handler("error_handler"); -//register_shutdown_function('shutdown'); diff --git a/src/File.php b/src/File.php deleted file mode 100644 index abad27a..0000000 --- a/src/File.php +++ /dev/null @@ -1,80 +0,0 @@ -file = $file; - $this->filename = $src; - $this->parent = $parent; - } - - function get($name) { - return isset($this->file[$name]) ? $this->file[$name] : null; - } - - function fileStat() - { - $type = is_dir($this->filename); - return array( - 'name' => ($this->parent) ? ".." : $this->getName(), - 'type' => $type, - 'extension' => ($type) ? 'folder' : pathinfo($this->filename, PATHINFO_EXTENSION), - 'date' => date("d.m.Y H:i", $this->getTime()), - 'access' => 0, - 'size' => ($type) ? "" : $this->getSizeString(), - 'state' => isset($this->file['state']) ? $this->file['state'] : 'unknown', - 'title' => $this->getTitle(), - /*'author' => $this->file['author'], - 'description' => $this->file['description'], - 'keywords' => $this->file['keywords'],*/ - ); - } - - function isExpected() - { - if (isset($this->file['state'])) { - return ($this->file['state'] == 'expected'); - } - return false; - } - - function getSizeString() - { - $size = $this->getSize(); - foreach (array('б ', 'Kб', 'Mб') as $suffix) { - if (($size / 1024) <= 1) { - return round($size, 0) . ' ' . $suffix; - } - $size /= 1024; - } - return round($size, 0) . ' GB'; - } - - function getSize() - { - return ($this->isExpected()) ? 0 : filesize($this->filename); - } - - function getTime() - { - return ($this->isExpected()) ? 0 : filemtime($this->filename); - } - - function getName() - { - return pathinfo($this->filename, PATHINFO_BASENAME); - } - - function getTitle() - { - return isset($this->file['title']) ? $this->file['title'] : $this->getName(); - } -} diff --git a/src/Filter/ActionAccess.php b/src/Filter/ActionAccess.php index 7504a86..dc39ba0 100644 --- a/src/Filter/ActionAccess.php +++ b/src/Filter/ActionAccess.php @@ -6,9 +6,9 @@ class Filter_ActionAccess { public $access = array(); + public $processor; - function __construct($processor) - { + function __construct(/*.Filter_Filter.*/$processor) { $this->processor = $processor; } @@ -17,14 +17,12 @@ class Filter_ActionAccess * !! Реализация класса проверки действий не должна быть внутри Контроллера!!! * Информация о доступе может быть в файле, базе данных и т.д. */ - function checkAction($action) - { + function checkAction($action) { // Импликация !! http://ru.wikipedia.org/wiki/Импликация - return (!isset($this->access[$action]) || in_array(UserAccess::$access, $this->access[$action])); + return (!isset($this->access[$action]) || in_array(Filter_UserAccess::$access, $this->access[$action])); } - function execute(HTTPRequest $request) - { + function execute(HttpRequest $request) { $action = $request->getAction(); if(! $this->checkAction($action)) { $request->set('action', 'index'); diff --git a/src/Filter/ActionLogger.php b/src/Filter/ActionLogger.php index 2d6c395..a71d5f5 100644 --- a/src/Filter/ActionLogger.php +++ b/src/Filter/ActionLogger.php @@ -2,22 +2,20 @@ class Filter_ActionLogger { - public $before = array (); + public $before = array(); public $file; public $action; public $processor; - function __construct($processor) - { + function __construct(/*.Filter_Filter.*/$processor) { $this->processor = $processor; $this->file = fopen(Shortcut::getUrl('access.log'), "a"); } - function execute(HTTPRequest $request) - { + function execute(HttpRequest $request) { $action = $request->getAction(); if(in_array($action, $this->before)) { - fwrite($this->file, "time: " . date("r", time()) . " query: ". json::encode(array_merge($_POST, $_GET)) . " by: " . UserAccess::$name . "\n"); + fwrite($this->file, "time: " . date("r", time()) . " query: ". json_encode(array_merge($_POST, $_GET)) . " by: " . Filter_UserAccess::$name . "\n"); } return $this->processor->execute($request); } diff --git a/src/Filter/Authorization.php b/src/Filter/Authorization.php new file mode 100644 index 0000000..17db6a6 --- /dev/null +++ b/src/Filter/Authorization.php @@ -0,0 +1,52 @@ +executeQuery("UPDATE visitor SET sid = '' WHERE id_visitor = " . $result->getInt('id_user')); + session_register("access"); + session_register("time"); + +// $_SESSION ["group"] = $result->getInt('access'); + $_SESSION ["access"] = $id; // id_user + $_SESSION [self::SESSION_BROWSER_SIGN_KEYNAME] = self::getBrowserSign(); + $_SESSION ["time"] = time(); + } + + private static function getBrowserSign() + { + $rawSign = self::SESSION_BROWSER_SIGN_SECRET; +// $signParts = array('HTTP_USER_AGENT', 'HTTP_ACCEPT_ENCODING'); + $signParts = array(); + + foreach ($signParts as $signPart) { + $rawSign .= '::' . (isset($_SERVER[$signPart]) ? $_SERVER[$signPart] : 'none'); + } + return md5($rawSign); + } + + static function logout() { + session_destroy(); + } +} diff --git a/src/Filter/Filter.php b/src/Filter/Filter.php index 9edf261..8140e8f 100644 --- a/src/Filter/Filter.php +++ b/src/Filter/Filter.php @@ -6,7 +6,7 @@ class Filter_Filter { public $processor; - public function __construct($processor) + public function __construct(/*.Filter_Filter.*/$processor) { $this->processor = $processor; } @@ -16,9 +16,9 @@ class Filter_Filter return $this->processor->execute($request); } - public function getView($name) + public function getView($name, $class = 'View_Top') { - return $this->processor->getView($name); + return $this->processor->getView($name, $class); } public function getConnection() diff --git a/src/Filter/UserAccess.php b/src/Filter/UserAccess.php index 8fac5e0..ce27a66 100644 --- a/src/Filter/UserAccess.php +++ b/src/Filter/UserAccess.php @@ -16,12 +16,12 @@ class Filter_UserAccess { } - public static function setUp($db) + public static function setUp(Database $db) { self::$db = $db; } - public static function getUserByQuery($stmt) + public static function getUserByQuery(Database_Statement $stmt) { global $GROUPS; $result = $stmt->executeQuery(); @@ -62,7 +62,7 @@ class Filter_UserAccess $time = time(); if ($time - $lasttime > self::LIFE_TIME) return null; // Вышло время сессии $id = self::$id; - $stmt = self::$db->executeQuery("UPDATE users SET lasttime = $time WHERE id_user = $id"); // Время последнего обращения входа + self::$db->executeQuery("UPDATE users SET lasttime = $time WHERE id_user = $id"); // Время последнего обращения входа } return $result; } diff --git a/src/Formats/Dot.php b/src/Formats/Dot.php deleted file mode 100644 index 83f71dd..0000000 --- a/src/Formats/Dot.php +++ /dev/null @@ -1,50 +0,0 @@ - $value) { - foreach ($value as $n) { - $result [] = "\t\"$key\" -> \"$n\"\n"; - } - } - $result [] = self::getFooter(); - return implode("", $result); - } -} diff --git a/src/Formats/Helix.php b/src/Formats/Helix.php deleted file mode 100644 index ff52c53..0000000 --- a/src/Formats/Helix.php +++ /dev/null @@ -1,85 +0,0 @@ -uuid = "*"; - $this->uuid_writeable = 1; - } - - public function getString () { - return "{$this->password};{$this->uuid};{$this->uuid_writeable}"; - } - - public function setPassword ($username, $realm, $password) { - $this->password = md5 ("$username:$realm:$password"); - } -} - -class HPermission { - public $url; - public $url_type; - public $permission_type; - public $expires; - public $debitted_time; - - public function __construct ($url, $url_type) { - $this->url = $url; - $this->url_type = $url_type; - $this->expires = "*"; // MM/DD/YYYY:HH:MM:SS - $this->permission_type = 0; - $this->debitted_time = 0; - } - - public function getString () { - return "{$this->url};{$this->url_type};{$this->permission_type};{$this->expires};{$this->debitted_time}"; - } -} - -class HFile { - public $authorize; - public $permission = array (); - - public function addAuthorize ($name, $realm, $password) { - $this->authorize = new HAuthorize (); - $this->authorize->setPassword ($name, $realm, $password); - } - - public function addPermission ($url, $url_type) { - $this->permission[] = new HPermission ($url, $url_type); - } - - public function write ($name) { - $file = fopen ($name, 'w'); - fwrite ($file, $this->getString ()); - fclose ($file); - } - - public function writeFTP ($ftp, $path) { - $file = tmpfile (); - fwrite ($file, $this->getString ()); - fseek ($file, 0); - - ftp_fput ($ftp, $path, $file, FTP_BINARY); - - fclose ($file); - } - - public function getString () { - $result = array (); - $result[] = $this->authorize->getString (); - $result[] = "\n"; - foreach ($this->permission as $p) { - $result[] = $p->getString (); - $result[] = "\n"; - } - return implode ("", $result); - } -} - diff --git a/src/Geometry/Point.php b/src/Geometry/Point.php deleted file mode 100644 index 0e11934..0000000 --- a/src/Geometry/Point.php +++ /dev/null @@ -1,12 +0,0 @@ -left = $left; - $this->top = $top; - } -} - diff --git a/src/Geometry/Rectangle.php b/src/Geometry/Rectangle.php deleted file mode 100644 index 80a9572..0000000 --- a/src/Geometry/Rectangle.php +++ /dev/null @@ -1,49 +0,0 @@ -left = $left; - $this->top = $top; - $this->width = $width; - $this->height = $height; - } - - function __get($name) - { - switch ($name) { - case 'right': return $this->left + $this->width; - case 'bottom': return $this->top + $this->height; - } - } - - function __set($name, $value) - { - switch ($name) { - case 'right': $this->width = $value - $this->left; - case 'bottom': $this->height = $value - $this->top; - } - } - - /** - * Смещает прямоугольник на заданное положение - */ - function addPoint(Point $point) - { - $result = clone $this; - $result->left += $point->left; - $result->top += $point->top; - return $result; - } - - /** - * Координаты точки при выравнивании прямоугольника относительно текущего - */ - function alignment(Rectangle $base) - { - return new Point((($base->left + $base->right) - ($this->left + $this->right)) / 2, $base->bottom - $this->height); - } -} diff --git a/src/IdnaConvert.php b/src/IdnaConvert.php deleted file mode 100644 index 8f9b07c..0000000 --- a/src/IdnaConvert.php +++ /dev/null @@ -1,2707 +0,0 @@ - - * @author Leonid Kogan - * @copyright 2004-2009 phlyLabs Berlin, http://phlylabs.de - * @version 0.6.3 - * @changelog since 0.5.1 class updated to PHP5/6 style should be compatible to PHP 4.3+ - * - added a missing replace mapping for THAI CHARACTER SARA AM - */ -class IdnaConvert -{ - // NP See below - - // Internal settings, do not mess with them - private $_punycode_prefix = 'xn--'; - private $_invalid_ucs = 0x80000000; - private $_max_ucs = 0x10FFFF; - private $_base = 36; - private $_tmin = 1; - private $_tmax = 26; - private $_skew = 38; - private $_damp = 700; - private $_initial_bias = 72; - private $_initial_n = 0x80; - private $_sbase = 0xAC00; - private $_lbase = 0x1100; - private $_vbase = 0x1161; - private $_tbase = 0x11A7; - private $_lcount = 19; - private $_vcount = 21; - private $_tcount = 28; - private $_ncount = 588; // _vcount * _tcount - private $_scount = 11172; // _lcount * _tcount * _vcount - private $_error = false; - - // See {@link set_paramter()} for details of how to change the following - // settings from within your script / application - private $_api_encoding = 'utf8'; // Default input charset is UTF-8 - private $_allow_overlong = false; // Overlong UTF-8 encodings are forbidden - private $_strict_mode = false; // Behave strict or not - - - /** - * the constructor - * - * @param array $options - * @return boolean - * @since 0.5.2 - */ - public function __construct($options = false) - { - $this->slast = $this->_sbase + $this->_lcount * $this->_vcount * $this->_tcount; - // If parameters are given, pass these to the respective method - if (is_array($options)) return $this->set_parameter($options); - return true; - } - - /** - * Sets a new option value. Available options and values: - * [encoding - Use either UTF-8, UCS4 as array or UCS4 as string as input ('utf8' for UTF-8, - * 'ucs4_string' and 'ucs4_array' respectively for UCS4); The output is always UTF-8] - * [overlong - Unicode does not allow unnecessarily long encodings of chars, - * to allow this, set this parameter to true, else to false; - * default is false.] - * [strict - true: strict mode, good for registration purposes - Causes errors - * on failures; false: loose mode, ideal for "wildlife" applications - * by silently ignoring errors and returning the original input instead - * - * @param mixed Parameter to set (string: single parameter; array of Parameter => Value pairs) - * @param string Value to use (if parameter 1 is a string) - * @return boolean true on success, false otherwise - */ - public function set_parameter($option, $value = false) - { - if (!is_array($option)) { - $option = array($option => $value); - } - foreach ($option as $k => $v) { - switch ($k) { - case 'encoding': - switch ($v) { - case 'utf8': - case 'ucs4_string': - case 'ucs4_array': - $this->_api_encoding = $v; - break; - default: - $this->_error('Set Parameter: Unknown parameter '.$v.' for option '.$k); - return false; - } - break; - case 'overlong': - $this->_allow_overlong = ($v) ? true : false; - break; - case 'strict': - $this->_strict_mode = ($v) ? true : false; - break; - default: - $this->_error('Set Parameter: Unknown option '.$k); - return false; - } - } - return true; - } - - /** - * Decode a given ACE domain name - * @param string Domain name (ACE string) - * [@param string Desired output encoding, see {@link set_parameter}] - * @return string Decoded Domain name (UTF-8 or UCS-4) - */ - public function decode($input, $one_time_encoding = false) - { - // Optionally set - if ($one_time_encoding) { - switch ($one_time_encoding) { - case 'utf8': - case 'ucs4_string': - case 'ucs4_array': - break; - default: - $this->_error('Unknown encoding '.$one_time_encoding); - return false; - } - } - // Make sure to drop any newline characters around - $input = trim($input); - - // Negotiate input and try to determine, whether it is a plain string, - // an email address or something like a complete URL - if (strpos($input, '@')) { // Maybe it is an email address - // No no in strict mode - if ($this->_strict_mode) { - $this->_error('Only simple domain name parts can be handled in strict mode'); - return false; - } - list ($email_pref, $input) = explode('@', $input, 2); - $arr = explode('.', $input); - foreach ($arr as $k => $v) { - if (preg_match('!^'.preg_quote($this->_punycode_prefix, '!').'!', $v)) { - $conv = $this->_decode($v); - if ($conv) $arr[$k] = $conv; - } - } - $input = join('.', $arr); - $arr = explode('.', $email_pref); - foreach ($arr as $k => $v) { - if (preg_match('!^'.preg_quote($this->_punycode_prefix, '!').'!', $v)) { - $conv = $this->_decode($v); - if ($conv) $arr[$k] = $conv; - } - } - $email_pref = join('.', $arr); - $return = $email_pref . '@' . $input; - } elseif (preg_match('![:\./]!', $input)) { // Or a complete domain name (with or without paths / parameters) - // No no in strict mode - if ($this->_strict_mode) { - $this->_error('Only simple domain name parts can be handled in strict mode'); - return false; - } - $parsed = parse_url($input); - if (isset($parsed['host'])) { - $arr = explode('.', $parsed['host']); - foreach ($arr as $k => $v) { - $conv = $this->_decode($v); - if ($conv) $arr[$k] = $conv; - } - $parsed['host'] = join('.', $arr); - $return = - (empty($parsed['scheme']) ? '' : $parsed['scheme'].(strtolower($parsed['scheme']) == 'mailto' ? ':' : '://')) - .(empty($parsed['user']) ? '' : $parsed['user'].(empty($parsed['pass']) ? '' : ':'.$parsed['pass']).'@') - .$parsed['host'] - .(empty($parsed['port']) ? '' : ':'.$parsed['port']) - .(empty($parsed['path']) ? '' : $parsed['path']) - .(empty($parsed['query']) ? '' : '?'.$parsed['query']) - .(empty($parsed['fragment']) ? '' : '#'.$parsed['fragment']); - } else { // parse_url seems to have failed, try without it - $arr = explode('.', $input); - foreach ($arr as $k => $v) { - $conv = $this->_decode($v); - $arr[$k] = ($conv) ? $conv : $v; - } - $return = join('.', $arr); - } - } else { // Otherwise we consider it being a pure domain name string - $return = $this->_decode($input); - if (!$return) $return = $input; - } - // The output is UTF-8 by default, other output formats need conversion here - // If one time encoding is given, use this, else the objects property - switch (($one_time_encoding) ? $one_time_encoding : $this->_api_encoding) { - case 'utf8': - return $return; - break; - case 'ucs4_string': - return $this->_ucs4_to_ucs4_string($this->_utf8_to_ucs4($return)); - break; - case 'ucs4_array': - return $this->_utf8_to_ucs4($return); - break; - default: - $this->_error('Unsupported output format'); - return false; - } - } - - /** - * Encode a given UTF-8 domain name - * @param string Domain name (UTF-8 or UCS-4) - * [@param string Desired input encoding, see {@link set_parameter}] - * @return string Encoded Domain name (ACE string) - */ - public function encode($decoded, $one_time_encoding = false) - { - // Forcing conversion of input to UCS4 array - // If one time encoding is given, use this, else the objects property - switch ($one_time_encoding ? $one_time_encoding : $this->_api_encoding) { - case 'utf8': - $decoded = $this->_utf8_to_ucs4($decoded); - break; - case 'ucs4_string': - $decoded = $this->_ucs4_string_to_ucs4($decoded); - case 'ucs4_array': - break; - default: - $this->_error('Unsupported input format: '.($one_time_encoding ? $one_time_encoding : $this->_api_encoding)); - return false; - } - - // No input, no output, what else did you expect? - if (empty($decoded)) return ''; - - // Anchors for iteration - $last_begin = 0; - // Output string - $output = ''; - foreach ($decoded as $k => $v) { - // Make sure to use just the plain dot - switch($v) { - case 0x3002: - case 0xFF0E: - case 0xFF61: - $decoded[$k] = 0x2E; - // Right, no break here, the above are converted to dots anyway - // Stumbling across an anchoring character - case 0x2E: - case 0x2F: - case 0x3A: - case 0x3F: - case 0x40: - // Neither email addresses nor URLs allowed in strict mode - if ($this->_strict_mode) { - $this->_error('Neither email addresses nor URLs are allowed in strict mode.'); - return false; - } else { - // Skip first char - if ($k) { - $encoded = ''; - $encoded = $this->_encode(array_slice($decoded, $last_begin, (($k)-$last_begin))); - if ($encoded) { - $output .= $encoded; - } else { - $output .= $this->_ucs4_to_utf8(array_slice($decoded, $last_begin, (($k)-$last_begin))); - } - $output .= chr($decoded[$k]); - } - $last_begin = $k + 1; - } - } - } - // Catch the rest of the string - if ($last_begin) { - $inp_len = sizeof($decoded); - $encoded = ''; - $encoded = $this->_encode(array_slice($decoded, $last_begin, (($inp_len)-$last_begin))); - if ($encoded) { - $output .= $encoded; - } else { - $output .= $this->_ucs4_to_utf8(array_slice($decoded, $last_begin, (($inp_len)-$last_begin))); - } - return $output; - } else { - if ($output = $this->_encode($decoded)) { - return $output; - } else { - return $this->_ucs4_to_utf8($decoded); - } - } - } - - /** - * Use this method to get the last error ocurred - * @param void - * @return string The last error, that occured - */ - public function get_last_error() - { - return $this->_error; - } - - /** - * The actual decoding algorithm - * @param string - * @return mixed - */ - private function _decode($encoded) - { - $decoded = array(); - // find the Punycode prefix - if (!preg_match('!^'.preg_quote($this->_punycode_prefix, '!').'!', $encoded)) { - $this->_error('This is not a punycode string'); - return false; - } - $encode_test = preg_replace('!^'.preg_quote($this->_punycode_prefix, '!').'!', '', $encoded); - // If nothing left after removing the prefix, it is hopeless - if (!$encode_test) { - $this->_error('The given encoded string was empty'); - return false; - } - // Find last occurence of the delimiter - $delim_pos = strrpos($encoded, '-'); - if ($delim_pos > strlen($this->_punycode_prefix)) { - for ($k = strlen($this->_punycode_prefix); $k < $delim_pos; ++$k) { - $decoded[] = ord($encoded{$k}); - } - } - $deco_len = count($decoded); - $enco_len = strlen($encoded); - - // Wandering through the strings; init - $is_first = true; - $bias = $this->_initial_bias; - $idx = 0; - $char = $this->_initial_n; - - for ($enco_idx = ($delim_pos) ? ($delim_pos + 1) : 0; $enco_idx < $enco_len; ++$deco_len) { - for ($old_idx = $idx, $w = 1, $k = $this->_base; 1 ; $k += $this->_base) { - $digit = $this->_decode_digit($encoded{$enco_idx++}); - $idx += $digit * $w; - $t = ($k <= $bias) ? $this->_tmin : - (($k >= $bias + $this->_tmax) ? $this->_tmax : ($k - $bias)); - if ($digit < $t) break; - $w = (int) ($w * ($this->_base - $t)); - } - $bias = $this->_adapt($idx - $old_idx, $deco_len + 1, $is_first); - $is_first = false; - $char += (int) ($idx / ($deco_len + 1)); - $idx %= ($deco_len + 1); - if ($deco_len > 0) { - // Make room for the decoded char - for ($i = $deco_len; $i > $idx; $i--) $decoded[$i] = $decoded[($i - 1)]; - } - $decoded[$idx++] = $char; - } - return $this->_ucs4_to_utf8($decoded); - } - - /** - * The actual encoding algorithm - * @param string - * @return mixed - */ - private function _encode($decoded) - { - // We cannot encode a domain name containing the Punycode prefix - $extract = strlen($this->_punycode_prefix); - $check_pref = $this->_utf8_to_ucs4($this->_punycode_prefix); - $check_deco = array_slice($decoded, 0, $extract); - - if ($check_pref == $check_deco) { - $this->_error('This is already a punycode string'); - return false; - } - // We will not try to encode strings consisting of basic code points only - $encodable = false; - foreach ($decoded as $k => $v) { - if ($v > 0x7a) { - $encodable = true; - break; - } - } - if (!$encodable) { - $this->_error('The given string does not contain encodable chars'); - return false; - } - // Do NAMEPREP - $decoded = $this->_nameprep($decoded); - if (!$decoded || !is_array($decoded)) return false; // NAMEPREP failed - $deco_len = count($decoded); - if (!$deco_len) return false; // Empty array - $codecount = 0; // How many chars have been consumed - $encoded = ''; - // Copy all basic code points to output - for ($i = 0; $i < $deco_len; ++$i) { - $test = $decoded[$i]; - // Will match [-0-9a-zA-Z] - if ((0x2F < $test && $test < 0x40) || (0x40 < $test && $test < 0x5B) - || (0x60 < $test && $test <= 0x7B) || (0x2D == $test)) { - $encoded .= chr($decoded[$i]); - $codecount++; - } - } - if ($codecount == $deco_len) return $encoded; // All codepoints were basic ones - - // Start with the prefix; copy it to output - $encoded = $this->_punycode_prefix.$encoded; - // If we have basic code points in output, add an hyphen to the end - if ($codecount) $encoded .= '-'; - // Now find and encode all non-basic code points - $is_first = true; - $cur_code = $this->_initial_n; - $bias = $this->_initial_bias; - $delta = 0; - while ($codecount < $deco_len) { - // Find the smallest code point >= the current code point and - // remember the last ouccrence of it in the input - for ($i = 0, $next_code = $this->_max_ucs; $i < $deco_len; $i++) { - if ($decoded[$i] >= $cur_code && $decoded[$i] <= $next_code) { - $next_code = $decoded[$i]; - } - } - $delta += ($next_code - $cur_code) * ($codecount + 1); - $cur_code = $next_code; - - // Scan input again and encode all characters whose code point is $cur_code - for ($i = 0; $i < $deco_len; $i++) { - if ($decoded[$i] < $cur_code) { - $delta++; - } elseif ($decoded[$i] == $cur_code) { - for ($q = $delta, $k = $this->_base; 1; $k += $this->_base) { - $t = ($k <= $bias) ? $this->_tmin : - (($k >= $bias + $this->_tmax) ? $this->_tmax : $k - $bias); - if ($q < $t) break; - $encoded .= $this->_encode_digit(intval($t + (($q - $t) % ($this->_base - $t)))); //v0.4.5 Changed from ceil() to intval() - $q = (int) (($q - $t) / ($this->_base - $t)); - } - $encoded .= $this->_encode_digit($q); - $bias = $this->_adapt($delta, $codecount+1, $is_first); - $codecount++; - $delta = 0; - $is_first = false; - } - } - $delta++; - $cur_code++; - } - return $encoded; - } - - /** - * Adapt the bias according to the current code point and position - * @param int $delta - * @param int $npoints - * @param int $is_first - * @return int - */ - private function _adapt($delta, $npoints, $is_first) - { - $delta = intval($is_first ? ($delta / $this->_damp) : ($delta / 2)); - $delta += intval($delta / $npoints); - for ($k = 0; $delta > (($this->_base - $this->_tmin) * $this->_tmax) / 2; $k += $this->_base) { - $delta = intval($delta / ($this->_base - $this->_tmin)); - } - return intval($k + ($this->_base - $this->_tmin + 1) * $delta / ($delta + $this->_skew)); - } - - /** - * Encoding a certain digit - * @param int $d - * @return string - */ - private function _encode_digit($d) - { - return chr($d + 22 + 75 * ($d < 26)); - } - - /** - * Decode a certain digit - * @param int $cp - * @return int - */ - private function _decode_digit($cp) - { - $cp = ord($cp); - return ($cp - 48 < 10) ? $cp - 22 : (($cp - 65 < 26) ? $cp - 65 : (($cp - 97 < 26) ? $cp - 97 : $this->_base)); - } - - /** - * Internal error handling method - * @param string $error - */ - private function _error($error = '') - { - $this->_error = $error; - } - - /** - * Do Nameprep according to RFC3491 and RFC3454 - * @param array Unicode Characters - * @return string Unicode Characters, Nameprep'd - */ - private function _nameprep($input) - { - $output = array(); - $error = false; - // - // Mapping - // Walking through the input array, performing the required steps on each of - // the input chars and putting the result into the output array - // While mapping required chars we apply the cannonical ordering - foreach ($input as $v) { - // Map to nothing == skip that code point - if (in_array($v, $this->NP['map_nothing'])) continue; - // Try to find prohibited input - if (in_array($v, $this->NP['prohibit']) || in_array($v, $this->NP['general_prohibited'])) { - $this->_error('NAMEPREP: Prohibited input U+'.sprintf('%08X', $v)); - return false; - } - foreach ($this->NP['prohibit_ranges'] as $range) { - if ($range[0] <= $v && $v <= $range[1]) { - $this->_error('NAMEPREP: Prohibited input U+'.sprintf('%08X', $v)); - return false; - } - } - // Hangul syllable decomposition - if (0xAC00 <= $v && $v <= 0xD7AF) { - foreach ($this->_hangul_decompose($v) as $out) $output[] = (int) $out; - // There's a decomposition mapping for that code point - } elseif (isset($this->NP['replacemaps'][$v])) { - foreach ($this->_apply_cannonical_ordering($this->NP['replacemaps'][$v]) as $out) { - $output[] = (int) $out; - } - } else { - $output[] = (int) $v; - } - } - // Before applying any Combining, try to rearrange any Hangul syllables - $output = $this->_hangul_compose($output); - // - // Combine code points - // - $last_class = 0; - $last_starter = 0; - $out_len = count($output); - for ($i = 0; $i < $out_len; ++$i) { - $class = $this->_get_combining_class($output[$i]); - if ((!$last_class || $last_class > $class) && $class) { - // Try to match - $seq_len = $i - $last_starter; - $out = $this->_combine(array_slice($output, $last_starter, $seq_len)); - // On match: Replace the last starter with the composed character and remove - // the now redundant non-starter(s) - if ($out) { - $output[$last_starter] = $out; - if (count($out) != $seq_len) { - for ($j = $i+1; $j < $out_len; ++$j) $output[$j-1] = $output[$j]; - unset($output[$out_len]); - } - // Rewind the for loop by one, since there can be more possible compositions - $i--; - $out_len--; - $last_class = ($i == $last_starter) ? 0 : $this->_get_combining_class($output[$i-1]); - continue; - } - } - // The current class is 0 - if (!$class) $last_starter = $i; - $last_class = $class; - } - return $output; - } - - /** - * Decomposes a Hangul syllable - * (see http://www.unicode.org/unicode/reports/tr15/#Hangul - * @param integer 32bit UCS4 code point - * @return array Either Hangul Syllable decomposed or original 32bit value as one value array - */ - private function _hangul_decompose($char) - { - $sindex = (int) $char - $this->_sbase; - if ($sindex < 0 || $sindex >= $this->_scount) return array($char); - $result = array(); - $result[] = (int) $this->_lbase + $sindex / $this->_ncount; - $result[] = (int) $this->_vbase + ($sindex % $this->_ncount) / $this->_tcount; - $T = intval($this->_tbase + $sindex % $this->_tcount); - if ($T != $this->_tbase) $result[] = $T; - return $result; - } - /** - * Ccomposes a Hangul syllable - * (see http://www.unicode.org/unicode/reports/tr15/#Hangul - * @param array Decomposed UCS4 sequence - * @return array UCS4 sequence with syllables composed - */ - private function _hangul_compose($input) - { - $inp_len = count($input); - if (!$inp_len) return array(); - $result = array(); - $last = (int) $input[0]; - $result[] = $last; // copy first char from input to output - - for ($i = 1; $i < $inp_len; ++$i) { - $char = (int) $input[$i]; - $sindex = $last - $this->_sbase; - $lindex = $last - $this->_lbase; - $vindex = $char - $this->_vbase; - $tindex = $char - $this->_tbase; - // Find out, whether two current characters are LV and T - if (0 <= $sindex && $sindex < $this->_scount && ($sindex % $this->_tcount == 0) - && 0 <= $tindex && $tindex <= $this->_tcount) { - // create syllable of form LVT - $last += $tindex; - $result[(count($result) - 1)] = $last; // reset last - continue; // discard char - } - // Find out, whether two current characters form L and V - if (0 <= $lindex && $lindex < $this->_lcount && 0 <= $vindex && $vindex < $this->_vcount) { - // create syllable of form LV - $last = (int) $this->_sbase + ($lindex * $this->_vcount + $vindex) * $this->_tcount; - $result[(count($result) - 1)] = $last; // reset last - continue; // discard char - } - // if neither case was true, just add the character - $last = $char; - $result[] = $char; - } - return $result; - } - - /** - * Returns the combining class of a certain wide char - * @param integer Wide char to check (32bit integer) - * @return integer Combining class if found, else 0 - */ - private function _get_combining_class($char) - { - return isset($this->NP['norm_combcls'][$char]) ? $this->NP['norm_combcls'][$char] : 0; - } - - /** - * Apllies the cannonical ordering of a decomposed UCS4 sequence - * @param array Decomposed UCS4 sequence - * @return array Ordered USC4 sequence - */ - private function _apply_cannonical_ordering($input) - { - $swap = true; - $size = count($input); - while ($swap) { - $swap = false; - $last = $this->_get_combining_class(intval($input[0])); - for ($i = 0; $i < $size-1; ++$i) { - $next = $this->_get_combining_class(intval($input[$i+1])); - if ($next != 0 && $last > $next) { - // Move item leftward until it fits - for ($j = $i + 1; $j > 0; --$j) { - if ($this->_get_combining_class(intval($input[$j-1])) <= $next) break; - $t = intval($input[$j]); - $input[$j] = intval($input[$j-1]); - $input[$j-1] = $t; - $swap = true; - } - // Reentering the loop looking at the old character again - $next = $last; - } - $last = $next; - } - } - return $input; - } - - /** - * Do composition of a sequence of starter and non-starter - * @param array UCS4 Decomposed sequence - * @return array Ordered USC4 sequence - */ - private function _combine($input) - { - $inp_len = count($input); - foreach ($this->NP['replacemaps'] as $np_src => $np_target) { - if ($np_target[0] != $input[0]) continue; - if (count($np_target) != $inp_len) continue; - $hit = false; - foreach ($input as $k2 => $v2) { - if ($v2 == $np_target[$k2]) { - $hit = true; - } else { - $hit = false; - break; - } - } - if ($hit) return $np_src; - } - return false; - } - - /** - * This converts an UTF-8 encoded string to its UCS-4 representation - * By talking about UCS-4 "strings" we mean arrays of 32bit integers representing - * each of the "chars". This is due to PHP not being able to handle strings with - * bit depth different from 8. This apllies to the reverse method _ucs4_to_utf8(), too. - * The following UTF-8 encodings are supported: - * bytes bits representation - * 1 7 0xxxxxxx - * 2 11 110xxxxx 10xxxxxx - * 3 16 1110xxxx 10xxxxxx 10xxxxxx - * 4 21 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - * 5 26 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx - * 6 31 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx - * Each x represents a bit that can be used to store character data. - * The five and six byte sequences are part of Annex D of ISO/IEC 10646-1:2000 - * @param string $input - * @return string - */ - private function _utf8_to_ucs4($input) - { - $output = array(); - $out_len = 0; - // Patch by Daniel Hahler; work around prolbem with mbstring.func_overload - if (function_exists('mb_strlen')) { - $inp_len = mb_strlen($input, '8bit'); - } else { - $inp_len = strlen($input); - } - $mode = 'next'; - $test = 'none'; - for ($k = 0; $k < $inp_len; ++$k) { - $v = ord($input{$k}); // Extract byte from input string - if ($v < 128) { // We found an ASCII char - put into stirng as is - $output[$out_len] = $v; - ++$out_len; - if ('add' == $mode) { - $this->_error('Conversion from UTF-8 to UCS-4 failed: malformed input at byte '.$k); - return false; - } - continue; - } - if ('next' == $mode) { // Try to find the next start byte; determine the width of the Unicode char - $start_byte = $v; - $mode = 'add'; - $test = 'range'; - if ($v >> 5 == 6) { // &110xxxxx 10xxxxx - $next_byte = 0; // Tells, how many times subsequent bitmasks must rotate 6bits to the left - $v = ($v - 192) << 6; - } elseif ($v >> 4 == 14) { // &1110xxxx 10xxxxxx 10xxxxxx - $next_byte = 1; - $v = ($v - 224) << 12; - } elseif ($v >> 3 == 30) { // &11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - $next_byte = 2; - $v = ($v - 240) << 18; - } elseif ($v >> 2 == 62) { // &111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx - $next_byte = 3; - $v = ($v - 248) << 24; - } elseif ($v >> 1 == 126) { // &1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx - $next_byte = 4; - $v = ($v - 252) << 30; - } else { - $this->_error('This might be UTF-8, but I don\'t understand it at byte '.$k); - return false; - } - if ('add' == $mode) { - $output[$out_len] = (int) $v; - ++$out_len; - continue; - } - } - if ('add' == $mode) { - if (!$this->_allow_overlong && $test == 'range') { - $test = 'none'; - if (($v < 0xA0 && $start_byte == 0xE0) || ($v < 0x90 && $start_byte == 0xF0) || ($v > 0x8F && $start_byte == 0xF4)) { - $this->_error('Bogus UTF-8 character detected (out of legal range) at byte '.$k); - return false; - } - } - if ($v >> 6 == 2) { // Bit mask must be 10xxxxxx - $v = ($v - 128) << ($next_byte * 6); - $output[($out_len - 1)] += $v; - --$next_byte; - } else { - $this->_error('Conversion from UTF-8 to UCS-4 failed: malformed input at byte '.$k); - return false; - } - if ($next_byte < 0) { - $mode = 'next'; - } - } - } // for - return $output; - } - - /** - * Convert UCS-4 string into UTF-8 string - * See _utf8_to_ucs4() for details - * @param string $input - * @return string - */ - private function _ucs4_to_utf8($input) - { - $output = ''; - foreach ($input as $k => $v) { - if ($v < 128) { // 7bit are transferred literally - $output .= chr($v); - } elseif ($v < (1 << 11)) { // 2 bytes - $output .= chr(192+($v >> 6)).chr(128+($v & 63)); - } elseif ($v < (1 << 16)) { // 3 bytes - $output .= chr(224+($v >> 12)).chr(128+(($v >> 6) & 63)).chr(128+($v & 63)); - } elseif ($v < (1 << 21)) { // 4 bytes - $output .= chr(240+($v >> 18)).chr(128+(($v >> 12) & 63)).chr(128+(($v >> 6) & 63)).chr(128+($v & 63)); - } elseif (self::$safe_mode) { - $output .= self::$safe_char; - } else { - $this->_error('Conversion from UCS-4 to UTF-8 failed: malformed input at byte '.$k); - return false; - } - } - return $output; - } - - /** - * Convert UCS-4 array into UCS-4 string - * - * @param array $input - * @return string - */ - private function _ucs4_to_ucs4_string($input) - { - $output = ''; - // Take array values and split output to 4 bytes per value - // The bit mask is 255, which reads &11111111 - foreach ($input as $v) { - $output .= chr(($v >> 24) & 255).chr(($v >> 16) & 255).chr(($v >> 8) & 255).chr($v & 255); - } - return $output; - } - - /** - * Convert UCS-4 strin into UCS-4 garray - * - * @param string $input - * @return array - */ - private function _ucs4_string_to_ucs4($input) - { - $output = array(); - $inp_len = strlen($input); - // Input length must be dividable by 4 - if ($inp_len % 4) { - $this->_error('Input UCS4 string is broken'); - return false; - } - // Empty input - return empty output - if (!$inp_len) return $output; - for ($i = 0, $out_len = -1; $i < $inp_len; ++$i) { - // Increment output position every 4 input bytes - if (!($i % 4)) { - $out_len++; - $output[$out_len] = 0; - } - $output[$out_len] += ord($input{$i}) << (8 * (3 - ($i % 4) ) ); - } - return $output; - } - - /** - * Holds all relevant mapping tables, loaded from a seperate file on construct - * See RFC3454 for details - * - * @private array - * @since 0.5.2 - * - */ - private $NP = array - ('map_nothing' => array - (0xAD, 0x34F, 0x1806, 0x180B, 0x180C, 0x180D, 0x200B - ,0x200C, 0x200D, 0x2060, 0xFE00, 0xFE01, 0xFE02, 0xFE03 - ,0xFE04, 0xFE05, 0xFE06, 0xFE07, 0xFE08, 0xFE09, 0xFE0A - ,0xFE0B, 0xFE0C, 0xFE0D, 0xFE0E, 0xFE0F, 0xFEFF - ) - ,'general_prohibited' => array - (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE - ,0xF, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 - ,0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20 - ,0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29 - ,0x2A, 0x2B, 0x2C, 0x2F, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F - ,0x40, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x7B, 0x7C - ,0x7D, 0x7E, 0x7F, 0x3002 - ) - ,'prohibit' => array - (0xA0, 0x340, 0x341, 0x6DD, 0x70F, 0x1680, 0x180E, 0x2000 - ,0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007 - ,0x2008, 0x2009, 0x200A, 0x200B, 0x200C, 0x200D, 0x200E - ,0x200F, 0x2028, 0x2029, 0x202A, 0x202B, 0x202C, 0x202D - ,0x202E, 0x202F, 0x205F, 0x206A, 0x206B, 0x206C, 0x206D - ,0x206E, 0x206F, 0x3000, 0xFEFF, 0xFFF9, 0xFFFA, 0xFFFB - ,0xFFFC, 0xFFFD, 0xFFFE, 0xFFFF, 0x1FFFE, 0x1FFFF, 0x2FFFE - ,0x2FFFF, 0x3FFFE, 0x3FFFF, 0x4FFFE, 0x4FFFF, 0x5FFFE - ,0x5FFFF, 0x6FFFE, 0x6FFFF, 0x7FFFE, 0x7FFFF, 0x8FFFE - ,0x8FFFF, 0x9FFFE, 0x9FFFF, 0xAFFFE, 0xAFFFF, 0xBFFFE - ,0xBFFFF, 0xCFFFE, 0xCFFFF, 0xDFFFE, 0xDFFFF, 0xE0001 - ,0xEFFFE, 0xEFFFF, 0xFFFFE, 0xFFFFF, 0x10FFFE, 0x10FFFF - ) - ,'prohibit_ranges' => array - (array(0x80, 0x9F), array(0x2060, 0x206F) - ,array(0x1D173, 0x1D17A), array(0xE000, 0xF8FF) - ,array(0xF0000, 0xFFFFD), array(0x100000, 0x10FFFD) - ,array(0xFDD0, 0xFDEF), array(0xD800, 0xDFFF) - ,array(0x2FF0, 0x2FFB), array(0xE0020, 0xE007F) - ) - ,'replacemaps' => array - (0x41 => array(0x61) - ,0x42 => array(0x62) - ,0x43 => array(0x63) - ,0x44 => array(0x64) - ,0x45 => array(0x65) - ,0x46 => array(0x66) - ,0x47 => array(0x67) - ,0x48 => array(0x68) - ,0x49 => array(0x69) - ,0x4A => array(0x6A) - ,0x4B => array(0x6B) - ,0x4C => array(0x6C) - ,0x4D => array(0x6D) - ,0x4E => array(0x6E) - ,0x4F => array(0x6F) - ,0x50 => array(0x70) - ,0x51 => array(0x71) - ,0x52 => array(0x72) - ,0x53 => array(0x73) - ,0x54 => array(0x74) - ,0x55 => array(0x75) - ,0x56 => array(0x76) - ,0x57 => array(0x77) - ,0x58 => array(0x78) - ,0x59 => array(0x79) - ,0x5A => array(0x7A) - ,0xB5 => array(0x3BC) - ,0xC0 => array(0xE0) - ,0xC1 => array(0xE1) - ,0xC2 => array(0xE2) - ,0xC3 => array(0xE3) - ,0xC4 => array(0xE4) - ,0xC5 => array(0xE5) - ,0xC6 => array(0xE6) - ,0xC7 => array(0xE7) - ,0xC8 => array(0xE8) - ,0xC9 => array(0xE9) - ,0xCA => array(0xEA) - ,0xCB => array(0xEB) - ,0xCC => array(0xEC) - ,0xCD => array(0xED) - ,0xCE => array(0xEE) - ,0xCF => array(0xEF) - ,0xD0 => array(0xF0) - ,0xD1 => array(0xF1) - ,0xD2 => array(0xF2) - ,0xD3 => array(0xF3) - ,0xD4 => array(0xF4) - ,0xD5 => array(0xF5) - ,0xD6 => array(0xF6) - ,0xD8 => array(0xF8) - ,0xD9 => array(0xF9) - ,0xDA => array(0xFA) - ,0xDB => array(0xFB) - ,0xDC => array(0xFC) - ,0xDD => array(0xFD) - ,0xDE => array(0xFE) - ,0xDF => array(0x73, 0x73) - ,0x100 => array(0x101) - ,0x102 => array(0x103) - ,0x104 => array(0x105) - ,0x106 => array(0x107) - ,0x108 => array(0x109) - ,0x10A => array(0x10B) - ,0x10C => array(0x10D) - ,0x10E => array(0x10F) - ,0x110 => array(0x111) - ,0x112 => array(0x113) - ,0x114 => array(0x115) - ,0x116 => array(0x117) - ,0x118 => array(0x119) - ,0x11A => array(0x11B) - ,0x11C => array(0x11D) - ,0x11E => array(0x11F) - ,0x120 => array(0x121) - ,0x122 => array(0x123) - ,0x124 => array(0x125) - ,0x126 => array(0x127) - ,0x128 => array(0x129) - ,0x12A => array(0x12B) - ,0x12C => array(0x12D) - ,0x12E => array(0x12F) - ,0x130 => array(0x69, 0x307) - ,0x132 => array(0x133) - ,0x134 => array(0x135) - ,0x136 => array(0x137) - ,0x139 => array(0x13A) - ,0x13B => array(0x13C) - ,0x13D => array(0x13E) - ,0x13F => array(0x140) - ,0x141 => array(0x142) - ,0x143 => array(0x144) - ,0x145 => array(0x146) - ,0x147 => array(0x148) - ,0x149 => array(0x2BC, 0x6E) - ,0x14A => array(0x14B) - ,0x14C => array(0x14D) - ,0x14E => array(0x14F) - ,0x150 => array(0x151) - ,0x152 => array(0x153) - ,0x154 => array(0x155) - ,0x156 => array(0x157) - ,0x158 => array(0x159) - ,0x15A => array(0x15B) - ,0x15C => array(0x15D) - ,0x15E => array(0x15F) - ,0x160 => array(0x161) - ,0x162 => array(0x163) - ,0x164 => array(0x165) - ,0x166 => array(0x167) - ,0x168 => array(0x169) - ,0x16A => array(0x16B) - ,0x16C => array(0x16D) - ,0x16E => array(0x16F) - ,0x170 => array(0x171) - ,0x172 => array(0x173) - ,0x174 => array(0x175) - ,0x176 => array(0x177) - ,0x178 => array(0xFF) - ,0x179 => array(0x17A) - ,0x17B => array(0x17C) - ,0x17D => array(0x17E) - ,0x17F => array(0x73) - ,0x181 => array(0x253) - ,0x182 => array(0x183) - ,0x184 => array(0x185) - ,0x186 => array(0x254) - ,0x187 => array(0x188) - ,0x189 => array(0x256) - ,0x18A => array(0x257) - ,0x18B => array(0x18C) - ,0x18E => array(0x1DD) - ,0x18F => array(0x259) - ,0x190 => array(0x25B) - ,0x191 => array(0x192) - ,0x193 => array(0x260) - ,0x194 => array(0x263) - ,0x196 => array(0x269) - ,0x197 => array(0x268) - ,0x198 => array(0x199) - ,0x19C => array(0x26F) - ,0x19D => array(0x272) - ,0x19F => array(0x275) - ,0x1A0 => array(0x1A1) - ,0x1A2 => array(0x1A3) - ,0x1A4 => array(0x1A5) - ,0x1A6 => array(0x280) - ,0x1A7 => array(0x1A8) - ,0x1A9 => array(0x283) - ,0x1AC => array(0x1AD) - ,0x1AE => array(0x288) - ,0x1AF => array(0x1B0) - ,0x1B1 => array(0x28A) - ,0x1B2 => array(0x28B) - ,0x1B3 => array(0x1B4) - ,0x1B5 => array(0x1B6) - ,0x1B7 => array(0x292) - ,0x1B8 => array(0x1B9) - ,0x1BC => array(0x1BD) - ,0x1C4 => array(0x1C6) - ,0x1C5 => array(0x1C6) - ,0x1C7 => array(0x1C9) - ,0x1C8 => array(0x1C9) - ,0x1CA => array(0x1CC) - ,0x1CB => array(0x1CC) - ,0x1CD => array(0x1CE) - ,0x1CF => array(0x1D0) - ,0x1D1 => array(0x1D2) - ,0x1D3 => array(0x1D4) - ,0x1D5 => array(0x1D6) - ,0x1D7 => array(0x1D8) - ,0x1D9 => array(0x1DA) - ,0x1DB => array(0x1DC) - ,0x1DE => array(0x1DF) - ,0x1E0 => array(0x1E1) - ,0x1E2 => array(0x1E3) - ,0x1E4 => array(0x1E5) - ,0x1E6 => array(0x1E7) - ,0x1E8 => array(0x1E9) - ,0x1EA => array(0x1EB) - ,0x1EC => array(0x1ED) - ,0x1EE => array(0x1EF) - ,0x1F0 => array(0x6A, 0x30C) - ,0x1F1 => array(0x1F3) - ,0x1F2 => array(0x1F3) - ,0x1F4 => array(0x1F5) - ,0x1F6 => array(0x195) - ,0x1F7 => array(0x1BF) - ,0x1F8 => array(0x1F9) - ,0x1FA => array(0x1FB) - ,0x1FC => array(0x1FD) - ,0x1FE => array(0x1FF) - ,0x200 => array(0x201) - ,0x202 => array(0x203) - ,0x204 => array(0x205) - ,0x206 => array(0x207) - ,0x208 => array(0x209) - ,0x20A => array(0x20B) - ,0x20C => array(0x20D) - ,0x20E => array(0x20F) - ,0x210 => array(0x211) - ,0x212 => array(0x213) - ,0x214 => array(0x215) - ,0x216 => array(0x217) - ,0x218 => array(0x219) - ,0x21A => array(0x21B) - ,0x21C => array(0x21D) - ,0x21E => array(0x21F) - ,0x220 => array(0x19E) - ,0x222 => array(0x223) - ,0x224 => array(0x225) - ,0x226 => array(0x227) - ,0x228 => array(0x229) - ,0x22A => array(0x22B) - ,0x22C => array(0x22D) - ,0x22E => array(0x22F) - ,0x230 => array(0x231) - ,0x232 => array(0x233) - ,0x345 => array(0x3B9) - ,0x37A => array(0x20, 0x3B9) - ,0x386 => array(0x3AC) - ,0x388 => array(0x3AD) - ,0x389 => array(0x3AE) - ,0x38A => array(0x3AF) - ,0x38C => array(0x3CC) - ,0x38E => array(0x3CD) - ,0x38F => array(0x3CE) - ,0x390 => array(0x3B9, 0x308, 0x301) - ,0x391 => array(0x3B1) - ,0x392 => array(0x3B2) - ,0x393 => array(0x3B3) - ,0x394 => array(0x3B4) - ,0x395 => array(0x3B5) - ,0x396 => array(0x3B6) - ,0x397 => array(0x3B7) - ,0x398 => array(0x3B8) - ,0x399 => array(0x3B9) - ,0x39A => array(0x3BA) - ,0x39B => array(0x3BB) - ,0x39C => array(0x3BC) - ,0x39D => array(0x3BD) - ,0x39E => array(0x3BE) - ,0x39F => array(0x3BF) - ,0x3A0 => array(0x3C0) - ,0x3A1 => array(0x3C1) - ,0x3A3 => array(0x3C3) - ,0x3A4 => array(0x3C4) - ,0x3A5 => array(0x3C5) - ,0x3A6 => array(0x3C6) - ,0x3A7 => array(0x3C7) - ,0x3A8 => array(0x3C8) - ,0x3A9 => array(0x3C9) - ,0x3AA => array(0x3CA) - ,0x3AB => array(0x3CB) - ,0x3B0 => array(0x3C5, 0x308, 0x301) - ,0x3C2 => array(0x3C3) - ,0x3D0 => array(0x3B2) - ,0x3D1 => array(0x3B8) - ,0x3D2 => array(0x3C5) - ,0x3D3 => array(0x3CD) - ,0x3D4 => array(0x3CB) - ,0x3D5 => array(0x3C6) - ,0x3D6 => array(0x3C0) - ,0x3D8 => array(0x3D9) - ,0x3DA => array(0x3DB) - ,0x3DC => array(0x3DD) - ,0x3DE => array(0x3DF) - ,0x3E0 => array(0x3E1) - ,0x3E2 => array(0x3E3) - ,0x3E4 => array(0x3E5) - ,0x3E6 => array(0x3E7) - ,0x3E8 => array(0x3E9) - ,0x3EA => array(0x3EB) - ,0x3EC => array(0x3ED) - ,0x3EE => array(0x3EF) - ,0x3F0 => array(0x3BA) - ,0x3F1 => array(0x3C1) - ,0x3F2 => array(0x3C3) - ,0x3F4 => array(0x3B8) - ,0x3F5 => array(0x3B5) - ,0x400 => array(0x450) - ,0x401 => array(0x451) - ,0x402 => array(0x452) - ,0x403 => array(0x453) - ,0x404 => array(0x454) - ,0x405 => array(0x455) - ,0x406 => array(0x456) - ,0x407 => array(0x457) - ,0x408 => array(0x458) - ,0x409 => array(0x459) - ,0x40A => array(0x45A) - ,0x40B => array(0x45B) - ,0x40C => array(0x45C) - ,0x40D => array(0x45D) - ,0x40E => array(0x45E) - ,0x40F => array(0x45F) - ,0x410 => array(0x430) - ,0x411 => array(0x431) - ,0x412 => array(0x432) - ,0x413 => array(0x433) - ,0x414 => array(0x434) - ,0x415 => array(0x435) - ,0x416 => array(0x436) - ,0x417 => array(0x437) - ,0x418 => array(0x438) - ,0x419 => array(0x439) - ,0x41A => array(0x43A) - ,0x41B => array(0x43B) - ,0x41C => array(0x43C) - ,0x41D => array(0x43D) - ,0x41E => array(0x43E) - ,0x41F => array(0x43F) - ,0x420 => array(0x440) - ,0x421 => array(0x441) - ,0x422 => array(0x442) - ,0x423 => array(0x443) - ,0x424 => array(0x444) - ,0x425 => array(0x445) - ,0x426 => array(0x446) - ,0x427 => array(0x447) - ,0x428 => array(0x448) - ,0x429 => array(0x449) - ,0x42A => array(0x44A) - ,0x42B => array(0x44B) - ,0x42C => array(0x44C) - ,0x42D => array(0x44D) - ,0x42E => array(0x44E) - ,0x42F => array(0x44F) - ,0x460 => array(0x461) - ,0x462 => array(0x463) - ,0x464 => array(0x465) - ,0x466 => array(0x467) - ,0x468 => array(0x469) - ,0x46A => array(0x46B) - ,0x46C => array(0x46D) - ,0x46E => array(0x46F) - ,0x470 => array(0x471) - ,0x472 => array(0x473) - ,0x474 => array(0x475) - ,0x476 => array(0x477) - ,0x478 => array(0x479) - ,0x47A => array(0x47B) - ,0x47C => array(0x47D) - ,0x47E => array(0x47F) - ,0x480 => array(0x481) - ,0x48A => array(0x48B) - ,0x48C => array(0x48D) - ,0x48E => array(0x48F) - ,0x490 => array(0x491) - ,0x492 => array(0x493) - ,0x494 => array(0x495) - ,0x496 => array(0x497) - ,0x498 => array(0x499) - ,0x49A => array(0x49B) - ,0x49C => array(0x49D) - ,0x49E => array(0x49F) - ,0x4A0 => array(0x4A1) - ,0x4A2 => array(0x4A3) - ,0x4A4 => array(0x4A5) - ,0x4A6 => array(0x4A7) - ,0x4A8 => array(0x4A9) - ,0x4AA => array(0x4AB) - ,0x4AC => array(0x4AD) - ,0x4AE => array(0x4AF) - ,0x4B0 => array(0x4B1) - ,0x4B2 => array(0x4B3) - ,0x4B4 => array(0x4B5) - ,0x4B6 => array(0x4B7) - ,0x4B8 => array(0x4B9) - ,0x4BA => array(0x4BB) - ,0x4BC => array(0x4BD) - ,0x4BE => array(0x4BF) - ,0x4C1 => array(0x4C2) - ,0x4C3 => array(0x4C4) - ,0x4C5 => array(0x4C6) - ,0x4C7 => array(0x4C8) - ,0x4C9 => array(0x4CA) - ,0x4CB => array(0x4CC) - ,0x4CD => array(0x4CE) - ,0x4D0 => array(0x4D1) - ,0x4D2 => array(0x4D3) - ,0x4D4 => array(0x4D5) - ,0x4D6 => array(0x4D7) - ,0x4D8 => array(0x4D9) - ,0x4DA => array(0x4DB) - ,0x4DC => array(0x4DD) - ,0x4DE => array(0x4DF) - ,0x4E0 => array(0x4E1) - ,0x4E2 => array(0x4E3) - ,0x4E4 => array(0x4E5) - ,0x4E6 => array(0x4E7) - ,0x4E8 => array(0x4E9) - ,0x4EA => array(0x4EB) - ,0x4EC => array(0x4ED) - ,0x4EE => array(0x4EF) - ,0x4F0 => array(0x4F1) - ,0x4F2 => array(0x4F3) - ,0x4F4 => array(0x4F5) - ,0x4F8 => array(0x4F9) - ,0x500 => array(0x501) - ,0x502 => array(0x503) - ,0x504 => array(0x505) - ,0x506 => array(0x507) - ,0x508 => array(0x509) - ,0x50A => array(0x50B) - ,0x50C => array(0x50D) - ,0x50E => array(0x50F) - ,0x531 => array(0x561) - ,0x532 => array(0x562) - ,0x533 => array(0x563) - ,0x534 => array(0x564) - ,0x535 => array(0x565) - ,0x536 => array(0x566) - ,0x537 => array(0x567) - ,0x538 => array(0x568) - ,0x539 => array(0x569) - ,0x53A => array(0x56A) - ,0x53B => array(0x56B) - ,0x53C => array(0x56C) - ,0x53D => array(0x56D) - ,0x53E => array(0x56E) - ,0x53F => array(0x56F) - ,0x540 => array(0x570) - ,0x541 => array(0x571) - ,0x542 => array(0x572) - ,0x543 => array(0x573) - ,0x544 => array(0x574) - ,0x545 => array(0x575) - ,0x546 => array(0x576) - ,0x547 => array(0x577) - ,0x548 => array(0x578) - ,0x549 => array(0x579) - ,0x54A => array(0x57A) - ,0x54B => array(0x57B) - ,0x54C => array(0x57C) - ,0x54D => array(0x57D) - ,0x54E => array(0x57E) - ,0x54F => array(0x57F) - ,0x550 => array(0x580) - ,0x551 => array(0x581) - ,0x552 => array(0x582) - ,0x553 => array(0x583) - ,0x554 => array(0x584) - ,0x555 => array(0x585) - ,0x556 => array(0x586) - ,0x587 => array(0x565, 0x582) - ,0xE33 => array(0xE4D, 0xE32) - ,0x1E00 => array(0x1E01) - ,0x1E02 => array(0x1E03) - ,0x1E04 => array(0x1E05) - ,0x1E06 => array(0x1E07) - ,0x1E08 => array(0x1E09) - ,0x1E0A => array(0x1E0B) - ,0x1E0C => array(0x1E0D) - ,0x1E0E => array(0x1E0F) - ,0x1E10 => array(0x1E11) - ,0x1E12 => array(0x1E13) - ,0x1E14 => array(0x1E15) - ,0x1E16 => array(0x1E17) - ,0x1E18 => array(0x1E19) - ,0x1E1A => array(0x1E1B) - ,0x1E1C => array(0x1E1D) - ,0x1E1E => array(0x1E1F) - ,0x1E20 => array(0x1E21) - ,0x1E22 => array(0x1E23) - ,0x1E24 => array(0x1E25) - ,0x1E26 => array(0x1E27) - ,0x1E28 => array(0x1E29) - ,0x1E2A => array(0x1E2B) - ,0x1E2C => array(0x1E2D) - ,0x1E2E => array(0x1E2F) - ,0x1E30 => array(0x1E31) - ,0x1E32 => array(0x1E33) - ,0x1E34 => array(0x1E35) - ,0x1E36 => array(0x1E37) - ,0x1E38 => array(0x1E39) - ,0x1E3A => array(0x1E3B) - ,0x1E3C => array(0x1E3D) - ,0x1E3E => array(0x1E3F) - ,0x1E40 => array(0x1E41) - ,0x1E42 => array(0x1E43) - ,0x1E44 => array(0x1E45) - ,0x1E46 => array(0x1E47) - ,0x1E48 => array(0x1E49) - ,0x1E4A => array(0x1E4B) - ,0x1E4C => array(0x1E4D) - ,0x1E4E => array(0x1E4F) - ,0x1E50 => array(0x1E51) - ,0x1E52 => array(0x1E53) - ,0x1E54 => array(0x1E55) - ,0x1E56 => array(0x1E57) - ,0x1E58 => array(0x1E59) - ,0x1E5A => array(0x1E5B) - ,0x1E5C => array(0x1E5D) - ,0x1E5E => array(0x1E5F) - ,0x1E60 => array(0x1E61) - ,0x1E62 => array(0x1E63) - ,0x1E64 => array(0x1E65) - ,0x1E66 => array(0x1E67) - ,0x1E68 => array(0x1E69) - ,0x1E6A => array(0x1E6B) - ,0x1E6C => array(0x1E6D) - ,0x1E6E => array(0x1E6F) - ,0x1E70 => array(0x1E71) - ,0x1E72 => array(0x1E73) - ,0x1E74 => array(0x1E75) - ,0x1E76 => array(0x1E77) - ,0x1E78 => array(0x1E79) - ,0x1E7A => array(0x1E7B) - ,0x1E7C => array(0x1E7D) - ,0x1E7E => array(0x1E7F) - ,0x1E80 => array(0x1E81) - ,0x1E82 => array(0x1E83) - ,0x1E84 => array(0x1E85) - ,0x1E86 => array(0x1E87) - ,0x1E88 => array(0x1E89) - ,0x1E8A => array(0x1E8B) - ,0x1E8C => array(0x1E8D) - ,0x1E8E => array(0x1E8F) - ,0x1E90 => array(0x1E91) - ,0x1E92 => array(0x1E93) - ,0x1E94 => array(0x1E95) - ,0x1E96 => array(0x68, 0x331) - ,0x1E97 => array(0x74, 0x308) - ,0x1E98 => array(0x77, 0x30A) - ,0x1E99 => array(0x79, 0x30A) - ,0x1E9A => array(0x61, 0x2BE) - ,0x1E9B => array(0x1E61) - ,0x1EA0 => array(0x1EA1) - ,0x1EA2 => array(0x1EA3) - ,0x1EA4 => array(0x1EA5) - ,0x1EA6 => array(0x1EA7) - ,0x1EA8 => array(0x1EA9) - ,0x1EAA => array(0x1EAB) - ,0x1EAC => array(0x1EAD) - ,0x1EAE => array(0x1EAF) - ,0x1EB0 => array(0x1EB1) - ,0x1EB2 => array(0x1EB3) - ,0x1EB4 => array(0x1EB5) - ,0x1EB6 => array(0x1EB7) - ,0x1EB8 => array(0x1EB9) - ,0x1EBA => array(0x1EBB) - ,0x1EBC => array(0x1EBD) - ,0x1EBE => array(0x1EBF) - ,0x1EC0 => array(0x1EC1) - ,0x1EC2 => array(0x1EC3) - ,0x1EC4 => array(0x1EC5) - ,0x1EC6 => array(0x1EC7) - ,0x1EC8 => array(0x1EC9) - ,0x1ECA => array(0x1ECB) - ,0x1ECC => array(0x1ECD) - ,0x1ECE => array(0x1ECF) - ,0x1ED0 => array(0x1ED1) - ,0x1ED2 => array(0x1ED3) - ,0x1ED4 => array(0x1ED5) - ,0x1ED6 => array(0x1ED7) - ,0x1ED8 => array(0x1ED9) - ,0x1EDA => array(0x1EDB) - ,0x1EDC => array(0x1EDD) - ,0x1EDE => array(0x1EDF) - ,0x1EE0 => array(0x1EE1) - ,0x1EE2 => array(0x1EE3) - ,0x1EE4 => array(0x1EE5) - ,0x1EE6 => array(0x1EE7) - ,0x1EE8 => array(0x1EE9) - ,0x1EEA => array(0x1EEB) - ,0x1EEC => array(0x1EED) - ,0x1EEE => array(0x1EEF) - ,0x1EF0 => array(0x1EF1) - ,0x1EF2 => array(0x1EF3) - ,0x1EF4 => array(0x1EF5) - ,0x1EF6 => array(0x1EF7) - ,0x1EF8 => array(0x1EF9) - ,0x1F08 => array(0x1F00) - ,0x1F09 => array(0x1F01) - ,0x1F0A => array(0x1F02) - ,0x1F0B => array(0x1F03) - ,0x1F0C => array(0x1F04) - ,0x1F0D => array(0x1F05) - ,0x1F0E => array(0x1F06) - ,0x1F0F => array(0x1F07) - ,0x1F18 => array(0x1F10) - ,0x1F19 => array(0x1F11) - ,0x1F1A => array(0x1F12) - ,0x1F1B => array(0x1F13) - ,0x1F1C => array(0x1F14) - ,0x1F1D => array(0x1F15) - ,0x1F28 => array(0x1F20) - ,0x1F29 => array(0x1F21) - ,0x1F2A => array(0x1F22) - ,0x1F2B => array(0x1F23) - ,0x1F2C => array(0x1F24) - ,0x1F2D => array(0x1F25) - ,0x1F2E => array(0x1F26) - ,0x1F2F => array(0x1F27) - ,0x1F38 => array(0x1F30) - ,0x1F39 => array(0x1F31) - ,0x1F3A => array(0x1F32) - ,0x1F3B => array(0x1F33) - ,0x1F3C => array(0x1F34) - ,0x1F3D => array(0x1F35) - ,0x1F3E => array(0x1F36) - ,0x1F3F => array(0x1F37) - ,0x1F48 => array(0x1F40) - ,0x1F49 => array(0x1F41) - ,0x1F4A => array(0x1F42) - ,0x1F4B => array(0x1F43) - ,0x1F4C => array(0x1F44) - ,0x1F4D => array(0x1F45) - ,0x1F50 => array(0x3C5, 0x313) - ,0x1F52 => array(0x3C5, 0x313, 0x300) - ,0x1F54 => array(0x3C5, 0x313, 0x301) - ,0x1F56 => array(0x3C5, 0x313, 0x342) - ,0x1F59 => array(0x1F51) - ,0x1F5B => array(0x1F53) - ,0x1F5D => array(0x1F55) - ,0x1F5F => array(0x1F57) - ,0x1F68 => array(0x1F60) - ,0x1F69 => array(0x1F61) - ,0x1F6A => array(0x1F62) - ,0x1F6B => array(0x1F63) - ,0x1F6C => array(0x1F64) - ,0x1F6D => array(0x1F65) - ,0x1F6E => array(0x1F66) - ,0x1F6F => array(0x1F67) - ,0x1F80 => array(0x1F00, 0x3B9) - ,0x1F81 => array(0x1F01, 0x3B9) - ,0x1F82 => array(0x1F02, 0x3B9) - ,0x1F83 => array(0x1F03, 0x3B9) - ,0x1F84 => array(0x1F04, 0x3B9) - ,0x1F85 => array(0x1F05, 0x3B9) - ,0x1F86 => array(0x1F06, 0x3B9) - ,0x1F87 => array(0x1F07, 0x3B9) - ,0x1F88 => array(0x1F00, 0x3B9) - ,0x1F89 => array(0x1F01, 0x3B9) - ,0x1F8A => array(0x1F02, 0x3B9) - ,0x1F8B => array(0x1F03, 0x3B9) - ,0x1F8C => array(0x1F04, 0x3B9) - ,0x1F8D => array(0x1F05, 0x3B9) - ,0x1F8E => array(0x1F06, 0x3B9) - ,0x1F8F => array(0x1F07, 0x3B9) - ,0x1F90 => array(0x1F20, 0x3B9) - ,0x1F91 => array(0x1F21, 0x3B9) - ,0x1F92 => array(0x1F22, 0x3B9) - ,0x1F93 => array(0x1F23, 0x3B9) - ,0x1F94 => array(0x1F24, 0x3B9) - ,0x1F95 => array(0x1F25, 0x3B9) - ,0x1F96 => array(0x1F26, 0x3B9) - ,0x1F97 => array(0x1F27, 0x3B9) - ,0x1F98 => array(0x1F20, 0x3B9) - ,0x1F99 => array(0x1F21, 0x3B9) - ,0x1F9A => array(0x1F22, 0x3B9) - ,0x1F9B => array(0x1F23, 0x3B9) - ,0x1F9C => array(0x1F24, 0x3B9) - ,0x1F9D => array(0x1F25, 0x3B9) - ,0x1F9E => array(0x1F26, 0x3B9) - ,0x1F9F => array(0x1F27, 0x3B9) - ,0x1FA0 => array(0x1F60, 0x3B9) - ,0x1FA1 => array(0x1F61, 0x3B9) - ,0x1FA2 => array(0x1F62, 0x3B9) - ,0x1FA3 => array(0x1F63, 0x3B9) - ,0x1FA4 => array(0x1F64, 0x3B9) - ,0x1FA5 => array(0x1F65, 0x3B9) - ,0x1FA6 => array(0x1F66, 0x3B9) - ,0x1FA7 => array(0x1F67, 0x3B9) - ,0x1FA8 => array(0x1F60, 0x3B9) - ,0x1FA9 => array(0x1F61, 0x3B9) - ,0x1FAA => array(0x1F62, 0x3B9) - ,0x1FAB => array(0x1F63, 0x3B9) - ,0x1FAC => array(0x1F64, 0x3B9) - ,0x1FAD => array(0x1F65, 0x3B9) - ,0x1FAE => array(0x1F66, 0x3B9) - ,0x1FAF => array(0x1F67, 0x3B9) - ,0x1FB2 => array(0x1F70, 0x3B9) - ,0x1FB3 => array(0x3B1, 0x3B9) - ,0x1FB4 => array(0x3AC, 0x3B9) - ,0x1FB6 => array(0x3B1, 0x342) - ,0x1FB7 => array(0x3B1, 0x342, 0x3B9) - ,0x1FB8 => array(0x1FB0) - ,0x1FB9 => array(0x1FB1) - ,0x1FBA => array(0x1F70) - ,0x1FBB => array(0x1F71) - ,0x1FBC => array(0x3B1, 0x3B9) - ,0x1FBE => array(0x3B9) - ,0x1FC2 => array(0x1F74, 0x3B9) - ,0x1FC3 => array(0x3B7, 0x3B9) - ,0x1FC4 => array(0x3AE, 0x3B9) - ,0x1FC6 => array(0x3B7, 0x342) - ,0x1FC7 => array(0x3B7, 0x342, 0x3B9) - ,0x1FC8 => array(0x1F72) - ,0x1FC9 => array(0x1F73) - ,0x1FCA => array(0x1F74) - ,0x1FCB => array(0x1F75) - ,0x1FCC => array(0x3B7, 0x3B9) - ,0x1FD2 => array(0x3B9, 0x308, 0x300) - ,0x1FD3 => array(0x3B9, 0x308, 0x301) - ,0x1FD6 => array(0x3B9, 0x342) - ,0x1FD7 => array(0x3B9, 0x308, 0x342) - ,0x1FD8 => array(0x1FD0) - ,0x1FD9 => array(0x1FD1) - ,0x1FDA => array(0x1F76) - ,0x1FDB => array(0x1F77) - ,0x1FE2 => array(0x3C5, 0x308, 0x300) - ,0x1FE3 => array(0x3C5, 0x308, 0x301) - ,0x1FE4 => array(0x3C1, 0x313) - ,0x1FE6 => array(0x3C5, 0x342) - ,0x1FE7 => array(0x3C5, 0x308, 0x342) - ,0x1FE8 => array(0x1FE0) - ,0x1FE9 => array(0x1FE1) - ,0x1FEA => array(0x1F7A) - ,0x1FEB => array(0x1F7B) - ,0x1FEC => array(0x1FE5) - ,0x1FF2 => array(0x1F7C, 0x3B9) - ,0x1FF3 => array(0x3C9, 0x3B9) - ,0x1FF4 => array(0x3CE, 0x3B9) - ,0x1FF6 => array(0x3C9, 0x342) - ,0x1FF7 => array(0x3C9, 0x342, 0x3B9) - ,0x1FF8 => array(0x1F78) - ,0x1FF9 => array(0x1F79) - ,0x1FFA => array(0x1F7C) - ,0x1FFB => array(0x1F7D) - ,0x1FFC => array(0x3C9, 0x3B9) - ,0x20A8 => array(0x72, 0x73) - ,0x2102 => array(0x63) - ,0x2103 => array(0xB0, 0x63) - ,0x2107 => array(0x25B) - ,0x2109 => array(0xB0, 0x66) - ,0x210B => array(0x68) - ,0x210C => array(0x68) - ,0x210D => array(0x68) - ,0x2110 => array(0x69) - ,0x2111 => array(0x69) - ,0x2112 => array(0x6C) - ,0x2115 => array(0x6E) - ,0x2116 => array(0x6E, 0x6F) - ,0x2119 => array(0x70) - ,0x211A => array(0x71) - ,0x211B => array(0x72) - ,0x211C => array(0x72) - ,0x211D => array(0x72) - ,0x2120 => array(0x73, 0x6D) - ,0x2121 => array(0x74, 0x65, 0x6C) - ,0x2122 => array(0x74, 0x6D) - ,0x2124 => array(0x7A) - ,0x2126 => array(0x3C9) - ,0x2128 => array(0x7A) - ,0x212A => array(0x6B) - ,0x212B => array(0xE5) - ,0x212C => array(0x62) - ,0x212D => array(0x63) - ,0x2130 => array(0x65) - ,0x2131 => array(0x66) - ,0x2133 => array(0x6D) - ,0x213E => array(0x3B3) - ,0x213F => array(0x3C0) - ,0x2145 => array(0x64) - ,0x2160 => array(0x2170) - ,0x2161 => array(0x2171) - ,0x2162 => array(0x2172) - ,0x2163 => array(0x2173) - ,0x2164 => array(0x2174) - ,0x2165 => array(0x2175) - ,0x2166 => array(0x2176) - ,0x2167 => array(0x2177) - ,0x2168 => array(0x2178) - ,0x2169 => array(0x2179) - ,0x216A => array(0x217A) - ,0x216B => array(0x217B) - ,0x216C => array(0x217C) - ,0x216D => array(0x217D) - ,0x216E => array(0x217E) - ,0x216F => array(0x217F) - ,0x24B6 => array(0x24D0) - ,0x24B7 => array(0x24D1) - ,0x24B8 => array(0x24D2) - ,0x24B9 => array(0x24D3) - ,0x24BA => array(0x24D4) - ,0x24BB => array(0x24D5) - ,0x24BC => array(0x24D6) - ,0x24BD => array(0x24D7) - ,0x24BE => array(0x24D8) - ,0x24BF => array(0x24D9) - ,0x24C0 => array(0x24DA) - ,0x24C1 => array(0x24DB) - ,0x24C2 => array(0x24DC) - ,0x24C3 => array(0x24DD) - ,0x24C4 => array(0x24DE) - ,0x24C5 => array(0x24DF) - ,0x24C6 => array(0x24E0) - ,0x24C7 => array(0x24E1) - ,0x24C8 => array(0x24E2) - ,0x24C9 => array(0x24E3) - ,0x24CA => array(0x24E4) - ,0x24CB => array(0x24E5) - ,0x24CC => array(0x24E6) - ,0x24CD => array(0x24E7) - ,0x24CE => array(0x24E8) - ,0x24CF => array(0x24E9) - ,0x3371 => array(0x68, 0x70, 0x61) - ,0x3373 => array(0x61, 0x75) - ,0x3375 => array(0x6F, 0x76) - ,0x3380 => array(0x70, 0x61) - ,0x3381 => array(0x6E, 0x61) - ,0x3382 => array(0x3BC, 0x61) - ,0x3383 => array(0x6D, 0x61) - ,0x3384 => array(0x6B, 0x61) - ,0x3385 => array(0x6B, 0x62) - ,0x3386 => array(0x6D, 0x62) - ,0x3387 => array(0x67, 0x62) - ,0x338A => array(0x70, 0x66) - ,0x338B => array(0x6E, 0x66) - ,0x338C => array(0x3BC, 0x66) - ,0x3390 => array(0x68, 0x7A) - ,0x3391 => array(0x6B, 0x68, 0x7A) - ,0x3392 => array(0x6D, 0x68, 0x7A) - ,0x3393 => array(0x67, 0x68, 0x7A) - ,0x3394 => array(0x74, 0x68, 0x7A) - ,0x33A9 => array(0x70, 0x61) - ,0x33AA => array(0x6B, 0x70, 0x61) - ,0x33AB => array(0x6D, 0x70, 0x61) - ,0x33AC => array(0x67, 0x70, 0x61) - ,0x33B4 => array(0x70, 0x76) - ,0x33B5 => array(0x6E, 0x76) - ,0x33B6 => array(0x3BC, 0x76) - ,0x33B7 => array(0x6D, 0x76) - ,0x33B8 => array(0x6B, 0x76) - ,0x33B9 => array(0x6D, 0x76) - ,0x33BA => array(0x70, 0x77) - ,0x33BB => array(0x6E, 0x77) - ,0x33BC => array(0x3BC, 0x77) - ,0x33BD => array(0x6D, 0x77) - ,0x33BE => array(0x6B, 0x77) - ,0x33BF => array(0x6D, 0x77) - ,0x33C0 => array(0x6B, 0x3C9) - ,0x33C1 => array(0x6D, 0x3C9) /* - ,0x33C2 => array(0x61, 0x2E, 0x6D, 0x2E) */ - ,0x33C3 => array(0x62, 0x71) - ,0x33C6 => array(0x63, 0x2215, 0x6B, 0x67) - ,0x33C7 => array(0x63, 0x6F, 0x2E) - ,0x33C8 => array(0x64, 0x62) - ,0x33C9 => array(0x67, 0x79) - ,0x33CB => array(0x68, 0x70) - ,0x33CD => array(0x6B, 0x6B) - ,0x33CE => array(0x6B, 0x6D) - ,0x33D7 => array(0x70, 0x68) - ,0x33D9 => array(0x70, 0x70, 0x6D) - ,0x33DA => array(0x70, 0x72) - ,0x33DC => array(0x73, 0x76) - ,0x33DD => array(0x77, 0x62) - ,0xFB00 => array(0x66, 0x66) - ,0xFB01 => array(0x66, 0x69) - ,0xFB02 => array(0x66, 0x6C) - ,0xFB03 => array(0x66, 0x66, 0x69) - ,0xFB04 => array(0x66, 0x66, 0x6C) - ,0xFB05 => array(0x73, 0x74) - ,0xFB06 => array(0x73, 0x74) - ,0xFB13 => array(0x574, 0x576) - ,0xFB14 => array(0x574, 0x565) - ,0xFB15 => array(0x574, 0x56B) - ,0xFB16 => array(0x57E, 0x576) - ,0xFB17 => array(0x574, 0x56D) - ,0xFF21 => array(0xFF41) - ,0xFF22 => array(0xFF42) - ,0xFF23 => array(0xFF43) - ,0xFF24 => array(0xFF44) - ,0xFF25 => array(0xFF45) - ,0xFF26 => array(0xFF46) - ,0xFF27 => array(0xFF47) - ,0xFF28 => array(0xFF48) - ,0xFF29 => array(0xFF49) - ,0xFF2A => array(0xFF4A) - ,0xFF2B => array(0xFF4B) - ,0xFF2C => array(0xFF4C) - ,0xFF2D => array(0xFF4D) - ,0xFF2E => array(0xFF4E) - ,0xFF2F => array(0xFF4F) - ,0xFF30 => array(0xFF50) - ,0xFF31 => array(0xFF51) - ,0xFF32 => array(0xFF52) - ,0xFF33 => array(0xFF53) - ,0xFF34 => array(0xFF54) - ,0xFF35 => array(0xFF55) - ,0xFF36 => array(0xFF56) - ,0xFF37 => array(0xFF57) - ,0xFF38 => array(0xFF58) - ,0xFF39 => array(0xFF59) - ,0xFF3A => array(0xFF5A) - ,0x10400 => array(0x10428) - ,0x10401 => array(0x10429) - ,0x10402 => array(0x1042A) - ,0x10403 => array(0x1042B) - ,0x10404 => array(0x1042C) - ,0x10405 => array(0x1042D) - ,0x10406 => array(0x1042E) - ,0x10407 => array(0x1042F) - ,0x10408 => array(0x10430) - ,0x10409 => array(0x10431) - ,0x1040A => array(0x10432) - ,0x1040B => array(0x10433) - ,0x1040C => array(0x10434) - ,0x1040D => array(0x10435) - ,0x1040E => array(0x10436) - ,0x1040F => array(0x10437) - ,0x10410 => array(0x10438) - ,0x10411 => array(0x10439) - ,0x10412 => array(0x1043A) - ,0x10413 => array(0x1043B) - ,0x10414 => array(0x1043C) - ,0x10415 => array(0x1043D) - ,0x10416 => array(0x1043E) - ,0x10417 => array(0x1043F) - ,0x10418 => array(0x10440) - ,0x10419 => array(0x10441) - ,0x1041A => array(0x10442) - ,0x1041B => array(0x10443) - ,0x1041C => array(0x10444) - ,0x1041D => array(0x10445) - ,0x1041E => array(0x10446) - ,0x1041F => array(0x10447) - ,0x10420 => array(0x10448) - ,0x10421 => array(0x10449) - ,0x10422 => array(0x1044A) - ,0x10423 => array(0x1044B) - ,0x10424 => array(0x1044C) - ,0x10425 => array(0x1044D) - ,0x1D400 => array(0x61) - ,0x1D401 => array(0x62) - ,0x1D402 => array(0x63) - ,0x1D403 => array(0x64) - ,0x1D404 => array(0x65) - ,0x1D405 => array(0x66) - ,0x1D406 => array(0x67) - ,0x1D407 => array(0x68) - ,0x1D408 => array(0x69) - ,0x1D409 => array(0x6A) - ,0x1D40A => array(0x6B) - ,0x1D40B => array(0x6C) - ,0x1D40C => array(0x6D) - ,0x1D40D => array(0x6E) - ,0x1D40E => array(0x6F) - ,0x1D40F => array(0x70) - ,0x1D410 => array(0x71) - ,0x1D411 => array(0x72) - ,0x1D412 => array(0x73) - ,0x1D413 => array(0x74) - ,0x1D414 => array(0x75) - ,0x1D415 => array(0x76) - ,0x1D416 => array(0x77) - ,0x1D417 => array(0x78) - ,0x1D418 => array(0x79) - ,0x1D419 => array(0x7A) - ,0x1D434 => array(0x61) - ,0x1D435 => array(0x62) - ,0x1D436 => array(0x63) - ,0x1D437 => array(0x64) - ,0x1D438 => array(0x65) - ,0x1D439 => array(0x66) - ,0x1D43A => array(0x67) - ,0x1D43B => array(0x68) - ,0x1D43C => array(0x69) - ,0x1D43D => array(0x6A) - ,0x1D43E => array(0x6B) - ,0x1D43F => array(0x6C) - ,0x1D440 => array(0x6D) - ,0x1D441 => array(0x6E) - ,0x1D442 => array(0x6F) - ,0x1D443 => array(0x70) - ,0x1D444 => array(0x71) - ,0x1D445 => array(0x72) - ,0x1D446 => array(0x73) - ,0x1D447 => array(0x74) - ,0x1D448 => array(0x75) - ,0x1D449 => array(0x76) - ,0x1D44A => array(0x77) - ,0x1D44B => array(0x78) - ,0x1D44C => array(0x79) - ,0x1D44D => array(0x7A) - ,0x1D468 => array(0x61) - ,0x1D469 => array(0x62) - ,0x1D46A => array(0x63) - ,0x1D46B => array(0x64) - ,0x1D46C => array(0x65) - ,0x1D46D => array(0x66) - ,0x1D46E => array(0x67) - ,0x1D46F => array(0x68) - ,0x1D470 => array(0x69) - ,0x1D471 => array(0x6A) - ,0x1D472 => array(0x6B) - ,0x1D473 => array(0x6C) - ,0x1D474 => array(0x6D) - ,0x1D475 => array(0x6E) - ,0x1D476 => array(0x6F) - ,0x1D477 => array(0x70) - ,0x1D478 => array(0x71) - ,0x1D479 => array(0x72) - ,0x1D47A => array(0x73) - ,0x1D47B => array(0x74) - ,0x1D47C => array(0x75) - ,0x1D47D => array(0x76) - ,0x1D47E => array(0x77) - ,0x1D47F => array(0x78) - ,0x1D480 => array(0x79) - ,0x1D481 => array(0x7A) - ,0x1D49C => array(0x61) - ,0x1D49E => array(0x63) - ,0x1D49F => array(0x64) - ,0x1D4A2 => array(0x67) - ,0x1D4A5 => array(0x6A) - ,0x1D4A6 => array(0x6B) - ,0x1D4A9 => array(0x6E) - ,0x1D4AA => array(0x6F) - ,0x1D4AB => array(0x70) - ,0x1D4AC => array(0x71) - ,0x1D4AE => array(0x73) - ,0x1D4AF => array(0x74) - ,0x1D4B0 => array(0x75) - ,0x1D4B1 => array(0x76) - ,0x1D4B2 => array(0x77) - ,0x1D4B3 => array(0x78) - ,0x1D4B4 => array(0x79) - ,0x1D4B5 => array(0x7A) - ,0x1D4D0 => array(0x61) - ,0x1D4D1 => array(0x62) - ,0x1D4D2 => array(0x63) - ,0x1D4D3 => array(0x64) - ,0x1D4D4 => array(0x65) - ,0x1D4D5 => array(0x66) - ,0x1D4D6 => array(0x67) - ,0x1D4D7 => array(0x68) - ,0x1D4D8 => array(0x69) - ,0x1D4D9 => array(0x6A) - ,0x1D4DA => array(0x6B) - ,0x1D4DB => array(0x6C) - ,0x1D4DC => array(0x6D) - ,0x1D4DD => array(0x6E) - ,0x1D4DE => array(0x6F) - ,0x1D4DF => array(0x70) - ,0x1D4E0 => array(0x71) - ,0x1D4E1 => array(0x72) - ,0x1D4E2 => array(0x73) - ,0x1D4E3 => array(0x74) - ,0x1D4E4 => array(0x75) - ,0x1D4E5 => array(0x76) - ,0x1D4E6 => array(0x77) - ,0x1D4E7 => array(0x78) - ,0x1D4E8 => array(0x79) - ,0x1D4E9 => array(0x7A) - ,0x1D504 => array(0x61) - ,0x1D505 => array(0x62) - ,0x1D507 => array(0x64) - ,0x1D508 => array(0x65) - ,0x1D509 => array(0x66) - ,0x1D50A => array(0x67) - ,0x1D50D => array(0x6A) - ,0x1D50E => array(0x6B) - ,0x1D50F => array(0x6C) - ,0x1D510 => array(0x6D) - ,0x1D511 => array(0x6E) - ,0x1D512 => array(0x6F) - ,0x1D513 => array(0x70) - ,0x1D514 => array(0x71) - ,0x1D516 => array(0x73) - ,0x1D517 => array(0x74) - ,0x1D518 => array(0x75) - ,0x1D519 => array(0x76) - ,0x1D51A => array(0x77) - ,0x1D51B => array(0x78) - ,0x1D51C => array(0x79) - ,0x1D538 => array(0x61) - ,0x1D539 => array(0x62) - ,0x1D53B => array(0x64) - ,0x1D53C => array(0x65) - ,0x1D53D => array(0x66) - ,0x1D53E => array(0x67) - ,0x1D540 => array(0x69) - ,0x1D541 => array(0x6A) - ,0x1D542 => array(0x6B) - ,0x1D543 => array(0x6C) - ,0x1D544 => array(0x6D) - ,0x1D546 => array(0x6F) - ,0x1D54A => array(0x73) - ,0x1D54B => array(0x74) - ,0x1D54C => array(0x75) - ,0x1D54D => array(0x76) - ,0x1D54E => array(0x77) - ,0x1D54F => array(0x78) - ,0x1D550 => array(0x79) - ,0x1D56C => array(0x61) - ,0x1D56D => array(0x62) - ,0x1D56E => array(0x63) - ,0x1D56F => array(0x64) - ,0x1D570 => array(0x65) - ,0x1D571 => array(0x66) - ,0x1D572 => array(0x67) - ,0x1D573 => array(0x68) - ,0x1D574 => array(0x69) - ,0x1D575 => array(0x6A) - ,0x1D576 => array(0x6B) - ,0x1D577 => array(0x6C) - ,0x1D578 => array(0x6D) - ,0x1D579 => array(0x6E) - ,0x1D57A => array(0x6F) - ,0x1D57B => array(0x70) - ,0x1D57C => array(0x71) - ,0x1D57D => array(0x72) - ,0x1D57E => array(0x73) - ,0x1D57F => array(0x74) - ,0x1D580 => array(0x75) - ,0x1D581 => array(0x76) - ,0x1D582 => array(0x77) - ,0x1D583 => array(0x78) - ,0x1D584 => array(0x79) - ,0x1D585 => array(0x7A) - ,0x1D5A0 => array(0x61) - ,0x1D5A1 => array(0x62) - ,0x1D5A2 => array(0x63) - ,0x1D5A3 => array(0x64) - ,0x1D5A4 => array(0x65) - ,0x1D5A5 => array(0x66) - ,0x1D5A6 => array(0x67) - ,0x1D5A7 => array(0x68) - ,0x1D5A8 => array(0x69) - ,0x1D5A9 => array(0x6A) - ,0x1D5AA => array(0x6B) - ,0x1D5AB => array(0x6C) - ,0x1D5AC => array(0x6D) - ,0x1D5AD => array(0x6E) - ,0x1D5AE => array(0x6F) - ,0x1D5AF => array(0x70) - ,0x1D5B0 => array(0x71) - ,0x1D5B1 => array(0x72) - ,0x1D5B2 => array(0x73) - ,0x1D5B3 => array(0x74) - ,0x1D5B4 => array(0x75) - ,0x1D5B5 => array(0x76) - ,0x1D5B6 => array(0x77) - ,0x1D5B7 => array(0x78) - ,0x1D5B8 => array(0x79) - ,0x1D5B9 => array(0x7A) - ,0x1D5D4 => array(0x61) - ,0x1D5D5 => array(0x62) - ,0x1D5D6 => array(0x63) - ,0x1D5D7 => array(0x64) - ,0x1D5D8 => array(0x65) - ,0x1D5D9 => array(0x66) - ,0x1D5DA => array(0x67) - ,0x1D5DB => array(0x68) - ,0x1D5DC => array(0x69) - ,0x1D5DD => array(0x6A) - ,0x1D5DE => array(0x6B) - ,0x1D5DF => array(0x6C) - ,0x1D5E0 => array(0x6D) - ,0x1D5E1 => array(0x6E) - ,0x1D5E2 => array(0x6F) - ,0x1D5E3 => array(0x70) - ,0x1D5E4 => array(0x71) - ,0x1D5E5 => array(0x72) - ,0x1D5E6 => array(0x73) - ,0x1D5E7 => array(0x74) - ,0x1D5E8 => array(0x75) - ,0x1D5E9 => array(0x76) - ,0x1D5EA => array(0x77) - ,0x1D5EB => array(0x78) - ,0x1D5EC => array(0x79) - ,0x1D5ED => array(0x7A) - ,0x1D608 => array(0x61) - ,0x1D609 => array(0x62) - ,0x1D60A => array(0x63) - ,0x1D60B => array(0x64) - ,0x1D60C => array(0x65) - ,0x1D60D => array(0x66) - ,0x1D60E => array(0x67) - ,0x1D60F => array(0x68) - ,0x1D610 => array(0x69) - ,0x1D611 => array(0x6A) - ,0x1D612 => array(0x6B) - ,0x1D613 => array(0x6C) - ,0x1D614 => array(0x6D) - ,0x1D615 => array(0x6E) - ,0x1D616 => array(0x6F) - ,0x1D617 => array(0x70) - ,0x1D618 => array(0x71) - ,0x1D619 => array(0x72) - ,0x1D61A => array(0x73) - ,0x1D61B => array(0x74) - ,0x1D61C => array(0x75) - ,0x1D61D => array(0x76) - ,0x1D61E => array(0x77) - ,0x1D61F => array(0x78) - ,0x1D620 => array(0x79) - ,0x1D621 => array(0x7A) - ,0x1D63C => array(0x61) - ,0x1D63D => array(0x62) - ,0x1D63E => array(0x63) - ,0x1D63F => array(0x64) - ,0x1D640 => array(0x65) - ,0x1D641 => array(0x66) - ,0x1D642 => array(0x67) - ,0x1D643 => array(0x68) - ,0x1D644 => array(0x69) - ,0x1D645 => array(0x6A) - ,0x1D646 => array(0x6B) - ,0x1D647 => array(0x6C) - ,0x1D648 => array(0x6D) - ,0x1D649 => array(0x6E) - ,0x1D64A => array(0x6F) - ,0x1D64B => array(0x70) - ,0x1D64C => array(0x71) - ,0x1D64D => array(0x72) - ,0x1D64E => array(0x73) - ,0x1D64F => array(0x74) - ,0x1D650 => array(0x75) - ,0x1D651 => array(0x76) - ,0x1D652 => array(0x77) - ,0x1D653 => array(0x78) - ,0x1D654 => array(0x79) - ,0x1D655 => array(0x7A) - ,0x1D670 => array(0x61) - ,0x1D671 => array(0x62) - ,0x1D672 => array(0x63) - ,0x1D673 => array(0x64) - ,0x1D674 => array(0x65) - ,0x1D675 => array(0x66) - ,0x1D676 => array(0x67) - ,0x1D677 => array(0x68) - ,0x1D678 => array(0x69) - ,0x1D679 => array(0x6A) - ,0x1D67A => array(0x6B) - ,0x1D67B => array(0x6C) - ,0x1D67C => array(0x6D) - ,0x1D67D => array(0x6E) - ,0x1D67E => array(0x6F) - ,0x1D67F => array(0x70) - ,0x1D680 => array(0x71) - ,0x1D681 => array(0x72) - ,0x1D682 => array(0x73) - ,0x1D683 => array(0x74) - ,0x1D684 => array(0x75) - ,0x1D685 => array(0x76) - ,0x1D686 => array(0x77) - ,0x1D687 => array(0x78) - ,0x1D688 => array(0x79) - ,0x1D689 => array(0x7A) - ,0x1D6A8 => array(0x3B1) - ,0x1D6A9 => array(0x3B2) - ,0x1D6AA => array(0x3B3) - ,0x1D6AB => array(0x3B4) - ,0x1D6AC => array(0x3B5) - ,0x1D6AD => array(0x3B6) - ,0x1D6AE => array(0x3B7) - ,0x1D6AF => array(0x3B8) - ,0x1D6B0 => array(0x3B9) - ,0x1D6B1 => array(0x3BA) - ,0x1D6B2 => array(0x3BB) - ,0x1D6B3 => array(0x3BC) - ,0x1D6B4 => array(0x3BD) - ,0x1D6B5 => array(0x3BE) - ,0x1D6B6 => array(0x3BF) - ,0x1D6B7 => array(0x3C0) - ,0x1D6B8 => array(0x3C1) - ,0x1D6B9 => array(0x3B8) - ,0x1D6BA => array(0x3C3) - ,0x1D6BB => array(0x3C4) - ,0x1D6BC => array(0x3C5) - ,0x1D6BD => array(0x3C6) - ,0x1D6BE => array(0x3C7) - ,0x1D6BF => array(0x3C8) - ,0x1D6C0 => array(0x3C9) - ,0x1D6D3 => array(0x3C3) - ,0x1D6E2 => array(0x3B1) - ,0x1D6E3 => array(0x3B2) - ,0x1D6E4 => array(0x3B3) - ,0x1D6E5 => array(0x3B4) - ,0x1D6E6 => array(0x3B5) - ,0x1D6E7 => array(0x3B6) - ,0x1D6E8 => array(0x3B7) - ,0x1D6E9 => array(0x3B8) - ,0x1D6EA => array(0x3B9) - ,0x1D6EB => array(0x3BA) - ,0x1D6EC => array(0x3BB) - ,0x1D6ED => array(0x3BC) - ,0x1D6EE => array(0x3BD) - ,0x1D6EF => array(0x3BE) - ,0x1D6F0 => array(0x3BF) - ,0x1D6F1 => array(0x3C0) - ,0x1D6F2 => array(0x3C1) - ,0x1D6F3 => array(0x3B8) - ,0x1D6F4 => array(0x3C3) - ,0x1D6F5 => array(0x3C4) - ,0x1D6F6 => array(0x3C5) - ,0x1D6F7 => array(0x3C6) - ,0x1D6F8 => array(0x3C7) - ,0x1D6F9 => array(0x3C8) - ,0x1D6FA => array(0x3C9) - ,0x1D70D => array(0x3C3) - ,0x1D71C => array(0x3B1) - ,0x1D71D => array(0x3B2) - ,0x1D71E => array(0x3B3) - ,0x1D71F => array(0x3B4) - ,0x1D720 => array(0x3B5) - ,0x1D721 => array(0x3B6) - ,0x1D722 => array(0x3B7) - ,0x1D723 => array(0x3B8) - ,0x1D724 => array(0x3B9) - ,0x1D725 => array(0x3BA) - ,0x1D726 => array(0x3BB) - ,0x1D727 => array(0x3BC) - ,0x1D728 => array(0x3BD) - ,0x1D729 => array(0x3BE) - ,0x1D72A => array(0x3BF) - ,0x1D72B => array(0x3C0) - ,0x1D72C => array(0x3C1) - ,0x1D72D => array(0x3B8) - ,0x1D72E => array(0x3C3) - ,0x1D72F => array(0x3C4) - ,0x1D730 => array(0x3C5) - ,0x1D731 => array(0x3C6) - ,0x1D732 => array(0x3C7) - ,0x1D733 => array(0x3C8) - ,0x1D734 => array(0x3C9) - ,0x1D747 => array(0x3C3) - ,0x1D756 => array(0x3B1) - ,0x1D757 => array(0x3B2) - ,0x1D758 => array(0x3B3) - ,0x1D759 => array(0x3B4) - ,0x1D75A => array(0x3B5) - ,0x1D75B => array(0x3B6) - ,0x1D75C => array(0x3B7) - ,0x1D75D => array(0x3B8) - ,0x1D75E => array(0x3B9) - ,0x1D75F => array(0x3BA) - ,0x1D760 => array(0x3BB) - ,0x1D761 => array(0x3BC) - ,0x1D762 => array(0x3BD) - ,0x1D763 => array(0x3BE) - ,0x1D764 => array(0x3BF) - ,0x1D765 => array(0x3C0) - ,0x1D766 => array(0x3C1) - ,0x1D767 => array(0x3B8) - ,0x1D768 => array(0x3C3) - ,0x1D769 => array(0x3C4) - ,0x1D76A => array(0x3C5) - ,0x1D76B => array(0x3C6) - ,0x1D76C => array(0x3C7) - ,0x1D76D => array(0x3C8) - ,0x1D76E => array(0x3C9) - ,0x1D781 => array(0x3C3) - ,0x1D790 => array(0x3B1) - ,0x1D791 => array(0x3B2) - ,0x1D792 => array(0x3B3) - ,0x1D793 => array(0x3B4) - ,0x1D794 => array(0x3B5) - ,0x1D795 => array(0x3B6) - ,0x1D796 => array(0x3B7) - ,0x1D797 => array(0x3B8) - ,0x1D798 => array(0x3B9) - ,0x1D799 => array(0x3BA) - ,0x1D79A => array(0x3BB) - ,0x1D79B => array(0x3BC) - ,0x1D79C => array(0x3BD) - ,0x1D79D => array(0x3BE) - ,0x1D79E => array(0x3BF) - ,0x1D79F => array(0x3C0) - ,0x1D7A0 => array(0x3C1) - ,0x1D7A1 => array(0x3B8) - ,0x1D7A2 => array(0x3C3) - ,0x1D7A3 => array(0x3C4) - ,0x1D7A4 => array(0x3C5) - ,0x1D7A5 => array(0x3C6) - ,0x1D7A6 => array(0x3C7) - ,0x1D7A7 => array(0x3C8) - ,0x1D7A8 => array(0x3C9) - ,0x1D7BB => array(0x3C3) - ,0x3F9 => array(0x3C3) - ,0x1D2C => array(0x61) - ,0x1D2D => array(0xE6) - ,0x1D2E => array(0x62) - ,0x1D30 => array(0x64) - ,0x1D31 => array(0x65) - ,0x1D32 => array(0x1DD) - ,0x1D33 => array(0x67) - ,0x1D34 => array(0x68) - ,0x1D35 => array(0x69) - ,0x1D36 => array(0x6A) - ,0x1D37 => array(0x6B) - ,0x1D38 => array(0x6C) - ,0x1D39 => array(0x6D) - ,0x1D3A => array(0x6E) - ,0x1D3C => array(0x6F) - ,0x1D3D => array(0x223) - ,0x1D3E => array(0x70) - ,0x1D3F => array(0x72) - ,0x1D40 => array(0x74) - ,0x1D41 => array(0x75) - ,0x1D42 => array(0x77) - ,0x213B => array(0x66, 0x61, 0x78) - ,0x3250 => array(0x70, 0x74, 0x65) - ,0x32CC => array(0x68, 0x67) - ,0x32CE => array(0x65, 0x76) - ,0x32CF => array(0x6C, 0x74, 0x64) - ,0x337A => array(0x69, 0x75) - ,0x33DE => array(0x76, 0x2215, 0x6D) - ,0x33DF => array(0x61, 0x2215, 0x6D) - ) - ,'norm_combcls' => array - (0x334 => 1 - ,0x335 => 1 - ,0x336 => 1 - ,0x337 => 1 - ,0x338 => 1 - ,0x93C => 7 - ,0x9BC => 7 - ,0xA3C => 7 - ,0xABC => 7 - ,0xB3C => 7 - ,0xCBC => 7 - ,0x1037 => 7 - ,0x3099 => 8 - ,0x309A => 8 - ,0x94D => 9 - ,0x9CD => 9 - ,0xA4D => 9 - ,0xACD => 9 - ,0xB4D => 9 - ,0xBCD => 9 - ,0xC4D => 9 - ,0xCCD => 9 - ,0xD4D => 9 - ,0xDCA => 9 - ,0xE3A => 9 - ,0xF84 => 9 - ,0x1039 => 9 - ,0x1714 => 9 - ,0x1734 => 9 - ,0x17D2 => 9 - ,0x5B0 => 10 - ,0x5B1 => 11 - ,0x5B2 => 12 - ,0x5B3 => 13 - ,0x5B4 => 14 - ,0x5B5 => 15 - ,0x5B6 => 16 - ,0x5B7 => 17 - ,0x5B8 => 18 - ,0x5B9 => 19 - ,0x5BB => 20 - ,0x5Bc => 21 - ,0x5BD => 22 - ,0x5BF => 23 - ,0x5C1 => 24 - ,0x5C2 => 25 - ,0xFB1E => 26 - ,0x64B => 27 - ,0x64C => 28 - ,0x64D => 29 - ,0x64E => 30 - ,0x64F => 31 - ,0x650 => 32 - ,0x651 => 33 - ,0x652 => 34 - ,0x670 => 35 - ,0x711 => 36 - ,0xC55 => 84 - ,0xC56 => 91 - ,0xE38 => 103 - ,0xE39 => 103 - ,0xE48 => 107 - ,0xE49 => 107 - ,0xE4A => 107 - ,0xE4B => 107 - ,0xEB8 => 118 - ,0xEB9 => 118 - ,0xEC8 => 122 - ,0xEC9 => 122 - ,0xECA => 122 - ,0xECB => 122 - ,0xF71 => 129 - ,0xF72 => 130 - ,0xF7A => 130 - ,0xF7B => 130 - ,0xF7C => 130 - ,0xF7D => 130 - ,0xF80 => 130 - ,0xF74 => 132 - ,0x321 => 202 - ,0x322 => 202 - ,0x327 => 202 - ,0x328 => 202 - ,0x31B => 216 - ,0xF39 => 216 - ,0x1D165 => 216 - ,0x1D166 => 216 - ,0x1D16E => 216 - ,0x1D16F => 216 - ,0x1D170 => 216 - ,0x1D171 => 216 - ,0x1D172 => 216 - ,0x302A => 218 - ,0x316 => 220 - ,0x317 => 220 - ,0x318 => 220 - ,0x319 => 220 - ,0x31C => 220 - ,0x31D => 220 - ,0x31E => 220 - ,0x31F => 220 - ,0x320 => 220 - ,0x323 => 220 - ,0x324 => 220 - ,0x325 => 220 - ,0x326 => 220 - ,0x329 => 220 - ,0x32A => 220 - ,0x32B => 220 - ,0x32C => 220 - ,0x32D => 220 - ,0x32E => 220 - ,0x32F => 220 - ,0x330 => 220 - ,0x331 => 220 - ,0x332 => 220 - ,0x333 => 220 - ,0x339 => 220 - ,0x33A => 220 - ,0x33B => 220 - ,0x33C => 220 - ,0x347 => 220 - ,0x348 => 220 - ,0x349 => 220 - ,0x34D => 220 - ,0x34E => 220 - ,0x353 => 220 - ,0x354 => 220 - ,0x355 => 220 - ,0x356 => 220 - ,0x591 => 220 - ,0x596 => 220 - ,0x59B => 220 - ,0x5A3 => 220 - ,0x5A4 => 220 - ,0x5A5 => 220 - ,0x5A6 => 220 - ,0x5A7 => 220 - ,0x5AA => 220 - ,0x655 => 220 - ,0x656 => 220 - ,0x6E3 => 220 - ,0x6EA => 220 - ,0x6ED => 220 - ,0x731 => 220 - ,0x734 => 220 - ,0x737 => 220 - ,0x738 => 220 - ,0x739 => 220 - ,0x73B => 220 - ,0x73C => 220 - ,0x73E => 220 - ,0x742 => 220 - ,0x744 => 220 - ,0x746 => 220 - ,0x748 => 220 - ,0x952 => 220 - ,0xF18 => 220 - ,0xF19 => 220 - ,0xF35 => 220 - ,0xF37 => 220 - ,0xFC6 => 220 - ,0x193B => 220 - ,0x20E8 => 220 - ,0x1D17B => 220 - ,0x1D17C => 220 - ,0x1D17D => 220 - ,0x1D17E => 220 - ,0x1D17F => 220 - ,0x1D180 => 220 - ,0x1D181 => 220 - ,0x1D182 => 220 - ,0x1D18A => 220 - ,0x1D18B => 220 - ,0x59A => 222 - ,0x5AD => 222 - ,0x1929 => 222 - ,0x302D => 222 - ,0x302E => 224 - ,0x302F => 224 - ,0x1D16D => 226 - ,0x5AE => 228 - ,0x18A9 => 228 - ,0x302B => 228 - ,0x300 => 230 - ,0x301 => 230 - ,0x302 => 230 - ,0x303 => 230 - ,0x304 => 230 - ,0x305 => 230 - ,0x306 => 230 - ,0x307 => 230 - ,0x308 => 230 - ,0x309 => 230 - ,0x30A => 230 - ,0x30B => 230 - ,0x30C => 230 - ,0x30D => 230 - ,0x30E => 230 - ,0x30F => 230 - ,0x310 => 230 - ,0x311 => 230 - ,0x312 => 230 - ,0x313 => 230 - ,0x314 => 230 - ,0x33D => 230 - ,0x33E => 230 - ,0x33F => 230 - ,0x340 => 230 - ,0x341 => 230 - ,0x342 => 230 - ,0x343 => 230 - ,0x344 => 230 - ,0x346 => 230 - ,0x34A => 230 - ,0x34B => 230 - ,0x34C => 230 - ,0x350 => 230 - ,0x351 => 230 - ,0x352 => 230 - ,0x357 => 230 - ,0x363 => 230 - ,0x364 => 230 - ,0x365 => 230 - ,0x366 => 230 - ,0x367 => 230 - ,0x368 => 230 - ,0x369 => 230 - ,0x36A => 230 - ,0x36B => 230 - ,0x36C => 230 - ,0x36D => 230 - ,0x36E => 230 - ,0x36F => 230 - ,0x483 => 230 - ,0x484 => 230 - ,0x485 => 230 - ,0x486 => 230 - ,0x592 => 230 - ,0x593 => 230 - ,0x594 => 230 - ,0x595 => 230 - ,0x597 => 230 - ,0x598 => 230 - ,0x599 => 230 - ,0x59C => 230 - ,0x59D => 230 - ,0x59E => 230 - ,0x59F => 230 - ,0x5A0 => 230 - ,0x5A1 => 230 - ,0x5A8 => 230 - ,0x5A9 => 230 - ,0x5AB => 230 - ,0x5AC => 230 - ,0x5AF => 230 - ,0x5C4 => 230 - ,0x610 => 230 - ,0x611 => 230 - ,0x612 => 230 - ,0x613 => 230 - ,0x614 => 230 - ,0x615 => 230 - ,0x653 => 230 - ,0x654 => 230 - ,0x657 => 230 - ,0x658 => 230 - ,0x6D6 => 230 - ,0x6D7 => 230 - ,0x6D8 => 230 - ,0x6D9 => 230 - ,0x6DA => 230 - ,0x6DB => 230 - ,0x6DC => 230 - ,0x6DF => 230 - ,0x6E0 => 230 - ,0x6E1 => 230 - ,0x6E2 => 230 - ,0x6E4 => 230 - ,0x6E7 => 230 - ,0x6E8 => 230 - ,0x6EB => 230 - ,0x6EC => 230 - ,0x730 => 230 - ,0x732 => 230 - ,0x733 => 230 - ,0x735 => 230 - ,0x736 => 230 - ,0x73A => 230 - ,0x73D => 230 - ,0x73F => 230 - ,0x740 => 230 - ,0x741 => 230 - ,0x743 => 230 - ,0x745 => 230 - ,0x747 => 230 - ,0x749 => 230 - ,0x74A => 230 - ,0x951 => 230 - ,0x953 => 230 - ,0x954 => 230 - ,0xF82 => 230 - ,0xF83 => 230 - ,0xF86 => 230 - ,0xF87 => 230 - ,0x170D => 230 - ,0x193A => 230 - ,0x20D0 => 230 - ,0x20D1 => 230 - ,0x20D4 => 230 - ,0x20D5 => 230 - ,0x20D6 => 230 - ,0x20D7 => 230 - ,0x20DB => 230 - ,0x20DC => 230 - ,0x20E1 => 230 - ,0x20E7 => 230 - ,0x20E9 => 230 - ,0xFE20 => 230 - ,0xFE21 => 230 - ,0xFE22 => 230 - ,0xFE23 => 230 - ,0x1D185 => 230 - ,0x1D186 => 230 - ,0x1D187 => 230 - ,0x1D189 => 230 - ,0x1D188 => 230 - ,0x1D1AA => 230 - ,0x1D1AB => 230 - ,0x1D1AC => 230 - ,0x1D1AD => 230 - ,0x315 => 232 - ,0x31A => 232 - ,0x302C => 232 - ,0x35F => 233 - ,0x362 => 233 - ,0x35D => 234 - ,0x35E => 234 - ,0x360 => 234 - ,0x361 => 234 - ,0x345 => 240 - ) - ); -} -?> \ No newline at end of file diff --git a/src/Layout/Empty.php b/src/Layout/Empty.php new file mode 100644 index 0000000..a7f99b8 --- /dev/null +++ b/src/Layout/Empty.php @@ -0,0 +1,13 @@ +processor->execute($request); + return $text; + } +} diff --git a/src/Layout/Manager.php b/src/Layout/Manager.php index 5107e36..965207d 100644 --- a/src/Layout/Manager.php +++ b/src/Layout/Manager.php @@ -69,8 +69,7 @@ class Layout_Manager extends Filter_Filter if (call_user_func($condition[0], $request)) { $layout = $condition[1]; $view = $layout->execute($request); - - if ($view instanceof View_Composite) { + if (is_object($view)) { echo $view->render(); } else { echo $view; diff --git a/src/Layout/None.php b/src/Layout/None.php deleted file mode 100644 index ed02085..0000000 --- a/src/Layout/None.php +++ /dev/null @@ -1,11 +0,0 @@ -processor->execute($request); - } -} diff --git a/src/Mail.php b/src/Mail.php index c1de6fe..f27a0a8 100644 --- a/src/Mail.php +++ b/src/Mail.php @@ -200,9 +200,8 @@ class Mail { $result = mail($this->_to, $this->getSubject(), $this->getMessage(), $this->getHeader()); if(! $result) { - throw new Exception('Невозможно отправить почту'); -// require_once "core/path.php"; -// file_put_contents(Path::resolveFile("data/email/send.eml"), $this->eml()); + file_put_contents(Path::resolveFile("send.eml"), $this->eml()); + throw new Exception('Невозможно отправить почту'); } return $result; } diff --git a/src/Mapper/Factory.php b/src/Mapper/Factory.php deleted file mode 100644 index d3dbe87..0000000 --- a/src/Mapper/Factory.php +++ /dev/null @@ -1,28 +0,0 @@ -db = $db; - } - - /** - * Создает модель - * @param string $name - * @return model - */ - public function getModel ($name) - { - require_once 'core/mapper/mapper.php'; // ???? - - require_once (Shortcut::getUrl(self::$shortcut, $name)); - $modelName = $name . "Mapper"; - $model = new $modelName(); - $model->db = $this->db; - $model->factory = $this; - return $model; - } -} diff --git a/src/Mapper/Mapper.php b/src/Mapper/Mapper.php deleted file mode 100644 index 5ce07dd..0000000 --- a/src/Mapper/Mapper.php +++ /dev/null @@ -1,265 +0,0 @@ - DataMapper implements IDataList, IDataSave, IDataSort, IDataDelete ... - * - * @package core - */ -class DataMapper implements IDataList -{ - /* Хранить метаданные в статическом свойстве класса для ототбражения ?!, + Скрипт для генерации метаданных!! - */ - public $factory; - public $className; /* Класс на который будет отображаться строчка таблицы */ - public $filter = ""; /* */ - public $schema = array (); /* Соответствие между свойством обьекта и столбцом, добавить тип для записей !! */ - public $database; /* Таблица */ - public $index; /* Индексный столбец */ - public $db; /* Соединение с базой данных */ - public $reference = array (null, null); - - public function __construct () - { - } - - public function setRange ($stmt, $page, $size) - { - $stmt->setLimit ($size); - $stmt->setOffset (($page-1) * $size); - } - - public function listSQL (array $list) - { - return implode ($list, ","); - } - - /** - * Поиск строки в таблице по идентификатору - * @param $id Значение идентификатора - * @return Обьект класса $className - */ - public function findById ($id) - { - // Строки запроса преобразовать в методы (getSQLSelect ...) - // Query::from($this->database)->where ($this->index, "=", $id)->select(); - $stmt = $this->db->prepareStatement ("SELECT * FROM ".$this->database." WHERE ".$this->index." = ?"); - $stmt->setInt (1, $id); - $rs = $stmt->executeQuery (); - $rs->next (); - return $this->mapOne ($rs); - } - - /** - * Преобразует parseResult в обьект - */ - public /* private */ function mapOne ($rs) - { - $result = new $this->className (); - foreach ($this->schema as $key => $value) { - list($value) = $value; - $result->$value->setRes($rs, $key); - } - return $result; - } - - public /* private */ function mapAll ($rs) - { - $result = array (); - // Преобразование SQL в обьект - while ($rs->next ()) { - $result[] = $this->mapOne ($rs); - } - return $result; - } - - private function clean ($value) { - return strtolower(trim(iconv('utf-8', 'cp1251', $value))); - } - - /** - * Преобразует параметры формы в SQL запрос WHERE - * @param array $params - * @param array $schema - * @return string - */ - public function requestToSQL (Collection $request, array $schema) - { - $result = array (); - foreach ($schema as $key => $value) { - $param = $request->get ($key); - if ($param) { - array_push ($result, "lower (".$value.") LIKE '".$this->clean ($param)."%'"); - } - } - if (empty ($result)) return null; - return implode ($result, " AND "); - } - - /** - * Удаление строк из таблицы с заданными индексами - * @param $list array Массив идентефикаторов - */ - public function deleteList (array $list) - { - // Query::from($this->database)->where($this->index, "in", $list)->delete(); - $sql = "DELETE FROM " . $this->database . " WHERE " . $this->index . " IN (" . $this->listSQL ($list) . ")"; - return $this->db->executeQuery ($sql); - } - - public static function findKey (array $schema, $sort) - { - foreach ($schema as $key => $item) { - list($item) = $item; - if ($item == $sort) { - return $key; - } - } - return $sort; - } - - public function getOrder (Collection $request) - { - $order = ""; - $sort = $request->get('key'); - $desc = ($request->get('desc') == 0)? 'DESC' : 'ASC'; - if ($sort) { - $sort = self::findKey ($this->schema, $sort); - $order = " ORDER BY $sort $desc"; - } - return $order; - } - - /** - * Извлекает список записей из базы данных - */ - public function findAll (Collection $request, $id = null) - { - $name0 = $this->database; - $foreign = $this->reference[1]; - // Переписать используя Query !!! - if ($foreign && $id) { - $filter = ($this->filter)?$filter = " AND ".$this->filter: ""; - $sql = "SELECT t1.* FROM $name0 as t1 WHERE t1.$foreign = $id " . $filter.self::getOrder($request); - } else { - $filter = ($this->filter)?$filter = " WHERE " . $this->filter: ""; - $sql = "SELECT * FROM $name0 " . $filter . self::getOrder($request); - } - $stmt = $this->db->prepareStatement ($sql); - - $page = $request->get('page'); - $limit = $request->get('size'); - if ($page && $limit) { - $this->setRange($stmt, $page, $limit); - } - - return $this->mapAll($stmt->executeQuery()); - } - - public function getCount (Collection $request, $id) - { - $name0 = $this->database; - $foreign = $this->reference[1]; - // Переписать используя Query !!! - if ($foreign && $id) { - $filter = ($this->filter)?$filter = " AND " . $this->filter: ""; - $sql = "SELECT count(t1.*) as length FROM $name0 as t1 WHERE t1.$foreign = $id " . $filter; - } else { - $filter = ($this->filter)?$filter = " WHERE " . $this->filter: ""; - $sql = "SELECT count(*) as length FROM $name0 " . $filter; - } - $rs = $this->db->executeQuery($sql); - $rs->next(); - return $rs->getInt('length'); - } - - /** - * Добавление записи в базу данных - * @param $o Обьект для записи в базу данных - */ - public function saveTo (Model $o) - { - $keys = array (); - $values = array (); - foreach ($this->schema as $key => $value) { - list($value) = $value; - if ($key != $this->index) { - $keys[] = $key; - $values[] = "'".$o->$value."'"; - } - } - $stmt = $this->db->prepareStatement ("INSERT INTO ".$this->database." (".implode ($keys, ",").") VALUES (".implode ($values, ",").")"); - $stmt->executeQuery (); - } - - /** - * Обновляет запись в базе данных - * @param $o Обьект для обновления - */ - public function updateTo (Model $o) - { - $keys_values = array (); - foreach ($this->schema as $key => $value) { - list($value) = $value; - if ($key != $this->index && !($o->$value instanceof FKey)) { - $keys_values[] = $key." = '".$o->$value."'"; - } - } - // Для всех должен быть идентефикатор id - $stmt = $this->db->prepareStatement ("UPDATE ".$this->database." SET ".implode($keys_values, ",")." WHERE ".$this->index." = ".$o->id); - $stmt->executeQuery (); - } - - function saveDB (Model $o) - { - if ($o->id) { - $this->updateTo($o); - } else { - $this->saveTo($o); - } - } - - function getModel($name) - { - require_once 'core/Mapper/Factory.php'; - if (!$this->factory) { - $this->factory = new ModelFactory($this->db); - } - return $this->factory->getModel($name); - } -} - -/** - * - */ -class Model -{ - public function __construct () - { - foreach (get_class_vars (get_class ($this)) as $key => $value) { - $this->$key = new Primitive (); - } - } - // __get, __set методы. В метаданных хранится тип свойств, проверять при присваивании!! -} - -?> \ No newline at end of file diff --git a/src/Mapper/PathMapper.php b/src/Mapper/PathMapper.php deleted file mode 100644 index 2c70315..0000000 --- a/src/Mapper/PathMapper.php +++ /dev/null @@ -1,74 +0,0 @@ - $value) { - $target->$name = $array->get($name); - } - } - - function basePath () - { - if ( ! $this->base) $this->base = $this->getBasePath(); - return $this->base; - } - - function findAll (Collection $request, $id = null) - { - $this->reference = $id; - - $base = $this->basePath (); - $path = new Path($base); - $list = $path->getContent(); - - $result = array (); - $this->count = 0; - foreach ($list as $name) { - if (is_dir (Path::join($this->basePath (), $name)) - && $module = $this->findById ($name)) { - $this->count++; - $result [] = $module; - } - } - return $result; - } - - function findById ($name) - { - $file = Path::join($this->basePath(), $this->getSettingsFile ($name)); - if (file_exists($file)) { - $settings = new Settings($file); - $settings->read(); - return $this->settingsMap($name, $settings); - } - return null; - } - - /** - * Число папок - */ - function getCount () - { - return $this->count; - } - - /** - * Удаление списка папок - */ - function deleteList(array $list) - { - foreach ($list as $name) - Path::delete(Path::join($this->getBasePath(), $name)); - } -} - diff --git a/src/Markup/SimpleBBCode.php b/src/Markup/SimpleBBCode.php deleted file mode 100644 index b21a845..0000000 --- a/src/Markup/SimpleBBCode.php +++ /dev/null @@ -1,113 +0,0 @@ - 'strong','i' => 'em','u' => 'span style="text-decoration:underline"','quote' => 'blockquote','s' => 'span style="text-decoration: line-through"', 'list' => 'ul','\*' => 'li'); - //Tags that must be mapped to diffierent parts - var $mapped = array('url' => array('a','href',true),'img' => array('img','src',false)); - //Tags with atributes - var $tags_with_att = array('color' => array('font','color'),'size' => array('font','size'),'url' => array('a','href')); - //Gotta have smilies - var $smilies = array(':)' => 'smile.gif',':(' => 'frown.gif'); - //Config Variables - //Convert new line charactes to linebreaks? - var $convert_newlines = true; - //Parse For smilies? - var $parse_smilies = true; - //auto link urls(http and ftp), and email addresses? - var $auto_links = true; - //Internal Storage - var $_code = ''; - function __construct($new=true,$parse=true,$links=true){ - $this->convert_newlines = $new; - $this->parse_smilies = $parse; - $this->auto_links = $links; - } - function parse($code){ - $this->_code = $code; - $this->_strip_html(); - $this->_parse_tags(); - $this->_parse_mapped(); - $this->_parse_tags_with_att(); - $this->_parse_smilies(); - $this->_parse_links(); - $this->_convert_nl(); - return $this->_code; - } - function _strip_html(){ - $this->_code = strip_tags($this->_code); - } - function _convert_nl(){ - if($this->convert_newlines){ - $this->_code = nl2br($this->_code); - } - } - function _parse_tags(){ - foreach($this->tags as $old=>$new){ - $ex = explode(' ',$new); - $this->_code = preg_replace('/\['.$old.'\](.+?)\[\/'.$old.'\]/is','<'.$new.'>$1',$this->_code); - } - } - function _parse_mapped(){ - foreach($this->mapped as $tag=>$data){ - $reg = '/\['.$tag.'\](.+?)\[\/'.$tag.'\]/is'; - if($data[2]){ - $this->_code = preg_replace($reg,'<'.$data[0].' '.$data[1].'="$1">$1',$this->_code); - } - else{ - $this->_code = preg_replace($reg,'<'.$data[0].' '.$data[1].'="$1">',$this->_code); - } - } - } - function _parse_tags_with_att(){ - foreach($this->tags_with_att as $tag=>$data){ - $this->_code = preg_replace('/\['.$tag.'=(.+?)\](.+?)\[\/'.$tag.'\]/is','<'.$data[0].' '.$data[1].'="$1">$2',$this->_code); - } - } - function _parse_smilies(){ - if($this->parse_smilies){ - foreach($this->smilies as $s=>$im){ - $this->_code = str_replace($s,'',$this->_code); - } - } - } - function _parse_links(){ - if($this->auto_links){ - $this->_code = preg_replace('/([^"])(http:\/\/|ftp:\/\/)([^\s,]*)/i','$1$2$3',$this->_code); - $this->_code = preg_replace('/([^"])([A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4})/i','$1$2',$this->_code); - } - } - function addTag($old,$new){ - $this->tags[$old] = $new; - } - function addMapped($bb,$html,$att,$end=true){ - $this->mapped[$bb] = array($html,$att,$end); - } - function addTagWithAttribute($bb,$html,$att){ - $this->tags_with_att[$bb] = array($html,$att); - } - function addSmiley($code,$src){ - $this->smilies[$code] = $src; - } -} -?> \ No newline at end of file diff --git a/src/Query/meta.php b/src/Query/meta.php deleted file mode 100644 index c1320a7..0000000 --- a/src/Query/meta.php +++ /dev/null @@ -1,9 +0,0 @@ -type = 'simple'; - $table->name = $name; - $table->alias = "t" . self::$alias++; - - $result->table = $table; - - return $result; - } - - /** - * Добавляет к запросу условие - * @param string $field Имя поля таблицы - * @param string $op Имя оператора - * @param $value Значение поля - * - * @return Query - */ - public function filter($field, $op, $value) - { - $result = clone $this; - $result->filter [] = $result->table->alias ."." . $field . $op . "'" . $value . "'"; - return $result; - } - - /** - * @param string $e Выражение - */ - public function calc($e) - { - $result = clone $this; - $result->calc [] = $e; - return $result; - } - - public function joinOn($first, $e) - { - $result = $this->compose($first, array ('filter', 'calc', 'order')); - - $e = strtr($e, array ("a." => $this->table->alias . ".", - "b." => $first->table->alias . ".")); - - $table = new Table (); - $table->type = 'join'; - $table->name = $this->table->name; - $table->alias = $this->table->alias; - $table->join = $first->table; - $table->condition = $e; - - $result->table = $table; - - return $result; - } - - /** - * Обьединяет параметры двух заросов - * @param Query $first - * @pram array $list Список параметров - * - * @return Query - */ - private function compose(Query $first, array $list) - { - $result = new Query(); - foreach ($list as $name) { - $result->$name = array_merge($this->$name, $first->$name); - } - return $result; - } - - /** - * Заковычивает значение - */ - public function quote ($value) - { - return "'" . $value . "'"; - } - - /** - * Компиляция таблицы - * @param Table $table - * - * @return string Часть строки SQL - */ - private function table(Table $table) - { - if ($table->type == 'simple') { - return $table->name ." AS ".$table->alias; - } - if ($table->type == 'join') { - return $table->name ." AS ".$table->alias. " JOIN " . $this->table ($table->join) . " ON " . $table->condition; - } - return ""; - } - - /** - * Компиляция WHERE - * - * @return string Часть строки SQL - */ - private function where () - { - return implode(" AND ", $this->filter); - } - - /** - * Компиляция запроса в SELECT SQL - * - * @return string SQL выражение - */ - public function select() - { - return "SELECT " - . ((!empty($this->calc))? implode (",", $this->calc): "*") - . " FROM " . $this->table($this->table) - . ((!empty ($this->filter))? " WHERE " . $this->where() : ""); - } - - /** - * Компиляция в DELETE - */ - public function delete() - { - return "DELETE FROM " . $this->table->name - . ((!empty ($this->filter))? " WHERE " . $this->where() : ""); - } - - private function add_prefix($prefix, $array) { - $result = array(); - foreach ($array as $value) { - $result [] = $prefix . $value; - } - return $result; - } - - /** - * Компиляция в UPDATE - * TODO: Разные типы запросов Query->update(); Query->select(), Query->insert();!! - * Возвраащают statement - */ - public function update($values) - { - $pairs = array (); - foreach ($values as $key => $value) { // - $pairs [] = $key . "=" . $this->quote ($value); - } - return "UPDATE " . $this->table->name . " SET " - . implode(",", $pairs) - . ((!empty($this->filter))? " WHERE " . $this->where() : ""); - } - - /** - * Компиляция в INSERT - */ - public function insert($values) - { - return "INSERT INTO ". $this->table->name . "(" - . implode(",", array_keys($values)) - . ") VALUES (" . implode(",", array_map(array($this, 'quote'), array_values($values))) . ")"; - } -} - diff --git a/src/Query/table.php b/src/Query/table.php deleted file mode 100644 index 19f67a4..0000000 --- a/src/Query/table.php +++ /dev/null @@ -1,14 +0,0 @@ -]*?>.*?'si" => "", // strip out javascript - "'<[\/\!]*?[^<>]*?>'si" => "", // strip out html tags - "'([\r\n])[\s]+'" => "\\1", // strip out white space - "'&(quot|#34|#034|#x22);'i" => "\"", // replace html entities - "'&(amp|#38|#038|#x26);'i" => "&", // added hexadecimal values - "'&(lt|#60|#060|#x3c);'i" => ">", - "'&(gt|#62|#062|#x3e);'i" => "<", - "'&(nbsp|#160|#xa0);'i" => " ", - "'&(iexcl|#161);'i" => chr(161), - "'&(cent|#162);'i" => chr(162), - "'&(pound|#163);'i" => chr(163), - "'&(copy|#169);'i" => chr(169), - "'&(reg|#174);'i" => chr(174), - "'&(deg|#176);'i" => chr(176)); - $text = preg_replace(array_keys($search), array_values($search), $document); - return $text; -} - -/** - * Разделение текста на массив слов - */ -function tokenize ($document) -{ - $array = preg_split("/[\W]+/", $document); - return $array; -} - - -/** - * Ищет один из символов с конца строки - * - * @param string $haystack - * @param array $needle Массив символов для поиска - * @param int $offset Смещение от начала строки - * - * @return int Позицию первого совпадения - */ -function indexRight ($haystack, $needle, $offset = 0) -{ - if ((bool)$offset === false) $offset = 0; - while ($offset >= 0) { - if (in_array ($haystack[$offset], $needle)) { - return $offset; - } - $offset --; - } - return false; -} - -/** - * Ищет один из символов с начала строки - * - * @param string $haystack - * @param array $needle Массив символов для поиска - * @param int $offset Смещение от начала строки - * - * @return int Позицию первого совпадения - */ -function indexLeft ($haystack, $needle, $offset = 0) -{ - if ($offset < 0) return false; - while ($offset < strlen($haystack)) { - if ((is_callable($needle) && call_user_func ($needle, $haystack[$offset])) - || (is_array ($needle) && in_array ($haystack[$offset], $needle))) { - return $offset; - } - $offset ++; - } - return false; -} - -function not_ctype_alpha ($ch) -{ - return !ctype_alpha($ch); -} diff --git a/src/Search/index.php b/src/Search/index.php deleted file mode 100644 index 6f79c33..0000000 --- a/src/Search/index.php +++ /dev/null @@ -1,80 +0,0 @@ -]*?>(.*?)'si"; - preg_match($title, $content, $matches); - if(isset($matches[1])) { - return $matches[1]; - } - return ""; - } - - // Выбираем основу слова - function clean ($word) - { - return Stemmer::russian(strtolower($word)); - } - - function process ($base, $files) - { - $path = new Path($base); - // Список документов - foreach ($path->getContentRec($files) as $file) { - $content = file_get_contents ($file); - $text = stripText($content); -// $title = self::getTitle ($content); - $title = pathinfo($file, PATHINFO_BASENAME); -// echo $file, "\n"; - // Список слов в документе - $list = tokenize($text); - foreach ($list as $word) { - $preword = self::clean($word); - if (isset($this->index[$preword])) { - $index = $this->index[$preword]; - if ( ! in_array ($this->count, $index)) $this->index[$preword] [] = $this->count; - } else { - // Не записываем слова длинна которых меньше 2 - if (strlen($preword) > 1) { - $this->index[$preword] = array ($this->count); - } - } - } - $this->text [] = array ($title, $path->relPath ($file), $text); - $this->count ++; - } - ksort($this->index); - } - - /** - * Сохранение результата поиска - */ - function saveData ($file) - { - $file = fopen($file, "w"); - // Количество слов и текстов - fwrite ($file, pack("SS", count($this->index), count($this->text))); - foreach ($this->index as $word => $value) { - $length = strlen($word); - array_unshift ($value, "SSa*S*", $length, count($value), $word); - fwrite($file, call_user_func_array ('pack', $value)); - } - - foreach ($this->text as $text) { - fwrite($file, pack("SSSa*a*a*", - strlen($text[0]), strlen($text[1]), strlen($text[2]) - , $text[0], $text[1], $text[2])); - } - } -} diff --git a/src/Search/lexer.php b/src/Search/lexer.php deleted file mode 100644 index b555006..0000000 --- a/src/Search/lexer.php +++ /dev/null @@ -1,91 +0,0 @@ -src = $src; - $this->offset; - } - - private function skipSpace () - { - while (!$this->isEOL() && $this->getChar() == " ") { - $this->offset++; - } - } - - private function getChar () - { - return $this->src [$this->offset]; - } - - /** - * Проверяет на конец строки - */ - private function isEOL () { - return $this->offset >= strlen($this->src); - } - - /** - * Односимвольный токен - */ - private function easyToken () { - $ch = $this->getChar (); - switch ($ch) { - case '~': $token = array(self::TOKEN_NOT, $ch); break; - case '|': $token = array(self::TOKEN_OR, $ch); break; - case '(': $token = array(self::TOKEN_LPAREN, $ch); break; - case ')': $token = array(self::TOKEN_RPAREN, $ch); break; - case '&': $token = array(self::TOKEN_AND, $ch); break; - default: - $this->offset++; - $token = $this->getToken(); - } - $this->offset++; - return $token; - } - - /** - * Возвращает следующий токен - */ - public function getToken () - { - $this->skipSpace (); - if ($this->isEOL()) { - return array(self::TOKEN_EOL, ""); - } - if (ctype_alpha($this->getChar())) { - $start = $this->offset; - while (!$this->isEOL() && ctype_alpha($this->getChar())) { - $this->offset ++; - } - return array(self::TOKEN_WORD, substr ($this->src, $start, $this->offset-$start)); - } - return $this->easyToken(); - } - - public function nextToken () - { - $this->token = $this->getToken(); - } -} diff --git a/src/Search/search.php b/src/Search/search.php deleted file mode 100644 index 718d8af..0000000 --- a/src/Search/search.php +++ /dev/null @@ -1,96 +0,0 @@ -lexer = new Lexer(); - $this->index = $index; - - $this->op = array ($this, 'Op'); - $this->binary = array ($this, 'binaryOp'); - $this->union = array ($this, 'union'); - $this->intersection = lcurry($this->op, 'array_uintersect', $this->union); - - $this->notQuery = lcurry ($this->binary, Lexer::TOKEN_NOT, - lcurry($this->op, 'array_udiff', 'array_udiff'), array ($this, 'easyQuery')); - - $this->orQuery = lcurry ($this->binary, Lexer::TOKEN_OR, - lcurry($this->op, $this->union, $this->union), $this->notQuery); - - $this->andQuery = lcurry ($this->binary, Lexer::TOKEN_AND, $this->intersection, $this->orQuery); - } - - function union ($a, $b, $callback) - { - return array_merge($a, $b); - } - - function Eq ($a, $b) - { - return $a == $b; - } - - function Op ($files, $words, $a, $b) { - return array ( - 'words' => call_user_func ($words, $a['words'], $b['words'], array ($this, 'eq')), - 'files' => call_user_func ($files, $a['files'], $b['files'], array ($this, 'eq')) - ); - } - - public function getQuery ($source) - { - $this->lexer->setSource ($source); - $this->lexer->nextToken(); - return $this->topQuery(); - } - - function topQuery () - { - $result = call_user_func ($this->andQuery); - while ($this->lexer->token[0] == Lexer::TOKEN_LPAREN) { - $result = call_user_func ($this->intersection, $result, call_user_func ($this->andQuery)); - } - return $result; - } - - function easyQuery () - { - $result = null; - if ($this->lexer->token[0] == Lexer::TOKEN_LPAREN) { - $this->lexer->nextToken (); - $result = $this->topQuery (); - if ($this->lexer->token[0] == Lexer::TOKEN_RPAREN) { - $this->lexer->nextToken (); - } - return $result; - } else { - $result = call_user_func ($this->index, $this->lexer->token[1]); - $this->lexer->nextToken (); - return $result; - } - } - - /** - * @param int $type Тип лексемы - * @param function $op Функция при совпадении типа лексемы при запросе - * @param function $next Следующий обработчик запроса - */ - function binaryOp ($type, $op, $next) - { - $result = call_user_func($next); - while ($this->lexer->token[0] == $type) { - $this->lexer->nextToken(); - $result = call_user_func($op, $result, call_user_func ($next)); - } - return $result; - } -} - diff --git a/src/Search/searcher.php b/src/Search/searcher.php deleted file mode 100644 index 4bc92d7..0000000 --- a/src/Search/searcher.php +++ /dev/null @@ -1,97 +0,0 @@ -search = new Search (array ($this, 'getWord')); - } - - /** - * Читает содержимое индексного файла - * - * @param string $file Имя файла - */ - function setSource ($fileName) - { - $file = fopen($fileName, "r"); - $words = fread($file, 4); - $all = unpack("Swords/Stexts", $words); - for ($i = 0; $i < $all['words']; $i++) { - $pos = fread($file, 4); - $size = unpack("Sword/Sindex", $pos); - - $word = fread($file, $size['word']); - $index = unpack("S*", fread($file, $size['index']*2)); - $this->index[$word] = $index; - } - - for ($i = 0; $i < $all['texts']; $i++) { - $pos = fread($file, 6); - $size = unpack("Stitle/Surl/Stext", $pos); - // - $title = fread($file, $size['title']); - $url = fread($file, $size['url']); - $text = fread($file, $size['text']); - $this->text [] = array ($title, $url, $text); - } - } - - // По слову возвращаем список файлов и слово - public function getWord ($word) - { - $preword = Stemmer::russian($word); // Index?? -> clean - if (isset($this->index[$preword])) { // Search?? - return array ('files' => $this->index[$preword], 'words' => array ($preword)); - } - return array ('files' => array (), 'words' => array ()); - } - - /** - * Список документов в которых встечается слово - * - */ - function getResult (&$query) - { - $result = array (); - $word = $query['words']; - $list = $query['files']; - // - foreach ($list as $n) { - $result [] = array ( - 'title' => $this->text[$n][0], - 'file' => $this->text[$n][1], - 'text' => self::getSlice ($word[0], $this->text[$n][2])); - } - return $result; - } - - /** - * Часть документа в котором встречается слово - * - * @param $word Слово - * @param $text Текст содержащий слово - */ - function getSlice ($word, $text) - { - $pos = stripos($text, $word); - $offset = max(max ($pos-100, indexRight($text, array ("."), $pos) + 1), 0); - $real = substr($text, $pos, strlen($word)) ; - return substr($text, $offset, $pos - $offset) - . "" . $real . "" . substr ($text, $pos + strlen($word), 100); - } - - /** - * Поиск по запросу - * - */ - function search ($query) - { - $result = $this->search->getQuery($query); - return $this->getResult($result); - } -} - diff --git a/src/Search/stemmer.php b/src/Search/stemmer.php deleted file mode 100644 index f3bee01..0000000 --- a/src/Search/stemmer.php +++ /dev/null @@ -1,180 +0,0 @@ -key = $key; diff --git a/src/Spell.php b/src/Spell.php deleted file mode 100644 index 43b0ce8..0000000 --- a/src/Spell.php +++ /dev/null @@ -1,98 +0,0 @@ - SpellHelper ?? - */ -class Spell -{ - private $pspell; - public $autocorrect = false; - public function __construct ($language, $encoding) - { - $this->pspell = pspell_new($language, '', '', $encoding, PSPELL_NORMAL); - } - - function spellCheckWord ($word) - { - $word = $word[0]; - - // Ignore ALL CAPS - if (preg_match('/^[A-Z0-9]*$/', $word)) return $word; - - // Return dictionary words - if (pspell_check($this->pspell, $word)) - return $word; - - // Auto-correct with the first suggestion, color green - if ($this->autocorrect && $suggestions = pspell_suggest($this->pspell, $word)) - return '' . current($suggestions) . ''; - - // No suggestions, color red - return '' . $word . ''; - } - - function isGoodWord ($word) - { - // Ignore ALL CAPS - if (preg_match('/^[A-Z]*$/', $word)) return true; - if (preg_match('/^[0-9]*$/', $word)) return true; - - // Return dictionary words - if (pspell_check($this->pspell, $word)) - return true; - - return false; - } - - function suggest ($string) - { - return preg_replace_callback('/\b\w+\b/', array($this, 'spellCheckWord'), $string); - } - - /** - * Вызывает функцию для каждого найденного слова - */ - function eachWord ($call, $string) - { - $begin = indexLeft ($string, 'ctype_alpha', 0); - while ($begin !== false) { - $end = indexLeft ($string, 'not_ctype_alpha', $begin); - call_user_func ($call, $string, $begin, $end); - $begin = indexLeft ($string, 'ctype_alpha', $end); - } - return false; - } - - /** - * Проверяет слово на соответствие со словарем - * - */ - function doWord (&$string, $begin, $end) - { - $word = substr($string, $begin, $end - $begin); - if (! $this->isGoodWord ($word)) { - $start = max(indexLeft ($string, 'not_ctype_alpha', $begin - 100), 0); - $offset = indexLeft ($string, 'not_ctype_alpha', $end + 100); - if (! $offset) { - $offset = strlen($string); - } - $length = $offset - $start; - throw new Exception ($this->suggest(substr($string, $start, $length))); - } - } - - /** - * Часть текста содержащий неправильное слово - */ - function getError ($string) - { - try { - self::eachWord (array ($this, 'doWord'), $string); - } catch (Exception $e) { - return $e->getMessage(); - } - return false; - } -} diff --git a/src/Tools/ExcelTable.php b/src/Tools/ExcelTable.php index 0816ee8..bc7ea38 100644 --- a/src/Tools/ExcelTable.php +++ b/src/Tools/ExcelTable.php @@ -6,7 +6,7 @@ class Excel_Number function __construct($value) { - $this->value = $value; + $this->value = intval($value); } function getString() @@ -70,13 +70,13 @@ class TableRow */ class ExcelTable { - static $index; + static $index; private $name; private $style; - protected $rows = array(); + protected $rows = array(); - protected $splitVertical = false; - protected $splitHorizontal = false; + protected $_splitVertical = false; + protected $_splitHorizontal = false; function __construct() { @@ -94,7 +94,8 @@ class ExcelTable if(! isset($this->rows[$x])) { $this->rows[$x] = new TableRow(); } - $this->rows[$x]->setCell($y, $value); + /*.TableRow.*/$row = $this->rows[$x]; + $row->setCell($y, $value); } /** @@ -142,12 +143,13 @@ class ExcelTable * @param $cell Номер столбца * @param $merge Количество клеток для обьединения */ - function setCellMerge ($row, $cell, $merge) + function setCellMerge($x, $cell, $merge) { - assert(is_numeric($row) && $row > 0); + assert(is_numeric($x) && $x > 0); assert(is_numeric($cell) && $cell > 0); - $this->rows[$row]->cells[$cell]->merge = $merge; + /*.TableRow.*/$row = $this->rows[$x]; + $row->cells[$cell]->merge = $merge; } /** @@ -181,7 +183,8 @@ class ExcelTable */ function getRows() { - return max(array_keys($this->rows)); + /*.array.*/$keys = array_keys($this->rows); + return max($keys); } /** @@ -189,27 +192,26 @@ class ExcelTable * * @return int */ - function getRowCells($row) + function getRowCells(TableRow $row) { - return max(array_keys($row->cells)); + /*.array.*/$keys = array_keys($row->cells); + return max($keys); } /** * Разделяет таблицу на две части по вертикали * @param $n integer Количество столбцов слева */ - function splitVertical($n) - { - $this->splitVertical = $n; + function splitVertical($n) { + $this->_splitVertical = $n; } /** * Разделяет таблицу на две части по горизонтали * @param $n integer Количество столбцов сверху */ - function splitHorizontal($n) - { - $this->splitHorizontal = $n; + function splitHorizontal($n) { + $this->_splitHorizontal = $n; } @@ -218,8 +220,7 @@ class ExcelTable * * @return int */ - function getColumns() - { + function getColumns() { return max(array_map(array($this, 'getRowCells'), $this->rows)); } @@ -231,7 +232,7 @@ class ExcelTable /** * Генерация клетки таблицы (Переработать) */ - function createCell ($ncell, XMLWriter $doc, $j, $value, $setIndex) { + function createCell (TableCell $ncell, XMLWriter $doc, $j, /*.any.*/$value, $setIndex) { $doc->startElement("Cell"); if ($ncell->style) { @@ -291,7 +292,7 @@ class ExcelTable $doc->writeAttribute('ss:Height', $this->rows[$i]->height); } - $nrow = $this->rows[$i]; + /*.TableRow.*/$nrow = $this->rows[$i]; // Флаг индикатор подстановки номера столбца $setIndex = false; for ($j = 1; $j <= $columns; $j++) { @@ -321,17 +322,17 @@ class ExcelTable $doc->writeAttribute('xmlns', 'urn:schemas-microsoft-com:office:excel'); $doc->writeElement('FrozenNoSplit'); - if ($this->splitVertical) { - $doc->writeElement('SplitVertical', $this->splitVertical); - $doc->writeElement('LeftColumnRightPane', $this->splitVertical); + if ($this->_splitVertical) { + $doc->writeElement('SplitVertical', $this->_splitVertical); + $doc->writeElement('LeftColumnRightPane', $this->_splitVertical); } - if ($this->splitHorizontal) { - $doc->writeElement('SplitHorizontal', $this->splitHorizontal); - $doc->writeElement('TopRowBottomPane', $this->splitHorizontal); + if ($this->_splitHorizontal) { + $doc->writeElement('SplitHorizontal', $this->_splitHorizontal); + $doc->writeElement('TopRowBottomPane', $this->_splitHorizontal); } - if ($this->splitHorizontal && $this->splitVertical) { + if ($this->_splitHorizontal && $this->_splitVertical) { $doc->writeElement('ActivePane', 0); - } else if($this->splitHorizontal) { + } else if($this->_splitHorizontal) { $doc->writeElement('ActivePane', 2); } $doc->endElement(); @@ -377,6 +378,7 @@ class ExcelDocument { if ($type == 'Borders') { $doc->startElement('Borders'); foreach ($s as $border) { + /*.array.*/$border = $border; $doc->startElement('Border'); foreach ($border as $key => $value) { $doc->writeAttribute('ss:' . $key, $value); @@ -403,7 +405,7 @@ class ExcelDocument { function clean ($s) { assert(is_string($s)); - return strtr($s, array ("\n" => ' ')); + return strtr($s, array ("\n" => " ")); } /** @@ -412,7 +414,7 @@ class ExcelDocument { */ function save($filename) { - $doc = new xmlWriter(); + $doc = new XMLWriter(); $doc->openURI($filename); $doc->setIndent(false); $doc->startDocument('1.0','utf-8'); diff --git a/src/Tools/Image.php b/src/Tools/Image.php index b7f7c1b..c9c10ef 100644 --- a/src/Tools/Image.php +++ b/src/Tools/Image.php @@ -16,7 +16,6 @@ class Tools_Image { $width = imagesx($image); $height = imagesy($image); - $percent = min($prewidth / $width, $preheight / $height); if ($percent > 1 && !$force) $percent = 1; $new_width = $width * $percent; diff --git a/src/Tools/Password.php b/src/Tools/Password.php deleted file mode 100644 index 1308a52..0000000 --- a/src/Tools/Password.php +++ /dev/null @@ -1,32 +0,0 @@ -. + */ + +/** + * Static class for extracting SQL statements from a string or file. + * + * @author Hans Lellelid + * @version $Revision: 1.5 $ + * @package creole.util.sql + */ +class Tools_SQLStatementExtractor { + + protected static $delimiter = ';'; + + /** + * Get SQL statements from file. + * + * @param string $filename Path to file to read. + * @return array SQL statements + */ + public static function extractFile($filename) { + $buffer = file_get_contents($filename); + if ($buffer === false) { + throw new Exception("Unable to read file: " . $filename); + } + return self::extractStatements(self::getLines($buffer)); + } + + /** + * Extract statements from string. + * + * @param string $txt + * @return array + */ + public static function extract($buffer) { + return self::extractStatements(self::getLines($buffer)); + } + + /** + * Extract SQL statements from array of lines. + * + * @param array $lines Lines of the read-in file. + * @return string + */ + protected static function extractStatements($lines) { + + $statements = array(); + $sql = ""; + + foreach($lines as $line) { + + $line = trim($line); + + if (self::startsWith("//", $line) || + self::startsWith("--", $line) || + self::startsWith("#", $line)) { + continue; + } + + if (strlen($line) > 4 && strtoupper(substr($line,0, 4)) == "REM ") { + continue; + } + + $sql .= " " . $line; + $sql = trim($sql); + + // SQL defines "--" as a comment to EOL + // and in Oracle it may contain a hint + // so we cannot just remove it, instead we must end it + if (strpos($line, "--") !== false) { + $sql .= "\n"; + } + + if (self::endsWith(self::$delimiter, $sql)) { + $statements[] = self::substring($sql, 0, strlen($sql)-1 - strlen(self::$delimiter)); + $sql = ""; + } + } + return $statements; + } + + // + // Some string helper methods + // + + /** + * Tests if a string starts with a given string. + * @param string $check The substring to check. + * @param string $string The string to check in (haystack). + * @return boolean True if $string starts with $check, or they are equal, or $check is empty. + */ + protected static function startsWith($check, $string) { + if ($check === "" || $check === $string) { + return true; + } else { + return (strpos($string, $check) === 0) ? true : false; + } + } + + /** + * Tests if a string ends with a given string. + * @param string $check The substring to check. + * @param string $string The string to check in (haystack). + * @return boolean True if $string ends with $check, or they are equal, or $check is empty. + */ + protected static function endsWith($check, $string) { + if ($check === "" || $check === $string) { + return true; + } else { + return (strpos(strrev($string), strrev($check)) === 0) ? true : false; + } + } + + /** + * a natural way of getting a subtring, php's circular string buffer and strange + * return values suck if you want to program strict as of C or friends + */ + protected static function substring($string, $startpos, $endpos = -1) { + $len = strlen($string); + $endpos = (int) (($endpos === -1) ? $len-1 : $endpos); + if ($startpos > $len-1 || $startpos < 0) { + trigger_error("substring(), Startindex out of bounds must be 0 $len-1 || $endpos < $startpos) { + trigger_error("substring(), Endindex out of bounds must be $startposlist = $list; - } - - function makeTable() { - $xls = new ExcelTable(); - $xls->setRow(1, 1, array_keys($this->list)); - - foreach($this->data as $n => $item) { - $result = array(); - foreach($this->list as $key => $c) { - if (is_callable($c)) { - $result [] = call_user_func($c, $item, $n); - } else { - if (is_numeric($item[$c])) { - $result [] = new Excel_Number($item[$c]); - } else { - $result [] = $item[$c]; - } - } - } - $xls->addRow(1, $result); - } - - return $xls; - } - - function writeTable($data, $file) { - $this->data = $data; - - $xls = new ExcelDocument(); - $xls->addTable(array($this, 'makeTable')); - $xls->save($file); - } -} - -class TableHTMLView { - private $list = array(); - private $stack = array(); - private $result = array(); - - function writeElement($name, $content) { - echo "<".$name.">"; - echo $content; - echo ""; - } - - function startElement($name) { - array_push($this->stack, $name); - echo "<".$name.">"; - } - - function endElement() { - $name = array_pop($this->stack); - echo ""; - } - - function setColumns(array $list) { - $this->list = $list; - } - - function writeTable($data) { - $this->startElement('table'); - $this->startElement('thead'); - $this->startElement('tr'); - foreach($this->list as $key => $c) { - $this->writeElement('th', $key); - } - $this->endElement(); - $this->endElement(); - - $this->startElement('tbody'); - foreach($data as $n => $item) { - $this->startElement('tr'); - foreach($this->list as $key => $c) { - if (is_callable($c)) { - $this->writeElement('td', call_user_func($c, $item, $n)); - } else { - $this->writeElement('td', $item[$c]); - } - } - $this->endElement(); - } - $this->endElement(); - $this->endElement(); - } -} - diff --git a/src/Tree/DBtree.php b/src/Tree/DBtree.php deleted file mode 100644 index 1a5792f..0000000 --- a/src/Tree/DBtree.php +++ /dev/null @@ -1,636 +0,0 @@ - -// WWW: http://dev.e-taller.net/dbtree/ -// Category: Databases -// Description: PHP class implementing a Nested Sets approach to storing -// tree-like structures in database tables. This technique was -// introduced by Joe Celko and has some -// advantages over a widely used method called Adjacency Matrix. -//**************************************************************************** -// The lib is FREEWARE. That means you may use it anywhere you want, you may -// do anything with it. The Author mentioned above is NOT responsible for any -// consequences of using this library. -// If you don't agree with this, you are NOT ALLOWED to use the lib! -//**************************************************************************** -// You're welcome to send me all improvings, feature requests, bug reports... -//**************************************************************************** -// SAMPLE DB TABLE STRUCTURE: -// -// CREATE TABLE categories ( -// cat_id INT UNSIGNED NOT NULL AUTO_INCREMENT, -// cat_left INT UNSIGNED NOT NULL, -// cat_right INT UNSIGNED NOT NULL, -// cat_level INT UNSIGNED NOT NULL, -// PRIMARY KEY(cat_id), -// KEY(cat_left, cat_right, cat_level) -// ); -// -// This is believed to be the optimal Nested Sets use case. Use `one-to-one` -// relations on `cat_id` field between this `structure` table and -// another `data` table in your database. -// -// Don't forget to make a single call to clear() -// to set up the Root node in an empty table. -// -//**************************************************************************** -// NOTE: Although you may use this library to retrieve data from the table, -// it is recommended to write your own queries for doing that. -// The main purpose of the library is to provide a simpler way to -// create, update and delete records. Not to SELECT them. -//**************************************************************************** -// -// IMPORTANT! DO NOT create either UNIQUE or PRIMARY keys on the set of -// fields (`cat_left`, `cat_right` and `cat_level`)! -// Unique keys will destroy the Nested Sets structure! -// -//**************************************************************************** -// CHANGELOG: -// 16-Apr-2003 -=- 1.1 -// - Added moveAll() method -// - Added fourth parameter to the constructor -// - Renamed getElementInfo() to getNodeInfo() /keeping BC/ -// - Added "Sample Table Structure" comment -// - Now it trigger_error()'s in case of any serious error, because if not you -// will lose the Nested Sets structure in your table -// 19-Feb-2004 -=- 1.2 -// - Fixed a bug in moveAll() method? -// Thanks to Maxim Matyukhin for the patch. -// 13-Jul-2004 -=- 1.3 -// - Changed all die()'s for a more standard trigger_error() -// Thanks to Dmitry Romakhin for pointing out an issue with -// incorrect error message call. -// 09-Nov-2004 -=- 1.4 -// - Added insertNear() method. -// Thanks to Michael Krenz who sent its implementation. -// - Removed IGNORE keyword from UPDATE clauses in insert() methods. -// It was dumb to have it there all the time. Sorry. Anyway, you had -// to follow the important note mencioned above. If you hadn't, you're -// in problem. -// -//**************************************************************************** -// Note: For best viewing of the code Tab size 4 is recommended -//**************************************************************************** - -function _case($c, $then, $else) { - return " (CASE WHEN $c THEN $then ELSE $else END) "; -} - -function _between($a, $x, $y) { - return " " . $a . " BETWEEN " . $x . " AND " . $y; -} - -function _inside($a, $x, $y) { - return " " . $a . " > " . $x . " AND " . $a . " < " . $y; -} - -class Tree_DBTree -{ - var $db; // CDatabase class to plug to - var $table; // Table with Nested Sets implemented - var $id; // Name of the ID-auto_increment-field in the table. - // These 3 variables are names of fields which are needed to implement - // Nested Sets. All 3 fields should exist in your table! - // However, you may want to change their names here to avoid name collisions. - var $left = 'cat_left'; - var $right = 'cat_right'; - var $level = 'cat_level'; - var $qryParams = ''; - var $qryFields = ''; - var $qryTables = ''; - var $qryWhere = ''; - var $qryGroupBy = ''; - var $qryHaving = ''; - var $qryOrderBy = ''; - var $qryLimit = ''; - var $sqlNeedReset = true; - var $sql; // Last SQL query - - //************************************************************************ - // Constructor - // $DB : CDatabase class instance to link to - // $tableName : table in database where to implement nested sets - // $itemId : name of the field which will uniquely identify every record - // $fieldNames : optional configuration array to set field names. Example: - // array( - // 'left' => 'cat_left', - // 'right' => 'cat_right', - // 'level' => 'cat_level' - // ) - function CDBTree(&$DB, $tableName, $itemId, $seq, $fieldNames = array()) - { - - if (empty($tableName)) trigger_error("phpDbTree: Unknown table", E_USER_ERROR); - - if (empty($itemId)) trigger_error("phpDbTree: Unknown ID column", E_USER_ERROR); - $this->seq = $seq; - $this->db = $DB; - $this->table = $tableName; - $this->id = $itemId; - - if (is_array($fieldNames) && sizeof($fieldNames)) - foreach($fieldNames as $k => $v) $this->$k = $v; - } - - //************************************************************************ - // Returns a Left and Right IDs and Level of an element or false on error - // $ID : an ID of the element - function getElementInfo($ID) - { - return $this->getNodeInfo($ID); - } - - function getNodeInfo($ID) - { - $this->sql = 'SELECT ' . $this->left . ',' . $this->right . ',' . $this->level . ' FROM ' . $this->table . ' WHERE ' . $this->id . '=\'' . $ID . '\''; -// print_r($this->sql); - - if (($query = $this->db->query($this->sql)) && ($this->db->num_rows($query) == 1) && ($Data = $this->db->fetch_array($query))) return array( - (int)$Data[$this->left], - (int)$Data[$this->right], - (int)$Data[$this->level] - ); - else trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR); // throw new Exception(); - } - - //************************************************************************ - // Clears table and creates 'root' node - // $data : optional argument with data for the root node - function clear($data = array()) - { - // clearing table - - if ((!$this->db->query('TRUNCATE ' . $this->table)) && (!$this->db->query('DELETE FROM ' . $this->table))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR); - // preparing data to be inserted - - if (sizeof($data)) { - $fld_names = implode(',', array_keys($data)) . ','; - - if (sizeof($data)) $fld_values = '\'' . implode('\',\'', array_values($data)) . '\','; - } - $fld_names.= $this->left . ',' . $this->right . ',' . $this->level; - $fld_values.= '1,2,0'; - // inserting new record - $this->sql = 'INSERT INTO ' . $this->table . '(' . $fld_names . ') VALUES(' . $fld_values . ')'; - - if (!($this->db->query($this->sql))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR); - return $this->db->insert_id($this->seq); - } - - //************************************************************************ - // Updates a record - // $ID : element ID - // $data : array with data to update: array( => ) - function update($ID, $data) - { - $sql_set = ''; - - foreach($data as $k => $v) $sql_set.= ',' . $k . '=\'' . addslashes($v) . '\''; - return $this->db->query('UPDATE ' . $this->table . ' SET ' . substr($sql_set, 1) . ' WHERE ' . $this->id . '=\'' . $ID . '\''); - } - - //************************************************************************ - // Inserts a record into the table with nested sets - // $ID : an ID of the parent element - // $data : array with data to be inserted: array( => ) - // Returns : true on success, or false on error - function insert($ID, $data) - { - - if (!(list($leftId, $rightId, $level) = $this->getNodeInfo($ID))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR); - // preparing data to be inserted - - if (sizeof($data)) { - $fld_names = implode(',', array_keys($data)) . ','; - $fld_values = '\'' . implode('\',\'', array_values($data)) . '\','; - } - $fld_names.= $this->left . ',' . $this->right . ',' . $this->level; - $fld_values.= ($rightId) . ',' . ($rightId+1) . ',' . ($level+1); - // creating a place for the record being inserted - - if ($ID) { - $this->sql = 'UPDATE ' . $this->table . ' SET ' . $this->left . '=' . _case($this->left . '>' . $rightId, $this->left . '+2', $this->left) . ',' . $this->right . '=' . _case($this->right . '>=' . $rightId, $this->right . '+2', $this->right) . 'WHERE ' . $this->right . '>=' . $rightId; - - if (!($this->db->query($this->sql))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR); - } - // inserting new record - $this->sql = 'INSERT INTO ' . $this->table . '(' . $fld_names . ') VALUES(' . $fld_values . ')'; - - if (!($this->db->query($this->sql))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR); - return $this->db->insert_id($this->seq); - } - - //************************************************************************ - // Inserts a record into the table with nested sets - // $ID : ID of the element after which (i.e. at the same level) the new element - // is to be inserted - // $data : array with data to be inserted: array( => ) - // Returns : true on success, or false on error - function insertNear($ID, $data) - { - - if (!(list($leftId, $rightId, $level) = $this->getNodeInfo($ID))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR); - // preparing data to be inserted - - if (sizeof($data)) { - $fld_names = implode(',', array_keys($data)) . ','; - $fld_values = '\'' . implode('\',\'', array_values($data)) . '\','; - } - $fld_names.= $this->left . ',' . $this->right . ',' . $this->level; - $fld_values.= ($rightId+1) . ',' . ($rightId+2) . ',' . ($level); - // creating a place for the record being inserted - - if ($ID) { - $this->sql = 'UPDATE ' . $this->table . ' SET ' . $this->left . '=' . _case($this->left . '>' . $rightId, $this->left . '+2', $this->left) . $this->right . '=' . _case($this->right . '>' . $rightId, $this->right . '+2', $this->right) . 'WHERE ' . $this->right . '>' . $rightId; - - if (!($this->db->query($this->sql))) trigger_error("phpDbTree error:" . $this->db->error() , E_USER_ERROR); - } - // inserting new record - $this->sql = 'INSERT INTO ' . $this->table . '(' . $fld_names . ') VALUES(' . $fld_values . ')'; - - if (!($this->db->query($this->sql))) trigger_error("phpDbTree error:" . $this->db->error() , E_USER_ERROR); - return $this->db->insert_id($this->seq); - } - - //************************************************************************ - // Assigns a node with all its children to another parent - // $ID : node ID - // $newParentID : ID of new parent node - // Returns : false on error - function moveAll($ID, $newParentId) - { - - if (!(list($leftId, $rightId, $level) = $this->getNodeInfo($ID))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR); - - if (!(list($leftIdP, $rightIdP, $levelP) = $this->getNodeInfo($newParentId))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR); - - if ($ID == $newParentId || $leftId == $leftIdP || ($leftIdP >= $leftId && $leftIdP <= $rightId)) return false; - // whether it is being moved upwards along the path - - if ($leftIdP < $leftId && $rightIdP > $rightId && $levelP < $level-1) { - $this->sql = 'UPDATE ' . $this->table . ' SET ' - . $this->level . '=' . _case($this->left . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->level . sprintf('%+d', -($level-1) +$levelP) , $this->level) . "," - . $this->right . '=' . _case($this->right . ' BETWEEN ' . ($rightId+1) . ' AND ' . ($rightIdP-1) , $this->right . '-' . ($rightId-$leftId+1) - , _case($this->left . ' BETWEEN ' . ($leftId) . ' AND ' . ($rightId) , $this->right . '+' . ((($rightIdP-$rightId-$level+$levelP) /2) *2+$level-$levelP-1) , $this->right)) . "," - . $this->left . '=' . _case($this->left . ' BETWEEN ' . ($rightId+1) . ' AND ' . ($rightIdP-1) , $this->left . '-' . ($rightId-$leftId+1) , _case($this->left . ' BETWEEN ' . $leftId . ' AND ' . ($rightId) , $this->left . '+' . ((($rightIdP-$rightId-$level+$levelP) /2) *2+$level-$levelP-1) , $this->left)) . 'WHERE ' . $this->left . ' BETWEEN ' . ($leftIdP+1) . ' AND ' . ($rightIdP-1); - - } elseif ($leftIdP < $leftId) { - $this->sql = 'UPDATE ' . $this->table . ' SET ' - . $this->level . '=' . _case($this->left . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->level . sprintf('%+d', -($level-1) +$levelP) , $this->level) . "," - . $this->left . '=' . _case($this->left . ' BETWEEN ' . $rightIdP . ' AND ' . ($leftId-1) , $this->left . '+' . ($rightId-$leftId+1) - , _case($this->left . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->left . '-' . ($leftId-$rightIdP) , $this->left)) . "," - . $this->right . '=' . _case($this->right . ' BETWEEN ' . $rightIdP . ' AND ' . $leftId, $this->right . '+' . ($rightId-$leftId+1) , _case($this->right . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->right . '-' . ($leftId-$rightIdP) , $this->right)) . 'WHERE ' . $this->left . ' BETWEEN ' . $leftIdP . ' AND ' . $rightId - // !!! added this line (Maxim Matyukhin) - . ' OR ' . $this->right . ' BETWEEN ' . $leftIdP . ' AND ' . $rightId; - } else { - $this->sql = 'UPDATE ' . $this->table . ' SET ' - . $this->level . '=' . _case($this->left . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->level . sprintf('%+d', -($level-1) +$levelP) , $this->level) . "," - . $this->left . '=' . _case($this->left . ' BETWEEN ' . $rightId . ' AND ' . $rightIdP, $this->left . '-' . ($rightId-$leftId+1) - , _case($this->left . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->left . '+' . ($rightIdP-1-$rightId), $this->left)) . ", " - . $this->right . '=' . _case($this->right . ' BETWEEN ' . ($rightId+1) . ' AND ' . ($rightIdP-1) , $this->right . '-' . ($rightId-$leftId+1) , _case($this->right . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->right . '+' . ($rightIdP-1-$rightId) , $this->right)) . 'WHERE ' . $this->left . ' BETWEEN ' . $leftId . ' AND ' . $rightIdP - // !!! added this line (Maxim Matyukhin) - . ' OR ' . $this->right . ' BETWEEN ' . $leftId . ' AND ' . $rightIdP; - } - return $this->db->query($this->sql) or trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR); - } - - // Перемещение всех детей ветки в другую ветку - function moveChildren($ID, $newParentId) - { - - if (!(list($leftId, $rightId, $level) = $this->getNodeInfo($ID))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR); - - if (!(list($leftIdP, $rightIdP, $levelP) = $this->getNodeInfo($newParentId))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR); - - if ($ID == $newParentId || $leftId == $leftIdP || ($leftIdP >= $leftId && $leftIdP <= $rightId)) return false; - // whether it is being moved upwards along the path - - if ($leftIdP < $leftId && $rightIdP > $rightId && $levelP < $level-1) { - // _update($this->table, array(), ) - $this->sql = 'UPDATE ' . $this->table . ' SET ' - // Меняем уровень - . $this->level . '=' . - _case(_between($this->left, $leftId, $rightId), - $this->level . sprintf('%+d', -($level-1) +$levelP) , $this->level) - // Меняем границы - . $this->left . '=' . - _case(_beetween($this->left, $rightId+1, $rightIdP-1), $this->left . '-' . $rightId-$leftId+1 , - _case(_between($this->left, $leftId, $rightId), $this->left . '+' . ((($rightIdP-$rightId-$level+$levelP) /2) *2+$level-$levelP-1) , $this->left)) - . $this->right . '=' . - _case(_between($this->right, $rightId+1, $rightIdP-1), $this->right . '-' . ($rightId-$leftId+1) , - _case(_between($this->left, $leftId, $rightId), $this->right . '+' . ((($rightIdP-$rightId-$level+$levelP) /2) *2+$level-$levelP-1) , $this->right)) - . 'WHERE ' . _between($this->left, ($leftIdP+1), ($rightIdP-1)); - - } elseif ($leftIdP < $leftId) { - $this->sql = 'UPDATE ' . $this->table . ' SET ' - . $this->level . '=' . - _case(_between($this->left, $leftId, $rightId), - $this->level . sprintf('%+d', -($level-1) +$levelP) , $this->level) - . $this->left . '=' . - _case(_between($this->left, $rightIdP, $leftId-1), $this->left . '+' . ($rightId-$leftId+1), - _case(_between($this->left, $leftId, $rightId), $this->left . '-' . ($leftId-$rightIdP) , $this->left)) - . $this->right . '=' . - _case(_between($this->right, $rightIdP, $leftId), $this->right . '+' . ($rightId-$leftId+1), - _case(_between($this->right, $leftId, $rightId), $this->right . '-' . ($leftId-$rightIdP) , $this->right)) - . 'WHERE ' . _between($this->left, $leftIdP, $rightId) - // !!! added this line (Maxim Matyukhin) - . ' OR ' . _between($this->right, $leftIdP, $rightId); - } else { - $this->sql = 'UPDATE ' . $this->table . ' SET ' - . $this->level . '=' - . _case(_between($this->left, $leftId, $rightId), - $this->level . sprintf('%+d', -($level-1) +$levelP) , $this->level) - . $this->left . '=' . - _case(_between($this->left, $rightId, $rightIdP), $this->left . '-' . ($rightId-$leftId+1), - _case(_between($this->left, $leftId, $rightId), $this->left . '+' . ($rightIdP-1-$rightId), $this->left)) - . $this->right . '=' . - _case(_between($this->right, $rightId+1, $rightIdP-1), $this->right . '-' . ($rightId-$leftId+1), - _case(_between($this->right, $leftId, $rightId), $this->right . '+' . ($rightIdP-1-$rightId) , $this->right)) - . 'WHERE ' . _between($this->left, $leftId, $rightIdP) - // !!! added this line (Maxim Matyukhin) - . ' OR ' . _between($this->right, $leftId, $rightIdP); - } - return $this->db->query($this->sql) or trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR); - - } - - //************************************************************************ - // Deletes a record wihtout deleting its children - // $ID : an ID of the element to be deleted - // Returns : true on success, or false on error - function delete($ID) - { - - if (!(list($leftId, $rightId, $level) = $this->getNodeInfo($ID))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR); - // Deleting record - $this->sql = 'DELETE FROM ' . $this->table . ' WHERE ' . $this->id . '=\'' . $ID . '\''; - - if (!$this->db->query($this->sql)) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR); - // Clearing blank spaces in a tree - $this->sql = 'UPDATE ' . $this->table . ' SET ' - . $this->left . '=' . _case($this->left . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->left . '-1', $this->left) . ", " - . $this->right . '=' . _case($this->right . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->right . '-1', $this->right) . ", " - . $this->level . '=' . _case($this->left . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->level . '-1', $this->level) . ", " - . $this->left . '=' . _case($this->left . '>' . $rightId, $this->left . '-2', $this->left) . ", " - . $this->right . '=' . _case($this->right . '>' . $rightId, $this->right . '-2', $this->right) - . ' WHERE ' . $this->right . '>' . $leftId; - - if (!$this->db->query($this->sql)) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR); - return true; - } - - //************************************************************************ - // Deletes a record with all its children - // $ID : an ID of the element to be deleted - // Returns : true on success, or false on error - function deleteAll($ID) - { - - if (!(list($leftId, $rightId, $level) = $this->getNodeInfo($ID))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR); - // Deleteing record(s) - $this->sql = 'DELETE FROM ' . $this->table . ' WHERE ' . $this->left . ' BETWEEN ' . $leftId . ' AND ' . $rightId; - - if (!$this->db->query($this->sql)) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR); - // Clearing blank spaces in a tree - $deltaId = ($rightId-$leftId) +1; - $this->sql = 'UPDATE ' . $this->table . ' SET ' - . $this->left . '=' . _case($this->left . '>' . $leftId, $this->left . '-' . $deltaId, $this->left) . ", " - . $this->right . '=' . _case($this->right . '>' . $leftId, $this->right . '-' . $deltaId, $this->right) - . ' WHERE ' . $this->right . '>' . $rightId; - - if (!$this->db->query($this->sql)) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR); - return true; - } - - //************************************************************************ - // Enumerates children of an element - // $ID : an ID of an element which children to be enumerated - // $start_level : relative level from which start to enumerate children - // $end_level : the last relative level at which enumerate children - // 1. If $end_level isn't given, only children of - // $start_level levels are enumerated - // 2. Level values should always be greater than zero. - // Level 1 means direct children of the element - // Returns : a result id for using with other DB functions - function enumChildrenAll($ID) - { - return $this->enumChildren($ID, 1, 0); - } - - function enumChildren($ID, $start_level = 1, $end_level = 1) - { - if ($start_level < 0) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR); - // We could use sprintf() here, but it'd be too slow - $whereSql1 = ' AND ' . $this->table . '.' . $this->level; - $whereSql2 = '_' . $this->table . '.' . $this->level . '+'; - - if (!$end_level) $whereSql = $whereSql1 . '>=' . $whereSql2 . (int)$start_level; - else { - $whereSql = ($end_level <= $start_level) ? $whereSql1 . '=' . $whereSql2 . (int)$start_level : ' AND ' . $this->table . '.' . $this->level . ' BETWEEN _' . $this->table . '.' . $this->level . '+' . (int)$start_level . ' AND _' . $this->table . '.' . $this->level . '+' . (int)$end_level; - } - $this->sql = $this->sqlComposeSelect(array( - '', // Params - '', // Fields - $this->table . ' _' . $this->table . ', ' . $this->table, // Tables - '_' . $this->table . '.' . $this->id . '=\'' . $ID . '\'' . ' AND ' . $this->table . '.' . $this->left . ' BETWEEN _' . $this->table . '.' . $this->left . ' AND _' . $this->table . '.' . $this->right . $whereSql - )); - return $this->db->query($this->sql); - } - - function enumChildrenArray($ID, $start_level = 1, $end_level = 1) - { - return $this->db->result2array($this->enumChildren($ID, $start_level, $end_level)); - } - - //************************************************************************ - // Enumerates the PATH from an element to its top level parent - // $ID : an ID of an element - // $showRoot : whether to show root node in a path - // Returns : a result id for using with other DB functions - function enumPath($ID, $showRoot = false) - { - $this->sql = $this->sqlComposeSelect(array( - '', // Params - '', // Fields - $this->table . ' _' . $this->table . ', ' . $this->table, // Tables - '_' . $this->table . '.' . $this->id . '=\'' . $ID . '\'' . ' AND _' . $this->table . '.' . $this->left . ' BETWEEN ' . $this->table . '.' . $this->left . ' AND ' . $this->table . '.' . $this->right . (($showRoot) ? '' : ' AND ' . $this->table . '.' . $this->level . '>0') , // Where - '', // GroupBy - '', // Having - $this->table . '.' . $this->left // OrderBy - - )); - return $this->db->query($this->sql); - } - - function enumPathArray($ID, $showRoot = false) - { - return $this->db->result2array($this->enumPath($ID, $showRoot)); - } - - //************************************************************************ - // Returns query result to fetch data of the element's parent - // $ID : an ID of an element which parent to be retrieved - // $level : Relative level of parent - // Returns : a result id for using with other DB functions - function getParent($ID, $level = 1) - { - - if ($level < 1) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR); - $this->sql = $this->sqlComposeSelect(array( - '', // Params - '', // Fields - $this->table . ' _' . $this->table . ', ' . $this->table, // Tables - '_' . $this->table . '.' . $this->id . '=\'' . $ID . '\'' . ' AND _' . $this->table . '.' . $this->left . ' BETWEEN ' . $this->table . '.' . $this->left . ' AND ' . $this->table . '.' . $this->right . ' AND ' . $this->table . '.' . $this->level . '=_' . $this->table . '.' . $this->level . '-' . (int)$level // Where - - )); - $result = $this->db->result2array($this->db->query($this->sql)); - return (int)$result[0][$this->id]; - } - //************************************************************************ - - function sqlReset() - { - $this->qryParams = ''; - $this->qryFields = ''; - $this->qryTables = ''; - $this->qryWhere = ''; - $this->qryGroupBy = ''; - $this->qryHaving = ''; - $this->qryOrderBy = ''; - $this->qryLimit = ''; - return true; - } - - //************************************************************************ - function sqlSetReset($resetMode) - { - $this->sqlNeedReset = ($resetMode) ? true : false; - } - - //************************************************************************ - function sqlParams($param = '') - { - return (empty($param)) ? $this->qryParams : $this->qryParams = $param; - } - - function sqlFields($param = '') - { - return (empty($param)) ? $this->qryFields : $this->qryFields = $param; - } - - function sqlSelect($param = '') - { - return $this->sqlFields($param); - } - - function sqlTables($param = '') - { - return (empty($param)) ? $this->qryTables : $this->qryTables = $param; - } - - function sqlFrom($param = '') - { - return $this->sqlTables($param); - } - - function sqlWhere($param = '') - { - return (empty($param)) ? $this->qryWhere : $this->qryWhere = $param; - } - - function sqlGroupBy($param = '') - { - return (empty($param)) ? $this->qryGroupBy : $this->qryGroupBy = $param; - } - - function sqlHaving($param = '') - { - return (empty($param)) ? $this->qryHaving : $this->qryHaving = $param; - } - - function sqlOrderBy($param = '') - { - return (empty($param)) ? $this->qryOrderBy : $this->qryOrderBy = $param; - } - - function sqlLimit($param = '') - { - return (empty($param)) ? $this->qryLimit : $this->qryLimit = $param; - } - - //************************************************************************ - function sqlComposeSelect($arSql) - { - $joinTypes = array( - 'join' => 1, - 'cross' => 1, - 'inner' => 1, - 'straight' => 1, - 'left' => 1, - 'natural' => 1, - 'right' => 1 - ); - $this->sql = 'SELECT ' . $arSql[0] . ' '; - - if (!empty($this->qryParams)) $this->sql.= $this->sqlParams . ' '; - - if (empty($arSql[1]) && empty($this->qryFields)) $this->sql.= $this->table . '.' . $this->id; - else { - - if (!empty($arSql[1])) $this->sql.= $arSql[1]; - - if (!empty($this->qryFields)) $this->sql.= ((empty($arSql[1])) ? '' : ',') . $this->qryFields; - } - $this->sql.= ' FROM '; -// $tblAr = array(0 => 'join'); - $isJoin = ($tblAr = explode(' ', trim($this->qryTables))) - && /*($joinTypes[strtolower($tblAr[0]) ])*/ 1; - - if (empty($arSql[2]) && empty($this->qryTables)) $this->sql.= $this->table; - else { - - if (!empty($arSql[2])) $this->sql.= $arSql[2]; - - if (!empty($this->qryTables)) { - - if (!empty($arSql[2])) $this->sql.= (($isJoin) ? ' ' : ','); - elseif ($isJoin) $this->sql.= $this->table . ' '; - $this->sql.= $this->qryTables; - } - } - - if ((!empty($arSql[3])) || (!empty($this->qryWhere))) { - $this->sql.= ' WHERE ' . $arSql[3] . ' '; - - if (!empty($this->qryWhere)) $this->sql.= (empty($arSql[3])) ? $this->qryWhere : 'AND(' . $this->qryWhere . ')'; - } - - if ((!empty($arSql[4])) || (!empty($this->qryGroupBy))) { - $this->sql.= ' GROUP BY ' . $arSql[4] . ' '; - - if (!empty($this->qryGroupBy)) $this->sql.= (empty($arSql[4])) ? $this->qryGroupBy : ',' . $this->qryGroupBy; - } - - if ((!empty($arSql[5])) || (!empty($this->qryHaving))) { - $this->sql.= ' HAVING ' . $arSql[5] . ' '; - - if (!empty($this->qryHaving)) $this->sql.= (empty($arSql[5])) ? $this->qryHaving : 'AND(' . $this->qryHaving . ')'; - } - - if ((!empty($arSql[6])) || (!empty($this->qryOrderBy))) { - $this->sql.= ' ORDER BY ' . (isset($arSql[6]) ? $arSql[6] : '') . ' '; - - if (!empty($this->qryOrderBy)) $this->sql.= (empty($arSql[6])) ? $this->qryOrderBy : ',' . $this->qryOrderBy; - } - - if (!empty($arSql[7])) $this->sql.= ' LIMIT ' . $arSql[7]; - elseif (!empty($this->qryLimit)) $this->sql.= ' LIMIT ' . $this->qryLimit; - - if ($this->sqlNeedReset) $this->sqlReset(); - return $this->sql; - } - //************************************************************************ - -} diff --git a/src/Tree/Database.php b/src/Tree/Database.php deleted file mode 100644 index 9c29f18..0000000 --- a/src/Tree/Database.php +++ /dev/null @@ -1,135 +0,0 @@ - -// Category: Databases -//**************************************************************************** -// The lib is FREEWARE. This means you may use it anywhere you want, you may -// do anything with it. The Author mentioned above is NOT responsible for any -// consequences of using this library. -// If you don't agree with this, you MAY NOT use the lib! -//**************************************************************************** -// All improvings, feature requests, bug reports, etc. are gladly accepted. -//**************************************************************************** -// Note: For best viewing of the code Tab size 4 is recommended -//**************************************************************************** - -class Tree_Database -{ - var $link; - var $db; - var $host, $user, $pass; - - function CDatabase($db, $host = "localhost", $user = "", $pass = "") - { - $this->db = $db; - $this->host = $host; - $this->user = $user; - $this->pass = $pass; - $str = "host={$host} port=5432 dbname={$db} user={$user} password={$pass}"; - $this->link = pg_connect($str); - } - - function query($sql) - { - if (!$this->link) return 0; - return pg_query($this->link, $sql); - } - - function affected_rows() - { - return pg_affected_rows($this->link); - } - - function num_rows($q) - { - return pg_num_rows($q); - } - - function fetch_array($q) // fetchAll - { - return pg_fetch_array($q, NULL); - } - - function fetch_object($q) // fetchObject - { - return pg_fetch_object($q); - } - /* function data_seek($q, $n) { - return pg_data_seek($q, $n); - } - */ - - function free_result($q) - { - return pg_free_result($q); - } - - function insert_id($seq) - { - $query = "SELECT currval('$seq')"; - $res = $this->query($query); - $row = pg_fetch_array($res, NULL, PGSQL_ASSOC); - pg_free_result($res); - return ($row) ? $row['currval'] : 0; - } - - function error() - { - return pg_last_error($this->link); - } - - function error_die($msg = '') - { - die(((empty($msg)) ? '' : $msg . ': ') . $this->error()); - } - - function sql2var($sql) - { - - if ((empty($sql)) || (!($query = $this->query($sql)))) return false; - - if ($this->num_rows($query) < 1) return false; - return $this->result2var($query); - } - - function result2var($q) - { - - if (!($Data = $this->fetch_array($q))) return false; - $this->free_result($q); - - foreach($Data as $k => $v) $GLOBALS[$k] = $v; - return true; - } - - /*function sql2array($sql, $keyField = '') - { - - if ((empty($sql)) || (!($query = $this->query($sql)))) return false; - - if ($this->num_rows($query) < 1) return false; - return $this->result2array($query, $keyField); - }*/ - - function result2array($q, $keyField = '') - { - $Result = array(); - while ($Data = $this->fetch_array($q)) - if (empty($keyField)) $Result[] = $Data; - else $Result[$Data[$keyField]] = $Data; - $this->free_result($q); - return $Result; - } - - /*function list_tables() - { - return mysql_list_tables($this->db, $this->link); - } - - function list_fields($table_name) - { - return mysql_list_fields($this->db, $table_name, $this->link); - }*/ -}; diff --git a/src/Tree/Sort.php b/src/Tree/Sort.php deleted file mode 100644 index 7cf4477..0000000 --- a/src/Tree/Sort.php +++ /dev/null @@ -1,79 +0,0 @@ -sortBy($data, 'name'); - */ -class Tree_Sort { - private $data = array(); - private $result = array(); - private $sortBy = ''; - - public function __construct() { - } - - // Преобразуем Nested Set в дерево и сортируем - private function listTree(array $tree, $offset, $level) { - $result = array(); - for ($i = $offset; $i < sizeof($tree); $i++) { - $leaf = $tree[$i]; - $clevel = $leaf['cat_level']; - if ($clevel == $level) { - $result [] = array($i); - } else if ($clevel > $level) { - list($subtree, $i) = $this->listTree($tree, $i, $clevel); - $i--; - $result[sizeof($result) - 1][1] = $subtree; - } else { - $this->sortList($result, $tree); - return array($result, $i); - } - } - $this->sortList($result, $tree); - return array($result, $i); - } - - // Сравнение двух элементов - private function compare($a, $b) { - $a1 = $this->data[$a[0]][$this->sortBy]; - $b1 = $this->data[$b[0]][$this->sortBy]; - return strcmp($a1, $b1); - } - - // Сортировка списка - private function sortList(array &$list, $data) { - usort($list, array($this, 'compare')); - } - - // Создает дерево в виде списка - private function reorder(array $tree) { - foreach($tree as $node) { - $this->result[] = $this->data[$node[0]]; - if (isset($node[1])) { - $this->reorder($node[1]); - } - } - } - - public function sortBy0(array $data, $sortBy) - { - $this->data = $data; - $this->sortBy = $sortBy; - $order = $this->listTree($data, 0, 0); - return $order[0]; - } - - // Сортировка по заданному полю - public function sortBy(array $data, $sortBy) { - $this->data = $data; - $this->sortBy = $sortBy; - $order = $this->listTree($data, 0, 0); - $this->reorder($order[0]); - return $this->result; - } -} diff --git a/src/UTF8.php b/src/UTF8.php new file mode 100644 index 0000000..3cc68b8 --- /dev/null +++ b/src/UTF8.php @@ -0,0 +1,12 @@ +get($this->field)); + } +} diff --git a/src/Validator/Validator.php b/src/Validator/Validator.php index 8feebe6..4f053a4 100644 --- a/src/Validator/Validator.php +++ b/src/Validator/Validator.php @@ -1,5 +1,7 @@ + /** * Проверка коллекции */ @@ -66,8 +68,7 @@ class Validator_Validator } } - public function addRule(&$rule) - { + public function addRule(/*.any.*/&$rule) { if (is_array($rule)) { $this->chain = array_merge($this->chain, $rule); } else { diff --git a/src/View/Page.php b/src/View/Page.php new file mode 100644 index 0000000..acddc60 --- /dev/null +++ b/src/View/Page.php @@ -0,0 +1,73 @@ +]*>/u'; + $matches = array(); + preg_match_all($pattern, $data, $matches, PREG_OFFSET_CAPTURE, 0); + + $split = array(); + $offset = 0; + foreach ($matches[0] as $key => $match) { + $text = $this->fixHTML(substr($data, $offset, $match[1] - $offset)); + if (trim($text)) { + $split[] = array('type' => 'page-text', 'content' => $text, 'component' => '', 'module' => ''); + } + $offset = $match[1] + strlen($match[0]); + $split[] = $this->replaceContent($matches[3][$key][0], $matches[3][$key][1]); + } + $text = $this->fixHTML(substr($data, $offset)); + if (trim($text)) { + $split[] = array('type' => 'page-text', 'content' => $text, 'component' => '', 'module' => ''); + } + + $this->text = $this->merge($split); + } + + function fixHTML($fragment) { + return $fragment; + } + + function merge($data) { + if (count($data) == 0) { + $data[] = array('type' => 'page-text', 'content' =>"

Добавьте текст

", 'component' => '', 'module' => ''); + } + $result = array(); + foreach($data as $key => $part) { + $result[] = $part['content']; + } + return implode("", $result); + } + + function replaceContent($match, $offset) + { + //$result = phptal_component($match, $offset); + + //* + global $db, $registry; // Нужно как-то передавать параметры + + $component = Controller_Component::loadComponent($match, $db, $registry); + $req = new HttpRequest(); + unset($req['active_page']); + + $info = $component->getInfo(); + $result = $component->execute($req); + + if (is_string($result)) { + return array('type' => 'page-component', 'content' => $result, 'component' => $match); + } else { + $this->setView('view' . $this->counter++, $result); + return array('type' => 'page-component', 'content' => $result->execute(), 'component' => $match); + } + } + + function execute() { + return $this->text; + } +} diff --git a/src/View/Plain.php b/src/View/Plain.php new file mode 100644 index 0000000..67d4521 --- /dev/null +++ b/src/View/Plain.php @@ -0,0 +1,48 @@ +document = $document; + } + + public function set($key, $value) + { + $this->values[$key] = $value; + } + + public function import($list) + { + $this->values = array_merge($this->values, $list); + } + + public function __set($key, $value) + { + $this->set($key, $value); + } + + public function execute() + { + $result = $this->values; + return self::getTemplateContent ($this->document, $result); + } + + static function getTemplateContent($document, $result) + { + ob_start (); + include ($document); + $content = ob_get_contents (); + ob_clean (); + return $content; + } +} diff --git a/src/View/View.php b/src/View/View.php index 979cae0..cd51d8b 100644 --- a/src/View/View.php +++ b/src/View/View.php @@ -1,40 +1,203 @@ View_Base + View_List + View_Template class View_View { - protected $document; - protected $values; + protected $_section = array(); // Вложенные шаблоны + // Блоки + protected $_stylesheet = array(); // Массив стилей текущего шаблона + protected $_script = array(); // Массив скриптов текущего шаблона + protected $_scriptstring = array(); + protected $_startup = array(); + protected $_values = array(); - public function __construct ($document) - { - $this->document = $document; + protected $_title = null; // Заголовок текущего шаблона + + public $active_module; + public $module_action; + + public $suggestions; //подсказки + + public $alias = array(); + public $codeGenerator = null; + public $parent_view = null; + + function __construct() { } - public function set($key, $value) + /** + * Связывет переменную с вложенным шаблоном + * + * @param string $section переменная шаблона + * @param CompositeView $view вложенный шаблон + */ + public function setView($section, View_View $view) { - $this->values[$key] = $value; + $this->_section [$section] = $view; + $view->parent_view = $this; } - public function __set($key, $value) + public function assignValues($values) { - $this->set($key, $value); + $this->_values = $values; + $this->_values["suggestions"] = $this->suggestions; } - public function execute() + public function jGrowl($message, $args) { - $result = $this->values; - return self::getTemplateContent ($this->document, $result); + $this->addScriptRaw('$.jGrowl("' . $message . '", ' . json_encode($args) . ");\n", true); } - static function getTemplateContent($document, $result) + public function setGlobal($name, $args) { - ob_start (); - include ($document); - $result = ob_get_contents (); - ob_clean (); + $this->addScriptRaw("var " . $name . " = " . json_encode($args) . ";\n", false); + } + + /** + * Добавляет скипт к текущему шаблону + * + * @param string $name путь к скрипту + */ + public function addScript($name) + { + $output = $this->resolveName($this->alias, $name); + $this->_script [] = $output; + } + + /** + * Добавляет код скипта к текущему шаблону + * + * @param string $name строка javascript кода + */ + public function addScriptRaw($name, $startup = false) + { + if ($startup) { + $this->_startup [] = $name; + } else { + $this->_scriptstring [] = $name; + } + } + + /** + * Добавляет стили к текущему шаблону + * + * @param string $name путь к стилю + */ + public function addStyleSheet($name) + { + $output = $this->resolveName($this->alias, $name); + $this->_stylesheet [] = $output; + } + + /** + * Рекурсивно извлекает из значение свойства обьекта + * + * @param string $list Имя свойства + * @param boolean $flatten + */ + protected function doTree($list, $flatten = true) + { + $result = ($flatten == true) ? $this->$list : array($this->$list); + foreach ($this->_section as $value) { + if (is_object($value)) { + if ($list == '_script' || $list == '_stylesheet') { + $result = array_merge($result, $value->doTree($list, $flatten)); + } else { + $result = array_merge($value->doTree($list, $flatten), $result); + } + } + } return $result; } -} + + /*abstract*/ public function set($key, $value) + { + } + + /** + * Обработка всех вложенных шаблонов + * + * @return string + */ + public function execute() + { + foreach ($this->_section as $key => $value) { + $this->set($key, (is_object($value)) ? $value->execute() : $value); // ? + } + } + + /** + * Установка заголовка шаблона + * + * @param string $title + */ + public function setTitle($title) + { + $this->_title = $title; + } + + protected function isNotNull($title) + { + return $title !== null; + } + + function setAlias($alias) + { + $this->alias = $alias; + } + + function addAlias($name, $path) + { + $this->alias[$name] = $path; + $this->set($name, $path); + } + + function find_file($pathlist, $file) { + foreach($pathlist as $key => $www) { + if (file_exists($key . '/' . $file)) { + return $www . '/' . $file; + } + } + throw new Exception("file not found: $file"); + } + + function resolveName($alias, $file) { + list($type, $filename) = explode(":", $file, 2); + + // Сделать поиск а не просто замену папки при совпадении имени + if (is_array($alias[$type])) { + $output = $this->find_file($alias[$type], $filename); + } else { + $output = $alias[$type] . '/' . $filename; + } + return $output; + } + + function loadImports($importFile) + { + $types = array( + 'js' => array($this, 'addScript'), + 'css' => array($this, 'addStyleSheet') + ); + // Подключение стилей и скриптов + if (file_exists($importFile)) { + $files = file($importFile); + foreach ($files as $file) { + // Получить расширение вместо strpos + $file = trim($file); + if (!empty($file)) { + $ext = pathinfo($file, PATHINFO_EXTENSION); + call_user_func($types[$ext], $file); + } + } + } + } + + public function resolveAllNames($alias, $list) { + $result = array(); + foreach($list as $item) { + $result [] = $this->resolveName($alias, $item); + } + return $result; + } +} \ No newline at end of file diff --git a/src/View/list.php b/src/View/list.php new file mode 100644 index 0000000..8522b32 --- /dev/null +++ b/src/View/list.php @@ -0,0 +1,13 @@ +_section as $key => $value) { + $result [] = $value->execute(); + } + return $result; + } +} diff --git a/src/data/areas.php b/src/data/areas.php deleted file mode 100644 index a864edf..0000000 --- a/src/data/areas.php +++ /dev/null @@ -1,26 +0,0 @@ - '', - 1 => 'Город Ярославль', - 2 => 'Большесельский район', - 3 => 'Борисоглебский район', - 4 => 'Брейтовский район', - 5 => 'Гаврилов-Ямский район', - 6 => 'Даниловский район', - 7 => 'Любимский район', - 8 => 'Мышкинский район', - 9 => 'Некоузский район', - 10 => 'Некрасовский район', - 11 => 'Переславский район', - 12 => 'Первомайский район', - 13 => 'Пошехонский район', - 14 => 'Ростовский район', - 15 => 'Рыбинский район', - 16 => 'Тутаевский район', - 17 => 'Угличский район', - 18 => 'Ярославский район', - 19 => 'Город Переславль', - 20 => 'Город Рыбинск' -); diff --git a/src/data/city-short.php b/src/data/city-short.php deleted file mode 100644 index bea4476..0000000 --- a/src/data/city-short.php +++ /dev/null @@ -1,14 +0,0 @@ - '', - 1 => 'г.', - 2 => 'с.', - 3 => 'п.', - 4 => 'д.', - 5 => 'пгт.', - 6 => 'р.п.', - 7 => 'ст.', - 8 => 'а.' -); - diff --git a/src/data/city.php b/src/data/city.php deleted file mode 100644 index 5fb0bef..0000000 --- a/src/data/city.php +++ /dev/null @@ -1,14 +0,0 @@ - '', - 1 => 'город', - 2 => 'село', - 3 => 'поселок', - 4 => 'деревня', - 5 => 'поселок городского типа', - 6 => 'рабочий поселок', - 7 => 'станица', - 8 => 'аул' -); diff --git a/src/data/mime.php b/src/data/mime.php deleted file mode 100644 index be65117..0000000 --- a/src/data/mime.php +++ /dev/null @@ -1,196 +0,0 @@ - "application/octet-stream", - "323" => "text/h323", - "acx" => "application/internet-property-stream", - "ai" => "application/postscript", - "aif" => "audio/x-aiff", - "aifc" => "audio/x-aiff", - "aiff" => "audio/x-aiff", - "asf" => "video/x-ms-asf", - "asr" => "video/x-ms-asf", - "asx" => "video/x-ms-asf", - "au" => "audio/basic", - "avi" => "video/x-msvideo", - "axs" => "application/olescript", - "bas" => "text/plain", - "bcpio" => "application/x-bcpio", - "bin" => "application/octet-stream", - "bmp" => "image/bmp", - "c" => "text/plain", - "cat" => "application/vnd.ms-pkiseccat", - "cdf" => "application/x-cdf", - "cer" => "application/x-x509-ca-cert", - "class" => "application/octet-stream", - "clp" => "application/x-msclip", - "cmx" => "image/x-cmx", - "cod" => "image/cis-cod", - "cpio" => "application/x-cpio", - "crd" => "application/x-mscardfile", - "crl" => "application/pkix-crl", - "crt" => "application/x-x509-ca-cert", - "csh" => "application/x-csh", - "css" => "text/css", - "dcr" => "application/x-director", - "der" => "application/x-x509-ca-cert", - "dir" => "application/x-director", - "dll" => "application/x-msdownload", - "dms" => "application/octet-stream", - "doc" => "application/msword", - "dot" => "application/msword", - "dvi" => "application/x-dvi", - "dxr" => "application/x-director", - "eps" => "application/postscript", - "etx" => "text/x-setext", - "evy" => "application/envoy", - "exe" => "application/octet-stream", - "fif" => "application/fractals", - "flr" => "x-world/x-vrml", - "gif" => "image/gif", - "gtar" => "application/x-gtar", - "gz" => "application/x-gzip", - "h" => "text/plain", - "hdf" => "application/x-hdf", - "hlp" => "application/winhlp", - "hqx" => "application/mac-binhex40", - "hta" => "application/hta", - "htc" => "text/x-component", - "htm" => "text/html", - "html" => "text/html", - "htt" => "text/webviewhtml", - "ico" => "image/x-icon", - "ief" => "image/ief", - "iii" => "application/x-iphone", - "ins" => "application/x-internet-signup", - "isp" => "application/x-internet-signup", - "jfif" => "image/pipeg", - "jpe" => "image/jpeg", - "jpeg" => "image/jpeg", - "jpg" => "image/jpeg", - "js" => "application/x-javascript", - "latex" => "application/x-latex", - "lha" => "application/octet-stream", - "lsf" => "video/x-la-asf", - "lsx" => "video/x-la-asf", - "lzh" => "application/octet-stream", - "m13" => "application/x-msmediaview", - "m14" => "application/x-msmediaview", - "m3u" => "audio/x-mpegurl", - "man" => "application/x-troff-man", - "mdb" => "application/x-msaccess", - "me" => "application/x-troff-me", - "mht" => "message/rfc822", - "mhtml" => "message/rfc822", - "mid" => "audio/mid", - "mny" => "application/x-msmoney", - "mov" => "video/quicktime", - "movie" => "video/x-sgi-movie", - "mp2" => "video/mpeg", - "mp3" => "audio/mpeg", - "mpa" => "video/mpeg", - "mpe" => "video/mpeg", - "mpeg" => "video/mpeg", - "mpg" => "video/mpeg", - "mpp" => "application/vnd.ms-project", - "mpv2" => "video/mpeg", - "ms" => "application/x-troff-ms", - "mvb" => "application/x-msmediaview", - "nws" => "message/rfc822", - "oda" => "application/oda", - "p10" => "application/pkcs10", - "p12" => "application/x-pkcs12", - "p7b" => "application/x-pkcs7-certificates", - "p7c" => "application/x-pkcs7-mime", - "p7m" => "application/x-pkcs7-mime", - "p7r" => "application/x-pkcs7-certreqresp", - "p7s" => "application/x-pkcs7-signature", - "pbm" => "image/x-portable-bitmap", - "pdf" => "application/pdf", - "pfx" => "application/x-pkcs12", - "pgm" => "image/x-portable-graymap", - "pko" => "application/ynd.ms-pkipko", - "pma" => "application/x-perfmon", - "pmc" => "application/x-perfmon", - "pml" => "application/x-perfmon", - "pmr" => "application/x-perfmon", - "pmw" => "application/x-perfmon", - "pnm" => "image/x-portable-anymap", - "pot," => "application/vnd.ms-powerpoint", - "ppm" => "image/x-portable-pixmap", - "pps" => "application/vnd.ms-powerpoint", - "ppt" => "application/vnd.ms-powerpoint", - "prf" => "application/pics-rules", - "ps" => "application/postscript", - "pub" => "application/x-mspublisher", - "qt" => "video/quicktime", - "ra" => "audio/x-pn-realaudio", - "ram" => "audio/x-pn-realaudio", - "ras" => "image/x-cmu-raster", - "rgb" => "image/x-rgb", - "rmi" => "audio/mid", - "roff" => "application/x-troff", - "rtf" => "application/rtf", - "rtx" => "text/richtext", - "scd" => "application/x-msschedule", - "sct" => "text/scriptlet", - "setpay" => "application/set-payment-initiation", - "setreg" => "application/set-registration-initiation", - "sh" => "application/x-sh", - "shar" => "application/x-shar", - "sit" => "application/x-stuffit", - "snd" => "audio/basic", - "spc" => "application/x-pkcs7-certificates", - "spl" => "application/futuresplash", - "src" => "application/x-wais-source", - "sst" => "application/vnd.ms-pkicertstore", - "stl" => "application/vnd.ms-pkistl", - "stm" => "text/html", - "svg" => "image/svg+xml", - "sv4cpio" => "application/x-sv4cpio", - "sv4crc" => "application/x-sv4crc", - "swf" => "application/x-shockwave-flash", - "t" => "application/x-troff", - "tar" => "application/x-tar", - "tcl" => "application/x-tcl", - "tex" => "application/x-tex", - "texi" => "application/x-texinfo", - "texinfo" => "application/x-texinfo", - "tgz" => "application/x-compressed", - "tif" => "image/tiff", - "tiff" => "image/tiff", - "tr" => "application/x-troff", - "trm" => "application/x-msterminal", - "tsv" => "text/tab-separated-values", - "txt" => "text/plain", - "uls" => "text/iuls", - "ustar" => "application/x-ustar", - "vcf" => "text/x-vcard", - "vrml" => "x-world/x-vrml", - "wav" => "audio/x-wav", - "wcm" => "application/vnd.ms-works", - "wdb" => "application/vnd.ms-works", - "wks" => "application/vnd.ms-works", - "wmf" => "application/x-msmetafile", - "wps" => "application/vnd.ms-works", - "wri" => "application/x-mswrite", - "wrl" => "x-world/x-vrml", - "wrz" => "x-world/x-vrml", - "xaf" => "x-world/x-vrml", - "xbm" => "image/x-xbitmap", - "xla" => "application/vnd.ms-excel", - "xlc" => "application/vnd.ms-excel", - "xlm" => "application/vnd.ms-excel", - "xls" => "application/vnd.ms-excel", - "xlt" => "application/vnd.ms-excel", - "xlw" => "application/vnd.ms-excel", - "xof" => "x-world/x-vrml", - "xpm" => "image/x-xpixmap", - "xwd" => "image/x-xwindowdump", - "z" => "application/x-compress", - "zip" => "application/zip", -); - diff --git a/src/data/okato.php b/src/data/okato.php deleted file mode 100644 index a066e66..0000000 --- a/src/data/okato.php +++ /dev/null @@ -1,35 +0,0 @@ - "район", - "г" => "город", - "пгт" => "поселок городского типа", - "рп" => "рабочий поселок", - "кп" => "курортный поселок", - "к" => "кишлак", - "пс" => "поселковый совет", - "сс" => "сельсовет", - "смн" => "сомон", - "вл" => "волость", - "дп" => "дачный поселковый совет", - "п" => "поселок сельского типа", - "нп" => "населенный пункт", - "п. ст" => "поселок при станции", - "ж/д ст" => "железнодорожная станция", - "с" => "село", - "м" => "местечко", - "д" => "деревня", - "сл" => "слобода", - "ст" => "станция", - "ст-ца" => "станица", - "х" => "хутор", - "у" => "улус", - "рзд" => "разъезд", - "клх" => "колхоз", - "им" => "имени", - "свх" => "совхоз", - "зим" => "зимовье", -); - diff --git a/src/data/regions.php b/src/data/regions.php deleted file mode 100644 index e2fb520..0000000 --- a/src/data/regions.php +++ /dev/null @@ -1,91 +0,0 @@ - '', - 2 => 'Алтайский край', - 3 => 'Амурская область', - 4 => 'Архангельская область', - 5 => 'Астраханская область', - 6 => 'Белгородская область', - 7 => 'Брянская область', - 8 => 'Владимирская область', - 9 => 'Волгоградская область', - 10 => 'Вологодская область', - 11 => 'Воронежская область', - 12 => 'г. Москва', - 13 => 'г. Санкт-Петербург', - 14 => 'Еврейская автономная область', - 84 => 'Забайкальский край', - 15 => 'Ивановская область', - 16 => 'Иркутская область', - 17 => 'Кабардино-Балкарская Республика', - 18 => 'Калининградская область', - 19 => 'Калужская область', - 20 => 'Камчатский край', - 21 => 'Карачаево-Черкесская Республика', - 22 => 'Кемеровская область', - 23 => 'Кировская область', - 28 => 'Костромская область', - 29 => 'Краснодарский край', - 30 => 'Красноярский край', - 31 => 'Курганская область', - 32 => 'Курская область', - 33 => 'Ленинградская область', - 34 => 'Липецкая область', - 35 => 'Магаданская область', - 36 => 'Московская область', - 37 => 'Мурманская область', - 38 => 'Ненецкий автономный округ', - 39 => 'Нижегородская область', - 40 => 'Новгородская область', - 41 => 'Новосибирская область', - 42 => 'Омская область', - 43 => 'Оренбургская область', - 44 => 'Орловская область', - 45 => 'Пензенская область', - 46 => 'Пермский край', - 47 => 'Приморский край', - 48 => 'Псковская область', - 49 => 'Республика Адыгея', - 50 => 'Республика Алтай', - 51 => 'Республика Башкортостан', - 52 => 'Республика Бурятия', - 25 => 'Республика Дагестан', - 26 => 'Республика Ингушетия', - 53 => 'Республика Калмыкия', - 54 => 'Республика Карелия', - 55 => 'Республика Коми', - 56 => 'Республика Марий Эл', - 57 => 'Республика Мордовия', - 58 => 'Республика Саха(Якутия)', - 59 => 'Республика Северная Осетия-Алания', - 60 => 'Республика Татарстан', - 61 => 'Республика Тыва', - 62 => 'Республика Хакасия', - 63 => 'Ростовская область', - 64 => 'Рязанская область', - 65 => 'Самарская область', - 66 => 'Саратовская область', - 67 => 'Сахалинская область', - 68 => 'Свердловская область', - 69 => 'Смоленская область', - 70 => 'Ставропольский край', - 71 => 'Таймырский (Долгано-Ненецкий) автономный округ', - 72 => 'Тамбовская область', - 73 => 'Тверская область', - 74 => 'Томская область', - 75 => 'Тульская область', - 76 => 'Тюменская область', - 77 => 'Удмуртская Республика', - 78 => 'Ульяновская область', - 80 => 'Хабаровский край', - 81 => 'Ханты-Мансийский автономный округ', - 82 => 'Челябинская область', - 83 => 'Чеченская Республика', - 85 => 'Чувашская Республика', - 86 => 'Чукотский автономный округ', - 87 => 'Эвенкийский автономный округ', - 88 => 'Ямало-Ненецкий автономный округ', - 89 => 'Ярославская область' -); - diff --git a/src/data/states.php b/src/data/states.php deleted file mode 100644 index 346cae4..0000000 --- a/src/data/states.php +++ /dev/null @@ -1,32 +0,0 @@ - array('title' => ''), - 1 => array( - 'title' => 'Центральный федеральный округ', - 'short' => 'ЦФО', - 'regions' => array(6, 7, 8, 11, 12, 15, 19, 28, 32, 34, 36, 44, 64, 69, 72, 73, 75, 89)), - 2 => array( - 'title' => 'Южный федеральный округ', - 'short' => 'ЮФО', - 'regions' => array(5, 9, 17, 21, 29, 49, 25, 26, 53, 59, 63, 70, 83)), - 3 => array( - 'title' => 'Северо-западный федеральный округ', - 'short' => 'СЗФО', - 'regions' => array(4, 10, 13, 18, 33, 37, 38, 40, 48, 54, 55)), - 4 => array( - 'title' => 'Дальневосточный федеральный округ', - 'short' => 'ДФО', - 'regions' => array(3, 14, 20, 35, 47, 58, 67, 80, 86)), - 5 => array( - 'title' => 'Сибирский федеральный округ', - 'short' => 'СФО', - 'regions' => array(2, 16, 22, 30, 41, 42, 50, 52, 61, 62, 71, 74, 84, 86, 87)), - 6 => array( - 'title' => 'Уральский федеральный округ', - 'short' => 'УФО', - 'regions' => array(31, 68, 76, 81, 82, 88)), - 7 => array( - 'title' => 'Приволжский федеральный округ', - 'short' => 'ПФО', - 'regions' => array(23, 39, 43, 45, 46, 51, 56, 57, 60, 65, 66, 77, 78, 85))); diff --git a/src/process.php b/src/process.php new file mode 100644 index 0000000..c32c284 --- /dev/null +++ b/src/process.php @@ -0,0 +1,41 @@ +execute($req); + $result = $component->execute($req); + + echo ""; + return $result; } From 7ce493414e6d9a505f82dc8df6362a814b32dd6c Mon Sep 17 00:00:00 2001 From: origami11 Date: Fri, 17 Feb 2017 17:08:18 +0300 Subject: [PATCH 12/13] =?UTF-8?q?=D0=A0=D0=B0=D0=B7=D0=B1=D0=B8=D0=BB=20?= =?UTF-8?q?=D1=84=D0=B0=D0=B9=D0=BB=20exceltable=20=D0=BD=D0=B0=20=D0=BA?= =?UTF-8?q?=D0=BB=D0=B0=D1=81=D1=81=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Database/PDOStatement.php | 4 +- src/Excel/DataTime.php | 16 +++ src/Excel/Document.php | 100 ++++++++++++++ src/Excel/Number.php | 17 +++ src/{Tools/ExcelTable.php => Excel/Table.php} | 130 +----------------- 5 files changed, 135 insertions(+), 132 deletions(-) create mode 100644 src/Excel/DataTime.php create mode 100644 src/Excel/Document.php create mode 100644 src/Excel/Number.php rename src/{Tools/ExcelTable.php => Excel/Table.php} (71%) diff --git a/src/Database/PDOStatement.php b/src/Database/PDOStatement.php index 971afb8..4561611 100644 --- a/src/Database/PDOStatement.php +++ b/src/Database/PDOStatement.php @@ -1,7 +1,5 @@ fields[$name]); + return Tools_String::strToArray($this->fields[$name]); } function getRecordCount() { diff --git a/src/Excel/DataTime.php b/src/Excel/DataTime.php new file mode 100644 index 0000000..0536cbd --- /dev/null +++ b/src/Excel/DataTime.php @@ -0,0 +1,16 @@ +value = intval($value); + } + + function getString() + { + return date('Y-m-d\TH:i:s.u', $this->value); + } +} diff --git a/src/Excel/Document.php b/src/Excel/Document.php new file mode 100644 index 0000000..e46ff31 --- /dev/null +++ b/src/Excel/Document.php @@ -0,0 +1,100 @@ +table [] = $table; + } + + /** + * Добавление стиля к документу + * @param $name string Имя стиля + * @param $values array Параметры стиля + * @param $type Тип стиля + */ + function setStyle ($name, array $values, $type = 'Interior') + { + if(!isset($this->styles[$name])) { + $this->styles[$name] = array(); + } + $this->styles[$name][$type] = $values; + } + + /** + * Генерация стилей + */ + private function createStyles (XMLWriter $doc) { + $doc->startElement('Styles'); + foreach ($this->styles as $name => $sn) { + $doc->startElement('Style'); + $doc->writeAttribute('ss:ID', $name); + foreach ($sn as $type => $s) { + // Стиль Borders - составной + if ($type == 'Borders') { + $doc->startElement('Borders'); + foreach ($s as $border) { + /*.array.*/$border = $border; + $doc->startElement('Border'); + foreach ($border as $key => $value) { + $doc->writeAttribute('ss:' . $key, $value); + } + $doc->endElement(); + } + $doc->endElement(); + } else { + $doc->startElement($type); + foreach ($s as $key => $value) { + $doc->writeAttribute('ss:' . $key, $value); + } + $doc->endElement(); + } + } + $doc->endElement(); + } + $doc->endElement(); + } + + /** + * Преобразует переводы строки в спец символы + */ + function clean ($s) { + assert(is_string($s)); + + return strtr($s, array ("\n" => " ")); + } + + /** + * Сохраняет таблицу в формате Office 2003 XML + * http://en.wikipedia.org/wiki/Microsoft_Office_XML_formats + */ + function save($filename) + { + $doc = new XMLWriter(); + $doc->openURI($filename); + $doc->setIndent(false); + $doc->startDocument('1.0','utf-8'); + $doc->startElement('Workbook'); + $doc->writeAttribute('xmlns', self::$ns); + $doc->writeAttribute('xmlns:ss', self::$ns); + + $this->createStyles($doc); + + foreach ($this->table as $table) { + if ($table instanceof Excel_Table) { + $table->createTable($doc); + } else { + $table_data = call_user_func($table); + $table_data->createTable($doc); + unset($table_data); + } + } + $doc->endElement(); + } +} + diff --git a/src/Excel/Number.php b/src/Excel/Number.php new file mode 100644 index 0000000..66dd6b6 --- /dev/null +++ b/src/Excel/Number.php @@ -0,0 +1,17 @@ +value = intval($value); + } + + function getString() + { + return $this->value; + } +} + diff --git a/src/Tools/ExcelTable.php b/src/Excel/Table.php similarity index 71% rename from src/Tools/ExcelTable.php rename to src/Excel/Table.php index bc7ea38..162c823 100644 --- a/src/Tools/ExcelTable.php +++ b/src/Excel/Table.php @@ -1,35 +1,5 @@ value = intval($value); - } - - function getString() - { - return $this->value; - } -} - -class Excel_DateTime -{ - public $value; - - function __construct($value) - { - $this->value = intval($value); - } - - function getString() - { - return date('Y-m-d\TH:i:s.u', $this->value); - } -} - /** * Клетка таблицы */ @@ -68,7 +38,7 @@ class TableRow /** * Таблица */ -class ExcelTable +class Excel_Table { static $index; private $name; @@ -339,101 +309,3 @@ class ExcelTable } } -/** - * Документ - */ -class ExcelDocument { - static $ns = "urn:schemas-microsoft-com:office:spreadsheet"; - private $table = array (); - protected $styles = array(); - - function addTable($table) { - $this->table [] = $table; - } - - /** - * Добавление стиля к документу - * @param $name string Имя стиля - * @param $values array Параметры стиля - * @param $type Тип стиля - */ - function setStyle ($name, array $values, $type = 'Interior') - { - if(!isset($this->styles[$name])) { - $this->styles[$name] = array(); - } - $this->styles[$name][$type] = $values; - } - - /** - * Генерация стилей - */ - private function createStyles (XMLWriter $doc) { - $doc->startElement('Styles'); - foreach ($this->styles as $name => $sn) { - $doc->startElement('Style'); - $doc->writeAttribute('ss:ID', $name); - foreach ($sn as $type => $s) { - // Стиль Borders - составной - if ($type == 'Borders') { - $doc->startElement('Borders'); - foreach ($s as $border) { - /*.array.*/$border = $border; - $doc->startElement('Border'); - foreach ($border as $key => $value) { - $doc->writeAttribute('ss:' . $key, $value); - } - $doc->endElement(); - } - $doc->endElement(); - } else { - $doc->startElement($type); - foreach ($s as $key => $value) { - $doc->writeAttribute('ss:' . $key, $value); - } - $doc->endElement(); - } - } - $doc->endElement(); - } - $doc->endElement(); - } - - /** - * Преобразует переводы строки в спец символы - */ - function clean ($s) { - assert(is_string($s)); - - return strtr($s, array ("\n" => " ")); - } - - /** - * Сохраняет таблицу в формате Office 2003 XML - * http://en.wikipedia.org/wiki/Microsoft_Office_XML_formats - */ - function save($filename) - { - $doc = new XMLWriter(); - $doc->openURI($filename); - $doc->setIndent(false); - $doc->startDocument('1.0','utf-8'); - $doc->startElement('Workbook'); - $doc->writeAttribute('xmlns', self::$ns); - $doc->writeAttribute('xmlns:ss', self::$ns); - - $this->createStyles($doc); - - foreach ($this->table as $table) { - if ($table instanceof ExcelTable) { - $table->createTable($doc); - } else { - $table_data = call_user_func($table); - $table_data->createTable($doc); - unset($table_data); - } - } - $doc->endElement(); - } -} - From 75bb35d5bfe89599aabe98af164e75ae3c27f780 Mon Sep 17 00:00:00 2001 From: origami11 Date: Fri, 17 Feb 2017 17:31:17 +0300 Subject: [PATCH 13/13] =?UTF-8?q?=D0=92=D0=B5=D1=80=D1=81=D0=B8=D1=8F=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=BB=D0=BD=D0=BE=D1=81=D1=82=D1=8C=D1=8E=20=D1=81?= =?UTF-8?q?=D0=BE=D0=B2=D0=BC=D0=B5=D1=81=D1=82=D0=B8=D0=BC=D0=B0=D1=8F=20?= =?UTF-8?q?c=20CMS?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Controller/Action.php | 227 ++++++++++++------- src/Controller/Component.php | 366 +++++++++++++++++++++---------- src/Controller/Front.php | 58 +++-- src/Controller/Installer.php | 46 +++- src/Controller/Model.php | 354 +++++++++++++++++++----------- src/Database/PDOStatement.php | 4 +- src/Filter/Login.php | 112 ++++++++-- src/Form/Form.php | 300 +++++++++++++++++++++---- src/Primitive.php | 160 ++++++++------ src/Tools/String.php | 154 ++++++++----- src/Validator/Rule/Alpha.php | 2 +- src/Validator/Rule/Date.php | 2 +- src/Validator/Rule/Email.php | 2 +- src/Validator/Rule/EmailList.php | 2 +- src/Validator/Rule/Match.php | 10 +- src/Validator/Rule/Numeric.php | 2 +- src/Validator/Rule/Time.php | 2 +- src/Validator/Rule/Unique.php | 5 +- src/Validator/Validator.php | 25 ++- src/View/Composite.php | 25 ++- src/View/Top.php | 329 +++++++++++---------------- 21 files changed, 1404 insertions(+), 783 deletions(-) diff --git a/src/Controller/Action.php b/src/Controller/Action.php index 6e51caa..4ddeb58 100644 --- a/src/Controller/Action.php +++ b/src/Controller/Action.php @@ -13,7 +13,7 @@ function forceUrl($name) /** * Контроллер страниц - */ + */ class Controller_Action { @@ -24,9 +24,16 @@ class Controller_Action public $themePath; // Глобальный путь к текущей теме // Параметры устанавливаются при создании контроллера - public $name; // Имя модуля - public $viewPath = null; // Путь к шаблонам контроллера - public /*.Database.*/$db; // Соединение с базой данных + public $name = ''; // Имя модуля + public $viewPath = null; // Путь к шаблонам контроллера + public $viewPathPrefix = null; // Путь к шаблонам контроллера + + public $moduleTitle = ""; + + /** + * Соединение с базой данных + */ + public $db; // Фильтры public $access = null; // Обьект хранит параметры доступа @@ -42,14 +49,11 @@ class Controller_Action public $iconPath = ''; public $path; - public function __construct () - { - // + public function __construct () { + $this->path = new Widgets_PathMenu(); } - public function setUp () - { - // override this + public function setUp() { } public function loadConfig($name) { @@ -69,15 +73,16 @@ class Controller_Action public function installPath($name) { - return Path::join(CMS_PATH, "modules", $name, "install"); + return Path::join(CMS_PATH, "modules", $name); } - public function addSuggest($view, $name) + public function addSuggest(View_View $view, $name) { $suggest = array(); $file = Path::join($this->viewPath, 'help', $name . '.suggest'); - if (file_exists($file) && include($file)) { - $view->addScriptRaw("add_suggest(".json_encode($suggest).");\n"); + if (file_exists($file)) { + include($file); + $view->suggestions = $suggest; } } @@ -85,39 +90,43 @@ class Controller_Action { return Path::join($this->iconPath, $size . 'x' . $size, $icon . '.png'); } - + /** * Создает представление - * @param string $file - * @return template + * @param $name String + * @param $viewClass String + * @return View_Composite */ - public function getView($name) + public function getView($name, $viewClass = 'View_Composite') { - $file = $name . self::TEMPLATE_EXTENSION; - // Список возможных директорий для поиска файла шаблона - $theme = $this->_registry->readKey(array('system', 'theme')); - $icon_theme = $this->_registry->readKey(array('system', 'icon_theme')); - $list = array( - Path::join($this->viewPath, TEMPLATES) => Path::join(WWW_PATH, "modules", $this->name, TEMPLATES), - PHPTAL_TEMPLATE_REPOSITORY => ""); + $file = $name . self::TEMPLATE_EXTENSION; + $list = array( + Path::join($this->viewPath, TEMPLATES, $this->viewPathPrefix) => Path::join(WWW_PATH, "modules", $this->name, TEMPLATES, $this->viewPathPrefix), + Path::join(CMS_PATH, "templates") => Path::join(WWW_PATH, "templates") + ); // Поиск файла для шаблона foreach($list as $ospath => $path) { - $template = Path::join($ospath, $file); + $template = Path::join($ospath, $file); if(file_exists($template)) { break; } } - $tpl = new View_Composite($template); - $tpl->icons = $this->iconPath; // Путь к файлам текущей темы - $tpl->media = $this->themePath; // Путь к файлам текущей темы - $tpl->script = $this->jsPath; // Путь к файлам скриптов - $tpl->template = $path; // Путь к файлам текущего шаблона + /*.View_Composite.*/$tpl = new $viewClass($template); + + $tpl->set('icons', $this->iconPath); // Путь к файлам текущей темы + $tpl->set('media', $this->themePath); // Путь к файлам текущей темы + $tpl->set('assets', Path::join(WWW_PATH, "assets", "css")); + $tpl->set('script', $this->jsPath); // Путь к файлам скриптов + $tpl->set('template', $path); // Путь к файлам текущего шаблона + $tpl->setAlias(array( - '${icons}' => $this->iconPath, - '${media}' => $this->themePath, - '${script}' => $this->jsPath, - '${template}' => $path)); + 'icons' => $this->iconPath, + 'script' => $this->jsPath, + // Для media и template поиск происходит как для файлов шаблонов + 'media' => $list, + 'template' => $list + )); $tpl->loadImports(Path::skipExtension($template) . ".import"); @@ -128,7 +137,7 @@ class Controller_Action public function getModel($name) { if (!$this->factory) { - $this->factory = new ModelFactory($this->db, $this->_registry, $this->_shortcut); + $this->factory = new Model_Factory($this->db, $this->_registry); } return $this->factory->getModel($name); } @@ -143,57 +152,59 @@ class Controller_Action public function execute1(HttpRequest $request) { $action = self::ACTION_PREFIX . ucfirst($request->getAction()); - if (method_exists($this, $action)) { - return $this->forward($action, $request); - } else { - return $this->forward("actionIndex", $request); + if (!method_exists($this, $action)) { + $action = "actionIndex"; } + $view = $this->forward($action, $request); + if ($view instanceof View_View) { + $view->active_module = get_class($this); + $view->module_action = $action; + } + return $view; } public function execute(HttpRequest $request) { $result = $this->execute1($request); - if ($result) { + if (!empty($result)) { $this->view = $result; } - return $this->render(); + $text = $this->render(); + return $text; } - public function forward($action, HttpRequest $args) - { - // Действия до вызова основного обработчика - /*foreach($this->_aspect as $aspect) { - if (isset($aspect->before[$action])) { - call_user_func ($aspect->before[$action], $action, $args); - } - }*/ - return call_user_func(array($this, $action), $args); + public function forward($action, HttpRequest $args) { + $value = call_user_func(array($this, $action), $args); + return $value; } /** * Страница по умолчанию */ - public function actionIndex(HttpRequest $request) - { + public function actionIndex(HttpRequest $request) { return ""; } public function postUrl($name, $param) { - return "?" . http_build_query( - array_merge(array('module' => strtolower(get_class($this)), "action" => $name), - $this->param, $param)); + $uri = array_merge(array('module' => + strtr($this->modulePrefix . strtolower(get_class($this)), array('module_' => '')), "action" => $name), + $this->param, $param); + + return "?" . http_build_query($uri); } /** * Генерация ссылки c учетом прав пользователя на ссылки - * - * @parma string $name Действие - * @parma string $param Дополнительные параметры + * @param string $name Действие + * @param array $param Дополнительные параметры + * 'mode' означает что элемент до отправки обрабатывается javascript + * @return array|null */ public function nUrl($name, array $param = array()) { - if (!$this->access || $this->access->checkAction($name)) { + /*.Filter_ActionAccess.*/$access = $this->access; + if ($access != null || $access->checkAction($name)) { return lcurry(array($this, 'postUrl'), $name, $param); } return null; @@ -217,6 +228,12 @@ class Controller_Action /** * Генерация ссылки на действие контроллера * Ajax определяется автоматически mode = ajax используется для смены layout + * @param $name + * @param array $param + * @return array|null + * + * @example ?action=$name&mode=ajax + * {$param[i].key = $param[i].value} */ public function aUrl($name, array $param = array()) { @@ -249,14 +266,14 @@ class Controller_Action /** * Загрузка файла класса */ - public function loadClass($path, $setup = null) + public function loadClass($path, $setup = null, $prefix = '') { if (file_exists($path)) { require_once ($path); - $class = pathinfo($path, PATHINFO_FILENAME); + $class = $prefix . pathinfo($path, PATHINFO_FILENAME); return new $class($setup); } - return null; + throw new Exception("NO CLASS $path"); } public function loadSettings($path) @@ -269,6 +286,7 @@ class Controller_Action // Для Widgets public $view = null; public $childNodes = array(); + public $ctrlValues = array(); public $childViews = array(); public function setView($name) @@ -292,6 +310,11 @@ class Controller_Action $this->childNodes[$section] = $node; } + public function setValue(/*Widget*/ $name, $value) + { + $this->ctrlValues[$name] = $value; + } + /** * Добавление дочернего отображения к текущему отображению */ @@ -306,34 +329,86 @@ class Controller_Action */ public function render() { - foreach ($this->childNodes as $name => $node) { - $node->make($this); - $this->view->setView($name, $node->view); - } - foreach ($this->childViews as $name => $node) { - $this->view->setView($name, $node); - } + if ($this->view instanceof View_View) { + $this->view->assignValues($this->ctrlValues); + + foreach ($this->childNodes as $name => $node) { + $node->make($this); + $this->view->setView($name, $node->view); + } + foreach ($this->childViews as $name => $node) { + $this->view->setView($name, $node); + } + } return $this->view; } - function getPageId($request) + function getPageId(HttpRequest $request) { $pageId = time(); $request->session()->set('page', $pageId); return $pageId; } - function checkPageId($request, $page) + function checkPageId(HttpRequest $request, $page) { + if ($request->get('__forced__')) { + return true; + } $_page = $request->session()->get('page'); $result = ($_page && $_page == $page); $request->session()->clean('page'); return $result; } - function redirect($action) { - header('location: ' . $this->fUrl($action)); - exit(); + function _getActionPath() + { + return new Controller_State('index'); } -} + // Тоже убрать в метод Controller_Model + function getActionPath(HttpRequest $request, $action = null) + { + $this->_getActionPath()->getPath($this, ($action) ? $action : $request->getAction()); + } + + function addFilePathToPath($filePath, $type) + { + $pathToItem = $this->directoryPath($filePath, $type, 'default'); + $this->path->addMenuItems($pathToItem['path']); + } + + function directoryPath($path, $type, $action) + { + $path = empty($path) ? '/' : $path; + + $base = new Path($path); + $parts = $base->getParts(); + + $_path = '/' . implode('/', $parts); + + $rs = new Model_Resources($this->db); + $section_path = $rs->getSectionByPath($_path, $type); + + $pathMenu = new Widgets_PathMenu(); + $pathMenu->addTitle('title'); + $modules = ['image' => 'images','page' => 'pages','document' => 'documents','media' => 'videos']; + + while ($section_path->id_parent) { + $_path = '/' . implode('/', $parts); + $pathMenu->addMenuItem( + forceUrl($this->nUrl('', array('module'=>$modules[$type],'action' => $action, 'mode' => 'ajax', 'path' => $_path))), + $section_path->title + ); + $section_path = $rs->getSectionById($section_path->id_parent); + array_pop($parts); + } + + $pathMenu->addMenuItem( + forceUrl($this->nUrl('', array('module'=>$modules[$type],'action' => $action, 'mode' => 'ajax', 'path' => '/'))), + $this->moduleTitle + ); + return $pathMenu->getItemsReverse(); + } + +} diff --git a/src/Controller/Component.php b/src/Controller/Component.php index ae4c131..0a8220c 100644 --- a/src/Controller/Component.php +++ b/src/Controller/Component.php @@ -1,7 +1,40 @@ ]*>/u', 'replaceContent', $text); +} + +class ComponentRequest { + public $component_id; + public $r; + + function __construct($c, HttpRequest $r) { + $this->component_id = $c; + $this->r = $r; + } + + function get($key, $default = null) { + if ($key == 'active_page') { + return $this->r->get($key); + } + if ($arr = $this->r->get($key)) { + if (is_array($arr)) { + return Arr::get($arr, $this->component_id, $default); + } else { + return $arr; + } + } + return $default; + } + + function getAction() { + return $this->r->getAction(); + } } /** @@ -9,51 +42,87 @@ class FileNotFountException extends Exception */ class Controller_Component { - static $_uid = 1; - public $uid; // UID компонента создается при создании страницы, вставки компонента, или это статическое свойство - public $viewPath; - public $registry; // Registry->getInstance - public $template; + public $viewPath = array(); + public $webPath = array(); - function __construct() - { - self::$_uid ++; - $this->uid = self::$_uid; + public $template = null; + public $templatePath; + + public $component_id; + public $COMPONENTS_WEB; + + public /*.Settings.*/$registry; + public /*.Database.*/$db; + public /*.Collection.*/$parameter; + + public $module; + public $item_module; + + function before() { } - function getUID() - { - return 'component:'. $this->uid; + function get($request, $key, $default) { + } + + function execute(HttpRequest $request, $has_id = true) { + $crequest = new ComponentRequest($this->component_id, $request); + $action = 'action' . ucfirst($request->get('action', 'index')); + + $this->before(); + if (method_exists($this, $action)) { + return call_user_func(array($this, $action), $crequest); + } else { + return $this->actionIndex($crequest); + } } public function getView($name) { - require_once "core/view/compositeview.php"; // - $template = ($this->template) ? $this->template : $this->_registry->readKey(array('system', 'template')); - // Загружать шаблон по умолчанию если не найден текущий - if (is_dir(Path::join($this->viewPath, 'templates', $template))) { - $template_file = Path::join($this->viewPath, 'templates', $template, $name); - } else { - $template_file = Path::join($this->viewPath, 'templates', 'modern', $name); + /*.Settings.*/$registry = $this->registry; + $template = ($this->template) ? $this->template : $registry->readKey(array('system', 'template')); + + $selected = null; + foreach ($this->viewPath as $index => $viewPath) { + // Загружать шаблон по умолчанию если не найден текущий + if(is_dir(Path::join($this->viewPath[$index], 'templates', $template))) { + $tpl = new PHPTAL(Path::join($this->viewPath[$index], 'templates', $template, $name)); + $tpl->setPhpCodeDestination(PHPTAL_PHP_CODE_DESTINATION); + $selected = $index; + break; + } } - $tpl = new View_Composite($template_file); - $tpl->script = $_script = Path::join(WWW_PATH, 'js'); - $tpl->media = $_media = Path::join(TEMPLATE_WEB, $template); - $tpl->component = $_template = Path::join(COMPONENTS_WEB, strtolower(get_class($this)), 'templates', 'modern'); - $tpl->setAlias(array( - '${media}' => $_media, - '${script}' => $_script, - '${template}' => $_template)); + if ($selected === null) { + $tpl = new PHPTAL(Path::join($this->viewPath[0], 'templates', 'modern', $name)); + $tpl->setPhpCodeDestination(PHPTAL_PHP_CODE_DESTINATION); + $template = 'modern'; + $selected = 0; + } - $tpl->loadImports(Path::skipExtension($template_file) . ".import"); + $tpl->stripComments(true); + $tpl->addPreFilter(new PHPTAL_PreFilter_Normalize()); + + $tpl->set('common', Path::join(WWW_PATH, '../', 'common')); + $tpl->set('script', Path::join(WWW_PATH, 'js')); + $tpl->set('media', Path::join(TEMPLATE_WEB, $template)); + $tpl->set('site_template', SITE_WWW_PATH . '/templates' . $registry->readKey(array('system', 'template'))); + $tpl->set('base', SITE_WWW_PATH); + + $tpl->set('component_base', $this->webPath[$selected]); + $tpl->set('component', Path::join($this->webPath[$selected], 'templates', $template)); + $tpl->set('component_id', $this->component_id); return $tpl; } - public function setParameters($view) + public function getTemplatePath($name) { + return Path::join($this->viewPath[0], 'templates', 'modern', $name); + } + + public function getTemplateWebPath() { + return Path::join($this->webPath[0], 'templates', 'modern'); } /** @@ -71,8 +140,6 @@ class Controller_Component */ public function getModel($name) { - require_once 'core/mapper/mapper.php'; - require_once ($this->getModelPath ($name)); $modelName = $name . "Mapper"; $model = new $modelName (); @@ -80,104 +147,179 @@ class Controller_Component return $model; } - public function options($key, $val, $res) { + public function options($key, $val, /*.Database_PDOStatement.*/$res) { $result = array(); while($res->next()) { - $result[] = array('value' => $res->getInt($key), 'name' => $res->getString($val)); + $result[] = array('value' => $res->getString($key), 'name' => $res->getString($val)); } return $result; } - public function optionsPair($list) { + public function optionsPair($list, $selected = false) { $result = array(); foreach ($list as $key => $value) { - $result [] = array('value' => $key, 'name' => $value); + $result [] = array('value' => $key, 'name' => $value, 'selected' => $key == $selected); } return $result; } - /* В дальнейшем нужно зменить на методы - + Методы могут быть и javascript - */ - protected $editUrl; - - function setEditUrl($url) - { - $this->editUrl = $url; + function getInfo() { + $filename = Path::join($this->viewPath[0], 'install.json'); + if (file_exists($filename)) { + $settings = json_decode(file_get_contents($filename), true); + return $settings; + } + return array(); } - function getEditUrl() + /** + * Генерация интерфейса для выбора галлереи фотографии + */ + public function setParameters(/*.View_Composite.*/$view) { - return $this->editUrl; - } -} + $form = new Form_Form(); + $options = new OptionFactory($this->db); -/** - * TALES для подключения компонентов - * component:name?param1=value1¶m2=value2 - */ -class Component_Tales implements PHPTAL_Tales -{ - static public function component($expression, $nothrow = false) + $settings = $this->getInfo(); + $form->addFieldList($settings['parameter'], $options); + + $view->form = $form; + $view->component = $settings['component']; + $view->component_title = $settings['title']; + } + + static function loadComponent($expression, Database $db, Settings $registry) { - return "phptal_component('" . $expression . "')"; - } -} + + $expression = htmlspecialchars_decode($expression); + $offset = strpos($expression, '?'); + $url = parse_url($expression); + + $arguments = array(); + if ($offset === false) { + $path = $expression; + } else if (is_int($offset)) { + $path = substr($expression, 0, $offset); + $query = substr($expression, $offset + 1); + parse_str($query, $arguments); + } + $name = $path; + + $path = Path::join (BASE_PATH, 'components', $name, $name . '.php'); + $className = 'Component_' . $name; + + if (file_exists($path)) { + require_once ($path); + + $component = new $className(); + $component->db = $db; + $component->registry = $registry; + + $component->viewPath = array(BASE_PATH . '/components/' . $name . '/'); + $component->webPath = array(SITE_WWW_PATH . '/components/' . $name); + + $component->COMPONENTS_WEB = SITE_WWW_PATH . '/components/'; + + } else { + $path = Path::join (COMPONENTS, $name, $name . '.php'); + require_once ($path); + $component = new $className(); + $component->db = $db; + $component->registry = $registry; + + $component->viewPath = array(COMPONENTS . '/' . $name . '/', BASE_PATH . '/components/' . $name . '/'); + if (defined('COMPONENTS_WEB')) { + $component->webPath = array(COMPONENTS_WEB . '/' . $name, SITE_WWW_PATH . '/components/' . $name); + $component->COMPONENTS_WEB = COMPONENTS_WEB; + } + } + + $stmt = $db->prepareStatement("SELECT * FROM component WHERE code = ?"); + $stmt->setString(1, $expression); + $cid = $stmt->executeQuery(); + if ($cid->next()) { + $component->component_id = $cid->getInt('id_component'); + } else { + $last = $db->getIdGenerator(); + if ($last->isBeforeInsert()) { + $result = $last->getId('component_id_component_seq'); + + $stmt = $db->prepareStatement("INSERT INTO component (id_component, code) VALUES ($result, ?)"); + $stmt->setString(1, $expression); + $stmt->executeQuery(); + } + if ($last->isAfterInsert()) { + $stmt = $db->prepareStatement("INSERT INTO component (code) VALUES (?)"); + $stmt->setString(1, $expression); + $stmt->executeQuery(); + + $result = $last->getId('component_id_component_seq'); + } + $component->component_id = $result; + } + + $params = new Collection(); + $params->import(array_merge($_GET, $arguments)); + $component->parameter = $params; + $component->template = $params->get('template', false); + + global $componentsConfig; + $editor = $component->getEditUrl(); + if ($editor) { + $componentsConfig[] = $editor; + } -function loadComponent($name, $db, $registry) -{ - $path = Path::join(COMPONENTS, $name, $name . ".php"); -// echo COMPONENTS, '
'; -// echo $path; - if (file_exists($path)) { - require_once ($path); - $component = new $name(); - $component->db = $db; - $component->_registry = $registry; - $component->viewPath = COMPONENTS."/".$name."/"; return $component; } - throw new FileNotFountException(); + + function getEditUrl() { + return null; + } + + function raw_query(/*.ComponentRequest.*/ $request) + { + $arr = $request->r->export('get'); + + $param = array(); + /*.Collection.*/$parameter = $this->parameter; + foreach($parameter->export() as $key => $value) { + $param[$key] = $value; + } + + $data = array(); + foreach($arr as $key => $value) { + if (is_array($value)) { + $data[$key] = Arr::get($value, $this->component_id); + } else { + $data[$key] = $value; + } + } + $data['param'] = $param; + return $data; + } + + + function query(/*.ComponentRequest.*/ $request, $list) + { + $arr = $request->r->export('get'); + + foreach($list as $key => $val) { + $arr[$key] [$this->component_id] = $val; + } + + unset($arr['active_page']); + return '?' . http_build_query($arr); + } + + function addRequireJsPath($name, $path, $shim = null) { + global $requireJsConfig; + $requireJsConfig['paths'][$name] = $path; + if ($shim) { + $requireJsConfig['shim'][$name] = $shim; + } + } + + function actionIndex(/*.ComponentRequest.*/ $request) { + } } -/** - * Функция подключения компонента - */ -global $componentList; -$componentList = array(); - -function phptal_component ($real_expression, $offset = 0) { - global $db, $registry, $componentList; // Нужно както передавать параметры - - $expression = htmlspecialchars_decode($real_expression); - $url = parse_url($expression); - parse_str($url['query'], $arguments); - $name = $url['path']; - - $component = loadComponent($name, $db, $registry); - $req = new HttpRequest(); - $params = new Collection(); - $params->import(array_merge($_GET, $arguments)); - $component->params = $params; - - $componentList [] = array( - 'uid' => $component->getUID(), 'params' => $expression, 'name' => $name, 'offset' => $offset, - 'size' => strlen($real_expression), - /* Вместо ссылки на редактирование нужно передавать список методов для работы с компонентом - edit (редактирование содержание), new (новое содержание), шаблон коменнента ... вместе с иконками этих методов - ! Компоненты могут содержать другие компоненты - */ - 'editurl' => $component->getEditUrl(), - 'newurl' => '' - ); - - unset($req['active_page']); - $component->template = $params->get('template', false); - - return $component->execute($params, $req); -} - -/* Регистрация нового префикса для подключения компонента */ -$registry = PHPTAL_TalesRegistry::getInstance(); -$registry->registerPrefix('component', array('Component_Tales', 'component')); - diff --git a/src/Controller/Front.php b/src/Controller/Front.php index badcf43..38b1a40 100644 --- a/src/Controller/Front.php +++ b/src/Controller/Front.php @@ -2,25 +2,37 @@ /** * Первичный контроллер контроллер страниц - * @package core + * @package system.controller */ class Controller_Front extends Controller_Action { - + + /** @var Shortcut */ protected $shortcut; // Ярлык к модулю protected $_param; // Параметр по которому выбирается модуль protected $default; // Значение параметра по умолчанию - public function __construct(Settings $_registry, $_shortcut) + protected $modules = array(); + + /** + * @param Settings $_registry + * @param Shortcut $_shortcut + */ + public function __construct(Settings $_registry, $_shortcut) // $db, $installer, $shortcut { parent::__construct(); $registry = $_registry; $this->_registry = $_registry; - $this->_shortcut = $_shortcut; + $this->_shortcut = $_shortcut; // $cc->newShortcut(); - $this->db = Database::getConnection($registry->readKey(array('system', 'dsn'))); + $dsn = $registry->readKey(array('system', 'dsn')); + $this->db = Database::getConnection($dsn); // $cc->newConnection(); } + public function isLoaded($name) + { + return isset($this->modules[$name]); + } /** * Создает экземпляр модуля и выполняет действия для него @@ -28,15 +40,22 @@ class Controller_Front extends Controller_Action * @param request $request Имя модуля * @return string */ - public function loadModule($name, Collection $request) + public function loadModule($name, Collection $request, $controller = false) { + if ($this->isLoaded($name)) { + $module = $this->modules[$name]; + return $module->access->execute($request); + } - $moduleFile = Shortcut::getUrl($this->shortcut, $name); // ModuleLoader (2) - $module = $this->loadClass($moduleFile); + if ($controller) { + $moduleFile = Shortcut::getUrl($this->shortcut, $name, $controller); // ModuleLoader (2) + } else { + $moduleFile = Shortcut::getUrl($this->shortcut, $name, $name); // ModuleLoader (2) + } + $module = $this->loadClass($moduleFile, null, 'Module_'); if ($module) { // Инициализация модуля -// $module->viewPath = dirname($moduleFile); $module->viewPath = Shortcut::getUrl('modulepath', $name); $module->name = $name; @@ -51,15 +70,17 @@ class Controller_Front extends Controller_Action $module->db = $this->db; // Не для всех приложений нужно вести лог действий // Ведение лога - $logger = $this->loadClass(FRAMEWORK_PATH . '/src/filter/actionlogger.php', $module); + $logger = $this->loadClass(FRAMEWORK_PATH . '/filter/actionlogger.php', $module, 'Filter_'); $logger->before = $this->loadSettings(Shortcut::getUrl('logger', $name)); // Управление доступом - $module->access = $this->loadClass(FRAMEWORK_PATH . '/src/filter/actionaccess.php', $logger); + $module->access = $this->loadClass(FRAMEWORK_PATH . '/filter/actionaccess.php', $logger, 'Filter_'); $module->access->access = $this->loadSettings(Shortcut::getUrl('access', $name)); $module->setUp(); - return $module->access->execute($request); + $this->modules[$name] = $module; + $result = $module->access->execute($request); + return $result; } return null; // throw new FileNotFoundException(); } @@ -72,13 +93,14 @@ class Controller_Front extends Controller_Action $this->default = $name; } - private function getParameter(Collection $list) - { - return ($list->get($this->_param)) ? $list->get($this->_param): $this->default; - } - public function execute(HTTPRequest $request) { - return $this->loadModule($this->getParameter($request), $request); + $name = explode("_", $request->get($this->_param, $this->default)); + if (count($name) >= 2) { + $controller = $name[1]; + } else { + $controller = false; + } + return $this->loadModule($name[0], $request, $controller); } } diff --git a/src/Controller/Installer.php b/src/Controller/Installer.php index 1bbbe3a..dcc4562 100644 --- a/src/Controller/Installer.php +++ b/src/Controller/Installer.php @@ -2,7 +2,7 @@ class Controller_Installer { - protected $db; + protected $db_manager; protected $installPath; public $_registry; @@ -11,15 +11,20 @@ class Controller_Installer $this->_registry = $_registry; } - public function setUp($db, $installPath) + public function setUp($db_manager, $installPath) { - $this->db = $db; + $this->db_manager = $db_manager; $this->installPath = $installPath; } function getSetupFile($name) { - return Path::join(call_user_func($this->installPath, $name), "setup.php"); + $setup = Path::join(call_user_func($this->installPath, $name), "install.json"); + return $setup; + } + + function getUninstallFile($name){ + return Path::join(call_user_func($this->installPath, $name), "sql", "uninstall.json"); } // Проверка версии обновления @@ -38,22 +43,33 @@ class Controller_Installer function installSQL(array $sql, $version_new, $version_old, $name) { - require_once "core/setup.php"; + $result = []; + $json_installer = new Database_JsonInstall($this->db_manager); foreach ($sql as $version => $install) { if (version_compare($version, $version_new, "<=") && version_compare($version, $version_old, ">")) { - // this->installPath this->db $file = Path::join(call_user_func($this->installPath, $name), "sql", $install); - Setup::batchSQL($this->db, $file); + $json_installer->install($file,null); + $result[] = $version; } } + return $result; } + function uninstall($name){ + $uninstall = $this->getUninstallFile($name); + if (file_exists($uninstall)) { + $json_installer = new Database_JsonInstall($this->db_manager); + $json_installer->install($uninstall,null); + } + $this->_registry->removeKey($name); + $this->_registry->write(); + } // Устанавливает обновления если есть function doUpdates($name, $force = false) // Установка модуля { + $result = array(); $setup = $this->getSetupFile($name); if (file_exists($setup) && ($this->isChanged($name) || $force)) { - $registry = $this->_registry; $settings = new Settings($setup); $settings->read(); @@ -67,21 +83,29 @@ class Controller_Installer $version_old = "0.0"; $registry->writeKey(array($name), array()); } - if (version_compare($version_old, $settings->get('version'), "!=")) { $sql = $settings->get('sql'); if (is_array($sql)) { - $this->installSQL($sql, $version_new, $version_old, $name); + $res = $this->installSQL($sql, $version_new, $version_old, $name); + if($res){ + $result[]=$res; + } } } // Обновление версии меню + $registry->removeKey($name); $registry->writeKey(array($name), $settings->get('settings')); $registry->writeKey(array($name), array('version' => $version_new, 'time' => filemtime($setup))); $registry->write(); } + return $result; + } + + function install($dbinit_path,$dbfill_path=null){ + $json_installer = new Database_JsonInstall($this->db_manager); + $json_installer->install($dbinit_path,$dbfill_path); } } - diff --git a/src/Controller/Model.php b/src/Controller/Model.php index 9c4dab7..4c1cbf9 100644 --- a/src/Controller/Model.php +++ b/src/Controller/Model.php @@ -28,38 +28,53 @@ class Controller_Model extends Controller_Action public function __construct() { - $this->path = new PathMenu(); - $this->menu = new PageMenu(); - $this->table = new ListTable(); + parent::__construct(); + $this->menu = new Widgets_PageMenu(); + $this->table = new Widgets_ReactListTable(); } /** */ - function setUp() - { - $this->table->addMenuItem($this->aUrl('delete'), 'удалить', false, 'all', 'warning'); - //$this->table->addMenuItem($this->nUrl('form'), 'редактировать', 'edit-24.png'); + function setUp() { + parent::setUp(); + $this->table->addMenuItem($this->aUrl('delete'), 'удалить', false, 'all', 'btn-danger', 'remove'); } - function saveParameters($args, $list) - { + function saveParameters(HttpRequest $args, $list) { foreach ($list as $item) { $args->session()->set(array($this, $item), $args->get($item)); } } - protected function getJSONList(/*Mapper*/ $model, Collection $request) - { + protected function getJSONList(/*.Model_Mapper.*/ $model, HttpRequest $request) { $result = array(); $this->saveParameters($request, array('size','page','desc', 'key')); $result['list'] = $model->findAll($request, $request->get('ref')); $result['size'] = $model->getCount($request, $request->get('ref')); - return json::encode($result); + return json_encode($result); } + protected function getCSV(Model_Mapper $model, HttpRequest $request, $title) { + $ref = $request->get('ref'); + + $list = $model->findAll($request, $request->get('ref')); + + header('Content-Type: text/csv; charset=utf-8'); + header('Content-Disposition: attachment; filename='.$title.'.csv'); + + echo "\xEF\xBB\xBF"; //UTF-8 BOM. + + $output = fopen('php://output', 'w'); + if (is_resource($output)) { + foreach ($list as $row) { + fputcsv($output, (array)$row,';'); + } + } + } + /** - * Удаление сторк из таблицы + * Удаление строк из таблицы */ public function actionDelete(HttpRequest $request) { @@ -68,7 +83,8 @@ class Controller_Model extends Controller_Action $list = ($request->get('table_item')) ? $request->get('table_item'): $request->get('id'); $model->deleteList($list); - return $this->getJSONList($model, $request); +// return $this->getJSONList($model, $request); + return json_encode(array('result' => 'ok')); } /** @@ -88,16 +104,29 @@ class Controller_Model extends Controller_Action public function actionList(HttpRequest $request) { $model = $this->getModel($this->useModel); + + if ($request->get('filter')) { + $data = new Collection(); + $data->import($request->get('filter')); + $model->addFilter($model->requestToSQL($data, $this->formSchema)); + } return $this->getJSONList($model, $request); } + public function actionCSV(HttpRequest $request) + { + $model = $this->getModel($this->useModel); + $title = $request->get("title"); + if(!$title){ + $title = "noname"; + } + return $this->getCSV($model, $request, $title); + } private function setFormSchema() { - require_once 'core/mapper/uimapper.php'; - $model = $this->getModel($this->useModel); - $ui = new UIMapper($model); + $ui = new Model_UIMapper($model); $this->formSchema = $ui->getFormSchema(); } @@ -105,29 +134,29 @@ class Controller_Model extends Controller_Action /** * Сохранение формы */ - function beforeSave(/*Model*/ $item, Collection $request) + function beforeSave(/*Model*/ $item, HttpRequest $request) { if (empty($this->formSchema)) { $this->setFormSchema(); } - // Сделать отображение Формы в обьект и обратно <-- Убрать в beforeSave + // Сделать отображение Формы в обьект и обратно foreach ($this->formSchema as $key => $conv) { list($value, $type) = $conv; - $item->$value = call_user_func(array('Cast', 'to_' . $type), $request->get($key)); // Здесть нужно преобразовывать тип значения + $item->$value = call_user_func(array('Primitive', 'to_' . $type), $request->get($key)); // Здесь нужно преобразовывать тип значения } } /** * Обновление формы */ - function formUpdate(TForm $form, Collection $request) - { + function formUpdate(Form_Form $form, HttpRequest $request) { + $form->setValues($request); } /** * Загрузка формы */ - function beforeLoad(/*Model*/ $item, TForm $form) + function beforeLoad(/*.Model_Model.*/$item, Form_Form $form) { if (empty($this->formSchema)) { $this->setFormSchema(); @@ -137,8 +166,13 @@ class Controller_Model extends Controller_Action $form->fill($item, $this->formSchema); } + function beforeFirstLoad(Form_Form $form) + { + + } + // Проверка ввода - protected function validate($validator, $request) + protected function validate(Validator_Validator $validator, Collection $request) { } @@ -147,8 +181,7 @@ class Controller_Model extends Controller_Action */ public function actionValidate($request) { - require_once "core/validator/validator.php"; - $validator = new Validator(); + $validator = new Validator_Validator(); $validator->addRuleList($this->schema); // Действия до проверки формы @@ -156,19 +189,19 @@ class Controller_Model extends Controller_Action $validator->validate($request); // --| // Проверка формы if (!$validator->isValid()) { - return json::encode($validator->getErrorMsg()); + return json_encode($validator->getErrorMsg()); } - return json::encode(true); + return json_encode(true); } /** * Инициализация формы */ - protected function formSetup($form, $id = null, $ref = null) + protected function formSetup(Form_Form $form, $id = null, $ref = null) { if (empty($this->schema)) { $model = $this->getModel($this->useModel); - $ui = new UIMapper($model); + $ui = new Model_UIMapper($model); $schema = $ui->getEditSchema(); $form->addFieldList($schema); @@ -178,71 +211,57 @@ class Controller_Model extends Controller_Action } /** - * Добавление пользователя + * Добавление */ public function actionAdd(HttpRequest $request) { - require_once "core/validator/validator.php"; // {{{ тоже может быть один ref или несколько $ref = $request->get('ref'); $this->addParameter('ref', $ref); // Добавляет параметр в url /// }}} - if ($this->checkPageId($request, $request->get('page'))) { - // Проверка - $validator = new Validator(); - $validator->addRuleList($this->schema); - - // Действия до проверки формы - $this->validate($validator, $request); // <--| - $validator->validate($request); // --| - // Проверка формы - if (!$validator->isValid()) { - $request->setAction('form'); - $this->getActionPath($request); + // Проверка + $validator = new Validator_Validator(); + $validator->addRuleList($this->schema); - $form = new TForm(); - $this->formSetup($form, $request->get('id'), $request->get('ref')); // Инициализация формы + // Действия до проверки формы + $this->validate($validator, $request); // <--| + $validator->validate($request); // --| + // Проверка формы + if (!$validator->isValid()) { + return json_encode(array('result'=>'fail','errors'=>$validator->getErrorMsg())); + } + // Нужен тест для формы + $model = $this->getModel($this->useModel); + $className = $model->className; + $item = new $className(); - $form->setValues($request); // <-- Убрать в formUpdate - $this->formUpdate($form, $request); + // Сохраняем значение в базе данных + $item->id = $request->get('id'); + // Если таблица связана с другой таблицей + if ($request->get('ref') && $model->reference[1]) { + $ref_id = $model->reference[1]; + $item->$ref_id = $request->get('ref'); + } - $form->setError($validator); // Установка ошибок для формы + // Подготовка к сохранению + $this->beforeSave($item, $request); // Сюдаже и истрия переходов + // nextId ??? или выход или новая форма для создания новости + + $id = $model->saveDB($item, $request); - $tpl = $this->formPage($form, $request); - $id = $request->get('id'); - if ($id) { // Редактирование - $tpl->action = forceUrl($this->nUrl('add', array('id' => $id, 'page' => $this->getPageId($request)))); // action Совйство формы - } - return $tpl /*->execute()*/; - } - - // Нужен тест для формы - $model = $this->getModel($this->useModel); - $className = $model->className; - $item = new $className(); - - // Сохраняем значение в базе данных - $item->id = $request->get('id'); - // Если таблица связана с другой таблицей - if ($request->get('ref') && $model->reference[1]) { - $ref_id = $model->reference[1]; - $item->$ref_id = $request->get('ref'); - } - - // Подготовка к сохранению - $this->beforeSave($item, $request); // Сюдаже и истрия переходов - // nextId ??? или выход или новая форма для создания новости - $model->saveDB($item, $request); - } - - // Для страницы со списком id -> идентефикатор родительской таблицы !!?? + // Для страницы со списком id -> идентификатор родительской таблицы !!?? // $request->set('id', $request->get('ref')); if ($request->get('apply')) { $request->setAction('form'); - return $this->forward('actionForm', $request); + return (string) $this->forward('actionForm', $request); } - return $this->forward('actionIndex', $request); + //$request->setAction('index'); + $result = array('result'=>'ok'); + if($id){ + $result['action'] = forceUrl($this->nUrl('add', array('id' => $id, 'ref' => $request->get('ref')))); + } + return json_encode($result); } /** @@ -275,38 +294,40 @@ class Controller_Model extends Controller_Action $this->setTitlePath($ref); $model = $this->getModel($this->useModel); - $form = new TForm(); // Показываем форму + $form = new Form_Form(); // Показываем форму $form->header = 'Редактирование записи'; $this->formSetup($form, $request->get('id'), $request->get('ref')); // Инициализация формы $list = $request->get('table_item'); $id = ($list[0]) ? $list[0] : $request->get('id'); - - $tpl = $this->formPage ($form, $request); + // + $tpl = $this->formPage($form, $request); if ($id) { // Редактирование $form->action = forceUrl($this->nUrl('add', array('id' => $id, 'page' => $this->getPageId($request)))); // action Свойство формы $item = $model->findById($id); // Загрузка формы $this->beforeLoad($item, $form); - /// + }else{//Создание нового элемента + $this->beforeFirstLoad($form); } - return $tpl; + return json_encode($tpl); } /** */ - function tableSetup($table, $id = null, $ref = null) + function tableSetup(Widgets_ListTable $table, $id = null, $ref = null) { // FIXME: После замены везде $tableSchema -> table->setHeader удалить! if ($this->tableSchema) { $table->setHeader($this->tableSchema); } else { // Настройка таблицы отображения по схеме данных - require_once 'core/mapper/uimapper.php'; $model = $this->getModel($this->useModel); - $ui = new UIMapper($model); - $schema = $ui->getTableSchema(); - $schema[0]['action'] = $table->getFirstItem(); + $ui = new Model_UIMapper($model); + $ui->hidden = $table->hidden; + + $schema = $ui->getTableSchema(); + $schema[0]['action'] = forceUrl($table->getFirstItem()); $table->setHeader($schema); } @@ -314,7 +335,7 @@ class Controller_Model extends Controller_Action /** */ - public function actionIndex(HttpRequest $request) + public function actionDefault(HttpRequest $request) { $this->getActionPath($request, 'index'); // Такое мета действие наверное можно вынести в отдельный класс @@ -335,14 +356,14 @@ class Controller_Model extends Controller_Action $ref = $request->session()->get('ref'); } - $request->session->set('ref', $ref); + $request->session()->set('ref', $ref); $this->addParameter('ref', $ref); // }}} $this->setTitlePath($ref); - $tpl = $this->getView('list'); + $tpl = new stdClass(); - // Помошники действий + // Помощники действий $this->callHelpers($request); // Таблица if ($request->session()->get(strtolower(get_class($this)))) { @@ -355,7 +376,7 @@ class Controller_Model extends Controller_Action 'size' => $session['size'], 'desc' => $session['desc'])); - $this->table->setData('sorter', $session['key']); + //$this->table->setData('sorter', $session['key']); if (isset($session['desc'])) { $this->table->setData('desc', $session['desc']); } @@ -363,64 +384,137 @@ class Controller_Model extends Controller_Action call_user_func($setup, $this->table, $request->get('id'), $ref);// --> Эквивалент formSetup $this->table->setAction($list); - // + if (!$this->table->getData('module')) { + $this->table->setData('module', strtolower($this->useModel)); + } $tpl->menu_path = $this->path->getItems(); - // Поиск - $search = new SearchDialog(); - $search->setTitle('Поиск'); - $search->setAction($this->aUrl('search')); - $search->setFriend($this->table); - $search->addFields($this->schemaSearch); + $this->table->makeData(); + $tpl->table = array('data' => $this->table->data); + $tpl->menu = $this->menu->menu->getItems(); + $tpl->path = $this->path->getItems(); - // Настройки - $setup = new SetupDialog(); - $setup->setTitle('Настройки'); - $setup->setAction($this->nUrl('setup')); - $setup->setFriend($this->table); - - // Меню - $this->menu->addMenuItem('?menu=toggle&id=' . $search->getName(), 'поиск', 'actions/system-search'); // Стандартный размер для иконок 22-24px - $this->menu->addMenuItem('?menu=toggle&id=' . $setup->getName(), 'настройки', 'categories/applications-system'); - // Добавление компонентов - $this->addChild('menu', $this->menu); - $this->addChild('search', $search); - $this->addChild('setup', $setup); - $this->addChild('table', $this->table); - // - return $tpl; + return json_encode($tpl); } /** */ - public function actionSetup($request) - { + public function actionSetup(HttpRequest $request) { $left = explode(",", $request->get('left')); $right = explode(",", $request->get('right')); - $$request->session()->set(strtolower(get_class($this)), - array('view' => array('left' => $left, 'right' => $right))); + $request->session()->set(strtolower(get_class($this)), + array('view' => array('left' => $left, 'right' => $right), 'page' => 1, 'size' => 0, 'desc' => 'asc', 'key' => false)); return $this->forward('actionIndex', $request); } /** */ - private function formPage($form, $request) - { - $view = $this->getView('form'); - $view->setView('form', $form); - $view->action = forceUrl($this->nUrl('add', array('page' => $this->getPageId($request)))); // Действие для формы + protected function formPage($form, $request, $template = 'form') { + $view = new stdClass();//$this->getView($template); + $view->form = $form; + $form->action = forceUrl($this->nUrl('add', array('page' => $this->getPageId($request)))); // Действие для формы - $view->menu_path = $this->path->getItems(); + $view->path = $this->path->getItems(); $view->back = $this->path->getPrev(); return $view; } + function _getActionPath() { + return new Controller_State('index'); + } + // Тоже убрать в метод Controller_Model - function getActionPath(HttpRequest $request/*, $action = false*/) - { - require_once 'state.php'; + function getActionPath(HttpRequest $request, $action = null) { $this->_getActionPath()->getPath($this, ($action) ? $action : $request->getAction()); } + + + function parse_params($expression) { + $expression = htmlspecialchars_decode($expression); + $offset = strpos($expression, '?'); + $url = parse_url($expression); + + $arguments = array(); + if ($offset === false) { + $path = $expression; + } else if (is_int($offset)) { + $path = substr($expression, 0, $offset); + $query = substr($expression, $offset+1); + parse_str($query, $arguments); + } + return $arguments; + } + + public function actionFormPage(HttpRequest $request) { + //$tpl = $this->getView('formpage', 'View_Top'); + + $view = $this->getView('formpage', 'View_Top'); + + $params = $this->parse_params($request->get('params')); + + +// $model = $this->getModel($this->useModel); + $form = new Form_Form(); // Показываем форму + $form->header = 'Редактирование записи'; + $this->formSetup($form, $request->get('id'), $request->get('ref')); // Инициализация формы + /* + $ui = new Model_UIMapper($model); + $schema = $ui->getEditSchema(); + $form->addFieldList($schema); + */ + + $list = $request->get('table_item'); + $id = ($list[0]) ? $list[0] : $request->get('id'); + +// $tpl = $this->formPage($form, $request); + + $view->setView('form', $form); + $view->action = forceUrl($this->nUrl('addpage', array('ref' => $params['id']))); // Действие для формы + +// $view->menu_path = $this->path->getItems(); + $view->back = ''; + return $view; + +// return $tpl; + } + + /* Для поддержки редактрования на сайте */ + public function actionAddPage(HttpRequest $request) + { + // {{{ тоже может быть один ref или несколько + $ref = $request->get('ref'); + $this->addParameter('ref', $ref); // Добавляет параметр в url + /// }}} + $validator = new Validator_Validator(); + $validator->addRuleList($this->schema); + + // Действия до проверки формы + $this->validate($validator, $request); // <--| + $validator->validate($request); // --| + // Проверка формы + if (!$validator->isValid()) { + return $validator; + } + + // Нужен тест для формы + $model = $this->getModel($this->useModel); + $className = $model->className; + $item = new $className(); + + // Сохраняем значение в базе данных + $item->id = $request->get('id'); + // Если таблица связана с другой таблицей + if ($request->get('ref') && $model->reference[1]) { + $ref_id = $model->reference[1]; + $item->$ref_id = $request->get('ref'); + } + + // Подготовка к сохранению + $this->beforeSave($item, $request); // Сюдаже и истрия переходов + $model->saveDB($item, $request); + + return null; + } } diff --git a/src/Database/PDOStatement.php b/src/Database/PDOStatement.php index 4561611..4df5db7 100644 --- a/src/Database/PDOStatement.php +++ b/src/Database/PDOStatement.php @@ -1,5 +1,7 @@ fields[$name]); + return strToArray($this->fields[$name]); } function getRecordCount() { diff --git a/src/Filter/Login.php b/src/Filter/Login.php index 7b0c8ea..4ce7302 100644 --- a/src/Filter/Login.php +++ b/src/Filter/Login.php @@ -13,6 +13,9 @@ class Filter_Login extends Filter_Filter const SESSION_BROWSER_SIGN_SECRET = '@w3dsju45Msk#'; const SESSION_BROWSER_SIGN_KEYNAME = 'session.app.browser.sign'; public $mode = 'ajax'; + + //AJAX-Реквесты для которых не требуется авторизация, потребовалось для сбора статистики + public $whiteRequestList = array(array('module' => "requiredcontent", "action" => "getcount")); /** * Проверка авторизации * @return Boolean Авторизовани пользователь или нет @@ -20,7 +23,7 @@ class Filter_Login extends Filter_Filter public function isLoggin(HttpRequest $request) { // Авторизация - // session_start(); + session_start(); $db = $this->getConnection(); Filter_UserAccess::setUp($db); // Соединение switch ($request->getAction()) { @@ -31,7 +34,18 @@ class Filter_Login extends Filter_Filter $result = Filter_UserAccess::getUserByLogin($login); // Поиск по логину if ($result) { - if (md5($password) == $result->getString('password')) { // password + $userPassword = $result->getString('password'); + if (Filter_UserAccess::$access == 'site_root' && defined('PARENT_PATH')) { + $s = new Settings(PARENT_PATH . '/settings.json'); + $s->read(); + $dsn = $s->readKey(array('system', 'dsn')); + + $db = Database::getConnection($dsn); + $user = $db->fetchOneArray("SELECT * FROM users WHERE login = :login", ['login' => $login]); + $userPassword = $user['password']; + } + // Извлечнеие пользователя из родительской CMS, для проверки пароля + if (md5($password) == $userPassword) { // password $this->enter($db, $result); return true; } @@ -45,7 +59,7 @@ class Filter_Login extends Filter_Filter case 'enter': $login = $request->get('login'); $password = $request->get('sid'); - $result = UserAccess::getUserByLogin($login); // Поиск по логину + $result = Filter_UserAccess::getUserByLogin($login); // Поиск по логину if ($result) { $temp = md5($result->getString('password') . $result->getString('login') . $result->getString('sid')); if ($password == $temp) { @@ -57,12 +71,15 @@ class Filter_Login extends Filter_Filter default: $hash = $this->getBrowserSign(); // Если $hash не совпадает $_SESSION['hash'] то удаляем сессию - if (isset($_SESSION ['access']) && isset($_SESSION[self::SESSION_BROWSER_SIGN_SECRET])) { - if ($hash == $_SESSION[self::SESSION_BROWSER_SIGN_SECRET]) { - UserAccess::getUserById($_SESSION ['access']); // Поиск по идентификатору + if (isset($_SESSION ['access']) && isset($_SESSION[self::SESSION_BROWSER_SIGN_KEYNAME])) { + if ($hash == $_SESSION[self::SESSION_BROWSER_SIGN_KEYNAME]) { + $this->user = $user = Filter_UserAccess::getUserById($_SESSION['access']); // Поиск по идентификатору + if ($user && isset($_SESSION['random']) && ($user->get('sid') == $_SESSION['random'])) { + return true; + } return true; } else { - session_destroy(); + session_destroy(); } } } @@ -72,9 +89,9 @@ class Filter_Login extends Filter_Filter private function getBrowserSign() { $rawSign = self::SESSION_BROWSER_SIGN_SECRET; - $signParts = array('HTTP_USER_AGENT', 'HTTP_ACCEPT_ENCODING'); + //$signParts = array('HTTP_USER_AGENT', 'HTTP_ACCEPT_ENCODING'); + $signParts = array(); - $rawSign = ''; foreach ($signParts as $signPart) { $rawSign .= '::' . (isset($_SERVER[$signPart]) ? $_SERVER[$signPart] : 'none'); } @@ -83,23 +100,78 @@ class Filter_Login extends Filter_Filter private function enter($db, $result) { - $db->executeQuery("UPDATE users SET sid = '' WHERE id_user = " . $result->getInt('id_user')); + $this->user = $result; + $random = rand(0, 1024 * 1024); + $db->executeQuery("UPDATE users SET sid = '$random' WHERE id_user = " . $result->getInt('id_user')); - $_SESSION ["group"] = $result->getInt('access'); - $_SESSION ["access"] = $result->getInt('id_user'); // id_user - $_SESSION [self::SESSION_BROWSER_SIGN_SECRET] = $this->getBrowserSign(); - $_SESSION ["time"] = time(); + $_SESSION["group"] = $result->getInt('access'); + $_SESSION["access"] = $result->getInt('id_user'); // id_user + $_SESSION["random"] = $random; // id_user + $_SESSION[self::SESSION_BROWSER_SIGN_KEYNAME] = $this->getBrowserSign(); + $_SESSION["time"] = time(); } public function execute(HttpRequest $request) { - if (!$this->isLoggin($request)) { - // Параметры при неправильной авторизации - // Действия по умолчанию !! Возможно переход на форму регистрации - $request->set('module', 'login'); - $request->set('mode', $this->mode); + $logged = $this->isLoggin($request); + if ($request->get('action') == 'user_access') { + if ($logged) { + $result = array(); + $result['fullname'] = $this->user->getString('patronymic') . " " . $this->user->getString('firstname'); + $result['email'] = $this->user->getString('email'); + $result['site'] = 187; + $result['hash'] = sha1(self::SESSION_BROWSER_SIGN_SECRET . $this->user->getString('email')); + return json_encode($result); + } else { + return json_encode("NOT AUTHORIZED"); + } } - return $this->processor->execute($request); + + if ($request->get('action') == 'relogin') { + if ($logged) { + return json_encode(array('result' => 'ok', 'message' => "Авторизация успешна")); + } else { + return json_encode(array('result' => 'fail', 'message' => "Неправильное имя пользователя или пароль")); + } + } + + if (!$logged) { + // Параметры при неправильной авторизации + // Действия по умолчанию !! Возможно переход на форму регистрации + if ($request->get('mode') == 'ajax') { + if (!$this->requestIsWhite($request, $this->whiteRequestList)) { + return json_encode(array('result' => 'fail', 'message' =>"NOT_AUTHORIZED")); + } + } else { + $request->set('module', 'login'); + $request->set('mode', $this->mode); + } + } else if (isset($_SERVER['HTTP_REFERER'])) { + $arr = array(); + parse_str(parse_url($_SERVER['HTTP_REFERER'], PHP_URL_QUERY), $arr); + if (isset($arr['back_page']) && $request->get('mode') != 'ajax') { + $request->redirect($arr['back_page']); + } + } + + $text = $this->processor->execute($request); + return $text; + } + + /* --------------------- + * Проверка на попадание реквеста в белый список + */ + + public function requestIsWhite(Collection $request, $whiteRequestList){ + $module = $request->get('module'); + $action = $request->get('action'); + foreach ($whiteRequestList as $whiteRequest) { + if ($module == $whiteRequest['module'] && $action == $whiteRequest['action']) { + return true; + } + } + + return false; } } diff --git a/src/Form/Form.php b/src/Form/Form.php index 7d38691..aa68acc 100644 --- a/src/Form/Form.php +++ b/src/Form/Form.php @@ -20,68 +20,147 @@ class TField public $description = ""; public $alias = array(); - public function __construct ($input) + public function __construct ($input = array(), $factory = null) { - $this->deafult = null; + + $this->default = null; if (isset($input['validate'])) { - $this->require = strpos($input['validate'], 'require') !== false; + $this->require = strpos($input['validate'], 'require') !== false; } // Инициализация свойст обьетка - foreach (array('label', 'name', 'type') as $name) { - $this->$name = $input[$name]; + foreach (array('label', 'name', 'type', 'description') as $name) { + if (isset($input[$name])) { + $this->$name = $input[$name]; + } } } - function setValue($value) + function setValue(/*.any.*/$value) { $this->value = $value; } + + function getId() + { + return $this->name . '_label'; + } } /** * Поле ввода Input - * @package core */ class TInput extends TField { } +class TCheckbox extends TField +{ + public $checked = false; + function setValue($value) + { + $this->value = $value; + $this->checked = $value; + } +} + + +class TSelect extends TField +{ + public $options = array(); + + public function __construct ($input, $factory) { + parent::__construct($input, $factory); + + if ($factory != null) { + $factory->create($this, $input); + } else if (isset($input['options.pair'])) { + $this->options = $this->optionsPair($input['options.pair']); + } else if (isset($input['options'])) { + $this->options = $input['options']; + } + + foreach ($this->options as &$option) { + $option['selected'] = false; + $option['class'] = (isset($option['class'])) ? $option['class'] : false; + } + } + + public function optionsPair($list, $selected = false) { + $result = array(); + foreach ($list as $key => $value) { + $result [] = array('value' => $key, 'name' => $value, 'selected' => $key == $selected); + } + return $result; + } +} + /** * Выбор из одного элемента */ -class TSelect1 extends TField +class TSelectOne extends TSelect { - public $options = array (); - public function __construct ($input) { - parent::__construct($input); - $this->options = $input['options']; - } - function setValue($value) { // Установить selected у options $this->value = $value; + foreach ($this->options as &$option) { + $option['selected'] = ($option['value'] == $value); + } + } +} + +class TSelectMany extends TSelect +{ + function setValue($value) + { + // Установить selected у options + if (!is_array($value)) { $value = array($value); } + $this->value = $value; + foreach ($this->options as &$option) { + $option['selected'] = (in_array($option['value'], $value)); + } + } +} + +class TQuestionType extends TSelect +{ + function setValue($value) + { + // Установить selected у options + $this->value = $value; + foreach ($this->options as &$option) { + $option['selected'] = ($option['value'] == $value); + } } } /** * Поле с датой - * @package core */ class TDate extends TField { } -/* * +/** + * Поле с цветом + */ +class TColor extends TField +{ +} + + +/** * Текстовое поле - * @package core */ class TTextArea extends TField { + function setValue($value) + { + $this->value = $value; + } } /** * Поле для ввода пароля - * @package core */ class TSecret extends TField { @@ -91,62 +170,181 @@ class TUpload extends TField { } +class THidden extends TInput { + public $hidden = true; +} + +class TComponentBrowserInput extends TInput +{ +} + +/** + * При рендеринге каждому классу соответствует шаблон (см. themes/maxim/templates/macros.html) + */ +class TDateTime extends TInput { +} + +class OptionFactory { + public $db; + + function __construct($db) { + $this->db = $db; + } + + function create(TSelect $field, $input) { + if (isset($input['options.resid'])) { + $type = $input['options.resid']; + + $res = new Model_Resources($this->db); + $field->options = $this->optionsArray('id_section', 'title', $res->getSubsections('', $type)); + + } else if (isset($input['options.res'])) { + $type = $input['options.res']; + + $res = new Model_Resources($this->db); + $field->options = $this->optionsArray('path', 'title', $res->getSubsections('', $type)); + + } else if (isset($input['options.all_res'])) { + $type = $input['options.all_res']; + + $res = new Model_Resources($this->db); + $field->options = $this->optionsArray('id_resource', 'subtitle', $res->getAllResource($type)); + + } else if (isset($input['options.db'])) { + list($table, $keyvalue) = explode(":", $input['options.db']); + list($key, $value) = explode(",", $keyvalue); + + $field->options = $this->optionsDB($key, $value, $this->db->executeQuery("SELECT * FROM $table")); + } elseif (isset($input['options.pair'])) { + $field->options = $this->optionsPair($input['options.pair']); + } else { + $field->options = $input['options']; + } + } + + public function optionsDB($key, $val, $res) { + $result = array(); + while($res->next()) { + $result[] = array('value' => $res->getInt($key), 'name' => $res->getString($val)); + } + return $result; + } + + public function optionsArray($key, $val, $res) { + $result = array(); + foreach($res as $item) { + $result[] = array('value' => $item->{$key}, 'name' => $item->{$val}); + } + return $result; + } + + public function optionsPair($list, $selected = false) { + $result = array(); + foreach ($list as $key => $value) { + $result [] = array('value' => $key, 'name' => $value, 'selected' => $key == $selected); + } + return $result; + } +} + /** * Форма для ввода - * @package core */ -class Form_Form -{ - public $field = array (); +class Form_Form extends View_View { + public $field = array(); public $action = ""; public $method = 'post'; + public $header; + protected $replace; protected $before; + + public $_title = array(); + public $alias = array(); + public $constructor = array(); - public function __construct () + /** + * Строим форму по ее структуре. Каждому типу соответствует определенный класс. + */ + public function __construct() { - $this->constructor = array ( - 'input' => 'TInput', - 'date' => 'TDate', - 'textarea' => 'TTextArea', - 'select' => 'TSelect', - 'select1' => 'TSelect1', - 'secret' => 'TSecret', - 'upload' => 'TUpload' + $this->constructor = array( + 'input' => 'TInput', + 'inputreq' => 'TInput', // input с проверкой на заполненность + + 'date' => 'TDate', + 'datereq' => 'TDate', + 'datetime' => 'TDateTime', + + 'color' => 'TColor', + 'textarea' => 'TTextArea', + 'text' => 'TTextArea', + 'multiselect' => 'TSelectMany', +// 'selectmany' => 'TSelectMany', + 'select1' => 'TSelectOne', + 'select' => 'TSelectOne', + 'questiontype'=> 'TQuestionType', + 'secret' => 'TSecret', + 'upload' => 'TUpload', + 'image' => 'TUpload', + 'checkbox' => 'TCheckbox', + 'checkmany' => 'TSelectMany', + 'hidden' => 'THidden', + 'radio' => 'TSelectOne', + 'filebrowser' => 'TComponentBrowserInput', ); + } + + function getId() + { + return '_form_edit'; + } + + public function addFieldClass($name, $class) + { + $this->constructor [$name] = $class; + } /** * Добавляет одно поле ввода на форму */ - public function addField (array $init) + public function addField(array $init, $factory = null) { - assert (isset($init['type'])); - assert (isset($init['name'])); + assert(isset($init['type'])); + assert(isset($init['name'])); + +// print_r($init); $constructor = $this->constructor[$init['type']]; - $el = new $constructor ($init); - $el->type = $init['type']; + $el = new $constructor($init, $factory); + if (!$el->type) { + $el->type = $init['type']; + } + if(isset($init['hint'])) { + $el->hint = $init['hint']; + } + $this->field [$init['name']] = $el; return $el; } /** - * Добавляет спсок полей для формы + * Добавляет список полей для формы * @param array $list */ - public function addFieldList (array $list) + public function addFieldList(array $list, $factory = null) { foreach ($list as $init) { - $this->addField ($init); + $this->addField($init, $factory); } } /** * Устанавливает ошибки после проверки */ - function setError (Validator $validator) + function setError(Validator_Validator $validator) { foreach ($validator->getErrorMsg() as $name => $error) { @@ -155,12 +353,18 @@ class Form_Form } } + function setFieldError($name, $message) + { + $this->field[$name]->error = true; + $this->field[$name]->error_msg = $message; + } + /** * Устанавливает значения из масива */ - function setValues (Collection $request) { + function setValues(HttpRequest $request) { foreach ($this->field as $key => $el) { - $value = $request->getRawData ($this->method, $key); + $value = $request->getRawData($this->method, $key); $this->field[$key]->setValue($value); } } @@ -170,10 +374,11 @@ class Form_Form * @param object $data * @param array $schema Связь между элементами формы и свойствами обьекта */ - public function fill ($data, array $schema) + public function fill($data, array $schema) { - foreach ($schema as $key => $value) { - $this->field [$value]->setValue($data->$value->getString ()); + foreach ($schema as $key => $conv) { + list($value, $type) = $conv; + $this->field [$key]->setValue(call_user_func(array('Primitive', 'from_' . $type), $data->$value)); } } @@ -181,4 +386,9 @@ class Form_Form { $this->field[$name]->setValue($value); } + + function execute() + { + return $this; + } } diff --git a/src/Primitive.php b/src/Primitive.php index e9dab1a..aec45fd 100644 --- a/src/Primitive.php +++ b/src/Primitive.php @@ -1,103 +1,119 @@ name = $name; + return ((string) $value); } - // Преобразование из внешнего вормата - public function setString ($value) + public static function from_varchar($value) { - $this->value = $value; + return $value; } - // Преобразование из формата базы данных - public function setRes ($res, $key) + // int + public static function to_bool($value) { - $this->value = $res->getString ($key); + return filter_var($value, FILTER_VALIDATE_BOOLEAN);//(int)((bool) $value); } - public function __toString () + public static function from_bool($value) { - return ((string) $this->value); + return ((bool) $value); } - // Преобразование во внешний формат - public function getString () + // int + public static function to_int($value) { - return $this->__toString (); - } -} - -/** - * Отображение поля таблицы в целое число - * @package core - */ -class Int4 extends Primitive { - public function setRes ($res, $key) { - $this->value = $res->getInt ($key); + return ((int) $value); } - public function setString ($value) { - $this->value = ((int) $value); - } -} - -/* Foreign key */ -class FKey extends Int4 {} - -/** - * Отображение поля таблицы в дату - время - */ -class Date extends Primitive -{ - public function setRes ($res, $key) + public static function from_int($value) { - $this->value = $res->getInt ($key); + return ((string) $value); } - - public function setString ($value) + + // date + public static function to_date($value) { - $this->value = 0; - if ($tmp = explode("/",$value,3)) { - if ($tmp[1] && $tmp[0] && $tmp[2]) { - if (checkdate($tmp[1], $tmp[0], $tmp[2])) { - $this->value = mktime(0, 0, 0, $tmp[1], $tmp[0], $tmp[2]); + $result = 0; + $tmp = explode("/", $value, 3); + if (!empty($tmp)) { + if (count($tmp) != 3) return $result; + + $year = intval($tmp[2]); + $month = intval($tmp[1]); + $day = intval($tmp[0]); + + if ($month != 0 && $day != 0 && $year != 0) { + if (checkdate($month, $day, $year)) { + return mktime(0, 0, 0, $month, $day, $year); + } else { + return 0; } } } + return $result; } - public function getString () + public static function to_datetime($value) { - return date ("d/m/Y", $this->value); + $result = 0; + + $tmp = array(); + if (preg_match('/(\d+)-(\d+)-(\d+)T(\d+):(\d+)Z/', $value, $tmp)) { + if (checkdate($tmp[2], $tmp[3], $tmp[1])) { + $result = mktime($tmp[4], $tmp[5], 0, $tmp[2], $tmp[3], $tmp[1]); + } + } + return $result; + } + + public static function from_date($value) + { + if ($value > 0) { + return date("d/m/Y", $value); + } + return ''; + } + + public static function from_datetime($value) + { + if ($value > 0) { + return date("Y-m-d\TH:i\Z", $value); + } + return ''; + } + + + // secure + public static function to_secure($value) + { + // Значение приабразуется во время сохранения в базе данных + return $value; + } + + public static function from_secure($value) + { + return $value; + } + + // array + public static function to_array($value) + { + return (is_array($value)) ? $value : array(); + } + + public static function from_array($value) + { + return $value; } } -/** - * - */ -class Password extends Primitive -{ - public function setRes ($res, $key) - { - $this->value = $res->getString($key); - } - - public function setString ($value) - { - $this->value = md5($value); - } - - public function getString () - { - return $this->value; - } -} diff --git a/src/Tools/String.php b/src/Tools/String.php index 1745b25..32aeb3b 100644 --- a/src/Tools/String.php +++ b/src/Tools/String.php @@ -1,53 +1,107 @@ 0) { // already in sub-array? - $subarr[$in_subarr][] = $tok; - if ('}' === substr($tok, -1, 1)) { // check to see if we just added last component - $res[] = $this->strToArray(implode(',', $subarr[$in_subarr])); - $in_subarr--; - } - } elseif ($tok{0} === '{') { // we're inside a new sub-array - if ('}' !== substr($tok, -1, 1)) { - $in_subarr++; - // if sub-array has more than one element - $subarr[$in_subarr] = array(); - $subarr[$in_subarr][] = $tok; - } else { - $res[] = $this->strToArray($tok); - } - } else { // not sub-array - $val = trim($tok, '"'); // remove " (surrounding strings) - // perform type castng here? - $res[] = $val; - } - } - - return $res; - } - - - static function translit($st) { - $st = strtr($st,"абвгдеёзийклмнопрстуфхъыэ !№", "abvgdeeziyklmnoprstufh_ie__#"); - $st = strtr($st,"АБВГДЕЁЗИЙКЛМНОПРСТУФХЪЫЭ", "ABVGDEEZIYKLMNOPRSTUFH_IE"); - $st = strtr($st, array( - "ж"=>"zh", "ц"=>"ts", "ч"=>"ch", "ш"=>"sh", - "щ"=>"shch","ь"=>"", "ю"=>"yu", "я"=>"ya", - "Ж"=>"ZH", "Ц"=>"TS", "Ч"=>"CH", "Ш"=>"SH", - "Щ"=>"SHCH","Ь"=>"", "Ю"=>"YU", "Я"=>"YA", - "ї"=>"i", "Ї"=>"Yi", "є"=>"ie", "Є"=>"Ye" - )); - return $st; - } +// from creole +function strToArray($str) { + $str = substr($str, 1, -1); // remove { } + $res = array(); + + $subarr = array(); + $in_subarr = 0; + + $toks = explode(',', $str); + foreach($toks as $tok) { + if ($in_subarr > 0) { // already in sub-array? + $subarr[$in_subarr][] = $tok; + if ('}' === substr($tok, -1, 1)) { // check to see if we just added last component + $res[] = strToArray(implode(',', $subarr[$in_subarr])); + $in_subarr--; + } + } elseif ($tok{0} === '{') { // we're inside a new sub-array + if ('}' !== substr($tok, -1, 1)) { + $in_subarr++; + // if sub-array has more than one element + $subarr[$in_subarr] = array(); + $subarr[$in_subarr][] = $tok; + } else { + $res[] = strToArray($tok); + } + } else { // not sub-array + $val = trim($tok, '"'); // remove " (surrounding strings) + // perform type castng here? + $res[] = $val; + } + } + + return $res; +} + +//Нормализация строк на русском +function normalizeRussian($str) { + $result = preg_replace('/\s+/',' ', $str); + if (is_string($result)) { + $result = trim($result); //Замена длинных пробелов на одинарные, пробелы по краям + $result = mb_strtolower($result); + $result = preg_replace('/ё/','е', $str); //е на ё + } + return $result; +} + +//Проверка равенства двух строк на русском языке. +function equalRussianCheck($str1,$str2) { + return normalizeRussian($str1) == normalizeRussian($str2); +} + + +/** + * Попадает ли строка в список вариантов + * input: $str="foo1" $variants="foo1|foo2|foo3" + * output: true + * input: $str="foo" $variants="foo1|foo2|foo3" + * output: false +*/ +function compare_string_to_variants($str, $variants){ + $variants_array = explode('|', $variants); + $founded = false; + foreach ($variants_array as $variant) { + $founded = $founded || equalRussianCheck($variant, $str); + } + return $founded; +} + +function mb_str_split($str) { + return preg_split('~~u', $str, null, PREG_SPLIT_NO_EMPTY); +} + +function mb_strtr($str, $from, $to) { + return str_replace(mb_str_split($from), mb_str_split($to), $str); +} + +function encodestring($st) { + $st = mb_strtr($st,"абвгдеёзийклмнопрстуфхъыэ !+-()", "abvgdeeziyklmnoprstufh_ie______"); + $st = mb_strtr($st,"АБВГДЕЁЗИЙКЛМНОПРСТУФХЪЫЭ", "ABVGDEEZIYKLMNOPRSTUFH_IE"); + $st = strtr($st, array( + " " => '_', + "." => '_', + "," => '_', + "?" => '_', + "\"" => '_', + "'" => '_', + "/" => '_', + "\\" => '_', + "%" => '_', + "#" => '_', + "*" => '_', + "ж"=>"zh", "ц"=>"ts", "ч"=>"ch", "ш"=>"sh", + "щ"=>"shch","ь"=>"", "ю"=>"yu", "я"=>"ya", + "Ж"=>"ZH", "Ц"=>"TS", "Ч"=>"CH", "Ш"=>"SH", + "Щ"=>"SHCH","Ь"=>"", "Ю"=>"YU", "Я"=>"YA", + "Й"=>"i", "й"=>"ie", "ё"=>"Ye", + "№"=>"N" + )); + return strtolower($st); +} + +function validate_encoded_string($st) { + $enc_st = encodestring($st); + return preg_match('/^[\w_-]+(\.[\w_-]+)?$/', $enc_st); } diff --git a/src/Validator/Rule/Alpha.php b/src/Validator/Rule/Alpha.php index 02b422e..2443da1 100644 --- a/src/Validator/Rule/Alpha.php +++ b/src/Validator/Rule/Alpha.php @@ -3,7 +3,7 @@ /** * Проверка на число */ -class Validator_Rule_Alpha extends Rule_Abstract +class Validator_Rule_Alpha extends Validator_Rule_Abstract { public function getErrorMsg() { diff --git a/src/Validator/Rule/Date.php b/src/Validator/Rule/Date.php index 8b40b4d..be8e17e 100644 --- a/src/Validator/Rule/Date.php +++ b/src/Validator/Rule/Date.php @@ -3,7 +3,7 @@ /** * Проверка формата даты */ -class Validator_Rule_Date extends Rule_Abstract +class Validator_Rule_Date extends Validator_Rule_Abstract { private $split = "\\/"; diff --git a/src/Validator/Rule/Email.php b/src/Validator/Rule/Email.php index e40486a..dd2b0e0 100644 --- a/src/Validator/Rule/Email.php +++ b/src/Validator/Rule/Email.php @@ -3,7 +3,7 @@ /** * Проверка формата электронной почты */ -class Validator_Rule_Email extends Rule_Abstract +class Validator_Rule_Email extends Validator_Rule_Abstract { public function getErrorMsg() { diff --git a/src/Validator/Rule/EmailList.php b/src/Validator/Rule/EmailList.php index 16bdd50..98ac122 100644 --- a/src/Validator/Rule/EmailList.php +++ b/src/Validator/Rule/EmailList.php @@ -3,7 +3,7 @@ /** * Проверка формата электронной почты */ -class Validator_Rule_EmailList extends Rule_Abstract +class Validator_Rule_EmailList extends Validator_Rule_Abstract { public function getErrorMsg() { diff --git a/src/Validator/Rule/Match.php b/src/Validator/Rule/Match.php index c3fdcdf..eb37a82 100644 --- a/src/Validator/Rule/Match.php +++ b/src/Validator/Rule/Match.php @@ -3,7 +3,7 @@ /** * Проверка на равентство двух полей */ -class Validator_Rule_Match extends Rule_Abstract +class Validator_Rule_Match extends Validator_Rule_Abstract { public $same; @@ -12,14 +12,6 @@ class Validator_Rule_Match extends Rule_Abstract return "Поля не совпадают"; } -/* public function __construct($field, $refField, $errorMsg) - { - $this->field = $field; - $this->refField = $refField; - $this->errorMsg = $errorMsg; - } -*/ - public function isValid(Collection $container, $status = null) { return (strcmp($container->get($this->field), $container->get($this->same)) == 0); } diff --git a/src/Validator/Rule/Numeric.php b/src/Validator/Rule/Numeric.php index 86b2bc2..2d080e7 100644 --- a/src/Validator/Rule/Numeric.php +++ b/src/Validator/Rule/Numeric.php @@ -3,7 +3,7 @@ /** * Проверка на число */ -class Validator_Rule_Numeric extends Rule_Abstract +class Validator_Rule_Numeric extends Validator_Rule_Abstract { public function getErrorMsg() { diff --git a/src/Validator/Rule/Time.php b/src/Validator/Rule/Time.php index b343a84..05a7a46 100644 --- a/src/Validator/Rule/Time.php +++ b/src/Validator/Rule/Time.php @@ -3,7 +3,7 @@ /** * Проверка формата времени */ -class Validator_Rule_Time extends Rule_Abstract +class Validator_Rule_Time extends Validator_Rule_Abstract { private $split = ":"; diff --git a/src/Validator/Rule/Unique.php b/src/Validator/Rule/Unique.php index fe97a07..e458b8d 100644 --- a/src/Validator/Rule/Unique.php +++ b/src/Validator/Rule/Unique.php @@ -1,9 +1,8 @@ ctx->isUnique($container->get($this->field), $status); + return $this->ctx->isUnique($container->get($this->field), $status, $container); } } diff --git a/src/Validator/Validator.php b/src/Validator/Validator.php index 4f053a4..fe3ea2e 100644 --- a/src/Validator/Validator.php +++ b/src/Validator/Validator.php @@ -32,7 +32,8 @@ class Validator_Validator 'require' => 'Validator_Rule_Notnull', 'numeric' => 'Validator_Rule_Numeric', 'unique' => 'Validator_Rule_Unique', - 'count' => 'Validator_Rule_Count', + 'filename' => 'Validator_Rule_FileName', + 'count' => 'Validator_Rule_Count', 'isfile' => 'Validator_Rule_IsFile', 'code' => 'Validator_Rule_Code' ); @@ -41,8 +42,7 @@ class Validator_Validator // Формат правила 'rule1|rule2,param1=value1|rule3,param1=value1,param2=value2' foreach ($input as $value) { // Список правил - if (!isset($value['validate']) || $value['validate'] == '') continue; - + if (! isset($value['validate'])) continue; $rules = explode("|", $value['validate']); foreach ($rules as $rule) { // Список параметров правила @@ -50,17 +50,17 @@ class Validator_Validator $name = array_shift($rule_param); if (isset($type[$name])) { - $constructor = $type[$name]; // "Rule_" . ucfirst($name) - $rule = new $constructor($value['name'], false); // Нужны шаблонные сообщения для правил + $constructor = $type[$name]; + $ruleObj = new $constructor($value['name'], false); // Нужны шаблонные сообщения для правил if (isset($value['context'])) { - $rule->setContext($value['context']); + $ruleObj->setContext($value['context']); } foreach ($rule_param as $param) { // Имя и значение параметра - list($name, $value) = explode("=", $param); - $rule->$name = $value; + list($p_name, $p_value) = explode("=", $param); + $ruleObj->$p_name = $p_value; } - $this->addRule($rule); + $this->addRule($ruleObj); } else { throw new Exception('Unknown validation rule "' . $rule . "'"); } @@ -90,14 +90,17 @@ class Validator_Validator public function validate(Collection $container, $rule = null, $status = null) { + $fields = array(); if ($rule) { $this->chain = $rule; } $this->errorMsg = array(); - foreach ($this->chain as $key => $rule) { - if (!$this->skip($rule, $container) && !$rule->isValid($container, $status)) { + foreach ($this->chain as $rule) { + //echo $key; + if (!in_array($rule->field, $fields) && !$this->skip($rule, $container) && !$rule->isValid($container, $status)) { $name = $rule->field; $this->errorMsg[$name] = $rule->getErrorMsg(); + $fields [] = $name; } } return $this->isValid(); diff --git a/src/View/Composite.php b/src/View/Composite.php index e9427a6..0a21508 100644 --- a/src/View/Composite.php +++ b/src/View/Composite.php @@ -1,36 +1,37 @@ tal = new PHPTAL($file); + $this->tal->setPhpCodeDestination(PHPTAL_PHP_CODE_DESTINATION); + $this->tal->setEncoding(PHPTAL_DEFAULT_ENCODING); // PHPTAL_DEFAULT_ENCODING !! + $this->tal->setTemplateRepository(PHPTAL_TEMPLATE_REPOSITORY); + $this->tal->setOutputMode(PHPTAL::HTML5); $this->tal->stripComments(true); +// $this->tal->addPreFilter(new PHPTAL_PreFilter_Normalize()); } - function set($key, $val) - { + function set($key, $val) { if ($key == 'title') { $this->setTitle($val); } $this->tal->set($key, $val); } - function __set($key, $val) - { + function __set($key, $val) { $this->tal->set($key, $val); } - function setTranslator($tr) - { - $this->tal->setTranslator($tr); - } - function execute() { parent::execute(); diff --git a/src/View/Top.php b/src/View/Top.php index 776d6d4..95bbff5 100644 --- a/src/View/Top.php +++ b/src/View/Top.php @@ -1,88 +1,139 @@ _section [$section] = $view; + return implode(" - ", array_filter($this->doTree('_title', false), array($this, 'isNotNull'))); } - public function jGrowl($message, $args) + private function findGroup($groups, $file) { - $this->addScriptRaw('$.jGrowl("' . $message . '", ' . json_encode($args) . ");\n", true); - } - - public function setGlobal($name, $args) - { - $this->addScriptRaw("var " . $name . " = " . json_encode($args) . ";\n", false); - } - - /** - * Добавляет скипт к текущему шаблону - * - * @param string $name путь к скрипту - */ - public function addScript($name) - { - $this->_script [] = $name; - } - - /** - * Добавляет код скипта к текущему шаблону - * - * @param string $name строка javascript кода - */ - public function addScriptRaw($name, $startup = false) - { - if ($startup) { - $this->_startup [] = $name; - } else { - $this->_scriptstring [] = $name; + foreach($groups as $key => $group) { + if(in_array($file, $group)) { + return $key; + } } + return false; } + private function groupFiles(array $list, $debug = true) + { + $debug = ($debug) ? 'debug=1' : ''; + $path = parse_url(WWW_PATH, PHP_URL_PATH); + // Группы определять в import через , + $groups = array( ); + $use = array(); + + $result = array(); + foreach ($list as $file) { + $name = $this->findGroup($groups, $file); + if($name) { + $use [$name] = 1; + } else { + if (strpos($file, 'ckeditor')) { + $result [] = $file; + } else { +// $result [] = WWW_PATH . "/min/?$debug&f=" . parse_url($file, PHP_URL_PATH); + $result [] = $file; + } + } + } + $list = array(); + foreach ($use as $name => $value) { +// $list [] = WWW_PATH . "/min/?$debug&f=" . implode(",", $groups[$name]); + $list [] = $groups[$name]; + } + + return array_merge($list, $result); + } + + + function getId($pref) { + $this->mid++; + return $pref.$this->mid; + } + /** - * Добавляет стили к текущему шаблону - * - * @param string $name путь к стилю - */ - public function addStyleSheet($name) - { - $this->_stylesheet [] = $name; - } - - /** - * Рекурсивно извлекает из значение свойства обьекта + * Обработка шаблона * - * @param string $list Имя свойства - * @param boolean $flatten + * @return string */ - private function doTree($list, $flatten = true) { - $result = ($flatten == true) ? $this->$list : array($this->$list); - foreach ($this->_section as $key => $value) { - if (is_object($value)) $result = array_merge($value->doTree($list, $flatten), $result); - } - return $result; + public function render() + { + + $alias = $this->doTree('alias'); + +// require_once 'minify.php'; + // Скрипты и стили + $this->set('scriptstring', $this->getScriptRaw()); + $this->set('scripts', array_unique($this->groupFiles($this->getScripts(), false))); + $this->set('stylesheet', array_unique($this->groupFiles($this->getStyleSheet(), false))); + + $this->require = array('admin' => 'ma'); + $this->deps = array(); + + $startup = array(); + foreach($this->_section as $s) { + $module = explode('_', $s->active_module, 2); + if (count($module) < 2) { + continue; + } + + $module = $module[1]; + + $name = mb_strtolower($module); + $fname = $name . '/' . $name; + + $current = $this->getId('m'); + $this->require[$fname] = $current; + + $value = $this->getId('v'); + + $script = "var " . $value . " = new " . $current . '.' . $module . "();\n"; + foreach($s->_values as $key => $v) { + $script .= $value . "." . $key . " = " . json_encode($v/*, JSON_PRETTY_PRINT*/) . ";\n"; + } + + $init = array(); + foreach($s->_section as $key => $item) { + /*.View_View.*/$ss = $item; + if ($ss->codeGenerator !== null) { + // функцию которая вычисляет а не результат + $part = call_user_func($ss->codeGenerator, $this, $key, $value); + $init [] = $part; + } + } + + $script .= $value . ".execute('" . $s->module_action . "', " . json_encode($init) .");\n"; + $startup[] = $script; + + } + + +/* echo "

";
+		print_r($this->require);
+		print_r(implode("", $startup));
+		echo "
";*/ + + //$this->set('scriptstring', ''); + $this->set('startup', implode("", $startup) . $this->getScriptStartup()); + + + $this->set('require', implode(",", array_map(function ($x) { return "'$x'";}, array_keys($this->require)))); + $this->set('deps', implode(",", array_values($this->require))); + + + $this->set('title', $this->getTitle()); + $this->set('jspath', WWW_PATH); + // + return $this->execute(); // execute+phptal ?? } /** @@ -95,15 +146,6 @@ class View_Top // AbstractCompositeView return $this->doTree('_script'); } - function resolveAlias($alias, $list) - { - $result = array(); - foreach($list as $item) { - $result [] = strtr($item, $alias); - } - return $result; - } - /** * Строка со скриптом * @@ -119,10 +161,6 @@ class View_Top // AbstractCompositeView return implode("\n", $this->doTree('_startup')); } - /*abstract*/ public function set($key, $value) - { - } - /** * Массив имен файлов стилей * @@ -132,128 +170,5 @@ class View_Top // AbstractCompositeView { return $this->doTree('_stylesheet'); } - - /** - * Обработка всех вложенных шаблонов - * - * @return string - */ - public function execute() - { - foreach ($this->_section as $key => $value) { - $this->set($key, (is_object($value)) ? $value->execute() : $value); // ? - } - } - /** - * Установка заголовка шаблона - * - * @param string $title - */ - public function setTitle($title) - { - $this->_title = $title; - } - - private function isNotNull($title) - { - return $title !== null; - } - - /** - * Общая строка заголовка - */ - public function getTitle() - { - return implode(" - ", array_filter($this->doTree('_title', false), array($this, 'isNotNull'))); - } - - private function findGroup($groups, $file) - { - foreach($groups as $key => $group) { - if(in_array($file, $group)) { - return $key; - } - } - return false; - } - - private function groupFiles(array $list, $debug) - { - $debug = ($debug) ? 'debug=1' : ''; - $path = parse_url(WWW_PATH, PHP_URL_PATH); - $list = array_reverse($list); - // Группы нужно передвавать как параметр !!! - $groups = array( - 'table' => array($path . '/js/table.js', $path . '/js/listtable.js', - $path . '/js/page.js', $path . '/js/pagemenu.js'), - 'base' => array($path . '/js/admin.js', $path . '/js/cookie.js'), - ); - $use = array(); - - $result = array(); - foreach ($list as $file) { - $name = $this->findGroup($groups, $file); - if($name) { - $use [$name] = 1; - } else { - $result [] = $file; - } - } - $list = array(); - foreach ($use as $name => $value) { - $list [] = WWW_PATH . "/min/?$debug&f=" . implode(",", $groups[$name]); - } - return array_merge($list, $result); - } - - /** - * Обработка шаблона - * - * @return string - */ - public function render() - { - - $alias = $this->doTree('alias'); - -// require_once 'minify.php'; - // Скрипты и стили - $this->set('scripts', array_unique($this->groupFiles($this->resolveAlias($alias, $this->getScripts()), false))); - $this->set('stylesheet', array_unique($this->groupFiles($this->resolveAlias($alias, $this->getStyleSheet()), false))); - - $this->set('scriptstring', $this->getScriptRaw()); - $this->set('startup', $this->getScriptStartup()); - $this->set('title', $this->getTitle()); - // - return $this->execute(); // execute+phptal ?? - } - - function setAlias($alias) - { - $this->alias = $alias; - } - - function addAlias($name, $path) - { - $this->alias['${' . $name . '}'] = $path; - $this->set($name, $path); - } - - function loadImports($importFile) - { - // Подключение стилей и скриптов - if (file_exists($importFile)) { - $import = file_get_contents($importFile); - $files = explode("\n", $import); - foreach ($files as $file) { - if (strpos($file, ".js") !== false) { - $this->addScript(strtr(trim($file), $this->alias)); - } else if(strpos($file, ".css") !== false) { - $this->addStyleSheet(strtr(trim($file), $this->alias)); - } - } - } - } } -