diff --git a/CHANGELOG-4.0.md b/CHANGELOG-4.0.md index a32ce70885a..426d2be7b55 100644 --- a/CHANGELOG-4.0.md +++ b/CHANGELOG-4.0.md @@ -7,6 +7,7 @@ - Added `chunk()`, `first()`, `firstKey()`, `flatten()`, `group()`, `isUnique()`, `last()`, `lastKey()`, `order()`, `pluck()`, `sliceLeft()`, `sliceRight()`, `split()`, `tail()`, `validateAll()`, `validateAny()` to `Phalcon\Helper\Arr` [#13954](https://github.com/phalcon/cphalcon/pull/13954) - Added `camelize()`, `concat()`, `countVowels()`, `decapitalize()`, `dynamic()`, `endsWith()`, `firstStringBetween()`, `includes()`, `increment()`, `isAnagram()`, `isLower()`, `isPalindrome()`, `isUpper()`, `lower()`, `random()`, `reduceSlashes()`, `startsWith()`, `uncamelize()`, `underscore()`, `upper()` to `Phalcon\Helper\Str` [#13954](https://github.com/phalcon/cphalcon/pull/13954) - Added `Phalcon\Mvc\Model\Query\BuilderInterface::getModels()` returns the models involved in the query +- Added `addConnect()`, `addPurge()` and `addTrace()` to `Phalcon\Mvc\Router\Group` and its interface. [#14001](https://github.com/phalcon/cphalcon/pull/14001) ## Changed - Refactored `Phalcon\Events\Manager` to only use `SplPriorityQueue` to store events. [#13924](https://github.com/phalcon/cphalcon/pull/13924) @@ -31,6 +32,7 @@ - Query Builder's `GROUP BY` field is now always an array. [#13962](https://github.com/phalcon/cphalcon/pull/13962) - Renamed `Phalcon\Paginator\Adapter::getPaginate()` to `paginate()` in documentation/tests (originally renamed in 4.0.0-alpha.1). [#13973](https://github.com/phalcon/cphalcon/pull/13973) - Fixed the exception message in `Phalcon\Security::computeHmac()` by removing `"%s"` from output. +- `Phalcon\Mvc\Model\Relation::isForeignKey()` now returns false if the `foreignKey` option is set to `false`. ## Removed - Removed `arrayHelpers` property from the Volt compiler. [#13925](https://github.com/phalcon/cphalcon/pull/13925) diff --git a/phalcon/Annotations/Reflection.zep b/phalcon/Annotations/Reflection.zep index 41aaf6e23be..7a98966e8d6 100644 --- a/phalcon/Annotations/Reflection.zep +++ b/phalcon/Annotations/Reflection.zep @@ -90,7 +90,7 @@ class Reflection */ public function getMethodsAnnotations() -> | bool { - var reflectionMethods, collections, methodName, reflectionMethod; + var reflectionMethods, methodName, reflectionMethod; if this->methodAnnotations === null { if fetch reflectionMethods, this->reflectionData["methods"] { diff --git a/phalcon/Db/Adapter.zep b/phalcon/Db/Adapter.zep index bce79401473..da0cc44b449 100644 --- a/phalcon/Db/Adapter.zep +++ b/phalcon/Db/Adapter.zep @@ -119,10 +119,8 @@ abstract class Adapter implements AdapterInterface, EventsAwareInterface */ if typeof dialectClass == "string" { let this->dialect = new {dialectClass}(); - } else { - if typeof dialectClass == "object" { - let this->dialect = dialectClass; - } + } elseif typeof dialectClass == "object" { + let this->dialect = dialectClass; } let this->descriptor = descriptor; @@ -270,10 +268,10 @@ abstract class Adapter implements AdapterInterface, EventsAwareInterface let escapedTable = this->escapeIdentifier(table); + let sql = "DELETE FROM " . escapedTable; + if !empty whereCondition { - let sql = "DELETE FROM " . escapedTable . " WHERE " . whereCondition; - } else { - let sql = "DELETE FROM " . escapedTable; + let sql .= " WHERE " . whereCondition; } /** @@ -587,13 +585,16 @@ abstract class Adapter implements AdapterInterface, EventsAwareInterface var result; let result = this->{"query"}(sqlQuery, bindParams, bindTypes); - if typeof result == "object" { - if typeof fetchMode !== "null" { - result->setFetchMode(fetchMode); - } - return result->$fetch(); + + if typeof result != "object" { + return []; } - return []; + + if typeof fetchMode !== "null" { + result->setFetchMode(fetchMode); + } + + return result->$fetch(); } /** diff --git a/phalcon/Db/AdapterInterface.zep b/phalcon/Db/AdapterInterface.zep index bbbb141c20f..56b128e6d8a 100644 --- a/phalcon/Db/AdapterInterface.zep +++ b/phalcon/Db/AdapterInterface.zep @@ -425,5 +425,4 @@ interface AdapterInterface * Generates SQL checking for the existence of a schema.view */ public function viewExists(string! viewName, string! schemaName = null) -> bool; - } diff --git a/phalcon/Db/Column.zep b/phalcon/Db/Column.zep index 33695e2c19b..9703df5b682 100644 --- a/phalcon/Db/Column.zep +++ b/phalcon/Db/Column.zep @@ -40,7 +40,6 @@ use Phalcon\Db\ColumnInterface; */ class Column implements ColumnInterface { - /** * Bind Type Blob */ @@ -329,12 +328,12 @@ class Column implements ColumnInterface /** * Get the column type, one of the TYPE_* constants */ - if fetch type, definition["type"] { - let this->type = type; - } else { + if !fetch type, definition["type"] { throw new Exception("Column type is required"); } + let this->type = type; + if fetch typeReference, definition["typeReference"] { let this->typeReference = typeReference; } @@ -445,7 +444,6 @@ class Column implements ColumnInterface if fetch bindType, definition["bindType"] { let this->bindType = bindType; } - } /** diff --git a/phalcon/Db/ColumnInterface.zep b/phalcon/Db/ColumnInterface.zep index c6d39c10494..50e5fe2f0eb 100644 --- a/phalcon/Db/ColumnInterface.zep +++ b/phalcon/Db/ColumnInterface.zep @@ -43,29 +43,21 @@ interface ColumnInterface /** * Returns column name - * - * @return string */ public function getName() -> string; /** * Returns column scale - * - * @return int */ public function getScale() -> int; /** * Returns schema's table related to column - * - * @return string */ public function getSchemaName() -> string; /** * Returns column size - * - * @return int */ public function getSize() -> int; @@ -78,8 +70,6 @@ interface ColumnInterface /** * Returns column type reference - * - * @return int */ public function getTypeReference() -> int; diff --git a/phalcon/Db/Dialect.zep b/phalcon/Db/Dialect.zep index d6845eda1c7..df6481344ca 100644 --- a/phalcon/Db/Dialect.zep +++ b/phalcon/Db/Dialect.zep @@ -18,7 +18,6 @@ namespace Phalcon\Db; */ abstract class Dialect implements DialectInterface { - protected escapeChar; protected customFunctions; diff --git a/phalcon/Db/Dialect/Mysql.zep b/phalcon/Db/Dialect/Mysql.zep index aa3f4289be3..07c9893f05e 100644 --- a/phalcon/Db/Dialect/Mysql.zep +++ b/phalcon/Db/Dialect/Mysql.zep @@ -25,7 +25,6 @@ use Phalcon\Db\DialectInterface; */ class Mysql extends Dialect { - protected escapeChar = "`"; /** @@ -579,11 +578,7 @@ class Mysql extends Dialect */ public function getForeignKeyChecks() -> string { - var sql; - - let sql = "SELECT @@foreign_key_checks"; - - return sql; + return "SELECT @@foreign_key_checks"; } /** diff --git a/phalcon/Db/Dialect/Postgresql.zep b/phalcon/Db/Dialect/Postgresql.zep index 0c2f1d3894a..ec08dcf04a1 100644 --- a/phalcon/Db/Dialect/Postgresql.zep +++ b/phalcon/Db/Dialect/Postgresql.zep @@ -25,7 +25,6 @@ use Phalcon\Db\DialectInterface; */ class Postgresql extends Dialect { - protected escapeChar = "\""; /** @@ -56,28 +55,28 @@ class Postgresql extends Dialect */ public function addForeignKey(string! tableName, string! schemaName, reference) -> string { - var sql, onDelete, onUpdate; - - let sql = "ALTER TABLE " . this->prepareTable(tableName, schemaName) . " ADD"; - if reference->getName() { - let sql .= " CONSTRAINT \"" . reference->getName() . "\""; - } - let sql .= " FOREIGN KEY (" . this->getColumnList(reference->getColumns()) . ")" - . " REFERENCES \"" . reference->getReferencedTable() . "\" (" . this->getColumnList(reference->getReferencedColumns()) . ")"; + var sql, onDelete, onUpdate; - let onDelete = reference->getOnDelete(); - if !empty onDelete { - let sql .= " ON DELETE " . onDelete; - } + let sql = "ALTER TABLE " . this->prepareTable(tableName, schemaName) . " ADD"; + if reference->getName() { + let sql .= " CONSTRAINT \"" . reference->getName() . "\""; + } + let sql .= " FOREIGN KEY (" . this->getColumnList(reference->getColumns()) . ")" + . " REFERENCES \"" . reference->getReferencedTable() . "\" (" . this->getColumnList(reference->getReferencedColumns()) . ")"; - let onUpdate = reference->getOnUpdate(); - if !empty onUpdate { - let sql .= " ON UPDATE " . onUpdate; - } + let onDelete = reference->getOnDelete(); + if !empty onDelete { + let sql .= " ON DELETE " . onDelete; + } - return sql; + let onUpdate = reference->getOnUpdate(); + if !empty onUpdate { + let sql .= " ON UPDATE " . onUpdate; } + return sql; + } + /** * Generates SQL to add an index to a table */ @@ -273,10 +272,11 @@ class Postgresql extends Dialect */ public function describeColumns(string! table, string schema = null) -> string { - if schema { - return "SELECT DISTINCT c.column_name AS Field, c.data_type AS Type, c.character_maximum_length AS Size, c.numeric_precision AS NumericSize, c.numeric_scale AS NumericScale, c.is_nullable AS Null, CASE WHEN pkc.column_name NOTNULL THEN 'PRI' ELSE '' END AS Key, CASE WHEN c.data_type LIKE '%int%' AND c.column_default LIKE '%nextval%' THEN 'auto_increment' ELSE '' END AS Extra, c.ordinal_position AS Position, c.column_default FROM information_schema.columns c LEFT JOIN ( SELECT kcu.column_name, kcu.table_name, kcu.table_schema FROM information_schema.table_constraints tc INNER JOIN information_schema.key_column_usage kcu on (kcu.constraint_name = tc.constraint_name and kcu.table_name=tc.table_name and kcu.table_schema=tc.table_schema) WHERE tc.constraint_type='PRIMARY KEY') pkc ON (c.column_name=pkc.column_name AND c.table_schema = pkc.table_schema AND c.table_name=pkc.table_name) WHERE c.table_schema='" . schema . "' AND c.table_name='" . table . "' ORDER BY c.ordinal_position"; + if schema === null { + let schema = "public"; } - return "SELECT DISTINCT c.column_name AS Field, c.data_type AS Type, c.character_maximum_length AS Size, c.numeric_precision AS NumericSize, c.numeric_scale AS NumericScale, c.is_nullable AS Null, CASE WHEN pkc.column_name NOTNULL THEN 'PRI' ELSE '' END AS Key, CASE WHEN c.data_type LIKE '%int%' AND c.column_default LIKE '%nextval%' THEN 'auto_increment' ELSE '' END AS Extra, c.ordinal_position AS Position, c.column_default FROM information_schema.columns c LEFT JOIN ( SELECT kcu.column_name, kcu.table_name, kcu.table_schema FROM information_schema.table_constraints tc INNER JOIN information_schema.key_column_usage kcu on (kcu.constraint_name = tc.constraint_name and kcu.table_name=tc.table_name and kcu.table_schema=tc.table_schema) WHERE tc.constraint_type='PRIMARY KEY') pkc ON (c.column_name=pkc.column_name AND c.table_schema = pkc.table_schema AND c.table_name=pkc.table_name) WHERE c.table_schema='public' AND c.table_name='" . table . "' ORDER BY c.ordinal_position"; + + return "SELECT DISTINCT c.column_name AS Field, c.data_type AS Type, c.character_maximum_length AS Size, c.numeric_precision AS NumericSize, c.numeric_scale AS NumericScale, c.is_nullable AS Null, CASE WHEN pkc.column_name NOTNULL THEN 'PRI' ELSE '' END AS Key, CASE WHEN c.data_type LIKE '%int%' AND c.column_default LIKE '%nextval%' THEN 'auto_increment' ELSE '' END AS Extra, c.ordinal_position AS Position, c.column_default FROM information_schema.columns c LEFT JOIN ( SELECT kcu.column_name, kcu.table_name, kcu.table_schema FROM information_schema.table_constraints tc INNER JOIN information_schema.key_column_usage kcu on (kcu.constraint_name = tc.constraint_name and kcu.table_name=tc.table_name and kcu.table_schema=tc.table_schema) WHERE tc.constraint_type='PRIMARY KEY') pkc ON (c.column_name=pkc.column_name AND c.table_schema = pkc.table_schema AND c.table_name=pkc.table_name) WHERE c.table_schema='" . schema . "' AND c.table_name='" . table . "' ORDER BY c.ordinal_position"; } /** @@ -292,15 +292,11 @@ class Postgresql extends Dialect */ public function describeReferences(string! table, string schema = null) -> string { - var sql = "SELECT DISTINCT tc.table_name AS TABLE_NAME, kcu.column_name AS COLUMN_NAME, tc.constraint_name AS CONSTRAINT_NAME, tc.table_catalog AS REFERENCED_TABLE_SCHEMA, ccu.table_name AS REFERENCED_TABLE_NAME, ccu.column_name AS REFERENCED_COLUMN_NAME, rc.update_rule AS UPDATE_RULE, rc.delete_rule AS DELETE_RULE FROM information_schema.table_constraints AS tc JOIN information_schema.key_column_usage AS kcu ON tc.constraint_name = kcu.constraint_name JOIN information_schema.constraint_column_usage AS ccu ON ccu.constraint_name = tc.constraint_name JOIN information_schema.referential_constraints rc ON tc.constraint_catalog = rc.constraint_catalog AND tc.constraint_schema = rc.constraint_schema AND tc.constraint_name = rc.constraint_name AND tc.constraint_type = 'FOREIGN KEY' WHERE constraint_type = 'FOREIGN KEY' AND "; - - if schema { - let sql .= "tc.table_schema = '" . schema . "' AND tc.table_name='" . table . "'"; - } else { - let sql .= "tc.table_schema = 'public' AND tc.table_name='" . table . "'"; + if schema === null { + let schema = "public"; } - return sql; + return "SELECT DISTINCT tc.table_name AS TABLE_NAME, kcu.column_name AS COLUMN_NAME, tc.constraint_name AS CONSTRAINT_NAME, tc.table_catalog AS REFERENCED_TABLE_SCHEMA, ccu.table_name AS REFERENCED_TABLE_NAME, ccu.column_name AS REFERENCED_COLUMN_NAME, rc.update_rule AS UPDATE_RULE, rc.delete_rule AS DELETE_RULE FROM information_schema.table_constraints AS tc JOIN information_schema.key_column_usage AS kcu ON tc.constraint_name = kcu.constraint_name JOIN information_schema.constraint_column_usage AS ccu ON ccu.constraint_name = tc.constraint_name JOIN information_schema.referential_constraints rc ON tc.constraint_catalog = rc.constraint_catalog AND tc.constraint_schema = rc.constraint_schema AND tc.constraint_name = rc.constraint_name AND tc.constraint_type = 'FOREIGN KEY' WHERE constraint_type = 'FOREIGN KEY' AND tc.table_schema = '" . schema . "' AND tc.table_name='" . table . "'"; } /** @@ -509,10 +505,11 @@ class Postgresql extends Dialect */ public function listTables(string schemaName = null) -> string { - if schemaName { - return "SELECT table_name FROM information_schema.tables WHERE table_schema = '" . schemaName . "' ORDER BY table_name"; + if schemaName === null { + let schemaName = "public"; } - return "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' ORDER BY table_name"; + + return "SELECT table_name FROM information_schema.tables WHERE table_schema = '" . schemaName . "' ORDER BY table_name"; } /** @@ -520,10 +517,11 @@ class Postgresql extends Dialect */ public function listViews(string schemaName = null) -> string { - if schemaName { - return "SELECT viewname AS view_name FROM pg_views WHERE schemaname = '" . schemaName . "' ORDER BY view_name"; + if schemaName === null { + let schemaName = "public"; } - return "SELECT viewname AS view_name FROM pg_views WHERE schemaname = 'public' ORDER BY view_name"; + + return "SELECT viewname AS view_name FROM pg_views WHERE schemaname = '" . schemaName . "' ORDER BY view_name"; } /** @@ -599,10 +597,11 @@ class Postgresql extends Dialect */ public function tableExists(string! tableName, string schemaName = null) -> string { - if schemaName { - return "SELECT CASE WHEN COUNT(*) > 0 THEN 1 ELSE 0 END FROM information_schema.tables WHERE table_schema = '" . schemaName . "' AND table_name='" . tableName . "'"; + if schemaName === null { + let schemaName = "public"; } - return "SELECT CASE WHEN COUNT(*) > 0 THEN 1 ELSE 0 END FROM information_schema.tables WHERE table_schema = 'public' AND table_name='" . tableName . "'"; + + return "SELECT CASE WHEN COUNT(*) > 0 THEN 1 ELSE 0 END FROM information_schema.tables WHERE table_schema = '" . schemaName . "' AND table_name='" . tableName . "'"; } /** @@ -636,10 +635,11 @@ class Postgresql extends Dialect */ public function viewExists(string! viewName, string schemaName = null) -> string { - if schemaName { - return "SELECT CASE WHEN COUNT(*) > 0 THEN 1 ELSE 0 END FROM pg_views WHERE viewname='" . viewName . "' AND schemaname='" . schemaName . "'"; + if schemaName === null { + let schemaName = "public"; } - return "SELECT CASE WHEN COUNT(*) > 0 THEN 1 ELSE 0 END FROM pg_views WHERE viewname='" . viewName . "' AND schemaname='public'"; + + return "SELECT CASE WHEN COUNT(*) > 0 THEN 1 ELSE 0 END FROM pg_views WHERE viewname='" . viewName . "' AND schemaname='" . schemaName . "'"; } protected function castDefault( column) -> string diff --git a/phalcon/Db/Dialect/Sqlite.zep b/phalcon/Db/Dialect/Sqlite.zep index 42df9711ce2..00cab0385c1 100644 --- a/phalcon/Db/Dialect/Sqlite.zep +++ b/phalcon/Db/Dialect/Sqlite.zep @@ -25,7 +25,6 @@ use Phalcon\Db\ReferenceInterface; */ class Sqlite extends Dialect { - protected escapeChar = "\""; /** diff --git a/phalcon/Db/Profiler/Item.zep b/phalcon/Db/Profiler/Item.zep index afc0601715f..cc313bc4474 100644 --- a/phalcon/Db/Profiler/Item.zep +++ b/phalcon/Db/Profiler/Item.zep @@ -53,7 +53,6 @@ class Item */ protected sqlVariables { set, get }; - /** * Returns the total time in seconds spent by the profile */ diff --git a/phalcon/Db/RawValue.zep b/phalcon/Db/RawValue.zep index 76013324b3a..33291041594 100644 --- a/phalcon/Db/RawValue.zep +++ b/phalcon/Db/RawValue.zep @@ -28,7 +28,6 @@ namespace Phalcon\Db; */ class RawValue { - /** * Raw value without quoting or formatting * @@ -41,16 +40,12 @@ class RawValue */ public function __construct(var value) -> void { - if typeof value == "string" && value == "" { + if value === "" { let this->value = "''"; - return; - } - - if value === null { + } elseif value === null { let this->value = "NULL"; - return; + } else { + let this->value = (string) value; } - - let this->value = (string) value; } } diff --git a/phalcon/Db/Reference.zep b/phalcon/Db/Reference.zep index 4c1ee2f37b5..147754d4e4c 100644 --- a/phalcon/Db/Reference.zep +++ b/phalcon/Db/Reference.zep @@ -77,7 +77,6 @@ class Reference implements ReferenceInterface */ protected schemaName { get }; - /** * ON DELETE * @@ -97,32 +96,31 @@ class Reference implements ReferenceInterface */ public function __construct(string! name, array! definition) -> void { - var columns, schema, referencedTable, - referencedSchema, referencedColumns, - onDelete, onUpdate; + var columns, schema, referencedTable, referencedSchema, + referencedColumns, onDelete, onUpdate; let this->name = name; - if fetch referencedTable, definition["referencedTable"] { - let this->referencedTable = referencedTable; - } else { + if !fetch referencedTable, definition["referencedTable"] { throw new Exception("Referenced table is required"); } - if fetch columns, definition["columns"] { - let this->columns = columns; - } else { + let this->referencedTable = referencedTable; + + if !fetch columns, definition["columns"] { throw new Exception("Foreign key columns are required"); } - if fetch referencedColumns, definition["referencedColumns"] { - let this->referencedColumns = referencedColumns; - } else { + let this->columns = columns; + + if !fetch referencedColumns, definition["referencedColumns"] { throw new Exception( "Referenced columns of the foreign key are required" ); } + let this->referencedColumns = referencedColumns; + if fetch schema, definition["schema"] { let this->schemaName = schema; } @@ -168,13 +166,16 @@ class Reference implements ReferenceInterface fetch onDelete, data["onDelete"]; fetch onUpdate, data["onUpdate"]; - return new Reference(constraintName, [ - "referencedSchema" : referencedSchema, - "referencedTable" : referencedTable, - "columns" : columns, - "referencedColumns" : referencedColumns, - "onDelete" : onDelete, - "onUpdate" : onUpdate - ]); + return new Reference( + constraintName, + [ + "referencedSchema": referencedSchema, + "referencedTable": referencedTable, + "columns": columns, + "referencedColumns": referencedColumns, + "onDelete": onDelete, + "onUpdate": onUpdate + ] + ); } } diff --git a/phalcon/Db/Result/Pdo.zep b/phalcon/Db/Result/Pdo.zep index b8ba8a54bcf..77b27f930f8 100644 --- a/phalcon/Db/Result/Pdo.zep +++ b/phalcon/Db/Result/Pdo.zep @@ -72,19 +72,12 @@ class Pdo implements ResultInterface public function __construct( connection, <\PDOStatement> result, sqlStatement = null, bindParams = null, bindTypes = null) -> void { - let this->connection = connection, this->pdoStatement = result; - if sqlStatement !== null { - let this->sqlStatement = sqlStatement; - } - if bindParams !== null { - let this->bindParams = bindParams; - } - if bindTypes !== null { - let this->bindTypes = bindTypes; - } + let this->sqlStatement = sqlStatement; + let this->bindParams = bindParams; + let this->bindTypes = bindTypes; } /** @@ -204,11 +197,7 @@ class Pdo implements ResultInterface ); } - if fetchStyle == Db::FETCH_COLUMN { - return pdoStatement->fetchAll(fetchStyle, fetchArgument); - } - - if fetchStyle == Db::FETCH_FUNC { + if fetchStyle == Db::FETCH_COLUMN || fetchStyle == Db::FETCH_FUNC { return pdoStatement->fetchAll(fetchStyle, fetchArgument); } @@ -351,34 +340,22 @@ class Pdo implements ResultInterface let pdoStatement = this->pdoStatement; - if fetchMode == Db::FETCH_CLASS { - if pdoStatement->setFetchMode(fetchMode, colNoOrClassNameOrObject, ctorargs) { - let this->fetchMode = fetchMode; - return true; + if fetchMode == Db::FETCH_CLASS || fetchMode == Db::FETCH_INTO { + if !pdoStatement->setFetchMode(fetchMode, colNoOrClassNameOrObject, ctorargs) { + return false; } - return false; - } - - if fetchMode == Db::FETCH_INTO { - if pdoStatement->setFetchMode(fetchMode, colNoOrClassNameOrObject) { - let this->fetchMode = fetchMode; - return true; + } elseif fetchMode == Db::FETCH_COLUMN { + if !pdoStatement->setFetchMode(fetchMode, colNoOrClassNameOrObject) { + return false; } - return false; - } - - if fetchMode == Db::FETCH_COLUMN { - if pdoStatement->setFetchMode(fetchMode, colNoOrClassNameOrObject) { - let this->fetchMode = fetchMode; - return true; + } else { + if !pdoStatement->setFetchMode(fetchMode) { + return false; } - return false; } - if pdoStatement->setFetchMode(fetchMode) { - let this->fetchMode = fetchMode; - return true; - } - return false; + let this->fetchMode = fetchMode; + + return true; } } diff --git a/phalcon/Mvc/Model/Relation.zep b/phalcon/Mvc/Model/Relation.zep index 6ab79069be4..fad47679546 100644 --- a/phalcon/Mvc/Model/Relation.zep +++ b/phalcon/Mvc/Model/Relation.zep @@ -184,7 +184,13 @@ class Relation implements RelationInterface */ public function isForeignKey() -> bool { - return isset this->options["foreignKey"]; + var foreignKey; + + if !fetch foreignKey, this->options["foreignKey"] { + return false; + } + + return (bool) foreignKey; } /** diff --git a/phalcon/Mvc/Router/Group.zep b/phalcon/Mvc/Router/Group.zep index fdb3079e558..ba0ded8193c 100644 --- a/phalcon/Mvc/Router/Group.zep +++ b/phalcon/Mvc/Router/Group.zep @@ -92,6 +92,16 @@ class Group implements GroupInterface return this->addRoute(pattern, paths, httpMethods); } + /** + * Adds a route to the router that only match if the HTTP method is CONNECT + * + * @param string|array paths + */ + public function addConnect(string! pattern, var paths = null) -> + { + return this->addRoute(pattern, paths, "CONNECT"); + } + /** * Adds a route to the router that only match if the HTTP method is DELETE * @@ -152,6 +162,16 @@ class Group implements GroupInterface return this->addRoute(pattern, paths, "POST"); } + /** + * Adds a route to the router that only match if the HTTP method is PURGE + * + * @param string|array paths + */ + public function addPurge(string! pattern, var paths = null) -> + { + return this->addRoute(pattern, paths, "PURGE"); + } + /** * Adds a route to the router that only match if the HTTP method is PUT * @@ -162,6 +182,16 @@ class Group implements GroupInterface return this->addRoute(pattern, paths, "PUT"); } + /** + * Adds a route to the router that only match if the HTTP method is TRACE + * + * @param string|array paths + */ + public function addTrace(string! pattern, var paths = null) -> + { + return this->addRoute(pattern, paths, "TRACE"); + } + /** * Sets a callback that is called if the route is matched. * The developer can implement any arbitrary conditions here diff --git a/phalcon/Mvc/Router/GroupInterface.zep b/phalcon/Mvc/Router/GroupInterface.zep index b4898a16229..960e9f83fe0 100644 --- a/phalcon/Mvc/Router/GroupInterface.zep +++ b/phalcon/Mvc/Router/GroupInterface.zep @@ -71,15 +71,20 @@ interface GroupInterface public function add(string! pattern, var paths = null, var httpMethods = null) -> ; /** - * Adds a route to the router that only match if the HTTP method is GET + * Adds a route to the router that only match if the HTTP method is CONNECT */ - public function addGet(string! pattern, var paths = null) -> ; + public function addConnect(string! pattern, var paths = null) -> ; /** * Adds a route to the router that only match if the HTTP method is DELETE */ public function addDelete(string! pattern, var paths = null) -> ; + /** + * Adds a route to the router that only match if the HTTP method is GET + */ + public function addGet(string! pattern, var paths = null) -> ; + /** * Adds a route to the router that only match if the HTTP method is HEAD */ @@ -100,11 +105,21 @@ interface GroupInterface */ public function addPost(string! pattern, var paths = null) -> ; + /** + * Adds a route to the router that only match if the HTTP method is PURGE + */ + public function addPurge(string! pattern, var paths = null) -> ; + /** * Adds a route to the router that only match if the HTTP method is PUT */ public function addPut(string! pattern, var paths = null) -> ; + /** + * Adds a route to the router that only match if the HTTP method is TRACE + */ + public function addTrace(string! pattern, var paths = null) -> ; + /** * Sets a callback that is called if the route is matched. * The developer can implement any arbitrary conditions here diff --git a/tests/integration/Mvc/Model/Relation/IsForeignKeyCest.php b/tests/integration/Mvc/Model/Relation/IsForeignKeyCest.php index 8cda07ef0e0..c2592389891 100644 --- a/tests/integration/Mvc/Model/Relation/IsForeignKeyCest.php +++ b/tests/integration/Mvc/Model/Relation/IsForeignKeyCest.php @@ -13,6 +13,7 @@ namespace Phalcon\Test\Integration\Mvc\Model\Relation; use IntegrationTester; +use Phalcon\Mvc\Model\Relation; /** * Class IsForeignKeyCest @@ -24,12 +25,101 @@ class IsForeignKeyCest * * @param IntegrationTester $I * - * @author Phalcon Team - * @since 2018-11-13 + * @author Sid Roberts + * @since 2019-04-18 */ public function mvcModelRelationIsForeignKey(IntegrationTester $I) { $I->wantToTest('Mvc\Model\Relation - isForeignKey()'); - $I->skipTest('Need implementation'); + + + + $options = []; + + $relation = new Relation( + Relation::HAS_MANY, + 'RobotsParts', + 'id', + 'robots_id', + $options + ); + + $I->assertFalse( + $relation->isForeignKey() + ); + + + + $options = [ + 'foreignKey' => false, + ]; + + $relation = new Relation( + Relation::HAS_MANY, + 'RobotsParts', + 'id', + 'robots_id', + $options + ); + + $I->assertFalse( + $relation->isForeignKey() + ); + + + + $options = [ + 'foreignKey' => [], + ]; + + $relation = new Relation( + Relation::HAS_MANY, + 'RobotsParts', + 'id', + 'robots_id', + $options + ); + + $I->assertFalse( + $relation->isForeignKey() + ); + + + + $options = [ + 'foreignKey' => true, + ]; + + $relation = new Relation( + Relation::HAS_MANY, + 'RobotsParts', + 'id', + 'robots_id', + $options + ); + + $I->assertTrue( + $relation->isForeignKey() + ); + + + + $options = [ + 'foreignKey' => [ + 'message' => 'The part_id does not exist on the Parts model', + ], + ]; + + $relation = new Relation( + Relation::HAS_MANY, + 'RobotsParts', + 'id', + 'robots_id', + $options + ); + + $I->assertTrue( + $relation->isForeignKey() + ); } } diff --git a/tests/integration/Mvc/Router/Group/AddDeleteCest.php b/tests/integration/Mvc/Router/Group/AddDeleteCest.php index c83500aabbf..64f6c68be7b 100644 --- a/tests/integration/Mvc/Router/Group/AddDeleteCest.php +++ b/tests/integration/Mvc/Router/Group/AddDeleteCest.php @@ -13,23 +13,64 @@ namespace Phalcon\Test\Integration\Mvc\Router\Group; use IntegrationTester; +use Phalcon\Mvc\Router; +use Phalcon\Mvc\Router\Group; +use Phalcon\Test\Fixtures\Traits\RouterTrait; /** * Class AddDeleteCest */ class AddDeleteCest { + use RouterTrait; + /** * Tests Phalcon\Mvc\Router\Group :: addDelete() * * @param IntegrationTester $I * - * @author Phalcon Team - * @since 2018-11-13 + * @author Sid Roberts + * @since 2019-04-17 */ public function mvcRouterGroupAddDelete(IntegrationTester $I) { $I->wantToTest('Mvc\Router\Group - addDelete()'); - $I->skipTest('Need implementation'); + + $router = $this->getRouter(false); + + $group = new Group(); + + $group->addDelete( + '/docs/index', + [ + 'controller' => 'documentation6', + 'action' => 'index', + ] + ); + + $router->mount($group); + + + + $_SERVER['REQUEST_METHOD'] = 'DELETE'; + + $router->handle('/docs/index'); + + + + $I->assertEquals( + 'documentation6', + $router->getControllerName() + ); + + $I->assertEquals( + 'index', + $router->getActionName() + ); + + $I->assertEquals( + [], + $router->getParams() + ); } } diff --git a/tests/integration/Mvc/Router/Group/AddGetCest.php b/tests/integration/Mvc/Router/Group/AddGetCest.php index 1d076d23bee..b7f0740c03b 100644 --- a/tests/integration/Mvc/Router/Group/AddGetCest.php +++ b/tests/integration/Mvc/Router/Group/AddGetCest.php @@ -13,23 +13,64 @@ namespace Phalcon\Test\Integration\Mvc\Router\Group; use IntegrationTester; +use Phalcon\Mvc\Router; +use Phalcon\Mvc\Router\Group; +use Phalcon\Test\Fixtures\Traits\RouterTrait; /** * Class AddGetCest */ class AddGetCest { + use RouterTrait; + /** * Tests Phalcon\Mvc\Router\Group :: addGet() * * @param IntegrationTester $I * - * @author Phalcon Team - * @since 2018-11-13 + * @author Sid Roberts + * @since 2019-04-17 */ public function mvcRouterGroupAddGet(IntegrationTester $I) { - $I->wantToTest('Mvc\Router\Group - addGet()'); - $I->skipTest('Need implementation'); + $I->wantToTest('Mvc\Router - addGet()'); + + $router = $this->getRouter(false); + + $group = new Group(); + + $group->addGet( + '/docs/index', + [ + 'controller' => 'documentation4', + 'action' => 'index', + ] + ); + + $router->mount($group); + + + + $_SERVER['REQUEST_METHOD'] = 'GET'; + + $router->handle('/docs/index'); + + + + $I->assertEquals( + 'documentation4', + $router->getControllerName() + ); + + $I->assertEquals( + 'index', + $router->getActionName() + ); + + $I->assertEquals( + [], + $router->getParams() + ); } } diff --git a/tests/integration/Mvc/Router/Group/AddHeadCest.php b/tests/integration/Mvc/Router/Group/AddHeadCest.php index 70346a8b01e..90a01dbfbfd 100644 --- a/tests/integration/Mvc/Router/Group/AddHeadCest.php +++ b/tests/integration/Mvc/Router/Group/AddHeadCest.php @@ -13,23 +13,64 @@ namespace Phalcon\Test\Integration\Mvc\Router\Group; use IntegrationTester; +use Phalcon\Mvc\Router; +use Phalcon\Mvc\Router\Group; +use Phalcon\Test\Fixtures\Traits\RouterTrait; /** * Class AddHeadCest */ class AddHeadCest { + use RouterTrait; + /** * Tests Phalcon\Mvc\Router\Group :: addHead() * * @param IntegrationTester $I * - * @author Phalcon Team - * @since 2018-11-13 + * @author Sid Roberts + * @since 2019-04-17 */ public function mvcRouterGroupAddHead(IntegrationTester $I) { - $I->wantToTest('Mvc\Router\Group - addHead()'); - $I->skipTest('Need implementation'); + $I->wantToTest('Mvc\Router - addHead()'); + + $router = $this->getRouter(false); + + $group = new Group(); + + $group->addHead( + '/docs/index', + [ + 'controller' => 'documentation8', + 'action' => 'index', + ] + ); + + $router->mount($group); + + + + $_SERVER['REQUEST_METHOD'] = 'HEAD'; + + $router->handle('/docs/index'); + + + + $I->assertEquals( + 'documentation8', + $router->getControllerName() + ); + + $I->assertEquals( + 'index', + $router->getActionName() + ); + + $I->assertEquals( + [], + $router->getParams() + ); } } diff --git a/tests/integration/Mvc/Router/Group/AddOptionsCest.php b/tests/integration/Mvc/Router/Group/AddOptionsCest.php index d72af1ae6c7..1144b966a9d 100644 --- a/tests/integration/Mvc/Router/Group/AddOptionsCest.php +++ b/tests/integration/Mvc/Router/Group/AddOptionsCest.php @@ -13,23 +13,64 @@ namespace Phalcon\Test\Integration\Mvc\Router\Group; use IntegrationTester; +use Phalcon\Mvc\Router; +use Phalcon\Mvc\Router\Group; +use Phalcon\Test\Fixtures\Traits\RouterTrait; /** * Class AddOptionsCest */ class AddOptionsCest { + use RouterTrait; + /** * Tests Phalcon\Mvc\Router\Group :: addOptions() * * @param IntegrationTester $I * - * @author Phalcon Team - * @since 2018-11-13 + * @author Sid Roberts + * @since 2019-04-17 */ public function mvcRouterGroupAddOptions(IntegrationTester $I) { - $I->wantToTest('Mvc\Router\Group - addOptions()'); - $I->skipTest('Need implementation'); + $I->wantToTest('Mvc\Router - addOptions()'); + + $router = $this->getRouter(false); + + $group = new Group(); + + $group->addOptions( + '/docs/index', + [ + 'controller' => 'documentation7', + 'action' => 'index', + ] + ); + + $router->mount($group); + + + + $_SERVER['REQUEST_METHOD'] = 'OPTIONS'; + + $router->handle('/docs/index'); + + + + $I->assertEquals( + 'documentation7', + $router->getControllerName() + ); + + $I->assertEquals( + 'index', + $router->getActionName() + ); + + $I->assertEquals( + [], + $router->getParams() + ); } } diff --git a/tests/integration/Mvc/Router/Group/AddPatchCest.php b/tests/integration/Mvc/Router/Group/AddPatchCest.php index 788bacaad7d..3c91a107405 100644 --- a/tests/integration/Mvc/Router/Group/AddPatchCest.php +++ b/tests/integration/Mvc/Router/Group/AddPatchCest.php @@ -13,23 +13,64 @@ namespace Phalcon\Test\Integration\Mvc\Router\Group; use IntegrationTester; +use Phalcon\Mvc\Router; +use Phalcon\Mvc\Router\Group; +use Phalcon\Test\Fixtures\Traits\RouterTrait; /** * Class AddPatchCest */ class AddPatchCest { + use RouterTrait; + /** * Tests Phalcon\Mvc\Router\Group :: addPatch() * * @param IntegrationTester $I * - * @author Phalcon Team - * @since 2018-11-13 + * @author Sid Roberts + * @since 2019-04-17 */ public function mvcRouterGroupAddPatch(IntegrationTester $I) { - $I->wantToTest('Mvc\Router\Group - addPatch()'); - $I->skipTest('Need implementation'); + $I->wantToTest('Mvc\Router - addPatch()'); + + $router = $this->getRouter(false); + + $group = new Group(); + + $group->addPatch( + '/docs/index', + [ + 'controller' => 'documentation4', + 'action' => 'index', + ] + ); + + $router->mount($group); + + + + $_SERVER['REQUEST_METHOD'] = 'PATCH'; + + $router->handle('/docs/index'); + + + + $I->assertEquals( + 'documentation4', + $router->getControllerName() + ); + + $I->assertEquals( + 'index', + $router->getActionName() + ); + + $I->assertEquals( + [], + $router->getParams() + ); } } diff --git a/tests/integration/Mvc/Router/Group/AddPostCest.php b/tests/integration/Mvc/Router/Group/AddPostCest.php index c9dab77dd08..3cadb3968c0 100644 --- a/tests/integration/Mvc/Router/Group/AddPostCest.php +++ b/tests/integration/Mvc/Router/Group/AddPostCest.php @@ -13,23 +13,64 @@ namespace Phalcon\Test\Integration\Mvc\Router\Group; use IntegrationTester; +use Phalcon\Mvc\Router; +use Phalcon\Mvc\Router\Group; +use Phalcon\Test\Fixtures\Traits\RouterTrait; /** * Class AddPostCest */ class AddPostCest { + use RouterTrait; + /** * Tests Phalcon\Mvc\Router\Group :: addPost() * * @param IntegrationTester $I * - * @author Phalcon Team - * @since 2018-11-13 + * @author Sid Roberts + * @since 2019-04-17 */ public function mvcRouterGroupAddPost(IntegrationTester $I) { - $I->wantToTest('Mvc\Router\Group - addPost()'); - $I->skipTest('Need implementation'); + $I->wantToTest('Mvc\Router - addPost()'); + + $router = $this->getRouter(false); + + $group = new Group(); + + $group->addPost( + '/docs/index', + [ + 'controller' => 'documentation3', + 'action' => 'index', + ] + ); + + $router->mount($group); + + + + $_SERVER['REQUEST_METHOD'] = 'POST'; + + $router->handle('/docs/index'); + + + + $I->assertEquals( + 'documentation3', + $router->getControllerName() + ); + + $I->assertEquals( + 'index', + $router->getActionName() + ); + + $I->assertEquals( + [], + $router->getParams() + ); } } diff --git a/tests/integration/Mvc/Router/Group/AddPutCest.php b/tests/integration/Mvc/Router/Group/AddPutCest.php index 7e63f183f43..ada4fcb551b 100644 --- a/tests/integration/Mvc/Router/Group/AddPutCest.php +++ b/tests/integration/Mvc/Router/Group/AddPutCest.php @@ -13,23 +13,64 @@ namespace Phalcon\Test\Integration\Mvc\Router\Group; use IntegrationTester; +use Phalcon\Mvc\Router; +use Phalcon\Mvc\Router\Group; +use Phalcon\Test\Fixtures\Traits\RouterTrait; /** * Class AddPutCest */ class AddPutCest { + use RouterTrait; + /** * Tests Phalcon\Mvc\Router\Group :: addPut() * * @param IntegrationTester $I * - * @author Phalcon Team - * @since 2018-11-13 + * @author Sid Roberts + * @since 2019-04-17 */ public function mvcRouterGroupAddPut(IntegrationTester $I) { - $I->wantToTest('Mvc\Router\Group - addPut()'); - $I->skipTest('Need implementation'); + $I->wantToTest('Mvc\Router - addPut()'); + + $router = $this->getRouter(false); + + $group = new Group(); + + $group->addPut( + '/docs/index', + [ + 'controller' => 'documentation5', + 'action' => 'index', + ] + ); + + $router->mount($group); + + + + $_SERVER['REQUEST_METHOD'] = 'PUT'; + + $router->handle('/docs/index'); + + + + $I->assertEquals( + 'documentation5', + $router->getControllerName() + ); + + $I->assertEquals( + 'index', + $router->getActionName() + ); + + $I->assertEquals( + [], + $router->getParams() + ); } } diff --git a/tests/integration/Mvc/Router/Group/GetPrefixCest.php b/tests/integration/Mvc/Router/Group/GetPrefixCest.php index d998a5acd37..9ac2a6c5075 100644 --- a/tests/integration/Mvc/Router/Group/GetPrefixCest.php +++ b/tests/integration/Mvc/Router/Group/GetPrefixCest.php @@ -13,6 +13,7 @@ namespace Phalcon\Test\Integration\Mvc\Router\Group; use IntegrationTester; +use Phalcon\Mvc\Router\Group; /** * Class GetPrefixCest @@ -24,12 +25,40 @@ class GetPrefixCest * * @param IntegrationTester $I * - * @author Phalcon Team - * @since 2018-11-13 + * @author Sid Roberts + * @since 2019-04-17 + */ + public function mvcRouterGroupGetPrefixEmpty(IntegrationTester $I) + { + $I->wantToTest('Mvc\Router\Group - empty getPrefix()'); + + $group = new Group(); + + $I->assertEquals( + '', + $group->getPrefix() + ); + } + + /** + * Tests Phalcon\Mvc\Router\Group :: getPrefix() when nothing is set + * + * @param IntegrationTester $I + * + * @author Sid Roberts + * @since 2019-04-17 */ public function mvcRouterGroupGetPrefix(IntegrationTester $I) { $I->wantToTest('Mvc\Router\Group - getPrefix()'); - $I->skipTest('Need implementation'); + + $group = new Group(); + + $group->setPrefix('/blog'); + + $I->assertEquals( + '/blog', + $group->getPrefix() + ); } }