diff --git a/CHANGELOG-4.0.md b/CHANGELOG-4.0.md index 426d2be7b55..bfab976ab46 100644 --- a/CHANGELOG-4.0.md +++ b/CHANGELOG-4.0.md @@ -22,6 +22,8 @@ - `Phalcon\Mvc\View\Simple::render()` `params` property is now always an array. - `Phalcon\Mvc\Model\CriteriaInterface::limit()` now takes `offset` as an integer. [#13977](https://github.com/phalcon/cphalcon/pull/13977) - Changed `Phalcon\Mvc\Model\Manager::getModelSource()` to use `setModelSource()` internally instead of setting the source manually [#13987](https://github.com/phalcon/cphalcon/pull/13987) +- The property `options` is always an array in `Phalcon\Mvc\Model\Relation`. [#13989](https://github.com/phalcon/cphalcon/pull/13989) +- `Phalcon\Logger\Adapter\AbstractAdapter::process()` is now actually abstract. [#14012](https://github.com/phalcon/cphalcon/pull/14012) ## Fixed - Fixed `Mvc\Collection::isInitialized()` now works as intended. [#13931](https://github.com/phalcon/cphalcon/pull/13931) @@ -37,6 +39,7 @@ ## Removed - Removed `arrayHelpers` property from the Volt compiler. [#13925](https://github.com/phalcon/cphalcon/pull/13925) - Removed legacy (PHP <5.5) code from GD image adapter. +- Removed support for HTTP_CONTENT_TYPE header (a bug in PHP 5). [#14013](https://github.com/phalcon/cphalcon/pull/14013) # [4.0.0-alpha.4](https://github.com/phalcon/cphalcon/releases/tag/v4.0.0-alpha.4) (2019-03-31) ## Added diff --git a/phalcon/Acl/Adapter.zep b/phalcon/Acl/Adapter.zep index b2cb0617ca4..0c5d1604c4d 100644 --- a/phalcon/Acl/Adapter.zep +++ b/phalcon/Acl/Adapter.zep @@ -29,6 +29,7 @@ abstract class Adapter implements AdapterInterface, EventsAwareInterface /** * Access Granted + * * @var bool */ protected accessGranted = false; @@ -50,6 +51,7 @@ abstract class Adapter implements AdapterInterface, EventsAwareInterface /** * Default access + * * @var bool */ protected defaultAccess = false; diff --git a/phalcon/Acl/Adapter/Memory.zep b/phalcon/Acl/Adapter/Memory.zep index fbaf115a2c2..392683c2d23 100644 --- a/phalcon/Acl/Adapter/Memory.zep +++ b/phalcon/Acl/Adapter/Memory.zep @@ -192,15 +192,17 @@ class Memory extends Adapter * $acl->addRole("administrator", ["consultant", "consultant2"]); * * - * @param array|string accessInherits + * @param array|string accessInherits * @param RoleInterface|string|array role */ public function addInherit(string roleName, var roleToInherits) -> bool { var roleInheritName, rolesNames, roleToInherit, checkRoleToInherit, - checkRoleToInherits, usedRoleToInherits, roleToInheritList, usedRoleToInherit; + checkRoleToInherits, usedRoleToInherits, roleToInheritList, + usedRoleToInherit; let rolesNames = this->rolesNames; + if !isset rolesNames[roleName] { throw new Exception( "Role '" . roleName . "' does not exist in the role list" @@ -210,14 +212,16 @@ class Memory extends Adapter if !isset this->roleInherits[roleName] { let this->roleInherits[roleName] = []; } + /** * Type conversion */ if typeof roleToInherits != "array" { let roleToInheritList = [roleToInherits]; - }else{ + } else { let roleToInheritList = roleToInherits; } + /** * inherits */ @@ -227,12 +231,14 @@ class Memory extends Adapter } else { let roleInheritName = roleToInherit; } + /** * Check if the role to inherit is repeat */ if in_array(roleInheritName, this->roleInherits[roleName]) { continue; } + /** * Check if the role to inherit is valid */ @@ -245,33 +251,40 @@ class Memory extends Adapter if roleName == roleInheritName { return false; } + /** * Deep check if the role to inherit is valid */ if isset this->roleInherits[roleInheritName] { let checkRoleToInherits = []; + for usedRoleToInherit in this->roleInherits[roleInheritName] { - array_push(checkRoleToInherits,usedRoleToInherit); + array_push(checkRoleToInherits, usedRoleToInherit); } + let usedRoleToInherits = []; + while !empty checkRoleToInherits { let checkRoleToInherit = array_shift(checkRoleToInherits); if isset usedRoleToInherits[checkRoleToInherit] { continue; } - let usedRoleToInherits[checkRoleToInherit]=true; + + let usedRoleToInherits[checkRoleToInherit] = true; + if roleName == checkRoleToInherit { throw new Exception( "Role '" . roleInheritName . "' (to inherit) is infinite loop " ); } + /** * Push inherited roles */ if isset this->roleInherits[checkRoleToInherit] { for usedRoleToInherit in this->roleInherits[checkRoleToInherit] { - array_push(checkRoleToInherits,usedRoleToInherit); + array_push(checkRoleToInherits, usedRoleToInherit); } } } @@ -279,6 +292,7 @@ class Memory extends Adapter let this->roleInherits[roleName][] = roleInheritName; } + return true; } @@ -296,7 +310,7 @@ class Memory extends Adapter * $acl->addRole("administrator", ["consultant", "consultant2"]); * * - * @param array|string accessInherits + * @param array|string accessInherits * @param RoleInterface|string|array role */ public function addRole(role, accessInherits = null) -> bool @@ -304,10 +318,8 @@ class Memory extends Adapter var roleName, roleObject; if typeof role == "object" && role instanceof RoleInterface { - let roleName = role->getName(); let roleObject = role; } elseif is_string(role) { - let roleName = role; let roleObject = new Role(role); } else { throw new Exception( @@ -315,6 +327,8 @@ class Memory extends Adapter ); } + let roleName = roleObject->getName(); + if isset this->rolesNames[roleName] { return false; } @@ -364,26 +378,26 @@ class Memory extends Adapter * * * @param Phalcon\Acl\Component|string componentValue - * @param array|string accessList + * @param array|string accessList */ public function addComponent(var componentValue, var accessList) -> bool { var componentName, componentObject; if typeof componentValue == "object" && componentValue instanceof ComponentInterface { - let componentName = componentValue->getName(); let componentObject = componentValue; - } else { - let componentName = componentValue; - let componentObject = new Component(componentName); - } + } else { + let componentObject = new Component(componentValue); + } - if !isset this->componentsNames[componentName] { + let componentName = componentObject->getName(); + + if !isset this->componentsNames[componentName] { let this->components[] = componentObject; let this->componentsNames[componentName] = true; - } + } - return this->addComponentAccess(componentName, accessList); + return this->addComponentAccess(componentName, accessList); } /** @@ -393,7 +407,9 @@ class Memory extends Adapter */ public function addComponentAccess(string componentName, var accessList) -> bool { - var accessName, accessKey, exists; + var accessName; + string accessKey; + bool exists; if !isset this->componentsNames[componentName] { throw new Exception( @@ -406,15 +422,18 @@ class Memory extends Adapter } let exists = true; + if typeof accessList == "array" { for accessName in accessList { let accessKey = componentName . "!" . accessName; + if !isset this->accessList[accessKey] { let this->accessList[accessKey] = exists; } } } else { let accessKey = componentName . "!" . accessList; + if !isset this->accessList[accessKey] { let this->accessList[accessKey] = exists; } @@ -523,6 +542,7 @@ class Memory extends Adapter if typeof accessList == "array" { for accessName in accessList { let accessKey = componentName . "!" . accessName; + if isset this->accessList[accessKey] { unset this->accessList[accessKey]; } @@ -625,6 +645,7 @@ class Memory extends Adapter * Check if the role exists */ let rolesNames = this->rolesNames; + if !isset rolesNames[roleName] { return (this->defaultAccess == Acl::ALLOW); } @@ -636,6 +657,7 @@ class Memory extends Adapter if accessKey != false && isset accessList[accessKey] { let haveAccess = accessList[accessKey]; + fetch funcAccess, funcList[accessKey]; } @@ -643,6 +665,7 @@ class Memory extends Adapter * Check in the inherits roles */ let this->accessGranted = haveAccess; + if typeof eventsManager == "object" { eventsManager->fire("acl:afterCheckAccess", this); } @@ -814,9 +837,9 @@ class Memory extends Adapter let accessList = this->accessList; if typeof access == "array" { - for accessName in access { let accessKey = componentName . "!" . accessName; + if !isset accessList[accessKey] { throw new Exception( "Access '" . accessName . "' does not exist in component '" . componentName . "'" @@ -825,18 +848,17 @@ class Memory extends Adapter } for accessName in access { - let accessKey = roleName . "!" .componentName . "!" . accessName; let this->access[accessKey] = action; + if func != null { let this->func[accessKey] = func; } } - } else { - if access != "*" { let accessKey = componentName . "!" . access; + if !isset accessList[accessKey] { throw new Exception( "Access '" . access . "' does not exist in component '" . componentName . "'" @@ -850,6 +872,7 @@ class Memory extends Adapter * Define the access action for the specified accessKey */ let this->access[accessKey] = action; + if func != null { let this->func[accessKey] = func; } @@ -861,9 +884,8 @@ class Memory extends Adapter */ private function canAccess(string roleName, string componentName, string access) -> string | bool { - var accessList, accessKey,checkRoleToInherit, - checkRoleToInherits, usedRoleToInherits, - usedRoleToInherit; + var accessList, accessKey,checkRoleToInherit, checkRoleToInherits, + usedRoleToInherits, usedRoleToInherit; let accessList = this->access; @@ -875,38 +897,48 @@ class Memory extends Adapter if isset accessList[accessKey] { return accessKey; } + /** * Check if there is a direct combination for role-*-* */ let accessKey = roleName . "!" . componentName . "!*"; + if isset accessList[accessKey] { return accessKey; } + /** * Check if there is a direct combination for role-*-* */ let accessKey = roleName . "!*!*"; + if isset accessList[accessKey] { return accessKey; } + /** * Deep check if the role to inherit is valid */ if isset this->roleInherits[roleName] { let checkRoleToInherits = []; + for usedRoleToInherit in this->roleInherits[roleName] { - array_push(checkRoleToInherits,usedRoleToInherit); + array_push(checkRoleToInherits, usedRoleToInherit); } + let usedRoleToInherits = []; + while !empty checkRoleToInherits { let checkRoleToInherit = array_shift(checkRoleToInherits); if isset usedRoleToInherits[checkRoleToInherit] { continue; } - let usedRoleToInherits[checkRoleToInherit]=true; + + let usedRoleToInherits[checkRoleToInherit] = true; let accessKey = checkRoleToInherit . "!" . componentName . "!" . access; + /** * Check if there is a direct combination in one of the * inherited roles @@ -914,30 +946,36 @@ class Memory extends Adapter if isset accessList[accessKey] { return accessKey; } + /** * Check if there is a direct combination for role-*-* */ let accessKey = checkRoleToInherit . "!" . componentName . "!*"; + if isset accessList[accessKey] { return accessKey; } + /** * Check if there is a direct combination for role-*-* */ let accessKey = checkRoleToInherit . "!*!*"; + if isset accessList[accessKey] { return accessKey; } + /** * Push inherited roles */ if isset this->roleInherits[checkRoleToInherit] { for usedRoleToInherit in this->roleInherits[checkRoleToInherit] { - array_push(checkRoleToInherits,usedRoleToInherit); + array_push(checkRoleToInherits, usedRoleToInherit); } } } } + return false; } } diff --git a/phalcon/Acl/AdapterInterface.zep b/phalcon/Acl/AdapterInterface.zep index e1565bdf775..2b53a837071 100644 --- a/phalcon/Acl/AdapterInterface.zep +++ b/phalcon/Acl/AdapterInterface.zep @@ -80,7 +80,7 @@ interface AdapterInterface /** * Returns the default ACL access level for no arguments provided in - *isAllowed action if there exists func for accessKey + * isAllowed action if there exists func for accessKey */ public function getNoArgumentsDefaultAction() -> int; diff --git a/phalcon/Acl/Component.zep b/phalcon/Acl/Component.zep index bd90c55f11b..2bb740eb6c8 100644 --- a/phalcon/Acl/Component.zep +++ b/phalcon/Acl/Component.zep @@ -19,15 +19,16 @@ use Phalcon\Acl\Exception; */ class Component implements ComponentInterface { - /** * Component description + * * @var string */ private description { get }; /** * Component name + * * @var string */ private name { get, __toString }; @@ -41,9 +42,7 @@ class Component implements ComponentInterface throw new Exception("Component name cannot be '*'"); } - let this->name = name; - if description { - let this->description = description; - } + let this->name = name, + this->description = description; } } diff --git a/phalcon/Acl/ComponentAware.zep b/phalcon/Acl/ComponentAware.zep index ed552efd6db..259cb16e8f1 100644 --- a/phalcon/Acl/ComponentAware.zep +++ b/phalcon/Acl/ComponentAware.zep @@ -19,6 +19,6 @@ interface ComponentAware { /** * Returns component name - */ + */ public function getComponentName() -> string; } diff --git a/phalcon/Acl/Role.zep b/phalcon/Acl/Role.zep index 32497648ddf..562103f9626 100644 --- a/phalcon/Acl/Role.zep +++ b/phalcon/Acl/Role.zep @@ -21,12 +21,14 @@ class Role implements RoleInterface { /** * Role name + * * @var string */ private name { get, __toString }; /** * Role description + * * @var string */ private description { get }; @@ -39,10 +41,8 @@ class Role implements RoleInterface if name == "*" { throw new Exception("Role name cannot be '*'"); } - let this->name = name; - if description { - let this->description = description; - } + let this->name = name, + this->description = description; } } diff --git a/phalcon/Acl/RoleAware.zep b/phalcon/Acl/RoleAware.zep index 5a5627bc7c8..37c189eb385 100644 --- a/phalcon/Acl/RoleAware.zep +++ b/phalcon/Acl/RoleAware.zep @@ -19,6 +19,6 @@ interface RoleAware { /** * Returns role name - */ + */ public function getRoleName() -> string; } diff --git a/phalcon/Acl/RoleInterface.zep b/phalcon/Acl/RoleInterface.zep index 09a042f1b64..aec68f6c3b5 100644 --- a/phalcon/Acl/RoleInterface.zep +++ b/phalcon/Acl/RoleInterface.zep @@ -31,5 +31,4 @@ interface RoleInterface * Magic method __toString */ public function __toString() -> string; - } diff --git a/phalcon/Annotations/Adapter.zep b/phalcon/Annotations/Adapter.zep index 30c428361db..b7e9ccb6ed7 100644 --- a/phalcon/Annotations/Adapter.zep +++ b/phalcon/Annotations/Adapter.zep @@ -62,7 +62,6 @@ abstract class Adapter implements AdapterInterface let reader = this->getReader(), parsedAnnotations = reader->parse(realClassName); - let classAnnotations = new Reflection(parsedAnnotations), this->annotations[realClassName] = classAnnotations; this->{"write"}(realClassName, classAnnotations); diff --git a/phalcon/Annotations/Adapter/Memory.zep b/phalcon/Annotations/Adapter/Memory.zep index 98622921c82..0975d5f5af7 100644 --- a/phalcon/Annotations/Adapter/Memory.zep +++ b/phalcon/Annotations/Adapter/Memory.zep @@ -34,11 +34,11 @@ class Memory extends Adapter { var data; - if fetch data, this->data[strtolower(key)] { - return data; + if !fetch data, this->data[strtolower(key)] { + return false; } - return false; + return data; } /** diff --git a/phalcon/Annotations/Annotation.zep b/phalcon/Annotations/Annotation.zep index e45d5230512..59be88e3c74 100644 --- a/phalcon/Annotations/Annotation.zep +++ b/phalcon/Annotations/Annotation.zep @@ -77,6 +77,7 @@ class Annotation * Returns an argument in a specific position * * @param int|string position + * * @return mixed */ public function getArgument(var position) @@ -106,8 +107,6 @@ class Annotation /** * Resolves an annotation expression - * - * @return mixed */ public function getExpression(array! expr) -> var { @@ -186,8 +185,6 @@ class Annotation /** * Returns a named parameter - * - * @return mixed */ public function getNamedParameter(string! name) -> var { diff --git a/phalcon/Annotations/Collection.zep b/phalcon/Annotations/Collection.zep index 5f2576affbc..c55d08a22cc 100644 --- a/phalcon/Annotations/Collection.zep +++ b/phalcon/Annotations/Collection.zep @@ -20,15 +20,15 @@ use Phalcon\Annotations\Exception; * of annotations easily * * - * //Traverse annotations + * // Traverse annotations * foreach ($classAnnotations as $annotation) { * echo "Name=", $annotation->getName(), PHP_EOL; * } * - * //Check if the annotations has a specific + * // Check if the annotations has a specific * var_dump($classAnnotations->has("Cacheable")); * - * //Get an specific annotation in the collection + * // Get an specific annotation in the collection * $annotation = $classAnnotations->get("Cacheable"); * */ @@ -44,11 +44,8 @@ class Collection implements \Iterator, \Countable */ protected position = 0; - /** * Phalcon\Annotations\Collection constructor - * - * @param array reflectionData */ public function __construct(array reflectionData = []) -> void { @@ -78,11 +75,11 @@ class Collection implements \Iterator, \Countable { var annotation; - if fetch annotation, this->annotations[this->position] { - return annotation; + if !fetch annotation, this->annotations[this->position] { + return false; } - return false; + return annotation; } /** @@ -149,6 +146,7 @@ class Collection implements \Iterator, \Countable return false; } + /** * Returns the current position/key in the iterator */ diff --git a/phalcon/Annotations/Factory.zep b/phalcon/Annotations/Factory.zep index 49ef0230398..27bb5c3be64 100644 --- a/phalcon/Annotations/Factory.zep +++ b/phalcon/Annotations/Factory.zep @@ -23,6 +23,7 @@ use Phalcon\Factory as BaseFactory; * "lifetime" => "3600", * "adapter" => "apc", * ]; + * * $annotations = Factory::load($options); * */ diff --git a/phalcon/Annotations/Reader.zep b/phalcon/Annotations/Reader.zep index 9fe685494f0..c3a414f4608 100644 --- a/phalcon/Annotations/Reader.zep +++ b/phalcon/Annotations/Reader.zep @@ -19,7 +19,6 @@ use Phalcon\Annotations\ReaderInterface; */ class Reader implements ReaderInterface { - /** * Reads annotations from the class docblocks, its methods and/or properties */ @@ -88,7 +87,6 @@ class Reader implements ReaderInterface if typeof propertyAnnotations == "array" { let annotationsProperties[property->name] = propertyAnnotations; } - } } @@ -130,7 +128,6 @@ class Reader implements ReaderInterface if count(annotationsMethods) { let annotations["methods"] = annotationsMethods; } - } return annotations; diff --git a/phalcon/Annotations/ReaderInterface.zep b/phalcon/Annotations/ReaderInterface.zep index add4a736931..d0ec7df14fc 100644 --- a/phalcon/Annotations/ReaderInterface.zep +++ b/phalcon/Annotations/ReaderInterface.zep @@ -17,10 +17,8 @@ namespace Phalcon\Annotations; */ interface ReaderInterface { - /** - * Reads annotations from the class docblocks, its methods and/or - * properties + * Reads annotations from the class docblocks, its methods and/or properties */ public function parse(string className) -> array; diff --git a/phalcon/Application.zep b/phalcon/Application.zep index bc2f64c84bb..46a0559f1a7 100644 --- a/phalcon/Application.zep +++ b/phalcon/Application.zep @@ -127,6 +127,7 @@ abstract class Application extends Injectable implements EventsAwareInterface public function setDefaultModule(string! defaultModule) -> { let this->defaultModule = defaultModule; + return this; } diff --git a/phalcon/Assets/Asset.zep b/phalcon/Assets/Asset.zep index dad95357a29..6f43ff20b8d 100644 --- a/phalcon/Assets/Asset.zep +++ b/phalcon/Assets/Asset.zep @@ -85,6 +85,7 @@ class Asset implements AssetInterface public function setType(string type) -> { let this->type = type; + return this; } @@ -94,6 +95,7 @@ class Asset implements AssetInterface public function setPath(string path) -> { let this->path = path; + return this; } @@ -103,6 +105,7 @@ class Asset implements AssetInterface public function setLocal(bool local) -> { let this->local = local; + return this; } @@ -112,6 +115,7 @@ class Asset implements AssetInterface public function setFilter(bool filter) -> { let this->filter = filter; + return this; } @@ -121,6 +125,7 @@ class Asset implements AssetInterface public function setAttributes(array attributes) -> { let this->attributes = attributes; + return this; } @@ -130,6 +135,7 @@ class Asset implements AssetInterface public function setTargetUri(string targetUri) -> { let this->targetUri = targetUri; + return this; } @@ -139,6 +145,7 @@ class Asset implements AssetInterface public function setSourcePath(string sourcePath) -> { let this->sourcePath = sourcePath; + return this; } @@ -148,6 +155,7 @@ class Asset implements AssetInterface public function setTargetPath(string targetPath) -> { let this->targetPath = targetPath; + return this; } @@ -206,9 +214,11 @@ class Asset implements AssetInterface var targetUri; let targetUri = this->targetUri; + if empty targetUri { let targetUri = this->path; } + return targetUri; } @@ -247,7 +257,6 @@ class Asset implements AssetInterface } if this->local { - /** * A base path for assets can be set in the assets manager */ diff --git a/phalcon/Assets/Collection.zep b/phalcon/Assets/Collection.zep index 574efecbe06..9f83a60e52f 100644 --- a/phalcon/Assets/Collection.zep +++ b/phalcon/Assets/Collection.zep @@ -84,7 +84,6 @@ class Collection implements \Countable, \Iterator */ protected targetUri { get }; - /** * Phalcon\Assets\Collection constructor */ @@ -135,6 +134,7 @@ class Collection implements \Countable, \Iterator public function addFilter( filter) -> { let this->filters[] = filter; + return this; } @@ -266,7 +266,9 @@ class Collection implements \Countable, \Iterator * use Phalcon\Assets\Collection; * * $collection = new Collection(); + * * $asset = new Asset("js", "js/jquery.js"); + * * $collection->add($asset); * $collection->has($asset); // true * @@ -288,6 +290,7 @@ class Collection implements \Countable, \Iterator public function join(bool join) -> { let this->join = join; + return this; } @@ -321,6 +324,7 @@ class Collection implements \Countable, \Iterator public function setAttributes(array! attributes) -> { let this->attributes = attributes; + return this; } @@ -330,6 +334,7 @@ class Collection implements \Countable, \Iterator public function setFilters(array! filters) -> { let this->filters = filters; + return this; } @@ -339,6 +344,7 @@ class Collection implements \Countable, \Iterator public function setLocal(bool! local) -> { let this->local = local; + return this; } @@ -348,6 +354,7 @@ class Collection implements \Countable, \Iterator public function setPrefix(string! prefix) -> { let this->prefix = prefix; + return this; } @@ -357,6 +364,7 @@ class Collection implements \Countable, \Iterator public function setTargetLocal(bool! targetLocal) -> { let this->targetLocal = targetLocal; + return this; } @@ -366,6 +374,7 @@ class Collection implements \Countable, \Iterator public function setTargetPath(string! targetPath) -> { let this->targetPath = targetPath; + return this; } @@ -375,6 +384,7 @@ class Collection implements \Countable, \Iterator public function setTargetUri(string! targetUri) -> { let this->targetUri = targetUri; + return this; } @@ -384,6 +394,7 @@ class Collection implements \Countable, \Iterator public function setSourcePath(string! sourcePath) -> { let this->sourcePath = sourcePath; + return this; } @@ -400,18 +411,18 @@ class Collection implements \Countable, \Iterator */ final protected function addAsset( asset) -> bool { - if !this->has(asset) { - if asset instanceof Asset { - let this->assets[] = asset; - } else { - let this->codes[] = asset; - } - - let this->includedAssets[] = asset->getAssetKey(); + if this->has(asset) { + return false; + } - return true; + if asset instanceof Asset { + let this->assets[] = asset; + } else { + let this->codes[] = asset; } - return false; + let this->includedAssets[] = asset->getAssetKey(); + + return true; } } diff --git a/phalcon/Assets/Exception.zep b/phalcon/Assets/Exception.zep index 7e09a543e7e..18d6984df2c 100644 --- a/phalcon/Assets/Exception.zep +++ b/phalcon/Assets/Exception.zep @@ -14,7 +14,6 @@ namespace Phalcon\Assets; * Phalcon\Assets\Exception * * Exceptions thrown in Phalcon\Assets will use this class - * */ class Exception extends \Phalcon\Exception { diff --git a/phalcon/Assets/FilterInterface.zep b/phalcon/Assets/FilterInterface.zep index c6567922e07..0dead65ab72 100644 --- a/phalcon/Assets/FilterInterface.zep +++ b/phalcon/Assets/FilterInterface.zep @@ -17,7 +17,6 @@ namespace Phalcon\Assets; */ interface FilterInterface { - /** * Filters the content returning a string with the filtered content */ diff --git a/phalcon/Assets/Inline.zep b/phalcon/Assets/Inline.zep index 87469494ff7..0e00382e370 100644 --- a/phalcon/Assets/Inline.zep +++ b/phalcon/Assets/Inline.zep @@ -67,6 +67,7 @@ class $Inline implements AssetInterface public function setAttributes(array attributes) -> { let this->attributes = attributes; + return this; } @@ -76,6 +77,7 @@ class $Inline implements AssetInterface public function setFilter(bool filter) -> { let this->filter = filter; + return this; } @@ -85,6 +87,7 @@ class $Inline implements AssetInterface public function setType(string type) -> { let this->type = type; + return this; } } diff --git a/phalcon/Assets/Inline/Css.zep b/phalcon/Assets/Inline/Css.zep index b3b23dcbc4f..9bc2bf433dd 100644 --- a/phalcon/Assets/Inline/Css.zep +++ b/phalcon/Assets/Inline/Css.zep @@ -27,7 +27,9 @@ class Css extends InlineBase public function __construct(string content, bool filter = true, attributes = null) -> void { if attributes == null { - let attributes = ["type": "text/css"]; + let attributes = [ + "type": "text/css" + ]; } parent::__construct("css", content, filter, attributes); diff --git a/phalcon/Assets/Inline/Js.zep b/phalcon/Assets/Inline/Js.zep index b3641173e43..f8d3d88f3b4 100644 --- a/phalcon/Assets/Inline/Js.zep +++ b/phalcon/Assets/Inline/Js.zep @@ -15,7 +15,7 @@ use Phalcon\Assets\Inline as InlineBase; /** * Phalcon\Assets\Inline\Js * - * Represents an inline Javascript + * Represents an inline JavaScript */ class Js extends InlineBase { @@ -27,7 +27,9 @@ class Js extends InlineBase public function __construct(string content, bool filter = true, var attributes = null) -> void { if attributes == null { - let attributes = ["type": "text/javascript"]; + let attributes = [ + "type": "text/javascript" + ]; } parent::__construct("js", content, filter, attributes); diff --git a/phalcon/Assets/Manager.zep b/phalcon/Assets/Manager.zep index 410a938c702..873f9606616 100644 --- a/phalcon/Assets/Manager.zep +++ b/phalcon/Assets/Manager.zep @@ -55,7 +55,7 @@ class Manager implements InjectionAwareInterface * Adds a raw asset to the manager * * - * assets->addAsset( + * $assets->addAsset( * new Phalcon\Assets\Asset("css", "css/style.css") * ); * @@ -65,7 +65,11 @@ class Manager implements InjectionAwareInterface /** * Adds the asset by its type */ - this->addAssetByType(asset->getType(), asset); + this->addAssetByType( + asset->getType(), + asset + ); + return this; } @@ -73,7 +77,8 @@ class Manager implements InjectionAwareInterface * Adds a asset by its type * * - * assets->addAssetByType("css", + * $assets->addAssetByType( + * "css", * new \Phalcon\Assets\Asset\Css("css/style.css") * ); * @@ -99,8 +104,8 @@ class Manager implements InjectionAwareInterface * Adds a Css asset to the 'css' collection * * - * assets->addCss("css/bootstrap.css"); - * assets->addCss("http://bootstrap.my-cdn.com/style.css", false); + * $assets->addCss("css/bootstrap.css"); + * $assets->addCss("http://bootstrap.my-cdn.com/style.css", false); * */ public function addCss(string! path, local = true, filter = true, var attributes = null) -> @@ -122,6 +127,7 @@ class Manager implements InjectionAwareInterface * Adds the inline code by its type */ this->addInlineCodeByType(code->getType(), code); + return this; } @@ -175,8 +181,8 @@ class Manager implements InjectionAwareInterface * Adds a javascript asset to the 'js' collection * * - * assets->addJs("scripts/jquery.js"); - * assets->addJs("http://jquery.my-cdn.com/jquery.js", false); + * $assets->addJs("scripts/jquery.js"); + * $assets->addJs("http://jquery.my-cdn.com/jquery.js", false); * */ public function addJs(string! path, local = true, filter = true, attributes = null) -> @@ -210,6 +216,7 @@ class Manager implements InjectionAwareInterface public function collectionAssetsByType(array assets, string type) -> array { var $filtered = [], asset; + for asset in assets { if asset->getType() == type { let $filtered[] = asset; @@ -223,9 +230,9 @@ class Manager implements InjectionAwareInterface * Returns true or false if collection exists. * * - * if (assets->exists("jsHeader")) { + * if ($assets->exists("jsHeader")) { * // \Phalcon\Assets\Collection - * $collection = assets->get("jsHeader"); + * $collection = $assets->get("jsHeader"); * } * */ @@ -238,7 +245,7 @@ class Manager implements InjectionAwareInterface * Returns a collection by its id. * * - * $scripts = assets->get("js"); + * $scripts = $assets->get("js"); * */ public function get(string! id) -> @@ -758,8 +765,10 @@ class Manager implements InjectionAwareInterface let callback = ["Phalcon\\Tag", "stylesheetLink"]; let container = this->container; + if typeof container == "object" && container->has("tag") { let tag = container->getShared("tag"); + let callback = [tag, "stylesheetLink"]; } @@ -888,12 +897,13 @@ class Manager implements InjectionAwareInterface * Sets a collection in the Assets Manager * * - * assets->set("js", $collection); + * $assets->set("js", $collection); * */ public function set(string! id, collection) -> { let this->collections[id] = collection; + return this; } @@ -911,6 +921,7 @@ class Manager implements InjectionAwareInterface public function setOptions(array! options) -> { let this->options = options; + return this; } @@ -920,6 +931,7 @@ class Manager implements InjectionAwareInterface public function useImplicitOutput(bool implicitOutput) -> { let this->implicitOutput = implicitOutput; + return this; } } diff --git a/phalcon/Cli/Console.zep b/phalcon/Cli/Console.zep index b842c7a10fe..a12ec060115 100644 --- a/phalcon/Cli/Console.zep +++ b/phalcon/Cli/Console.zep @@ -32,9 +32,8 @@ class Console extends BaseApplication */ public function handle(array arguments = null) { - var container, router, eventsManager, - moduleName, modules, module, path, className, - moduleObject, dispatcher, task; + var container, router, eventsManager, moduleName, modules, module, path, + className, moduleObject, dispatcher, task; let container = this->container; if typeof container != "object" { @@ -188,12 +187,15 @@ class Console extends BaseApplication if count(args) { let handleArgs["task"] = array_shift(args); } + if count(args) { let handleArgs["action"] = array_shift(args); } + if count(args) { let handleArgs = array_merge(handleArgs, args); } + let this->arguments = handleArgs; } diff --git a/phalcon/Cli/Console/Exception.zep b/phalcon/Cli/Console/Exception.zep index 632ea685ba5..6bf673a9c19 100644 --- a/phalcon/Cli/Console/Exception.zep +++ b/phalcon/Cli/Console/Exception.zep @@ -14,7 +14,6 @@ namespace Phalcon\Cli\Console; * Phalcon\Cli\Console\Exception * * Exceptions thrown in Phalcon\Cli\Console will use this class - * */ class Exception extends \Phalcon\Application\Exception { diff --git a/phalcon/Cli/Dispatcher.zep b/phalcon/Cli/Dispatcher.zep index f121fef2f6c..c697dd1e556 100644 --- a/phalcon/Cli/Dispatcher.zep +++ b/phalcon/Cli/Dispatcher.zep @@ -194,7 +194,9 @@ class Dispatcher extends CliDispatcher implements DispatcherInterface protected function handleException(<\Exception> exception) { var eventsManager; + let eventsManager = this->eventsManager; + if typeof eventsManager == "object" { if eventsManager->fire("dispatch:beforeException", this, exception) === false { return false; diff --git a/phalcon/Cli/Router.zep b/phalcon/Cli/Router.zep index 000563e830b..c3072a5c280 100644 --- a/phalcon/Cli/Router.zep +++ b/phalcon/Cli/Router.zep @@ -93,7 +93,7 @@ class Router implements \Phalcon\Di\InjectionAwareInterface let routes[] = new Route( "#^(?::delimiter)?([a-zA-Z0-9\\_\\-]+):delimiter([a-zA-Z0-9\\.\\_]+)(:delimiter.*)*$#", [ - "task": 1, + "task": 1, "action": 2, "params": 3 ] @@ -118,6 +118,7 @@ class Router implements \Phalcon\Di\InjectionAwareInterface let route = new Route(pattern, paths), this->routes[] = route; + return route; } @@ -183,6 +184,7 @@ class Router implements \Phalcon\Di\InjectionAwareInterface return route; } } + return false; } @@ -198,6 +200,7 @@ class Router implements \Phalcon\Di\InjectionAwareInterface return route; } } + return false; } @@ -224,10 +227,9 @@ class Router implements \Phalcon\Di\InjectionAwareInterface */ public function handle(arguments = null) { - var moduleName, taskName, actionName, - params, route, parts, pattern, routeFound, matches, paths, - beforeMatch, converters, converter, part, position, matchPosition, - strParams; + var moduleName, taskName, actionName, params, route, parts, pattern, + routeFound, matches, paths, beforeMatch, converters, converter, + part, position, matchPosition, strParams; let routeFound = false, parts = [], @@ -348,6 +350,7 @@ class Router implements \Phalcon\Di\InjectionAwareInterface } let this->matchedRoute = route; + break; } } @@ -368,6 +371,7 @@ class Router implements \Phalcon\Di\InjectionAwareInterface this->task = this->defaultTask, this->action = this->defaultAction, this->params = this->defaultParams; + return this; } } else { @@ -417,8 +421,10 @@ class Router implements \Phalcon\Di\InjectionAwareInterface let params = []; } } + unset parts["params"]; } + if count(params) { let params = array_merge(params, parts); } else { diff --git a/phalcon/Cli/Router/Exception.zep b/phalcon/Cli/Router/Exception.zep index 663721ab6f9..3493d0d28fc 100644 --- a/phalcon/Cli/Router/Exception.zep +++ b/phalcon/Cli/Router/Exception.zep @@ -14,7 +14,6 @@ namespace Phalcon\Cli\Router; * Phalcon\Cli\Router\Exception * * Exceptions thrown in Phalcon\Cli\Router will use this class - * */ class Exception extends \Phalcon\Exception { diff --git a/phalcon/Cli/Router/Route.zep b/phalcon/Cli/Router/Route.zep index 412cdb6f50a..315e4caf4d0 100644 --- a/phalcon/Cli/Router/Route.zep +++ b/phalcon/Cli/Router/Route.zep @@ -78,6 +78,7 @@ class Route public function beforeMatch(var callback) -> { let this->beforeMatch = callback; + return this; } @@ -174,6 +175,7 @@ class Route public function convert(string! name, converter) -> { let this->converters[name] = converter; + return this; } @@ -289,6 +291,7 @@ class Route route .= item, route .= '}'; } + continue; } } @@ -391,9 +394,11 @@ class Route var reversed, path, position; let reversed = []; + for path, position in this->paths { let reversed[position] = path; } + return reversed; } @@ -559,6 +564,7 @@ class Route public function setDescription(string! description) -> { let this->description = description; + return this; } @@ -577,6 +583,7 @@ class Route public function setName(string! name) -> { let this->name = name; + return this; } } diff --git a/phalcon/Cli/RouterInterface.zep b/phalcon/Cli/RouterInterface.zep index b841584e815..8d4db5ba122 100644 --- a/phalcon/Cli/RouterInterface.zep +++ b/phalcon/Cli/RouterInterface.zep @@ -81,7 +81,6 @@ interface RouterInterface */ public function setDefaultAction(string! actionName) -> void; - /** * Sets the name of the default module */ diff --git a/phalcon/Collection.zep b/phalcon/Collection.zep index 75c95174809..349946c7142 100644 --- a/phalcon/Collection.zep +++ b/phalcon/Collection.zep @@ -203,7 +203,6 @@ class Collection implements \ArrayAccess, \Countable, \IteratorAggregate, \JsonS { var data, lowerKeys, value; - let data = this->data, lowerKeys = this->lowerKeys; diff --git a/phalcon/Config.zep b/phalcon/Config.zep index ddf035c97f5..e8b34687091 100644 --- a/phalcon/Config.zep +++ b/phalcon/Config.zep @@ -80,7 +80,9 @@ class Config implements \ArrayAccess, \Countable */ public function count() -> int { - return count(get_object_vars(this)); + return count( + get_object_vars(this) + ); } /** @@ -96,11 +98,11 @@ class Config implements \ArrayAccess, \Countable { let index = strval(index); - if isset this->{index} { - return this->{index}; + if !isset this->{index} { + return defaultValue; } - return defaultValue; + return this->{index}; } /** @@ -111,6 +113,7 @@ class Config implements \ArrayAccess, \Countable var delimiter; let delimiter = self::pathDelimiter; + if !delimiter { let delimiter = self::DEFAULT_PATH_DELIMITER; } @@ -310,8 +313,8 @@ class Config implements \ArrayAccess, \Countable let number = instance->count(); for key, value in get_object_vars(config) { - let property = strval(key); + if fetch localObject, instance->{property} { if typeof localObject === "object" && typeof value === "object" { if localObject instanceof Config && value instanceof Config { @@ -323,6 +326,7 @@ class Config implements \ArrayAccess, \Countable if is_numeric(key) { let key = strval(key); + while instance->offsetExists(key) { /** * Increment the number afterwards, because "number" starts @@ -331,7 +335,8 @@ class Config implements \ArrayAccess, \Countable let key = strval(number); let number++; } - } + } + let instance->{key} = value; } diff --git a/phalcon/Config/Adapter/Grouped.zep b/phalcon/Config/Adapter/Grouped.zep index 650e267f80d..7083761c2b0 100644 --- a/phalcon/Config/Adapter/Grouped.zep +++ b/phalcon/Config/Adapter/Grouped.zep @@ -84,11 +84,17 @@ class Grouped extends Config // Set to default adapter if passed as string if typeof configName === "string" { if defaultAdapter === "" { - this->internalMerge(Factory::load(configName)); + this->internalMerge( + Factory::load(configName) + ); + continue; } - let configInstance = ["filePath" : configName, "adapter" : defaultAdapter]; + let configInstance = [ + "filePath": configName, + "adapter": defaultAdapter + ]; } elseif !isset configInstance["adapter"] { let configInstance["adapter"] = defaultAdapter; } diff --git a/phalcon/Config/Adapter/Ini.zep b/phalcon/Config/Adapter/Ini.zep index 7602baed598..fe6bd76da10 100644 --- a/phalcon/Config/Adapter/Ini.zep +++ b/phalcon/Config/Adapter/Ini.zep @@ -167,6 +167,7 @@ class Ini extends Config protected function parseIniString(string! path, var value) -> array { var pos, key; + let value = this->cast(value); let pos = strpos(path, "."); @@ -183,5 +184,4 @@ class Ini extends Config key: this->parseIniString(path, value) ]; } - } diff --git a/phalcon/Config/Adapter/Json.zep b/phalcon/Config/Adapter/Json.zep index 9b5fb47ff88..197da7a7554 100644 --- a/phalcon/Config/Adapter/Json.zep +++ b/phalcon/Config/Adapter/Json.zep @@ -39,6 +39,11 @@ class Json extends Config */ public function __construct(string! filePath) -> void { - parent::__construct(json_decode(file_get_contents(filePath), true)); + parent::__construct( + json_decode( + file_get_contents(filePath), + true + ) + ); } } diff --git a/phalcon/Config/Adapter/Php.zep b/phalcon/Config/Adapter/Php.zep index 44f73f7513c..73c3f8b5ef7 100644 --- a/phalcon/Config/Adapter/Php.zep +++ b/phalcon/Config/Adapter/Php.zep @@ -20,7 +20,7 @@ use Phalcon\Config; * Given the next configuration file: * * - * [ @@ -54,6 +54,8 @@ class Php extends Config */ public function __construct(string! filePath) -> void { - parent::__construct(require filePath); + parent::__construct( + require filePath + ); } } diff --git a/phalcon/Config/Exception.zep b/phalcon/Config/Exception.zep index e1cde6123a9..02630a46031 100644 --- a/phalcon/Config/Exception.zep +++ b/phalcon/Config/Exception.zep @@ -14,7 +14,6 @@ namespace Phalcon\Config; * Phalcon\Config\Exception * * Exceptions thrown in Phalcon\Config will use this class - * */ class Exception extends \Phalcon\Exception { diff --git a/phalcon/Config/Factory.zep b/phalcon/Config/Factory.zep index 2fb9cfd2d4c..b358186d7b9 100644 --- a/phalcon/Config/Factory.zep +++ b/phalcon/Config/Factory.zep @@ -53,7 +53,7 @@ class Factory extends BaseFactory } let config = [ - "adapter": extension, + "adapter": extension, "filePath": oldConfig ]; } diff --git a/phalcon/Crypt.zep b/phalcon/Crypt.zep index 93daf4835e1..fc5028b6623 100644 --- a/phalcon/Crypt.zep +++ b/phalcon/Crypt.zep @@ -84,7 +84,6 @@ class Crypt implements CryptInterface */ protected useSigning = true; - /** * Phalcon\Crypt constructor. */ @@ -129,6 +128,7 @@ class Crypt implements CryptInterface this->assertCipherIsAvailable(cipher); let ivLength = this->ivLength; + if likely ivLength > 0 { let blockSize = ivLength; } else { @@ -180,7 +180,7 @@ class Crypt implements CryptInterface */ public function decryptBase64(string! text, key = null, bool! safe = false) -> string { - if safe == true { + if safe { return this->decrypt( base64_decode( strtr(text, "-_", "+/") . substr("===", (strlen(text) + 3) % 4) @@ -232,6 +232,7 @@ class Crypt implements CryptInterface this->assertCipherIsAvailable(cipher); let ivLength = this->ivLength; + if likely ivLength > 0 { let blockSize = ivLength; } else { @@ -253,7 +254,13 @@ class Crypt implements CryptInterface let padded = text; } - let encrypted = openssl_encrypt(padded, cipher, encryptKey, OPENSSL_RAW_DATA, iv); + let encrypted = openssl_encrypt( + padded, + cipher, + encryptKey, + OPENSSL_RAW_DATA, + iv + ); if this->useSigning { var digest, hashAlgo; @@ -273,9 +280,21 @@ class Crypt implements CryptInterface public function encryptBase64(string! text, key = null, bool! safe = false) -> string { if safe == true { - return rtrim(strtr(base64_encode(this->encrypt(text, key)), "+/", "-_"), "="); + return rtrim( + strtr( + base64_encode( + this->encrypt(text, key) + ), + "+/", + "-_" + ), + "=" + ); } - return base64_encode(this->encrypt(text, key)); + + return base64_encode( + this->encrypt(text, key) + ); } /** @@ -286,8 +305,10 @@ class Crypt implements CryptInterface var availableCiphers; let availableCiphers = this->availableCiphers; + if unlikely typeof availableCiphers !== "array" { this->initializeAvailableCiphers(); + let availableCiphers = this->availableCiphers; } @@ -387,6 +408,7 @@ class Crypt implements CryptInterface public function setKey(string! key) -> { let this->key = key; + return this; } @@ -396,6 +418,7 @@ class Crypt implements CryptInterface public function setPadding(int! scheme) -> { let this->padding = scheme; + return this; } @@ -490,8 +513,8 @@ class Crypt implements CryptInterface var paddingSize = 0, padding = null; if mode == "cbc" || mode == "ecb" { - let paddingSize = blockSize - (strlen(text) % blockSize); + if paddingSize >= 256 { throw new Exception("Block size is bigger than 256"); } @@ -508,10 +531,13 @@ class Crypt implements CryptInterface case self::PADDING_ISO_10126: let padding = ""; + for i in range(0, paddingSize - 2) { let padding .= chr(rand()); } + let padding .= chr(paddingSize); + break; case self::PADDING_ISO_IEC_7816_4: @@ -561,32 +587,38 @@ class Crypt implements CryptInterface int i, paddingSize = 0, ord; let length = strlen(text); - if length > 0 && (length % blockSize == 0) && (mode == "cbc" || mode == "ecb") { + if length > 0 && (length % blockSize == 0) && (mode == "cbc" || mode == "ecb") { switch paddingType { case self::PADDING_ANSI_X_923: let last = substr(text, length - 1, 1); let ord = (int) ord(last); + if ord <= blockSize { let paddingSize = ord; let padding = str_repeat(chr(0), paddingSize - 1) . last; + if substr(text, length - paddingSize) != padding { let paddingSize = 0; } } + break; case self::PADDING_PKCS7: let last = substr(text, length - 1, 1); let ord = (int) ord(last); + if ord <= blockSize { let paddingSize = ord; let padding = str_repeat(chr(paddingSize), paddingSize); + if substr(text, length - paddingSize) != padding { let paddingSize = 0; } } + break; case self::PADDING_ISO_10126: @@ -596,28 +628,35 @@ class Crypt implements CryptInterface case self::PADDING_ISO_IEC_7816_4: let i = length - 1; + while i > 0 && text[i] == 0x00 && paddingSize < blockSize { let paddingSize++, i--; } + if text[i] == 0x80 { let paddingSize++; } else { let paddingSize = 0; } + break; case self::PADDING_ZERO: let i = length - 1; + while i >= 0 && text[i] == 0x00 && paddingSize <= blockSize { let paddingSize++, i--; } + break; case self::PADDING_SPACE: let i = length - 1; + while i >= 0 && text[i] == 0x20 && paddingSize <= blockSize { let paddingSize++, i--; } + break; default: @@ -625,12 +664,11 @@ class Crypt implements CryptInterface } if paddingSize && paddingSize <= blockSize { - if paddingSize < length { return substr(text, 0, length - paddingSize); } - return ""; + return ""; } else { let paddingSize = 0; } diff --git a/phalcon/Crypt/Exception.zep b/phalcon/Crypt/Exception.zep index ac8486e4a64..767405015a7 100644 --- a/phalcon/Crypt/Exception.zep +++ b/phalcon/Crypt/Exception.zep @@ -14,7 +14,6 @@ namespace Phalcon\Crypt; * Phalcon\Crypt\Exception * * Exceptions thrown in Phalcon\Crypt use this class - * */ class Exception extends \Phalcon\Exception { diff --git a/phalcon/Db/Adapter.zep b/phalcon/Db/Adapter.zep index da0cc44b449..dfcafdce4fa 100644 --- a/phalcon/Db/Adapter.zep +++ b/phalcon/Db/Adapter.zep @@ -288,17 +288,16 @@ abstract class Adapter implements AdapterInterface, EventsAwareInterface * $connection->describeIndexes("robots_parts") * ); * - * - * @param string schema */ public function describeIndexes(string! table, string schema = null) -> { var indexes, index, keyName, indexObjects, name, indexColumns, columns; let indexes = []; - for index in this->fetchAll(this->dialect->describeIndexes(table, schema), Db::FETCH_NUM) { + for index in this->fetchAll(this->dialect->describeIndexes(table, schema), Db::FETCH_NUM) { let keyName = index[2]; + if !isset indexes[keyName] { let columns = []; } else { @@ -310,8 +309,8 @@ abstract class Adapter implements AdapterInterface, EventsAwareInterface } let indexObjects = []; - for name, indexColumns in indexes { + for name, indexColumns in indexes { /** * Every index is abstracted using a Phalcon\Db\Index instance */ @@ -332,15 +331,15 @@ abstract class Adapter implements AdapterInterface, EventsAwareInterface */ public function describeReferences(string! table, string! schema = null) -> { - var references, reference, - arrayReference, constraintName, referenceObjects, name, - referencedSchema, referencedTable, columns, referencedColumns; + var references, reference, arrayReference, constraintName, + referenceObjects, name, referencedSchema, referencedTable, columns, + referencedColumns; let references = []; for reference in this->fetchAll(this->dialect->describeReferences(table, schema), Db::FETCH_NUM) { - let constraintName = reference[2]; + if !isset references[constraintName] { let referencedSchema = reference[3]; let referencedTable = reference[4]; @@ -365,6 +364,7 @@ abstract class Adapter implements AdapterInterface, EventsAwareInterface } let referenceObjects = []; + for name, arrayReference in references { let referenceObjects[name] = new Reference( name, @@ -522,18 +522,17 @@ abstract class Adapter implements AdapterInterface, EventsAwareInterface */ public function fetchAll(string sqlQuery, int fetchMode = Db::FETCH_ASSOC, var bindParams = null, var bindTypes = null) -> array { - var results, result; - - let results = [], - result = this->{"query"}(sqlQuery, bindParams, bindTypes); - if typeof result == "object" { + var result; - result->setFetchMode(fetchMode); + let result = this->{"query"}(sqlQuery, bindParams, bindTypes); - let results = result->fetchAll(); + if typeof result != "object" { + return []; } - return results; + result->setFetchMode(fetchMode); + + return result->fetchAll(); } /** @@ -560,11 +559,11 @@ abstract class Adapter implements AdapterInterface, EventsAwareInterface let row = this->fetchOne(sqlQuery, Db::FETCH_BOTH, placeholders); - if !empty row && fetch columnValue, row[column] { - return columnValue; + if !fetch columnValue, row[column] { + return false; } - return false; + return columnValue; } /** @@ -576,7 +575,10 @@ abstract class Adapter implements AdapterInterface, EventsAwareInterface * print_r($robot); * * // Getting first robot with associative indexes only - * $robot = $connection->fetchOne("SELECT * FROM robots", \Phalcon\Db::FETCH_ASSOC); + * $robot = $connection->fetchOne( + * "SELECT * FROM robots", + * \Phalcon\Db::FETCH_ASSOC + * ); * print_r($robot); * */ @@ -756,9 +758,8 @@ abstract class Adapter implements AdapterInterface, EventsAwareInterface */ public function insert(string table, array! values, var fields = null, var dataTypes = null) -> bool { - var placeholders, insertValues, bindDataTypes, bindType, - position, value, escapedTable, joinedValues, escapedFields, - field, insertSql; + var placeholders, insertValues, bindDataTypes, bindType, position, + value, escapedTable, joinedValues, escapedFields, field, insertSql; /** * A valid array with more than one element is required @@ -791,6 +792,7 @@ abstract class Adapter implements AdapterInterface, EventsAwareInterface } else { let placeholders[] = "?"; let insertValues[] = value; + if typeof dataTypes == "array" { if !fetch bindType, dataTypes[position] { throw new Exception( @@ -810,8 +812,10 @@ abstract class Adapter implements AdapterInterface, EventsAwareInterface * Build the final SQL INSERT statement */ let joinedValues = join(", ", placeholders); + if typeof fields == "array" { let escapedFields = []; + for field in fields { let escapedFields[] = this->escapeIdentifier(field); } @@ -1022,7 +1026,6 @@ abstract class Adapter implements AdapterInterface, EventsAwareInterface */ public function setNestedTransactionsWithSavepoints(bool nestedTransactionsWithSavepoints) -> { - if this->transactionLevel > 0 { throw new Exception( "Nested transaction with savepoints behavior cannot be changed while a transaction is open" @@ -1036,6 +1039,7 @@ abstract class Adapter implements AdapterInterface, EventsAwareInterface } let this->transactionsWithSavepoints = nestedTransactionsWithSavepoints; + return this; } @@ -1084,10 +1088,12 @@ abstract class Adapter implements AdapterInterface, EventsAwareInterface var sql; let sql = this->dialect->tableOptions(tableName, schemaName); - if sql { - return this->fetchAll(sql, Db::FETCH_ASSOC)[0]; + + if !sql { + return []; } - return []; + + return this->fetchAll(sql, Db::FETCH_ASSOC)[0]; } /** @@ -1124,16 +1130,16 @@ abstract class Adapter implements AdapterInterface, EventsAwareInterface * * Warning! If $whereCondition is string it not escaped. * - * @param array fields - * @param array values - * @param string|array whereCondition - * @param array dataTypes + * @param array fields + * @param array values + * @param string|array whereCondition + * @param array dataTypes */ public function update(string table, var fields, var values, var whereCondition = null, var dataTypes = null) -> bool { - var placeholders, updateValues, position, value, - field, bindDataTypes, escapedField, bindType, escapedTable, - setClause, updateSql, conditions, whereBind, whereTypes; + var placeholders, updateValues, position, value, field, bindDataTypes, + escapedField, bindType, escapedTable, setClause, updateSql, + conditions, whereBind, whereTypes; let placeholders = [], updateValues = []; @@ -1153,6 +1159,7 @@ abstract class Adapter implements AdapterInterface, EventsAwareInterface } let escapedField = this->escapeIdentifier(field); + if typeof value == "object" && value instanceof RawValue { let placeholders[] = escapedField . " = " . (string) value; } else { @@ -1164,6 +1171,7 @@ abstract class Adapter implements AdapterInterface, EventsAwareInterface let placeholders[] = escapedField . " = null"; } else { let updateValues[] = value; + if typeof dataTypes == "array" { if !fetch bindType, dataTypes[position] { throw new Exception( @@ -1173,6 +1181,7 @@ abstract class Adapter implements AdapterInterface, EventsAwareInterface let bindDataTypes[] = bindType; } + let placeholders[] = escapedField . " = ?"; } } @@ -1183,7 +1192,6 @@ abstract class Adapter implements AdapterInterface, EventsAwareInterface let setClause = join(", ", placeholders); if whereCondition !== null { - let updateSql = "UPDATE " . escapedTable . " SET " . setClause . " WHERE "; /** @@ -1256,9 +1264,9 @@ abstract class Adapter implements AdapterInterface, EventsAwareInterface * UPDATE `robots` SET `name` = "Astro boy" WHERE id = 101 * * - * @param array data - * @param string whereCondition - * @param array dataTypes + * @param array data + * @param string whereCondition + * @param array dataTypes */ public function updateAsDict(string table, var data, var whereCondition = null, var dataTypes = null) -> bool { diff --git a/phalcon/Db/Adapter/Pdo.zep b/phalcon/Db/Adapter/Pdo.zep index 70f81dc4bcf..98d9d742433 100644 --- a/phalcon/Db/Adapter/Pdo.zep +++ b/phalcon/Db/Adapter/Pdo.zep @@ -39,7 +39,6 @@ use Phalcon\Events\ManagerInterface; */ abstract class Pdo extends Adapter { - /** * Last affected rows */ @@ -58,6 +57,7 @@ abstract class Pdo extends Adapter public function __construct(array! descriptor) -> void { this->connect(descriptor); + parent::__construct(descriptor); } @@ -101,7 +101,6 @@ abstract class Pdo extends Adapter let transactionLevel = (int) this->transactionLevel; if transactionLevel == 1 { - /** * Notify the events manager about the started transaction */ @@ -112,7 +111,6 @@ abstract class Pdo extends Adapter return pdo->beginTransaction(); } else { - /** * Check if the current database system supports nested transactions */ @@ -130,7 +128,6 @@ abstract class Pdo extends Adapter return this->createSavepoint(savepointName); } - } return false; @@ -157,7 +154,6 @@ abstract class Pdo extends Adapter } if transactionLevel == 1 { - /** * Notify the events manager about the committed transaction */ @@ -173,12 +169,10 @@ abstract class Pdo extends Adapter return pdo->commit(); } else { - /** * Check if the current database system supports nested transactions */ if transactionLevel && nesting && this->isNestedTransactionsWithSavepoints() { - /** * Notify the events manager about the committed savepoint */ @@ -195,7 +189,6 @@ abstract class Pdo extends Adapter return this->releaseSavepoint(savepointName); } - } /** @@ -215,10 +208,13 @@ abstract class Pdo extends Adapter public function close() -> bool { var pdo; + let pdo = this->pdo; + if typeof pdo == "object" { let this->pdo = null; } + return true; } @@ -289,6 +285,7 @@ abstract class Pdo extends Adapter // the form of key=value with semicolons delineating sections. if fetch dsnAttributesCustomRaw, descriptor["dsn"] { let dsnParts[] = dsnAttributesCustomRaw; + unset descriptor["dsn"]; } @@ -297,7 +294,10 @@ abstract class Pdo extends Adapter * descriptor. At this point the descriptor should be a valid DSN * key-value map due to all other values having been removed. */ - let dsnAttributesMap = array_merge(this->getDsnDefaults(), descriptor); + let dsnAttributesMap = array_merge( + this->getDsnDefaults(), + descriptor + ); for key, value in dsnAttributesMap { let dsnParts[] = key . "=" . value; @@ -333,16 +333,16 @@ abstract class Pdo extends Adapter */ public function convertBoundParams(string! sql, array params = []) -> array { - var boundSql, placeHolders, bindPattern, matches, - setOrder, placeMatch, value; + var boundSql, placeHolders, bindPattern, matches, setOrder, placeMatch, + value; let placeHolders = [], bindPattern = "/\\?([0-9]+)|:([a-zA-Z0-9_]+):/", - matches = null, setOrder = 2; + matches = null, + setOrder = 2; if preg_match_all(bindPattern, sql, matches, setOrder) { for placeMatch in matches { - if !fetch value, params[placeMatch[1]] { if isset placeMatch[2] { if !fetch value, params[placeMatch[2]] { @@ -416,6 +416,7 @@ abstract class Pdo extends Adapter let this->sqlStatement = sqlStatement, this->sqlVariables = bindParams, this->sqlBindTypes = bindTypes; + if eventsManager->fire("db:beforeQuery", this) === false { return false; } @@ -427,8 +428,10 @@ abstract class Pdo extends Adapter let affectedRows = 0; let pdo = <\Pdo> this->pdo; + if typeof bindParams == "array" { let statement = pdo->prepare(sqlStatement); + if typeof statement == "object" { let newStatement = this->executePrepared( statement, @@ -447,6 +450,7 @@ abstract class Pdo extends Adapter */ if typeof affectedRows == "integer" { let this->affectedRows = affectedRows; + if typeof eventsManager == "object" { eventsManager->fire("db:afterQuery", this); } @@ -481,11 +485,9 @@ abstract class Pdo extends Adapter */ public function executePrepared(<\PDOStatement> statement, array! placeholders, dataTypes) -> <\PDOStatement> { - var wildcard, value, type, castValue, - parameter, position, itemValue; + var wildcard, value, type, castValue, parameter, position, itemValue; for wildcard, value in placeholders { - if typeof wildcard == "integer" { let parameter = wildcard + 1; } elseif typeof wildcard == "string" { @@ -495,7 +497,6 @@ abstract class Pdo extends Adapter } if typeof dataTypes == "array" && fetch type, dataTypes[wildcard] { - /** * The bind type needs to be string because the precision * is lost if it is casted as a double @@ -617,10 +618,13 @@ abstract class Pdo extends Adapter public function isUnderTransaction() -> bool { var pdo; + let pdo = this->pdo; + if typeof pdo == "object" { return pdo->inTransaction(); } + return false; } @@ -651,10 +655,13 @@ abstract class Pdo extends Adapter public function lastInsertId(sequenceName = null) -> int | bool { var pdo; + let pdo = this->pdo; + if typeof pdo != "object" { return false; } + return pdo->lastInsertId(sequenceName); } @@ -716,6 +723,7 @@ abstract class Pdo extends Adapter let this->sqlStatement = sqlStatement, this->sqlVariables = bindParams, this->sqlBindTypes = bindTypes; + if eventsManager->fire("db:beforeQuery", this) === false { return false; } @@ -778,7 +786,6 @@ abstract class Pdo extends Adapter } if transactionLevel == 1 { - /** * Notify the events manager about the rollbacked transaction */ @@ -793,9 +800,7 @@ abstract class Pdo extends Adapter let this->transactionLevel--; return pdo->rollback(); - } else { - /** * Check if the current database system supports nested transactions */ diff --git a/phalcon/Db/Adapter/Pdo/Factory.zep b/phalcon/Db/Adapter/Pdo/Factory.zep index e22cdfe2ecc..9dfb2e4899b 100644 --- a/phalcon/Db/Adapter/Pdo/Factory.zep +++ b/phalcon/Db/Adapter/Pdo/Factory.zep @@ -27,6 +27,7 @@ use Phalcon\Db\AdapterInterface; * "password" => "secret", * "adapter" => "mysql", * ]; + * * $db = Factory::load($options); * */ diff --git a/phalcon/Db/Adapter/Pdo/Mysql.zep b/phalcon/Db/Adapter/Pdo/Mysql.zep index cd09dc1cfa8..6fff319f352 100644 --- a/phalcon/Db/Adapter/Pdo/Mysql.zep +++ b/phalcon/Db/Adapter/Pdo/Mysql.zep @@ -41,7 +41,6 @@ use Phalcon\Db\ReferenceInterface; */ class Mysql extends PdoAdapter { - protected dialectType = "mysql"; protected type = "mysql"; @@ -102,7 +101,9 @@ class Mysql extends PdoAdapter /** * By default the bind types is two */ - let definition = ["bindType": Column::BIND_PARAM_STR]; + let definition = [ + "bindType": Column::BIND_PARAM_STR + ]; /** * By checking every column type we convert it to a @@ -133,6 +134,7 @@ class Mysql extends PdoAdapter let definition["type"] = Column::TYPE_BOOLEAN, definition["isNumeric"] = true, definition["bindType"] = Column::BIND_PARAM_BOOL; + break; /** @@ -142,6 +144,7 @@ class Mysql extends PdoAdapter let definition["type"] = Column::TYPE_BIGINTEGER, definition["isNumeric"] = true, definition["bindType"] = Column::BIND_PARAM_INT; + break; /** @@ -151,6 +154,7 @@ class Mysql extends PdoAdapter let definition["type"] = Column::TYPE_MEDIUMINTEGER, definition["isNumeric"] = true, definition["bindType"] = Column::BIND_PARAM_INT; + break; /** @@ -160,6 +164,7 @@ class Mysql extends PdoAdapter let definition["type"] = Column::TYPE_SMALLINTEGER, definition["isNumeric"] = true, definition["bindType"] = Column::BIND_PARAM_INT; + break; /** @@ -172,6 +177,7 @@ class Mysql extends PdoAdapter let definition["type"] = Column::TYPE_TINYINTEGER, definition["isNumeric"] = true, definition["bindType"] = Column::BIND_PARAM_INT; + break; /** @@ -190,6 +196,7 @@ class Mysql extends PdoAdapter case memstr(columnType, "bit"): let definition["type"] = Column::TYPE_BIT, definition["bindType"] = Column::BIND_PARAM_INT; + break; /** @@ -197,14 +204,15 @@ class Mysql extends PdoAdapter */ case memstr(columnType, "enum"): let definition["type"] = Column::TYPE_ENUM; - break; + break; /** * DATE */ case memstr(columnType, "datetime"): let definition["type"] = Column::TYPE_DATETIME; + break; /** @@ -212,6 +220,7 @@ class Mysql extends PdoAdapter */ case memstr(columnType, "date"): let definition["type"] = Column::TYPE_DATE; + break; /** @@ -221,6 +230,7 @@ class Mysql extends PdoAdapter case memstr(columnType, "decimal"): let definition["type"] = Column::TYPE_DECIMAL, definition["isNumeric"] = true; + break; /** @@ -230,6 +240,7 @@ class Mysql extends PdoAdapter let definition["type"] = Column::TYPE_DOUBLE, definition["isNumeric"] = true, definition["bindType"] = Column::BIND_PARAM_DECIMAL; + break; /** @@ -239,6 +250,7 @@ class Mysql extends PdoAdapter let definition["type"] = Column::TYPE_FLOAT, definition["isNumeric"] = true, definition["bindType"] = Column::BIND_PARAM_DECIMAL; + break; /** @@ -246,6 +258,7 @@ class Mysql extends PdoAdapter */ case memstr(columnType, "mediumblob"): let definition["type"] = Column::TYPE_MEDIUMBLOB; + break; /** @@ -253,6 +266,7 @@ class Mysql extends PdoAdapter */ case memstr(columnType, "longblob"): let definition["type"] = Column::TYPE_LONGBLOB; + break; /** @@ -260,6 +274,7 @@ class Mysql extends PdoAdapter */ case memstr(columnType, "tinyblob"): let definition["type"] = Column::TYPE_TINYBLOB; + break; /** @@ -267,6 +282,7 @@ class Mysql extends PdoAdapter */ case memstr(columnType, "blob"): let definition["type"] = Column::TYPE_BLOB; + break; /** @@ -274,6 +290,7 @@ class Mysql extends PdoAdapter */ case memstr(columnType, "timestamp"): let definition["type"] = Column::TYPE_TIMESTAMP; + break; /** @@ -281,6 +298,7 @@ class Mysql extends PdoAdapter */ case memstr(columnType, "time"): let definition["type"] = Column::TYPE_TIME; + break; /** @@ -288,6 +306,7 @@ class Mysql extends PdoAdapter */ case memstr(columnType, "json"): let definition["type"] = Column::TYPE_JSON; + break; /** @@ -295,6 +314,7 @@ class Mysql extends PdoAdapter */ case memstr(columnType, "longtext"): let definition["type"] = Column::TYPE_LONGTEXT; + break; /** @@ -302,6 +322,7 @@ class Mysql extends PdoAdapter */ case memstr(columnType, "mediumtext"): let definition["type"] = Column::TYPE_MEDIUMTEXT; + break; /** @@ -309,6 +330,7 @@ class Mysql extends PdoAdapter */ case memstr(columnType, "tinytext"): let definition["type"] = Column::TYPE_TINYTEXT; + break; /** @@ -316,6 +338,7 @@ class Mysql extends PdoAdapter */ case memstr(columnType, "text"): let definition["type"] = Column::TYPE_TEXT; + break; /** @@ -323,6 +346,7 @@ class Mysql extends PdoAdapter */ case memstr(columnType, "varchar"): let definition["type"] = Column::TYPE_VARCHAR; + break; /** @@ -330,6 +354,7 @@ class Mysql extends PdoAdapter */ case memstr(columnType, "char"): let definition["type"] = Column::TYPE_CHAR; + break; /** @@ -337,6 +362,7 @@ class Mysql extends PdoAdapter */ default: let definition["type"] = Column::TYPE_VARCHAR; + break; } @@ -346,12 +372,14 @@ class Mysql extends PdoAdapter */ if memstr(columnType, "(") { let matches = null; + if definition["type"] == Column::TYPE_ENUM { let definition["size"] = substr(columnType, 5, -1); } elseif preg_match(sizePattern, columnType, matches) { if fetch matchOne, matches[1] { let definition["size"] = (int) matchOne; } + if fetch matchTwo, matches[2] { let definition["scale"] = (int) matchTwo; } @@ -427,6 +455,7 @@ class Mysql extends PdoAdapter var indexes, index, keyName, indexType, indexObjects, columns, name; let indexes = []; + for index in this->fetchAll(this->dialect->describeIndexes(table, schema), Db::FETCH_ASSOC) { let keyName = index["Key_name"]; let indexType = index["Index_type"]; @@ -456,6 +485,7 @@ class Mysql extends PdoAdapter } let indexObjects = []; + for name, index in indexes { let indexObjects[name] = new Index( name, @@ -478,16 +508,16 @@ class Mysql extends PdoAdapter */ public function describeReferences(string! table, string! schema = null) -> { - var references, reference, - arrayReference, constraintName, referenceObjects, name, - referencedSchema, referencedTable, columns, referencedColumns, - referenceUpdate, referenceDelete; + var references, reference, arrayReference, constraintName, + referenceObjects, name, referencedSchema, referencedTable, columns, + referencedColumns, referenceUpdate, referenceDelete; let references = []; for reference in this->fetchAll(this->dialect->describeReferences(table, schema), Db::FETCH_NUM) { let constraintName = reference[2]; + if !isset references[constraintName] { let referencedSchema = reference[3]; let referencedTable = reference[4]; @@ -495,7 +525,6 @@ class Mysql extends PdoAdapter let referenceDelete = reference[7]; let columns = []; let referencedColumns = []; - } else { let referencedSchema = references[constraintName]["referencedSchema"]; let referencedTable = references[constraintName]["referencedTable"]; diff --git a/phalcon/Db/Adapter/Pdo/Postgresql.zep b/phalcon/Db/Adapter/Pdo/Postgresql.zep index ba5c8b953d3..33f5bdf4971 100644 --- a/phalcon/Db/Adapter/Pdo/Postgresql.zep +++ b/phalcon/Db/Adapter/Pdo/Postgresql.zep @@ -85,8 +85,9 @@ class Postgresql extends PdoAdapter let status = parent::connect(descriptor); - if ! empty schema { + if !empty schema { let sql = "SET search_path TO '" . schema . "'"; + this->execute(sql); } @@ -98,7 +99,7 @@ class Postgresql extends PdoAdapter */ public function createTable(string! tableName, string! schemaName, array! definition) -> bool { - var sql,queries,query,exception,columns; + var sql, queries, query, exception, columns; if !fetch columns, definition["columns"] { throw new Exception("The table must contain at least one column"); @@ -115,21 +116,24 @@ class Postgresql extends PdoAdapter if count(queries) > 1 { try { this->{"begin"}(); + for query in queries { if empty query { continue; } this->{"query"}(query . ";"); } + return this->{"commit"}(); } catch \Throwable, exception { - this->{"rollback"}(); - throw exception; - } + + throw exception; + } } else { return this->{"execute"}(queries[0] . ";"); } + return true; } @@ -144,8 +148,8 @@ class Postgresql extends PdoAdapter */ public function describeColumns(string table, string schema = null) -> { - var columns, columnType, fields, field, definition, - oldColumn, columnName, charSize, numericSize, numericScale; + var columns, columnType, fields, field, definition, oldColumn, + columnName, charSize, numericSize, numericScale; let oldColumn = null, columns = []; @@ -164,7 +168,9 @@ class Postgresql extends PdoAdapter /** * By default the bind types is two */ - let definition = ["bindType": Column::BIND_PARAM_STR]; + let definition = [ + "bindType": Column::BIND_PARAM_STR + ]; /** * By checking every column type we convert it to a @@ -198,6 +204,7 @@ class Postgresql extends PdoAdapter let definition["type"] = Column::TYPE_BOOLEAN, definition["isNumeric"] = true, definition["bindType"] = Column::BIND_PARAM_BOOL; + break; /** @@ -207,6 +214,7 @@ class Postgresql extends PdoAdapter let definition["type"] = Column::TYPE_BIGINTEGER, definition["isNumeric"] = true, definition["bindType"] = Column::BIND_PARAM_INT; + break; /** @@ -216,6 +224,7 @@ class Postgresql extends PdoAdapter let definition["type"] = Column::TYPE_MEDIUMINTEGER, definition["isNumeric"] = true, definition["bindType"] = Column::BIND_PARAM_INT; + break; /** @@ -225,6 +234,7 @@ class Postgresql extends PdoAdapter let definition["type"] = Column::TYPE_SMALLINTEGER, definition["isNumeric"] = true, definition["bindType"] = Column::BIND_PARAM_INT; + break; /** @@ -237,6 +247,7 @@ class Postgresql extends PdoAdapter let definition["type"] = Column::TYPE_TINYINTEGER, definition["isNumeric"] = true, definition["bindType"] = Column::BIND_PARAM_INT; + break; /** @@ -255,6 +266,7 @@ class Postgresql extends PdoAdapter case memstr(columnType, "bit"): let definition["type"] = Column::TYPE_BIT, definition["size"] = numericSize; + break; /** @@ -262,8 +274,8 @@ class Postgresql extends PdoAdapter */ case memstr(columnType, "enum"): let definition["type"] = Column::TYPE_ENUM; - break; + break; /** * DATE @@ -271,6 +283,7 @@ class Postgresql extends PdoAdapter case memstr(columnType, "datetime"): let definition["type"] = Column::TYPE_DATETIME, definition["size"] = 0; + break; /** @@ -279,6 +292,7 @@ class Postgresql extends PdoAdapter case memstr(columnType, "date"): let definition["type"] = Column::TYPE_DATE, definition["size"] = 0; + break; /** @@ -291,6 +305,7 @@ class Postgresql extends PdoAdapter definition["size"] = numericSize, definition["isNumeric"] = true, definition["bindType"] = Column::BIND_PARAM_DECIMAL; + break; /** @@ -301,6 +316,7 @@ class Postgresql extends PdoAdapter definition["isNumeric"] = true, definition["size"] = numericSize, definition["bindType"] = Column::BIND_PARAM_DECIMAL; + break; /** @@ -312,6 +328,7 @@ class Postgresql extends PdoAdapter definition["isNumeric"] = true, definition["size"] = numericSize, definition["bindType"] = Column::BIND_PARAM_DECIMAL; + break; /** @@ -319,6 +336,7 @@ class Postgresql extends PdoAdapter */ case memstr(columnType, "mediumblob"): let definition["type"] = Column::TYPE_TEXT; + break; /** @@ -326,6 +344,7 @@ class Postgresql extends PdoAdapter */ case memstr(columnType, "longblob"): let definition["type"] = Column::TYPE_LONGBLOB; + break; /** @@ -333,6 +352,7 @@ class Postgresql extends PdoAdapter */ case memstr(columnType, "tinyblob"): let definition["type"] = Column::TYPE_TINYBLOB; + break; /** @@ -340,6 +360,7 @@ class Postgresql extends PdoAdapter */ case memstr(columnType, "blob"): let definition["type"] = Column::TYPE_BLOB; + break; /** @@ -347,6 +368,7 @@ class Postgresql extends PdoAdapter */ case memstr(columnType, "timestamp"): let definition["type"] = Column::TYPE_TIMESTAMP; + break; /** @@ -354,6 +376,7 @@ class Postgresql extends PdoAdapter */ case memstr(columnType, "time"): let definition["type"] = Column::TYPE_TIME; + break; /** @@ -361,6 +384,7 @@ class Postgresql extends PdoAdapter */ case memstr(columnType, "jsonb"): let definition["type"] = Column::TYPE_JSONB; + break; /** @@ -368,6 +392,7 @@ class Postgresql extends PdoAdapter */ case memstr(columnType, "json"): let definition["type"] = Column::TYPE_JSON; + break; /** @@ -375,6 +400,7 @@ class Postgresql extends PdoAdapter */ case memstr(columnType, "longtext"): let definition["type"] = Column::TYPE_LONGTEXT; + break; /** @@ -382,6 +408,7 @@ class Postgresql extends PdoAdapter */ case memstr(columnType, "mediumtext"): let definition["type"] = Column::TYPE_MEDIUMTEXT; + break; /** @@ -389,6 +416,7 @@ class Postgresql extends PdoAdapter */ case memstr(columnType, "tinytext"): let definition["type"] = Column::TYPE_TINYTEXT; + break; /** @@ -396,6 +424,7 @@ class Postgresql extends PdoAdapter */ case memstr(columnType, "text"): let definition["type"] = Column::TYPE_TEXT; + break; /** @@ -405,6 +434,7 @@ class Postgresql extends PdoAdapter case memstr(columnType, "varchar"): let definition["type"] = Column::TYPE_VARCHAR, definition["size"] = charSize; + break; /** @@ -413,6 +443,7 @@ class Postgresql extends PdoAdapter case memstr(columnType, "char"): let definition["type"] = Column::TYPE_CHAR, definition["size"] = charSize; + break; /** @@ -421,6 +452,7 @@ class Postgresql extends PdoAdapter case memstr(columnType, "uuid"): let definition["type"] = Column::TYPE_CHAR, definition["size"] = 36; + break; /** @@ -428,6 +460,7 @@ class Postgresql extends PdoAdapter */ default: let definition["type"] = Column::TYPE_VARCHAR; + break; } @@ -498,16 +531,15 @@ class Postgresql extends PdoAdapter */ public function describeReferences(string! table, string! schema = null) -> { - var references, reference, - arrayReference, constraintName, referenceObjects, name, - referencedSchema, referencedTable, columns, referencedColumns, - referenceUpdate, referenceDelete; + var references, reference, arrayReference, constraintName, + referenceObjects, name, referencedSchema, referencedTable, columns, + referencedColumns, referenceUpdate, referenceDelete; let references = []; for reference in this->fetchAll(this->dialect->describeReferences(table, schema), Db::FETCH_NUM) { - let constraintName = reference[2]; + if !isset references[constraintName] { let referencedSchema = reference[3]; let referencedTable = reference[4]; @@ -515,7 +547,6 @@ class Postgresql extends PdoAdapter let referenceDelete = reference[7]; let columns = []; let referencedColumns = []; - } else { let referencedSchema = references[constraintName]["referencedSchema"]; let referencedTable = references[constraintName]["referencedTable"]; @@ -539,6 +570,7 @@ class Postgresql extends PdoAdapter } let referenceObjects = []; + for name, arrayReference in references { let referenceObjects[name] = new Reference( name, @@ -586,7 +618,7 @@ class Postgresql extends PdoAdapter */ public function modifyColumn(string! tableName, string! schemaName, column, currentColumn = null) -> bool { - var sql,queries,query,exception; + var sql, queries, query, exception; let sql = this->dialect->modifyColumn( tableName, @@ -599,25 +631,26 @@ class Postgresql extends PdoAdapter if count(queries) > 1 { try { - this->{"begin"}(); + for query in queries { if empty query { continue; } + this->{"query"}(query . ";"); } - return this->{"commit"}(); + return this->{"commit"}(); } catch \Throwable, exception { - this->{"rollback"}(); - throw exception; - } + throw exception; + } } else { return !empty sql ? this->{"execute"}(queries[0] . ";") : true; } + return true; } diff --git a/phalcon/Db/Adapter/Pdo/Sqlite.zep b/phalcon/Db/Adapter/Pdo/Sqlite.zep index f53d8497b1a..990b6955313 100644 --- a/phalcon/Db/Adapter/Pdo/Sqlite.zep +++ b/phalcon/Db/Adapter/Pdo/Sqlite.zep @@ -38,7 +38,6 @@ use Phalcon\Db\ReferenceInterface; */ class Sqlite extends PdoAdapter { - protected dialectType = "sqlite"; protected type = "sqlite"; @@ -71,6 +70,7 @@ class Sqlite extends PdoAdapter if fetch dbname, descriptor["dbname"] { let descriptor["dsn"] = dbname; + unset descriptor["dbname"]; } elseif !isset descriptor["dsn"] { throw new Exception( @@ -92,8 +92,8 @@ class Sqlite extends PdoAdapter */ public function describeColumns(string! table, string! schema = null) -> { - var columns, columnType, fields, field, definition, - oldColumn, sizePattern, matches, matchOne, matchTwo, columnName; + var columns, columnType, fields, field, definition, oldColumn, + sizePattern, matches, matchOne, matchTwo, columnName; let oldColumn = null, sizePattern = "#\\(([0-9]+)(?:,\\s*([0-9]+))*\\)#"; @@ -113,7 +113,9 @@ class Sqlite extends PdoAdapter /** * By default the bind types is two */ - let definition = ["bindType": Column::BIND_PARAM_STR]; + let definition = [ + "bindType": Column::BIND_PARAM_STR + ]; /** * By checking every column type we convert it to a @@ -242,6 +244,7 @@ class Sqlite extends PdoAdapter */ if memstr(columnType, "(") { let matches = null; + if preg_match(sizePattern, columnType, matches) { if fetch matchOne, matches[1] { let definition["size"] = (int) matchOne; @@ -320,6 +323,7 @@ class Sqlite extends PdoAdapter describeIndexes, describeIndex, indexSql; let indexes = []; + for index in this->fetchAll(this->dialect->describeIndexes(table, schema), Db::FETCH_ASSOC) { let keyName = index["name"]; @@ -360,6 +364,7 @@ class Sqlite extends PdoAdapter } let indexObjects = []; + for name, index in indexes { let indexObjects[name] = new Index( name, @@ -376,16 +381,15 @@ class Sqlite extends PdoAdapter */ public function describeReferences(string! table, string! schema = null) -> { - var references, reference, - arrayReference, constraintName, referenceObjects, name, - referencedSchema, referencedTable, columns, referencedColumns, - number; + var references, reference, arrayReference, constraintName, + referenceObjects, name, referencedSchema, referencedTable, columns, + referencedColumns, number; let references = []; for number, reference in this->fetchAll(this->dialect->describeReferences(table, schema), Db::FETCH_NUM) { - let constraintName = "foreign_key_" . number; + if !isset references[constraintName] { let referencedSchema = null; let referencedTable = reference[2]; @@ -410,6 +414,7 @@ class Sqlite extends PdoAdapter } let referenceObjects = []; + for name, arrayReference in references { let referenceObjects[name] = new Reference( name, diff --git a/phalcon/Db/Column.zep b/phalcon/Db/Column.zep index 9703df5b682..4f4387e8844 100644 --- a/phalcon/Db/Column.zep +++ b/phalcon/Db/Column.zep @@ -319,9 +319,9 @@ class Column implements ColumnInterface */ public function __construct(string! name, array! definition) -> void { - var type, notNull, primary, size, scale, dunsigned, first, - after, bindType, isNumeric, autoIncrement, defaultValue, - typeReference, typeValues; + var type, notNull, primary, size, scale, dunsigned, first, after, + bindType, isNumeric, autoIncrement, defaultValue, typeReference, + typeValues; let this->name = name; @@ -451,10 +451,9 @@ class Column implements ColumnInterface */ public static function __set_state(array! data) -> { - var definition, columnType, notNull, size, dunsigned, after, - isNumeric, first, bindType, primary, columnName, scale, - defaultValue, autoIncrement, - columnTypeReference, columnTypeValues; + var definition, columnType, notNull, size, dunsigned, after, isNumeric, + first, bindType, primary, columnName, scale, defaultValue, + autoIncrement, columnTypeReference, columnTypeValues; if !fetch columnName, data["columnName"] { if !fetch columnName, data["name"] { @@ -537,8 +536,6 @@ class Column implements ColumnInterface /** * Check whether field absolute to position in table - * - * @return string */ public function getAfterPosition() -> string { diff --git a/phalcon/Db/Dialect.zep b/phalcon/Db/Dialect.zep index df6481344ca..cc443319ed4 100644 --- a/phalcon/Db/Dialect.zep +++ b/phalcon/Db/Dialect.zep @@ -46,7 +46,6 @@ abstract class Dialect implements DialectInterface } if !memstr(str, ".") { - if escapeChar != "" && str != "*" { return escapeChar . str_replace(escapeChar, escapeChar . escapeChar, str) . escapeChar; } @@ -57,8 +56,8 @@ abstract class Dialect implements DialectInterface let parts = (array) explode(".", trim(str, escapeChar)); let newParts = parts; - for key, part in parts { + for key, part in parts { if escapeChar == "" || part == "" || part == "*" { continue; } @@ -90,6 +89,7 @@ abstract class Dialect implements DialectInterface * * * $sql = $dialect->forUpdate("SELECT * FROM robots"); + * * echo $sql; // SELECT * FROM robots FOR UPDATE * */ @@ -142,7 +142,6 @@ abstract class Dialect implements DialectInterface } if !isset column["type"] { - /** * The index "0" is the column field */ @@ -153,12 +152,10 @@ abstract class Dialect implements DialectInterface "type": "scalar", "value": columnField ]; - } elseif columnField == "*" { let columnExpression = [ "type": "all" ]; - } else { let columnExpression = [ "type": "qualified", @@ -265,6 +262,7 @@ abstract class Dialect implements DialectInterface return join(", ", placeholders); } + return expression["value"]; /** @@ -399,17 +397,22 @@ abstract class Dialect implements DialectInterface * Generates the SQL for LIMIT clause * * - * $sql = $dialect->limit("SELECT * FROM robots", 10); - * echo $sql; // SELECT * FROM robots LIMIT 10 + * // SELECT * FROM robots LIMIT 10 + * echo $dialect->limit( + * "SELECT * FROM robots", + * 10 + * ); * - * $sql = $dialect->limit("SELECT * FROM robots", [10, 50]); - * echo $sql; // SELECT * FROM robots LIMIT 10 OFFSET 50 + * // SELECT * FROM robots LIMIT 10 OFFSET 50 + * echo $dialect->limit( + * "SELECT * FROM robots", + * [10, 50] + * ); * */ public function limit(string! sqlQuery, var number) -> string { if typeof number == "array" { - let sqlQuery .= " LIMIT " . number[0]; if isset number[1] && strlen(number[1]) { @@ -428,6 +431,7 @@ abstract class Dialect implements DialectInterface public function registerCustomFunction(string name, callable customFunction) -> { let this->customFunctions[name] = customFunction; + return this; } @@ -468,13 +472,11 @@ abstract class Dialect implements DialectInterface } if fetch distinct, definition["distinct"] { - if distinct { let sql = "SELECT DISTINCT"; } else { let sql = "SELECT ALL"; } - } else { let sql = "SELECT"; } @@ -601,11 +603,11 @@ abstract class Dialect implements DialectInterface */ protected function checkColumnTypeSql( column) -> string { - if typeof column->getType() == "string" { - return column->getType(); + if typeof column->getType() != "string" { + return ""; } - return ""; + return column->getType(); } /** @@ -717,7 +719,6 @@ abstract class Dialect implements DialectInterface var table, tables; if typeof expression == "array" { - let tables = []; for table in expression { @@ -725,7 +726,6 @@ abstract class Dialect implements DialectInterface } let tables = join(", ", tables); - } else { let tables = expression; } @@ -748,11 +748,15 @@ abstract class Dialect implements DialectInterface if fetch arguments, expression["arguments"] && typeof arguments == "array" { - let arguments = this->getSqlExpression([ - "type": "list", - "parentheses": false, - "value": arguments - ], escapeChar, bindCounts); + let arguments = this->getSqlExpression( + [ + "type": "list", + "parentheses": false, + "value": arguments + ], + escapeChar, + bindCounts + ); if isset expression["distinct"] && expression["distinct"] { return name . "(DISTINCT " . arguments . ")"; @@ -772,7 +776,6 @@ abstract class Dialect implements DialectInterface var field, fields; if typeof expression == "array" { - let fields = []; for field in expression { @@ -788,7 +791,6 @@ abstract class Dialect implements DialectInterface } let fields = join(", ", fields); - } else { let fields = expression; } @@ -818,7 +820,6 @@ abstract class Dialect implements DialectInterface * Check if the join has conditions */ if fetch joinConditionsArray, join["conditions"] && !empty joinConditionsArray { - if !isset joinConditionsArray[0] { let joinCondition = this->getSqlExpression( joinConditionsArray, @@ -826,7 +827,6 @@ abstract class Dialect implements DialectInterface bindCounts ); } else { - let joinCondition = []; for condition in joinConditionsArray { @@ -861,6 +861,7 @@ abstract class Dialect implements DialectInterface final protected function getSqlExpressionLimit(var expression, string escapeChar = null, bindCounts = null) -> string { var sql = "", value, limit, offset = null; + let value = expression["value"]; if isset expression["sql"] { @@ -868,9 +869,12 @@ abstract class Dialect implements DialectInterface } if typeof value == "array" { - if typeof value["number"] == "array" { - let limit = this->getSqlExpression(value["number"], escapeChar, bindCounts); + let limit = this->getSqlExpression( + value["number"], + escapeChar, + bindCounts + ); } else { let limit = value["number"]; } @@ -879,7 +883,11 @@ abstract class Dialect implements DialectInterface * Check for an OFFSET condition */ if fetch offset, value["offset"] && typeof offset == "array" { - let offset = this->getSqlExpression(offset, escapeChar, bindCounts); + let offset = this->getSqlExpression( + offset, + escapeChar, + bindCounts + ); } } else { @@ -945,7 +953,6 @@ abstract class Dialect implements DialectInterface var field, fields, type, fieldSql = null; if typeof expression == "array" { - let fields = []; for field in expression { @@ -971,7 +978,6 @@ abstract class Dialect implements DialectInterface } let fields = join(", ", fields); - } else { let fields = expression; } @@ -985,6 +991,7 @@ abstract class Dialect implements DialectInterface final protected function getSqlExpressionQualified(array! expression, string escapeChar = null) -> string { var column, domain; + let column = expression["name"]; /** @@ -1067,6 +1074,7 @@ abstract class Dialect implements DialectInterface if alias != "" { return qualified . " AS " . this->escape(alias, escapeChar); } + return qualified; } diff --git a/phalcon/Db/Dialect/Mysql.zep b/phalcon/Db/Dialect/Mysql.zep index 07c9893f05e..2babaa6517a 100644 --- a/phalcon/Db/Dialect/Mysql.zep +++ b/phalcon/Db/Dialect/Mysql.zep @@ -38,6 +38,7 @@ class Mysql extends Dialect if column->hasDefault() { let defaultValue = column->getDefault(); + if memstr(strtoupper(defaultValue), "CURRENT_TIMESTAMP") { let sql .= " DEFAULT CURRENT_TIMESTAMP"; } else { @@ -75,6 +76,7 @@ class Mysql extends Dialect if reference->getName() { let sql .= " CONSTRAINT `" . $reference->getName() . "`"; } + let sql .= " FOREIGN KEY (" . this->getColumnList(reference->getColumns()) . ") REFERENCES " . this->prepareTable(reference->getReferencedTable(), reference->getReferencedSchema()) . "(" . this->getColumnList(reference->getReferencedColumns()) . ")"; let onDelete = reference->getOnDelete(); @@ -107,6 +109,7 @@ class Mysql extends Dialect } let sql .= "`" . index->getName() . "` (" . this->getColumnList(index->getColumns()) . ")"; + return sql; } @@ -123,10 +126,9 @@ class Mysql extends Dialect */ public function createTable(string! tableName, string! schemaName, array! definition) -> string { - var temporary, options, table, createLines, columns, - column, indexes, index, reference, references, indexName, - indexSql, sql, columnLine, indexType, - referenceSql, onDelete, onUpdate, defaultValue; + var temporary, options, table, createLines, columns, column, indexes, + index, reference, references, indexName, indexSql, sql, columnLine, + indexType, referenceSql, onDelete, onUpdate, defaultValue; if !fetch columns, definition["columns"] { throw new Exception( @@ -160,6 +162,7 @@ class Mysql extends Dialect */ if column->hasDefault() { let defaultValue = column->getDefault(); + if memstr(strtoupper(defaultValue), "CURRENT_TIMESTAMP") { let columnLine .= " DEFAULT CURRENT_TIMESTAMP"; } else { @@ -292,11 +295,13 @@ class Mysql extends Dialect public function describeReferences(string! table, string schema = null) -> string { var sql = "SELECT DISTINCT KCU.TABLE_NAME, KCU.COLUMN_NAME, KCU.CONSTRAINT_NAME, KCU.REFERENCED_TABLE_SCHEMA, KCU.REFERENCED_TABLE_NAME, KCU.REFERENCED_COLUMN_NAME, RC.UPDATE_RULE, RC.DELETE_RULE FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KCU LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS RC ON RC.CONSTRAINT_NAME = KCU.CONSTRAINT_NAME AND RC.CONSTRAINT_SCHEMA = KCU.CONSTRAINT_SCHEMA WHERE KCU.REFERENCED_TABLE_NAME IS NOT NULL AND "; + if schema { let sql .= "KCU.CONSTRAINT_SCHEMA = '" . schema . "' AND KCU.TABLE_NAME = '" . table . "'"; } else { let sql .= "KCU.CONSTRAINT_SCHEMA = DATABASE() AND KCU.TABLE_NAME = '" . table . "'"; } + return sql; } @@ -384,168 +389,206 @@ class Mysql extends Dialect if empty columnSql { let columnSql .= "BIGINT"; } + let columnSql .= this->getColumnSize(column) . this->checkColumnUnsigned(column); + break; case Column::TYPE_BIT: if empty columnSql { let columnSql .= "BIT"; } + let columnSql .= this->getColumnSize(column); + break; case Column::TYPE_BLOB: if empty columnSql { let columnSql .= "BLOB"; } + break; case Column::TYPE_BOOLEAN: if empty columnSql { let columnSql .= "TINYINT(1)"; } + break; case Column::TYPE_CHAR: if empty columnSql { let columnSql .= "CHAR"; } + let columnSql .= this->getColumnSize(column); + break; case Column::TYPE_DATE: if empty columnSql { let columnSql .= "DATE"; } + break; case Column::TYPE_DATETIME: if empty columnSql { let columnSql .= "DATETIME"; } + break; case Column::TYPE_DECIMAL: if empty columnSql { let columnSql .= "DECIMAL"; } + let columnSql .= this->getColumnSizeAndScale(column) . this->checkColumnUnsigned(column); + break; case Column::TYPE_DOUBLE: if empty columnSql { let columnSql .= "DOUBLE"; } + let columnSql .= this->checkColumnSizeAndScale(column) . this->checkColumnUnsigned(column); + break; case Column::TYPE_ENUM: if empty columnSql { let columnSql .= "ENUM"; } + let columnSql .= this->getColumnSize(column); + break; case Column::TYPE_FLOAT: if empty columnSql { let columnSql .= "FLOAT"; } + let columnSql .= this->checkColumnSizeAndScale(column) . this->checkColumnUnsigned(column); + break; case Column::TYPE_INTEGER: if empty columnSql { let columnSql .= "INT"; } + let columnSql .= this->getColumnSize(column) . this->checkColumnUnsigned(column); + break; case Column::TYPE_JSON: if empty columnSql { let columnSql .= "JSON"; } + break; case Column::TYPE_LONGBLOB: if empty columnSql { let columnSql .= "LONGBLOB"; } + break; case Column::TYPE_LONGTEXT: if empty columnSql { let columnSql .= "LONGTEXT"; } + break; case Column::TYPE_MEDIUMBLOB: if empty columnSql { let columnSql .= "MEDIUMBLOB"; } + break; case Column::TYPE_MEDIUMINTEGER: if empty columnSql { let columnSql .= "MEDIUMINT"; } + let columnSql .= this->getColumnSize(column) . this->checkColumnUnsigned(column); + break; case Column::TYPE_MEDIUMTEXT: if empty columnSql { let columnSql .= "MEDIUMTEXT"; } + break; case Column::TYPE_SMALLINTEGER: if empty columnSql { let columnSql .= "SMALLINT"; } + let columnSql .= this->getColumnSize(column) . this->checkColumnUnsigned(column); + break; case Column::TYPE_TEXT: if empty columnSql { let columnSql .= "TEXT"; } + break; case Column::TYPE_TIME: if empty columnSql { let columnSql .= "TIME"; } + break; case Column::TYPE_TIMESTAMP: if empty columnSql { let columnSql .= "TIMESTAMP"; } + break; case Column::TYPE_TINYBLOB: if empty columnSql { let columnSql .= "TINYBLOB"; } + break; case Column::TYPE_TINYINTEGER: if empty columnSql { let columnSql .= "TINYINT"; } + let columnSql .= this->getColumnSize(column) . this->checkColumnUnsigned(column); + break; case Column::TYPE_TINYTEXT: if empty columnSql { let columnSql .= "TINYTEXT"; } + break; case Column::TYPE_VARCHAR: if empty columnSql { let columnSql .= "VARCHAR"; } + let columnSql .= this->getColumnSize(column); + break; default: @@ -559,10 +602,13 @@ class Mysql extends Dialect if !empty typeValues { if typeof typeValues == "array" { var value, valueSql; + let valueSql = ""; + for value in typeValues { let valueSql .= "\"" . addcslashes(value, "\"") . "\", "; } + let columnSql .= "(" . substr(valueSql, 0, -2) . ")"; } else { let columnSql .= "(\"" . addcslashes(typeValues, "\"") . "\")"; @@ -595,6 +641,7 @@ class Mysql extends Dialect if schemaName { return "SHOW TABLES FROM `" . schemaName . "`"; } + return "SHOW TABLES"; } @@ -606,6 +653,7 @@ class Mysql extends Dialect if schemaName { return "SELECT `TABLE_NAME` AS view_name FROM `INFORMATION_SCHEMA`.`VIEWS` WHERE `TABLE_SCHEMA` = '" . schemaName . "' ORDER BY view_name"; } + return "SELECT `TABLE_NAME` AS view_name FROM `INFORMATION_SCHEMA`.`VIEWS` WHERE `TABLE_SCHEMA` = DATABASE() ORDER BY view_name"; } @@ -631,6 +679,7 @@ class Mysql extends Dialect if column->hasDefault() { let defaultValue = column->getDefault(); + if memstr(strtoupper(defaultValue), "CURRENT_TIMESTAMP") { let sql .= " DEFAULT CURRENT_TIMESTAMP"; } else { @@ -650,10 +699,12 @@ class Mysql extends Dialect let sql .= " FIRST"; } else { let afterPosition = column->getAfterPosition(); + if afterPosition { let sql .= " AFTER `" . afterPosition . "`"; } } + return sql; } @@ -662,6 +713,7 @@ class Mysql extends Dialect * * * $sql = $dialect->sharedLock("SELECT * FROM robots"); + * * echo $sql; // SELECT * FROM robots LOCK IN SHARE MODE * */ @@ -684,6 +736,7 @@ class Mysql extends Dialect if schemaName { return "SELECT IF(COUNT(*) > 0, 1, 0) FROM `INFORMATION_SCHEMA`.`TABLES` WHERE `TABLE_NAME`= '" . tableName . "' AND `TABLE_SCHEMA` = '" . schemaName . "'"; } + return "SELECT IF(COUNT(*) > 0, 1, 0) FROM `INFORMATION_SCHEMA`.`TABLES` WHERE `TABLE_NAME` = '" . tableName . "' AND `TABLE_SCHEMA` = DATABASE()"; } @@ -693,9 +746,11 @@ class Mysql extends Dialect public function tableOptions(string! table, string schema = null) -> string { var sql = "SELECT TABLES.TABLE_TYPE AS table_type,TABLES.AUTO_INCREMENT AS auto_increment,TABLES.ENGINE AS engine,TABLES.TABLE_COLLATION AS table_collation FROM INFORMATION_SCHEMA.TABLES WHERE "; + if schema { return sql . "TABLES.TABLE_SCHEMA = '" . schema . "' AND TABLES.TABLE_NAME = '" . table . "'"; } + return sql . "TABLES.TABLE_SCHEMA = DATABASE() AND TABLES.TABLE_NAME = '" . table . "'"; } @@ -725,6 +780,7 @@ class Mysql extends Dialect if schemaName { return "SELECT IF(COUNT(*) > 0, 1, 0) FROM `INFORMATION_SCHEMA`.`VIEWS` WHERE `TABLE_NAME`= '" . viewName . "' AND `TABLE_SCHEMA`='" . schemaName . "'"; } + return "SELECT IF(COUNT(*) > 0, 1, 0) FROM `INFORMATION_SCHEMA`.`VIEWS` WHERE `TABLE_NAME`='" . viewName . "' AND `TABLE_SCHEMA` = DATABASE()"; } @@ -733,8 +789,8 @@ class Mysql extends Dialect */ protected function getTableOptions(array! definition) -> string { - var options, engine, autoIncrement, tableCollation, - collationParts, tableOptions; + var options, engine, autoIncrement, tableCollation, collationParts, + tableOptions; if fetch options, definition["options"] { @@ -787,6 +843,7 @@ class Mysql extends Dialect if column->getSize() { let columnSql .= "(" . column->getSize(); + if column->getScale() { let columnSql .= "," . column->getScale() . ")"; } else { diff --git a/phalcon/Db/Dialect/Postgresql.zep b/phalcon/Db/Dialect/Postgresql.zep index ec08dcf04a1..6d91fb165cb 100644 --- a/phalcon/Db/Dialect/Postgresql.zep +++ b/phalcon/Db/Dialect/Postgresql.zep @@ -97,6 +97,7 @@ class Postgresql extends Dialect let sql .= " INDEX \"" . index->getName() . "\" ON " . this->prepareTable(tableName, schemaName); let sql .= " (" . this->getColumnList(index->getColumns()) . ")"; + return sql; } @@ -113,11 +114,10 @@ class Postgresql extends Dialect */ public function createTable(string! tableName, string! schemaName, array! definition) -> string { - var temporary, options, table, createLines, columns, - column, indexes, index, reference, references, indexName, - indexSql, indexSqlAfterCreate, sql, columnLine, indexType, - referenceSql, onDelete, onUpdate, primaryColumns, - columnDefinition; + var temporary, options, table, createLines, columns, column, indexes, + index, reference, references, indexName, indexSql, + indexSqlAfterCreate, sql, columnLine, indexType, referenceSql, + onDelete, onUpdate, primaryColumns, columnDefinition; if !fetch columns, definition["columns"] { throw new Exception( @@ -171,6 +171,7 @@ class Postgresql extends Dialect let createLines[] = columnLine; } + if !empty primaryColumns { let createLines[] = "PRIMARY KEY (" . this->getColumnList(primaryColumns) . ")"; } @@ -196,17 +197,18 @@ class Postgresql extends Dialect if !empty indexType { let indexSql = "CONSTRAINT \"" . indexName . "\" " . indexType . " (" . this->getColumnList(index->getColumns()) . ")"; } else { - let indexSqlAfterCreate .= "CREATE INDEX \"" . index->getName() . "\" ON " . this->prepareTable(tableName, schemaName); let indexSqlAfterCreate .= " (" . this->getColumnList(index->getColumns()) . ");"; } } + if !empty indexSql { let createLines[] = indexSql; } } } + /** * Create related references */ @@ -387,25 +389,30 @@ class Postgresql extends Dialect let columnSql .= "BIGINT"; } } + break; case Column::TYPE_BOOLEAN: if empty columnSql { let columnSql .= "BOOLEAN"; } + break; case Column::TYPE_CHAR: if empty columnSql { let columnSql .= "CHARACTER"; } + let columnSql .= this->getColumnSize(column); + break; case Column::TYPE_DATE: if empty columnSql { let columnSql .= "DATE"; } + break; case Column::TYPE_DATETIME: @@ -418,13 +425,16 @@ class Postgresql extends Dialect if empty columnSql { let columnSql .= "NUMERIC"; } + let columnSql .= this->getColumnSizeAndScale(column); + break; case Column::TYPE_FLOAT: if empty columnSql { let columnSql .= "FLOAT"; } + break; case Column::TYPE_INTEGER: @@ -435,39 +445,45 @@ class Postgresql extends Dialect let columnSql .= "INT"; } } + break; case Column::TYPE_JSON: if empty columnSql { let columnSql .= "JSON"; } + break; case Column::TYPE_JSONB: if empty columnSql { let columnSql .= "JSONB"; } + break; case Column::TYPE_TIMESTAMP: if empty columnSql { let columnSql .= "TIMESTAMP"; } + break; case Column::TYPE_TEXT: if empty columnSql { let columnSql .= "TEXT"; } + break; case Column::TYPE_VARCHAR: if empty columnSql { let columnSql .= "CHARACTER VARYING"; } + let columnSql .= this->getColumnSize(column); - break; + break; default: if empty columnSql { @@ -480,10 +496,13 @@ class Postgresql extends Dialect if !empty typeValues { if typeof typeValues == "array" { var value, valueSql; + let valueSql = ""; + for value in typeValues { let valueSql .= "'" . addcslashes(value, "\'") . "', "; } + let columnSql .= "(" . substr(valueSql, 0, -2) . ")"; } else { let columnSql .= "('" . addcslashes(typeValues, "\'") . "')"; @@ -565,6 +584,7 @@ class Postgresql extends Dialect if column->hasDefault() { let defaultValue = this->castDefault(column); + if memstr(strtoupper(columnDefinition), "BOOLEAN") { let sql .= " ALTER COLUMN \"" . column->getName() . "\" SET DEFAULT " . defaultValue; } else { @@ -576,7 +596,6 @@ class Postgresql extends Dialect return sql; } - /** * Returns a SQL modified a shared lock statement. For now this method * returns the original query diff --git a/phalcon/Db/Dialect/Sqlite.zep b/phalcon/Db/Dialect/Sqlite.zep index 00cab0385c1..cc5c0186088 100644 --- a/phalcon/Db/Dialect/Sqlite.zep +++ b/phalcon/Db/Dialect/Sqlite.zep @@ -40,6 +40,7 @@ class Sqlite extends Dialect if column->hasDefault() { let defaultValue = column->getDefault(); + if memstr(strtoupper(defaultValue), "CURRENT_TIMESTAMP") { let sql .= " DEFAULT CURRENT_TIMESTAMP"; } else { @@ -90,6 +91,7 @@ class Sqlite extends Dialect } let sql .= this->getColumnList(index->getColumns()) . ")"; + return sql; } @@ -160,6 +162,7 @@ class Sqlite extends Dialect */ if column->hasDefault() { let defaultValue = column->getDefault(); + if memstr(strtoupper(defaultValue), "CURRENT_TIMESTAMP") { let columnLine .= " DEFAULT CURRENT_TIMESTAMP"; } else { @@ -305,6 +308,7 @@ class Sqlite extends Dialect if schemaName { return "DROP INDEX \"" . schemaName . "\".\"" . indexName . "\""; } + return "DROP INDEX \"" . indexName . "\""; } @@ -348,6 +352,7 @@ class Sqlite extends Dialect if ifExists { return "DROP VIEW IF EXISTS " . view; } + return "DROP VIEW " . view; } @@ -379,105 +384,126 @@ class Sqlite extends Dialect if empty columnSql { let columnSql .= "BIGINT"; } + if column->isUnsigned() { let columnSql .= " UNSIGNED"; } + break; case Column::TYPE_BLOB: if empty columnSql { let columnSql .= "BLOB"; } + break; case Column::TYPE_BOOLEAN: if empty columnSql { let columnSql .= "TINYINT"; } + break; case Column::TYPE_CHAR: if empty columnSql { let columnSql .= "CHARACTER"; } + let columnSql .= this->getColumnSize(column); + break; case Column::TYPE_DATE: if empty columnSql { let columnSql .= "DATE"; } + break; case Column::TYPE_DATETIME: if empty columnSql { let columnSql .= "DATETIME"; } + break; case Column::TYPE_DECIMAL: if empty columnSql { let columnSql .= "NUMERIC"; } + let columnSql .= this->getColumnSizeAndScale(column); + break; case Column::TYPE_DOUBLE: if empty columnSql { let columnSql .= "DOUBLE"; } + if column->isUnsigned() { let columnSql .= " UNSIGNED"; } + break; case Column::TYPE_FLOAT: if empty columnSql { let columnSql .= "FLOAT"; } + break; case Column::TYPE_INTEGER: if empty columnSql { let columnSql .= "INTEGER"; } + break; case Column::TYPE_LONGBLOB: if empty columnSql { let columnSql .= "LONGBLOB"; } + break; case Column::TYPE_MEDIUMBLOB: if empty columnSql { let columnSql .= "MEDIUMBLOB"; } + break; case Column::TYPE_TEXT: if empty columnSql { let columnSql .= "TEXT"; } + break; case Column::TYPE_TIMESTAMP: if empty columnSql { let columnSql .= "TIMESTAMP"; } + break; case Column::TYPE_TINYBLOB: if empty columnSql { let columnSql .= "TINYBLOB"; } + break; case Column::TYPE_VARCHAR: if empty columnSql { let columnSql .= "VARCHAR"; } + let columnSql .= this->getColumnSize(column); + break; default: @@ -491,10 +517,13 @@ class Sqlite extends Dialect if !empty typeValues { if typeof typeValues == "array" { var value, valueSql; + let valueSql = ""; + for value in typeValues { let valueSql .= "\"" . addcslashes(value, "\"") . "\", "; } + let columnSql .= "(" . substr(valueSql, 0, -2) . ")"; } else { let columnSql .= "(\"" . addcslashes(typeValues, "\"") . "\")"; diff --git a/phalcon/Db/Index.zep b/phalcon/Db/Index.zep index 0695e3cf01f..d57f8cebd66 100644 --- a/phalcon/Db/Index.zep +++ b/phalcon/Db/Index.zep @@ -23,7 +23,7 @@ namespace Phalcon\Db; * 'column_UNIQUE', * [ * 'column', - * 'column' + * 'column', * ], * 'UNIQUE' * ); @@ -32,7 +32,7 @@ namespace Phalcon\Db; * $index_primary = new \Phalcon\Db\Index( * 'PRIMARY', * [ - * 'column' + * 'column', * ] * ); * diff --git a/phalcon/Db/Profiler.zep b/phalcon/Db/Profiler.zep index 0536e887915..ecaa6609370 100644 --- a/phalcon/Db/Profiler.zep +++ b/phalcon/Db/Profiler.zep @@ -126,6 +126,7 @@ class Profiler public function reset() -> { let this->allProfiles = []; + return this; } diff --git a/phalcon/Db/Reference.zep b/phalcon/Db/Reference.zep index 147754d4e4c..1a0005b39a1 100644 --- a/phalcon/Db/Reference.zep +++ b/phalcon/Db/Reference.zep @@ -149,9 +149,8 @@ class Reference implements ReferenceInterface */ public static function __set_state(array! data) -> { - var referencedSchema, referencedTable, columns, - referencedColumns, constraintName, - onDelete, onUpdate; + var referencedSchema, referencedTable, columns, referencedColumns, + constraintName, onDelete, onUpdate; if !fetch constraintName, data["referenceName"] { if !fetch constraintName, data["name"] { diff --git a/phalcon/Db/Result/Pdo.zep b/phalcon/Db/Result/Pdo.zep index 77b27f930f8..225da4f2fd5 100644 --- a/phalcon/Db/Result/Pdo.zep +++ b/phalcon/Db/Result/Pdo.zep @@ -112,6 +112,7 @@ class Pdo implements ResultInterface */ if typeof bindParams == "array" { let statement = pdo->prepare(sqlStatement); + if typeof statement == "object" { let statement = connection->executePrepared( statement, @@ -125,9 +126,12 @@ class Pdo implements ResultInterface let this->pdoStatement = statement; - let n = -1, number--; + let n = -1, + number--; + while n != number { statement->$fetch(); + let n++; } } @@ -250,12 +254,12 @@ class Pdo implements ResultInterface */ public function numRows() -> int { - var sqlStatement, rowCount, connection, type, - pdoStatement, matches, result, row; + var sqlStatement, rowCount, connection, type, pdoStatement, matches, + result, row; let rowCount = this->rowCount; - if rowCount === false { + if rowCount === false { let connection = this->connection, type = connection->getType(); @@ -271,7 +275,6 @@ class Pdo implements ResultInterface * We should get the count using a new statement :( */ if rowCount === false { - /** * SQLite/SQLServer returns resultsets that to the client eyes * (PDO) has an arbitrary number of rows, so we need to perform @@ -284,8 +287,8 @@ class Pdo implements ResultInterface * make the count */ if !starts_with(sqlStatement, "SELECT COUNT(*) ") { - let matches = null; + if preg_match("/^SELECT\\s+(.*)/i", sqlStatement, matches) { let result = connection->query( "SELECT COUNT(*) \"numrows\" FROM (SELECT " . matches[1] . ")", @@ -306,6 +309,7 @@ class Pdo implements ResultInterface */ let this->rowCount = rowCount; } + return rowCount; } diff --git a/phalcon/Debug.zep b/phalcon/Debug.zep index 2a8c3644df2..1796288f9bb 100644 --- a/phalcon/Debug.zep +++ b/phalcon/Debug.zep @@ -62,6 +62,7 @@ class Debug public function clearVars() -> { let this->data = null; + return this; } @@ -70,7 +71,12 @@ class Debug */ public function debugVar(varz, string key = null) -> { - let this->data[] = [varz, debug_backtrace(), time()]; + let this->data[] = [ + varz, + debug_backtrace(), + time() + ]; + return this; } @@ -82,9 +88,11 @@ class Debug var uri, sources; let uri = this->uri; + let sources = ""; let sources .= ""; let sources .= ""; + return sources; } @@ -96,11 +104,13 @@ class Debug var uri, sources; let uri = this->uri; + let sources = ""; let sources .= ""; let sources .= ""; let sources .= ""; let sources .= ""; + return sources; } @@ -137,9 +147,11 @@ class Debug if exceptions { this->listenExceptions(); } + if lowSeverity { this->listenLowSeverity(); } + return this; } @@ -148,7 +160,10 @@ class Debug */ public function listenExceptions() -> { - set_exception_handler([this, "onUncaughtException"]); + set_exception_handler( + [this, "onUncaughtException"] + ); + return this; } @@ -157,8 +172,14 @@ class Debug */ public function listenLowSeverity() -> { - set_error_handler([this, "onUncaughtLowSeverity"]); - set_exception_handler([this, "onUncaughtException"]); + set_error_handler( + [this, "onUncaughtLowSeverity"] + ); + + set_exception_handler( + [this, "onUncaughtException"] + ); + return this; } @@ -185,6 +206,7 @@ class Debug */ if self::isActive { echo exception->getMessage(); + return; } @@ -228,7 +250,6 @@ class Debug * Check if the developer wants to show the backtrace or not */ if showBackTrace { - let dataVars = this->data; /** @@ -240,21 +261,25 @@ class Debug let html .= "
  • Server
  • "; let html .= "
  • Included Files
  • "; let html .= "
  • Memory
  • "; + if typeof dataVars == "array" { let html .= "
  • Variables
  • "; } + let html .= ""; /** * Print backtrace */ let html .= "
    "; + for n, traceItem in exception->getTrace() { /** * Every line in the trace is rendered using "showTraceItem" */ let html .= this->showTraceItem(n, traceItem); } + let html .= "
    "; /** @@ -263,6 +288,7 @@ class Debug let html .= "
    "; let html .= ""; let blacklist = Arr::get(this->blacklist, "request", []); + for keyRequest, value in _REQUEST { if true !== isset(blacklist[strtolower(keyRequest)]) { if typeof value != "array" { @@ -272,6 +298,7 @@ class Debug } } } + let html .= "
    KeyValue
    "; /** @@ -280,11 +307,13 @@ class Debug let html .= "
    "; let html .= ""; let blacklist = Arr::get(this->blacklist, "server", []); + for keyServer, value in _SERVER { if true !== isset(blacklist[strtolower(keyServer)]) { let html .= ""; } } + let html .= "
    KeyValue
    " . keyServer . "" . this->getVarDump(value) . "
    "; /** @@ -292,9 +321,11 @@ class Debug */ let html .= "
    "; let html .= ""; + for keyFile, value in get_included_files() { let html .= ""; } + let html .= "
    #Path
    " . keyFile . "" . value . "
    "; /** @@ -310,9 +341,11 @@ class Debug if typeof dataVars == "array" { let html .= "
    "; let html .= ""; + for keyVar, dataVar in dataVars { let html .= ""; } + let html .= "
    KeyValue
    " . keyVar . "" . this->getVarDump(dataVar[0]) . "
    "; } @@ -384,6 +417,7 @@ class Debug public function setShowBackTrace(bool showBackTrace) -> { let this->showBackTrace = showBackTrace; + return this; } @@ -394,6 +428,7 @@ class Debug public function setShowFileFragment(bool showFileFragment) -> { let this->showFileFragment = showFileFragment; + return this; } @@ -403,6 +438,7 @@ class Debug public function setShowFiles(bool showFiles) -> { let this->showFiles = showFiles; + return this; } @@ -412,6 +448,7 @@ class Debug public function setUri(string! uri) -> { let this->uri = uri; + return this; } @@ -449,8 +486,8 @@ class Debug } let dump = []; - for k, v in argument { + for k, v in argument { if v == "" { let varDump = "(empty string)"; } elseif is_scalar(v) { @@ -478,29 +515,25 @@ class Debug { var className, dumpedObject; - if is_scalar(variable) { + if variable == true { + return "true"; + } - /** - * Boolean variables are represented as "true"/"false" - */ - if typeof variable == "boolean" { - if variable { - return "true"; - } else { - return "false"; - } - } + if variable === false { + return "false"; + } - /** - * String variables are escaped to avoid XSS injections - */ - if typeof variable == "string" { - return this->escapeString(variable); - } + /** + * String variables are escaped to avoid XSS injections + */ + if typeof variable == "string" { + return this->escapeString(variable); + } - /** - * Other scalar variables are just converted to strings - */ + /** + * Scalar variables are just converted to strings + */ + if is_scalar(variable) { return variable; } @@ -569,13 +602,11 @@ class Debug let html = "#" . n . ""; if fetch className, trace["class"] { - /** * We assume that classes starting by Phalcon are framework's * classes */ if preg_match("/^Phalcon/", className) { - /** * Prepare the class name according to the Phalcon's conventions */ @@ -586,14 +617,12 @@ class Debug */ let classNameWithLink = "" . className . ""; } else { - let classReflection = new \ReflectionClass(className); /** * Check if classes are PHP's classes */ if classReflection->isInternal() { - let prepareInternalClass = str_replace( "_", "-", @@ -621,15 +650,14 @@ class Debug * Normally the backtrace contains only classes */ let functionName = trace["function"]; + if isset trace["class"] { let functionNameWithLink = functionName; } else { - /** * Check if the function exists */ if function_exists(functionName) { - let functionReflection = new \ReflectionFunction(functionName); /** @@ -660,10 +688,9 @@ class Debug * Check for arguments in the function */ if fetch traceArgs, trace["args"] { - let arguments = []; - for argument in traceArgs { + for argument in traceArgs { /** * Every argument is generated using getVarDump * Append the HTML generated to the argument's list @@ -682,7 +709,6 @@ class Debug * the user */ if fetch filez, trace["file"] { - let line = (string) trace["line"]; /** @@ -696,7 +722,6 @@ class Debug * The developer can change if the files must be opened or not */ if showFiles { - /** * Open the file to an array using "file", this respects the * openbase-dir directive @@ -747,8 +772,8 @@ class Debug } let i = firstLine; - while i <= lastLine { + while i <= lastLine { /** * Current line in the file */ @@ -794,6 +819,7 @@ class Debug let i++; } + let html .= ""; } } diff --git a/phalcon/Debug/Dump.zep b/phalcon/Debug/Dump.zep index 35de0b067bc..a9bd8f20fce 100644 --- a/phalcon/Debug/Dump.zep +++ b/phalcon/Debug/Dump.zep @@ -108,6 +108,7 @@ class Dump ]; let this->styles = array_merge(defaultStyles, styles); + return this->styles; } @@ -144,10 +145,13 @@ class Dump */ public function variable(var variable, string name = null) -> string { - return strtr("
    :output
    ", [ - ":style": this->getStyle("pre"), - ":output": this->output(variable, name) - ]); + return strtr( + "
    :output
    ", + [ + ":style": this->getStyle("pre"), + ":output": this->output(variable, name) + ] + ); } /** @@ -170,8 +174,12 @@ class Dump var key, value, output; let output = ""; + for key, value in func_get_args() { - let output .= this->one(value, "var " . key); + let output .= this->one( + value, + "var " . key + ); } return output; @@ -184,11 +192,11 @@ class Dump { var style; - if fetch style, this->styles[type] { - return style; - } else { + if !fetch style, this->styles[type] { return "color:gray"; } + + return style; } /** @@ -197,6 +205,7 @@ class Dump protected function output(var variable, string name = null, int tab = 1) -> string { var key, value, output, space, type, attr; + let space = " ", output = ""; @@ -218,10 +227,11 @@ class Dump if tab == 1 && name != "" && !is_int(key) && name == key { continue; - } else { - let output .= this->output(value, "", tab + 1) . "\n"; } + + let output .= this->output(value, "", tab + 1) . "\n"; } + return output . str_repeat(space, tab - 1) . ")"; } @@ -297,6 +307,7 @@ class Dump let output .= str_repeat(space, tab + 1) . strtr("->:method();\n", [":style": this->getStyle("obj"), ":method": value]); } } + let output .= str_repeat(space, tab) . ")\n"; } diff --git a/phalcon/Debug/Exception.zep b/phalcon/Debug/Exception.zep index abaeb1b2f8f..fa91ce74e56 100644 --- a/phalcon/Debug/Exception.zep +++ b/phalcon/Debug/Exception.zep @@ -14,7 +14,6 @@ namespace Phalcon\Debug; * Phalcon\Debug\Exception * * Exceptions thrown in Phalcon\Debug will use this class - * */ class Exception extends \Phalcon\Exception { diff --git a/phalcon/Di.zep b/phalcon/Di.zep index fdbd0ba7cc0..7cb64f5fd72 100644 --- a/phalcon/Di.zep +++ b/phalcon/Di.zep @@ -123,7 +123,13 @@ class Di implements DiInterface */ if starts_with(method, "set") { if fetch definition, arguments[0] { - this->set(lcfirst(substr(method, 3)), definition); + this->set( + lcfirst( + substr(method, 3) + ), + definition + ); + return null; } } @@ -143,13 +149,13 @@ class Di implements DiInterface */ public function attempt(string! name, definition, bool shared = false) -> | bool { - if !isset this->services[name] { - let this->services[name] = new Service(definition, shared); - - return this->services[name]; + if isset this->services[name] { + return false; } - return false; + let this->services[name] = new Service(definition, shared); + + return this->services[name]; } /** @@ -165,6 +171,7 @@ class Di implements DiInterface */ if fetch service, this->services[name] { let isShared = service->isShared(); + if isShared && isset this->sharedInstances[name] { return this->sharedInstances[name]; } @@ -181,7 +188,7 @@ class Di implements DiInterface "di:beforeServiceResolve", this, [ - "name": name, + "name": name, "parameters": parameters ] ); @@ -189,7 +196,6 @@ class Di implements DiInterface if typeof instance != "object" { if service !== null { - // The service is registered in the DI. try { let instance = service->resolve(parameters, this); @@ -204,7 +210,6 @@ class Di implements DiInterface let this->sharedInstances[name] = instance; } } else { - /** * The DI also acts as builder for any class even if it isn't * defined in the DI @@ -242,9 +247,9 @@ class Di implements DiInterface "di:afterServiceResolve", this, [ - "name": name, + "name": name, "parameters": parameters, - "instance": instance + "instance": instance ] ); } @@ -313,7 +318,6 @@ class Di implements DiInterface * requests for this service will return the same instance * * @param array parameters - * @return mixed */ public function getShared(string! name, parameters = null) -> var { @@ -491,9 +495,12 @@ class Di implements DiInterface * { * public function register(DiInterface $di) * { - * $di->setShared('service', function () { - * // ... - * }); + * $di->setShared( + * 'service', + * function () { + * // ... + * } + * ); * } * } * @@ -554,6 +561,7 @@ class Di implements DiInterface public function setRaw(string! name, rawDefinition) -> { let this->services[name] = rawDefinition; + return rawDefinition; } diff --git a/phalcon/Di/Exception/ServiceResolutionException.zep b/phalcon/Di/Exception/ServiceResolutionException.zep index 584b7d505b0..d851797d30a 100644 --- a/phalcon/Di/Exception/ServiceResolutionException.zep +++ b/phalcon/Di/Exception/ServiceResolutionException.zep @@ -14,7 +14,6 @@ /** * Phalcon\Di\Exception\ServiceResolutionException - * */ class ServiceResolutionException extends \Phalcon\Di\Exception { diff --git a/phalcon/Di/Injectable.zep b/phalcon/Di/Injectable.zep index da09a7c6cbb..68068d6956f 100644 --- a/phalcon/Di/Injectable.zep +++ b/phalcon/Di/Injectable.zep @@ -73,8 +73,10 @@ abstract class Injectable implements InjectionAwareInterface, EventsAwareInterfa var container, service, persistent; let container = this->container; + if typeof container != "object" { let container = \Phalcon\Di::getDefault(); + if typeof container != "object" { throw new Exception( Exception::containerServiceNotFound("internal services") @@ -88,11 +90,13 @@ abstract class Injectable implements InjectionAwareInterface, EventsAwareInterfa if container->has(propertyName) { let service = container->getShared(propertyName); let this->{propertyName} = service; + return service; } if propertyName == "di" { let this->{"di"} = container; + return container; } @@ -102,6 +106,7 @@ abstract class Injectable implements InjectionAwareInterface, EventsAwareInterfa if propertyName == "persistent" { let persistent = container->get("sessionBag", [get_class(this)]), this->{"persistent"} = persistent; + return persistent; } @@ -109,6 +114,7 @@ abstract class Injectable implements InjectionAwareInterface, EventsAwareInterfa * A notice is shown if the property is not defined and isn't a valid service */ trigger_error("Access to undefined property " . propertyName); + return null; } @@ -120,9 +126,11 @@ abstract class Injectable implements InjectionAwareInterface, EventsAwareInterfa var container; let container = this->container; + if typeof container != "object" { let container = Di::getDefault(); } + return container; } diff --git a/phalcon/Di/Service/Builder.zep b/phalcon/Di/Service/Builder.zep index 8b661a7761a..92b2e806f05 100644 --- a/phalcon/Di/Service/Builder.zep +++ b/phalcon/Di/Service/Builder.zep @@ -127,7 +127,6 @@ class Builder } if count(arguments) { - /** * Call the method on the instance */ diff --git a/phalcon/Di/ServiceProviderInterface.zep b/phalcon/Di/ServiceProviderInterface.zep index 4fd4868c66e..c144604bde0 100644 --- a/phalcon/Di/ServiceProviderInterface.zep +++ b/phalcon/Di/ServiceProviderInterface.zep @@ -28,9 +28,12 @@ use Phalcon\DiInterface; * { * public function register(DiInterface $di) * { - * $di->setShared('service', function () { - * // ... - * }); + * $di->setShared( + * 'service', + * function () { + * // ... + * } + * ); * } * } * diff --git a/phalcon/Dispatcher.zep b/phalcon/Dispatcher.zep index df4b66a605a..e82bbb432cd 100644 --- a/phalcon/Dispatcher.zep +++ b/phalcon/Dispatcher.zep @@ -117,7 +117,10 @@ abstract class Dispatcher implements DispatcherInterface, InjectionAwareInterfac public function callActionMethod(handler, string actionMethod, array! params = []) { - return call_user_func_array([handler, actionMethod], params); + return call_user_func_array( + [handler, actionMethod], + params + ); } /** @@ -134,13 +137,12 @@ abstract class Dispatcher implements DispatcherInterface, InjectionAwareInterfac { bool hasService, hasEventsManager; int numberDispatches; - var value, handler, container, namespaceName, handlerName, - actionName, params, eventsManager, - handlerClass, status, actionMethod, - modelBinder, bindCacheKey, - isNewHandler, handlerHash, e; + var value, handler, container, namespaceName, handlerName, actionName, + params, eventsManager, handlerClass, status, actionMethod, + modelBinder, bindCacheKey, isNewHandler, handlerHash, e; let container = this->container; + if typeof container != "object" { this->{"throwDispatchException"}( PhalconException::containerServiceNotFound( @@ -148,6 +150,7 @@ abstract class Dispatcher implements DispatcherInterface, InjectionAwareInterfac ), self::EXCEPTION_NO_DI ); + return false; } @@ -180,6 +183,7 @@ abstract class Dispatcher implements DispatcherInterface, InjectionAwareInterfac */ let status = this->{"handleException"}(e); + if this->finished !== false { // No forwarding if status === false { @@ -214,6 +218,7 @@ abstract class Dispatcher implements DispatcherInterface, InjectionAwareInterfac } let this->finished = true; + this->resolveEmptyProperties(); if hasEventsManager { @@ -238,6 +243,7 @@ abstract class Dispatcher implements DispatcherInterface, InjectionAwareInterfac * Container */ let hasService = (bool) container->has(handlerClass); + if !hasService { /** * DI doesn't have a service with that name, try to load it @@ -256,6 +262,7 @@ abstract class Dispatcher implements DispatcherInterface, InjectionAwareInterfac if status === false && this->finished === false { continue; } + break; } @@ -271,12 +278,15 @@ abstract class Dispatcher implements DispatcherInterface, InjectionAwareInterfac if status === false && this->finished === false { continue; } + break; } // Check if the handler is new (hasn't been initialized). let handlerHash = spl_object_hash(handler); + let isNewHandler = !(isset this->handlerHashes[handlerHash]); + if isNewHandler { let this->handlerHashes[handlerHash] = true; } @@ -303,6 +313,7 @@ abstract class Dispatcher implements DispatcherInterface, InjectionAwareInterfac if status === false && this->finished === false { continue; } + break; } @@ -358,6 +369,7 @@ abstract class Dispatcher implements DispatcherInterface, InjectionAwareInterfac } catch Exception, e { if this->{"handleException"}(e) === false || this->finished === false { container->remove(handlerClass); + continue; } @@ -370,11 +382,13 @@ abstract class Dispatcher implements DispatcherInterface, InjectionAwareInterfac // Calling "beforeExecuteRoute" as direct method if handler->beforeExecuteRoute(this) === false || this->finished === false { container->remove(handlerClass); + continue; } } catch Exception, e { if this->{"handleException"}(e) === false || this->finished === false { container->remove(handlerClass); + continue; } @@ -385,7 +399,6 @@ abstract class Dispatcher implements DispatcherInterface, InjectionAwareInterfac /** * Call the "initialize" method just once per request * - * * Note: The `dispatch:afterInitialize` event is called regardless * of the presence of an `initialize()` method. The naming is * poor; however, the intent is for a more global "constructor @@ -404,8 +417,8 @@ abstract class Dispatcher implements DispatcherInterface, InjectionAwareInterfac if method_exists(handler, "initialize") { try { let this->isControllerInitialize = true; - handler->initialize(); + handler->initialize(); } catch Exception, e { let this->isControllerInitialize = false; @@ -706,11 +719,11 @@ abstract class Dispatcher implements DispatcherInterface, InjectionAwareInterfac let modelBinder = this->modelBinder; - if modelBinder != null { - return modelBinder->getBoundModels(); + if modelBinder == null { + return []; } - return []; + return modelBinder->getBoundModels(); } /** @@ -782,6 +795,7 @@ abstract class Dispatcher implements DispatcherInterface, InjectionAwareInterfac var params, filter, paramValue, container; let params = this->params; + if !fetch paramValue, params[param] { return defaultValue; } @@ -791,6 +805,7 @@ abstract class Dispatcher implements DispatcherInterface, InjectionAwareInterfac } let container = this->container; + if typeof container != "object" { this->{"throwDispatchException"}( PhalconException::containerServiceNotFound( @@ -799,8 +814,10 @@ abstract class Dispatcher implements DispatcherInterface, InjectionAwareInterfac self::EXCEPTION_NO_DI ); } + let filter = container->getShared("filter"); // let filter = container->getShared("filter"); + return filter->sanitize(paramValue, filters); } @@ -867,8 +884,8 @@ abstract class Dispatcher implements DispatcherInterface, InjectionAwareInterfac */ public function getHandlerClass() -> string { - var handlerSuffix, handlerName, namespaceName, - camelizedClass, handlerClass; + var handlerSuffix, handlerName, namespaceName, camelizedClass, + handlerClass; this->resolveEmptyProperties(); @@ -954,7 +971,10 @@ abstract class Dispatcher implements DispatcherInterface, InjectionAwareInterfac * function() { * $dispatcher = new Dispatcher(); * - * $dispatcher->setModelBinder(new Binder(), 'cache'); + * $dispatcher->setModelBinder( + * new Binder(), + * 'cache' + * ); * * return $dispatcher; * } @@ -967,6 +987,7 @@ abstract class Dispatcher implements DispatcherInterface, InjectionAwareInterfac if typeof cache == "string" { let container = this->container; + let cache = container->get(cache); } diff --git a/phalcon/DispatcherInterface.zep b/phalcon/DispatcherInterface.zep index 3751c729db7..399be48f784 100644 --- a/phalcon/DispatcherInterface.zep +++ b/phalcon/DispatcherInterface.zep @@ -19,8 +19,6 @@ interface DispatcherInterface { /** * Dispatches a handle action taking into account the routing parameters - * - * @return object */ public function dispatch() -> object | bool; @@ -48,7 +46,6 @@ interface DispatcherInterface * Gets a param by its name or numeric index * * @param string|array filters - * @return mixed */ public function getParam(var param, filters = null) -> var; diff --git a/phalcon/Escaper.zep b/phalcon/Escaper.zep index 049c6199b7a..4927e93ddbd 100644 --- a/phalcon/Escaper.zep +++ b/phalcon/Escaper.zep @@ -59,6 +59,7 @@ class Escaper implements EscaperInterface * Check if charset is ASCII or ISO-8859-1 */ let charset = phalcon_is_basic_charset(str); + if typeof charset == "string" { return charset; } @@ -96,7 +97,9 @@ class Escaper implements EscaperInterface * Normalize encoding to UTF-32 * Escape the string */ - return phalcon_escape_css(this->normalizeEncoding(css)); + return phalcon_escape_css( + this->normalizeEncoding(css) + ); } /** @@ -109,7 +112,9 @@ class Escaper implements EscaperInterface * Normalize encoding to UTF-32 * Escape the string */ - return phalcon_escape_js(this->normalizeEncoding(js)); + return phalcon_escape_js( + this->normalizeEncoding(js) + ); } /** diff --git a/phalcon/Events/Manager.zep b/phalcon/Events/Manager.zep index c73206ce469..b94faabb386 100644 --- a/phalcon/Events/Manager.zep +++ b/phalcon/Events/Manager.zep @@ -53,7 +53,6 @@ class Manager implements ManagerInterface } if !fetch priorityQueue, this->events[eventType] { - // Create a SplPriorityQueue to store the events with priorities let priorityQueue = new SplPriorityQueue(); @@ -103,12 +102,12 @@ class Manager implements ManagerInterface } if fetch priorityQueue, this->events[eventType] { - /** * SplPriorityQueue doesn't have a method for element deletion so we * need to rebuild queue */ let newPriorityQueue = new SplPriorityQueue(); + newPriorityQueue->setExtractFlags(SplPriorityQueue::EXTR_DATA); priorityQueue->setExtractFlags(SplPriorityQueue::EXTR_BOTH); @@ -116,9 +115,14 @@ class Manager implements ManagerInterface while priorityQueue->valid() { let data = priorityQueue->current(); + priorityQueue->next(); + if data["data"] !== handler { - newPriorityQueue->insert(data["data"], data["priority"]); + newPriorityQueue->insert( + data["data"], + data["priority"] + ); } } @@ -189,9 +193,7 @@ class Manager implements ManagerInterface // Check if events are grouped by type if fetch fireEvents, events[type] { - if typeof fireEvents == "object" { - // Create the event context let event = new Event(eventName, source, data, cancelable); @@ -202,9 +204,7 @@ class Manager implements ManagerInterface // Check if there are listeners for the event type itself if fetch fireEvents, events[eventType] { - if typeof fireEvents == "object" { - // Create the event if it wasn't created before if event === null { let event = new Event(eventName, source, data, cancelable); @@ -258,14 +258,13 @@ class Manager implements ManagerInterface // Get the current data let handler = iterator->current(); + iterator->next(); // Only handler objects are valid if typeof handler == "object" { - // Check if the event is a closure if handler instanceof \Closure { - // Create the closure arguments if arguments === null { let arguments = [event, source, data]; @@ -280,18 +279,14 @@ class Manager implements ManagerInterface } if cancelable { - // Check if the event was stopped by the user if event->isStopped() { break; } } - } else { - // Check if the listener has implemented an event with the same name if method_exists(handler, eventName) { - // Call the function in the PHP userland let status = handler->{eventName}(event, source, data); @@ -301,7 +296,6 @@ class Manager implements ManagerInterface } if cancelable { - // Check if the event was stopped by the user if event->isStopped() { break; diff --git a/phalcon/Factory.zep b/phalcon/Factory.zep index 68d370ecde3..cbb14201e77 100644 --- a/phalcon/Factory.zep +++ b/phalcon/Factory.zep @@ -31,6 +31,7 @@ abstract class Factory implements FactoryInterface if fetch adapter, config["adapter"] { unset config["adapter"]; + let className = namespaceClass . "\\" . adapter; return new {className}(config); diff --git a/phalcon/Filter/Exception.zep b/phalcon/Filter/Exception.zep index 6d11caf54b8..02f3e759e09 100644 --- a/phalcon/Filter/Exception.zep +++ b/phalcon/Filter/Exception.zep @@ -14,7 +14,6 @@ namespace Phalcon\Filter; * Phalcon\Filter\Exception * * Exceptions thrown in Phalcon\Filter will use this class - * */ class Exception extends \Phalcon\Exception { diff --git a/phalcon/Filter/FilterLocator.zep b/phalcon/Filter/FilterLocator.zep index 9b760c38d40..bbd003aa392 100644 --- a/phalcon/Filter/FilterLocator.zep +++ b/phalcon/Filter/FilterLocator.zep @@ -77,9 +77,9 @@ class FilterLocator extends Locator * The above should produce "-had-a-little-lamb" */ - /** - * Filter is an array - */ + /** + * Filter is an array + */ if typeof sanitizers == "array" { /** * Null value - return immediately @@ -146,6 +146,7 @@ class FilterLocator extends Locator var arrayValue, itemKey, itemValue; let arrayValue = []; + for itemKey, itemValue in values { let arrayValue[itemKey] = this->sanitizer( itemValue, diff --git a/phalcon/Filter/Sanitize/AbsInt.zep b/phalcon/Filter/Sanitize/AbsInt.zep index a5be94c399b..e12a1a27bf9 100644 --- a/phalcon/Filter/Sanitize/AbsInt.zep +++ b/phalcon/Filter/Sanitize/AbsInt.zep @@ -22,6 +22,10 @@ class AbsInt */ public function __invoke(var input) { - return abs(intval(filter_var(input, FILTER_SANITIZE_NUMBER_INT))); + return abs( + intval( + filter_var(input, FILTER_SANITIZE_NUMBER_INT) + ) + ); } } diff --git a/phalcon/Filter/Sanitize/Email.zep b/phalcon/Filter/Sanitize/Email.zep index 299d92a753d..e60c6d056c9 100644 --- a/phalcon/Filter/Sanitize/Email.zep +++ b/phalcon/Filter/Sanitize/Email.zep @@ -22,6 +22,10 @@ class Email */ public function __invoke(var input) { - return filter_var(input, FILTER_SANITIZE_EMAIL, FILTER_FLAG_EMAIL_UNICODE); + return filter_var( + input, + FILTER_SANITIZE_EMAIL, + FILTER_FLAG_EMAIL_UNICODE + ); } } diff --git a/phalcon/Filter/Sanitize/Upper.zep b/phalcon/Filter/Sanitize/Upper.zep index b2018d2d440..ee03d6dacc4 100644 --- a/phalcon/Filter/Sanitize/Upper.zep +++ b/phalcon/Filter/Sanitize/Upper.zep @@ -26,6 +26,8 @@ class Upper return mb_convert_case(input, MB_CASE_UPPER, "UTF-8"); } - return strtoupper(utf8_decode(input)); + return strtoupper( + utf8_decode(input) + ); } } diff --git a/phalcon/Flash.zep b/phalcon/Flash.zep index 99f89d8f7c4..50a744cc8b0 100644 --- a/phalcon/Flash.zep +++ b/phalcon/Flash.zep @@ -116,6 +116,7 @@ abstract class Flash implements FlashInterface, InjectionAwareInterface public function getDI() -> { var di; + let di = this->container; if typeof di != "object" { @@ -133,6 +134,7 @@ abstract class Flash implements FlashInterface, InjectionAwareInterface var escaper, container; let escaper = this->escaperService; + if typeof escaper != "object" { let container = this->getDI(); @@ -160,6 +162,7 @@ abstract class Flash implements FlashInterface, InjectionAwareInterface public function setAutoescape(bool autoescape) -> { let this->autoescape = autoescape; + return this; } @@ -169,6 +172,7 @@ abstract class Flash implements FlashInterface, InjectionAwareInterface public function setAutomaticHtml(bool automaticHtml) -> { let this->automaticHtml = automaticHtml; + return this; } @@ -178,6 +182,7 @@ abstract class Flash implements FlashInterface, InjectionAwareInterface public function setCssClasses(array! cssClasses) -> { let this->cssClasses = cssClasses; + return this; } @@ -187,6 +192,7 @@ abstract class Flash implements FlashInterface, InjectionAwareInterface public function setCustomTemplate(string! customTemplate) -> { let this->customTemplate = customTemplate; + return this; } @@ -196,6 +202,7 @@ abstract class Flash implements FlashInterface, InjectionAwareInterface public function setDI( container) -> { let this->container = container; + return this; } @@ -205,6 +212,7 @@ abstract class Flash implements FlashInterface, InjectionAwareInterface public function setEscaperService( escaperService) -> { let this->escaperService = escaperService; + return this; } @@ -215,6 +223,7 @@ abstract class Flash implements FlashInterface, InjectionAwareInterface public function setImplicitFlush(bool implicitFlush) -> { let this->implicitFlush = implicitFlush; + return this; } @@ -243,12 +252,11 @@ abstract class Flash implements FlashInterface, InjectionAwareInterface public function outputMessage(string type, var message) { bool implicitFlush; - var content, msg, - htmlMessage, preparedMsg; + var content, msg, htmlMessage, preparedMsg; let implicitFlush = (bool) this->implicitFlush; - if typeof message == "array" { + if typeof message == "array" { /** * We create the message with implicit flush or other */ @@ -285,7 +293,6 @@ abstract class Flash implements FlashInterface, InjectionAwareInterface if !implicitFlush { return content; } - } else { /** * Check if the message needs to be escaped @@ -305,6 +312,7 @@ abstract class Flash implements FlashInterface, InjectionAwareInterface echo htmlMessage; } else { let this->messages[] = htmlMessage; + return htmlMessage; } } @@ -325,8 +333,8 @@ abstract class Flash implements FlashInterface, InjectionAwareInterface private function getTemplate(string cssClassses) -> string { - if ("" === this->customTemplate) { - if ("" === cssClassses) { + if "" === this->customTemplate { + if "" === cssClassses { return "
    %message%
    " . PHP_EOL; } else { return "
    %message%
    " . PHP_EOL; @@ -370,6 +378,7 @@ abstract class Flash implements FlashInterface, InjectionAwareInterface } let classes = this->cssClasses; + if fetch typeClasses, classes[type] { if typeof typeClasses == "array" { let cssClasses = join(" ", typeClasses); diff --git a/phalcon/Flash/Exception.zep b/phalcon/Flash/Exception.zep index 5f2b3188db8..5eb4e29fc26 100644 --- a/phalcon/Flash/Exception.zep +++ b/phalcon/Flash/Exception.zep @@ -14,7 +14,6 @@ namespace Phalcon\Flash; * Phalcon\Flash\Exception * * Exceptions thrown in Phalcon\Flash will use this class - * */ class Exception extends \Phalcon\Exception { diff --git a/phalcon/Flash/Session.zep b/phalcon/Flash/Session.zep index 967a0134ca2..0d9ac9f332f 100644 --- a/phalcon/Flash/Session.zep +++ b/phalcon/Flash/Session.zep @@ -133,6 +133,7 @@ class Session extends FlashBase session = container->getShared("session"); session->set("_flashMessages", messages); + return messages; } } diff --git a/phalcon/Forms/Element.zep b/phalcon/Forms/Element.zep index 19f1738d510..dce587b3f3a 100644 --- a/phalcon/Forms/Element.zep +++ b/phalcon/Forms/Element.zep @@ -40,8 +40,8 @@ abstract class Element implements ElementInterface /** * Phalcon\Forms\Element constructor * - * @param string name Attribute name (value of 'name' attribute of HTML element) - * @param array attributes Additional HTML element attributes + * @param string name Attribute name (value of 'name' attribute of HTML element) + * @param array attributes Additional HTML element attributes */ public function __construct(string name, array attributes = []) -> void { @@ -154,11 +154,11 @@ abstract class Element implements ElementInterface let attributes = this->attributes; - if fetch value, attributes[attribute] { - return value; + if !fetch value, attributes[attribute] { + return defaultValue; } - return defaultValue; + return value; } /** @@ -170,10 +170,6 @@ abstract class Element implements ElementInterface let attributes = this->attributes; - if typeof attributes != "array" { - return []; - } - return attributes; } @@ -235,11 +231,11 @@ abstract class Element implements ElementInterface { var value; - if fetch value, this->options[option] { - return value; + if !fetch value, this->options[option] { + return defaultValue; } - return defaultValue; + return value; } /** @@ -316,12 +312,8 @@ abstract class Element implements ElementInterface let name = this->name; } - if typeof attributes == "array" { - if !isset attributes["for"] { - let attributes["for"] = name; - } - } else { - let attributes = ["for": name]; + if !isset attributes["for"] { + let attributes["for"] = name; } let code = Tag::renderAttributes("label; + if label || is_numeric(label) { let code .= ">" . label . ""; } else { @@ -343,36 +336,23 @@ abstract class Element implements ElementInterface * Returns an array of prepared attributes for Phalcon\Tag helpers * according to the element parameters */ - public function prepareAttributes(array attributes = null, bool useChecked = false) -> array + public function prepareAttributes(array attributes = [], bool useChecked = false) -> array { - var value, name, widgetAttributes, mergedAttributes, - defaultAttributes, currentValue; + var value, name, mergedAttributes, defaultAttributes, currentValue; let name = this->name; - /** - * Create an array of parameters - */ - if typeof attributes != "array" { - let widgetAttributes = []; - } else { - let widgetAttributes = attributes; - } - - let widgetAttributes[0] = name; + let attributes[0] = name; /** * Merge passed parameters with default ones */ let defaultAttributes = this->attributes; - if typeof defaultAttributes == "array" { - let mergedAttributes = array_merge( - defaultAttributes, - widgetAttributes - ); - } else { - let mergedAttributes = widgetAttributes; - } + + let mergedAttributes = array_merge( + defaultAttributes, + attributes + ); /** * Get the current element value diff --git a/phalcon/Forms/Element/Check.zep b/phalcon/Forms/Element/Check.zep index a7370523aa1..f060d9160b5 100644 --- a/phalcon/Forms/Element/Check.zep +++ b/phalcon/Forms/Element/Check.zep @@ -20,12 +20,13 @@ use Phalcon\Forms\Element; */ class Check extends Element { - /** * Renders the element widget returning html */ public function render(array attributes = []) -> string { - return Tag::checkField(this->prepareAttributes(attributes, true)); + return Tag::checkField( + this->prepareAttributes(attributes, true) + ); } } diff --git a/phalcon/Forms/Element/Date.zep b/phalcon/Forms/Element/Date.zep index beb6d9325ec..84c7c5c5c6e 100644 --- a/phalcon/Forms/Element/Date.zep +++ b/phalcon/Forms/Element/Date.zep @@ -20,12 +20,13 @@ use Phalcon\Forms\Element; */ class Date extends Element { - /** * Renders the element widget returning html */ public function render(array attributes = []) -> string { - return Tag::dateField(this->prepareAttributes(attributes)); + return Tag::dateField( + this->prepareAttributes(attributes) + ); } } diff --git a/phalcon/Forms/Element/Email.zep b/phalcon/Forms/Element/Email.zep index 1f84f670abb..53d81a874f6 100644 --- a/phalcon/Forms/Element/Email.zep +++ b/phalcon/Forms/Element/Email.zep @@ -20,12 +20,13 @@ use Phalcon\Forms\Element; */ class Email extends Element { - /** * Renders the element widget returning html */ public function render(array attributes = []) -> string { - return Tag::emailField(this->prepareAttributes(attributes)); + return Tag::emailField( + this->prepareAttributes(attributes) + ); } } diff --git a/phalcon/Forms/Element/File.zep b/phalcon/Forms/Element/File.zep index feddce1ce74..42cb865c28b 100644 --- a/phalcon/Forms/Element/File.zep +++ b/phalcon/Forms/Element/File.zep @@ -20,12 +20,13 @@ use Phalcon\Forms\Element; */ class File extends Element { - /** * Renders the element widget returning html */ public function render(array attributes = []) -> string { - return Tag::fileField(this->prepareAttributes(attributes)); + return Tag::fileField( + this->prepareAttributes(attributes) + ); } } diff --git a/phalcon/Forms/Element/Hidden.zep b/phalcon/Forms/Element/Hidden.zep index 6a1b6d377ff..b6208fa36d5 100644 --- a/phalcon/Forms/Element/Hidden.zep +++ b/phalcon/Forms/Element/Hidden.zep @@ -20,12 +20,13 @@ use Phalcon\Forms\Element; */ class Hidden extends Element { - /** * Renders the element widget returning html */ public function render(array attributes = []) -> string { - return Tag::hiddenField(this->prepareAttributes(attributes)); + return Tag::hiddenField( + this->prepareAttributes(attributes) + ); } } diff --git a/phalcon/Forms/Element/Numeric.zep b/phalcon/Forms/Element/Numeric.zep index efc2216264f..db2a6950947 100644 --- a/phalcon/Forms/Element/Numeric.zep +++ b/phalcon/Forms/Element/Numeric.zep @@ -20,12 +20,13 @@ use Phalcon\Forms\Element; */ class Numeric extends Element { - /** * Renders the element widget returning html */ public function render(array attributes = []) -> string { - return Tag::numericField(this->prepareAttributes(attributes)); + return Tag::numericField( + this->prepareAttributes(attributes) + ); } } diff --git a/phalcon/Forms/Element/Password.zep b/phalcon/Forms/Element/Password.zep index 1f89b3df149..a3803d629fe 100644 --- a/phalcon/Forms/Element/Password.zep +++ b/phalcon/Forms/Element/Password.zep @@ -20,12 +20,13 @@ use Phalcon\Forms\Element; */ class Password extends Element { - /** * Renders the element widget returning html */ public function render(array attributes = []) -> string { - return Tag::passwordField(this->prepareAttributes(attributes)); + return Tag::passwordField( + this->prepareAttributes(attributes) + ); } } diff --git a/phalcon/Forms/Element/Radio.zep b/phalcon/Forms/Element/Radio.zep index 36cd10187c9..a6643d1ffd6 100644 --- a/phalcon/Forms/Element/Radio.zep +++ b/phalcon/Forms/Element/Radio.zep @@ -20,12 +20,13 @@ use Phalcon\Forms\Element; */ class Radio extends Element { - /** * Renders the element widget returning html */ public function render(array attributes = []) -> string { - return Tag::radioField(this->prepareAttributes(attributes, true)); + return Tag::radioField( + this->prepareAttributes(attributes, true) + ); } } diff --git a/phalcon/Forms/Element/Select.zep b/phalcon/Forms/Element/Select.zep index 145c5630a54..ffe6c26aab6 100644 --- a/phalcon/Forms/Element/Select.zep +++ b/phalcon/Forms/Element/Select.zep @@ -26,11 +26,12 @@ class Select extends Element * Phalcon\Forms\Element constructor * * @param object|array options - * @param array attributes + * @param array attributes */ public function __construct(string name, options = null, attributes = null) -> void { let this->optionsValues = options; + parent::__construct(name, attributes); } @@ -86,6 +87,7 @@ class Select extends Element public function setOptions(var options) -> { let this->optionsValues = options; + return this; } } diff --git a/phalcon/Forms/Element/Submit.zep b/phalcon/Forms/Element/Submit.zep index 8293cbf97d3..e31eca74371 100644 --- a/phalcon/Forms/Element/Submit.zep +++ b/phalcon/Forms/Element/Submit.zep @@ -20,7 +20,6 @@ use Phalcon\Forms\Element; */ class Submit extends Element { - /** * Renders the element widget */ @@ -29,6 +28,8 @@ class Submit extends Element /** * Merged passed attributes with previously defined ones */ - return Tag::submitButton(this->prepareAttributes(attributes)); + return Tag::submitButton( + this->prepareAttributes(attributes) + ); } } diff --git a/phalcon/Forms/Element/Text.zep b/phalcon/Forms/Element/Text.zep index fa6389dcf7a..fe348bfd53a 100644 --- a/phalcon/Forms/Element/Text.zep +++ b/phalcon/Forms/Element/Text.zep @@ -20,12 +20,13 @@ use Phalcon\Forms\Element; */ class Text extends Element { - /** * Renders the element widget */ public function render(array attributes = []) -> string { - return Tag::textField(this->prepareAttributes(attributes)); + return Tag::textField( + this->prepareAttributes(attributes) + ); } } diff --git a/phalcon/Forms/Element/TextArea.zep b/phalcon/Forms/Element/TextArea.zep index 76206882c5a..3c3c5f3deee 100644 --- a/phalcon/Forms/Element/TextArea.zep +++ b/phalcon/Forms/Element/TextArea.zep @@ -20,12 +20,13 @@ use Phalcon\Forms\Element; */ class TextArea extends Element { - /** * Renders the element widget */ public function render(array attributes = []) -> string { - return Tag::textArea(this->prepareAttributes(attributes)); + return Tag::textArea( + this->prepareAttributes(attributes) + ); } } diff --git a/phalcon/Forms/ElementInterface.zep b/phalcon/Forms/ElementInterface.zep index 5af12685746..af89963563b 100644 --- a/phalcon/Forms/ElementInterface.zep +++ b/phalcon/Forms/ElementInterface.zep @@ -126,7 +126,7 @@ interface ElementInterface * Returns an array of prepared attributes for Phalcon\Tag helpers * according to the element's parameters */ - public function prepareAttributes(array attributes = null, bool useChecked = false) -> array; + public function prepareAttributes(array attributes = [], bool useChecked = false) -> array; /** * Renders the element widget @@ -156,7 +156,6 @@ interface ElementInterface */ public function setFilters(filters) -> ; - /** * Sets the parent form to the element */ diff --git a/phalcon/Forms/Form.zep b/phalcon/Forms/Form.zep index 819a083b1e3..59052a50cdf 100644 --- a/phalcon/Forms/Form.zep +++ b/phalcon/Forms/Form.zep @@ -57,6 +57,7 @@ class Form extends Injectable implements \Countable, \Iterator if typeof entity != "object" { throw new Exception("The base entity is not valid"); } + let this->entity = entity; } @@ -106,12 +107,14 @@ class Form extends Injectable implements \Countable, \Iterator /** * Add the element before position */ - let elements[name] = element, elements[key] = value; + let elements[name] = element, + elements[key] = value; } else { /** * Add the element after position */ - let elements[key] = value, elements[name] = element; + let elements[key] = value, + elements[name] = element; } } else { /** @@ -120,8 +123,10 @@ class Form extends Injectable implements \Countable, \Iterator let elements[key] = value; } } + let this->elements = elements; } + return this; } @@ -165,7 +170,6 @@ class Form extends Injectable implements \Countable, \Iterator let filters = element->getFilters(); if filters { - if typeof filter != "object" { let container = this->getDI(), filter = container->getShared("filter"); @@ -186,6 +190,7 @@ class Form extends Injectable implements \Countable, \Iterator let method = "set" . camelize(key); if method_exists(entity, method) { entity->{method}(filteredValue); + continue; } @@ -210,6 +215,7 @@ class Form extends Injectable implements \Countable, \Iterator var elements, element, data, field; let data = this->data; + if fields === null { let data = []; } else { @@ -280,11 +286,11 @@ class Form extends Injectable implements \Countable, \Iterator { var element; - if fetch element, this->elementsIndexed[this->position] { - return element; + if !fetch element, this->elementsIndexed[this->position] { + return false; } - return false; + return element; } /** @@ -294,13 +300,13 @@ class Form extends Injectable implements \Countable, \Iterator { var element; - if fetch element, this->elements[name] { - return element; + if !fetch element, this->elements[name] { + throw new Exception( + "Element with ID=" . name . " is not part of the form" + ); } - throw new Exception( - "Element with ID=" . name . " is not part of the form" - ); + return element; } /** @@ -389,6 +395,7 @@ class Form extends Injectable implements \Countable, \Iterator */ if unlikely byItemName { let messagesByItem = []; + messages->rewind(); while messages->valid() { @@ -407,8 +414,10 @@ class Form extends Injectable implements \Countable, \Iterator messages->next(); } + return messagesByItem; } + return messages; } @@ -423,6 +432,7 @@ class Form extends Injectable implements \Countable, \Iterator if this->has(name) { return this->get(name)->getMessages(); } + return new Messages(); } @@ -432,10 +442,12 @@ class Form extends Injectable implements \Countable, \Iterator public function getUserOption(string option, var defaultValue = null) -> var { var value; - if fetch value, this->options[option] { - return value; + + if !fetch value, this->options[option] { + return defaultValue; } - return defaultValue; + + return value; } /** @@ -464,7 +476,6 @@ class Form extends Injectable implements \Countable, \Iterator } if typeof entity == "object" { - /** * Check if the entity has a getter */ @@ -482,7 +493,6 @@ class Form extends Injectable implements \Countable, \Iterator } if typeof data == "array" { - /** * Check if the data is in the data array */ @@ -492,18 +502,18 @@ class Form extends Injectable implements \Countable, \Iterator } let forbidden = [ - "validation" : true, - "action" : true, - "useroption" : true, - "useroptions" : true, - "entity" : true, - "elements" : true, - "messages" : true, - "messagesfor" : true, - "label" : true, - "value" : true, - "di" : true, - "eventsmanager" : true + "validation": true, + "action": true, + "useroption": true, + "useroptions": true, + "entity": true, + "elements": true, + "messages": true, + "messagesfor": true, + "label": true, + "value": true, + "di": true, + "eventsmanager": true ]; /** @@ -611,8 +621,8 @@ class Form extends Injectable implements \Countable, \Iterator } for element in this->elements { - let validators = element->getValidators(); + if count(validators) == 0 { continue; } @@ -651,7 +661,9 @@ class Form extends Injectable implements \Countable, \Iterator for elementMessage in iterator(messages) { this->get(elementMessage->getField())->appendMessage(elementMessage); } + messages->rewind(); + let validationStatus = false; } @@ -690,13 +702,13 @@ class Form extends Injectable implements \Countable, \Iterator { var element; - if fetch element, this->elements[name] { - return element->label(attributes); + if !fetch element, this->elements[name] { + throw new Exception( + "Element with ID=" . name . " is not part of the form" + ); } - throw new Exception( - "Element with ID=" . name . " is not part of the form" - ); + return element->label(attributes); } /** @@ -733,6 +745,7 @@ class Form extends Injectable implements \Countable, \Iterator */ if isset this->elements[name] { unset this->elements[name]; + return true; } @@ -760,6 +773,7 @@ class Form extends Injectable implements \Countable, \Iterator public function setAction(string! action) ->
    { let this->action = action; + return this; } @@ -771,6 +785,7 @@ class Form extends Injectable implements \Countable, \Iterator public function setEntity(var entity) -> { let this->entity = entity; + return this; } @@ -780,6 +795,7 @@ class Form extends Injectable implements \Countable, \Iterator public function setUserOption(string option, var value) -> { let this->options[option] = value; + return this; } @@ -789,6 +805,7 @@ class Form extends Injectable implements \Countable, \Iterator public function setUserOptions(array! options) -> { let this->options = options; + return this; } diff --git a/phalcon/Forms/Manager.zep b/phalcon/Forms/Manager.zep index d0578061eb9..eb74122cd06 100644 --- a/phalcon/Forms/Manager.zep +++ b/phalcon/Forms/Manager.zep @@ -38,9 +38,11 @@ class Manager public function get(string name) -> { var form; + if !fetch form, this->forms[name] { throw new Exception("There is no form with name='" . name . "'"); } + return form; } @@ -58,6 +60,7 @@ class Manager public function set(string name, form) -> { let this->forms[name] = form; + return this; } diff --git a/phalcon/Helper/Arr.zep b/phalcon/Helper/Arr.zep index 647baadcafe..dd13ec65e2e 100644 --- a/phalcon/Helper/Arr.zep +++ b/phalcon/Helper/Arr.zep @@ -21,12 +21,6 @@ class Arr { /** * Chunks an array into smaller arrays of a specified size. - * - * @param array $collection - * @param int $size - * @param bool $preserveKeys - * - * @return array */ final public static function chunk(array! collection, int size, bool preserveKeys = false) -> array { @@ -37,10 +31,7 @@ class Arr * Returns the first element of the collection. If a callable is passed, the * element returned is the first that validates true * - * @param array $collection * @param callable $method - * - * @return mixed */ final public static function first(array! collection, var method = null) -> var { @@ -55,10 +46,7 @@ class Arr * Returns the key of the first element of the collection. If a callable * is passed, the element returned is the first that validates true * - * @param array $collection * @param callable $method - * - * @return mixed */ final public static function firstKey(array! collection, var method = null) -> var { @@ -77,11 +65,6 @@ class Arr /** * Flattens an array up to the one level depth, unless `$deep` is set to `true` - * - * @param array $collection - * @param bool $deep - * - * @return array */ final public static function flatten(array! collection, bool deep = false) -> array { @@ -120,10 +103,7 @@ class Arr /** * Groups the elements of an array based on the passed callable * - * @param array $collection * @param callable $method - * - * @return array */ final public static function group(array! collection, var method) -> array { @@ -148,11 +128,6 @@ class Arr /** * Helper method to get an array element or a default - * - * @param array $collection - * @param mixed $index - * - * return bool */ final public static function has(array! collection, var index) -> bool { @@ -162,10 +137,6 @@ class Arr /** * Checks a flat list for duplicate values. Returns true if duplicate * values exist and false if values are all unique. - * - * @param array $collection - * - * @return bool */ final public static function isUnique(array! collection) -> bool { @@ -176,10 +147,7 @@ class Arr * Returns the last element of the collection. If a callable is passed, the * element returned is the first that validates true * - * @param array $collection * @param callable $method - * - * return mixed */ final public static function last(array! collection, var method = null) -> var { @@ -198,10 +166,7 @@ class Arr * Returns the key of the last element of the collection. If a callable is * passed, the element returned is the first that validates true * - * @param array $collection * @param callable $method - * - * @return mixed */ final public static function lastKey(array! collection, var method = null) -> var { @@ -220,12 +185,6 @@ class Arr /** * Sorts a collection of arrays or objects by key - * - * @param array $collection - * @param mixed $attr - * @param string $order - * - * @return array */ final public static function order(array! collection, var attribute, string order = "asc") -> array { @@ -233,6 +192,7 @@ class Arr array sorted; let sorted = []; + for item in collection { if typeof item === "object" { let key = item->{attribute}; @@ -253,12 +213,7 @@ class Arr } /** - * Retrieves all of the values for a given key: - * - * @param array $collection - * @param string $element - * - * @return array + * Retrieves all of the values for a given key. */ final public static function pluck(array! collection, string element) -> array { @@ -266,6 +221,7 @@ class Arr array filtered; let filtered = []; + for item in collection { if typeof item === "object" && isset item->{element} { let filtered[] = item->{element}; @@ -279,12 +235,6 @@ class Arr /** * Helper method to set an array element - * - * @param array $collection - * @param mixed $value - * @param mixed $index - * - * @return array */ final public static function set(array! collection, var value, var index = null) -> array { @@ -299,11 +249,6 @@ class Arr /** * Returns a new array with n elements removed from the right. - * - * @param array $collection - * @param int $elements - * - * @return array */ final public static function sliceLeft(array! collection, int elements = 1) -> array { @@ -312,11 +257,6 @@ class Arr /** * Returns a new array with the X elements from the right - * - * @param array $collection - * @param int $elements - * - * @return array */ final public static function sliceRight(array! collection, int elements = 1) -> array { @@ -326,24 +266,20 @@ class Arr /** * Returns a new array with keys of the passed array as one element and * values as another - * - * @param array $collection - * - * @return array */ final public static function split(array! collection) -> array { - return [array_keys(collection), array_values(collection)]; + return [ + array_keys(collection), + array_values(collection) + ]; } /** * Returns true if the provided function returns true for all elements of * the collection, false otherwise. * - * @param array $collection * @param callable $method - * - * @return bool */ final public static function validateAll(array! collection, var method) -> bool { @@ -354,10 +290,7 @@ class Arr * Returns true if the provided function returns true for at least one * element fo the collection, false otherwise. * - * @param array $collection * @param callable $method - * - * @return bool */ final public static function validateAny(array! collection, var method) -> bool { diff --git a/phalcon/Helper/Str.zep b/phalcon/Helper/Str.zep index 2449620c925..68722301823 100644 --- a/phalcon/Helper/Str.zep +++ b/phalcon/Helper/Str.zep @@ -16,7 +16,7 @@ use Phalcon\Helper\Exception; /** * Phalcon\Helper\Str * - * This class offers quick string functions throught the framework + * This class offers quick string functions throughout the framework */ class Str { @@ -37,11 +37,6 @@ class Str * echo Str::camelize("co_co-bon_go", "-"); // Co_coBon_go * echo Str::camelize("co_co-bon_go", "_-"); // CoCoBonGo * - * - * @param string $text - * @param mixed $delimiter - * - * @return string */ final public static function camelize(string! text, var delimiter = null) -> string { @@ -68,8 +63,6 @@ class Str * @param string a * @param string b * @param string ...N - * - * @return string */ final public static function concat() -> string { @@ -108,10 +101,6 @@ class Str /** * Retuns number of vowels in provided string. Uses a regular expression * to count the number of vowels (A, E, I, O, U) in a string. - * - * @param string $string - * - * @return int */ final public static function countVowels(string! text) -> int { @@ -126,12 +115,6 @@ class Str * Decapitalizes the first letter of the sring and then adds it with rest * of the string. Omit the upperRest parameter to keep the rest of the * string intact, or set it to true to convert to uppercase. - * - * @param string $string - * @param bool $upperRest - * @param string $encoding - * - * @return string */ final public static function decapitalize( string! text, @@ -186,13 +169,6 @@ class Str * "/" * ); * - * - * @param string $text - * @param string $leftDelimiter - * @param string $rightDelimiter - * @param string $separator - * - * @return string */ final public static function dynamic( string! text, @@ -244,12 +220,6 @@ class Str * echo Str::endsWith("Hello", "LLO", false); // false * echo Str::endsWith("Hello", "LLO"); // true * - * - * @param string $text - * @param string $end - * @param bool $ignoreCase - * - * @return bool */ final public static function endsWith(string text, string end, bool ignoreCase = true) -> bool { @@ -259,12 +229,6 @@ class Str /** * Returns the first string there is between the strings from the * parameter start and end. - * - * @param string $text - * @param string $start - * @param string $end - * - * @return string */ final public static function firstBetween( string! text, @@ -288,10 +252,6 @@ class Str * echo Str::humanize("start-a-horse"); // "start a horse" * echo Str::humanize("five_cats"); // "five cats" * - * - * @param string $text - * - * @return string */ final public static function humanize(string! text) -> string { @@ -300,11 +260,6 @@ class Str /** * Lets you determine whether or not a string includes another string. - * - * @param string $needle - * @param string $haystack - * - * @return bool */ final public static function includes(string! needle, string! haystack) -> bool { @@ -325,11 +280,6 @@ class Str * echo Str::increment("a"); // "a_1" * echo Str::increment("a_1"); // "a_2" * - * - * @param string $text - * @param string $separator - * - * @return string */ final public static function increment(string text, string separator = "_") -> string { @@ -349,11 +299,6 @@ class Str /** * Compare two strings and returns true if both strings are anagram, * false otherwise. - * - * @param string $first - * @param string $second - * - * @return bool */ final public static function isAnagram(string! first, string! second) -> bool { @@ -362,11 +307,6 @@ class Str /** * Returns true if the given string is lower case, false otherwise. - * - * @param string $text - * @param string $encoding - * - * @return bool */ final public static function isLower(string! text, string! encoding = "UTF-8") -> bool { @@ -379,10 +319,6 @@ class Str /** * Returns true if the given string is a palindrome, false otherwise. - * - * @param string $text - * - * @return bool */ final public static function isPalindrome(string! text) -> bool { @@ -391,11 +327,6 @@ class Str /** * Returns true if the given string is upper case, false otherwise. - * - * @param string text - * @param string encoding - * - * @return bool */ final public static function isUpper(string! text, string! encoding = "UTF-8") -> bool { @@ -413,11 +344,6 @@ class Str * * echo Phalcon\Helper\Str::lower("HELLO"); // hello * - * - * @param string $text - * @param string $encoding - * - * @return string */ final public static function lower(string! text, string! encoding = "UTF-8") -> string { @@ -441,11 +367,6 @@ class Str * * echo Str::random(Str::RANDOM_ALNUM); // "aloiwkqz" * - * - * @param int $type - * @param int $length - * - * @return string */ final public static function random(int type = 0, long length = 8) -> string { @@ -501,10 +422,6 @@ class Str * echo Phalcon\Helper\Str::reduceSlashes("foo//bar/baz"); // foo/bar/baz * echo Phalcon\Helper\Str::reduceSlashes("http://foo.bar///baz/buz"); // http://foo.bar/baz/buz * - * - * @param string $text - * - * @return string */ final public static function reduceSlashes(string! text) -> string { @@ -521,12 +438,6 @@ class Str * echo Str::startsWith("Hello", "he", false); // false * echo Str::startsWith("Hello", "he"); // true * - * - * @param string $text - * @param string $start - * @param bool $ignoreCase - * - * @return bool */ final public static function startsWith(string! text, string! start, bool ignoreCase = true) -> bool { @@ -542,11 +453,6 @@ class Str * echo Str::uncamelize("CocoBongo"); // coco_bongo * echo Str::uncamelize("CocoBongo", "-"); // coco-bongo * - * - * @param string $text - * @param mixed $delimiter - * - * @return string */ final public static function uncamelize(string! text, var delimiter = null) -> string { @@ -562,10 +468,6 @@ class Str * echo Str::underscore("look behind"); // "look_behind" * echo Str::underscore("Awesome Phalcon"); // "Awesome_Phalcon" * - * - * @param string $text - * - * @return string */ final public static function underscore(string! text) -> string { @@ -579,11 +481,6 @@ class Str * * echo Phalcon\Helper\Str::upper("hello"); // HELLO * - * - * @param string $text - * @param string $encoding - * - * @return string */ final public static function upper(string! text, string! encoding = "UTF-8") -> string { diff --git a/phalcon/Html/Breadcrumbs.zep b/phalcon/Html/Breadcrumbs.zep index ec1d1af45c8..365507251a4 100644 --- a/phalcon/Html/Breadcrumbs.zep +++ b/phalcon/Html/Breadcrumbs.zep @@ -61,7 +61,7 @@ class Breadcrumbs } /** - * Clears the crumbx + * Clears the crumbs * * * $breadcrumbs->clear() @@ -97,7 +97,7 @@ class Breadcrumbs * Renders and outputs breadcrumbs based on previously set template. * * - * // Php Engine + * // PHP Engine * echo $breadcrumbs->render(); * */ diff --git a/phalcon/Html/Exception.zep b/phalcon/Html/Exception.zep index 9cf48a6c4c8..3886558b43e 100644 --- a/phalcon/Html/Exception.zep +++ b/phalcon/Html/Exception.zep @@ -14,7 +14,6 @@ namespace Phalcon\Html; * Phalcon\Html\Tag\Exception * * Exceptions thrown in Phalcon\Html\Tag will use this class - * */ class Exception extends \Phalcon\Exception { diff --git a/phalcon/Html/Helper/AbstractHelper.zep b/phalcon/Html/Helper/AbstractHelper.zep index 3a2ffb39cb9..a4d7f4bac5d 100644 --- a/phalcon/Html/Helper/AbstractHelper.zep +++ b/phalcon/Html/Helper/AbstractHelper.zep @@ -73,6 +73,7 @@ abstract class AbstractHelper var key, result, value; let result = ""; + for key, value in attributes { if typeof key == "string" && value !== null { if typeof value == "array" || typeof value == "resource" || typeof value == "object" { @@ -82,7 +83,6 @@ abstract class AbstractHelper } let result .= key . "=\"" . this->escaper->escapeHtmlAttr(value) . "\" "; - } } diff --git a/phalcon/Html/Helper/Anchor.zep b/phalcon/Html/Helper/Anchor.zep index f2f93bde512..b8f993322bd 100644 --- a/phalcon/Html/Helper/Anchor.zep +++ b/phalcon/Html/Helper/Anchor.zep @@ -28,7 +28,9 @@ class Anchor extends AbstractHelper { var escapedText, overrides; - let overrides = ["href" : href]; + let overrides = [ + "href": href + ]; /** * Avoid duplicate "href" and ignore it if it is passed in the attributes diff --git a/phalcon/Html/Tag.zep b/phalcon/Html/Tag.zep index c8c24ad6704..3cb05a923f3 100644 --- a/phalcon/Html/Tag.zep +++ b/phalcon/Html/Tag.zep @@ -211,6 +211,7 @@ class Tag implements InjectionAwareInterface if useEol { return "" . PHP_EOL; } + return ""; } @@ -265,6 +266,7 @@ class Tag implements InjectionAwareInterface */ if fetch params, parameters["parameters"] { let parameters["action"] .= "?" . params; + unset parameters["parameters"]; } @@ -1203,7 +1205,12 @@ class Tag implements InjectionAwareInterface * For the ResultsetInterface we need the 'using' parameter */ if typeof data === "object" { - let using = Arr::get(parameters, "using", []); + let using = Arr::get( + parameters, + "using", + [] + ); + if typeof using === "array" && count(using) === 2 { unset parameters["using"]; } else { @@ -1486,6 +1493,7 @@ class Tag implements InjectionAwareInterface if isset parameters["value"] { let content = parameters["value"]; + unset parameters["value"]; } else { let content = this->getValue(parameters["id"], parameters); @@ -1522,7 +1530,7 @@ class Tag implements InjectionAwareInterface ); } - if ("escaper" === name) { + if "escaper" === name { let service = container->getShared(name), this->escaper = service; } else { @@ -1561,6 +1569,7 @@ class Tag implements InjectionAwareInterface unset attrs["escape"]; let newCode = code; + for key, value in attrs { if typeof key == "string" && value !== null { if typeof value == "array" || typeof value == "resource" { @@ -1568,11 +1577,13 @@ class Tag implements InjectionAwareInterface "Value at index: '" . key . "' type: '" . gettype(value) . "' cannot be rendered" ); } + if escaper { let escaped = escaper->escapeHtmlAttr(value); } else { let escaped = value; } + let newCode .= " " . key . "=\"" . escaped . "\""; } } @@ -1639,6 +1650,7 @@ class Tag implements InjectionAwareInterface if value !== null && currentValue === value { let parameters["checked"] = "checked"; } + let parameters["value"] = currentValue; } else { let value = this->getValue(id, parameters); @@ -1681,9 +1693,10 @@ class Tag implements InjectionAwareInterface * Check if this is an option group */ if typeof optionText === "array" { - let output .= "\t" . PHP_EOL - . this->renderSelectArray(optionText, value, closeOption) . "\t" . PHP_EOL; - continue; + let output .= "\t" . PHP_EOL + . this->renderSelectArray(optionText, value, closeOption) . "\t" . PHP_EOL; + + continue; } if typeof value === "array" { diff --git a/phalcon/Html/TagLocatorFactory.zep b/phalcon/Html/TagLocatorFactory.zep index c47dc0863d8..6dce5c5f1e6 100644 --- a/phalcon/Html/TagLocatorFactory.zep +++ b/phalcon/Html/TagLocatorFactory.zep @@ -83,7 +83,7 @@ class TagLocatorFactory implements LocatorFactoryInterface * Get the escaper service * * I really don't like this here but it has to be here this way because there - * is a lot mroe groundwork to be done to refactor the whole DI implementation + * is a lot more groundwork to be done to refactor the whole DI implementation */ private function getEscaper() -> { diff --git a/phalcon/Http/Cookie.zep b/phalcon/Http/Cookie.zep index 6fe2a788cb5..14e4fdb68ec 100644 --- a/phalcon/Http/Cookie.zep +++ b/phalcon/Http/Cookie.zep @@ -56,7 +56,6 @@ class Cookie implements CookieInterface, InjectionAwareInterface protected value; - /** * Phalcon\Http\Cookie constructor. */ @@ -112,15 +111,26 @@ class Cookie implements CookieInterface, InjectionAwareInterface httpOnly = this->httpOnly; let container = this->container; + if typeof container == "object" { let session = container->getShared("session"); + if session->exists() { session->remove("_PHCOOKIE_" . name); } } let this->value = null; - setcookie(name, null, time() - 691200, path, domain, secure, httpOnly); + + setcookie( + name, + null, + time() - 691200, + path, + domain, + secure, + httpOnly + ); } /** @@ -139,6 +149,7 @@ class Cookie implements CookieInterface, InjectionAwareInterface if !this->restored { this->restore(); } + return this->domain; } @@ -150,6 +161,7 @@ class Cookie implements CookieInterface, InjectionAwareInterface if !this->restored { this->restore(); } + return this->expire; } @@ -161,6 +173,7 @@ class Cookie implements CookieInterface, InjectionAwareInterface if !this->restored { this->restore(); } + return this->httpOnly; } @@ -180,6 +193,7 @@ class Cookie implements CookieInterface, InjectionAwareInterface if !this->restored { this->restore(); } + return this->path; } @@ -192,6 +206,7 @@ class Cookie implements CookieInterface, InjectionAwareInterface if !this->restored { this->restore(); } + return this->secure; } @@ -210,83 +225,85 @@ class Cookie implements CookieInterface, InjectionAwareInterface name = this->name; if this->read === false { + if !fetch value, _COOKIE[name] { + return defaultValue; + } - if fetch value, _COOKIE[name] { + if this->useEncryption { + let container = this->container; - if this->useEncryption { + if typeof container != "object" { + throw new Exception( + Exception::containerServiceNotFound( + "the 'filter' and 'crypt' services" + ) + ); + } - let container = this->container; - if typeof container != "object" { - throw new Exception( - Exception::containerServiceNotFound( - "the 'filter' and 'crypt' services" - ) - ); - } + let crypt = container->getShared("crypt"); - let crypt = container->getShared("crypt"); - if typeof crypt != "object" { - throw new Exception( - "A dependency which implements CryptInterface is required to use encryption" - ); - } + if typeof crypt != "object" { + throw new Exception( + "A dependency which implements CryptInterface is required to use encryption" + ); + } + + /** + * Verify the cookie's value if the sign key was set + */ + let signKey = this->signKey; + if typeof signKey === "string" { /** - * Verify the cookie's value if the sign key was set + * Decrypt the value also decoding it with base64 */ - let signKey = this->signKey; - if typeof signKey === "string" { - /** - * Decrypt the value also decoding it with base64 - */ - let decryptedValue = crypt->decryptBase64( - value, - signKey - ); - } else { - /** - * Decrypt the value also decoding it with base64 - */ - let decryptedValue = crypt->decryptBase64(value); - } + let decryptedValue = crypt->decryptBase64( + value, + signKey + ); } else { - let decryptedValue = value; + /** + * Decrypt the value also decoding it with base64 + */ + let decryptedValue = crypt->decryptBase64(value); } + } else { + let decryptedValue = value; + } - /** - * Update the decrypted value - */ - let this->value = decryptedValue; - - if filters !== null { - let filter = this->filter; - if typeof filter != "object" { - - if container === null { - let container = this->container; - if typeof container != "object" { - throw new Exception( - Exception::containerServiceNotFound( - "the 'filter' service" - ) - ); - } - } + /** + * Update the decrypted value + */ + let this->value = decryptedValue; -// let filter = container->getShared("filter"), - let filter = container->getShared("filter"), - this->filter = filter; + if filters !== null { + let filter = this->filter; + + if typeof filter != "object" { + if container === null { + let container = this->container; + + if typeof container != "object" { + throw new Exception( + Exception::containerServiceNotFound( + "the 'filter' service" + ) + ); + } } - return filter->sanitize(decryptedValue, filters); +// let filter = container->getShared("filter"), + let filter = container->getShared("filter"), + this->filter = filter; } - /** - * Return the value without filtering - */ - return decryptedValue; + return filter->sanitize(decryptedValue, filters); } - return defaultValue; + + /** + * Return the value without filtering + */ + return decryptedValue; } return this->value; @@ -309,39 +326,38 @@ class Cookie implements CookieInterface, InjectionAwareInterface */ public function restore() -> { - var container, expire, domain, path, secure, - httpOnly, session, definition; + var container, expire, domain, path, secure, httpOnly, session, + definition; if !this->restored { - let container = this->container; - if typeof container == "object" { + if typeof container == "object" { let session = container->getShared("session"); if session->exists() { - let definition = session->get("_PHCOOKIE_" . this->name); - if typeof definition == "array" { + let definition = session->get( + "_PHCOOKIE_" . this->name + ); - if fetch expire, definition["expire"] { - let this->expire = expire; - } + if fetch expire, definition["expire"] { + let this->expire = expire; + } - if fetch domain, definition["domain"] { - let this->domain = domain; - } + if fetch domain, definition["domain"] { + let this->domain = domain; + } - if fetch path, definition["path"] { - let this->path = path; - } + if fetch path, definition["path"] { + let this->path = path; + } - if fetch secure, definition["secure"] { - let this->secure = secure; - } + if fetch secure, definition["secure"] { + let this->secure = secure; + } - if fetch httpOnly, definition["httpOnly"] { - let this->httpOnly = httpOnly; - } + if fetch httpOnly, definition["httpOnly"] { + let this->httpOnly = httpOnly; } } } @@ -359,8 +375,8 @@ class Cookie implements CookieInterface, InjectionAwareInterface */ public function send() -> { - var name, value, expire, domain, path, secure, httpOnly, - container, definition, session, crypt, encryptValue, signKey; + var name, value, expire, domain, path, secure, httpOnly, container, + definition, session, crypt, encryptValue, signKey; let name = this->name, value = this->value, @@ -405,49 +421,48 @@ class Cookie implements CookieInterface, InjectionAwareInterface */ if count(definition) { let session = container->getShared("session"); + if session->exists() { - session->set("_PHCOOKIE_" . name, definition); + session->set( + "_PHCOOKIE_" . name, + definition + ); } } - if this->useEncryption { + if this->useEncryption && !empty value { + if typeof container != "object" { + throw new Exception( + Exception::containerServiceNotFound( + "the 'filter' service" + ) + ); + } - if !empty value { + let crypt = container->getShared("crypt"); - if typeof container != "object" { - throw new Exception( - Exception::containerServiceNotFound( - "the 'filter' service" - ) - ); - } - - let crypt = container->getShared("crypt"); - if typeof crypt != "object" { - throw new Exception( - "A dependency which implements CryptInterface is required to use encryption" - ); - } + if typeof crypt != "object" { + throw new Exception( + "A dependency which implements CryptInterface is required to use encryption" + ); + } - /** - * Encrypt the value also coding it with base64. - * Sign the cookie's value if the sign key was set - */ - let signKey = this->signKey; - if typeof signKey === "string" { - let encryptValue = crypt->encryptBase64( - (string) value, - signKey - ); - } else { - let encryptValue = crypt->encryptBase64( - (string) value - ); - } + /** + * Encrypt the value also coding it with base64. + * Sign the cookie's value if the sign key was set + */ + let signKey = this->signKey; + + if typeof signKey === "string" { + let encryptValue = crypt->encryptBase64( + (string) value, + signKey + ); } else { - let encryptValue = value; + let encryptValue = crypt->encryptBase64( + (string) value + ); } - } else { let encryptValue = value; } @@ -476,7 +491,9 @@ class Cookie implements CookieInterface, InjectionAwareInterface if !this->restored { this->restore(); } + let this->domain = domain; + return this; } @@ -488,7 +505,9 @@ class Cookie implements CookieInterface, InjectionAwareInterface if !this->restored { this->restore(); } + let this->expire = expire; + return this; } @@ -500,7 +519,9 @@ class Cookie implements CookieInterface, InjectionAwareInterface if !this->restored { this->restore(); } + let this->httpOnly = httpOnly; + return this; } @@ -512,7 +533,9 @@ class Cookie implements CookieInterface, InjectionAwareInterface if !this->restored { this->restore(); } + let this->path = path; + return this; } @@ -524,7 +547,9 @@ class Cookie implements CookieInterface, InjectionAwareInterface if !this->restored { this->restore(); } + let this->secure = secure; + return this; } @@ -559,6 +584,7 @@ class Cookie implements CookieInterface, InjectionAwareInterface { let this->value = value, this->read = true; + return this; } @@ -568,6 +594,7 @@ class Cookie implements CookieInterface, InjectionAwareInterface public function useEncryption(bool useEncryption) -> { let this->useEncryption = useEncryption; + return this; } @@ -581,6 +608,7 @@ class Cookie implements CookieInterface, InjectionAwareInterface var length; let length = mb_strlen(signKey); + if length < 32 { throw new CookieException( sprintf( diff --git a/phalcon/Http/Message/Exception.zep b/phalcon/Http/Message/Exception.zep index 4400bca7ede..e93451e21d1 100644 --- a/phalcon/Http/Message/Exception.zep +++ b/phalcon/Http/Message/Exception.zep @@ -14,7 +14,6 @@ namespace Phalcon\Http\Message; * Phalcon\Http\Message\Exception * * Exceptions thrown in Phalcon\Http\Message/* will use this class - * */ class Exception extends \Phalcon\Exception { diff --git a/phalcon/Http/Message/Request.zep b/phalcon/Http/Message/Request.zep index f53c471d29b..db82ab3d676 100644 --- a/phalcon/Http/Message/Request.zep +++ b/phalcon/Http/Message/Request.zep @@ -141,11 +141,7 @@ class Request implements RequestInterface let header = this->getHeader(name); - if count(header) > 0 { - return implode(",", header); - } - - return ""; + return implode(",", header); } /** @@ -181,8 +177,8 @@ class Request implements RequestInterface * clients), as it appeared at request (for servers), or as it was * specified for the instance (see withRequestTarget()). * - * In most cases, this will be the origin-form of the composed URI, - * unless a value was provided to the concrete implementation (see + * In most cases, this will be the origin-form of the composed URI, unless a + * value was provided to the concrete implementation (see * withRequestTarget() below). */ public function getRequestTarget() -> string @@ -193,6 +189,7 @@ class Request implements RequestInterface if null === requestTarget { let requestTarget = this->uri->getPath(); + if true === this->uri->getQuery() { let requestTarget .= this->uri->getQuery(); } @@ -498,6 +495,7 @@ class Request implements RequestInterface var newInstance; let newInstance = clone this; + if element !== this->{property} { let newInstance->{property} = element; } @@ -524,8 +522,10 @@ class Request implements RequestInterface } let valueData = []; + for value in values { this->checkHeaderValue(value); + let valueData[] = (string) value; } @@ -540,6 +540,7 @@ class Request implements RequestInterface var host; let host = uri->getHost(); + if null !== uri->getPort() { let host .= ":" . uri->getPort(); } @@ -557,7 +558,9 @@ class Request implements RequestInterface } if typeof body !== "string" && typeof body !== "resource" { - throw new \InvalidArgumentException("Invalid stream passed as a parameter"); + throw new \InvalidArgumentException( + "Invalid stream passed as a parameter" + ); } return new Stream(body, mode); @@ -572,8 +575,8 @@ class Request implements RequestInterface if typeof headers === "array" { let collection = new Collection(); - for name, value in headers { + for name, value in headers { this->checkHeaderName(name); let name = (string) name, @@ -620,7 +623,9 @@ class Request implements RequestInterface ]; if !(!empty(method) && typeof method === "string" && isset methods[method]) { - throw new \InvalidArgumentException("Invalid or unsupported method " . method); + throw new \InvalidArgumentException( + "Invalid or unsupported method " . method + ); } return method; @@ -645,7 +650,9 @@ class Request implements RequestInterface } if !isset protocols[protocol] { - throw new \InvalidArgumentException("Unsupported protocol " . protocol); + throw new \InvalidArgumentException( + "Unsupported protocol " . protocol + ); } return protocol; @@ -663,7 +670,9 @@ class Request implements RequestInterface } elseif typeof uri === "string" || null === uri { let localUri = new Uri(uri); } else { - throw new \InvalidArgumentException("Invalid uri passed as a parameter"); + throw new \InvalidArgumentException( + "Invalid uri passed as a parameter" + ); } return localUri; diff --git a/phalcon/Http/Message/Response.zep b/phalcon/Http/Message/Response.zep index 5d2163a53db..1f81395709c 100644 --- a/phalcon/Http/Message/Response.zep +++ b/phalcon/Http/Message/Response.zep @@ -130,11 +130,7 @@ class Response implements ResponseInterface let header = this->getHeader(name); - if count(header) > 0 { - return implode(",", header); - } - - return ""; + return implode(",", header); } /** @@ -386,6 +382,7 @@ class Response implements ResponseInterface var newInstance; let newInstance = clone this; + if element !== this->{property} { let newInstance->{property} = element; } @@ -412,8 +409,10 @@ class Response implements ResponseInterface } let valueData = []; + for value in values { this->checkHeaderValue(value); + let valueData[] = (string) value; } @@ -530,7 +529,9 @@ class Response implements ResponseInterface } if typeof body !== "string" && typeof body !== "resource" { - throw new \InvalidArgumentException("Invalid stream passed as a parameter"); + throw new \InvalidArgumentException( + "Invalid stream passed as a parameter" + ); } return new Stream(body, mode); @@ -574,8 +575,8 @@ class Response implements ResponseInterface var collection, name, value; let collection = new Collection(); - for name, value in headers { + for name, value in headers { this->checkHeaderName(name); let name = (string) name, @@ -601,12 +602,14 @@ class Response implements ResponseInterface "3.0" : 1 ]; - if (empty(protocol)) || typeof protocol !== "string" { + if empty(protocol) || typeof protocol !== "string" { throw new \InvalidArgumentException("Invalid protocol value"); } if !isset protocols[protocol] { - throw new \InvalidArgumentException("Unsupported protocol " . protocol); + throw new \InvalidArgumentException( + "Unsupported protocol " . protocol + ); } return protocol; diff --git a/phalcon/Http/Message/ServerRequest.zep b/phalcon/Http/Message/ServerRequest.zep index 3288768e01d..2ba6c6013b3 100644 --- a/phalcon/Http/Message/ServerRequest.zep +++ b/phalcon/Http/Message/ServerRequest.zep @@ -284,11 +284,7 @@ class ServerRequest implements ServerRequestInterface let header = this->getHeader(name); - if count(header) > 0 { - return implode(",", header); - } - - return ""; + return implode(",", header); } /** @@ -336,6 +332,7 @@ class ServerRequest implements ServerRequestInterface if null === requestTarget { let requestTarget = this->uri->getPath(); + if true === this->uri->getQuery() { let requestTarget .= this->uri->getQuery(); } @@ -791,6 +788,7 @@ class ServerRequest implements ServerRequestInterface var newInstance; let newInstance = clone this; + if element !== this->{property} { let newInstance->{property} = element; } @@ -817,8 +815,10 @@ class ServerRequest implements ServerRequestInterface } let valueData = []; + for value in values { this->checkHeaderValue(value); + let valueData[] = (string) value; } @@ -833,6 +833,7 @@ class ServerRequest implements ServerRequestInterface var host; let host = uri->getHost(); + if null !== uri->getPort() { let host .= ":" . uri->getPort(); } @@ -867,8 +868,8 @@ class ServerRequest implements ServerRequestInterface if typeof headers === "array" { let collection = new Collection(); - for name, value in headers { + for name, value in headers { this->checkHeaderName(name); let name = (string) name, diff --git a/phalcon/Http/Message/Stream.zep b/phalcon/Http/Message/Stream.zep index 9b7d40029cf..3e4990f9aeb 100644 --- a/phalcon/Http/Message/Stream.zep +++ b/phalcon/Http/Message/Stream.zep @@ -87,6 +87,7 @@ class Stream implements StreamInterface if null !== this->handle { let handle = this->detach(); + fclose(handle); } } @@ -170,6 +171,7 @@ class Stream implements StreamInterface if null !== this->handle { let stats = fstat(this->handle); + if false !== stats { return Arr::get(stats, "size", null); } @@ -278,7 +280,9 @@ class Stream implements StreamInterface let this->warning = true; } ); + let handle = fopen(stream, mode); + restore_error_handler(); } @@ -300,6 +304,7 @@ class Stream implements StreamInterface var position; this->checkHandle(); + let position = ftell(this->handle); if typeof position !== "int" { diff --git a/phalcon/Http/Message/Stream/Input.zep b/phalcon/Http/Message/Stream/Input.zep index 8a1658bb79f..395f07788d7 100644 --- a/phalcon/Http/Message/Stream/Input.zep +++ b/phalcon/Http/Message/Stream/Input.zep @@ -55,7 +55,6 @@ class Input extends Stream * string casting operations. * * @see http://php.net/manual/en/language.oop5.magic.php#object.tostring - * @return string */ public function __toString() -> string { @@ -71,7 +70,6 @@ class Input extends Stream /** * Returns the remaining contents in a string * - * @return string * @throws \RuntimeException if unable to read. * @throws \RuntimeException if error occurs while reading. */ @@ -94,9 +92,7 @@ class Input extends Stream } /** - * Returns whether or not the stream is writable. - * - * @return bool + * Returns whether or not the stream is writeable. */ public function isWritable() -> bool { diff --git a/phalcon/Http/Message/UploadedFile.zep b/phalcon/Http/Message/UploadedFile.zep index 9655eb576ef..4182a0454a3 100644 --- a/phalcon/Http/Message/UploadedFile.zep +++ b/phalcon/Http/Message/UploadedFile.zep @@ -210,7 +210,9 @@ class UploadedFile implements UploadedFileInterface } if constant("UPLOAD_ERR_OK") !== this->error { - throw new Exception(this->getErrorDescription(this->error)); + throw new Exception( + this->getErrorDescription(this->error) + ); } let dirname = dirname(targetPath); @@ -285,21 +287,21 @@ class UploadedFile implements UploadedFileInterface { switch error { case constant("UPLOAD_ERR_OK"): - return "There is no error, the file uploaded with success."; + return "There is no error, the file uploaded with success."; case constant("UPLOAD_ERR_INI_SIZE"): - return "The uploaded file exceeds the upload_max_filesize directive in php.ini."; + return "The uploaded file exceeds the upload_max_filesize directive in php.ini."; case constant("UPLOAD_ERR_FORM_SIZE"): - return "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form."; + return "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form."; case constant("UPLOAD_ERR_PARTIAL"): - return "The uploaded file was only partially uploaded."; + return "The uploaded file was only partially uploaded."; case constant("UPLOAD_ERR_NO_FILE"): - return "No file was uploaded."; + return "No file was uploaded."; case constant("UPLOAD_ERR_NO_TMP_DIR"): - return "Missing a temporary folder."; + return "Missing a temporary folder."; case constant("UPLOAD_ERR_CANT_WRITE"): - return "Failed to write file to disk."; + return "Failed to write file to disk."; case constant("UPLOAD_ERR_EXTENSION"): - return "A PHP extension stopped the file upload."; + return "A PHP extension stopped the file upload."; } return "Unknown upload error"; @@ -316,8 +318,10 @@ class UploadedFile implements UploadedFileInterface stream = this->getStream(); stream->rewind(); + while (true !== stream->eof()) { let data = stream->read(2048); + fwrite(handle, data); } diff --git a/phalcon/Http/Message/UploadedFileFactory.zep b/phalcon/Http/Message/UploadedFileFactory.zep index 2e7e76aedb6..6f4a17ae831 100644 --- a/phalcon/Http/Message/UploadedFileFactory.zep +++ b/phalcon/Http/Message/UploadedFileFactory.zep @@ -47,6 +47,12 @@ class UploadedFileFactory implements UploadedFileFactoryInterface string clientMediaType = null ) -> { - return new UploadedFile(stream, size, error, clientFilename, clientMediaType); + return new UploadedFile( + stream, + size, + error, + clientFilename, + clientMediaType + ); } } diff --git a/phalcon/Http/Message/Uri.zep b/phalcon/Http/Message/Uri.zep index 5413f6cdde3..c5815dbb0ca 100644 --- a/phalcon/Http/Message/Uri.zep +++ b/phalcon/Http/Message/Uri.zep @@ -444,11 +444,13 @@ class Uri implements UriInterface var newInstance; this->checkStringParameter(user, "user"); + if null !== password { this->checkStringParameter(user, "pass"); } let user = rawurlencode(user); + if null !== password { let password = rawurlencode(password); } @@ -496,6 +498,7 @@ class Uri implements UriInterface var newInstance; let newInstance = clone this; + if element !== this->{property} { let newInstance->{property} = element; } @@ -625,16 +628,18 @@ class Uri implements UriInterface for key, value in parts { let split = explode("=", value); + if !isset split[1] { let split[] = null; } if null === split[1] { - let parts[key] = rawurlencode(split[0]); + let parts[key] = rawurlencode(split[0]); + continue; - } else { - let parts[key] = rawurlencode(split[0]) . "=" . rawurlencode(split[1]); } + + let parts[key] = rawurlencode(split[0]) . "=" . rawurlencode(split[1]); } return implode("&", parts); diff --git a/phalcon/Http/Request.zep b/phalcon/Http/Request.zep index c72e24735c0..e1975927285 100644 --- a/phalcon/Http/Request.zep +++ b/phalcon/Http/Request.zep @@ -96,7 +96,6 @@ class Request implements RequestInterface, InjectionAwareInterface ); } - /** * Gets an array with mime/types and their quality accepted by the * browser/client from _SERVER["HTTP_ACCEPT"] @@ -112,16 +111,14 @@ class Request implements RequestInterface, InjectionAwareInterface */ public function getBasicAuth() -> array | null { - var auth; - - if isset _SERVER["PHP_AUTH_USER"] && isset _SERVER["PHP_AUTH_PW"] { - let auth = []; - let auth["username"] = _SERVER["PHP_AUTH_USER"]; - let auth["password"] = _SERVER["PHP_AUTH_PW"]; - return auth; + if !isset _SERVER["PHP_AUTH_USER"] || !isset _SERVER["PHP_AUTH_PW"] { + return null; } - return null; + return [ + "username": _SERVER["PHP_AUTH_USER"], + "password": _SERVER["PHP_AUTH_PW"] + ]; } /** @@ -165,6 +162,7 @@ class Request implements RequestInterface, InjectionAwareInterface */ if trustForwardedHeader { fetch address, _SERVER["HTTP_X_FORWARDED_FOR"]; + if address === null { fetch address, _SERVER["HTTP_CLIENT_IP"]; } @@ -174,18 +172,19 @@ class Request implements RequestInterface, InjectionAwareInterface fetch address, _SERVER["REMOTE_ADDR"]; } - if typeof address == "string" { - if memstr(address, ",") { - /** - * The client address has multiples parts, only return the first - * part - */ - return explode(",", address)[0]; - } - return address; + if typeof address != "string" { + return false; } - return false; + if memstr(address, ",") { + /** + * The client address has multiples parts, only return the first + * part + */ + return explode(",", address)[0]; + } + + return address; } /** @@ -204,18 +203,11 @@ class Request implements RequestInterface, InjectionAwareInterface { var contentType; - if fetch contentType, _SERVER["CONTENT_TYPE"] { - return contentType; - } else { - /** - * @see https://bugs.php.net/bug.php?id=66606 - */ - if fetch contentType, _SERVER["HTTP_CONTENT_TYPE"] { - return contentType; - } + if !fetch contentType, _SERVER["CONTENT_TYPE"] { + return null; } - return null; + return contentType; } @@ -237,11 +229,14 @@ class Request implements RequestInterface, InjectionAwareInterface array auth; let auth = []; + if fetch digest, _SERVER["PHP_AUTH_DIGEST"] { let matches = []; + if !preg_match_all("#(\\w+)=(['\"]?)([^'\" ,]+)\\2#", digest, matches, 2) { return auth; } + if typeof matches == "array" { for match in matches { let auth[match[1]] = match[3]; @@ -319,7 +314,9 @@ class Request implements RequestInterface, InjectionAwareInterface { var value, name; - let name = strtoupper(strtr(header, "-", "_")); + let name = strtoupper( + strtr(header, "-", "_") + ); if fetch value, _SERVER[name] { return value; @@ -380,6 +377,7 @@ class Request implements RequestInterface, InjectionAwareInterface // The "CONTENT_" headers are not prefixed with "HTTP_". let name = strtoupper(name); + if isset contentHeaders[name] { let name = ucwords( strtolower( @@ -447,8 +445,8 @@ class Request implements RequestInterface, InjectionAwareInterface * Get the server name from $_SERVER["HTTP_HOST"] */ let host = this->getServer("HTTP_HOST"); - if !host { + if !host { /** * Get the server name from $_SERVER["SERVER_NAME"] */ @@ -465,7 +463,10 @@ class Request implements RequestInterface, InjectionAwareInterface /** * Cleanup. Force lowercase as per RFC 952/2181 */ - let host = strtolower(trim(host)); + let host = strtolower( + trim(host) + ); + if memstr(host, ":") { let host = preg_replace("/:[[:digit:]]+$/", "", host); } @@ -489,10 +490,12 @@ class Request implements RequestInterface, InjectionAwareInterface public function getHTTPReferer() -> string { var httpReferer; - if fetch httpReferer, _SERVER["HTTP_REFERER"] { - return httpReferer; + + if !fetch httpReferer, _SERVER["HTTP_REFERER"] { + return ""; } - return ""; + + return httpReferer; } /** @@ -503,6 +506,7 @@ class Request implements RequestInterface, InjectionAwareInterface var rawBody; let rawBody = this->getRawBody(); + if typeof rawBody != "string" { return false; } @@ -543,6 +547,7 @@ class Request implements RequestInterface, InjectionAwareInterface if "POST" === returnMethod { let overridedMethod = this->getHeader("X-HTTP-METHOD-OVERRIDE"); + if !empty overridedMethod { let returnMethod = strtoupper(overridedMethod); } elseif this->httpMethodParameterOverride { @@ -570,19 +575,20 @@ class Request implements RequestInterface, InjectionAwareInterface * Get the server name from $_SERVER["HTTP_HOST"] */ let host = this->getServer("HTTP_HOST"); - if host { - if memstr(host, ":") { - let pos = strrpos(host, ":"); - if false !== pos { - return (int) substr(host, pos + 1); - } - } + if !host { + return (int) this->getServer("SERVER_PORT"); + } + + if memstr(host, ":") { + let pos = strrpos(host, ":"); - return "https" === $this->getScheme() ? 443 : 80; + if false !== pos { + return (int) substr(host, pos + 1); + } } - return (int) this->getServer("SERVER_PORT"); + return "https" === $this->getScheme() ? 443 : 80; } /** @@ -628,13 +634,16 @@ class Request implements RequestInterface, InjectionAwareInterface if typeof put != "array" { let contentType = this->getContentType(); + if typeof contentType == "string" && stripos(contentType, "json") != false { let put = this->getJsonRawBody(true); - if (typeof put != "array") { + + if typeof put != "array" { let put = []; } } else { let put = []; + parse_str(this->getRawBody(), put); } @@ -686,16 +695,18 @@ class Request implements RequestInterface, InjectionAwareInterface var rawBody, contents; let rawBody = this->rawBody; - if empty rawBody { + if empty rawBody { let contents = file_get_contents("php://input"); /** * We need store the read raw body because it can't be read again */ let this->rawBody = contents; + return contents; } + return rawBody; } @@ -704,19 +715,15 @@ class Request implements RequestInterface, InjectionAwareInterface */ public function getScheme() -> string { - var https, scheme; + var https; let https = this->getServer("HTTPS"); - if https { - if https == "off" { - let scheme = "http"; - } else { - let scheme = "https"; - } - } else { - let scheme = "http"; + + if https && https != "off" { + return "https"; } - return scheme; + + return "http"; } /** @@ -726,10 +733,11 @@ class Request implements RequestInterface, InjectionAwareInterface { var serverValue; - if fetch serverValue, _SERVER[name] { - return serverValue; + if !fetch serverValue, _SERVER[name] { + return null; } - return null; + + return serverValue; } /** @@ -739,10 +747,11 @@ class Request implements RequestInterface, InjectionAwareInterface { var serverAddr; - if fetch serverAddr, _SERVER["SERVER_ADDR"] { - return serverAddr; + if !fetch serverAddr, _SERVER["SERVER_ADDR"] { + return gethostbyname("localhost"); } - return gethostbyname("localhost"); + + return serverAddr; } /** @@ -752,11 +761,11 @@ class Request implements RequestInterface, InjectionAwareInterface { var serverName; - if fetch serverName, _SERVER["SERVER_NAME"] { - return serverName; + if !fetch serverName, _SERVER["SERVER_NAME"] { + return "localhost"; } - return "localhost"; + return serverName; } /** @@ -770,7 +779,6 @@ class Request implements RequestInterface, InjectionAwareInterface let superFiles = _FILES; if count(superFiles) > 0 { - for prefix, input in superFiles { if typeof input["name"] == "array" { let smoothInput = this->smoothFiles( @@ -827,11 +835,11 @@ class Request implements RequestInterface, InjectionAwareInterface { var requestURI; - if fetch requestURI, _SERVER["REQUEST_URI"] { - return requestURI; + if !fetch requestURI, _SERVER["REQUEST_URI"] { + return ""; } - return ""; + return requestURI; } /** @@ -841,10 +849,11 @@ class Request implements RequestInterface, InjectionAwareInterface { var userAgent; - if fetch userAgent, _SERVER["HTTP_USER_AGENT"] { - return userAgent; + if !fetch userAgent, _SERVER["HTTP_USER_AGENT"] { + return ""; } - return ""; + + return userAgent; } /** @@ -873,7 +882,6 @@ class Request implements RequestInterface, InjectionAwareInterface for file in files { if fetch error, file["error"] { - if typeof error != "array" { if !error || !onlySuccessful { let numberFiles++; @@ -901,15 +909,7 @@ class Request implements RequestInterface, InjectionAwareInterface let name = strtoupper(strtr(header, "-", "_")); - if isset _SERVER[name] { - return true; - } - - if isset _SERVER["HTTP_" . name] { - return true; - } - - return false; + return isset _SERVER[name] || isset _SERVER["HTTP_" . name]; } /** @@ -1006,6 +1006,7 @@ class Request implements RequestInterface, InjectionAwareInterface if strict && !this->isValidHttpMethod(methods) { throw new Exception("Invalid HTTP method: " . methods); } + return methods == httpMethod; } @@ -1097,13 +1098,15 @@ class Request implements RequestInterface, InjectionAwareInterface if isset _SERVER["HTTP_SOAPACTION"] { return true; - } else { - let contentType = this->getContentType(); - if !empty contentType { - return memstr(contentType, "application/soap+xml"); - } } - return false; + + let contentType = this->getContentType(); + + if empty contentType { + return false; + } + + return memstr(contentType, "application/soap+xml"); } /** @@ -1212,13 +1215,16 @@ class Request implements RequestInterface, InjectionAwareInterface selectedName = accept[name]; } else { let acceptQuality = (double) accept["quality"]; + if acceptQuality > quality { let quality = acceptQuality, selectedName = accept[name]; } } + let i++; } + return selectedName; } @@ -1237,10 +1243,12 @@ class Request implements RequestInterface, InjectionAwareInterface if !fetch value, source[name] { return defaultValue; } + if filters !== null { let filter = this->filterLocator; if typeof filter != "object" { let container = this->container; + if typeof container != "object" { throw new Exception( Exception::containerServiceNotFound( @@ -1248,6 +1256,7 @@ class Request implements RequestInterface, InjectionAwareInterface ) ); } + let filter = container->getShared("filter"); // let filter = container->getShared("filter"); let this->filterLocator = filter; @@ -1307,11 +1316,12 @@ class Request implements RequestInterface, InjectionAwareInterface ); for part in parts { - let headerParts = []; + for headerPart in preg_split("/\s*;\s*/", trim(part), -1, PREG_SPLIT_NO_EMPTY) { if strpos(headerPart, "=") !== false { let split = explode("=", headerPart, 2); + if split[0] === "q" { let headerParts["quality"] = (double) split[1]; } else { @@ -1343,6 +1353,7 @@ class Request implements RequestInterface, InjectionAwareInterface // TODO: Make Request implements EventsAwareInterface for v4.0.0 if typeof container === "object" { let hasEventsManager = (bool) container->has("eventsManager"); + if hasEventsManager { let eventsManager = container->getShared("eventsManager"); } @@ -1404,7 +1415,10 @@ class Request implements RequestInterface, InjectionAwareInterface let resolved = eventsManager->fire( "request:afterAuthorizationResolve", this, - ["headers": headers, "server": _SERVER] + [ + "headers": headers, + "server": _SERVER + ] ); if typeof resolved === "array" { @@ -1429,14 +1443,13 @@ class Request implements RequestInterface, InjectionAwareInterface let p = prefix . "." . idx; if typeof name == "string" { - let files[] = [ - "name": name, - "type": types[idx], + "name": name, + "type": types[idx], "tmp_name": tmp_names[idx], - "size": sizes[idx], - "error": errors[idx], - "key": p + "size": sizes[idx], + "error": errors[idx], + "key": p ]; } @@ -1467,13 +1480,16 @@ class Request implements RequestInterface, InjectionAwareInterface var container, locator; let locator = this->filterLocator; + if typeof locator != "object" { let container = this->container; + if typeof container != "object" { throw new Exception( Exception::containerServiceNotFound("the 'filter' service") ); } + let locator = container->getShared("filter"), this->filterLocator = locator; } diff --git a/phalcon/Http/Request/Exception.zep b/phalcon/Http/Request/Exception.zep index 46444aee1b0..a21cdf64e5b 100644 --- a/phalcon/Http/Request/Exception.zep +++ b/phalcon/Http/Request/Exception.zep @@ -14,7 +14,6 @@ namespace Phalcon\Http\Request; * Phalcon\Http\Request\Exception * * Exceptions thrown in Phalcon\Http\Request will use this class - * */ class Exception extends \Phalcon\Exception { diff --git a/phalcon/Http/Request/File.zep b/phalcon/Http/Request/File.zep index 91a3099cbec..a0d26ba2b1e 100644 --- a/phalcon/Http/Request/File.zep +++ b/phalcon/Http/Request/File.zep @@ -30,7 +30,7 @@ use Phalcon\Http\Request\FileInterface; * foreach ($this->request->getUploadedFiles() as $file) { * echo $file->getName(), " ", $file->getSize(), "\n"; * } - * } + * } * } * } * @@ -114,11 +114,13 @@ class File implements FileInterface var finfo, mime; let finfo = finfo_open(FILEINFO_MIME_TYPE); + if typeof finfo != "resource" { return ""; } let mime = finfo_file(finfo, this->tmp); + finfo_close(finfo); return mime; @@ -157,6 +159,7 @@ class File implements FileInterface var tmp; let tmp = this->getTempName(); + return typeof tmp == "string" && is_uploaded_file(tmp); } diff --git a/phalcon/Http/Response.zep b/phalcon/Http/Response.zep index 8ab2c7c37c4..753784c005f 100644 --- a/phalcon/Http/Response.zep +++ b/phalcon/Http/Response.zep @@ -51,6 +51,9 @@ class Response implements ResponseInterface, InjectionAwareInterface, EventsAwar protected headers; + /** + * @var bool + */ protected sent = false; protected statusCodes; @@ -80,6 +83,7 @@ class Response implements ResponseInterface, InjectionAwareInterface, EventsAwar public function appendContent(content) -> { let this->content = this->getContent() . content; + return this; } @@ -105,16 +109,21 @@ class Response implements ResponseInterface, InjectionAwareInterface, EventsAwar public function getDI() -> { var container; + let container = this->container; + if typeof container != "object" { let container = \Phalcon\Di::getDefault(); + if typeof container != "object" { throw new Exception( Exception::containerServiceNotFound("the 'url' service") ); } + let this->container = container; } + return container; } @@ -144,7 +153,12 @@ class Response implements ResponseInterface, InjectionAwareInterface, EventsAwar public function getReasonPhrase() -> string | null { var statusReasonPhrase; - let statusReasonPhrase = substr(this->getHeaders()->get("Status"), 4); + + let statusReasonPhrase = substr( + this->getHeaders()->get("Status"), + 4 + ); + return statusReasonPhrase ? statusReasonPhrase : null; } @@ -158,7 +172,13 @@ class Response implements ResponseInterface, InjectionAwareInterface, EventsAwar public function getStatusCode() -> int | null { var statusCode; - let statusCode = substr(this->getHeaders()->get("Status"), 0, 3); + + let statusCode = substr( + this->getHeaders()->get("Status"), + 0, + 3 + ); + return statusCode ? (int) statusCode : null; } @@ -172,6 +192,7 @@ class Response implements ResponseInterface, InjectionAwareInterface, EventsAwar public function hasHeader(string name) -> bool { var headers; + let headers = this->getHeaders(); return headers->has(name); @@ -217,6 +238,7 @@ class Response implements ResponseInterface, InjectionAwareInterface, EventsAwar } else { if typeof location == "string" && strstr(location, "://") { let matched = preg_match("/^[^:\\/?#]++:/", location); + if matched { let header = location; } else { @@ -236,6 +258,7 @@ class Response implements ResponseInterface, InjectionAwareInterface, EventsAwar if container->has("view") { let view = container->getShared("view"); + if view instanceof ViewInterface { view->disable(); } @@ -268,8 +291,11 @@ class Response implements ResponseInterface, InjectionAwareInterface, EventsAwar public function removeHeader(string name) -> { var headers; + let headers = this->getHeaders(); + headers->remove(name); + return this; } /** @@ -278,8 +304,11 @@ class Response implements ResponseInterface, InjectionAwareInterface, EventsAwar public function resetHeaders() -> { var headers; + let headers = this->getHeaders(); + headers->reset(); + return this; } @@ -302,6 +331,7 @@ class Response implements ResponseInterface, InjectionAwareInterface, EventsAwar * Output the response body */ let content = this->content; + if content != null { echo content; } else { @@ -313,6 +343,7 @@ class Response implements ResponseInterface, InjectionAwareInterface, EventsAwar } let this->sent = true; + return this; } @@ -322,10 +353,13 @@ class Response implements ResponseInterface, InjectionAwareInterface, EventsAwar public function sendCookies() -> { var cookies; + let cookies = this->cookies; + if typeof cookies == "object" { cookies->send(); } + return this; } @@ -367,10 +401,17 @@ class Response implements ResponseInterface, InjectionAwareInterface, EventsAwar var date; let date = new \DateTime(); - date->modify("+" . minutes . " minutes"); + + date->modify( + "+" . minutes . " minutes" + ); this->setExpires(date); - this->setHeader("Cache-Control", "max-age=" . (minutes * 60)); + + this->setHeader( + "Cache-Control", + "max-age=" . (minutes * 60) + ); return this; } @@ -385,6 +426,7 @@ class Response implements ResponseInterface, InjectionAwareInterface, EventsAwar public function setContent(string content) -> { let this->content = content; + return this; } @@ -412,15 +454,12 @@ class Response implements ResponseInterface, InjectionAwareInterface, EventsAwar */ public function setContentType(string contentType, charset = null) -> { - if charset === null { - this->setHeader("Content-Type", contentType); - } else { - this->setHeader( - "Content-Type", - contentType . "; charset=" . charset - ); + if charset !== null { + let contentType .= "; charset=" . charset; } + this->setHeader("Content-Type", contentType); + return this; } @@ -430,6 +469,7 @@ class Response implements ResponseInterface, InjectionAwareInterface, EventsAwar public function setCookies( cookies) -> { let this->cookies = cookies; + return this; } @@ -445,7 +485,11 @@ class Response implements ResponseInterface, InjectionAwareInterface, EventsAwar * Set a custom ETag * * - * $response->setEtag(md5(time())); + * $response->setEtag( + * md5( + * time() + * ) + * ); * */ public function setEtag(string etag) -> @@ -472,14 +516,20 @@ class Response implements ResponseInterface, InjectionAwareInterface, EventsAwar /** * All the expiration times are sent in UTC - * Change the timezone to utc + * Change the timezone to UTC */ - date->setTimezone(new \DateTimeZone("UTC")); + date->setTimezone( + new \DateTimeZone("UTC") + ); /** * The 'Expires' header set this info */ - this->setHeader("Expires", date->format("D, d M Y H:i:s") . " GMT"); + this->setHeader( + "Expires", + date->format("D, d M Y H:i:s") . " GMT" + ); + return this; } @@ -526,8 +576,11 @@ class Response implements ResponseInterface, InjectionAwareInterface, EventsAwar public function setHeader(string name, value) -> { var headers; + let headers = this->getHeaders(); + headers->set(name, value); + return this; } @@ -565,7 +618,11 @@ class Response implements ResponseInterface, InjectionAwareInterface, EventsAwar public function setJsonContent(var content, int jsonOptions = 0, int depth = 512) -> { this->setContentType("application/json", "UTF-8"); - this->setContent(json_encode(content, jsonOptions, depth)); + + this->setContent( + json_encode(content, jsonOptions, depth) + ); + return this; } @@ -586,9 +643,11 @@ class Response implements ResponseInterface, InjectionAwareInterface, EventsAwar /** * All the Last-Modified times are sent in UTC - * Change the timezone to utc + * Change the timezone to UTC */ - date->setTimezone(new \DateTimeZone("UTC")); + date->setTimezone( + new \DateTimeZone("UTC") + ); /** * The 'Last-Modified' header sets this info @@ -607,6 +666,7 @@ class Response implements ResponseInterface, InjectionAwareInterface, EventsAwar public function setNotModified() -> { this->setStatusCode(304, "Not modified"); + return this; } @@ -629,11 +689,9 @@ class Response implements ResponseInterface, InjectionAwareInterface, EventsAwar * * Before that we would like to unset any existing HTTP/x.y headers */ - if typeof currentHeadersRaw == "array" { - for key, _ in currentHeadersRaw { - if typeof key == "string" && strstr(key, "HTTP/") { - headers->remove(key); - } + for key, _ in currentHeadersRaw { + if typeof key == "string" && strstr(key, "HTTP/") { + headers->remove(key); } } @@ -728,7 +786,10 @@ class Response implements ResponseInterface, InjectionAwareInterface, EventsAwar /** * We also define a 'Status' header with the HTTP status */ - headers->set("Status", code . " " . message); + headers->set( + "Status", + code . " " . message + ); return this; } @@ -743,8 +804,11 @@ class Response implements ResponseInterface, InjectionAwareInterface, EventsAwar public function setRawHeader(string header) -> { var headers; + let headers = this->getHeaders(); + headers->setRaw(header); + return this; } } diff --git a/phalcon/Http/Response/Cookies.zep b/phalcon/Http/Response/Cookies.zep index 728c106a639..c1c97e2c077 100644 --- a/phalcon/Http/Response/Cookies.zep +++ b/phalcon/Http/Response/Cookies.zep @@ -41,13 +41,13 @@ use Phalcon\Http\Cookie\Exception; * * // The `$key' should have been previously generated in a cryptographically safe way. * $key = "T4\xb1\x8d\xa9\x98\x05\\\x8c\xbe\x1d\x07&[\x99\x18\xa4~Lc1\xbeW\xb3"; + * * $crypt->setKey($key); * * return $crypt; * } * ); * - * * $di->set( * 'cookies', * function () { @@ -56,6 +56,7 @@ use Phalcon\Http\Cookie\Exception; * // The `$key' MUST be at least 32 characters long and generated using a * // cryptographically secure pseudo random generator. * $key = "#1dj8$=dp?.ak//j1V$~%*0XaK\xb1\x8d\xa9\x98\x054t7w!z%C*F-Jk\x98\x05\\\x5c"; + * * $cookies->setSignKey($key); * * return $cookies; @@ -100,12 +101,13 @@ class Cookies implements CookiesInterface, InjectionAwareInterface /** * Check the internal bag */ - if fetch cookie, this->cookies[name] { - cookie->delete(); - return true; + if !fetch cookie, this->cookies[name] { + return false; } - return false; + cookie->delete(); + + return true; } /** @@ -131,7 +133,6 @@ class Cookies implements CookiesInterface, InjectionAwareInterface container = this->container; if typeof container == "object" { - /** * Pass the DI to created cookies */ @@ -173,21 +174,7 @@ class Cookies implements CookiesInterface, InjectionAwareInterface */ public function has(string! name) -> bool { - /** - * Check the internal bag - */ - if isset this->cookies[name] { - return true; - } - - /** - * Check the superglobal - */ - if isset _COOKIE[name] { - return true; - } - - return false; + return isset this->cookies[name] || isset _COOKIE[name]; } /** @@ -204,6 +191,7 @@ class Cookies implements CookiesInterface, InjectionAwareInterface public function reset() -> { let this->cookies = []; + return this; } @@ -215,15 +203,15 @@ class Cookies implements CookiesInterface, InjectionAwareInterface { var cookie; - if !headers_sent() { - for cookie in this->cookies { - cookie->send(); - } + if headers_sent() { + return false; + } - return true; + for cookie in this->cookies { + cookie->send(); } - return false; + return true; } /** @@ -278,11 +266,11 @@ class Cookies implements CookiesInterface, InjectionAwareInterface */ if encryption { cookie->useEncryption(encryption); + cookie->setSignKey(this->signKey); } let this->cookies[name] = cookie; - } else { /** * Override any settings in the cookie @@ -300,8 +288,8 @@ class Cookies implements CookiesInterface, InjectionAwareInterface * Register the cookies bag in the response */ if this->registered === false { - let container = this->container; + if typeof container != "object" { throw new Exception( Exception::containerServiceNotFound( @@ -355,6 +343,7 @@ class Cookies implements CookiesInterface, InjectionAwareInterface public function useEncryption(bool useEncryption) -> { let this->useEncryption = useEncryption; + return this; } } diff --git a/phalcon/Http/Response/Headers.zep b/phalcon/Http/Response/Headers.zep index e1d6f14b3cc..7c77bf1e2d0 100644 --- a/phalcon/Http/Response/Headers.zep +++ b/phalcon/Http/Response/Headers.zep @@ -27,12 +27,15 @@ class Headers implements HeadersInterface public static function __set_state(array! data) -> { var headers, key, value, dataHeaders; + let headers = new self(); + if fetch dataHeaders, data["headers"] { for key, value in dataHeaders { headers->set(key, value); } } + return headers; } @@ -42,13 +45,14 @@ class Headers implements HeadersInterface public function get(string name) -> string | bool { var headers, headerValue; + let headers = this->headers; - if fetch headerValue, headers[name] { - return headerValue; + if !fetch headerValue, headers[name] { + return false; } - return false; + return headerValue; } /** @@ -56,7 +60,7 @@ class Headers implements HeadersInterface */ public function has(string name) -> bool { - return isset(this->headers[name]); + return isset this->headers[name]; } /** @@ -85,21 +89,33 @@ class Headers implements HeadersInterface public function send() -> bool { var header, value; - if !headers_sent() { - for header, value in this->headers { - if value !== null { - header(header . ": " . value, true); + + if headers_sent() { + return false; + } + + for header, value in this->headers { + if value !== null { + header( + header . ": " . value, + true + ); + } else { + if memstr(header, ":") || substr(header, 0, 5) == "HTTP/" { + header( + header, + true + ); } else { - if memstr(header, ":") || substr(header, 0, 5) == "HTTP/" { - header(header, true); - } else { - header(header . ": ", true); - } + header( + header . ": ", + true + ); } } - return true; } - return false; + + return true; } /** diff --git a/phalcon/Image/Adapter.zep b/phalcon/Image/Adapter.zep index e02dbe26199..8eefe73bf78 100644 --- a/phalcon/Image/Adapter.zep +++ b/phalcon/Image/Adapter.zep @@ -71,9 +71,13 @@ abstract class Adapter implements AdapterInterface let color = preg_replace("/./", "$0$0", color); } - let colors = array_map("hexdec", str_split(color, 2)); + let colors = array_map( + "hexdec", + str_split(color, 2) + ); this->{"processBackground"}(colors[0], colors[1], colors[2], opacity); + return this; } @@ -89,6 +93,7 @@ abstract class Adapter implements AdapterInterface } this->{"processBlur"}(radius); + return this; } @@ -144,6 +149,7 @@ abstract class Adapter implements AdapterInterface } this->{"processFlip"}(direction); + return this; } @@ -160,6 +166,7 @@ abstract class Adapter implements AdapterInterface public function liquidRescale(int width, int height, int deltaX = 0, int rigidity = 0) -> { this->{"processLiquidRescale"}(width, height, deltaX, rigidity); + return this; } @@ -169,6 +176,7 @@ abstract class Adapter implements AdapterInterface public function mask( watermark) -> { this->{"processMask"}(watermark); + return this; } @@ -182,6 +190,7 @@ abstract class Adapter implements AdapterInterface } this->{"processPixelate"}(amount); + return this; } @@ -266,14 +275,18 @@ abstract class Adapter implements AdapterInterface if !width { throw new Exception("width must be specified"); } + let height = this->height * width / this->width; + break; case Image::HEIGHT: if !height { throw new Exception("height must be specified"); } + let width = this->width * height / this->height; + break; case Image::PRECISE: @@ -282,6 +295,7 @@ abstract class Adapter implements AdapterInterface "width and height must be specified" ); } + let ratio = this->width / this->height; if (width / height) > ratio { @@ -289,6 +303,7 @@ abstract class Adapter implements AdapterInterface } else { let width = this->width * height / this->height; } + break; case Image::NONE: @@ -299,6 +314,7 @@ abstract class Adapter implements AdapterInterface if !height { let width = (int) this->height; } + break; } } @@ -319,6 +335,7 @@ abstract class Adapter implements AdapterInterface if degrees > 180 { // FIXME: Fix Zephir Parser to allow use let degrees %= 360 let degrees = degrees % 360; + if degrees > 180 { let degrees -= 360; } @@ -329,6 +346,7 @@ abstract class Adapter implements AdapterInterface } this->{"processRotate"}(degrees); + return this; } @@ -342,6 +360,7 @@ abstract class Adapter implements AdapterInterface } this->{"processSave"}(file, quality); + return this; } @@ -357,6 +376,7 @@ abstract class Adapter implements AdapterInterface } this->{"processSharpen"}(amount); + return this; } @@ -383,9 +403,22 @@ abstract class Adapter implements AdapterInterface let color = preg_replace("/./", "$0$0", color); } - let colors = array_map("hexdec", str_split(color, 2)); - - this->{"processText"}(text, offsetX, offsetY, opacity, colors[0], colors[1], colors[2], size, fontfile); + let colors = array_map( + "hexdec", + str_split(color, 2) + ); + + this->{"processText"}( + text, + offsetX, + offsetY, + opacity, + colors[0], + colors[1], + colors[2], + size, + fontfile + ); return this; } diff --git a/phalcon/Image/Adapter/Gd.zep b/phalcon/Image/Adapter/Gd.zep index efbebce5ee1..88b8a245368 100644 --- a/phalcon/Image/Adapter/Gd.zep +++ b/phalcon/Image/Adapter/Gd.zep @@ -28,7 +28,6 @@ class Gd extends Adapter let this->file = file; if file_exists(this->file) { - let this->realpath = realpath(this->file); let imageinfo = getimagesize(this->file); @@ -43,29 +42,33 @@ class Gd extends Adapter case 1: let this->image = imagecreatefromgif(this->file); break; + case 2: let this->image = imagecreatefromjpeg(this->file); break; + case 3: let this->image = imagecreatefrompng(this->file); break; + case 15: let this->image = imagecreatefromwbmp(this->file); break; + case 16: let this->image = imagecreatefromxbm(this->file); break; + default: if this->mime { throw new Exception( "Installed GD does not support " . this->mime . " images" ); - } else { - throw new Exception( - "Installed GD does not support such images" - ); } - break; + + throw new Exception( + "Installed GD does not support such images" + ); } imagesavealpha(this->image, true); @@ -78,6 +81,7 @@ class Gd extends Adapter } let this->image = imagecreatetruecolor(width, height); + imagealphablending(this->image, true); imagesavealpha(this->image, true); @@ -94,6 +98,7 @@ class Gd extends Adapter var image; let image = this->image; + if typeof image == "resource" { imagedestroy(image); } @@ -137,6 +142,7 @@ class Gd extends Adapter } let version = null; + if defined("GD_VERSION") { let version = GD_VERSION; } else { @@ -160,10 +166,12 @@ class Gd extends Adapter let background = this->processCreate(this->width, this->height); let color = imagecolorallocatealpha(background, r, g, b, opacity); + imagealphablending(background, true); if imagecopy(background, this->image, 0, 0, 0, 0, this->width, this->height) { imagedestroy(this->image); + let this->image = background; } } @@ -171,9 +179,12 @@ class Gd extends Adapter protected function processBlur(int radius) { int i; + let i = 0; + while i < radius { imagefilter(this->image, IMG_FILTER_GAUSSIAN_BLUR); + let i++; } } @@ -225,7 +236,10 @@ class Gd extends Adapter var maskImage, newimage, tempImage, color, index, r, g, b; int mask_width, mask_height, x, y, alpha; - let maskImage = imagecreatefromstring(mask->render()); + let maskImage = imagecreatefromstring( + mask->render() + ); + let mask_width = (int) imagesx(maskImage); let mask_height = (int) imagesy(maskImage); let alpha = 127; @@ -233,6 +247,7 @@ class Gd extends Adapter imagesavealpha(maskImage, true); let newimage = this->processCreate(this->width, this->height); + imagesavealpha(newimage, true); let color = imagecolorallocatealpha(newimage, 0, 0, 0, alpha); @@ -261,11 +276,11 @@ class Gd extends Adapter } let x = 0; - while x < this->width { + while x < this->width { let y = 0; - while y < this->height { + while y < this->height { let index = imagecolorat(maskImage, x, y), color = imagecolorsforindex(maskImage, index); @@ -275,17 +290,22 @@ class Gd extends Adapter let index = imagecolorat(this->image, x, y), color = imagecolorsforindex(this->image, index), - r = color["red"], g = color["green"], b = color["blue"], + r = color["red"], + g = color["green"], + b = color["blue"], color = imagecolorallocatealpha(newimage, r, g, b, alpha); imagesetpixel(newimage, x, y, color); + let y++; } + let x++; } imagedestroy(this->image); imagedestroy(maskImage); + let this->image = newimage; } @@ -295,19 +315,24 @@ class Gd extends Adapter int x, y, x1, y1, x2, y2; let x = 0; + while x < this->width { let y = 0; + while y < this->height { let x1 = x + amount/2; let y1 = y + amount/2; + let color = imagecolorat(this->image, x1, y1); let x2 = x + amount; let y2 = y + amount; + imagefilledrectangle(this->image, x, y, x2, y2, color); let y += amount; } + let x += amount; } } @@ -342,8 +367,8 @@ class Gd extends Adapter ); let offset = 0; - while height >= offset { + while height >= offset { let src_y = this->height - offset - 1; let dst_y = this->height + offset; @@ -359,13 +384,42 @@ class Gd extends Adapter let line = this->processCreate(this->width, 1); - imagecopy(line, this->image, 0, 0, 0, src_y, this->width, 1); - imagefilter(line, IMG_FILTER_COLORIZE, 0, 0, 0, dst_opacity); - imagecopy(reflection, line, 0, dst_y, 0, 0, this->width, 1); + imagecopy( + line, + this->image, + 0, + 0, + 0, + src_y, + this->width, + 1 + ); + + imagefilter( + line, + IMG_FILTER_COLORIZE, + 0, + 0, + 0, + dst_opacity + ); + + imagecopy( + reflection, + line, + 0, + dst_y, + 0, + 0, + this->width, + 1 + ); + let offset++; } imagedestroy(this->image); + let this->image = reflection; let this->width = imagesx(reflection); let this->height = imagesy(reflection); @@ -374,31 +428,26 @@ class Gd extends Adapter protected function processRender(string ext, int quality) { let ext = strtolower(ext); + ob_start(); + if strcmp(ext, "gif") == 0 { imagegif(this->image); - return ob_get_clean(); - } - if strcmp(ext, "jpg") == 0 || strcmp(ext, "jpeg") == 0 { + } elseif strcmp(ext, "jpg") == 0 || strcmp(ext, "jpeg") == 0 { imagejpeg(this->image, null, quality); - return ob_get_clean(); - } - if strcmp(ext, "png") == 0 { + } elseif strcmp(ext, "png") == 0 { imagepng(this->image); - return ob_get_clean(); - } - if strcmp(ext, "wbmp") == 0 { + } elseif strcmp(ext, "wbmp") == 0 { imagewbmp(this->image); - return ob_get_clean(); - } - if strcmp(ext, "xbm") == 0 { + } elseif strcmp(ext, "xbm") == 0 { imagexbm(this->image, null); - return ob_get_clean(); + } else { + throw new Exception( + "Installed GD does not support '" . ext . "' images" + ); } - throw new Exception( - "Installed GD does not support '" . ext . "' images" - ); + return ob_get_clean(); } protected function processResize(int width, int height) @@ -406,7 +455,9 @@ class Gd extends Adapter var image; let image = imagescale(this->image, width, height); + imagedestroy(this->image); + let this->image = image; let this->width = imagesx(image); let this->height = imagesy(image); @@ -416,8 +467,20 @@ class Gd extends Adapter { var image, transparent, width, height; - let transparent = imagecolorallocatealpha(this->image, 0, 0, 0, 127); - let image = imagerotate(this->image, 360 - degrees, transparent, 1); + let transparent = imagecolorallocatealpha( + this->image, + 0, + 0, + 0, + 127 + ); + + let image = imagerotate( + this->image, + 360 - degrees, + transparent, + 1 + ); imagesavealpha(image, TRUE); @@ -426,6 +489,7 @@ class Gd extends Adapter if imagecopymerge(this->image, image, 0, 0, 0, 0, width, height, 100) { imagedestroy(this->image); + let this->image = image; let this->width = width; let this->height = height; @@ -448,42 +512,55 @@ class Gd extends Adapter if strcmp(ext, "gif") == 0 { let this->type = 1; let this->mime = image_type_to_mime_type(this->type); + imagegif(this->image, file); + return true; } + if strcmp(ext, "jpg") == 0 || strcmp(ext, "jpeg") == 0 { let this->type = 2; let this->mime = image_type_to_mime_type(this->type); - if quality >= 0 { if quality < 1 { let quality = 1; } elseif quality > 100 { let quality = 100; } + imagejpeg(this->image, file, quality); } else { imagejpeg(this->image, file); } + return true; } + if strcmp(ext, "png") == 0 { let this->type = 3; let this->mime = image_type_to_mime_type(this->type); + imagepng(this->image, file); + return true; } + if strcmp(ext, "wbmp") == 0 { let this->type = 15; let this->mime = image_type_to_mime_type(this->type); + imagewbmp(this->image, file); + return true; } + if strcmp(ext, "xbm") == 0 { let this->type = 16; let this->mime = image_type_to_mime_type(this->type); + imagexbm(this->image, file); + return true; } @@ -518,7 +595,6 @@ class Gd extends Adapter let opacity = (int) round(abs((opacity * 127 / 100) - 127)); if fontfile { - let space = imagettfbbox(size, 0, fontfile, text); if isset space[0] { @@ -544,6 +620,7 @@ class Gd extends Adapter } let color = imagecolorallocatealpha(this->image, r, g, b, opacity); + let angle = 0; imagettftext( @@ -569,6 +646,7 @@ class Gd extends Adapter } let color = imagecolorallocatealpha(this->image, r, g, b, opacity); + imagestring(this->image, size, offsetX, offsetY, text, color); } } @@ -578,7 +656,9 @@ class Gd extends Adapter var overlay, color; int width, height; - let overlay = imagecreatefromstring(watermark->render()); + let overlay = imagecreatefromstring( + watermark->render() + ); imagesavealpha(overlay, true); diff --git a/phalcon/Image/Adapter/Imagick.zep b/phalcon/Image/Adapter/Imagick.zep index 9b6f581f9f5..898bee7ff32 100644 --- a/phalcon/Image/Adapter/Imagick.zep +++ b/phalcon/Image/Adapter/Imagick.zep @@ -65,6 +65,7 @@ class Imagick extends Adapter if this->type == 1 { let image = this->image->coalesceImages(); + this->image->clear(); this->image->destroy(); @@ -162,15 +163,18 @@ class Imagick extends Adapter let pixel2 = new \ImagickPixel("transparent"); let background = new \Imagick(); + this->image->setIteratorIndex(0); loop { background->newImage(this->width, this->height, pixel1); + if !background->getImageAlphaChannel() { background->setImageAlphaChannel( constant("Imagick::ALPHACHANNEL_SET") ); } + background->setImageBackgroundColor(pixel2); background->evaluateImage( @@ -216,6 +220,7 @@ class Imagick extends Adapter loop { this->image->blurImage(radius, 100); + if this->image->nextImage() === false { break; } @@ -228,12 +233,12 @@ class Imagick extends Adapter protected function processCrop(int width, int height, int offsetX, int offsetY) { var image; + let image = this->image; image->setIteratorIndex(0); loop { - image->cropImage(width, height, offsetX, offsetY); image->setImagePage(width, height, 0, 0); @@ -254,6 +259,7 @@ class Imagick extends Adapter var func; let func = "flipImage"; + if direction == \Phalcon\Image::HORIZONTAL { let func = "flopImage"; } @@ -262,6 +268,7 @@ class Imagick extends Adapter loop { this->image->{func}(); + if this->image->nextImage() === false { break; } @@ -280,6 +287,7 @@ class Imagick extends Adapter protected function processLiquidRescale(int width, int height, int deltaX, int rigidity) { var ret, image; + let image = this->image; image->setIteratorIndex(0); @@ -314,7 +322,10 @@ class Imagick extends Adapter let mask = new \Imagick(); - mask->readImageBlob(image->render()); + mask->readImageBlob( + image->render() + ); + this->image->setIteratorIndex(0); loop { @@ -357,6 +368,7 @@ class Imagick extends Adapter loop { this->image->scaleImage(width, height); this->image->scaleImage(this->width, this->height); + if this->image->nextImage() === false{ break; } @@ -380,8 +392,21 @@ class Imagick extends Adapter loop { reflection->flipImage(); - reflection->cropImage(reflection->getImageWidth(), height, 0, 0); - reflection->setImagePage(reflection->getImageWidth(), height, 0, 0); + + reflection->cropImage( + reflection->getImageWidth(), + height, + 0, + 0 + ); + + reflection->setImagePage( + reflection->getImageWidth(), + height, + 0, + 0 + ); + if reflection->nextImage() === false { break; } @@ -433,9 +458,18 @@ class Imagick extends Adapter loop { image->newImage(this->width, height, pixel); - image->setImageAlphaChannel(constant("Imagick::ALPHACHANNEL_SET")); - image->setColorspace(this->image->getColorspace()); - image->setImageDelay(this->image->getImageDelay()); + + image->setImageAlphaChannel( + constant("Imagick::ALPHACHANNEL_SET") + ); + + image->setColorspace( + this->image->getColorspace() + ); + + image->setImageDelay( + this->image->getImageDelay() + ); let ret = image->compositeImage( this->image, @@ -507,6 +541,7 @@ class Imagick extends Adapter constant("Imagick::COMPRESSION_JPEG") ); } + image->setImageCompressionQuality(quality); } @@ -519,12 +554,14 @@ class Imagick extends Adapter protected function processResize(int width, int height) { var image; + let image = this->image; image->setIteratorIndex(0); loop { image->scaleImage(width, height); + if image->nextImage() === false { break; } @@ -547,7 +584,14 @@ class Imagick extends Adapter loop { this->image->rotateImage(pixel, degrees); - this->image->setImagePage(this->width, this->height, 0, 0); + + this->image->setImagePage( + this->width, + this->height, + 0, + 0 + ); + if this->image->nextImage() === false { break; } @@ -574,9 +618,13 @@ class Imagick extends Adapter if strcasecmp(ext, "gif") == 0 { this->image->optimizeImageLayers(); - let fp= fopen(file, "w"); + + let fp = fopen(file, "w"); + this->image->writeImagesFile(fp); + fclose(fp); + return; } else { if strcasecmp(ext, "jpg") == 0 || strcasecmp(ext, "jpeg") == 0 { @@ -591,8 +639,10 @@ class Imagick extends Adapter } elseif quality > 100 { let quality = 100; } + this->image->setImageCompressionQuality(quality); } + this->image->writeImage(file); } } @@ -609,6 +659,7 @@ class Imagick extends Adapter loop { this->image->sharpenImage(0, amount); + if this->image->nextImage() === false { break; } @@ -626,7 +677,9 @@ class Imagick extends Adapter draw = new \ImagickDraw(), color = sprintf("rgb(%d, %d, %d)", r, g, b); - draw->setFillColor(new \ImagickPixel(color)); + draw->setFillColor( + new \ImagickPixel(color) + ); if fontfile { draw->setFont(fontfile); @@ -644,24 +697,14 @@ class Imagick extends Adapter if typeof offsetX == "boolean" { if typeof offsetY == "boolean" { - let offsetX = 0, + let offsetX = 0, offsetY = 0; - if offsetX && offsetY { - let gravity = constant("Imagick::GRAVITY_SOUTHEAST"); - } else { - if offsetX { - let gravity = constant("Imagick::GRAVITY_EAST"); - } else { - if offsetY { - let gravity = constant("Imagick::GRAVITY_SOUTH"); - } else { - let gravity = constant("Imagick::GRAVITY_CENTER"); - } - } - } + + let gravity = constant("Imagick::GRAVITY_CENTER"); } else { if typeof offsetY == "int" { let y = (int) offsetY; + if offsetX { if y < 0 { let offsetX = 0, @@ -686,6 +729,7 @@ class Imagick extends Adapter } else { if typeof offsetX == "int" { let x = (int) offsetX; + if offsetX { if typeof offsetY == "boolean" { if offsetY { @@ -743,6 +787,7 @@ class Imagick extends Adapter loop { this->image->annotateImage(draw, offsetX, offsetY, 0, text); + if this->image->nextImage() === false { break; } @@ -761,7 +806,9 @@ class Imagick extends Adapter let opacity = opacity / 100, watermark = new \Imagick(); - watermark->readImageBlob(image->render()); + watermark->readImageBlob( + image->render() + ); watermark->evaluateImage( constant("Imagick::EVALUATE_MULTIPLY"), diff --git a/phalcon/Loader.zep b/phalcon/Loader.zep index 13e6baed2e5..04fc1679b5f 100644 --- a/phalcon/Loader.zep +++ b/phalcon/Loader.zep @@ -44,7 +44,6 @@ use Phalcon\Events\EventsAwareInterface; */ class Loader implements EventsAwareInterface { - protected checkedPath = null; /** @@ -62,6 +61,7 @@ class Loader implements EventsAwareInterface * @var array */ protected extensions = ["php"]; + protected fileCheckingCallback = "is_file"; /** @@ -90,10 +90,11 @@ class Loader implements EventsAwareInterface public function autoLoad(string! className) -> bool { var eventsManager, classes, extensions, filePath, ds, fixedDirectory, - directories, ns, namespaces, nsPrefix, - directory, fileName, extension, nsClassName, fileCheckingCallback; + directories, ns, namespaces, nsPrefix, directory, fileName, + extension, nsClassName, fileCheckingCallback; let eventsManager = this->eventsManager; + if typeof eventsManager == "object" { eventsManager->fire("loader:beforeCheckClass", this, className); } @@ -102,12 +103,15 @@ class Loader implements EventsAwareInterface * First we check for static paths for classes */ let classes = this->classes; + if fetch filePath, classes[className] { if typeof eventsManager == "object" { let this->foundPath = filePath; eventsManager->fire("loader:pathFound", this, filePath); } + require filePath; + return true; } @@ -124,7 +128,6 @@ class Loader implements EventsAwareInterface let fileCheckingCallback = this->fileCheckingCallback; for nsPrefix, directories in namespaces { - /** * The class name must start with the current namespace */ @@ -151,7 +154,6 @@ class Loader implements EventsAwareInterface let fixedDirectory = rtrim(directory, ds) . ds; for extension in extensions { - let filePath = fixedDirectory . fileName . "." . extension; /** @@ -159,6 +161,7 @@ class Loader implements EventsAwareInterface */ if typeof eventsManager == "object" { let this->checkedPath = filePath; + eventsManager->fire("loader:beforeCheckPath", this); } @@ -167,9 +170,9 @@ class Loader implements EventsAwareInterface * exists */ if call_user_func(fileCheckingCallback, filePath) { - if typeof eventsManager == "object" { let this->foundPath = filePath; + eventsManager->fire("loader:pathFound", this, filePath); } @@ -198,14 +201,12 @@ class Loader implements EventsAwareInterface let directories = this->directories; for directory in directories { - /** * Add a trailing directory separator if the user forgot to do that */ let fixedDirectory = rtrim(directory, ds) . ds; for extension in extensions { - /** * Create a possible path for the file */ @@ -213,19 +214,24 @@ class Loader implements EventsAwareInterface if typeof eventsManager == "object" { let this->checkedPath = filePath; - eventsManager->fire("loader:beforeCheckPath", this, filePath); + + eventsManager->fire( + "loader:beforeCheckPath", + this, + filePath + ); } /** * Check in every directory if the class exists here */ if call_user_func(fileCheckingCallback, filePath) { - /** * Call 'pathFound' event */ if typeof eventsManager == "object" { let this->foundPath = filePath; + eventsManager->fire("loader:pathFound", this, filePath); } @@ -337,13 +343,17 @@ class Loader implements EventsAwareInterface * Check if the file specified even exists */ if call_user_func(fileCheckingCallback, filePath) { - /** * Call 'pathFound' event */ if typeof this->eventsManager == "object" { let this->foundPath = filePath; - this->eventsManager->fire("loader:pathFound", this, filePath); + + this->eventsManager->fire( + "loader:pathFound", + this, + filePath + ); } /** @@ -368,10 +378,15 @@ class Loader implements EventsAwareInterface /** * Registers directories & namespaces to PHP's autoload */ - spl_autoload_register([this, "autoLoad"], true, prepend); + spl_autoload_register( + [this, "autoLoad"], + true, + prepend + ); let this->registered = true; } + return this; } @@ -460,6 +475,7 @@ class Loader implements EventsAwareInterface public function setExtensions(array! extensions) -> { let this->extensions = extensions; + return this; } @@ -501,9 +517,16 @@ class Loader implements EventsAwareInterface public function unregister() -> { if this->registered === true { - spl_autoload_unregister([this, "autoLoad"]); + spl_autoload_unregister( + [ + this, + "autoLoad" + ] + ); + let this->registered = false; } + return this; } @@ -512,6 +535,7 @@ class Loader implements EventsAwareInterface var localPaths, name, paths, prepared; let prepared = []; + for name, paths in $namespace { if typeof paths != "array" { let localPaths = [paths]; diff --git a/phalcon/Loader/Exception.zep b/phalcon/Loader/Exception.zep index 877dfc387f9..05ab9fc3d4b 100644 --- a/phalcon/Loader/Exception.zep +++ b/phalcon/Loader/Exception.zep @@ -14,7 +14,6 @@ namespace Phalcon\Loader; * Phalcon\Loader\Exception * * Exceptions thrown in Phalcon\Loader will use this class - * */ class Exception extends \Phalcon\Exception { diff --git a/phalcon/Logger.zep b/phalcon/Logger.zep index 3188f2f1b9b..5ba75358db7 100644 --- a/phalcon/Logger.zep +++ b/phalcon/Logger.zep @@ -89,6 +89,7 @@ class Logger implements LoggerInterface public function __construct(string! name, array! adapters = []) -> void { let this->name = name; + this->setAdapters(adapters); } @@ -97,8 +98,6 @@ class Logger implements LoggerInterface * * @param string name The name of the adapter * @param adapter The adapter to add to the stack - * - * @return */ public function addAdapter(string name, adapter) -> { @@ -114,9 +113,6 @@ class Logger implements LoggerInterface * trigger the SMS alerts and wake you up. * * @param string message - * @param array context - * - * @return void */ public function alert(message, array context = []) -> void { @@ -129,9 +125,6 @@ class Logger implements LoggerInterface * Example: Application component unavailable, unexpected exception. * * @param string message - * @param array context - * - * @return void */ public function critical(message, array context = []) -> void { @@ -142,9 +135,6 @@ class Logger implements LoggerInterface * Detailed debug information. * * @param string message - * @param array context - * - * @return void */ public function debug(message, array context = []) -> void { @@ -156,9 +146,6 @@ class Logger implements LoggerInterface * be logged and monitored. * * @param string message - * @param array context - * - * @return void */ public function error(message, array context = []) -> void { @@ -169,9 +156,6 @@ class Logger implements LoggerInterface * System is unusable. * * @param string message - * @param array context - * - * @return void */ public function emergency(message, array context = []) -> void { @@ -179,12 +163,7 @@ class Logger implements LoggerInterface } /** - * System is unusable. - * - * @param string message - * @param array context - * - * @return void + * Exclude certain adapters. */ public function excludeAdapters(array adapters = []) -> { @@ -211,7 +190,6 @@ class Logger implements LoggerInterface * * @param string name The name of the adapter * - * @return * @throws */ public function getAdapter(string name) -> @@ -239,8 +217,6 @@ class Logger implements LoggerInterface /** * Returns the name of the logger - * - * @return string */ public function getName() -> string { @@ -253,9 +229,6 @@ class Logger implements LoggerInterface * Example: User logs in, SQL logs. * * @param string message - * @param array context - * - * @return void */ public function info(message, array context = []) -> void { @@ -265,11 +238,8 @@ class Logger implements LoggerInterface /** * Logs with an arbitrary level. * - * @param mixed $level + * @param mixed level * @param string message - * @param array context - * - * @return void */ public function log(level, message, array context = []) -> void { @@ -284,9 +254,6 @@ class Logger implements LoggerInterface * Normal but significant events. * * @param string message - * @param array context - * - * @return void */ public function notice(message, array context = []) -> void { @@ -298,7 +265,6 @@ class Logger implements LoggerInterface * * @param string name The name of the adapter * - * @return * @throws */ public function removeAdapter(string name) -> @@ -322,8 +288,6 @@ class Logger implements LoggerInterface * Sets the adapters stack overriding what is already there * * @param array adapters An array of adapters - * - * @return */ public function setAdapters(array! adapters) -> { @@ -339,9 +303,6 @@ class Logger implements LoggerInterface * that are not necessarily wrong. * * @param string message - * @param array context - * - * @return void */ public function warning(message, array context = []) -> void { @@ -353,9 +314,7 @@ class Logger implements LoggerInterface * * @param int level * @param string message - * @param array context * - * @return bool * @throws */ protected function addMessage(int level, string message, array context = []) -> bool @@ -370,6 +329,7 @@ class Logger implements LoggerInterface } let levels = this->getLevels(); + if !fetch levelName, levels[level] { let levelName = levels[self::CUSTOM]; } @@ -380,12 +340,16 @@ class Logger implements LoggerInterface * Compare the actual adapters array with the excluded one. Whatever * the difference is, that is the array of adapters that we will log * this message to. By default `excluded` is empty so the message will - * be loggged to all registered adapters + * be logged to all registered adapters */ - let keys = array_diff(array_keys(registered), excluded); + let keys = array_diff( + array_keys(registered), + excluded + ); for key in keys { let adapter = registered[key]; + adapter->process(item); } @@ -399,8 +363,6 @@ class Logger implements LoggerInterface /** * Returns an array of log levels with integer to string conversion - * - * @return array */ protected function getLevels() -> array { @@ -421,8 +383,6 @@ class Logger implements LoggerInterface * Converts the level from string/word to an integer * * @param string|int level - * - * @return int */ private function getLevelNumber(level) -> int { @@ -443,6 +403,6 @@ class Logger implements LoggerInterface } } - return self::CUSTOM; + return self::CUSTOM; } } diff --git a/phalcon/Logger/Adapter/AbstractAdapter.zep b/phalcon/Logger/Adapter/AbstractAdapter.zep index 25393233680..f0a71dd8f9e 100644 --- a/phalcon/Logger/Adapter/AbstractAdapter.zep +++ b/phalcon/Logger/Adapter/AbstractAdapter.zep @@ -59,8 +59,8 @@ abstract class AbstractAdapter implements AdapterInterface } /** - * Adds a message to the queue - */ + * Adds a message to the queue + */ public function add( item) -> { let this->queue[] = item; @@ -69,8 +69,8 @@ abstract class AbstractAdapter implements AdapterInterface } /** - * Starts a transaction - */ + * Starts a transaction + */ public function begin() -> { let this->inTransaction = true; @@ -79,8 +79,8 @@ abstract class AbstractAdapter implements AdapterInterface } /** - * Commits the internal transaction - */ + * Commits the internal transaction + */ public function commit() -> { var inTransaction, item, queue; @@ -113,6 +113,7 @@ abstract class AbstractAdapter implements AdapterInterface if typeof this->formatter !== "object" { let className = "Phalcon\\Logger\\Formatter\\" . this->defaultFormatter; + let this->formatter = new {className}(); } @@ -130,14 +131,11 @@ abstract class AbstractAdapter implements AdapterInterface /** * Processes the message in the adapter */ - public function process( item) -> void - { - throw new Exception("This method cannot be called directly in the adapter"); - } + abstract public function process( item) -> void; /** - * Rollbacks the internal transaction - */ + * Rollbacks the internal transaction + */ public function rollback() -> { var inTransaction; diff --git a/phalcon/Logger/Adapter/AdapterInterface.zep b/phalcon/Logger/Adapter/AdapterInterface.zep index 278c3314037..0216aff9e45 100644 --- a/phalcon/Logger/Adapter/AdapterInterface.zep +++ b/phalcon/Logger/Adapter/AdapterInterface.zep @@ -21,23 +21,23 @@ use Phalcon\Logger\Item; interface AdapterInterface { /** - * Adds a message in the queue - */ + * Adds a message in the queue + */ public function add( item) -> void; /** - * Starts a transaction - */ + * Starts a transaction + */ public function begin() -> ; /** - * Closes the logger - */ + * Closes the logger + */ public function close() -> bool; /** - * Commits the internal transaction - */ + * Commits the internal transaction + */ public function commit() -> ; /** @@ -46,13 +46,13 @@ interface AdapterInterface public function getFormatter() -> ; /** - * Processes the message in the adapter - */ + * Processes the message in the adapter + */ public function process( item) -> void; /** - * Rollbacks the internal transaction - */ + * Rollbacks the internal transaction + */ public function rollback() -> ; /** diff --git a/phalcon/Logger/Adapter/Stream.zep b/phalcon/Logger/Adapter/Stream.zep index ceff99ab68b..c46bb30d6f2 100644 --- a/phalcon/Logger/Adapter/Stream.zep +++ b/phalcon/Logger/Adapter/Stream.zep @@ -112,8 +112,13 @@ class Stream extends AbstractAdapter if !is_resource(this->handler) { let $this->handler = null; + throw new \UnexpectedValueException( - sprintf("The file '%s' cannot be opened with mode '%s'", this->name, this->mode) + sprintf( + "The file '%s' cannot be opened with mode '%s'", + this->name, + this->mode + ) ); } } diff --git a/phalcon/Logger/Adapter/Syslog.zep b/phalcon/Logger/Adapter/Syslog.zep index 35efe4ada41..39b6f5eba73 100644 --- a/phalcon/Logger/Adapter/Syslog.zep +++ b/phalcon/Logger/Adapter/Syslog.zep @@ -130,9 +130,9 @@ class Syslog extends AbstractAdapter ); } - let opened = true, + let opened = true, this->opened = opened, - level = this->logLevelToSyslog(message[1]); + level = this->logLevelToSyslog(message[1]); syslog(level, message[1]); } diff --git a/phalcon/Logger/Factory.zep b/phalcon/Logger/Factory.zep index 6d717a7613c..c248796aa48 100644 --- a/phalcon/Logger/Factory.zep +++ b/phalcon/Logger/Factory.zep @@ -19,16 +19,16 @@ use Phalcon\Logger; * Loads Logger Adapter class using 'adapter' option * * - * use Phalcon\Logger\Factory; + * use Phalcon\Logger\Factory; * - * $options = [ - * 'adapters' => [ - * 'type' => 'stream', - * 'name' => 'log.txt', - * ] - * ]; + * $options = [ + * 'adapters' => [ + * 'type' => 'stream', + * 'name' => 'log.txt', + * ] + * ]; * - * $logger = Factory::load($options); + * $logger = Factory::load($options); * */ class Factory extends BaseFactory diff --git a/phalcon/Logger/Formatter/AbstractFormatter.zep b/phalcon/Logger/Formatter/AbstractFormatter.zep index a035947a427..d157018162e 100644 --- a/phalcon/Logger/Formatter/AbstractFormatter.zep +++ b/phalcon/Logger/Formatter/AbstractFormatter.zep @@ -27,11 +27,14 @@ abstract class AbstractFormatter implements FormatterInterface if typeof context == "array" && count(context) > 0 { let replace = []; + for key, value in context { let replace["{" . key . "}"] = value; } + return strtr(message, replace); } + return message; } } diff --git a/phalcon/Logger/Formatter/FormatterInterface.zep b/phalcon/Logger/Formatter/FormatterInterface.zep index b80c13d2117..91dbe6c629c 100644 --- a/phalcon/Logger/Formatter/FormatterInterface.zep +++ b/phalcon/Logger/Formatter/FormatterInterface.zep @@ -21,10 +21,6 @@ interface FormatterInterface { /** * Applies a format to an item - * - * @param item - * - * @return string|array */ public function format( item) -> string | array; } diff --git a/phalcon/Logger/Formatter/Json.zep b/phalcon/Logger/Formatter/Json.zep index 1790cddc244..55f7b1e38cd 100644 --- a/phalcon/Logger/Formatter/Json.zep +++ b/phalcon/Logger/Formatter/Json.zep @@ -41,10 +41,6 @@ class Json extends AbstractFormatter /** * Applies a format to a message before sent it to the internal log - * - * @param item - * - * @return string */ public function format( item) -> string { diff --git a/phalcon/Logger/Formatter/Line.zep b/phalcon/Logger/Formatter/Line.zep index 1dc7adad1b5..8a479556d79 100644 --- a/phalcon/Logger/Formatter/Line.zep +++ b/phalcon/Logger/Formatter/Line.zep @@ -52,10 +52,6 @@ class Line extends AbstractFormatter /** * Applies a format to a message before sent it to the internal log - * - * @param item - * - * @return string */ public function format( item) -> string { diff --git a/phalcon/Logger/Formatter/Syslog.zep b/phalcon/Logger/Formatter/Syslog.zep index ee63d338ce4..d641c6d0f3c 100644 --- a/phalcon/Logger/Formatter/Syslog.zep +++ b/phalcon/Logger/Formatter/Syslog.zep @@ -22,10 +22,6 @@ class Syslog extends AbstractFormatter { /** * Applies a format to a message before sent it to the internal log - * - * @param item - * - * @return array */ public function format( item) -> array { diff --git a/phalcon/Logger/Item.zep b/phalcon/Logger/Item.zep index 96b6178c6fd..93a7af48011 100644 --- a/phalcon/Logger/Item.zep +++ b/phalcon/Logger/Item.zep @@ -50,12 +50,6 @@ class Item /** * Phalcon\Logger\Item constructor - * - * @param string message - * @param string name - * @param int type - * @param int time - * @param array context */ public function __construct(string message, string name, int type, int time = 0, var context = []) { diff --git a/phalcon/Messages/Exception.zep b/phalcon/Messages/Exception.zep index 531bd9f86df..dc3c84fc55a 100644 --- a/phalcon/Messages/Exception.zep +++ b/phalcon/Messages/Exception.zep @@ -14,7 +14,6 @@ namespace Phalcon\Messages; * Phalcon\Validation\Exception * * Exceptions thrown in Phalcon\Messages\* classes will use this class - * */ class Exception extends \Phalcon\Exception { diff --git a/phalcon/Messages/Message.zep b/phalcon/Messages/Message.zep index 1d6133e4d34..c476b5dbd8c 100644 --- a/phalcon/Messages/Message.zep +++ b/phalcon/Messages/Message.zep @@ -79,8 +79,8 @@ class Message implements MessageInterface, \JsonSerializable } /** - * Serializes the object for json_encode - */ + * Serializes the object for json_encode + */ public function jsonSerialize() -> array { return [ @@ -98,6 +98,7 @@ class Message implements MessageInterface, \JsonSerializable public function setCode(int code) -> { let this->code = code; + return this; } @@ -107,6 +108,7 @@ class Message implements MessageInterface, \JsonSerializable public function setField(var field) -> { let this->field = field; + return this; } @@ -116,6 +118,7 @@ class Message implements MessageInterface, \JsonSerializable public function setMessage(string! message) -> { let this->message = message; + return this; } @@ -125,6 +128,7 @@ class Message implements MessageInterface, \JsonSerializable public function setMetaData(array! metaData) -> { let this->metaData = metaData; + return this; } @@ -134,6 +138,7 @@ class Message implements MessageInterface, \JsonSerializable public function setType(string! type) -> { let this->type = type; + return this; } } diff --git a/phalcon/Messages/Messages.zep b/phalcon/Messages/Messages.zep index f5df8b9f4f0..0464ead1840 100644 --- a/phalcon/Messages/Messages.zep +++ b/phalcon/Messages/Messages.zep @@ -71,8 +71,8 @@ class Messages implements \ArrayAccess, \Countable, \Iterator, \JsonSerializable } let currentMessages = this->messages; - if typeof messages == "array" { + if typeof messages == "array" { /** * An array of messages is simply merged into the current one */ @@ -81,10 +81,9 @@ class Messages implements \ArrayAccess, \Countable, \Iterator, \JsonSerializable } else { let finalMessages = messages; } - let this->messages = finalMessages; + let this->messages = finalMessages; } else { - /** * A collection of messages is iterated and appended one-by-one to * the current list @@ -94,6 +93,7 @@ class Messages implements \ArrayAccess, \Countable, \Iterator, \JsonSerializable //} messages->rewind(); + while messages->valid() { let message = messages->current(); this->appendMessage(message); @@ -127,14 +127,13 @@ class Messages implements \ArrayAccess, \Countable, \Iterator, \JsonSerializable let filtered = [], messages = this->messages; - if typeof messages == "array" { + if typeof messages == "array" { /** * A collection of messages is iterated and appended one-by-one to * the current list */ for message in messages { - /** * Get the field name */ @@ -240,6 +239,7 @@ class Messages implements \ArrayAccess, \Countable, \Iterator, \JsonSerializable if typeof message != "object" { throw new Exception("The message must be an object"); } + let this->messages[index] = message; } diff --git a/phalcon/Mvc/Application.zep b/phalcon/Mvc/Application.zep index 3778a1e28bd..cdc2b3166b7 100644 --- a/phalcon/Mvc/Application.zep +++ b/phalcon/Mvc/Application.zep @@ -69,7 +69,6 @@ use Phalcon\Mvc\ModuleDefinitionInterface; */ class Application extends BaseApplication { - protected implicitView = true; protected sendCookies = true; @@ -82,11 +81,12 @@ class Application extends BaseApplication public function handle(string! uri) -> | bool { var container, eventsManager, router, dispatcher, response, view, - module, moduleObject, moduleName, className, path, - implicitView, returnedResponse, controller, possibleResponse, - renderStatus, matchedRoute, match; + module, moduleObject, moduleName, className, path, implicitView, + returnedResponse, controller, possibleResponse, renderStatus, + matchedRoute, match; let container = this->container; + if typeof container != "object" { throw new Exception( Exception::containerServiceNotFound("internal services") @@ -117,10 +117,11 @@ class Application extends BaseApplication * The whole dispatcher+view behavior can be overridden by the developer */ let matchedRoute = router->getMatchedRoute(); + if typeof matchedRoute == "object" { let match = matchedRoute->getMatch(); - if match !== null { + if match !== null { if match instanceof \Closure { let match = \Closure::bind(match, container); } @@ -138,7 +139,9 @@ class Application extends BaseApplication */ if typeof possibleResponse == "string" { let response = container->getShared("response"); + response->setContent(possibleResponse); + return response; } @@ -146,12 +149,11 @@ class Application extends BaseApplication * If the returned string is a ResponseInterface use it as * response */ - if typeof possibleResponse == "object" { - if possibleResponse instanceof ResponseInterface { - possibleResponse->sendHeaders(); - possibleResponse->sendCookies(); - return possibleResponse; - } + if typeof possibleResponse == "object" && possibleResponse instanceof ResponseInterface { + possibleResponse->sendHeaders(); + possibleResponse->sendCookies(); + + return possibleResponse; } } } @@ -160,6 +162,7 @@ class Application extends BaseApplication * If the router doesn't return a valid module we use the default module */ let moduleName = router->getModuleName(); + if !moduleName { let moduleName = this->defaultModule; } @@ -170,7 +173,6 @@ class Application extends BaseApplication * Process the module definition */ if moduleName { - if typeof eventsManager == "object" { if eventsManager->fire("application:beforeStartModule", this, moduleName) === false { return false; @@ -194,7 +196,6 @@ class Application extends BaseApplication * class */ if typeof module == "array" { - /** * Class name used to load the module definition */ @@ -225,9 +226,7 @@ class Application extends BaseApplication */ moduleObject->registerAutoloaders(container); moduleObject->registerServices(container); - } else { - /** * A module definition object, can be a Closure instance */ @@ -265,6 +264,7 @@ class Application extends BaseApplication * Assign the values passed from the router */ let dispatcher = container->getShared("dispatcher"); + dispatcher->setModuleName(router->getModuleName()); dispatcher->setNamespaceName(router->getNamespaceName()); dispatcher->setControllerName(router->getControllerName()); @@ -300,18 +300,17 @@ class Application extends BaseApplication /** * Returning false from an action cancels the view */ - if typeof possibleResponse == "boolean" && possibleResponse === false { + if possibleResponse === false { let response = container->getShared("response"); } else { - /** * Returning a string makes use it as the body of the response */ if typeof possibleResponse == "string" { let response = container->getShared("response"); + response->setContent(possibleResponse); } else { - /** * Check if the returned object is already a response */ @@ -330,7 +329,6 @@ class Application extends BaseApplication */ if returnedResponse === false && implicitView === true { if typeof controller == "object" { - let renderStatus = true; /** @@ -366,22 +364,22 @@ class Application extends BaseApplication } if returnedResponse === true { - /** * We don't need to create a response because there is one * already created */ let response = possibleResponse; } else { - let response = container->getShared("response"); - if implicitView === true { + if implicitView === true { /** * The content returned by the view is passed to the * response service */ - response->setContent(view->getContent()); + response->setContent( + view->getContent() + ); } } } @@ -420,6 +418,7 @@ class Application extends BaseApplication public function sendCookiesOnHandleRequest(bool sendCookies) -> { let this->sendCookies = sendCookies; + return this; } @@ -430,6 +429,7 @@ class Application extends BaseApplication public function sendHeadersOnHandleRequest(bool sendHeaders) -> { let this->sendHeaders = sendHeaders; + return this; } @@ -440,6 +440,7 @@ class Application extends BaseApplication public function useImplicitView(bool implicitView) -> { let this->implicitView = implicitView; + return this; } } diff --git a/phalcon/Mvc/Collection/Document.zep b/phalcon/Mvc/Collection/Document.zep index e3a9e6e27eb..aa3b419af13 100644 --- a/phalcon/Mvc/Collection/Document.zep +++ b/phalcon/Mvc/Collection/Document.zep @@ -27,10 +27,12 @@ class Document implements EntityInterface, \ArrayAccess public function offsetGet(var index) -> var { var value; - if fetch value, this->{index} { - return value; + + if !fetch value, this->{index} { + throw new Exception("The index does not exist in the row"); } - throw new Exception("The index does not exist in the row"); + + return value; } /** @@ -67,10 +69,12 @@ class Document implements EntityInterface, \ArrayAccess public function readAttribute(string! attribute) -> var | null { var value; - if fetch value, this->{attribute} { - return value; + + if !fetch value, this->{attribute} { + return null; } - return null; + + return value; } /** diff --git a/phalcon/Mvc/Controller.zep b/phalcon/Mvc/Controller.zep index 33bf8e3491b..2d43646a552 100644 --- a/phalcon/Mvc/Controller.zep +++ b/phalcon/Mvc/Controller.zep @@ -54,7 +54,6 @@ use Phalcon\Di\Injectable; */ abstract class Controller extends Injectable implements ControllerInterface { - /** * Phalcon\Mvc\Controller constructor */ diff --git a/phalcon/Mvc/Dispatcher.zep b/phalcon/Mvc/Dispatcher.zep index efb06d1eb9a..f9e2f707d22 100644 --- a/phalcon/Mvc/Dispatcher.zep +++ b/phalcon/Mvc/Dispatcher.zep @@ -41,7 +41,6 @@ use Phalcon\Dispatcher as BaseDispatcher; */ class Dispatcher extends BaseDispatcher implements DispatcherInterface { - protected defaultAction = "index"; protected defaultHandler = "index"; @@ -107,6 +106,7 @@ class Dispatcher extends BaseDispatcher implements DispatcherInterface var eventsManager; let eventsManager = this->eventsManager; + if typeof eventsManager == "object" { eventsManager->fire("dispatch:beforeForward", this, forward); } @@ -201,7 +201,9 @@ class Dispatcher extends BaseDispatcher implements DispatcherInterface protected function handleException(<\Exception> exception) { var eventsManager; + let eventsManager = this->eventsManager; + if typeof eventsManager == "object" { if eventsManager->fire("dispatch:beforeException", this, exception) === false { return false; @@ -217,6 +219,7 @@ class Dispatcher extends BaseDispatcher implements DispatcherInterface var container, response, exception; let container = this->container; + if typeof container != "object" { throw new Exception( Exception::containerServiceNotFound("the 'response' service"), diff --git a/phalcon/Mvc/Micro.zep b/phalcon/Mvc/Micro.zep index b2d72ee52c0..9de684cb835 100644 --- a/phalcon/Mvc/Micro.zep +++ b/phalcon/Mvc/Micro.zep @@ -95,6 +95,7 @@ class Micro extends Injectable implements \ArrayAccess public function after(handler) -> { let this->afterHandlers[] = handler; + return this; } @@ -102,11 +103,11 @@ class Micro extends Injectable implements \ArrayAccess * Appends a afterBinding middleware to be called after model binding * * @param callable handler - * @return \Phalcon\Mvc\Micro */ public function afterBinding(handler) -> { let this->afterBindingHandlers[] = handler; + return this; } @@ -118,6 +119,7 @@ class Micro extends Injectable implements \ArrayAccess public function before(handler) -> { let this->beforeHandlers[] = handler; + return this; } @@ -160,6 +162,7 @@ class Micro extends Injectable implements \ArrayAccess public function error(var handler) -> { let this->errorHandler = handler; + return this; } @@ -171,6 +174,7 @@ class Micro extends Injectable implements \ArrayAccess public function finish(handler) -> { let this->finishHandlers[] = handler; + return this; } @@ -223,11 +227,11 @@ class Micro extends Injectable implements \ArrayAccess let modelBinder = this->modelBinder; - if modelBinder != null { - return modelBinder->getBoundModels(); + if modelBinder == null { + return []; } - return []; + return modelBinder->getBoundModels(); } /** @@ -264,8 +268,8 @@ class Micro extends Injectable implements \ArrayAccess var router; let router = this->router; - if typeof router != "object" { + if typeof router != "object" { let router = this->getSharedService("router"); /** @@ -297,8 +301,10 @@ class Micro extends Injectable implements \ArrayAccess var container; let container = this->container; + if typeof container != "object" { let container = new FactoryDefault(); + let this->container = container; } @@ -315,8 +321,10 @@ class Micro extends Injectable implements \ArrayAccess var container; let container = this->container; + if typeof container != "object" { let container = new FactoryDefault(); + let this->container = container; } @@ -339,6 +347,7 @@ class Micro extends Injectable implements \ArrayAccess afterBinding; let container = this->container; + if typeof container != "object" { throw new Exception( Exception::containerServiceNotFound("micro services") @@ -346,13 +355,13 @@ class Micro extends Injectable implements \ArrayAccess } try { - let returnedValue = null; /** * Calling beforeHandle routing */ let eventsManager = this->eventsManager; + if typeof eventsManager == "object" { if eventsManager->fire("micro:beforeHandleRoute", this) === false { return false; @@ -373,8 +382,8 @@ class Micro extends Injectable implements \ArrayAccess * Check if one route was matched */ let matchedRoute = router->getMatchedRoute(); - if typeof matchedRoute == "object" { + if typeof matchedRoute == "object" { if !fetch handler, this->handlers[matchedRoute->getRouteId()] { throw new Exception( "Matched route doesn't have an associated handler" @@ -398,18 +407,16 @@ class Micro extends Injectable implements \ArrayAccess } let beforeHandlers = this->beforeHandlers; - if typeof beforeHandlers == "array" { + if typeof beforeHandlers == "array" { let this->stopped = false; /** * Calls the before handlers */ for before in beforeHandlers { - if typeof before == "object" { if before instanceof MiddlewareInterface { - /** * Call the middleware */ @@ -441,7 +448,7 @@ class Micro extends Injectable implements \ArrayAccess /** * break the execution if the middleware was stopped */ - if this->stopped { + if this->stopped { break; } } @@ -462,8 +469,10 @@ class Micro extends Injectable implements \ArrayAccess */ if typeof handler == "object" && handler instanceof \Closure { let handler = \Closure::bind(handler, this); + if modelBinder != null { let routeName = matchedRoute->getName(); + if routeName != null { let bindCacheKey = "_PHMB_" . routeName; } else { @@ -481,9 +490,7 @@ class Micro extends Injectable implements \ArrayAccess /** * Calling the Handler in the PHP userland */ - - if typeof handler == "array" { - + if typeof handler == "array" { let realHandler = handler[0]; if realHandler instanceof Controller && modelBinder != null { @@ -531,6 +538,7 @@ class Micro extends Injectable implements \ArrayAccess } let afterBindingHandlers = this->afterBindingHandlers; + if typeof afterBindingHandlers == "array" { let this->stopped = false; @@ -538,9 +546,7 @@ class Micro extends Injectable implements \ArrayAccess * Calls the after binding handlers */ for afterBinding in afterBindingHandlers { - if typeof afterBinding == "object" && afterBinding instanceof MiddlewareInterface { - /** * Call the middleware */ @@ -575,8 +581,9 @@ class Micro extends Injectable implements \ArrayAccess break; } } + /** - * Reload the 'stopped' status + * Reload the 'stopped' status */ if this->stopped { return status; @@ -596,18 +603,16 @@ class Micro extends Injectable implements \ArrayAccess } let afterHandlers = this->afterHandlers; - if typeof afterHandlers == "array" { + if typeof afterHandlers == "array" { let this->stopped = false; /** * Calls the after handlers */ for after in afterHandlers { - if typeof after == "object" { if after instanceof MiddlewareInterface { - /** * Call the middleware */ @@ -642,11 +647,11 @@ class Micro extends Injectable implements \ArrayAccess } } else { - /** * Calling beforeNotFound event */ let eventsManager = this->eventsManager; + if typeof eventsManager == "object" { if eventsManager->fire("micro:beforeNotFound", this) === false { return false; @@ -657,6 +662,7 @@ class Micro extends Injectable implements \ArrayAccess * Check if a notfoundhandler is defined and it's callable */ let notFoundHandler = this->notFoundHandler; + if !is_callable(notFoundHandler) { throw new Exception( "Not-Found handler is not callable or is not defined" @@ -677,8 +683,8 @@ class Micro extends Injectable implements \ArrayAccess } let finishHandlers = this->finishHandlers; - if typeof finishHandlers == "array" { + if typeof finishHandlers == "array" { let this->stopped = false; let params = null; @@ -687,14 +693,11 @@ class Micro extends Injectable implements \ArrayAccess * Calls the finish handlers */ for finish in finishHandlers { - /** * Try to execute middleware as plugins */ if typeof finish == "object" { - if finish instanceof MiddlewareInterface { - /** * Call the middleware */ @@ -734,23 +737,26 @@ class Micro extends Injectable implements \ArrayAccess } } } - } catch \Throwable, e { - /** * Calling beforeNotFound event */ let eventsManager = this->eventsManager; + if typeof eventsManager == "object" { - let returnedValue = eventsManager->fire("micro:beforeException", this, e); + let returnedValue = eventsManager->fire( + "micro:beforeException", + this, + e + ); } /** * Check if an errorhandler is defined and it's callable */ let errorHandler = this->errorHandler; - if errorHandler { + if errorHandler { if !is_callable(errorHandler) { throw new Exception("Error handler is not callable"); } @@ -758,7 +764,11 @@ class Micro extends Injectable implements \ArrayAccess /** * Call the Error handler */ - let returnedValue = call_user_func_array(errorHandler, [e]); + let returnedValue = call_user_func_array( + errorHandler, + [e] + ); + if typeof returnedValue == "object" { if !(returnedValue instanceof ResponseInterface) { throw e; @@ -768,7 +778,6 @@ class Micro extends Injectable implements \ArrayAccess throw e; } } - } else { if returnedValue !== false { throw e; @@ -776,13 +785,11 @@ class Micro extends Injectable implements \ArrayAccess } } - /** * Check if a response handler is defined, else use default response * handler */ if this->responseHandler { - if !is_callable(this->responseHandler) { throw new Exception( "Response handler is not callable or is not defined" @@ -790,15 +797,14 @@ class Micro extends Injectable implements \ArrayAccess } let returnedValue = call_user_func(this->responseHandler); - } else { - /** * Check if the returned value is a string and take it as response * body */ if typeof returnedValue == "string" { let response = container->getShared("response"); + if !response->isSent() { response->setContent(returnedValue); response->send(); @@ -828,8 +834,10 @@ class Micro extends Injectable implements \ArrayAccess var container; let container = this->container; + if typeof container != "object" { let container = new FactoryDefault(); + let this->container = container; } @@ -908,17 +916,18 @@ class Micro extends Injectable implements \ArrayAccess * Get the main handler */ let mainHandler = collection->getHandler(); + if empty mainHandler { throw new Exception("Collection requires a main handler"); } let handlers = collection->getHandlers(); + if !count(handlers) { throw new Exception("There are no handlers to mount"); } if typeof handlers == "array" { - /** * Check if handler is lazy */ @@ -934,7 +943,6 @@ class Micro extends Injectable implements \ArrayAccess let prefix = collection->getPrefix(); for handler in handlers { - if typeof handler != "array" { throw new Exception( "One of the registered handlers is invalid" @@ -988,6 +996,7 @@ class Micro extends Injectable implements \ArrayAccess public function notFound(var handler) -> { let this->notFoundHandler = handler; + return this; } @@ -1009,8 +1018,6 @@ class Micro extends Injectable implements \ArrayAccess * $app["request"] * ); * - * - * @return mixed */ public function offsetGet(var alias) -> var { @@ -1039,8 +1046,10 @@ class Micro extends Injectable implements \ArrayAccess var container; let container = this->container; + if typeof container != "object" { let container = new FactoryDefault(); + let this->container = container; } @@ -1206,6 +1215,7 @@ class Micro extends Injectable implements \ArrayAccess if typeof cache == "string" { let container = this->container; + let cache = container->get(cache); } @@ -1227,6 +1237,7 @@ class Micro extends Injectable implements \ArrayAccess public function setResponseHandler(handler) -> { let this->responseHandler = handler; + return this; } @@ -1238,8 +1249,10 @@ class Micro extends Injectable implements \ArrayAccess var container; let container = this->container; + if typeof container != "object" { let container = new FactoryDefault(); + let this->container = container; } diff --git a/phalcon/Mvc/Micro/Collection.zep b/phalcon/Mvc/Micro/Collection.zep index 6217a7aefb2..c486946946c 100644 --- a/phalcon/Mvc/Micro/Collection.zep +++ b/phalcon/Mvc/Micro/Collection.zep @@ -47,6 +47,7 @@ class Collection implements CollectionInterface public function delete(string! routePattern, var handler, string name = null) -> { this->addMap("DELETE", routePattern, handler, name); + return this; } @@ -58,6 +59,7 @@ class Collection implements CollectionInterface public function get(string! routePattern, var handler, string name = null) -> { this->addMap("GET", routePattern, handler, name); + return this; } @@ -93,6 +95,7 @@ class Collection implements CollectionInterface public function head(string! routePattern, var handler, string name = null) -> { this->addMap("HEAD", routePattern, handler, name); + return this; } @@ -112,6 +115,7 @@ class Collection implements CollectionInterface public function map(string! routePattern, var handler, string name = null) -> { this->addMap(null, routePattern, handler, name); + return this; } @@ -140,6 +144,7 @@ class Collection implements CollectionInterface public function options(string! routePattern, var handler, string name = null) -> { this->addMap("OPTIONS", routePattern, handler, name); + return this; } @@ -151,6 +156,7 @@ class Collection implements CollectionInterface public function patch(string! routePattern, var handler, string name = null) -> { this->addMap("PATCH", routePattern, handler, name); + return this; } @@ -162,6 +168,7 @@ class Collection implements CollectionInterface public function post(string! routePattern, var handler, string name = null) -> { this->addMap("POST", routePattern, handler, name); + return this; } @@ -173,6 +180,7 @@ class Collection implements CollectionInterface public function put(string! routePattern, var handler, string name = null) -> { this->addMap("PUT", routePattern, handler, name); + return this; } @@ -183,7 +191,9 @@ class Collection implements CollectionInterface */ public function setHandler(var handler, bool lazy = false) -> { - let this->handler = handler, this->lazy = lazy; + let this->handler = handler, + this->lazy = lazy; + return this; } @@ -193,6 +203,7 @@ class Collection implements CollectionInterface public function setLazy(bool! lazy) -> { let this->lazy = lazy; + return this; } @@ -202,13 +213,14 @@ class Collection implements CollectionInterface public function setPrefix(string! prefix) -> { let this->prefix = prefix; + return this; } /** * Internal function to add a handler to the group. * - * @param string|array method + * @param string|array method * @param callable|string handler */ protected function addMap(var method, string! routePattern, var handler, string name) diff --git a/phalcon/Mvc/Micro/CollectionInterface.zep b/phalcon/Mvc/Micro/CollectionInterface.zep index eaae7734b69..bd27039f02c 100644 --- a/phalcon/Mvc/Micro/CollectionInterface.zep +++ b/phalcon/Mvc/Micro/CollectionInterface.zep @@ -87,7 +87,6 @@ interface CollectionInterface */ public function setLazy(bool! lazy) -> ; - /** * Sets a prefix for all routes added to the collection */ diff --git a/phalcon/Mvc/Micro/Exception.zep b/phalcon/Mvc/Micro/Exception.zep index 5dbf12866cf..0afdac104aa 100644 --- a/phalcon/Mvc/Micro/Exception.zep +++ b/phalcon/Mvc/Micro/Exception.zep @@ -14,7 +14,6 @@ namespace Phalcon\Mvc\Micro; * Phalcon\Mvc\Micro\Exception * * Exceptions thrown in Phalcon\Mvc\Micro will use this class - * */ class Exception extends \Phalcon\Exception { diff --git a/phalcon/Mvc/Micro/LazyLoader.zep b/phalcon/Mvc/Micro/LazyLoader.zep index 1e2f082729a..bb3819f7a43 100644 --- a/phalcon/Mvc/Micro/LazyLoader.zep +++ b/phalcon/Mvc/Micro/LazyLoader.zep @@ -34,7 +34,6 @@ class LazyLoader /** * Calling __call method * - * @param string method * @param array arguments * @return mixed */ @@ -47,17 +46,27 @@ class LazyLoader if typeof handler != "object" { let handler = new {definition}(); + let this->handler = handler; } if modelBinder != null { let bindCacheKey = "_PHMB_" . definition . "_" . method; - let arguments = modelBinder->bindToHandler(handler, arguments, bindCacheKey, method); + + let arguments = modelBinder->bindToHandler( + handler, + arguments, + bindCacheKey, + method + ); } /** * Call the handler */ - return call_user_func_array([handler, method], arguments); + return call_user_func_array( + [handler, method], + arguments + ); } } diff --git a/phalcon/Mvc/Model.zep b/phalcon/Mvc/Model.zep index bb1153e90bd..34489d35a56 100644 --- a/phalcon/Mvc/Model.zep +++ b/phalcon/Mvc/Model.zep @@ -185,6 +185,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface var modelName, status, records; let records = self::_invokeFinder(method, arguments); + if records !== null { return records; } @@ -195,6 +196,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * Check if there is a default action using the magic getter */ let records = this->_getRelatedRecords(modelName, method, arguments); + if records !== null { return records; } @@ -204,6 +206,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * behavior/listener */ let status = ( this->modelsManager)->missingMethod(this, method, arguments); + if status !== null { return status; } @@ -219,13 +222,14 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface /** * Handles method calls when a static method is not implemented * - * @return mixed + * @return mixed */ public static function __callStatic(string method, array arguments) { var records; let records = self::_invokeFinder(method, arguments); + if records === null { throw new Exception( "The static method '" . method . "' doesn't exist" @@ -280,7 +284,6 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * Assign the result to the object */ if typeof result == "object" { - /** * We assign the result to the instance avoiding future queries */ @@ -343,38 +346,39 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface */ public function __set(string property, value) { - var lowerProperty, related, modelName, manager, lowerKey, - relation, referencedModel, key, item, dirtyState; + var lowerProperty, related, modelName, manager, lowerKey, relation, + referencedModel, key, item, dirtyState; bool haveRelation; /** * Values are probably relationships if they are objects */ - if typeof value == "object" { - if value instanceof ModelInterface { - let dirtyState = this->dirtyState; - if (value->getDirtyState() != dirtyState) { - let dirtyState = self::DIRTY_STATE_TRANSIENT; - } - let lowerProperty = strtolower(property), - this->{lowerProperty} = value, - this->related[lowerProperty] = value, - this->dirtyState = dirtyState; - return value; + if typeof value == "object" && value instanceof ModelInterface { + let dirtyState = this->dirtyState; + + if value->getDirtyState() != dirtyState { + let dirtyState = self::DIRTY_STATE_TRANSIENT; } + + let lowerProperty = strtolower(property), + this->{lowerProperty} = value, + this->related[lowerProperty] = value, + this->dirtyState = dirtyState; + + return value; } /** * Check if the value is an array */ if typeof value == "array" { - let lowerProperty = strtolower(property), modelName = get_class(this), manager = this->getModelsManager(); let haveRelation = false; let related = []; + for key, item in value { if typeof item == "object" { if item instanceof ModelInterface { @@ -386,9 +390,9 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface this->{lowerKey} = item; let relation = manager->getRelationByAlias( - modelName, - lowerProperty - ); + modelName, + lowerProperty + ); if typeof relation == "object" { let referencedModel = manager->load( @@ -396,6 +400,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface ); referencedModel->writeAttribute(lowerKey, item); + let haveRelation = true; } } @@ -422,6 +427,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface */ if property_exists(this, property) { let manager = this->getModelsManager(); + if !manager->isVisibleModelProperty(this, property) { throw new Exception( "Property '" . property . "' does not have a setter." @@ -448,11 +454,11 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * { * $this->addBehavior( * new Timestampable( - * [ - * "onCreate" => [ + * [ + * "onCreate" => [ * "field" => "created_at", * "format" => "Y-m-d", - * ], + * ], * ] * ) * ); @@ -490,6 +496,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface public function appendMessage( message) -> { let this->errorMessages[] = message; + return this; } @@ -552,6 +559,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface // apply column map for data, if exist if typeof dataColumnMap == "array" { let dataMapped = []; + for key, value in data { if fetch keyMapped, dataColumnMap[key] { let dataMapped[keyMapped] = value; @@ -574,7 +582,6 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface } for attribute in metaData->getAttributes(this) { - // Try to find case-insensitive key variant if !isset columnMap[attribute] && globals_get("orm.case_insensitive_column_map") { let attribute = self::caseInsensitiveColumnMap( @@ -590,9 +597,9 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface throw new Exception( "Column '" . attribute. "' doesn't make part of the column map" ); - } else { - continue; } + + continue; } } else { let attributeField = attribute; @@ -601,7 +608,6 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface // The value in the array passed // Check if we there is data for the field if fetch value, dataMapped[attributeField] { - // If white-list exists check if the attribute is on that list if typeof whiteList == "array" { if !in_array(attributeField, whiteList) { @@ -686,6 +692,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface "Invalid key in array data provided to dumpResult()" ); } + let instance->{key} = value; } @@ -725,12 +732,11 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface instance->setDirtyState(dirtyState); for key, value in data { - if typeof key == "string" { - // Only string keys in the data are valid if typeof columnMap != "array" { let instance->{key} = value; + continue; } @@ -740,13 +746,14 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface throw new Exception( "Column '" . key . "' doesn't make part of the column map" ); - } else { - continue; } + + continue; } if typeof attribute != "array" { let instance->{attribute} = value; + continue; } @@ -847,7 +854,6 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface } if typeof columnMap == "array" { - // Try to find case-insensitive key variant if !isset columnMap[key] && globals_get("orm.case_insensitive_column_map") { let key = self::caseInsensitiveColumnMap(columnMap, key); @@ -869,7 +875,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface /** * Attribute can store info about his type */ - if (typeof attribute == "array") { + if typeof attribute == "array" { let attributeName = attribute[0]; } else { let attributeName = attribute; @@ -919,9 +925,11 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface var result; let result = self::_groupResult("COUNT", "rowcount", parameters); + if typeof result == "string" { return (int) result; } + return result; } @@ -972,6 +980,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface "InvalidCreateAttempt" ) ]; + return false; } @@ -1046,7 +1055,6 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * Create a condition from the primary keys */ for primaryKey in primaryKeys { - /** * Every column part of the primary key must be in the bind data * types @@ -1089,7 +1097,6 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface } if globals_get("orm.events") { - let this->skipped = false; /** @@ -1275,18 +1282,50 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * $secondNewRobot->save(); * * // this transaction will find the robot. - * $resultInFirstTransaction = Robot::find(['name' => 'first-transaction-robot', Model::TRANSACTION_INDEX => $myTransaction1]); + * $resultInFirstTransaction = Robot::find( + * [ + * 'name' => 'first-transaction-robot', + * Model::TRANSACTION_INDEX => $myTransaction1, + * ] + * ); + * * // this transaction won't find the robot. - * $resultInSecondTransaction = Robot::find(['name' => 'first-transaction-robot', Model::TRANSACTION_INDEX => $myTransaction2]); + * $resultInSecondTransaction = Robot::find( + * [ + * 'name' => 'first-transaction-robot', + * Model::TRANSACTION_INDEX => $myTransaction2, + * ] + * ); + * * // this transaction won't find the robot. - * $resultOutsideAnyExplicitTransaction = Robot::find(['name' => 'first-transaction-robot']); + * $resultOutsideAnyExplicitTransaction = Robot::find( + * [ + * 'name' => 'first-transaction-robot', + * ] + * ); * * // this transaction won't find the robot. - * $resultInFirstTransaction = Robot::find(['name' => 'second-transaction-robot', Model::TRANSACTION_INDEX => $myTransaction2]); + * $resultInFirstTransaction = Robot::find( + * [ + * 'name' => 'second-transaction-robot', + * Model::TRANSACTION_INDEX => $myTransaction2, + * ] + * ); + * * // this transaction will find the robot. - * $resultInSecondTransaction = Robot::find(['name' => 'second-transaction-robot', Model::TRANSACTION_INDEX => $myTransaction1]); + * $resultInSecondTransaction = Robot::find( + * [ + * 'name' => 'second-transaction-robot', + * Model::TRANSACTION_INDEX => $myTransaction1, + * ] + * ); + * * // this transaction won't find the robot. - * $resultOutsideAnyExplicitTransaction = Robot::find(['name' => 'second-transaction-robot']); + * $resultOutsideAnyExplicitTransaction = Robot::find( + * [ + * 'name' => 'second-transaction-robot', + * ] + * ); * * $transaction1->rollback(); * $transaction2->rollback(); @@ -1298,6 +1337,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface if typeof parameters != "array" { let params = []; + if parameters !== null { let params[] = parameters; } @@ -1353,6 +1393,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * // behaviour with transaction * $myTransaction = new Transaction(\Phalcon\Di::getDefault()); * $myTransaction->begin(); + * * $newRobot = new Robot(); * $newRobot->setTransaction($myTransaction); * $newRobot->assign( @@ -1364,14 +1405,29 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * ); * $newRobot->save(); * - * $findsARobot = Robot::findFirst(['name' => 'test', Model::TRANSACTION_INDEX => $myTransaction]); - * $doesNotFindARobot = Robot::findFirst(['name' => 'test']); + * $findsARobot = Robot::findFirst( + * [ + * 'name' => 'test', + * Model::TRANSACTION_INDEX => $myTransaction, + * ] + * ); + * + * $doesNotFindARobot = Robot::findFirst( + * [ + * 'name' => 'test', + * ] + * ); * * var_dump($findARobot); * var_dump($doesNotFindARobot); * * $transaction->commit(); - * $doesFindTheRobotNow = Robot::findFirst(['name' => 'test']); + * + * $doesFindTheRobotNow = Robot::findFirst( + * [ + * 'name' => 'test', + * ] + * ); * * * @param string|array parameters @@ -1384,7 +1440,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface let params = []; } elseif typeof parameters === "array" { let params = parameters; - } elseif (typeof parameters === "string" || is_numeric(parameters)) { + } elseif typeof parameters === "string" || is_numeric(parameters) { let params = []; let params[] = parameters; } else { @@ -1468,10 +1524,10 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface */ public function getChangedFields() -> array { - var metaData, changed, name, snapshot, - columnMap, allAttributes, value; + var metaData, changed, name, snapshot, columnMap, allAttributes, value; let snapshot = this->snapshot; + if typeof snapshot != "array" { throw new Exception( "The record doesn't have a valid data snapshot" @@ -1509,6 +1565,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface */ if !isset snapshot[name] { let changed[] = name; + continue; } @@ -1518,6 +1575,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface */ if !fetch value, this->{name} { let changed[] = name; + continue; } @@ -1526,6 +1584,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface */ if value !== snapshot[name] { let changed[] = name; + continue; } } @@ -1587,11 +1646,13 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface if typeof filter == "string" && !empty filter { let filtered = []; + for message in this->errorMessages { if message->getField() == filter { let filtered[] = message; } } + return filtered; } @@ -1614,14 +1675,15 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface var metaData, container; let metaData = this->modelsMetaData; - if typeof metaData != "object" { + if typeof metaData != "object" { let container = this->container; /** * Obtain the models-metadata service from the DI */ let metaData = container->getShared("modelsMetadata"); + if typeof metaData != "object" { throw new Exception( "The injected service 'modelsMetadata' is not valid" @@ -1633,6 +1695,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface */ let this->modelsMetaData = metaData; } + return metaData; } @@ -1661,6 +1724,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface var transaction; let transaction = this->transaction; + if typeof transaction == "object" { return transaction->getConnection(); } @@ -1738,7 +1802,6 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface return ( this->modelsManager)->getModelSource(this); } - /** * Returns a list of updated values. * @@ -1757,8 +1820,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface */ public function getUpdatedFields() -> array { - var updated, name, snapshot, - oldSnapshot, value; + var updated, name, snapshot, oldSnapshot, value; let snapshot = this->snapshot; let oldSnapshot = this->oldSnapshot; @@ -1791,14 +1853,8 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * If some attribute is not present in the oldSnapshot, we assume * the record as changed */ - if !isset oldSnapshot[name] { - let updated[] = name; - continue; - } - - if value !== oldSnapshot[name] { + if !isset oldSnapshot[name] || value !== oldSnapshot[name] { let updated[] = name; - continue; } } @@ -1813,6 +1869,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface var transaction; let transaction = this->transaction; + if typeof transaction == "object" { return transaction->getConnection(); } @@ -1841,7 +1898,9 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * $robot->year = 1952; * * $robot->create(); + * * $robot->type = "hydraulic"; + * * $hasChanged = $robot->hasChanged("type"); // returns true * $hasChanged = $robot->hasChanged(["type", "name"]); // returns true * $hasChanged = $robot->hasChanged(["type", "name", true]); // returns false @@ -1851,7 +1910,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface */ public function hasChanged(var fieldName = null, bool allFields = false) -> bool { - var changedFields; + var changedFields, intersect; let changedFields = this->getChangedFields(); @@ -1860,12 +1919,16 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface */ if typeof fieldName == "string" { return in_array(fieldName, changedFields); - } elseif typeof fieldName == "array" { + } + + if typeof fieldName == "array" { + let intersect = array_intersect(fieldName, changedFields); + if allFields { - return array_intersect(fieldName, changedFields) == fieldName; + return intersect == fieldName; } - return count(array_intersect(fieldName, changedFields)) > 0; + return count(intersect) > 0; } return count(changedFields) > 0; @@ -1877,6 +1940,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface public function hasSnapshotData() -> bool { var snapshot; + let snapshot = this->snapshot; return typeof snapshot == "array"; @@ -1890,7 +1954,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface */ public function hasUpdated(var fieldName = null, bool allFields = false) -> bool { - var updatedFields; + var updatedFields, intersect; let updatedFields = this->getUpdatedFields(); @@ -1899,12 +1963,15 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface */ if typeof fieldName == "string" { return in_array(fieldName, updatedFields); - } elseif typeof fieldName == "array" { + } + + if typeof fieldName == "array" { + let intersect = array_intersect(fieldName, updatedFields); if allFields { - return array_intersect(fieldName, updatedFields) == fieldName; + return intersect == fieldName; } - return count(array_intersect(fieldName, updatedFields)) > 0; + return count(intersect) > 0; } return count(updatedFields) > 0; @@ -1981,7 +2048,6 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * * * @param array parameters - * @return mixed */ public static function minimum(parameters = null) -> var { @@ -2011,10 +2077,13 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface ); } else { let criteria = new Criteria(); + criteria->setDI(container); } - criteria->setModelName(get_called_class()); + criteria->setModelName( + get_called_class() + ); return criteria; } @@ -2063,8 +2132,8 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface } let uniqueKey = this->uniqueKey; - if !uniqueKey { + if !uniqueKey { /** * We need to check if the record exists */ @@ -2078,6 +2147,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface } let uniqueParams = this->uniqueParams; + if typeof uniqueParams != "array" { throw new Exception( "The record cannot be refreshed because it does not exist or is deleted" @@ -2088,6 +2158,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * We only refresh the attributes in the model's metadata */ let fields = []; + for attribute in metaData->getAttributes(this) { let fields[] = [attribute]; } @@ -2096,11 +2167,13 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * We directly build the SELECT to save resources */ let dialect = readConnection->getDialect(), - tables = dialect->select([ - "columns": fields, - "tables": readConnection->escapeIdentifier(table), - "where": uniqueKey - ]); + tables = dialect->select( + [ + "columns": fields, + "tables": readConnection->escapeIdentifier(table), + "where": uniqueKey + ] + ); let row = readConnection->fetchOne( tables, @@ -2115,7 +2188,9 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface */ if typeof row == "array" { let columnMap = metaData->getColumnMap(this); + this->assign(row, columnMap); + if manager->isKeepingSnapshots(this) { this->setSnapshotData(row, columnMap); this->setOldSnapshotData(row, columnMap); @@ -2151,8 +2226,8 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface */ public function save() -> bool { - var metaData, related, schema, writeConnection, readConnection, - source, table, identityField, exists, success; + var metaData, related, schema, writeConnection, readConnection, source, + table, identityField, exists, success; let metaData = this->getModelsMetaData(); @@ -2170,6 +2245,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * Save related records in belongsTo relationships */ let related = this->related; + if typeof related == "array" { if this->_preSaveRelatedRecords(writeConnection, related) === false { return false; @@ -2215,7 +2291,6 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * _preSave() makes all the validations */ if this->_preSave(metaData, exists, identityField) === false { - /** * Rollback the current transaction if there was validation errors */ @@ -2231,7 +2306,10 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * Launch a Phalcon\Mvc\Model\ValidationFailed to notify that * the save failed */ - throw new ValidationFailed(this, this->getMessages()); + throw new ValidationFailed( + this, + this->getMessages() + ); } return false; @@ -2259,7 +2337,6 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface } if typeof related == "array" { - /** * Rollbacks the implicit transaction if the master save has failed */ @@ -2309,6 +2386,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface if manager->isKeepingSnapshots(this) { let snapshot = this->snapshot; + /** * If attributes is not the same as snapshot then save snapshot too */ @@ -2316,7 +2394,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface return serialize( [ "_attributes": attributes, - "snapshot": snapshot + "snapshot": snapshot ] ); } @@ -2333,12 +2411,13 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface var attributes, container, manager, key, value, snapshot; let attributes = unserialize(data); - if typeof attributes == "array" { + if typeof attributes == "array" { /** * Obtain the default DI */ let container = Di::getDefault(); + if typeof container != "object" { throw new Exception( Exception::containerServiceNotFound( @@ -2356,6 +2435,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * Gets the default modelsManager service */ let manager = container->getShared("modelsManager"); + if typeof manager != "object" { throw new Exception( "The injected service 'modelsManager' is not valid" @@ -2371,12 +2451,12 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * Try to initialize the model */ manager->initialize(this); + if manager->isKeepingSnapshots(this) { if fetch snapshot, attributes["snapshot"] { let this->snapshot = snapshot; let attributes = attributes["_attributes"]; - } - else { + } else { let this->snapshot = attributes; } } @@ -2409,6 +2489,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface public function setDirtyState(int dirtyState) -> | bool { let this->dirtyState = dirtyState; + return this; } @@ -2452,11 +2533,13 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface public function setOldSnapshotData(array! data, columnMap = null) { var key, value, snapshot, attribute; + /** * Build the snapshot based on a column map */ if typeof columnMap == "array" { let snapshot = []; + for key, value in data { /** * Use only strings @@ -2464,6 +2547,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface if typeof key != "string" { continue; } + /** * Every field must be part of the column map */ @@ -2472,21 +2556,23 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface throw new Exception( "Column '" . key . "' doesn't make part of the column map" ); - } else { - continue; } + + continue; } + if typeof attribute == "array" { if !fetch attribute, attribute[0] { if !globals_get("orm.ignore_unknown_columns") { throw new Exception( "Column '" . key . "' doesn't make part of the column map" ); - } else { - continue; } + + continue; } } + let snapshot[attribute] = value; } } else { @@ -2511,10 +2597,9 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * Build the snapshot based on a column map */ if typeof columnMap == "array" { - let snapshot = []; - for key, value in data { + for key, value in data { /** * Use only strings */ @@ -2535,9 +2620,9 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface throw new Exception( "Column '" . key . "' doesn't make part of the column map" ); - } else { - continue; } + + continue; } if typeof attribute == "array" { @@ -2546,9 +2631,9 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface throw new Exception( "Column '" . key . "' doesn't make part of the column map" ); - } else { - continue; } + + continue; } } @@ -2604,6 +2689,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface public function setTransaction( transaction) -> { let this->transaction = transaction; + return this; } @@ -2764,15 +2850,13 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface */ public function toArray(columns = null) -> array { - var data, metaData, columnMap, attribute, - attributeField, value; + var data, metaData, columnMap, attribute, attributeField, value; let data = [], metaData = this->getModelsMetaData(), columnMap = metaData->getColumnMap(this); for attribute in metaData->getAttributes(this) { - /** * Check if the columns must be renamed */ @@ -2790,9 +2874,9 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface throw new Exception( "Column '" . attribute . "' doesn't make part of the column map" ); - } else { - continue; } + + continue; } } else { let attributeField = attribute; @@ -2836,7 +2920,6 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * We don't check if the record exists if the record is already checked */ if this->dirtyState { - let metaData = this->getModelsMetaData(); if !this->_exists(metaData, this->getReadConnection()) { @@ -2877,9 +2960,9 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface */ final protected function _checkForeignKeysRestrict() -> bool { - var manager, belongsTo, foreignKey, relation, conditions, - position, bindParams, extraConditions, message, fields, - referencedFields, field, referencedModel, value, allowNulls; + var manager, belongsTo, foreignKey, relation, conditions, position, + bindParams, extraConditions, message, fields, referencedFields, + field, referencedModel, value, allowNulls; int action, numberNull; bool error, validateWithNulls; @@ -2895,10 +2978,11 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface let belongsTo = manager->getBelongsTo(this); let error = false; - for relation in belongsTo { + for relation in belongsTo { let validateWithNulls = false; let foreignKey = relation->getForeignKey(); + if foreignKey === false { continue; } @@ -2947,18 +3031,19 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface */ for position, field in fields { fetch value, this->{field}; + let conditions[] = "[" . referencedFields[position] . "] = ?" . position, bindParams[] = value; + if typeof value == "null" { let numberNull++; } } let validateWithNulls = numberNull == count(fields); - } else { - fetch value, this->{fields}; + let conditions[] = "[" . referencedFields . "] = ?0", bindParams[] = value; @@ -2990,7 +3075,6 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * values using bound parameters. Let's check */ if !validateWithNulls && !referencedModel->count([join(" AND ", conditions), "bind": bindParams]) { - /** * Get the user message or produce a new one */ @@ -3010,6 +3094,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface ); let error = true; + break; } } @@ -3022,6 +3107,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface this->fireEvent("onValidationFails"); this->_cancelOperation(); } + return false; } @@ -3034,10 +3120,9 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface */ final protected function _checkForeignKeysReverseCascade() -> bool { - var manager, relations, relation, foreignKey, - resultset, conditions, bindParams, referencedModel, - referencedFields, fields, field, position, value, - extraConditions; + var manager, relations, relation, foreignKey, resultset, conditions, + bindParams, referencedModel, referencedFields, fields, field, + position, value, extraConditions; int action; /** @@ -3051,11 +3136,11 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface let relations = manager->getHasOneAndHasMany(this); for relation in relations { - /** * Check if the relation has a virtual foreign key */ let foreignKey = relation->getForeignKey(); + if foreignKey === false { continue; } @@ -3068,10 +3153,8 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface /** * Try to find a different action in the foreign key's options */ - if typeof foreignKey == "array" { - if isset foreignKey["action"] { - let action = (int) foreignKey["action"]; - } + if typeof foreignKey == "array" && isset foreignKey["action"] { + let action = (int) foreignKey["action"]; } /** @@ -3100,11 +3183,13 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface if typeof fields == "array" { for position, field in fields { fetch value, this->{field}; + let conditions[] = "[". referencedFields[position] . "] = ?" . position, bindParams[] = value; } } else { fetch value, this->{fields}; + let conditions[] = "[" . referencedFields . "] = ?0", bindParams[] = value; } @@ -3121,10 +3206,12 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * passing the values using bound parameters * Let's make the checking */ - let resultset = referencedModel->find([ - join(" AND ", conditions), - "bind": bindParams - ]); + let resultset = referencedModel->find( + [ + join(" AND ", conditions), + "bind": bindParams + ] + ); /** * Delete the resultset @@ -3145,10 +3232,9 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface final protected function _checkForeignKeysReverseRestrict() -> bool { bool error; - var manager, relations, foreignKey, relation, - relationClass, referencedModel, fields, referencedFields, - conditions, bindParams,position, field, - value, extraConditions, message; + var manager, relations, foreignKey, relation, relationClass, + referencedModel, fields, referencedFields, conditions, bindParams, + position, field, value, extraConditions, message; int action; /** @@ -3162,12 +3248,13 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface let relations = manager->getHasOneAndHasMany(this); let error = false; - for relation in relations { + for relation in relations { /** * Check if the relation has a virtual foreign key */ let foreignKey = relation->getForeignKey(); + if foreignKey === false { continue; } @@ -3180,10 +3267,8 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface /** * Try to find a different action in the foreign key's options */ - if typeof foreignKey == "array" { - if isset foreignKey["action"] { - let action = (int) foreignKey["action"]; - } + if typeof foreignKey == "array" && isset foreignKey["action"] { + let action = (int) foreignKey["action"]; } /** @@ -3207,18 +3292,19 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * Create the checking conditions. A relation can has many fields or * a single one */ - let conditions = [], bindParams = []; + let conditions = [], + bindParams = []; if typeof fields == "array" { - for position, field in fields { fetch value, this->{field}; + let conditions[] = "[" . referencedFields[position] . "] = ?" . position, bindParams[] = value; } - } else { fetch value, this->{fields}; + let conditions[] = "[" . referencedFields . "] = ?0", bindParams[] = value; } @@ -3236,7 +3322,6 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * Let's make the checking */ if referencedModel->count([join(" AND ", conditions), "bind": bindParams]) { - /** * Create a new message */ @@ -3252,6 +3337,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface ); let error = true; + break; } } @@ -3264,6 +3350,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface this->fireEvent("onValidationFails"); this->_cancelOperation(); } + return false; } @@ -3308,7 +3395,6 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * All fields in the model makes part or the INSERT */ for field in attributes { - /** * Check if the model has a column map */ @@ -3323,18 +3409,15 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface } if !isset automaticAttributes[attributeField] { - /** * Check every attribute in the model except identity field */ if field != identityField { - /** * This isset checks that the property be defined in the * model */ if fetch value, this->{attributeField} { - if value === null && isset defaultValues[field] { let snapshot[attributeField] = null; let value = connection->getDefaultValue(); @@ -3351,11 +3434,13 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface ); } - let fields[] = field, values[] = value, bindTypes[] = bindType; + let fields[] = field, + values[] = value, + bindTypes[] = bindType; } else { - if isset defaultValues[field] { let values[] = connection->getDefaultValue(); + /** * This is default value so we set null, keep in * mind its value in database! @@ -3366,7 +3451,8 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface let snapshot[attributeField] = value; } - let fields[] = field, bindTypes[] = bindSkip; + let fields[] = field, + bindTypes[] = bindSkip; } } } @@ -3376,7 +3462,6 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * If there is an identity field we add it using "null" or "default" */ if identityField !== false { - let defaultValue = connection->getDefaultIdValue(); /** @@ -3384,6 +3469,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * identity columns */ let useExplicitIdentity = (bool) connection->useExplicitIdValue(); + if useExplicitIdentity { let fields[] = identityField; } @@ -3405,13 +3491,11 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * Check if the developer set an explicit value for the column */ if fetch value, this->{attributeField} { - if value === null || value === "" { if useExplicitIdentity { let values[] = defaultValue, bindTypes[] = bindSkip; } } else { - /** * Add the explicit value to the field list if the user has * defined a value for it @@ -3429,11 +3513,13 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface ); } - let values[] = value, bindTypes[] = bindType; + let values[] = value, + bindTypes[] = bindType; } } else { if useExplicitIdentity { - let values[] = defaultValue, bindTypes[] = bindSkip; + let values[] = defaultValue, + bindTypes[] = bindSkip; } } } @@ -3442,17 +3528,17 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * The low level insert is performed */ let success = connection->insert(table, values, fields, bindTypes); - if success && identityField !== false { + if success && identityField !== false { /** * We check if the model have sequences */ let sequenceName = null; + if connection->supportSequences() { if method_exists(this, "getSequenceName") { let sequenceName = this->{"getSequenceName"}(); } else { - let source = this->getSource(), schema = this->getSchema(); @@ -3483,7 +3569,6 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface let this->snapshot = snapshot; } - return success; } @@ -3521,7 +3606,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface } let dataTypes = metaData->getDataTypes(this), - bindDataTypes = metaData->getBindTypes(this), + bindDataTypes = metaData->getBindTypes(this), nonPrimary = metaData->getNonPrimaryKeyAttributes(this), automaticAttributes = metaData->getAutomaticUpdateAttributes(this); @@ -3536,7 +3621,6 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * in primary key attributes are ignored */ for field in nonPrimary { - /** * Check if the model has a column map */ @@ -3551,7 +3635,6 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface } if !isset automaticAttributes[attributeField] { - /** * Check a bind type for field to update */ @@ -3561,21 +3644,19 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface ); } - /** * Get the field's value * If a field isn't set we pass a null value */ if fetch value, this->{attributeField} { - /** * When dynamic update is not used we pass every field to the update */ if !useDynamicUpdate { - let fields[] = field, values[] = value; + let fields[] = field, + values[] = value; let bindTypes[] = bindType; } else { - /** * If the field is not part of the snapshot we add them as changed */ @@ -3596,7 +3677,6 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface if snapshotValue === null { let changed = true; } else { - if !fetch dataType, dataTypes[field] { throw new Exception( "Column '" . field . "' have not defined a data type" @@ -3639,8 +3719,9 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * Only changed values are added to the SQL Update */ if changed { - let fields[] = field, values[] = value; - let bindTypes[] = bindType; + let fields[] = field, + values[] = value, + bindTypes[] = bindType; } } let newSnapshot[attributeField] = value; @@ -3662,6 +3743,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface if useDynamicUpdate { let this->oldSnapshot = snapshot; } + return true; } @@ -3673,7 +3755,6 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * When unique params is null we need to rebuild the bind params */ if typeof uniqueParams != "array" { - let primaryKeys = metaData->getPrimaryKeyAttributes(this); /** @@ -3686,8 +3767,8 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface } let uniqueParams = []; - for field in primaryKeys { + for field in primaryKeys { /** * Check if the model has a column map */ @@ -3749,8 +3830,8 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface { int numberEmpty, numberPrimary; var uniqueParams, uniqueTypes, uniqueKey, columnMap, primaryKeys, - wherePk, field, attributeField, value, bindDataTypes, - joinWhere, num, type, schema, source; + wherePk, field, attributeField, value, bindDataTypes, joinWhere, + num, type, schema, source; let uniqueParams = null, uniqueTypes = null; @@ -3759,12 +3840,13 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * Builds a unique primary key condition */ let uniqueKey = this->uniqueKey; - if uniqueKey === null { + if uniqueKey === null { let primaryKeys = metaData->getPrimaryKeyAttributes(this), bindDataTypes = metaData->getBindTypes(this); let numberPrimary = count(primaryKeys); + if !numberPrimary { return false; } @@ -3787,7 +3869,6 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * We need to create a primary key based on the current data */ for field in primaryKeys { - if typeof columnMap == "array" { if !fetch attributeField, columnMap[field] { throw new Exception( @@ -3803,8 +3884,8 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * conditions */ let value = null; - if fetch value, this->{attributeField} { + if fetch value, this->{attributeField} { /** * We count how many fields are empty, if all fields are * empty we don't perform an 'exist' check @@ -3812,8 +3893,8 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface if value === null || value === "" { let numberEmpty++; } - let uniqueParams[] = value; + let uniqueParams[] = value; } else { let uniqueParams[] = null, numberEmpty++; @@ -3869,6 +3950,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface } let schema = this->getSchema(), source = this->getSource(); + if schema { let table = [schema, source]; } else { @@ -3885,8 +3967,10 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface uniqueParams, uniqueTypes ); + if num["rowcount"] { let this->dirtyState = self::DIRTY_STATE_PERSISTENT; + return true; } else { let this->dirtyState = self::DIRTY_STATE_TRANSIENT; @@ -3927,9 +4011,9 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface let queryMethod = "count"; let relation = manager->getRelationByAlias( - modelName, - substr(method, 5) - ); + modelName, + substr(method, 5) + ); } /** @@ -3956,15 +4040,16 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface */ protected static function _groupResult(string! functionName, string! alias, var parameters) -> { - var params, distinctColumn, groupColumn, columns, - bindParams, bindTypes, resultset, cache, firstRow, groupColumns, - builder, query, container, manager; + var params, distinctColumn, groupColumn, columns, bindParams, bindTypes, + resultset, cache, firstRow, groupColumns, builder, query, container, + manager; let container = Di::getDefault(); let manager = container->getShared("modelsManager"); if typeof parameters != "array" { let params = []; + if parameters !== null { let params[] = parameters; } @@ -3993,8 +4078,12 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * Builds a query with the passed parameters */ let builder = manager->createBuilder(params); + builder->columns(columns); - builder->from(get_called_class()); + + builder->from( + get_called_class() + ); let query = builder->getQuery(); @@ -4029,6 +4118,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * Return only the value in the first result */ let firstRow = resultset->getFirst(); + return firstRow->{alias}; } @@ -4039,8 +4129,8 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface */ protected final static function _invokeFinder(string method, array arguments) { - var extraMethod, type, modelName, value, model, - attributes, field, extraMethodFirst, metaData; + var extraMethod, type, modelName, value, model, attributes, field, + extraMethodFirst, metaData; let extraMethod = null; @@ -4090,6 +4180,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * Get the attributes */ let attributes = metaData->getReverseColumnMap(model); + if typeof attributes != "array" { let attributes = metaData->getDataTypes(model); } @@ -4100,19 +4191,19 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface if isset attributes[extraMethod] { let field = extraMethod; } else { - /** * Lowercase the first letter of the extra-method */ let extraMethodFirst = lcfirst(extraMethod); + if isset attributes[extraMethodFirst] { let field = extraMethodFirst; } else { - /** * Get the possible real method name */ let field = uncamelize(extraMethod); + if !isset attributes[field] { throw new Exception( "Cannot resolve attribute '" . extraMethod . "' in the model" @@ -4124,10 +4215,12 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface /** * Execute the query */ - return {modelName}::{type}([ - "conditions": "[" . field . "] = ?0", - "bind" : [value] - ]); + return {modelName}::{type}( + [ + "conditions": "[" . field . "] = ?0", + "bind" : [value] + ] + ); } /** @@ -4138,11 +4231,14 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface var possibleSetter; let possibleSetter = "set" . camelize(property); - if method_exists(this, possibleSetter) { - this->{possibleSetter}(value); - return true; + + if !method_exists(this, possibleSetter) { + return false; } - return false; + + this->{possibleSetter}(value); + + return true; } /** @@ -4158,7 +4254,6 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * Run Validation Callbacks Before */ if globals_get("orm.events") { - /** * Call the beforeValidation */ @@ -4193,10 +4288,9 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * Columns marked as not null are automatically validated by the ORM */ if globals_get("orm.not_null_validations") { - let notNull = metaData->getNotNullAttributes(this); - if typeof notNull == "array" { + if typeof notNull == "array" { /** * Gets the fields that are numeric, these are validated in a * different way @@ -4226,8 +4320,8 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface let emptyStringValues = metaData->getEmptyStringAttributes(this); let error = false; - for field in notNull { + for field in notNull { if typeof columnMap == "array" { if !fetch attributeField, columnMap[field] { throw new Exception( @@ -4242,17 +4336,14 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * We don't check fields that must be omitted */ if !isset automaticAttributes[attributeField] { - let isNull = false; - /** * Field is null when: 1) is not set, 2) is numeric but * its value is not numeric, 3) is null or 4) is empty string * Read the attribute from the this_ptr using the real or renamed name */ if fetch value, this->{attributeField} { - /** * Objects are never treated as null, numeric fields * must be numeric to be accepted as not null @@ -4280,7 +4371,6 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface } if isNull { - if !exists { /** * The identity field can be null @@ -4316,6 +4406,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface this->fireEvent("onValidationFails"); this->_cancelOperation(); } + return false; } } @@ -4328,6 +4419,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface if globals_get("orm.events") { this->fireEvent("onValidationFails"); } + return false; } @@ -4335,7 +4427,6 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * Run Validation */ if globals_get("orm.events") { - /** * Run Validation Callbacks After */ @@ -4381,7 +4472,6 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface if this->skipped === true { return true; } - } return true; @@ -4408,7 +4498,6 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface manager = this->getModelsManager(); for name, record in related { - /** * Try to get a relation with the same name */ @@ -4418,7 +4507,6 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface ); if typeof relation == "object" { - /** * Get the relation type */ @@ -4428,9 +4516,9 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * Only belongsTo are stored before save the master record */ if type == Relation::BELONGS_TO { - if typeof record != "object" { connection->rollback(nesting); + throw new Exception( "Only objects can be stored as part of belongs-to relations" ); @@ -4442,6 +4530,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface if typeof columns == "array" { connection->rollback(nesting); + throw new Exception("Not implemented"); } @@ -4450,20 +4539,20 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * take any action */ if !record->save() { - /** * Get the validation messages generated by the * referenced model */ for message in record->getMessages() { - /** * Set the related model */ if typeof message == "object" { - message->setMetaData([ - "model" : record - ]); + message->setMetaData( + [ + "model": record + ] + ); } /** @@ -4476,6 +4565,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * Rollback the implicit transaction */ connection->rollback(nesting); + return false; } @@ -4536,7 +4626,6 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface ); if typeof relation == "object" { - /** * Discard belongsTo relations */ @@ -4546,6 +4635,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface if typeof record != "object" && typeof record != "array" { connection->rollback(nesting); + throw new Exception( "Only objects/arrays can be stored as part of has-many/has-one/has-many-to-many relations" ); @@ -4557,6 +4647,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface if typeof columns == "array" { connection->rollback(nesting); + throw new Exception("Not implemented"); } @@ -4571,6 +4662,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface if !fetch value, this->{columns} { connection->rollback(nesting); + throw new Exception( "The column '" . columns . "' needs to be present in the model" ); @@ -4592,13 +4684,11 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface } for recordAfter in relatedRecords { - /** * For non has-many-to-many relations just assign the local * value in the referenced model */ if !isThrough { - /** * Assign the value to the */ @@ -4609,20 +4699,20 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * Save the record and get messages */ if !recordAfter->save() { - /** * Get the validation messages generated by the * referenced model */ for message in recordAfter->getMessages() { - /** * Set the related model */ if typeof message == "object" { - message->setMetaData([ - "model" : record - ]); + message->setMetaData( + [ + "model": record + ] + ); } /** @@ -4635,11 +4725,11 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * Rollback the implicit transaction */ connection->rollback(nesting); + return false; } if isThrough { - /** * Create a new instance of the intermediate model */ @@ -4674,12 +4764,10 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * Save the record and get messages */ if !intermediateModel->save() { - /** * Get the validation messages generated by the referenced model */ for message in intermediateModel->getMessages() { - /** * Set the related model */ @@ -4701,6 +4789,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * Rollback the implicit transaction */ connection->rollback(nesting); + return false; } } @@ -4721,6 +4810,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * Commit the implicit transaction */ connection->commit(nesting); + return true; } @@ -4747,6 +4837,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface var keysAttributes, attribute; let keysAttributes = []; + for attribute in attributes { let keysAttributes[attribute] = true; } @@ -4808,7 +4899,10 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface * Builds a query with the passed parameters */ let builder = manager->createBuilder(params); - builder->from(get_called_class()); + + builder->from( + get_called_class() + ); if limit != null { builder->limit(limit); @@ -4980,6 +5074,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface final protected function setSource(string! source) -> { ( this->modelsManager)->setModelSource(this, source); + return this; } @@ -5030,6 +5125,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface var keysAttributes, attribute; let keysAttributes = []; + for attribute in attributes { let keysAttributes[attribute] = null; } @@ -5063,6 +5159,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface var keysAttributes, attribute; let keysAttributes = []; + for attribute in attributes { let keysAttributes[attribute] = null; } diff --git a/phalcon/Mvc/Model/Behavior.zep b/phalcon/Mvc/Model/Behavior.zep index ae52660fb0e..1aaa0acc0b0 100644 --- a/phalcon/Mvc/Model/Behavior.zep +++ b/phalcon/Mvc/Model/Behavior.zep @@ -40,12 +40,15 @@ abstract class Behavior implements BehaviorInterface var options, eventOptions; let options = this->options; + if eventName !== null { if fetch eventOptions, options[eventName] { return eventOptions; } + return null; } + return options; } diff --git a/phalcon/Mvc/Model/Behavior/SoftDelete.zep b/phalcon/Mvc/Model/Behavior/SoftDelete.zep index 4cb287158c8..989e30b3595 100644 --- a/phalcon/Mvc/Model/Behavior/SoftDelete.zep +++ b/phalcon/Mvc/Model/Behavior/SoftDelete.zep @@ -17,8 +17,8 @@ use Phalcon\Mvc\Model\Exception; /** * Phalcon\Mvc\Model\Behavior\SoftDelete * - * Instead of permanently delete a record it marks the record as - * deleted changing the value of a flag column + * Instead of permanently delete a record it marks the record as deleted + * changing the value of a flag column */ class SoftDelete extends Behavior { @@ -91,8 +91,14 @@ class SoftDelete extends Behavior if modelsManager->isKeepingSnapshots(model) && globals_get("orm.update_snapshot_on_save") { let metaData = model->getModelsMetaData(); - model->setSnapshotData(updateModel->getSnapshotData()); - model->setOldSnapshotData(updateModel->getOldSnapshotData()); + + model->setSnapshotData( + updateModel->getSnapshotData() + ); + + model->setOldSnapshotData( + updateModel->getOldSnapshotData() + ); } } } diff --git a/phalcon/Mvc/Model/Behavior/Timestampable.zep b/phalcon/Mvc/Model/Behavior/Timestampable.zep index 7fa9480948a..22641dd5e5c 100644 --- a/phalcon/Mvc/Model/Behavior/Timestampable.zep +++ b/phalcon/Mvc/Model/Behavior/Timestampable.zep @@ -17,8 +17,8 @@ use Phalcon\Mvc\Model\Exception; /** * Phalcon\Mvc\Model\Behavior\Timestampable * - * Allows to automatically update a model’s attribute saving the - * datetime when a record is created or updated + * Allows to automatically update a model’s attribute saving the datetime when a + * record is created or updated */ class Timestampable extends Behavior { @@ -37,8 +37,8 @@ class Timestampable extends Behavior } let options = this->getOptions(type); - if typeof options == "array" { + if typeof options == "array" { /** * The field name is required in this behavior */ @@ -75,7 +75,7 @@ class Timestampable extends Behavior } /** - * Assign the value to the field, use writeattribute if the property is protected + * Assign the value to the field, use writeAttribute() if the property is protected */ if typeof field == "array" { for singleField in field { diff --git a/phalcon/Mvc/Model/Binder.zep b/phalcon/Mvc/Model/Binder.zep index ca0a3899d21..af184ac6708 100644 --- a/phalcon/Mvc/Model/Binder.zep +++ b/phalcon/Mvc/Model/Binder.zep @@ -81,7 +81,12 @@ class Binder implements BinderInterface return params; } - return this->getParamsFromReflection(handler, params, cacheKey, methodName); + return this->getParamsFromReflection( + handler, + params, + cacheKey, + methodName + ); } /** @@ -128,8 +133,9 @@ class Binder implements BinderInterface */ protected function getParamsFromReflection(object handler, array params, string cacheKey, string! methodName) -> array { - var methodParams, reflection, paramKey, methodParam, paramsCache, className, realClasses = null, - boundModel, cache, handlerClass, reflectionClass, paramsKeys, paramValue; + var methodParams, reflection, paramKey, methodParam, paramsCache, + className, realClasses = null, boundModel, cache, handlerClass, + reflectionClass, paramsKeys, paramValue; let paramsCache = []; @@ -220,5 +226,4 @@ class Binder implements BinderInterface return this; } - } diff --git a/phalcon/Mvc/Model/Binder/BindableInterface.zep b/phalcon/Mvc/Model/Binder/BindableInterface.zep index 667f2d4ece6..751163eceb7 100644 --- a/phalcon/Mvc/Model/Binder/BindableInterface.zep +++ b/phalcon/Mvc/Model/Binder/BindableInterface.zep @@ -18,7 +18,8 @@ namespace Phalcon\Mvc\Model\Binder; interface BindableInterface { /** - * Return the model name or models names and parameters keys associated with this class + * Return the model name or models names and parameters keys associated with + * this class */ public function getModelName() -> string | array; } diff --git a/phalcon/Mvc/Model/Criteria.zep b/phalcon/Mvc/Model/Criteria.zep index 5e1b7361ec1..e137a4b744a 100644 --- a/phalcon/Mvc/Model/Criteria.zep +++ b/phalcon/Mvc/Model/Criteria.zep @@ -23,8 +23,8 @@ use Phalcon\Mvc\Model\Query\BuilderInterface; * Phalcon\Mvc\Model\Criteria * * This class is used to build the array parameter required by - * Phalcon\Mvc\Model::find() and Phalcon\Mvc\Model::findFirst() - * using an object-oriented interface. + * Phalcon\Mvc\Model::find() and Phalcon\Mvc\Model::findFirst() using an + * object-oriented interface. * * * $robots = Robots::query() @@ -96,6 +96,7 @@ class Criteria implements CriteriaInterface, InjectionAwareInterface } else { let bind = null; } + if typeof bind == "array" { let this->params["bind"] = bind + bindParams; } else { @@ -317,7 +318,8 @@ class Criteria implements CriteriaInterface, InjectionAwareInterface ] ); - let nextHiddenParam++, this->hiddenParamNumber = nextHiddenParam; + let nextHiddenParam++, + this->hiddenParamNumber = nextHiddenParam; return this; } @@ -682,8 +684,8 @@ class Criteria implements CriteriaInterface, InjectionAwareInterface array conditions, bind; let conditions = []; - if count(data) { + if count(data) { let metaData = container->getShared("modelsMetadata"); let model = new {modelName}(null, container), @@ -694,8 +696,8 @@ class Criteria implements CriteriaInterface, InjectionAwareInterface * We look for attributes in the array passed as data */ let bind = []; - for field, value in data { + for field, value in data { if typeof columnMap == "array" && count(columnMap) { let attribute = columnMap[field]; } else { @@ -704,19 +706,21 @@ class Criteria implements CriteriaInterface, InjectionAwareInterface if fetch type, dataTypes[attribute] { if value !== null && value !== "" { - if type == Column::TYPE_VARCHAR { /** * For varchar types we use LIKE operator */ - let conditions[] = "[" . field . "] LIKE :" . field . ":", bind[field] = "%" . value . "%"; + let conditions[] = "[" . field . "] LIKE :" . field . ":", + bind[field] = "%" . value . "%"; + continue; } /** * For the rest of data types we use a plain = operator */ - let conditions[] = "[" . field . "] = :" . field . ":", bind[field] = value; + let conditions[] = "[" . field . "] = :" . field . ":", + bind[field] = value; } } } @@ -726,8 +730,15 @@ class Criteria implements CriteriaInterface, InjectionAwareInterface * Create an object instance and pass the parameters to it */ let criteria = new self(); + if count(conditions) { - criteria->where(join(" " . operator . " ", conditions)); + criteria->where( + join( + " " . operator . " ", + conditions + ) + ); + criteria->bind(bind); } @@ -764,6 +775,7 @@ class Criteria implements CriteriaInterface, InjectionAwareInterface * Builds a query with the passed parameters */ let builder = manager->createBuilder(this->params); + builder->from(this->model); return builder; diff --git a/phalcon/Mvc/Model/Manager.zep b/phalcon/Mvc/Model/Manager.zep index 8abf5670804..a45bf198f5f 100644 --- a/phalcon/Mvc/Model/Manager.zep +++ b/phalcon/Mvc/Model/Manager.zep @@ -54,7 +54,6 @@ use Phalcon\Events\ManagerInterface as EventsManagerInterface; */ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareInterface { - protected aliases = []; /** @@ -144,7 +143,6 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI protected writeConnectionServices = []; - /** * Stores a list of reusable instances */ @@ -172,6 +170,7 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI public function setEventsManager( eventsManager) -> { let this->eventsManager = eventsManager; + return this; } @@ -244,6 +243,7 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI * model */ let eventsManager = this->eventsManager; + if typeof eventsManager == "object" { eventsManager->fire("modelsManager:afterInitialize", this, model); } @@ -309,14 +309,19 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI * * use Phalcon\Mvc\Model\Manager; * - * $di->set("modelsManager", function () { - * $modelsManager = new Manager(); - * $modelsManager->setModelPrefix("wp_"); + * $di->set( + * "modelsManager", + * function () { + * $modelsManager = new Manager(); * - * return $modelsManager; - * }); + * $modelsManager->setModelPrefix("wp_"); + * + * return $modelsManager; + * } + * ); * * $robots = new Robots(); + * * echo $robots->getSource(); // wp_robots * */ @@ -331,14 +336,19 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI * * use Phalcon\Mvc\Model\Manager; * - * $di->set("modelsManager", function () { - * $modelsManager = new Manager(); - * $modelsManager->setModelPrefix("wp_"); + * $di->set( + * "modelsManager", + * function () { + * $modelsManager = new Manager(); + * + * $modelsManager->setModelPrefix("wp_"); * - * return $modelsManager; - * }); + * return $modelsManager; + * } + * ); * * $robots = new Robots(); + * * echo $robots->getSource(); // wp_robots * */ @@ -390,7 +400,12 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI let entityName = get_class_lower(model); if !isset this->sources[entityName] { - this->setModelSource(model, uncamelize(get_class_ns(model))); + this->setModelSource( + model, + uncamelize( + get_class_ns(model) + ) + ); } return this->prefix . this->sources[entityName]; @@ -469,6 +484,7 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI let service = this->_getConnectionService(model, connectionServices); let container = this->container; + if typeof container != "object" { throw new Exception( Exception::containerServiceNotFound( @@ -542,12 +558,12 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI * Dispatch events to the global events manager */ if fetch modelsBehaviors, this->behaviors[get_class_lower(model)] { - /** * Notify all the events on the behavior */ for behavior in modelsBehaviors { let status = behavior->notify(eventName, model); + if status === false { return false; } @@ -558,8 +574,10 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI * Dispatch events to the global events manager */ let eventsManager = this->eventsManager; + if typeof eventsManager == "object" { let status = eventsManager->fire("model:" . eventName, model); + if status === false { return status; } @@ -570,6 +588,7 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI */ if fetch customEventsManager, this->customEventsManager[get_class_lower(model)] { let status = customEventsManager->fire("model:" . eventName, model); + if status === false { return false; } @@ -591,12 +610,12 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI * Dispatch events to the global events manager */ if fetch modelsBehaviors, this->behaviors[get_class_lower(model)] { - /** * Notify all the events on the behavior */ for behavior in modelsBehaviors { let result = behavior->missingMethod(model, eventName, data); + if result !== null { return result; } @@ -607,8 +626,13 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI * Dispatch events to the global events manager */ let eventsManager = this->eventsManager; + if typeof eventsManager == "object" { - return eventsManager->fire("model:" . eventName, model, data); + return eventsManager->fire( + "model:" . eventName, + model, + data + ); } return null; @@ -669,6 +693,7 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI public function useDynamicUpdate( model, bool dynamicUpdate) -> void { var entityName; + let entityName = get_class_lower(model), this->dynamicUpdate[entityName] = dynamicUpdate, this->keepSnapshots[entityName] = dynamicUpdate; @@ -696,8 +721,8 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI public function addHasOne( model, var fields, string! referencedModel, var referencedFields, var options = null) -> { - var entityName, referencedEntity, relation, - keyRelation, relations, alias, lowerAlias, singleRelations; + var entityName, referencedEntity, relation, keyRelation, relations, + alias, lowerAlias, singleRelations; let entityName = get_class_lower(model), referencedEntity = strtolower(referencedModel); @@ -737,6 +762,7 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI if typeof alias != "string" { throw new Exception("Relation alias must be a string"); } + let lowerAlias = strtolower(alias); } else { let lowerAlias = referencedEntity; @@ -820,6 +846,7 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI if typeof alias != "string" { throw new Exception("Relation alias must be a string"); } + let lowerAlias = strtolower(alias); } else { let lowerAlias = referencedEntity; @@ -863,14 +890,15 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI public function addHasMany( model, var fields, string! referencedModel, var referencedFields, var options = null) -> { - var entityName, referencedEntity, hasMany, relation, - keyRelation, relations, alias, lowerAlias, singleRelations; + var entityName, referencedEntity, hasMany, relation, keyRelation, + relations, alias, lowerAlias, singleRelations; let entityName = get_class_lower(model), referencedEntity = strtolower(referencedModel), keyRelation = entityName . "$" . referencedEntity; let hasMany = this->hasMany; + if !fetch relations, hasMany[keyRelation] { let relations = []; } @@ -904,6 +932,7 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI if typeof alias != "string" { throw new Exception("Relation alias must be a string"); } + let lowerAlias = strtolower(alias); } else { let lowerAlias = referencedEntity; @@ -959,6 +988,7 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI keyRelation = entityName . "$" . referencedEntity; let hasManyToMany = this->hasManyToMany; + if !fetch relations, hasManyToMany[keyRelation] { let relations = []; } @@ -1014,6 +1044,7 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI if typeof alias != "string" { throw new Exception("Relation alias must be a string"); } + let lowerAlias = strtolower(alias); } else { let lowerAlias = referencedEntity; @@ -1176,10 +1207,9 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI } let findParams = []; - if typeof findParamsOne == "array" { + if typeof findParamsOne == "array" { for key, value in findParamsOne { - if key === 0 || key === "conditions" { if !isset findParams[0] { let findParams[0] = value; @@ -1198,15 +1228,14 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI } if typeof findParamsTwo == "array" { - for key, value in findParamsTwo { - if key === 0 || key === "conditions" { if !isset findParams[0] { let findParams[0] = value; } else { let findParams[0] = "(" . findParams[0] . ") AND (" . value . ")"; } + continue; } @@ -1223,6 +1252,7 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI ); } } + continue; } @@ -1286,6 +1316,7 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI * relation */ let fields = relation->getFields(); + if typeof fields != "array" { let conditions[] = "[" . intermediateModel . "].[" . intermediateFields . "] = :APR0:", placeholders["APR0"] = record->readAttribute(fields); @@ -1299,6 +1330,7 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI * Create the join conditions */ let intermediateFields = relation->getIntermediateReferencedFields(); + if typeof intermediateFields != "array" { let joinConditions[] = "[" . intermediateModel . "].[" . intermediateFields . "] = [" . referencedModel . "].[" . relation->getReferencedFields() . "]"; } else { @@ -1314,8 +1346,16 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI ); builder->from(referencedModel); - builder->innerJoin(intermediateModel, join(" AND ", joinConditions)); - builder->andWhere(join(" AND ", conditions), placeholders); + + builder->innerJoin( + intermediateModel, + join(" AND ", joinConditions) + ); + + builder->andWhere( + join(" AND ", conditions), + placeholders + ); if method == "count" { builder->columns("COUNT(*) AS rowcount"); @@ -1340,15 +1380,16 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI * Appends conditions created from the fields defined in the relation */ let fields = relation->getFields(); + if typeof fields != "array" { let conditions[] = "[". relation->getReferencedFields() . "] = :APR0:", placeholders["APR0"] = record->readAttribute(fields); } else { - /** * Compound relation */ let referencedFields = relation->getReferencedFields(); + for refPosition, field in relation->getFields() { let conditions[] = "[". referencedFields[refPosition] . "] = :APR" . refPosition . ":", placeholders["APR" . refPosition] = record->readAttribute(field); @@ -1381,7 +1422,6 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI */ if method === null { switch relation->getType() { - case Relation::BELONGS_TO: case Relation::HAS_ONE: let retrieveMethod = "findFirst"; @@ -1404,9 +1444,11 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI * Find first results could be reusable */ let reusable = (bool) relation->isReusable(); + if reusable { let uniqueKey = unique_key(referencedModel, arguments), records = this->getReusableRecords(referencedModel, uniqueKey); + if typeof records == "array" || typeof records == "object" { return records; } @@ -1440,10 +1482,12 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI public function getReusableRecords(string! modelName, string! key) { var records; - if fetch records, this->reusable[key] { - return records; + + if !fetch records, this->reusable[key] { + return null; } - return null; + + return records; } /** @@ -1474,6 +1518,7 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI * Check if there is a relation between them */ let keyRelation = strtolower(modelName) . "$" . strtolower(modelRelation); + if !fetch relations, this->hasMany[keyRelation] { return false; } @@ -1502,6 +1547,7 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI * Check if there is a relation between them */ let keyRelation = strtolower(modelName) . "$" . strtolower(modelRelation); + if !fetch relations, this->hasMany[keyRelation] { return false; } @@ -1530,6 +1576,7 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI * Check if there is a relation between them */ let keyRelation = strtolower(modelName) . "$" . strtolower(modelRelation); + if !fetch relations, this->hasOne[keyRelation] { return false; } @@ -1697,6 +1744,7 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI var container, query; let container = this->container; + if typeof container != "object" { throw new Exception( Exception::containerServiceNotFound( @@ -1749,6 +1797,7 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI var container; let container = this->container; + if typeof container != "object" { throw new Exception( Exception::containerServiceNotFound( @@ -1792,13 +1841,13 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI { var namespaceName; - if fetch namespaceName, this->namespaceAliases[alias] { - return namespaceName; + if !fetch namespaceName, this->namespaceAliases[alias] { + throw new Exception( + "Namespace alias '" . alias . "' is not registered" + ); } - throw new Exception( - "Namespace alias '" . alias . "' is not registered" - ); + return namespaceName; } /** @@ -1815,6 +1864,7 @@ class Manager implements ManagerInterface, InjectionAwareInterface, EventsAwareI public function __destruct() { phalcon_orm_destroy_cache(); + Query::clean(); } } diff --git a/phalcon/Mvc/Model/ManagerInterface.zep b/phalcon/Mvc/Model/ManagerInterface.zep index cd7c7f9b3ab..20e8e01c2f7 100644 --- a/phalcon/Mvc/Model/ManagerInterface.zep +++ b/phalcon/Mvc/Model/ManagerInterface.zep @@ -277,8 +277,6 @@ interface ManagerInterface /** * Receives events generated in the models and dispatches them to an events-manager if available * Notify the behaviors that are listening in the model - * - * @param string $eventName */ public function notifyEvent(string! eventName, model); diff --git a/phalcon/Mvc/Model/Metadata.zep b/phalcon/Mvc/Model/Metadata.zep index db7aba0ca84..73b97305050 100644 --- a/phalcon/Mvc/Model/Metadata.zep +++ b/phalcon/Mvc/Model/Metadata.zep @@ -77,10 +77,13 @@ abstract class MetaData implements InjectionAwareInterface, MetaDataInterface public function getAttributes( model) -> array { var data; + let data = this->readMetaDataIndex(model, self::MODELS_ATTRIBUTES); + if typeof data != "array" { throw new Exception("The meta-data is invalid or is corrupt"); } + return data; } @@ -98,10 +101,13 @@ abstract class MetaData implements InjectionAwareInterface, MetaDataInterface public function getAutomaticCreateAttributes( model) -> array { var data; + let data = this->readMetaDataIndex(model, self::MODELS_AUTOMATIC_DEFAULT_INSERT); + if typeof data != "array" { throw new Exception("The meta-data is invalid or is corrupt"); } + return data; } @@ -119,10 +125,13 @@ abstract class MetaData implements InjectionAwareInterface, MetaDataInterface public function getAutomaticUpdateAttributes( model) -> array { var data; + let data = this->readMetaDataIndex(model, self::MODELS_AUTOMATIC_DEFAULT_UPDATE); + if typeof data != "array" { throw new Exception("The meta-data is invalid or is corrupt"); } + return data; } @@ -140,10 +149,13 @@ abstract class MetaData implements InjectionAwareInterface, MetaDataInterface public function getBindTypes( model) -> array { var data; + let data = this->readMetaDataIndex(model, self::MODELS_DATA_TYPES_BIND); + if typeof data != "array" { throw new Exception("The meta-data is invalid or is corrupt"); } + return data; } @@ -163,9 +175,11 @@ abstract class MetaData implements InjectionAwareInterface, MetaDataInterface var data; let data = this->readColumnMapIndex(model, self::MODELS_COLUMN_MAP); + if typeof data != "null" && typeof data != "array" { throw new Exception("The meta-data is invalid or is corrupt"); } + return data; } @@ -183,10 +197,13 @@ abstract class MetaData implements InjectionAwareInterface, MetaDataInterface public function getDefaultValues( model) -> array { var data; + let data = this->readMetaDataIndex(model, self::MODELS_DEFAULT_VALUES); + if typeof data != "array" { throw new Exception("The meta-data is invalid or is corrupt"); } + return data; } @@ -204,10 +221,13 @@ abstract class MetaData implements InjectionAwareInterface, MetaDataInterface public function getDataTypes( model) -> array { var data; + let data = this->readMetaDataIndex(model, self::MODELS_DATA_TYPES); + if typeof data != "array" { throw new Exception("The meta-data is invalid or is corrupt"); } + return data; } @@ -225,10 +245,13 @@ abstract class MetaData implements InjectionAwareInterface, MetaDataInterface public function getDataTypesNumeric( model) -> array { var data; + let data = this->readMetaDataIndex(model, self::MODELS_DATA_TYPES_NUMERIC); + if typeof data != "array" { throw new Exception("The meta-data is invalid or is corrupt"); } + return data; } @@ -254,10 +277,13 @@ abstract class MetaData implements InjectionAwareInterface, MetaDataInterface public function getEmptyStringAttributes( model) -> array { var data; + let data = this->readMetaDataIndex(model, self::MODELS_EMPTY_STRING_VALUES); + if typeof data != "array" { throw new Exception("The meta-data is invalid or is corrupt"); } + return data; } @@ -294,10 +320,13 @@ abstract class MetaData implements InjectionAwareInterface, MetaDataInterface public function getNonPrimaryKeyAttributes( model) -> array { var data; + let data = this->readMetaDataIndex(model, self::MODELS_NON_PRIMARY_KEY); + if typeof data != "array" { throw new Exception("The meta-data is invalid or is corrupt"); } + return data; } @@ -315,10 +344,13 @@ abstract class MetaData implements InjectionAwareInterface, MetaDataInterface public function getNotNullAttributes( model) -> array { var data; + let data = this->readMetaDataIndex(model, self::MODELS_NOT_NULL); + if typeof data != "array" { throw new Exception("The meta-data is invalid or is corrupt"); } + return data; } @@ -336,10 +368,13 @@ abstract class MetaData implements InjectionAwareInterface, MetaDataInterface public function getPrimaryKeyAttributes( model) -> array { var data; + let data = this->readMetaDataIndex(model, self::MODELS_PRIMARY_KEY); + if typeof data != "array" { throw new Exception("The meta-data is invalid or is corrupt"); } + return data; } @@ -359,9 +394,11 @@ abstract class MetaData implements InjectionAwareInterface, MetaDataInterface var data; let data = this->readColumnMapIndex(model, self::MODELS_REVERSE_COLUMN_MAP); + if typeof data != "null" && typeof data != "array" { throw new Exception("The meta-data is invalid or is corrupt"); } + return data; } @@ -394,6 +431,7 @@ abstract class MetaData implements InjectionAwareInterface, MetaDataInterface var columnMap; let columnMap = this->getReverseColumnMap(model); + if typeof columnMap == "array" { return isset columnMap[attribute]; } @@ -435,8 +473,10 @@ abstract class MetaData implements InjectionAwareInterface, MetaDataInterface } let keyName = get_class_lower(model); + if !fetch data, this->columnMap[keyName] { this->initialize(model, null, null, null); + let data = this->columnMap[keyName]; } @@ -467,6 +507,7 @@ abstract class MetaData implements InjectionAwareInterface, MetaDataInterface if !fetch columnMapModel, this->columnMap[keyName] { this->initialize(model, null, null, null); + let columnMapModel = this->columnMap[keyName]; } @@ -497,6 +538,7 @@ abstract class MetaData implements InjectionAwareInterface, MetaDataInterface * Unique key for meta-data is created using class-name-schema-source */ let key = get_class_lower(model) . "-" . schema . source; + if !isset this->metaData[key] { this->initialize(model, key, source, schema); } @@ -562,7 +604,11 @@ abstract class MetaData implements InjectionAwareInterface, MetaDataInterface */ public function setAutomaticCreateAttributes( model, array attributes) -> void { - this->writeMetaDataIndex(model, self::MODELS_AUTOMATIC_DEFAULT_INSERT, attributes); + this->writeMetaDataIndex( + model, + self::MODELS_AUTOMATIC_DEFAULT_INSERT, + attributes + ); } /** @@ -579,7 +625,11 @@ abstract class MetaData implements InjectionAwareInterface, MetaDataInterface */ public function setAutomaticUpdateAttributes( model, array attributes) -> void { - this->writeMetaDataIndex(model, self::MODELS_AUTOMATIC_DEFAULT_UPDATE, attributes); + this->writeMetaDataIndex( + model, + self::MODELS_AUTOMATIC_DEFAULT_UPDATE, + attributes + ); } /** @@ -596,7 +646,11 @@ abstract class MetaData implements InjectionAwareInterface, MetaDataInterface */ public function setEmptyStringAttributes( model, array attributes) -> void { - this->writeMetaDataIndex(model, self::MODELS_EMPTY_STRING_VALUES, attributes); + this->writeMetaDataIndex( + model, + self::MODELS_EMPTY_STRING_VALUES, + attributes + ); } /** @@ -665,31 +719,30 @@ abstract class MetaData implements InjectionAwareInterface, MetaDataInterface className = get_class(model); if key !== null { - let metaData = this->metaData; - if !isset metaData[key] { + if !isset metaData[key] { /** * The meta-data is read from the adapter always if not available in _metaData property */ let prefixKey = "meta-" . key, data = this->{"read"}(prefixKey); + if data !== null { let this->metaData[key] = data; } else { - /** * Check if there is a method 'metaData' in the model to retrieve meta-data from it */ if method_exists(model, "metaData") { let modelMetadata = model->{"metaData"}(); + if typeof modelMetadata != "array" { throw new Exception( "Invalid meta-data for model " . className ); } } else { - /** * Get the meta-data extraction strategy */ @@ -719,6 +772,7 @@ abstract class MetaData implements InjectionAwareInterface, MetaDataInterface } let keyName = strtolower(className); + if isset this->columnMap[keyName] { return null; } @@ -732,6 +786,7 @@ abstract class MetaData implements InjectionAwareInterface, MetaDataInterface if data !== null { let this->columnMap[keyName] = data; + return null; } diff --git a/phalcon/Mvc/Model/Metadata/Apcu.zep b/phalcon/Mvc/Model/Metadata/Apcu.zep index 7509d933f82..32700179811 100644 --- a/phalcon/Mvc/Model/Metadata/Apcu.zep +++ b/phalcon/Mvc/Model/Metadata/Apcu.zep @@ -48,13 +48,12 @@ class Apcu extends MetaData { var prefix, ttl; - if typeof options == "array" { - if fetch prefix, options["prefix"] { - let this->prefix = prefix; - } - if fetch ttl, options["lifetime"] { - let this->ttl = ttl; - } + if fetch prefix, options["prefix"] { + let this->prefix = prefix; + } + + if fetch ttl, options["lifetime"] { + let this->ttl = ttl; } } @@ -66,10 +65,12 @@ class Apcu extends MetaData var data; let data = apcu_fetch("$PMM$" . this->prefix . key); - if typeof data == "array" { - return data; + + if typeof data != "array" { + return null; } - return null; + + return data; } /** @@ -77,6 +78,10 @@ class Apcu extends MetaData */ public function write(string! key, array data) -> void { - apcu_store("$PMM$" . this->prefix . key, data, this->ttl); + apcu_store( + "$PMM$" . this->prefix . key, + data, + this->ttl + ); } } diff --git a/phalcon/Mvc/Model/Metadata/Files.zep b/phalcon/Mvc/Model/Metadata/Files.zep index 0a573ebe198..e21acb1527c 100644 --- a/phalcon/Mvc/Model/Metadata/Files.zep +++ b/phalcon/Mvc/Model/Metadata/Files.zep @@ -52,11 +52,14 @@ class Files extends MetaData public function read(string! key) -> array | null { var path; + let path = this->metaDataDir . prepare_virtual_path(key, "_") . ".php"; - if file_exists(path) { - return require path; + + if !file_exists(path) { + return null; } - return null; + + return require path; } /** @@ -67,6 +70,7 @@ class Files extends MetaData var path; let path = this->metaDataDir . prepare_virtual_path(key, "_") . ".php"; + if file_put_contents(path, "memcache->get(key); - if typeof data == "array" { - return data; + + if typeof data != "array" { + return null; } - return null; + + return data; } /** @@ -113,7 +115,6 @@ class Libmemcached extends MetaData let meta = this->metaData; if typeof meta == "array" { - for key, _ in meta { let realKey = "meta-" . key; diff --git a/phalcon/Mvc/Model/Metadata/Redis.zep b/phalcon/Mvc/Model/Metadata/Redis.zep index a19b4533398..23363558eea 100644 --- a/phalcon/Mvc/Model/Metadata/Redis.zep +++ b/phalcon/Mvc/Model/Metadata/Redis.zep @@ -66,7 +66,11 @@ class Redis extends MetaData } let this->redis = new Redis( - new FrontendData(["lifetime": this->ttl]), + new FrontendData( + [ + "lifetime": this->ttl + ] + ), options ); } @@ -79,10 +83,12 @@ class Redis extends MetaData var data; let data = this->redis->get(key); - if typeof data == "array" { - return data; + + if typeof data != "array" { + return null; } - return null; + + return data; } /** @@ -103,7 +109,6 @@ class Redis extends MetaData let meta = this->metaData; if typeof meta == "array" { - for key, _ in meta { let realKey = "meta-" . key; diff --git a/phalcon/Mvc/Model/Metadata/Session.zep b/phalcon/Mvc/Model/Metadata/Session.zep index aa4d1efe073..7e6e8a65252 100644 --- a/phalcon/Mvc/Model/Metadata/Session.zep +++ b/phalcon/Mvc/Model/Metadata/Session.zep @@ -55,16 +55,17 @@ class Session extends MetaData var metaData, status; let status = session_status(); + if status !== PHP_SESSION_ACTIVE { // To use $_SESSION variable we need to start session first return null; } - if fetch metaData, _SESSION["$PMM$" . this->prefix][key] { - return metaData; + if !fetch metaData, _SESSION["$PMM$" . this->prefix][key] { + return null; } - return null; + return metaData; } /** @@ -75,6 +76,7 @@ class Session extends MetaData var status; let status = session_status(); + if status !== PHP_SESSION_ACTIVE { // To use $_SESSION variable we need to start session first return; diff --git a/phalcon/Mvc/Model/Metadata/Strategy/Annotations.zep b/phalcon/Mvc/Model/Metadata/Strategy/Annotations.zep index 374286703a8..f15c6da36cb 100644 --- a/phalcon/Mvc/Model/Metadata/Strategy/Annotations.zep +++ b/phalcon/Mvc/Model/Metadata/Strategy/Annotations.zep @@ -24,9 +24,9 @@ class Annotations implements StrategyInterface */ final public function getColumnMaps( model, container) -> array { - var annotations, className, reflection, propertiesAnnotations; - var property, propAnnotations, columnAnnotation, columnName; - var orderedColumnMap, reversedColumnMap, hasReversedColumn; + var annotations, className, reflection, propertiesAnnotations, property, + propAnnotations, columnAnnotation, columnName, orderedColumnMap, + reversedColumnMap, hasReversedColumn; if typeof container != "object" { throw new Exception("The dependency injector is invalid"); @@ -34,7 +34,9 @@ class Annotations implements StrategyInterface let annotations = container->get("annotations"); - let className = get_class(model), reflection = annotations->get(className); + let className = get_class(model), + reflection = annotations->get(className); + if typeof reflection != "object" { throw new Exception( "No annotations were found in class " . className @@ -45,6 +47,7 @@ class Annotations implements StrategyInterface * Get the properties defined in */ let propertiesAnnotations = reflection->getPropertiesAnnotations(); + if !count(propertiesAnnotations) { throw new Exception( "No properties with annotations were found in class " . className @@ -56,7 +59,6 @@ class Annotations implements StrategyInterface hasReversedColumn = false; for property, propAnnotations in propertiesAnnotations { - /** * All columns marked with the 'Column' annotation are considered columns */ @@ -150,7 +152,6 @@ class Annotations implements StrategyInterface emptyStringValues = []; for property, propAnnotations in propertiesAnnotations { - /** * All columns marked with the 'Column' annotation are considered * columns diff --git a/phalcon/Mvc/Model/Metadata/Strategy/Introspection.zep b/phalcon/Mvc/Model/Metadata/Strategy/Introspection.zep index 6d6320278fa..99cb5ea3dcd 100644 --- a/phalcon/Mvc/Model/Metadata/Strategy/Introspection.zep +++ b/phalcon/Mvc/Model/Metadata/Strategy/Introspection.zep @@ -39,13 +39,15 @@ class Introspection implements StrategyInterface * Check for a columnMap() method on the model */ if method_exists(model, "columnMap") { - let userColumnMap = model->{"columnMap"}(); + if typeof userColumnMap != "array" { throw new Exception("columnMap() not returned an array"); } - let reversedColumnMap = [], orderedColumnMap = userColumnMap; + let reversedColumnMap = [], + orderedColumnMap = userColumnMap; + for name, userName in userColumnMap { let reversedColumnMap[userName] = name; } @@ -62,13 +64,13 @@ class Introspection implements StrategyInterface */ final public function getMetaData( model, container) -> array { - var schema, table, readConnection, columns, attributes, - primaryKeys, nonPrimaryKeys, completeTable, numericTyped, notNull, - fieldTypes, automaticDefault, identityField, fieldBindTypes, - defaultValues, column, fieldName, defaultValue, emptyStringValues; + var schema, table, readConnection, columns, attributes, primaryKeys, + nonPrimaryKeys, completeTable, numericTyped, notNull, fieldTypes, + automaticDefault, identityField, fieldBindTypes, defaultValues, + column, fieldName, defaultValue, emptyStringValues; - let schema = model->getSchema(), - table = model->getSource(); + let schema = model->getSchema(), + table = model->getSource(); /** * Check if the mapped table exists on the database @@ -76,7 +78,6 @@ class Introspection implements StrategyInterface let readConnection = model->getReadConnection(); if !readConnection->tableExists(table, schema) { - if schema { let completeTable = schema . "'.'" . table; } else { @@ -95,8 +96,8 @@ class Introspection implements StrategyInterface * Try to describe the table */ let columns = readConnection->describeColumns(table, schema); - if !count(columns) { + if !count(columns) { if schema { let completeTable = schema . "'.'" . table; } else { @@ -127,7 +128,6 @@ class Introspection implements StrategyInterface let emptyStringValues = []; for column in columns { - let fieldName = column->getName(), attributes[] = fieldName; @@ -175,6 +175,7 @@ class Introspection implements StrategyInterface * If column has default value or column is nullable and default value is null */ let defaultValue = column->getDefault(); + if defaultValue !== null || !column->isNotNull() { if !column->isAutoIncrement() { let defaultValues[fieldName] = defaultValue; diff --git a/phalcon/Mvc/Model/Query.zep b/phalcon/Mvc/Model/Query.zep index 9e99a07932c..e2ef1d857c2 100644 --- a/phalcon/Mvc/Model/Query.zep +++ b/phalcon/Mvc/Model/Query.zep @@ -78,8 +78,7 @@ use Phalcon\Db\DialectInterface; * $resultWithEntries = $queryWithTransaction->execute(); * * $queryWithOutTransaction = new Query($phql, $di); - * $resultWithOutEntries = $queryWithTransaction->execute() - * + * $resultWithOutEntries = $queryWithTransaction->execute(); * */ class Query implements QueryInterface, InjectionAwareInterface @@ -153,11 +152,13 @@ class Query implements QueryInterface, InjectionAwareInterface var manager, metaData; let manager = container->getShared("modelsManager"); + if typeof manager != "object" { throw new Exception("Injected service 'modelsManager' is invalid"); } let metaData = container->getShared("modelsMetadata"); + if typeof metaData != "object" { throw new Exception("Injected service 'modelsMetaData' is invalid"); } @@ -183,6 +184,7 @@ class Query implements QueryInterface, InjectionAwareInterface public function setUniqueRow(bool uniqueRow) -> { let this->uniqueRow = uniqueRow; + return this; } @@ -232,7 +234,6 @@ class Query implements QueryInterface, InjectionAwareInterface * Check if the qualified name has a domain */ if fetch columnDomain, expr["domain"] { - let sqlAliases = this->sqlAliases; /** @@ -248,7 +249,6 @@ class Query implements QueryInterface, InjectionAwareInterface * Change the selected column by its real name on its mapped table */ if globals_get("orm.column_renaming") { - /** * Retrieve the corresponding model by its alias */ @@ -278,27 +278,27 @@ class Query implements QueryInterface, InjectionAwareInterface } else { let realColumnName = columnName; } - } else { - /** * If the column IR doesn't have a domain, we must check for * ambiguities */ - let number = 0, hasModel = false; + let number = 0, + hasModel = false; for model in this->modelsInstances { - /** * Check if the attribute belongs to the current model */ if metaData->hasAttribute(model, columnName) { let number++; + if number > 1 { throw new Exception( "The column '" . columnName . "' is ambiguous, when preparing: " . this->phql ); } + let hasModel = model; } } @@ -317,6 +317,7 @@ class Query implements QueryInterface, InjectionAwareInterface * Check if the models property is correctly prepared */ let models = this->models; + if typeof models != "array" { throw new Exception("The models list was not loaded correctly"); } @@ -325,6 +326,7 @@ class Query implements QueryInterface, InjectionAwareInterface * Obtain the model's source from the models list */ let className = get_class(hasModel); + if !fetch source, models[className] { throw new Exception( "Can't obtain model's source from models list: '" . className . "', when preparing: " . this->phql @@ -371,8 +373,11 @@ class Query implements QueryInterface, InjectionAwareInterface final protected function _getCallArgument(array! argument) -> array { if argument["type"] == PHQL_T_STARALL { - return ["type": "all"]; + return [ + "type": "all" + ]; } + return this->_getExpression(argument); } @@ -384,6 +389,7 @@ class Query implements QueryInterface, InjectionAwareInterface var whenClauses, whenExpr; let whenClauses = []; + for whenExpr in expr["right"] { if isset whenExpr["right"] { let whenClauses[] = [ @@ -414,7 +420,6 @@ class Query implements QueryInterface, InjectionAwareInterface var arguments, distinct, argument, functionArgs; if fetch arguments, expr["arguments"] { - if isset expr["distinct"] { let distinct = 1; } else { @@ -424,12 +429,15 @@ class Query implements QueryInterface, InjectionAwareInterface if isset arguments[0] { // There are more than one argument let functionArgs = []; + for argument in arguments { let functionArgs[] = this->_getCallArgument(argument); } } else { // There is only one argument - let functionArgs = [this->_getCallArgument(arguments)]; + let functionArgs = [ + this->_getCallArgument(arguments) + ]; } if distinct { @@ -464,11 +472,9 @@ class Query implements QueryInterface, InjectionAwareInterface exprValue, valueParts, name, bindType, bind; if fetch exprType, expr["type"] { - let tempNotQuoting = true; if exprType != PHQL_T_CASE { - /** * Resolving the left part of the expression if any */ @@ -488,7 +494,6 @@ class Query implements QueryInterface, InjectionAwareInterface * Every node in the AST has a unique integer type */ switch exprType { - case PHQL_T_LESS: let exprReturn = ["type": "binary-op", "op": "<", "left": left, "right": right]; break; @@ -578,6 +583,7 @@ class Query implements QueryInterface, InjectionAwareInterface case PHQL_T_STRING: let value = expr["value"]; + if quoting { /** * Check if static literals have single quotes and @@ -588,10 +594,12 @@ class Query implements QueryInterface, InjectionAwareInterface } else { let escapedValue = value; } + let exprValue = "'" . escapedValue . "'"; } else { let exprValue = value; } + let exprReturn = ["type": "literal", "value": exprValue]; break; @@ -795,10 +803,15 @@ class Query implements QueryInterface, InjectionAwareInterface */ if isset expr[0] { let listItems = []; + for exprListItem in expr { let listItems[] = this->_getExpression(exprListItem); } - return ["type": "list", listItems]; + + return [ + "type": "list", + listItems + ]; } throw new Exception("Unknown expression"); @@ -830,7 +843,6 @@ class Query implements QueryInterface, InjectionAwareInterface */ if columnType == PHQL_T_STARALL { for modelName, source in this->models { - let sqlColumn = [ "type" : "object", "model" : modelName, @@ -845,6 +857,7 @@ class Query implements QueryInterface, InjectionAwareInterface let sqlColumns[] = sqlColumn; } + return sqlColumns; } @@ -856,7 +869,6 @@ class Query implements QueryInterface, InjectionAwareInterface * Check if selected column is qualified.*, ex: robots.* */ if columnType == PHQL_T_DOMAINALL { - let sqlAliases = this->sqlAliases; /** @@ -900,7 +912,7 @@ class Query implements QueryInterface, InjectionAwareInterface * Each item is a complex type returning a complete object */ let sqlColumn = [ - "type": "object", + "type": "object", "model": modelName, "column": sqlColumnAlias, "balias": preparedAlias @@ -979,13 +991,10 @@ class Query implements QueryInterface, InjectionAwareInterface */ final protected function _getJoin( manager, array join) -> array { - var qualified, modelName, realModelName, nsAlias, - source, model, schema; + var qualified, modelName, realModelName, nsAlias, source, model, schema; if fetch qualified, join["qualified"] { - if qualified["type"] == PHQL_T_QUALIFIED { - let modelName = qualified["name"]; if memstr(modelName, ":") { @@ -1023,7 +1032,6 @@ class Query implements QueryInterface, InjectionAwareInterface } switch type { - case PHQL_T_INNERJOIN: return "INNER"; @@ -1066,7 +1074,6 @@ class Query implements QueryInterface, InjectionAwareInterface let referencedFields = relation->getReferencedFields(); if typeof fields != "array" { - /** * Create the left part of the expression * Create a binary operation for the join conditions @@ -1074,29 +1081,31 @@ class Query implements QueryInterface, InjectionAwareInterface */ let sqlJoinConditions = [ [ - "type" : "binary-op", - "op" : "=", - "left" : this->_getQualified([ - "type" : PHQL_T_QUALIFIED, - "domain" : modelAlias, - "name" : fields - ]), - "right" : this->_getQualified([ - "type" : "qualified", - "domain" : joinAlias, - "name" : referencedFields - ]) + "type" : "binary-op", + "op" : "=", + "left" : this->_getQualified( + [ + "type" : PHQL_T_QUALIFIED, + "domain" : modelAlias, + "name" : fields + ] + ), + "right": this->_getQualified( + [ + "type" : "qualified", + "domain" : joinAlias, + "name" : referencedFields + ] + ) ] ]; - } else { - /** * Resolve the compound operation */ let sqlJoinPartialConditions = []; - for position, field in fields { + for position, field in fields { /** * Get the referenced field in the same position */ @@ -1114,16 +1123,20 @@ class Query implements QueryInterface, InjectionAwareInterface let sqlJoinPartialConditions[] = [ "type" : "binary-op", "op" : "=", - "left" : this->_getQualified([ - "type" : PHQL_T_QUALIFIED, - "domain" : modelAlias, - "name" : field - ]), - "right" : this->_getQualified([ - "type" : "qualified", - "domain" : joinAlias, - "name" : referencedField - ]) + "left" : this->_getQualified( + [ + "type" : PHQL_T_QUALIFIED, + "domain" : modelAlias, + "name" : field + ] + ), + "right": this->_getQualified( + [ + "type" : "qualified", + "domain" : joinAlias, + "name" : referencedField + ] + ) ]; } @@ -1215,9 +1228,7 @@ class Query implements QueryInterface, InjectionAwareInterface let referencedModelName = relation->getReferencedModel(); if typeof fields == "array" { - for field, position in fields { - if !isset referencedFields[position] { throw new Exception( "The number of fields must be equal to the number of referenced fields in join " . modelAlias . "-" . joinAlias . ", when preparing: " . this->phql @@ -1234,17 +1245,21 @@ class Query implements QueryInterface, InjectionAwareInterface */ let sqlEqualsJoinCondition = [ "type" : "binary-op", - "op" : "=", - "left" : this->_getQualified([ - "type" : PHQL_T_QUALIFIED, - "domain" : modelAlias, - "name" : field - ]), - "right" : this->_getQualified([ - "type" : "qualified", - "domain" : joinAlias, - "name" : referencedFields - ]) + "op" : "=", + "left" : this->_getQualified( + [ + "type" : PHQL_T_QUALIFIED, + "domain" : modelAlias, + "name" : field + ] + ), + "right" : this->_getQualified( + [ + "type" : "qualified", + "domain" : joinAlias, + "name" : referencedFields + ] + ) ]; //let sqlJoinPartialConditions[] = sqlEqualsJoinCondition; @@ -1259,24 +1274,29 @@ class Query implements QueryInterface, InjectionAwareInterface * A single join */ let sqlJoins = [ - [ - "type" : joinType, - "source" : intermediateSource, - "conditions" : [[ - "type" : "binary-op", - "op" : "=", - "left" : this->_getQualified([ - "type" : PHQL_T_QUALIFIED, - "domain" : modelAlias, - "name" : fields - ]), - "right" : this->_getQualified([ - "type" : "qualified", - "domain" : intermediateModelName, - "name" : intermediateFields - ]) - ]] + "type" : joinType, + "source" : intermediateSource, + "conditions" : [ + [ + "type" : "binary-op", + "op" : "=", + "left" : this->_getQualified( + [ + "type" : PHQL_T_QUALIFIED, + "domain" : modelAlias, + "name" : fields + ] + ), + "right" : this->_getQualified( + [ + "type" : "qualified", + "domain" : intermediateModelName, + "name" : intermediateFields + ] + ) + ] + ] ], /** @@ -1286,22 +1306,28 @@ class Query implements QueryInterface, InjectionAwareInterface * A single join */ [ - "type" : joinType, - "source" : joinSource, - "conditions" : [[ - "type" : "binary-op", - "op" : "=", - "left" : this->_getQualified([ - "type" : PHQL_T_QUALIFIED, - "domain" : intermediateModelName, - "name" : intermediateReferencedFields - ]), - "right" : this->_getQualified([ - "type" : "qualified", - "domain" : referencedModelName, - "name" : referencedFields - ]) - ]] + "type" : joinType, + "source" : joinSource, + "conditions" : [ + [ + "type" : "binary-op", + "op" : "=", + "left" : this->_getQualified( + [ + "type" : PHQL_T_QUALIFIED, + "domain" : intermediateModelName, + "name" : intermediateReferencedFields + ] + ), + "right" : this->_getQualified( + [ + "type" : "qualified", + "domain" : referencedModelName, + "name" : referencedFields + ] + ) + ] + ] ] ]; } @@ -1342,6 +1368,7 @@ class Query implements QueryInterface, InjectionAwareInterface let manager = this->manager; let tables = select["tables"]; + if !isset tables[0] { let selectTables = [tables]; } else { @@ -1349,6 +1376,7 @@ class Query implements QueryInterface, InjectionAwareInterface } let joins = select["joins"]; + if !isset joins[0] { let selectJoins = [joins]; } else { @@ -1376,7 +1404,6 @@ class Query implements QueryInterface, InjectionAwareInterface * Process join alias */ if fetch aliasExpr, joinItem["alias"] { - let alias = aliasExpr["name"]; /** @@ -1437,9 +1464,7 @@ class Query implements QueryInterface, InjectionAwareInterface * Complete source related to a model */ let joinPrepared[alias] = joinItem; - } else { - /** * Check if alias is unique */ @@ -1532,6 +1557,7 @@ class Query implements QueryInterface, InjectionAwareInterface "conditions": [preCondition] ]; } + return sqlJoins; } @@ -1539,6 +1565,7 @@ class Query implements QueryInterface, InjectionAwareInterface * Build the list of tables used in the SELECT clause */ let fromModels = []; + for tableItem in selectTables { let fromModels[tableItem["qualifiedName"]["name"]] = true; } @@ -1547,9 +1574,7 @@ class Query implements QueryInterface, InjectionAwareInterface * Create join relationships dynamically */ for fromModelName, _ in fromModels { - for joinAlias, joinModel in joinModels { - /** * Real source name for joined model */ @@ -1564,7 +1589,6 @@ class Query implements QueryInterface, InjectionAwareInterface * Check if the model already have pre-defined conditions */ if !fetch preCondition, joinPreCondition[joinAlias] { - /** * Get the model name from its source */ @@ -1579,7 +1603,6 @@ class Query implements QueryInterface, InjectionAwareInterface ); if relation === false { - /** * Check for relations between models */ @@ -1589,7 +1612,6 @@ class Query implements QueryInterface, InjectionAwareInterface ); if typeof relations == "array" { - /** * More than one relation must throw an exception */ @@ -1610,7 +1632,6 @@ class Query implements QueryInterface, InjectionAwareInterface * Valid relations are objects */ if typeof relation == "object" { - /** * Get the related model alias of the left part */ @@ -1647,21 +1668,18 @@ class Query implements QueryInterface, InjectionAwareInterface } else { let sqlJoins[] = sqlJoin; } - } else { - /** * Join without conditions because no relation has been * found between the models */ let sqlJoins[] = [ - "type": joinType, - "source": joinSource, + "type": joinType, + "source": joinSource, "conditions": [] ]; } } else { - /** * Get the conditions established by the developer * Join with conditions established by the developer @@ -1685,8 +1703,8 @@ class Query implements QueryInterface, InjectionAwareInterface */ final protected function _getOrderClause(order) -> array { - var orderColumns, orderParts, orderItem, orderPartExpr, - orderSort, orderPartSort; + var orderColumns, orderParts, orderItem, orderPartExpr, orderSort, + orderPartSort; if !isset order[0] { let orderColumns = [order]; @@ -1695,9 +1713,11 @@ class Query implements QueryInterface, InjectionAwareInterface } let orderParts = []; - for orderItem in orderColumns { - let orderPartExpr = this->_getExpression(orderItem["column"]); + for orderItem in orderColumns { + let orderPartExpr = this->_getExpression( + orderItem["column"] + ); /** * Check if the order has a predefined ordering mode @@ -1730,11 +1750,14 @@ class Query implements QueryInterface, InjectionAwareInterface * The select is grouped by several columns */ let groupParts = []; + for groupItem in group { let groupParts[] = this->_getExpression(groupItem); } } else { - let groupParts = [this->_getExpression(group)]; + let groupParts = [ + this->_getExpression(group) + ]; } return groupParts; } @@ -1872,7 +1895,6 @@ class Query implements QueryInterface, InjectionAwareInterface automaticJoins = []; for selectedModel in selectedModels { - let qualifiedName = selectedModel["qualifiedName"], modelName = qualifiedName["name"]; @@ -1903,7 +1925,6 @@ class Query implements QueryInterface, InjectionAwareInterface * referenced in the column list */ if fetch alias, selectedModel["alias"] { - // Check if the alias was used before if isset sqlAliases[alias] { throw new Exception( @@ -1924,8 +1945,8 @@ class Query implements QueryInterface, InjectionAwareInterface } else { let completeSource = [source, null, alias]; } - let models[realModelName] = alias; + let models[realModelName] = alias; } else { let alias = source, sqlAliases[realModelName] = source, @@ -1937,7 +1958,6 @@ class Query implements QueryInterface, InjectionAwareInterface // Eager load any specified relationship(s) if fetch with, selectedModel["with"] { - if !isset with[0] { let withs = [with]; } else { @@ -1946,7 +1966,6 @@ class Query implements QueryInterface, InjectionAwareInterface // Simulate the definition of inner joins for withItem in withs { - let joinAlias = "AA" . number, relationModel = withItem["name"]; @@ -2014,7 +2033,6 @@ class Query implements QueryInterface, InjectionAwareInterface this->sqlModelsAliases = sqlModelsAliases, this->sqlAliasesModelsInstances = sqlAliasesModelsInstances; } else { - let tempModels = this->models, tempModelsInstances = this->modelsInstances, tempSqlAliases = this->sqlAliases, @@ -2057,14 +2075,11 @@ class Query implements QueryInterface, InjectionAwareInterface sqlColumnAliases = []; for column in selectColumns { - for sqlColumn in this->_getSelectColumn(column) { - /** * If "alias" is set, the user defined an alias for the column */ if fetch alias, column["alias"] { - /** * The best alias is the one provided by the user */ @@ -2072,7 +2087,6 @@ class Query implements QueryInterface, InjectionAwareInterface sqlColumn["sqlAlias"] = alias, sqlColumns[alias] = sqlColumn, sqlColumnAliases[alias] = true; - } else { /** * "balias" is the best alias chosen for the column @@ -2081,6 +2095,7 @@ class Query implements QueryInterface, InjectionAwareInterface if isset column["column"]["domain"] { let alias = column["column"]["domain"] . "_" . alias; } + let sqlColumns[alias] = sqlColumn; } else { if sqlColumn["type"] == "scalar" { @@ -2094,6 +2109,7 @@ class Query implements QueryInterface, InjectionAwareInterface let position++; } } + let this->sqlColumnAliases[this->nestingLevel] = sqlColumnAliases; // sqlSelect is the final prepared SELECT @@ -2206,7 +2222,6 @@ class Query implements QueryInterface, InjectionAwareInterface exprValues = []; for exprValue in ast["values"] { - // Resolve every expression in the "values" clause let exprValues[] = [ "type" : exprValue["type"], @@ -2223,8 +2238,8 @@ class Query implements QueryInterface, InjectionAwareInterface if fetch fields, ast["fields"] { let sqlFields = []; - for field in fields { + for field in fields { let name = field["name"]; // Check that inserted fields are part of the model @@ -2293,8 +2308,8 @@ class Query implements QueryInterface, InjectionAwareInterface } let manager = this->manager; - for table in updateTables { + for table in updateTables { let qualifiedName = table["qualifiedName"], modelName = qualifiedName["name"]; @@ -2361,8 +2376,8 @@ class Query implements QueryInterface, InjectionAwareInterface } let notQuoting = false; - for updateValue in updateValues { + for updateValue in updateValues { let sqlFields[] = this->_getExpression(updateValue["column"], notQuoting), exprColumn = updateValue["expr"], sqlValues[] = [ @@ -2395,11 +2410,10 @@ class Query implements QueryInterface, InjectionAwareInterface */ final protected function _prepareDelete() -> array { - var ast, delete, tables, models, modelsInstances, - sqlTables, sqlModels, sqlAliases, sqlAliasesModelsInstances, - deleteTables, manager, table, qualifiedName, modelName, nsAlias, - realModelName, model, source, schema, completeSource, alias, - sqlDelete, where, limit; + var ast, delete, tables, models, modelsInstances, sqlTables, sqlModels, + sqlAliases, sqlAliasesModelsInstances, deleteTables, manager, table, + qualifiedName, modelName, nsAlias, realModelName, model, source, + schema, completeSource, alias, sqlDelete, where, limit; let ast = this->ast; @@ -2430,8 +2444,8 @@ class Query implements QueryInterface, InjectionAwareInterface } let manager = this->manager; - for table in deleteTables { + for table in deleteTables { let qualifiedName = table["qualifiedName"], modelName = qualifiedName["name"]; @@ -2508,6 +2522,7 @@ class Query implements QueryInterface, InjectionAwareInterface var intermediate, phql, ast, irPhql, uniqueId, type; let intermediate = this->intermediate; + if typeof intermediate == "array" { return intermediate; } @@ -2518,10 +2533,10 @@ class Query implements QueryInterface, InjectionAwareInterface let phql = this->phql, ast = phql_parse_phql(phql); - let irPhql = null, uniqueId = null; + let irPhql = null, + uniqueId = null; if typeof ast == "array" { - /** * Check if the prepared PHQL is already cached * Parsed ASTs have a unique id @@ -2531,6 +2546,7 @@ class Query implements QueryInterface, InjectionAwareInterface if typeof irPhql == "array" { // Assign the type to the query let this->type = ast["type"]; + return irPhql; } } @@ -2540,12 +2556,10 @@ class Query implements QueryInterface, InjectionAwareInterface * A valid AST must have a type */ if fetch type, ast["type"] { - let this->ast = ast, this->type = type; switch type { - case PHQL_T_SELECT: let irPhql = this->_prepareSelect(); break; @@ -2582,6 +2596,7 @@ class Query implements QueryInterface, InjectionAwareInterface } let this->intermediate = irPhql; + return irPhql; } @@ -2619,7 +2634,6 @@ class Query implements QueryInterface, InjectionAwareInterface let models = intermediate["models"]; for modelName in models { - // Load model if it is not loaded if !fetch model, this->modelsInstances[modelName] { let model = manager->load(modelName), @@ -2636,6 +2650,7 @@ class Query implements QueryInterface, InjectionAwareInterface if typeof connection == "object" { // More than one type of connection is not allowed let connectionTypes[connection->getType()] = true; + if count(connectionTypes) == 2 { throw new Exception( "Cannot use models of different database systems in the same query" @@ -2655,7 +2670,6 @@ class Query implements QueryInterface, InjectionAwareInterface let columns1 = columns; for column in columns { - if typeof column != "array" { throw new Exception("Invalid column definition"); } @@ -2664,9 +2678,11 @@ class Query implements QueryInterface, InjectionAwareInterface if !isset column["balias"] { let isComplex = true; } + let haveScalars = true; } else { - let haveObjects = true, numberObjects++; + let haveObjects = true, + numberObjects++; } } @@ -2694,12 +2710,10 @@ class Query implements QueryInterface, InjectionAwareInterface metaData = this->metaData; for aliasCopy, column in columns { - let sqlColumn = column["column"]; // Complete objects are treated in a different way if column["type"] == "object" { - let modelName = column["model"]; /** @@ -2711,8 +2725,8 @@ class Query implements QueryInterface, InjectionAwareInterface } let attributes = metaData->getAttributes(instance); - if isComplex { + if isComplex { /** * If the resultset is complex we open every model into * their columns @@ -2745,9 +2759,7 @@ class Query implements QueryInterface, InjectionAwareInterface if isKeepingSnapshots { let columns1[aliasCopy]["keepSnapshots"] = isKeepingSnapshots; } - } else { - /** * Query only the columns that are registered as attributes * in the metaData @@ -2757,7 +2769,6 @@ class Query implements QueryInterface, InjectionAwareInterface } } } else { - /** * Create an alias if the column doesn't have one */ @@ -2766,6 +2777,7 @@ class Query implements QueryInterface, InjectionAwareInterface } else { let columnAlias = [sqlColumn, null, aliasCopy]; } + let selectColumns[] = columnAlias; } @@ -2789,8 +2801,8 @@ class Query implements QueryInterface, InjectionAwareInterface */ if typeof bindParams == "array" { let processed = []; - for wildcard, value in bindParams { + for wildcard, value in bindParams { if typeof wildcard == "integer" { let wildcardValue = ":" . wildcard; } else { @@ -2798,6 +2810,7 @@ class Query implements QueryInterface, InjectionAwareInterface } let processed[wildcardValue] = value; + if typeof value == "array" { let bindCounts[wildcardValue] = count(value); } @@ -2811,6 +2824,7 @@ class Query implements QueryInterface, InjectionAwareInterface */ if typeof bindTypes == "array" { let processedTypes = []; + for typeWildcard, value in bindTypes { if typeof typeWildcard == "integer" { let processedTypes[":" . typeWildcard] = value; @@ -2832,6 +2846,7 @@ class Query implements QueryInterface, InjectionAwareInterface */ let dialect = connection->getDialect(), sqlSelect = dialect->select(intermediate); + if this->sharedLock { let sqlSelect = dialect->sharedLock(sqlSelect); } @@ -2865,13 +2880,12 @@ class Query implements QueryInterface, InjectionAwareInterface * Choose a resultset type */ let cache = this->cache; - if !isComplex { + if !isComplex { /** * Select the base object */ if isSimpleStd { - /** * If the result is a simple standard object use an * Phalcon\Mvc\Model\Row as base @@ -2882,9 +2896,7 @@ class Query implements QueryInterface, InjectionAwareInterface * Standard objects can't keep snapshots */ let isKeepingSnapshots = false; - } else { - if typeof instance == "object" { let resultObject = instance; } else { @@ -2897,12 +2909,12 @@ class Query implements QueryInterface, InjectionAwareInterface if !globals_get("orm.cast_on_hydrate") { let simpleColumnMap = metaData->getColumnMap(resultObject); } else { - let columnMap = metaData->getColumnMap(resultObject), typesColumnMap = metaData->getDataTypes(resultObject); if typeof columnMap === "null" { let simpleColumnMap = []; + for attribute in metaData->getAttributes(resultObject) { let simpleColumnMap[attribute] = [ attribute, @@ -2911,6 +2923,7 @@ class Query implements QueryInterface, InjectionAwareInterface } } else { let simpleColumnMap = []; + for column, attribute in columnMap { let simpleColumnMap[column] = [ attribute, @@ -2979,15 +2992,16 @@ class Query implements QueryInterface, InjectionAwareInterface */ final protected function _executeInsert(array intermediate, var bindParams, var bindTypes) -> { - var modelName, manager, connection, metaData, attributes, - fields, columnMap, dialect, insertValues, number, value, model, - values, exprValue, insertValue, wildcard, fieldName, attributeName, + var modelName, manager, connection, metaData, attributes, fields, + columnMap, dialect, insertValues, number, value, model, values, + exprValue, insertValue, wildcard, fieldName, attributeName, insertModel; bool automaticFields; let modelName = intermediate["model"]; let manager = this->manager; + if !fetch model, this->modelsInstances[modelName] { let model = manager->load(modelName); } @@ -2999,7 +3013,8 @@ class Query implements QueryInterface, InjectionAwareInterface bindTypes ); - let metaData = this->metaData, attributes = metaData->getAttributes(model); + let metaData = this->metaData, + attributes = metaData->getAttributes(model); let automaticFields = false; @@ -3010,6 +3025,7 @@ class Query implements QueryInterface, InjectionAwareInterface if !fetch fields, intermediate["fields"] { let automaticFields = true, fields = attributes; + if globals_get("orm.column_renaming") { let columnMap = metaData->getColumnMap(model); } else { @@ -3036,8 +3052,8 @@ class Query implements QueryInterface, InjectionAwareInterface let insertValues = []; for number, value in values { - let exprValue = value["value"]; + switch value["type"] { case PHQL_T_STRING: @@ -3060,7 +3076,12 @@ class Query implements QueryInterface, InjectionAwareInterface ); } - let wildcard = str_replace(":", "", dialect->getSqlExpression(exprValue)); + let wildcard = str_replace( + ":", + "", + dialect->getSqlExpression(exprValue) + ); + if !fetch insertValue, bindParams[wildcard] { throw new Exception( "Bound parameter '" . wildcard . "' cannot be replaced because it isn't in the placeholders list" @@ -3070,7 +3091,10 @@ class Query implements QueryInterface, InjectionAwareInterface break; default: - let insertValue = new RawValue(dialect->getSqlExpression(exprValue)); + let insertValue = new RawValue( + dialect->getSqlExpression(exprValue) + ); + break; } @@ -3080,15 +3104,11 @@ class Query implements QueryInterface, InjectionAwareInterface * If the user didn't define a column list we assume all the model's * attributes as columns */ - if automaticFields { - if typeof columnMap == "array" { - if !fetch attributeName, columnMap[fieldName] { - throw new Exception( - "Column '" . fieldName . "' isn't part of the column map" - ); - } - } else { - let attributeName = fieldName; + if automaticFields && typeof columnMap == "array" { + if !fetch attributeName, columnMap[fieldName] { + throw new Exception( + "Column '" . fieldName . "' isn't part of the column map" + ); } } else { let attributeName = fieldName; @@ -3108,7 +3128,10 @@ class Query implements QueryInterface, InjectionAwareInterface * Call 'create' to ensure that an insert is performed * Return the insert status */ - return new Status(insertModel->create(), insertModel); + return new Status( + insertModel->create(), + insertModel + ); } /** @@ -3120,10 +3143,9 @@ class Query implements QueryInterface, InjectionAwareInterface */ final protected function _executeUpdate(array intermediate, var bindParams, var bindTypes) -> { - var models, modelName, model, connection, dialect, - fields, values, updateValues, fieldName, value, - selectBindParams, selectBindTypes, number, field, - records, exprValue, updateValue, wildcard, record; + var models, modelName, model, connection, dialect, fields, values, + updateValues, fieldName, value, selectBindParams, selectBindTypes, + number, field, records, exprValue, updateValue, wildcard, record; let models = intermediate["models"]; @@ -3168,7 +3190,6 @@ class Query implements QueryInterface, InjectionAwareInterface selectBindTypes = bindTypes; for number, field in fields { - let value = values[number], exprValue = value["value"]; @@ -3179,7 +3200,6 @@ class Query implements QueryInterface, InjectionAwareInterface } switch value["type"] { - case PHQL_T_STRING: case PHQL_T_INTEGER: case PHQL_T_DOUBLE: @@ -3263,7 +3283,6 @@ class Query implements QueryInterface, InjectionAwareInterface //for record in iterator(records) { while records->valid() { - let record = records->current(); record->assign(updateValues); @@ -3272,7 +3291,6 @@ class Query implements QueryInterface, InjectionAwareInterface * We apply the executed values to every record found */ if !record->update() { - /** * Rollback the transaction on failure */ @@ -3351,14 +3369,12 @@ class Query implements QueryInterface, InjectionAwareInterface records->rewind(); while records->valid() { - let record = records->current(); /** * We delete every record found */ if !record->delete() { - /** * Rollback the transaction */ @@ -3425,6 +3441,7 @@ class Query implements QueryInterface, InjectionAwareInterface * We create another Phalcon\Mvc\Model\Query to get the related records */ let query = new self(); + query->setDI(this->container); query->setType(PHQL_T_SELECT); query->setIntermediate(selectIr); @@ -3441,15 +3458,15 @@ class Query implements QueryInterface, InjectionAwareInterface */ public function execute(var bindParams = null, var bindTypes = null) { - var uniqueRow, cacheOptions, key, cacheService, - cache, result, preparedResult, defaultBindParams, mergedParams, - defaultBindTypes, mergedTypes, type, lifetime, intermediate; + var uniqueRow, cacheOptions, key, cacheService, cache, result, + preparedResult, defaultBindParams, mergedParams, defaultBindTypes, + mergedTypes, type, lifetime, intermediate; let uniqueRow = this->uniqueRow; let cacheOptions = this->cacheOptions; - if typeof cacheOptions != "null" { + if typeof cacheOptions != "null" { if typeof cacheOptions != "array" { throw new Exception("Invalid caching options"); } @@ -3478,13 +3495,14 @@ class Query implements QueryInterface, InjectionAwareInterface } let cache = this->container->getShared(cacheService); + if typeof cache != "object" { throw new Exception("Cache service must be an object"); } let result = cache->get(key, lifetime); - if !empty result { + if !empty result { if typeof result != "object" { throw new Exception( "Cache didn't return a valid resultset" @@ -3518,6 +3536,7 @@ class Query implements QueryInterface, InjectionAwareInterface * Check for default bind parameters and merge them with the passed ones */ let defaultBindParams = this->bindParams; + if typeof defaultBindParams == "array" { if typeof bindParams == "array" { let mergedParams = defaultBindParams + bindParams; @@ -3532,6 +3551,7 @@ class Query implements QueryInterface, InjectionAwareInterface * Check for default bind types and merge them with the passed ones */ let defaultBindTypes = this->bindTypes; + if typeof defaultBindTypes == "array" { if typeof bindTypes == "array" { let mergedTypes = defaultBindTypes + bindTypes; @@ -3551,8 +3571,8 @@ class Query implements QueryInterface, InjectionAwareInterface } let type = this->type; - switch type { + switch type { case PHQL_T_SELECT: let result = this->_executeSelect( intermediate, @@ -3646,6 +3666,7 @@ class Query implements QueryInterface, InjectionAwareInterface public function setType(int type) -> { let this->type = type; + return this; } @@ -3666,6 +3687,7 @@ class Query implements QueryInterface, InjectionAwareInterface if merge { let currentBindParams = this->bindParams; + if typeof currentBindParams == "array" { let this->bindParams = currentBindParams + bindParams; } else { @@ -3695,6 +3717,7 @@ class Query implements QueryInterface, InjectionAwareInterface if unlikely merge { let currentBindTypes = this->bindTypes; + if typeof currentBindTypes == "array" { let this->bindTypes = currentBindTypes + bindTypes; } else { @@ -3731,6 +3754,7 @@ class Query implements QueryInterface, InjectionAwareInterface public function setIntermediate(array! intermediate) -> { let this->intermediate = intermediate; + return this; } @@ -3748,6 +3772,7 @@ class Query implements QueryInterface, InjectionAwareInterface public function cache(array cacheOptions) -> { let this->cacheOptions = cacheOptions; + return this; } @@ -3802,6 +3827,7 @@ class Query implements QueryInterface, InjectionAwareInterface protected function getReadConnection( model, array intermediate = null, array bindParams = null, array bindTypes = null) -> { var connection = null, transaction; + let transaction = this->_transaction; if typeof transaction == "object" && transaction instanceof TransactionInterface { @@ -3821,8 +3847,10 @@ class Query implements QueryInterface, InjectionAwareInterface "selectReadConnection did not return a connection" ); } + return connection; } + return model->getReadConnection(); } @@ -3865,6 +3893,7 @@ class Query implements QueryInterface, InjectionAwareInterface public function setTransaction( transaction) -> { let this->_transaction = transaction; + return this; } } diff --git a/phalcon/Mvc/Model/Query/Builder.zep b/phalcon/Mvc/Model/Query/Builder.zep index 481a3458e38..3ed07c92cee 100644 --- a/phalcon/Mvc/Model/Query/Builder.zep +++ b/phalcon/Mvc/Model/Query/Builder.zep @@ -84,13 +84,11 @@ class Builder implements BuilderInterface, InjectionAwareInterface { var conditions, columns, groupClause, havingClause, limitClause, forUpdate, sharedLock, orderClause, offsetClause, joinsClause, - singleConditionArray, limit, offset, fromClause, - mergedConditions, mergedParams, mergedTypes, - singleCondition, singleParams, singleTypes, - distinct, bind, bindTypes; + singleConditionArray, limit, offset, fromClause, mergedConditions, + mergedParams, mergedTypes, singleCondition, singleParams, + singleTypes, distinct, bind, bindTypes; if typeof params == "array" { - /** * Process conditions */ @@ -103,14 +101,12 @@ class Builder implements BuilderInterface, InjectionAwareInterface } if typeof conditions == "array" { - let mergedConditions = []; let mergedParams = []; let mergedTypes = []; - for singleConditionArray in conditions { + for singleConditionArray in conditions { if typeof singleConditionArray == "array" { - fetch singleCondition, singleConditionArray[0]; fetch singleParams, singleConditionArray[1]; fetch singleTypes, singleConditionArray[2]; @@ -209,6 +205,7 @@ class Builder implements BuilderInterface, InjectionAwareInterface if is_int(limit) { let this->limit = limit; } + if fetch offset, limitClause[1] { if is_int(offset) { let this->offset = offset; @@ -272,6 +269,7 @@ class Builder implements BuilderInterface, InjectionAwareInterface var models, currentModel; let models = this->models; + if typeof models != "array" { if typeof models != "null" { let currentModel = models, @@ -288,6 +286,7 @@ class Builder implements BuilderInterface, InjectionAwareInterface } let this->models = models; + return this; } @@ -417,6 +416,7 @@ class Builder implements BuilderInterface, InjectionAwareInterface public function columns(var columns) -> { let this->columns = columns; + return this; } @@ -428,11 +428,12 @@ class Builder implements BuilderInterface, InjectionAwareInterface * $builder->distinct(null); * */ - public function distinct(var distinct) -> - { - let this->distinct = distinct; - return this; - } + public function distinct(var distinct) -> + { + let this->distinct = distinct; + + return this; + } /** * Sets a FOR UPDATE clause @@ -444,6 +445,7 @@ class Builder implements BuilderInterface, InjectionAwareInterface public function forUpdate(bool forUpdate) -> { let this->forUpdate = forUpdate; + return this; } @@ -471,6 +473,7 @@ class Builder implements BuilderInterface, InjectionAwareInterface public function from(var models) -> { let this->models = models; + return this; } @@ -597,13 +600,13 @@ class Builder implements BuilderInterface, InjectionAwareInterface */ final public function getPhql() -> string { - var container, models, conditions, model, metaData, - modelInstance, primaryKeys, firstPrimaryKey, columnMap, modelAlias, - attributeField, phql, column, columns, selectedColumns, selectedColumn, - selectedModel, selectedModels, columnAlias, modelColumnAlias, - joins, join, joinModel, joinConditions, joinAlias, joinType, group, - groupItems, groupItem, having, order, orderItems, orderItem, - limit, number, offset, forUpdate, distinct; + var container, models, conditions, model, metaData, modelInstance, + primaryKeys, firstPrimaryKey, columnMap, modelAlias, attributeField, + phql, column, columns, selectedColumns, selectedColumn, + selectedModel, selectedModels, columnAlias, modelColumnAlias, joins, + join, joinModel, joinConditions, joinAlias, joinType, group, + groupItems, groupItem, having, order, orderItems, orderItem, limit, + number, offset, forUpdate, distinct; bool noPrimary; let container = this->container; @@ -630,7 +633,6 @@ class Builder implements BuilderInterface, InjectionAwareInterface let conditions = this->conditions; if is_numeric(conditions) { - /** * If the conditions is a single numeric field. We internally create * a condition using the related primary key @@ -706,13 +708,12 @@ class Builder implements BuilderInterface, InjectionAwareInterface let columns = this->columns; if typeof columns !== "null" { - /** * Generate PHQL for columns */ if typeof columns == "array" { - let selectedColumns = []; + for columnAlias, column in columns { if typeof columnAlias == "integer" { let selectedColumns[] = column; @@ -722,25 +723,24 @@ class Builder implements BuilderInterface, InjectionAwareInterface } let phql .= join(", ", selectedColumns); - } else { let phql .= columns; } } else { - /** * Automatically generate an array of models */ if typeof models == "array" { - let selectedColumns = []; + for modelColumnAlias, model in models { if typeof modelColumnAlias == "integer" { let selectedColumn = this->autoescape(model) . ".*"; } else { let selectedColumn = this->autoescape(modelColumnAlias) . ".*"; } + let selectedColumns[] = selectedColumn; } @@ -754,10 +754,9 @@ class Builder implements BuilderInterface, InjectionAwareInterface * Join multiple models or use a single one if it is a string */ if typeof models == "array" { - let selectedModels = []; - for modelAlias, model in models { + for modelAlias, model in models { if typeof modelAlias == "string" { let selectedModel = this->autoescape(model) . " AS " . this->autoescape(modelAlias); } else { @@ -778,9 +777,7 @@ class Builder implements BuilderInterface, InjectionAwareInterface */ let joins = this->joins; if typeof joins == "array" { - for join in joins { - /** * The joined table is in the first place of the array */ @@ -839,6 +836,7 @@ class Builder implements BuilderInterface, InjectionAwareInterface let group = this->group; if group !== null { let groupItems = []; + for groupItem in group { let groupItems[] = this->autoescape(groupItem); } @@ -863,6 +861,7 @@ class Builder implements BuilderInterface, InjectionAwareInterface if order !== null { if typeof order == "array" { let orderItems = []; + for orderItem in order { /** * For case 'ORDER BY 1' @@ -875,6 +874,7 @@ class Builder implements BuilderInterface, InjectionAwareInterface if memstr(orderItem, " ") !== 0 { var itemExplode; + let itemExplode = explode(" ", orderItem); let orderItems[] = this->autoescape(itemExplode[0]) . " " . itemExplode[1]; @@ -895,17 +895,16 @@ class Builder implements BuilderInterface, InjectionAwareInterface */ let limit = this->limit; if limit !== null { - let number = null; - if typeof limit == "array" { + if typeof limit == "array" { let number = limit["number"]; + if fetch offset, limit["offset"] { if !is_numeric(offset) { let offset = 0; } } - } else { if is_numeric(limit) { let number = limit, @@ -919,7 +918,6 @@ class Builder implements BuilderInterface, InjectionAwareInterface } if is_numeric(number) { - let phql .= " LIMIT :APL0:", this->bindParams["APL0"] = intval(number, 10), this->bindTypes["APL0"] = Column::BIND_PARAM_INT; @@ -1055,6 +1053,7 @@ class Builder implements BuilderInterface, InjectionAwareInterface */ if typeof bindParams == "array" { let currentBindParams = this->bindParams; + if typeof currentBindParams == "array" { let this->bindParams = currentBindParams + bindParams; } else { @@ -1067,6 +1066,7 @@ class Builder implements BuilderInterface, InjectionAwareInterface */ if typeof bindTypes == "array" { let currentBindTypes = this->bindTypes; + if typeof currentBindTypes == "array" { let this->bindTypes = currentBindTypes + bindTypes; } else { @@ -1106,6 +1106,7 @@ class Builder implements BuilderInterface, InjectionAwareInterface public function innerJoin(string! model, string conditions = null, string alias = null) -> { let this->joins[] = [model, conditions, alias, "INNER"]; + return this; } @@ -1113,7 +1114,10 @@ class Builder implements BuilderInterface, InjectionAwareInterface * Appends an IN condition to the current WHERE conditions * * - * $builder->inWhere("id", [1, 2, 3]); + * $builder->inWhere( + * "id", + * [1, 2, 3] + * ); * */ public function inWhere(string! expr, array! values, string! operator = BuilderInterface::OPERATOR_AND) -> @@ -1141,6 +1145,7 @@ class Builder implements BuilderInterface, InjectionAwareInterface public function join(string! model, string conditions = null, string alias = null, string type = null) -> { let this->joins[] = [model, conditions, alias, type]; + return this; } @@ -1154,6 +1159,7 @@ class Builder implements BuilderInterface, InjectionAwareInterface public function leftJoin(string! model, string conditions = null, string alias = null) -> { let this->joins[] = [model, conditions, alias, "LEFT"]; + return this; } @@ -1241,6 +1247,7 @@ class Builder implements BuilderInterface, InjectionAwareInterface public function offset(int offset) -> { let this->offset = offset; + return this; } @@ -1258,6 +1265,7 @@ class Builder implements BuilderInterface, InjectionAwareInterface public function orderBy(var orderBy) -> { let this->order = orderBy; + return this; } @@ -1337,6 +1345,7 @@ class Builder implements BuilderInterface, InjectionAwareInterface public function rightJoin(string! model, string conditions = null, string alias = null) -> { let this->joins[] = [model, conditions, alias, "RIGHT"]; + return this; } @@ -1370,6 +1379,7 @@ class Builder implements BuilderInterface, InjectionAwareInterface if unlikely merge { let currentBindTypes = this->bindTypes; + if typeof currentBindTypes == "array" { let this->bindTypes = currentBindTypes + bindTypes; } else { @@ -1388,6 +1398,7 @@ class Builder implements BuilderInterface, InjectionAwareInterface public function setDI( container) -> { let this->container = container; + return this; } @@ -1419,6 +1430,7 @@ class Builder implements BuilderInterface, InjectionAwareInterface */ if count(bindParams) > 0 { let currentBindParams = this->bindParams; + if typeof currentBindParams == "array" { let this->bindParams = currentBindParams + bindParams; } else { @@ -1431,6 +1443,7 @@ class Builder implements BuilderInterface, InjectionAwareInterface */ if count(bindTypes) > 0 { let currentBindTypes = this->bindTypes; + if typeof currentBindTypes == "array" { let this->bindTypes = currentBindTypes + bindTypes; } else { @@ -1448,7 +1461,7 @@ class Builder implements BuilderInterface, InjectionAwareInterface { var hiddenParam, nextHiddenParam, minimumKey, maximumKey, operatorMethod; - if (operator !== Builder::OPERATOR_AND && operator !== Builder::OPERATOR_OR) { + if operator !== Builder::OPERATOR_AND && operator !== Builder::OPERATOR_OR { throw new Exception(sprintf("Operator % is not available.", operator)); } @@ -1471,7 +1484,10 @@ class Builder implements BuilderInterface, InjectionAwareInterface this->{operatorMethod}( expr . " BETWEEN :" . minimumKey . ": AND :" . maximumKey . ":", - [minimumKey: minimum, maximumKey: maximum] + [ + minimumKey: minimum, + maximumKey: maximum + ] ); let nextHiddenParam++, @@ -1488,22 +1504,29 @@ class Builder implements BuilderInterface, InjectionAwareInterface var key, queryKey, value, bindKeys, bindParams, operatorMethod; int hiddenParam; - if (operator !== Builder::OPERATOR_AND && operator !== Builder::OPERATOR_OR) { - throw new Exception(sprintf("Operator % is not available.", operator)); + if operator !== Builder::OPERATOR_AND && operator !== Builder::OPERATOR_OR { + throw new Exception( + sprintf( + "Operator % is not available.", + operator + ) + ); } let operatorMethod = operator . clause; if !count(values) { this->{operatorMethod}(expr . " != " . expr); + return this; } let hiddenParam = (int) this->hiddenParamNumber; - let bindParams = [], bindKeys = []; - for value in values { + let bindParams = [], + bindKeys = []; + for value in values { /** * Key with auto bind-params */ @@ -1518,7 +1541,10 @@ class Builder implements BuilderInterface, InjectionAwareInterface * Create a standard IN condition with bind params * Append the IN to the current conditions using and "and" */ - this->{operatorMethod}(expr . " IN (" . join(", ", bindKeys) . ")", bindParams); + this->{operatorMethod}( + expr . " IN (" . join(", ", bindKeys) . ")", + bindParams + ); let this->hiddenParamNumber = hiddenParam; @@ -1532,8 +1558,13 @@ class Builder implements BuilderInterface, InjectionAwareInterface { var hiddenParam, nextHiddenParam, minimumKey, maximumKey, operatorMethod; - if (operator !== Builder::OPERATOR_AND && operator !== Builder::OPERATOR_OR) { - throw new Exception(sprintf("Operator % is not available.", operator)); + if operator !== Builder::OPERATOR_AND && operator !== Builder::OPERATOR_OR { + throw new Exception( + sprintf( + "Operator % is not available.", + operator + ) + ); } let operatorMethod = operator . clause; @@ -1554,7 +1585,10 @@ class Builder implements BuilderInterface, InjectionAwareInterface */ this->{operatorMethod}( expr . " NOT BETWEEN :" . minimumKey . ": AND :" . maximumKey . ":", - [minimumKey: minimum, maximumKey: maximum] + [ + minimumKey: minimum, + maximumKey: maximum + ] ); let nextHiddenParam++, @@ -1571,22 +1605,29 @@ class Builder implements BuilderInterface, InjectionAwareInterface var key, queryKey, value, bindKeys, bindParams, operatorMethod; int hiddenParam; - if (operator !== Builder::OPERATOR_AND && operator !== Builder::OPERATOR_OR) { - throw new Exception(sprintf("Operator % is not available.", operator)); + if operator !== Builder::OPERATOR_AND && operator !== Builder::OPERATOR_OR { + throw new Exception( + sprintf( + "Operator % is not available.", + operator + ) + ); } let operatorMethod = operator . clause; if !count(values) { this->{operatorMethod}(expr . " != " . expr); + return this; } let hiddenParam = (int) this->hiddenParamNumber; - let bindParams = [], bindKeys = []; - for value in values { + let bindParams = [], + bindKeys = []; + for value in values { /** * Key with auto bind-params */ diff --git a/phalcon/Mvc/Model/Query/BuilderInterface.zep b/phalcon/Mvc/Model/Query/BuilderInterface.zep index 5d8ceb56a90..b913a3b3fda 100644 --- a/phalcon/Mvc/Model/Query/BuilderInterface.zep +++ b/phalcon/Mvc/Model/Query/BuilderInterface.zep @@ -250,5 +250,4 @@ interface BuilderInterface * Sets conditions for the query */ public function where(string conditions, array bindParams = [], array bindTypes = []) -> ; - } diff --git a/phalcon/Mvc/Model/Query/Lang.zep b/phalcon/Mvc/Model/Query/Lang.zep index 2d095d0b459..13d3dbc7b42 100644 --- a/phalcon/Mvc/Model/Query/Lang.zep +++ b/phalcon/Mvc/Model/Query/Lang.zep @@ -24,7 +24,9 @@ namespace Phalcon\Mvc\Model\Query; * parser with a very low memory footprint that is also thread-safe. * * - * $intermediate = Phalcon\Mvc\Model\Query\Lang::parsePHQL("SELECT r.* FROM Robots r LIMIT 10"); + * $intermediate = Phalcon\Mvc\Model\Query\Lang::parsePHQL( + * "SELECT r.* FROM Robots r LIMIT 10" + * ); * */ abstract class Lang diff --git a/phalcon/Mvc/Model/Query/Status.zep b/phalcon/Mvc/Model/Query/Status.zep index 99cc08a8550..125aa83abfa 100644 --- a/phalcon/Mvc/Model/Query/Status.zep +++ b/phalcon/Mvc/Model/Query/Status.zep @@ -62,10 +62,13 @@ class Status implements StatusInterface public function getMessages() -> { var model; + let model = this->model; + if typeof model != "object" { return []; } + return model->getMessages(); } diff --git a/phalcon/Mvc/Model/Relation.zep b/phalcon/Mvc/Model/Relation.zep index fad47679546..0836bfc6161 100644 --- a/phalcon/Mvc/Model/Relation.zep +++ b/phalcon/Mvc/Model/Relation.zep @@ -40,12 +40,10 @@ class Relation implements RelationInterface /** * Phalcon\Mvc\Model\Relation constructor * - * @param int type * @param string|array fields * @param string|array referencedFields - * @param array options */ - public function __construct(int type, string! referencedModel, var fields, var referencedFields, var options = null) -> void + public function __construct(int type, string! referencedModel, var fields, var referencedFields, array options = []) -> void { let this->type = type, this->referencedModel = referencedModel, @@ -72,14 +70,15 @@ class Relation implements RelationInterface public function getForeignKey() { var options, foreignKey; + let options = this->options; - if typeof options == "array" { - if fetch foreignKey, options["foreignKey"] { - if foreignKey { - return foreignKey; - } + + if fetch foreignKey, options["foreignKey"] { + if foreignKey { + return foreignKey; } } + return false; } @@ -118,18 +117,18 @@ class Relation implements RelationInterface public function getOption(string! name) { var option; - if fetch option, this->options[name] { - return option; + + if !fetch option, this->options[name] { + return null; } - return null; + + return option; } /** * Returns the options - * - * @return string|array */ - public function getOptions() + public function getOptions() -> array { return this->options; } @@ -142,14 +141,15 @@ class Relation implements RelationInterface public function getParams() { var options, params; + let options = this->options; - if typeof options == "array" { - if fetch params, options["params"] { - if params { - return params; - } + + if fetch params, options["params"] { + if params { + return params; } } + return false; } @@ -199,7 +199,9 @@ class Relation implements RelationInterface public function isThrough() -> bool { var type; + let type = this->type; + return type == self::HAS_ONE_THROUGH || type == self::HAS_MANY_THROUGH; } @@ -209,20 +211,21 @@ class Relation implements RelationInterface public function isReusable() -> bool { var options, reusable; + let options = this->options; - if typeof options == "array" { - if fetch reusable, options["reusable"] { - return reusable; - } + + if !fetch reusable, options["reusable"] { + return false; } - return false; + + return reusable; } /** * Sets the intermediate model data for has-*-through relations * * @param string|array intermediateFields - * @param string intermediateReferencedFields + * @param string intermediateReferencedFields */ public function setIntermediateRelation(var intermediateFields, string! intermediateModel, var intermediateReferencedFields) { diff --git a/phalcon/Mvc/Model/RelationInterface.zep b/phalcon/Mvc/Model/RelationInterface.zep index fdc0b471af6..6819ae38242 100644 --- a/phalcon/Mvc/Model/RelationInterface.zep +++ b/phalcon/Mvc/Model/RelationInterface.zep @@ -58,10 +58,8 @@ interface RelationInterface /** * Returns the options - * - * @return string|array */ - public function getOptions(); + public function getOptions() -> array; /** * Returns parameters that must be always used when the related records are obtained diff --git a/phalcon/Mvc/Model/Resultset.zep b/phalcon/Mvc/Model/Resultset.zep index d614023fee0..081a67d1cec 100644 --- a/phalcon/Mvc/Model/Resultset.zep +++ b/phalcon/Mvc/Model/Resultset.zep @@ -132,6 +132,7 @@ abstract class Resultset * Update the row-count */ let rowCount = result->numRows(); + let this->count = rowCount; /** @@ -279,6 +280,7 @@ abstract class Resultset */ if typeof processedRecord != "object" && typeof processedRecord != "array" { this->next(); + continue; } @@ -490,6 +492,7 @@ abstract class Resultset let this->pointer = position; let this->activeRow = null; + return; } @@ -497,6 +500,7 @@ abstract class Resultset * Fetch from PDO one-by-one. */ let result = this->result; + if this->row === null && this->pointer === 0 { /** * Fresh result-set: Query was already executed in @@ -568,11 +572,9 @@ abstract class Resultset this->rewind(); while this->valid() { - let record = this->current(); if transaction === false { - /** * We only can update resultsets if every element is a complete object */ @@ -603,7 +605,6 @@ abstract class Resultset * Try to update the record */ if !record->save() { - /** * Get the messages from the record that produce the error */ @@ -613,7 +614,9 @@ abstract class Resultset * Rollback the transaction */ connection->rollback(); + let transaction = false; + break; } diff --git a/phalcon/Mvc/Model/Resultset/Complex.zep b/phalcon/Mvc/Model/Resultset/Complex.zep index 50c6c0130b7..ce162c9e29c 100644 --- a/phalcon/Mvc/Model/Resultset/Complex.zep +++ b/phalcon/Mvc/Model/Resultset/Complex.zep @@ -56,12 +56,12 @@ class Complex extends Resultset implements ResultsetInterface */ final public function current() -> | bool { - var row, hydrateMode, eager, - dirtyState, alias, activeRow, type, column, columnValue, - value, attribute, source, attributes, - columnMap, rowModel, keepSnapshots, sqlAlias, modelName; + var row, hydrateMode, eager, dirtyState, alias, activeRow, type, column, + columnValue, value, attribute, source, attributes, columnMap, + rowModel, keepSnapshots, sqlAlias, modelName; let activeRow = this->activeRow; + if activeRow !== null { return activeRow; } @@ -76,6 +76,7 @@ class Complex extends Resultset implements ResultsetInterface */ if this->disableHydration { let this->activeRow = row; + return row; } @@ -84,6 +85,7 @@ class Complex extends Resultset implements ResultsetInterface */ if typeof row != "array" { let this->activeRow = false; + return false; } @@ -96,7 +98,6 @@ class Complex extends Resultset implements ResultsetInterface * Each row in a complex result is a Phalcon\Mvc\Model\Row instance */ switch hydrateMode { - case Resultset::HYDRATE_RECORDS: let activeRow = new Row(); break; @@ -120,14 +121,13 @@ class Complex extends Resultset implements ResultsetInterface * Create every record according to the column types */ for alias, column in this->columnTypes { - if typeof column != "array" { throw new Exception("Column type is corrupt"); } let type = column["type"]; - if type == "object" { + if type == "object" { /** * Object columns are assigned column by column */ @@ -139,8 +139,8 @@ class Complex extends Resultset implements ResultsetInterface * Assign the values from the _source_attribute notation to its real column name */ let rowModel = []; - for attribute in attributes { + for attribute in attributes { /** * Columns are supposed to be in the form _table_field */ @@ -154,7 +154,6 @@ class Complex extends Resultset implements ResultsetInterface switch hydrateMode { case Resultset::HYDRATE_RECORDS: - // Check if the resultset must keep snapshots if !fetch keepSnapshots, column["keepSnapshots"] { let keepSnapshots = false; @@ -182,6 +181,7 @@ class Complex extends Resultset implements ResultsetInterface column["instance"], rowModel, columnMap, dirtyState, keepSnapshots ); } + break; default: @@ -238,6 +238,7 @@ class Complex extends Resultset implements ResultsetInterface * Store the generated row in this_ptr->activeRow to be retrieved by 'current' */ let this->activeRow = activeRow; + return activeRow; } @@ -255,6 +256,7 @@ class Complex extends Resultset implements ResultsetInterface while this->valid() { let current = this->current(); let records[] = current; + this->next(); } @@ -267,6 +269,7 @@ class Complex extends Resultset implements ResultsetInterface public function serialize() -> string { var records, cache, columnTypes, hydrateMode, container, serializer; + /** * Obtain the records as an array */ @@ -275,26 +278,34 @@ class Complex extends Resultset implements ResultsetInterface let cache = this->cache, columnTypes = this->columnTypes, hydrateMode = this->hydrateMode; + let container = Di::getDefault(); + if typeof container != "object" { throw new Exception("The dependency injector container is not valid"); } + if container->has("serializer") { let serializer = container->getShared("serializer"); - return serializer->beforeStore([ - "cache" : cache, - "rows" : records, - "columnTypes" : columnTypes, - "hydrateMode" : hydrateMode - ]); + + return serializer->beforeStore( + [ + "cache" : cache, + "rows" : records, + "columnTypes" : columnTypes, + "hydrateMode" : hydrateMode + ] + ); } - return serialize([ - "cache" : cache, - "rows" : records, - "columnTypes" : columnTypes, - "hydrateMode" : hydrateMode - ]); + return serialize( + [ + "cache" : cache, + "rows" : records, + "columnTypes" : columnTypes, + "hydrateMode" : hydrateMode + ] + ); } /** @@ -303,20 +314,27 @@ class Complex extends Resultset implements ResultsetInterface public function unserialize(var data) -> void { var resultset, container, serializer; + /** - * Rows are already hydrated - */ + * Rows are already hydrated + */ let this->disableHydration = true; + let container = Di::getDefault(); + if typeof container != "object" { - throw new Exception("The dependency injector container is not valid"); + throw new Exception( + "The dependency injector container is not valid" + ); } + if container->has("serializer") { let serializer = container->getShared("serializer"); let resultset = serializer->afterRetrieve(data); } else { let resultset = unserialize(data); } + if typeof resultset != "array" { throw new Exception("Invalid serialization data"); } diff --git a/phalcon/Mvc/Model/Resultset/Simple.zep b/phalcon/Mvc/Model/Resultset/Simple.zep index 5faf6727cbb..5163d8a46fb 100644 --- a/phalcon/Mvc/Model/Resultset/Simple.zep +++ b/phalcon/Mvc/Model/Resultset/Simple.zep @@ -36,7 +36,7 @@ class Simple extends Resultset /** * Phalcon\Mvc\Model\Resultset\Simple constructor * - * @param array columnMap + * @param array columnMap * @param \Phalcon\Mvc\ModelInterface|Phalcon\Mvc\Model\Row model */ public function __construct(var columnMap, var model, result, cache = null, bool keepSnapshots = null) -> void @@ -60,6 +60,7 @@ class Simple extends Resultset var row, hydrateMode, columnMap, activeRow, modelName; let activeRow = this->activeRow; + if activeRow !== null { return activeRow; } @@ -74,6 +75,7 @@ class Simple extends Resultset */ if typeof row != "array" { let this->activeRow = false; + return false; } @@ -91,15 +93,12 @@ class Simple extends Resultset * Hydrate based on the current hydration */ switch hydrateMode { - case Resultset::HYDRATE_RECORDS: - /** * Set records as dirty state PERSISTENT by default * Performs the standard hydration based on objects */ if globals_get("orm.late_state_binding") { - if this->model instanceof \Phalcon\Mvc\Model { let modelName = get_class(this->model); } else { @@ -122,6 +121,7 @@ class Simple extends Resultset this->keepSnapshots ); } + break; default: @@ -138,6 +138,7 @@ class Simple extends Resultset } let this->activeRow = activeRow; + return activeRow; } @@ -149,21 +150,25 @@ class Simple extends Resultset */ public function toArray(bool renameColumns = true) -> array { - var result, records, record, renamed, renamedKey, - key, value, renamedRecords, columnMap; + var result, records, record, renamed, renamedKey, key, value, + renamedRecords, columnMap; /** * If _rows is not present, fetchAll from database * and keep them in memory for further operations */ let records = this->rows; + if typeof records != "array" { let result = this->result; + if this->row !== null { // re-execute query if required and fetchAll rows result->execute(); } + let records = result->fetchAll(); + let this->row = null; let this->rows = records; // keep result-set in memory } @@ -172,23 +177,22 @@ class Simple extends Resultset * We need to rename the whole set here, this could be slow */ if renameColumns { - /** * Get the resultset column map */ let columnMap = this->columnMap; + if typeof columnMap != "array" { return records; } let renamedRecords = []; - if typeof records == "array" { + if typeof records == "array" { for record in records { - let renamed = []; - for key, value in record { + for key, value in record { /** * Check if the key is part of the column map */ @@ -199,7 +203,6 @@ class Simple extends Resultset } if typeof renamedKey == "array" { - if !fetch renamedKey, renamedKey[0] { throw new Exception( "Column '" . key . "' is not part of the column map" @@ -229,34 +232,35 @@ class Simple extends Resultset public function serialize() -> string { var container, serializer; + array data; + let container = Di::getDefault(); + if typeof container != "object" { throw new Exception( "The dependency injector container is not valid" ); } - if container->has("serializer") { - let serializer = container->getShared("serializer"); - return serializer->beforeStore([ - "model" : this->model, - "cache" : this->cache, - "rows" : this->toArray(false), - "columnMap" : this->columnMap, - "hydrateMode" : this->hydrateMode, - "keepSnapshots" : this->keepSnapshots - ]); - } - /** - * Serialize the cache using the serialize function - */ - return serialize([ + + let data = [ "model" : this->model, "cache" : this->cache, "rows" : this->toArray(false), "columnMap" : this->columnMap, "hydrateMode" : this->hydrateMode, "keepSnapshots" : this->keepSnapshots - ]); + ]; + + if container->has("serializer") { + let serializer = container->getShared("serializer"); + + return serializer->beforeStore(data); + } + + /** + * Serialize the cache using the serialize function + */ + return serialize(data); } /** @@ -266,18 +270,22 @@ class Simple extends Resultset public function unserialize(var data) -> void { var resultset, keepSnapshots, container, serializer; + let container = Di::getDefault(); + if typeof container != "object" { throw new Exception( "The dependency injector container is not valid" ); } + if container->has("serializer") { let serializer = container->getShared("serializer"); let resultset = serializer->afterRetrieve(data); } else { let resultset = unserialize(data); } + if typeof resultset != "array" { throw new Exception("Invalid serialization data"); } diff --git a/phalcon/Mvc/Model/Row.zep b/phalcon/Mvc/Model/Row.zep index 0066928f485..bdf32d4df87 100644 --- a/phalcon/Mvc/Model/Row.zep +++ b/phalcon/Mvc/Model/Row.zep @@ -35,15 +35,18 @@ class Row implements EntityInterface, ResultInterface, \ArrayAccess, \JsonSerial * Gets a record in a specific position of the row * * @param string|int index + * * @return string|Phalcon\Mvc\ModelInterface */ public function offsetGet(var index) -> var { var value; - if fetch value, this->{index} { - return value; + + if !fetch value, this->{index} { + throw new Exception("The index does not exist in the row"); } - throw new Exception("The index does not exist in the row"); + + return value; } /** @@ -89,10 +92,12 @@ class Row implements EntityInterface, ResultInterface, \ArrayAccess, \JsonSerial public function readAttribute(string! attribute) { var value; - if fetch value, this->{attribute} { - return value; + + if !fetch value, this->{attribute} { + return null; } - return null; + + return value; } /** diff --git a/phalcon/Mvc/Model/Transaction.zep b/phalcon/Mvc/Model/Transaction.zep index d228eff43ed..a378978345d 100644 --- a/phalcon/Mvc/Model/Transaction.zep +++ b/phalcon/Mvc/Model/Transaction.zep @@ -19,9 +19,10 @@ use Phalcon\Mvc\Model\TransactionInterface; /** * Phalcon\Mvc\Model\Transaction * - * Transactions are protective blocks where SQL statements are only permanent if they can - * all succeed as one atomic action. Phalcon\Transaction is intended to be used with Phalcon_Model_Base. - * Phalcon Transactions should be created using Phalcon\Transaction\Manager. + * Transactions are protective blocks where SQL statements are only permanent if + * they can all succeed as one atomic action. Phalcon\Transaction is intended to + * be used with Phalcon_Model_Base. Phalcon Transactions should be created using + * Phalcon\Transaction\Manager. * * * use Phalcon\Mvc\Model\Transaction\Failed; @@ -91,6 +92,7 @@ class Transaction implements TransactionInterface } let this->connection = connection; + if autoBegin { connection->begin(); } @@ -112,6 +114,7 @@ class Transaction implements TransactionInterface var manager; let manager = this->manager; + if typeof manager == "object" { manager->notifyCommit(this); } @@ -129,6 +132,7 @@ class Transaction implements TransactionInterface this->rollback("The request was aborted"); } } + return this->connection; } @@ -164,18 +168,22 @@ class Transaction implements TransactionInterface var manager, connection; let manager = this->manager; + if typeof manager == "object" { manager->notifyRollback(this); } let connection = this->connection; + if connection->rollback() { if !rollbackMessage { let rollbackMessage = "Transaction aborted"; } + if typeof rollbackRecord == "object" { let this->rollbackRecord = rollbackRecord; } + throw new TxFailed(rollbackMessage, this->rollbackRecord); } diff --git a/phalcon/Mvc/Model/Transaction/Failed.zep b/phalcon/Mvc/Model/Transaction/Failed.zep index cc6c240d1d4..ab58d9a997a 100644 --- a/phalcon/Mvc/Model/Transaction/Failed.zep +++ b/phalcon/Mvc/Model/Transaction/Failed.zep @@ -29,6 +29,7 @@ class Failed extends Exception public function __construct(string! message, record = null) -> void { let this->record = record; + parent::__construct(message); } @@ -48,6 +49,7 @@ class Failed extends Exception var record; let record = this->record; + if record !== null { return record->getMessages(); } diff --git a/phalcon/Mvc/Model/Transaction/Manager.zep b/phalcon/Mvc/Model/Transaction/Manager.zep index 830a6224a44..dc25e99d258 100644 --- a/phalcon/Mvc/Model/Transaction/Manager.zep +++ b/phalcon/Mvc/Model/Transaction/Manager.zep @@ -25,8 +25,8 @@ use Phalcon\Mvc\Model\TransactionInterface; * them. * * This class manages the objects that compose a transaction. - * A transaction produces a unique connection that is passed to every - * object part of the transaction. + * A transaction produces a unique connection that is passed to every object + * part of the transaction. * * * use Phalcon\Mvc\Model\Transaction\Failed; @@ -66,7 +66,6 @@ use Phalcon\Mvc\Model\TransactionInterface; */ class Manager implements ManagerInterface, InjectionAwareInterface { - protected container; protected initialized = false; @@ -107,10 +106,12 @@ class Manager implements ManagerInterface, InjectionAwareInterface var transactions; let transactions = this->transactions; + if count(transactions) { for _ in transactions { let this->number--; } + let this->transactions = null; } } @@ -121,10 +122,13 @@ class Manager implements ManagerInterface, InjectionAwareInterface public function commit() { var transactions, transaction, connection; + let transactions = this->transactions; + if typeof transactions == "array" { for transaction in transactions { let connection = transaction->getConnection(); + if connection->isUnderTransaction() { connection->commit(); } @@ -140,10 +144,17 @@ class Manager implements ManagerInterface, InjectionAwareInterface { if !this->initialized { if this->rollbackPendent { - register_shutdown_function([this, "rollbackPendent"]); + register_shutdown_function( + [ + this, + "rollbackPendent" + ] + ); } + let this->initialized = true; } + return this->getOrCreateTransaction(autoBegin); } @@ -171,6 +182,7 @@ class Manager implements ManagerInterface, InjectionAwareInterface var container, transaction, transactions; let container = this->container; + if typeof container != "object" { throw new Exception( Exception::containerServiceNotFound( @@ -181,10 +193,12 @@ class Manager implements ManagerInterface, InjectionAwareInterface if this->number { let transactions = this->transactions; + if typeof transactions == "array" { for transaction in reverse transactions { if typeof transaction == "object" { transaction->setIsNewTransaction(false); + return transaction; } } @@ -241,13 +255,16 @@ class Manager implements ManagerInterface, InjectionAwareInterface var transactions, transaction, connection; let transactions = this->transactions; + if typeof transactions == "array" { for transaction in transactions { let connection = transaction->getConnection(); + if connection->isUnderTransaction() { connection->rollback(); connection->close(); } + if collect { this->collectTransaction(transaction); } @@ -269,6 +286,7 @@ class Manager implements ManagerInterface, InjectionAwareInterface public function setDbService(string! service) -> { let this->service = service; + return this; } @@ -287,6 +305,7 @@ class Manager implements ManagerInterface, InjectionAwareInterface public function setRollbackPendent(bool rollbackPendent) -> { let this->rollbackPendent = rollbackPendent; + return this; } @@ -298,16 +317,18 @@ class Manager implements ManagerInterface, InjectionAwareInterface var transactions, newTransactions, managedTransaction; let transactions = this->transactions; + if count(transactions) { let newTransactions = []; + for managedTransaction in transactions { if managedTransaction != transaction { let newTransactions[] = transaction; - } - else { + } else { let this->number--; } } + let this->transactions = newTransactions; } } diff --git a/phalcon/Mvc/Router.zep b/phalcon/Mvc/Router.zep index 5b0e64f79b6..c7db21b62ed 100644 --- a/phalcon/Mvc/Router.zep +++ b/phalcon/Mvc/Router.zep @@ -83,7 +83,6 @@ class Router implements InjectionAwareInterface, RouterInterface, EventsAwareInt array routes = []; if defaultRoutes { - /** * Two routes are added by default to match /:controller/:action and * /:controller/:action/:params @@ -360,6 +359,7 @@ class Router implements InjectionAwareInterface, RouterInterface, EventsAwareInt return route; } } + return false; } @@ -376,6 +376,7 @@ class Router implements InjectionAwareInterface, RouterInterface, EventsAwareInt for key, route in this->routes { let routeName = route->getName(); + if !empty routeName { let this->keyRouteNames[routeName] = key; @@ -384,6 +385,7 @@ class Router implements InjectionAwareInterface, RouterInterface, EventsAwareInt } } } + return false; } @@ -446,14 +448,14 @@ class Router implements InjectionAwareInterface, RouterInterface, EventsAwareInt * Look for HTTP method constraints */ let methods = route->getHttpMethods(); - if methods !== null { + if methods !== null { /** * Retrieve the request service from the container */ if request === null { - let container = this->container; + if typeof container != "object" { throw new Exception( Exception::containerServiceNotFound( @@ -477,14 +479,14 @@ class Router implements InjectionAwareInterface, RouterInterface, EventsAwareInt * Look for hostname constraints */ let hostname = route->getHostName(); - if hostname !== null { + if hostname !== null { /** * Retrieve the request service from the container */ if request === null { - let container = this->container; + if typeof container != "object" { throw new Exception( Exception::containerServiceNotFound( @@ -517,13 +519,16 @@ class Router implements InjectionAwareInterface, RouterInterface, EventsAwareInt if memstr(hostname, "(") { if !memstr(hostname, "#") { let regexHostName = "#^" . hostname; + if !memstr(hostname, ":") { let regexHostName .= "(:[[:digit:]]+)?"; } + let regexHostName .= "$#i"; } else { let regexHostName = hostname; } + let matched = preg_match(regexHostName, currentHostName); } else { let matched = currentHostName == hostname; @@ -553,14 +558,13 @@ class Router implements InjectionAwareInterface, RouterInterface, EventsAwareInt * Check for beforeMatch conditions */ if routeFound { - if typeof eventsManager == "object" { eventsManager->fire("router:matchedRoute", this, route); } let beforeMatch = route->getBeforeMatch(); - if beforeMatch !== null { + if beforeMatch !== null { /** * Check first if the callback is callable */ @@ -590,7 +594,6 @@ class Router implements InjectionAwareInterface, RouterInterface, EventsAwareInt } if routeFound { - /** * Start from the default paths */ @@ -601,14 +604,12 @@ class Router implements InjectionAwareInterface, RouterInterface, EventsAwareInt * Check if the matches has variables */ if typeof matches == "array" { - /** * Get the route converters if any */ let converters = route->getConverters(); for part, position in paths { - if typeof part != "string" { throw new Exception("Wrong key in paths: " . part); } @@ -618,7 +619,6 @@ class Router implements InjectionAwareInterface, RouterInterface, EventsAwareInt } if fetch matchPosition, matches[position] { - /** * Check if the part has a converter */ @@ -638,7 +638,6 @@ class Router implements InjectionAwareInterface, RouterInterface, EventsAwareInt */ let parts[part] = matchPosition; } else { - /** * Apply the converters anyway */ @@ -650,7 +649,6 @@ class Router implements InjectionAwareInterface, RouterInterface, EventsAwareInt ); } } else { - /** * Remove the path if the parameter was not * matched @@ -669,6 +667,7 @@ class Router implements InjectionAwareInterface, RouterInterface, EventsAwareInt } let this->matchedRoute = route; + break; } } @@ -687,6 +686,7 @@ class Router implements InjectionAwareInterface, RouterInterface, EventsAwareInt */ if !routeFound { let notFoundPaths = this->notFoundPaths; + if notFoundPaths !== null { let parts = Route::getRoutePaths(notFoundPaths), routeFound = true; @@ -703,7 +703,6 @@ class Router implements InjectionAwareInterface, RouterInterface, EventsAwareInt this->params = this->defaultParams; if routeFound { - /** * Check for a namespace */ @@ -711,6 +710,7 @@ class Router implements InjectionAwareInterface, RouterInterface, EventsAwareInt if !is_numeric(vnamespace) { let this->namespaceName = vnamespace; } + unset parts["namespace"]; } @@ -721,6 +721,7 @@ class Router implements InjectionAwareInterface, RouterInterface, EventsAwareInt if !is_numeric(module) { let this->module = module; } + unset parts["module"]; } @@ -731,6 +732,7 @@ class Router implements InjectionAwareInterface, RouterInterface, EventsAwareInt if !is_numeric(controller) { let this->controller = controller; } + unset parts["controller"]; } @@ -741,6 +743,7 @@ class Router implements InjectionAwareInterface, RouterInterface, EventsAwareInt if !is_numeric(action) { let this->action = action; } + unset parts["action"]; } @@ -750,6 +753,7 @@ class Router implements InjectionAwareInterface, RouterInterface, EventsAwareInt if fetch paramsStr, parts["params"] { if typeof paramsStr == "string" { let strParams = trim(paramsStr, "/"); + if strParams !== "" { let params = explode("/", strParams); } @@ -777,6 +781,7 @@ class Router implements InjectionAwareInterface, RouterInterface, EventsAwareInt { return true; } + /** * Mounts a group of routes in the router */ @@ -791,6 +796,7 @@ class Router implements InjectionAwareInterface, RouterInterface, EventsAwareInt } let groupRoutes = group->getRoutes(); + if !count(groupRoutes) { throw new Exception( "The group of routes does not contain any routes" @@ -819,11 +825,7 @@ class Router implements InjectionAwareInterface, RouterInterface, EventsAwareInt let routes = this->routes; - if typeof routes == "array" { - let this->routes = array_merge(routes, groupRoutes); - } else { - let this->routes = groupRoutes; - } + let this->routes = array_merge(routes, groupRoutes); return this; } @@ -839,7 +841,9 @@ class Router implements InjectionAwareInterface, RouterInterface, EventsAwareInt "The not-found paths must be an array or string" ); } + let this->notFoundPaths = paths; + return this; } @@ -849,6 +853,7 @@ class Router implements InjectionAwareInterface, RouterInterface, EventsAwareInt public function removeExtraSlashes(bool! remove) -> { let this->removeExtraSlashes = remove; + return this; } @@ -858,6 +863,7 @@ class Router implements InjectionAwareInterface, RouterInterface, EventsAwareInt public function setDefaultAction(string! actionName) -> { let this->defaultAction = actionName; + return this; } @@ -867,6 +873,7 @@ class Router implements InjectionAwareInterface, RouterInterface, EventsAwareInt public function setDefaultController(string! controllerName) -> { let this->defaultController = controllerName; + return this; } @@ -876,6 +883,7 @@ class Router implements InjectionAwareInterface, RouterInterface, EventsAwareInt public function setDefaultModule(string! moduleName) -> { let this->defaultModule = moduleName; + return this; } @@ -885,6 +893,7 @@ class Router implements InjectionAwareInterface, RouterInterface, EventsAwareInt public function setDefaultNamespace(string! namespaceName) -> { let this->defaultNamespace = namespaceName; + return this; } diff --git a/phalcon/Mvc/Router/Annotations.zep b/phalcon/Mvc/Router/Annotations.zep index 4645d836baf..04a01a643cf 100644 --- a/phalcon/Mvc/Router/Annotations.zep +++ b/phalcon/Mvc/Router/Annotations.zep @@ -90,6 +90,7 @@ class Annotations extends Router method, collection; let container = this->container; + if typeof container != "object" { throw new Exception( Exception::containerServiceNotFound("the 'annotations' service") @@ -103,7 +104,6 @@ class Annotations extends Router let controllerSuffix = this->controllerSuffix; for scope in handlers { - if typeof scope != "array" { continue; } @@ -123,7 +123,6 @@ class Annotations extends Router let handler = scope[1]; if memstr(handler, "\\") { - /** * Extract the real class name from the namespaced class * The lowercased class name is used as controller @@ -133,6 +132,7 @@ class Annotations extends Router namespaceName = get_ns_class(handler); } else { let controllerName = handler; + fetch namespaceName, this->defaultNamespace; } @@ -165,8 +165,10 @@ class Annotations extends Router * Process class annotations */ let classAnnotations = handlerAnnotations->getClassAnnotations(); + if typeof classAnnotations == "object" { let annotations = classAnnotations->getAnnotations(); + if typeof annotations == "array" { for annotation in annotations { this->processControllerAnnotation( @@ -181,6 +183,7 @@ class Annotations extends Router * Process method annotations */ let methodAnnotations = handlerAnnotations->getMethodsAnnotations(); + if typeof methodAnnotations == "array" { let lowerControllerName = uncamelize(controllerName); @@ -212,9 +215,8 @@ class Annotations extends Router public function processActionAnnotation(string! module, string! namespaceName, string! controller, string! action, annotation) { - var name, actionName, routePrefix, paths, value, uri, - route, methods, converts, param, convert, conversorParam, routeName, - beforeMatch; + var name, actionName, routePrefix, paths, value, uri, route, methods, + converts, param, convert, conversorParam, routeName, beforeMatch; bool isRoute; let isRoute = false, @@ -225,7 +227,6 @@ class Annotations extends Router * Find if the route is for adding routes */ switch name { - case "Route": let isRoute = true; break; @@ -256,7 +257,6 @@ class Annotations extends Router } if isRoute { - let actionName = strtolower(str_replace(this->actionSuffix, "", action)), routePrefix = this->routePrefix; @@ -264,6 +264,7 @@ class Annotations extends Router * Check for existing paths in the annotation */ let paths = annotation->getNamedArgument("paths"); + if typeof paths != "array" { let paths = []; } @@ -316,6 +317,7 @@ class Annotations extends Router route->via(methods); } else { let methods = annotation->getNamedArgument("methods"); + if typeof methods == "array" || typeof methods == "string" { route->via(methods); } @@ -325,6 +327,7 @@ class Annotations extends Router * Add the converters */ let converts = annotation->getNamedArgument("converts"); + if typeof converts == "array" { for param, convert in converts { route->convert(param, convert); @@ -335,6 +338,7 @@ class Annotations extends Router * Add the conversors */ let converts = annotation->getNamedArgument("conversors"); + if typeof converts == "array" { for conversorParam, convert in converts { route->convert(conversorParam, convert); @@ -345,11 +349,13 @@ class Annotations extends Router * Add the conversors */ let beforeMatch = annotation->getNamedArgument("beforeMatch"); + if typeof beforeMatch == "array" || typeof beforeMatch == "string" { route->beforeMatch(beforeMatch); } let routeName = annotation->getNamedArgument("name"); + if typeof routeName == "string" { route->setName(routeName); } diff --git a/phalcon/Mvc/Router/Group.zep b/phalcon/Mvc/Router/Group.zep index ba0ded8193c..ce213798acd 100644 --- a/phalcon/Mvc/Router/Group.zep +++ b/phalcon/Mvc/Router/Group.zep @@ -200,6 +200,7 @@ class Group implements GroupInterface public function beforeMatch(callable beforeMatch) -> { let this->beforeMatch = beforeMatch; + return this; } @@ -257,6 +258,7 @@ class Group implements GroupInterface public function setHostname(string hostname) -> { let this->hostname = hostname; + return this; } @@ -266,6 +268,7 @@ class Group implements GroupInterface public function setPaths(var paths) -> { let this->paths = paths; + return this; } @@ -275,6 +278,7 @@ class Group implements GroupInterface public function setPrefix(string prefix) -> { let this->prefix = prefix; + return this; } @@ -291,7 +295,6 @@ class Group implements GroupInterface let defaultPaths = this->paths; if typeof defaultPaths == "array" { - if typeof paths == "string" { let processedPaths = Route::getRoutePaths(paths); } else { @@ -317,6 +320,7 @@ class Group implements GroupInterface this->routes[] = route; route->setGroup(this); + return route; } } diff --git a/phalcon/Mvc/Router/GroupInterface.zep b/phalcon/Mvc/Router/GroupInterface.zep index 960e9f83fe0..5a605453810 100644 --- a/phalcon/Mvc/Router/GroupInterface.zep +++ b/phalcon/Mvc/Router/GroupInterface.zep @@ -15,7 +15,6 @@ use Phalcon\Mvc\Router\RouteInterface; /** * Phalcon\Mvc\Router\GroupInterface * - * * * $router = new \Phalcon\Mvc\Router(); * @@ -157,7 +156,6 @@ interface GroupInterface */ public function getRoutes() -> ; - /** * Set a hostname restriction for all the routes in the group */ diff --git a/phalcon/Mvc/Router/Route.zep b/phalcon/Mvc/Router/Route.zep index 9b2eb9b4bd0..42d517e501d 100644 --- a/phalcon/Mvc/Router/Route.zep +++ b/phalcon/Mvc/Router/Route.zep @@ -47,6 +47,7 @@ class Route implements RouteInterface // Get the unique Id from the static member _uniqueId let uniqueId = self::uniqueId; + if uniqueId === null { let uniqueId = 0; } @@ -84,6 +85,7 @@ class Route implements RouteInterface public function beforeMatch(var callback) -> { let this->beforeMatch = callback; + return this; } @@ -96,7 +98,6 @@ class Route implements RouteInterface // If a pattern contains ':', maybe there are placeholders to replace if memstr(pattern, ":") { - // This is a pattern for valid identifiers let idPattern = "/([\\w0-9\\_\\-]+)"; @@ -171,10 +172,9 @@ class Route implements RouteInterface } let matches = [], - route = ""; + route = ""; for cursor, ch in pattern { - if parenthesesCount == 0 { if ch == '{' { if bracketCount == 0 { @@ -182,26 +182,27 @@ class Route implements RouteInterface intermediate = 0, notValid = false; } + let bracketCount++; } else { if ch == '}' { let bracketCount--; + if intermediate > 0 { if bracketCount == 0 { - let numberMatches++, variable = null, regexp = null, item = (string) substr(pattern, marker, cursor - marker); for cursorVar, ch in item { - if ch == '\0' { break; } if cursorVar == 0 && !((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) { let notValid = true; + break; } @@ -209,26 +210,27 @@ class Route implements RouteInterface if ch == ':' { let variable = (string) substr(item, 0, cursorVar), regexp = (string) substr(item, cursorVar + 1); + break; } } else { let notValid = true; + break; } - } if !notValid { - let tmp = numberMatches; if variable && regexp { - let foundPattern = 0; + for ch in regexp { if ch == '\0' { break; } + if !foundPattern { if ch == '(' { let foundPattern = 1; @@ -236,6 +238,7 @@ class Route implements RouteInterface } else { if ch == ')' { let foundPattern = 2; + break; } } @@ -246,6 +249,7 @@ class Route implements RouteInterface } else { let route .= regexp; } + let matches[variable] = tmp; } else { let route .= "([^/]*)", @@ -254,6 +258,7 @@ class Route implements RouteInterface } else { let route .= "{" . item . "}"; } + continue; } } @@ -267,6 +272,7 @@ class Route implements RouteInterface } else { if ch == ')' { let parenthesesCount--; + if parenthesesCount == 0 { let numberMatches++; } @@ -282,6 +288,7 @@ class Route implements RouteInterface let route .= '\\'; } } + let route .= ch, prevCh = ch; } @@ -378,9 +385,11 @@ class Route implements RouteInterface var reversed, path, position; let reversed = []; + for path, position in this->paths { let reversed[position] = path; } + return reversed; } @@ -397,13 +406,11 @@ class Route implements RouteInterface */ public static function getRoutePaths(var paths = null) -> array { - var moduleName, controllerName, actionName, - parts, routePaths, realClassName, - namespaceName; + var moduleName, controllerName, actionName, parts, routePaths, + realClassName, namespaceName; if paths !== null { if typeof paths == "string" { - let moduleName = null, controllerName = null, actionName = null; @@ -439,10 +446,8 @@ class Route implements RouteInterface // Process controller name if controllerName !== null { - // Check if we need to obtain the namespace if memstr(controllerName, "\\") { - // Extract the real class name from the namespaced class let realClassName = get_class_ns(controllerName); @@ -496,6 +501,7 @@ class Route implements RouteInterface public function match(var callback) -> { let this->match = callback; + return this; } @@ -504,8 +510,7 @@ class Route implements RouteInterface */ public function reConfigure(string! pattern, var paths = null) -> void { - var routePaths, pcrePattern, compiledPattern, - extracted; + var routePaths, pcrePattern, compiledPattern, extracted; let routePaths = self::getRoutePaths(paths); @@ -513,7 +518,6 @@ class Route implements RouteInterface * If the route starts with '#' we assume that it is a regular expression */ if !starts_with(pattern, "#") { - if memstr(pattern, "{") { /** * The route has named parameters so we need to extract them @@ -563,6 +567,7 @@ class Route implements RouteInterface public function setGroup( group) -> { let this->group = group; + return this; } @@ -571,12 +576,19 @@ class Route implements RouteInterface * * * $route->setHttpMethods("GET"); - * $route->setHttpMethods(["GET", "POST"]); + * + * $route->setHttpMethods( + * [ + * "GET", + * "POST", + * ] + * ); * */ public function setHttpMethods(var httpMethods) -> { let this->methods = httpMethods; + return this; } @@ -590,6 +602,7 @@ class Route implements RouteInterface public function setHostname(string! hostname) -> { let this->hostname = hostname; + return this; } @@ -608,6 +621,7 @@ class Route implements RouteInterface public function setName(string name) -> { let this->name = name; + return this; } @@ -628,6 +642,7 @@ class Route implements RouteInterface public function via(var httpMethods) -> { let this->methods = httpMethods; + return this; } } diff --git a/phalcon/Mvc/View.zep b/phalcon/Mvc/View.zep index 3e8851937d6..0722ff729a2 100644 --- a/phalcon/Mvc/View.zep +++ b/phalcon/Mvc/View.zep @@ -172,8 +172,8 @@ class View extends Injectable implements ViewInterface var viewOptions, cacheOptions, key, value, cacheLevel; if typeof options == "array" { - let viewOptions = this->options; + if typeof viewOptions != "array" { let viewOptions = []; } @@ -202,7 +202,6 @@ class View extends Injectable implements ViewInterface let viewOptions["cache"] = cacheOptions; let this->options = viewOptions; } else { - /** * If 'options' isn't an array we enable the cache with default * options @@ -223,6 +222,7 @@ class View extends Injectable implements ViewInterface public function cleanTemplateAfter() -> { let this->templatesAfter = []; + return this; } @@ -232,6 +232,7 @@ class View extends Injectable implements ViewInterface public function cleanTemplateBefore() -> { let this->templatesBefore = []; + return this; } @@ -252,6 +253,7 @@ class View extends Injectable implements ViewInterface } else { let this->disabledLevels[level] = true; } + return this; } @@ -261,6 +263,7 @@ class View extends Injectable implements ViewInterface public function disable() -> { let this->disabled = true; + return this; } @@ -270,6 +273,7 @@ class View extends Injectable implements ViewInterface public function enable() -> { let this->disabled = false; + return this; } @@ -308,6 +312,7 @@ class View extends Injectable implements ViewInterface public function finish() -> { ob_end_clean(); + return this; } @@ -331,10 +336,8 @@ class View extends Injectable implements ViewInterface activeRenderPath = this->activeRenderPaths; if viewsDirsCount === 1 { - if typeof activeRenderPath == "array" { - if count(activeRenderPath) { - let activeRenderPath = activeRenderPath[0]; - } + if typeof activeRenderPath == "array" && count(activeRenderPath) { + let activeRenderPath = activeRenderPath[0]; } } @@ -436,7 +439,9 @@ class View extends Injectable implements ViewInterface // not liking the ob_* functions here, but it will greatly reduce the // amount of double code. ob_start(); + this->partial(partialPath, params); + return ob_get_clean(); } @@ -589,7 +594,6 @@ class View extends Injectable implements ViewInterface * symbol table */ if typeof params == "array" { - /** * Merge the new params as parameters */ @@ -652,19 +656,22 @@ class View extends Injectable implements ViewInterface if typeof renderView == "array" { let pickView = renderView; } else { - let layout = null; + if memstr(renderView, "/") { - let parts = explode("/", renderView), layout = parts[0]; + let parts = explode("/", renderView), + layout = parts[0]; } let pickView = [renderView]; + if layout !== null { let pickView[] = layout; } } let this->pickView = pickView; + return this; } @@ -674,9 +681,9 @@ class View extends Injectable implements ViewInterface * * $this->view->registerEngines( * [ - * ".phtml" => "Phalcon\\Mvc\\View\\Engine\\Php", - * ".volt" => "Phalcon\\Mvc\\View\\Engine\\Volt", - * ".mhtml" => "MyCustomEngine", + * ".phtml" => \Phalcon\Mvc\View\Engine\Php::class, + * ".volt" => \Phalcon\Mvc\View\Engine\Volt::class, + * ".mhtml" => \MyCustomEngine::class, * ] * ); * @@ -684,6 +691,7 @@ class View extends Injectable implements ViewInterface public function registerEngines(array! engines) -> { let this->registeredEngines = engines; + return this; } @@ -699,10 +707,9 @@ class View extends Injectable implements ViewInterface { bool silence, mustClean; int renderLevel; - var layoutsDir, layout, pickView, layoutName, - engines, renderView, pickViewAction, eventsManager, - disabledLevels, templatesBefore, templatesAfter, - templateBefore, templateAfter, cache; + var layoutsDir, layout, pickView, layoutName, engines, renderView, + pickViewAction, eventsManager, disabledLevels, templatesBefore, + templatesAfter, templateBefore, templateAfter, cache; let this->currentRenderLevel = 0; @@ -712,6 +719,7 @@ class View extends Injectable implements ViewInterface */ if this->disabled !== false { let this->content = ob_get_contents(); + return false; } @@ -726,6 +734,7 @@ class View extends Injectable implements ViewInterface * Check if there is a layouts directory set */ let layoutsDir = this->layoutsDir; + if !layoutsDir { let layoutsDir = "layouts/"; } @@ -734,6 +743,7 @@ class View extends Injectable implements ViewInterface * Check if the user has defined a custom layout */ let layout = this->layout; + if layout { let layoutName = layout; } else { @@ -753,12 +763,12 @@ class View extends Injectable implements ViewInterface if pickView === null { let renderView = controllerName . "/" . actionName; } else { - /** * The 'picked' view is an array, where the first element is * controller and the second the action */ let renderView = pickView[0]; + if layoutName === null { if fetch pickViewAction, pickView[1] { let layoutName = pickViewAction; @@ -810,8 +820,8 @@ class View extends Injectable implements ViewInterface * Render level will tell use when to stop */ let renderLevel = (int) this->renderLevel; - if renderLevel { + if renderLevel { /** * Inserts view related to action */ @@ -839,6 +849,7 @@ class View extends Injectable implements ViewInterface let templatesBefore = this->templatesBefore; let silence = false; + for templateBefore in templatesBefore { this->engineRender( engines, @@ -848,6 +859,7 @@ class View extends Injectable implements ViewInterface cache ); } + let silence = true; } } @@ -858,6 +870,7 @@ class View extends Injectable implements ViewInterface if renderLevel >= self::LEVEL_LAYOUT { if !isset disabledLevels[self::LEVEL_LAYOUT] { let this->currentRenderLevel = self::LEVEL_LAYOUT; + this->engineRender( engines, layoutsDir . layoutName, @@ -878,6 +891,7 @@ class View extends Injectable implements ViewInterface let templatesAfter = this->templatesAfter; let silence = false; + for templateAfter in templatesAfter { this->engineRender( engines, @@ -887,6 +901,7 @@ class View extends Injectable implements ViewInterface cache ); } + let silence = true; } } @@ -945,6 +960,7 @@ class View extends Injectable implements ViewInterface this->content = null, this->templatesBefore = [], this->templatesAfter = []; + return this; } @@ -953,12 +969,13 @@ class View extends Injectable implements ViewInterface * or backslash * * - * $view->setBasePath(__DIR__ . "/"); + * $view->setBasePath(__DIR__ . "/"); * */ public function setBasePath(string basePath) -> { let this->basePath = basePath; + return this; } @@ -972,6 +989,7 @@ class View extends Injectable implements ViewInterface public function setContent(string content) -> { let this->content = content; + return this; } @@ -986,6 +1004,7 @@ class View extends Injectable implements ViewInterface public function setLayout(string layout) -> { let this->layout = layout; + return this; } @@ -1001,6 +1020,7 @@ class View extends Injectable implements ViewInterface public function setLayoutsDir(string layoutsDir) -> { let this->layoutsDir = layoutsDir; + return this; } @@ -1016,6 +1036,7 @@ class View extends Injectable implements ViewInterface public function setMainView(string viewPath) -> { let this->mainView = viewPath; + return this; } @@ -1031,6 +1052,7 @@ class View extends Injectable implements ViewInterface public function setPartialsDir(string partialsDir) -> { let this->partialsDir = partialsDir; + return this; } @@ -1044,6 +1066,7 @@ class View extends Injectable implements ViewInterface public function setParamToView(string! key, var value) -> { let this->viewParams[key] = value; + return this; } @@ -1060,6 +1083,7 @@ class View extends Injectable implements ViewInterface public function setRenderLevel(int level) -> { let this->renderLevel = level; + return this; } @@ -1073,6 +1097,7 @@ class View extends Injectable implements ViewInterface } else { let this->templatesAfter = templateAfter; } + return this; } @@ -1086,6 +1111,7 @@ class View extends Injectable implements ViewInterface } else { let this->templatesBefore = templateBefore; } + return this; } @@ -1099,6 +1125,7 @@ class View extends Injectable implements ViewInterface public function setVar(string! key, var value) -> { let this->viewParams[key] = value; + return this; } @@ -1137,18 +1164,17 @@ class View extends Injectable implements ViewInterface } let directorySeparator = DIRECTORY_SEPARATOR; - if typeof viewsDir == "string" { + if typeof viewsDir == "string" { if substr(viewsDir, -1) != directorySeparator { let viewsDir = viewsDir . directorySeparator; } let this->viewsDirs = viewsDir; } else { - let newViewsDir = []; - for position, directory in viewsDir { + for position, directory in viewsDir { if typeof directory != "string" { throw new Exception( "Views directory item must be a string" @@ -1174,7 +1200,9 @@ class View extends Injectable implements ViewInterface public function start() -> { ob_start(); + let this->content = null; + return this; } @@ -1183,10 +1211,10 @@ class View extends Injectable implements ViewInterface */ protected function createCache() -> { - var container, cacheService, viewCache, - viewOptions, cacheOptions; + var container, cacheService, viewCache, viewOptions, cacheOptions; let container = this->container; + if typeof container != "object" { throw new Exception( Exception::containerServiceNotFound("the view cache services") @@ -1207,6 +1235,7 @@ class View extends Injectable implements ViewInterface * The injected service must be an object */ let viewCache = container->getShared(cacheService); + if typeof viewCache != "object" { throw new Exception("The injected caching service is invalid"); } @@ -1221,9 +1250,9 @@ class View extends Injectable implements ViewInterface { bool notExists; int renderLevel, cacheLevel; - var key, lifetime, viewsDir, basePath, viewsDirPath, - viewOptions, cacheOptions, cachedView, viewParams, eventsManager, - extension, engine, viewEnginePath, viewEnginePaths; + var key, lifetime, viewsDir, basePath, viewsDirPath, viewOptions, + cacheOptions, cachedView, viewParams, eventsManager, extension, + engine, viewEnginePath, viewEnginePaths; let notExists = true, basePath = this->basePath, @@ -1232,7 +1261,6 @@ class View extends Injectable implements ViewInterface viewEnginePaths = []; for viewsDir in this->getViewsDirs() { - if !this->isAbsolutePath(viewPath) { let viewsDirPath = basePath . viewsDir . viewPath; } else { @@ -1240,18 +1268,15 @@ class View extends Injectable implements ViewInterface } if typeof cache == "object" { - let renderLevel = (int) this->renderLevel, cacheLevel = (int) this->cacheLevel; if renderLevel >= cacheLevel { - /** * Check if the cache is started, the first time a cache is * started we start the cache */ if !cache->isStarted() { - let key = null, lifetime = null; @@ -1279,6 +1304,7 @@ class View extends Injectable implements ViewInterface * We start the cache using the key set */ let cachedView = cache->start(key, lifetime); + if cachedView !== null { let this->content = cachedView; return null; @@ -1299,16 +1325,16 @@ class View extends Injectable implements ViewInterface * Views are rendered in each engine */ for extension, engine in engines { - let viewEnginePath = viewsDirPath . extension; - if file_exists(viewEnginePath) { + if file_exists(viewEnginePath) { /** * Call beforeRenderView if there is an events manager * available */ if typeof eventsManager == "object" { let this->activeRenderPaths = [viewEnginePath]; + if eventsManager->fire("view:beforeRenderView", this, viewEnginePath) === false { continue; } @@ -1321,6 +1347,7 @@ class View extends Injectable implements ViewInterface * available */ let notExists = false; + if typeof eventsManager == "object" { eventsManager->fire("view:afterRenderView", this); } @@ -1337,6 +1364,7 @@ class View extends Injectable implements ViewInterface */ if typeof eventsManager == "object" { let this->activeRenderPaths = viewEnginePaths; + eventsManager->fire("view:notFoundView", this, viewEnginePath); } @@ -1373,19 +1401,17 @@ class View extends Injectable implements ViewInterface * If the engines aren't initialized 'engines' is false */ if engines === false { - let di = this->container; let engines = []; let registeredEngines = this->registeredEngines; - if empty registeredEngines { + if empty registeredEngines { /** * We use Phalcon\Mvc\View\Engine\Php as default */ let engines[".phtml"] = new PhpEngine(this, di); } else { - if typeof di != "object" { throw new Exception( Exception::containerServiceNotFound( @@ -1395,9 +1421,7 @@ class View extends Injectable implements ViewInterface } for extension, engineService in registeredEngines { - if typeof engineService == "object" { - /** * Engine can be a closure */ @@ -1414,9 +1438,7 @@ class View extends Injectable implements ViewInterface } else { let engines[extension] = engineService; } - } else { - /** * Engine can be a string representing a service in the DI */ diff --git a/phalcon/Mvc/View/Engine/Volt.zep b/phalcon/Mvc/View/Engine/Volt.zep index 1f696ec629a..c44c20efe90 100644 --- a/phalcon/Mvc/View/Engine/Volt.zep +++ b/phalcon/Mvc/View/Engine/Volt.zep @@ -76,7 +76,9 @@ class Volt extends Engine /** * There are no enough extensions available */ - throw new Exception("Any of 'mbstring' or 'iconv' is required to perform the charset conversion"); + throw new Exception( + "Any of 'mbstring' or 'iconv' is required to perform the charset conversion" + ); } /** @@ -87,14 +89,15 @@ class Volt extends Engine var compiler, container, options; let compiler = this->compiler; - if typeof compiler != "object" { + if typeof compiler != "object" { let compiler = new Compiler(this->view); /** * Pass the IoC to the compiler only of it's an object */ let container = this->container; + if typeof container == "object" { compiler->setDi(container); } @@ -103,12 +106,14 @@ class Volt extends Engine * Pass the options to the compiler only if they're an array */ let options = this->options; + if typeof options == "array" { compiler->setOptions(options); } let this->compiler = compiler; } + return compiler; } @@ -225,7 +230,6 @@ class Volt extends Engine * Objects must implement a Traversable interface */ if typeof value == "object" { - if end === null { let end = count(value) - 1; } @@ -240,6 +244,7 @@ class Volt extends Engine } value->next(); + let position++; } @@ -289,6 +294,7 @@ class Volt extends Engine public function sort(array value) -> array { asort(value); + return value; } } diff --git a/phalcon/Mvc/View/Engine/Volt/Compiler.zep b/phalcon/Mvc/View/Engine/Volt/Compiler.zep index b3040611045..359703e5a29 100644 --- a/phalcon/Mvc/View/Engine/Volt/Compiler.zep +++ b/phalcon/Mvc/View/Engine/Volt/Compiler.zep @@ -52,7 +52,6 @@ class Compiler implements InjectionAwareInterface protected prefix; protected view; - /** * Phalcon\Mvc\View\Engine\Volt\Compiler */ @@ -80,6 +79,7 @@ class Compiler implements InjectionAwareInterface } let this->extensions[] = extension; + return this; } @@ -89,6 +89,7 @@ class Compiler implements InjectionAwareInterface public function addFilter(string! name, var definition) -> { let this->filters[name] = definition; + return this; } @@ -98,6 +99,7 @@ class Compiler implements InjectionAwareInterface public function addFunction(string! name, var definition) -> { let this->functions[name] = definition; + return this; } @@ -113,7 +115,6 @@ class Compiler implements InjectionAwareInterface let left = expr["left"]; if left["type"] == PHVOLT_T_IDENTIFIER { - let variable = left["value"]; /** @@ -124,7 +125,6 @@ class Compiler implements InjectionAwareInterface exprCode .= "$" . this->getUniquePrefix() . level . "loop", this->loopPointers[level] = level; } else { - /** * Services registered in the dependency injector container are * available always @@ -135,9 +135,9 @@ class Compiler implements InjectionAwareInterface let exprCode .= "$" . variable; } } - } else { let leftCode = this->expression(left), leftType = left["type"]; + if leftType != PHVOLT_T_DOT && leftType != PHVOLT_T_FCALL { let exprCode .= leftCode; } else { @@ -195,8 +195,8 @@ class Compiler implements InjectionAwareInterface let compilation = null; let options = this->options; - if typeof options == "array" { + if typeof options == "array" { /** * This makes that templates will be compiled always */ @@ -226,6 +226,7 @@ class Compiler implements InjectionAwareInterface */ if isset options["prefix"] { let prefix = options["prefix"]; + if typeof prefix != "string" { throw new Exception("'prefix' must be a string"); } @@ -246,7 +247,9 @@ class Compiler implements InjectionAwareInterface E_USER_DEPRECATED ); } + let compiledPath = options[optionKey]; + if typeof compiledPath != "string" { if typeof compiledPath != "object" { throw new Exception( @@ -270,7 +273,9 @@ class Compiler implements InjectionAwareInterface E_USER_DEPRECATED ); } + let compiledSeparator = options[optionKey]; + if typeof compiledSeparator != "string" { throw new Exception("'" . optionKey . "' must be a string"); } @@ -290,7 +295,9 @@ class Compiler implements InjectionAwareInterface E_USER_DEPRECATED ); } + let compiledExtension = options[optionKey]; + if typeof compiledExtension != "string" { throw new Exception("'" . optionKey . "' must be a string"); } @@ -308,7 +315,6 @@ class Compiler implements InjectionAwareInterface * Check if there is a compiled path */ if typeof compiledPath == "string" { - /** * Calculate the template realpath's */ @@ -333,16 +339,12 @@ class Compiler implements InjectionAwareInterface } else { let compiledTemplatePath = compiledPath . prefix . templateSepPath . compiledExtension; } - } else { - /** * A closure can dynamically compile the path */ if typeof compiledPath == "object" { - if compiledPath instanceof \Closure { - let compiledTemplatePath = call_user_func_array( compiledPath, [templatePath, options, extendsMode] @@ -474,9 +476,12 @@ class Compiler implements InjectionAwareInterface * Cache statement */ let exprCode = this->expression(expr); + let compilation = "expression(expr) . "] = $this->di->get('viewCache'); "; + if fetch lifetime, statement["lifetime"] { let compilation .= "$_cacheKey[" . exprCode . "]"; + if lifetime["type"] == PHVOLT_T_IDENTIFIER { let compilation .= " = $_cache[" . exprCode . "]->start(" . exprCode . ", $" . lifetime["value"] . "); "; } else { @@ -485,6 +490,7 @@ class Compiler implements InjectionAwareInterface } else { let compilation .= "$_cacheKey[" . exprCode . "] = $_cache[" . exprCode."]->start(" . exprCode . "); "; } + let compilation .= "if ($_cacheKey[" . exprCode . "] === null) { ?>"; /** @@ -504,6 +510,7 @@ class Compiler implements InjectionAwareInterface } else { let compilation .= "save(" . exprCode . ", null, " . lifetime["value"] . "); "; } + let compilation .= "} else { echo $_cacheKey[" . exprCode . "]; } ?>"; } else { let compilation .= "save(" . exprCode . "); } else { echo $_cacheKey[" . exprCode . "]; } ?>"; @@ -587,11 +594,9 @@ class Compiler implements InjectionAwareInterface let exprCode = this->expression(expr); if expr["type"] == PHVOLT_T_FCALL { - let name = expr["name"]; if name["type"] == PHVOLT_T_IDENTIFIER { - /** * super() is a function however the return of this function * must be output as it is @@ -666,6 +671,7 @@ class Compiler implements InjectionAwareInterface * respect the open_basedir directive */ let viewCode = file_get_contents(path); + if viewCode === false { throw new Exception( "Template file " . path . " could not be opened" @@ -673,6 +679,7 @@ class Compiler implements InjectionAwareInterface } let this->currentPath = path; + let compilation = this->compileSource(viewCode, extendsMode); /** @@ -700,9 +707,9 @@ class Compiler implements InjectionAwareInterface */ public function compileForeach(array! statement, bool extendsMode = false) -> string { - var compilation, prefix, level, prefixLevel, expr, - exprCode, bstatement, type, blockStatements, forElse, code, - loopContext, iterator, key, ifExpr, variable; + var compilation, prefix, level, prefixLevel, expr, exprCode, bstatement, + type, blockStatements, forElse, code, loopContext, iterator, key, + ifExpr, variable; /** * A valid expression is required @@ -711,11 +718,13 @@ class Compiler implements InjectionAwareInterface throw new Exception("Corrupted statement"); } - let compilation = "", forElse = null; + let compilation = "", + forElse = null; let this->foreachLevel++; let prefix = this->getUniquePrefix(); + let level = this->foreachLevel; /** @@ -727,6 +736,7 @@ class Compiler implements InjectionAwareInterface * Evaluate common expressions */ let expr = statement["expr"]; + let exprCode = this->expression(expr); /** @@ -735,10 +745,9 @@ class Compiler implements InjectionAwareInterface let blockStatements = statement["block_statements"]; let forElse = false; - if typeof blockStatements == "array" { + if typeof blockStatements == "array" { for bstatement in blockStatements { - if typeof bstatement != "array" { break; } @@ -754,9 +763,9 @@ class Compiler implements InjectionAwareInterface let compilation .= ""; let forElse = prefixLevel; let this->forElsePointers[level] = forElse; + break; } - } } @@ -859,13 +868,16 @@ class Compiler implements InjectionAwareInterface var level, prefix; let level = this->foreachLevel; - if fetch prefix, this->forElsePointers[level] { - if isset this->loopPointers[level] { - return ""; - } - return ""; + + if !fetch prefix, this->forElsePointers[level] { + return ""; + } + + if isset this->loopPointers[level] { + return ""; } - return ""; + + return ""; } /** @@ -891,7 +903,6 @@ class Compiler implements InjectionAwareInterface * Check for a "else"/"elseif" block */ if fetch blockStatements, statement["false_statements"] { - /** * Process statements in the "false" block */ @@ -923,13 +934,11 @@ class Compiler implements InjectionAwareInterface * If the path is an string try to make an static compilation */ if pathExpr["type"] == 260 { - /** * Static compilation cannot be performed if the user passed extra * parameters */ if !isset statement["params"] { - /** * Get the static path */ @@ -944,8 +953,8 @@ class Compiler implements InjectionAwareInterface */ let subCompiler = clone this; let compilation = subCompiler->compile(finalPath, false); - if typeof compilation == "null" { + if typeof compilation == "null" { /** * Use file-get-contents to respect the openbase_dir * directive @@ -957,7 +966,6 @@ class Compiler implements InjectionAwareInterface return compilation; } - } /** @@ -1005,16 +1013,16 @@ class Compiler implements InjectionAwareInterface let macroName = "$this->macros['" . name . "']"; let code = ""; } else { - /** * Parameters are always received as an array */ let code .= macroName . " = function($__p = null) { "; - for position, parameter in parameters { + for position, parameter in parameters { let variableName = parameter["variable"]; let code .= "if (isset($__p[" . position . "])) { "; @@ -1023,11 +1031,13 @@ class Compiler implements InjectionAwareInterface let code .= "if (array_key_exists(\"" . variableName . "\", $__p)) { "; let code .= "$" . variableName . " = $__p[\"" . variableName ."\"];"; let code .= " } else { "; + if fetch defaultValue, parameter["default"] { let code .= "$" . variableName . " = " . this->expression(defaultValue) . ";"; } else { let code .= " throw new \\Phalcon\\Mvc\\View\\Exception(\"Macro '" . name . "' was called without parameter: " . variableName . "\"); "; } + let code .= " } } "; } @@ -1038,7 +1048,6 @@ class Compiler implements InjectionAwareInterface * Block statements are allowed */ if fetch blockStatements, statement["block_statements"] { - /** * Process statements block */ @@ -1095,7 +1104,6 @@ class Compiler implements InjectionAwareInterface * A single set can have several assignments */ for assignment in assignments { - let exprCode = this->expression(assignment["expr"]); /** @@ -1133,6 +1141,7 @@ class Compiler implements InjectionAwareInterface } let compilation .= " ?>"; + return compilation; } @@ -1146,6 +1155,7 @@ class Compiler implements InjectionAwareInterface public function compileString(string! viewCode, bool extendsMode = false) -> string { let this->currentPath = "eval code"; + return this->compileSource(viewCode, extendsMode); } @@ -1224,13 +1234,15 @@ class Compiler implements InjectionAwareInterface let extensions = this->extensions; loop { - if typeof extensions == "array" { - /** * Notify the extensions about being resolving an expression */ - let exprCode = this->fireExtensionEvent("resolveExpression", [expr]); + let exprCode = this->fireExtensionEvent( + "resolveExpression", + [expr] + ); + if typeof exprCode == "string" { break; } @@ -1238,15 +1250,21 @@ class Compiler implements InjectionAwareInterface if !fetch type, expr["type"] { let items = []; + for singleExpr in expr { - let singleExprCode = this->expression(singleExpr["expr"]); + let singleExprCode = this->expression( + singleExpr["expr"] + ); + if fetch name, singleExpr["name"] { let items[] = "'" . name . "' => " . singleExprCode; } else { let items[] = singleExprCode; } } + let exprCode = join(", ", items); + break; } @@ -1255,6 +1273,7 @@ class Compiler implements InjectionAwareInterface */ if type == PHVOLT_T_DOT { let exprCode = this->attributeReader(expr); + break; } @@ -1269,7 +1288,11 @@ class Compiler implements InjectionAwareInterface * Operator "is" also needs special handling */ if type == PHVOLT_T_IS { - let exprCode = this->resolveTest(expr["right"], leftCode); + let exprCode = this->resolveTest( + expr["right"], + leftCode + ); + break; } @@ -1277,7 +1300,11 @@ class Compiler implements InjectionAwareInterface * We don't resolve the right expression for filters */ if type == 124 { - let exprCode = this->resolveFilter(expr["right"], leftCode); + let exprCode = this->resolveFilter( + expr["right"], + leftCode + ); + break; } @@ -1289,8 +1316,8 @@ class Compiler implements InjectionAwareInterface } let exprCode = null; - switch type { + switch type { case PHVOLT_T_NOT: let exprCode = "!" . rightCode; break; @@ -1341,6 +1368,7 @@ class Compiler implements InjectionAwareInterface } else { let exprCode = "[]"; } + break; case 258: @@ -1547,14 +1575,13 @@ class Compiler implements InjectionAwareInterface var extensions, extension, status; let extensions = this->extensions; + if typeof extensions == "array" { for extension in extensions { - /** * Check if the extension implements the required event name */ if method_exists(extension, name) { - if typeof arguments == "array" { let status = call_user_func_array( [extension, name], @@ -1581,27 +1608,27 @@ class Compiler implements InjectionAwareInterface */ public function functionCall(array! expr) -> string { - var code, funcArguments, arguments, nameExpr, - nameType, name, extensions, functions, definition, - extendedBlocks, block, currentBlock, exprLevel, escapedCode, - method, arrayHelpers; + var code, funcArguments, arguments, nameExpr, nameType, name, + extensions, functions, definition, extendedBlocks, block, + currentBlock, exprLevel, escapedCode, method, arrayHelpers; let code = null; let funcArguments = null; + if fetch funcArguments, expr["arguments"] { let arguments = this->expression(funcArguments); } else { let arguments = ""; } - let nameExpr = expr["name"], nameType = nameExpr["type"]; + let nameExpr = expr["name"], + nameType = nameExpr["type"]; /** * Check if it's a single function */ if nameType == PHVOLT_T_IDENTIFIER { - let name = nameExpr["value"]; /** @@ -1609,12 +1636,16 @@ class Compiler implements InjectionAwareInterface * this function */ let extensions = this->extensions; - if typeof extensions == "array" { + if typeof extensions == "array" { /** * Notify the extensions about being compiling a function */ - let code = this->fireExtensionEvent("compileFunction", [name, arguments, funcArguments]); + let code = this->fireExtensionEvent( + "compileFunction", + [name, arguments, funcArguments] + ); + if typeof code == "string" { return code; } @@ -1624,9 +1655,9 @@ class Compiler implements InjectionAwareInterface * Check if it's a user defined function */ let functions = this->functions; + if typeof functions == "array" { if fetch definition, functions[name] { - /** * Use the string as function */ @@ -1639,7 +1670,6 @@ class Compiler implements InjectionAwareInterface * definition */ if typeof definition == "object" { - if definition instanceof \Closure { return call_user_func_array( definition, @@ -1674,14 +1704,16 @@ class Compiler implements InjectionAwareInterface */ if name == "super" { let extendedBlocks = this->extendedBlocks; - if typeof extendedBlocks == "array" { + if typeof extendedBlocks == "array" { let currentBlock = this->currentBlock; - if fetch block, extendedBlocks[currentBlock] { + if fetch block, extendedBlocks[currentBlock] { let exprLevel = this->exprLevel; + if typeof block == "array" { let code = this->statementListOrExtends(block); + if exprLevel == 1 { let escapedCode = code; } else { @@ -1701,31 +1733,34 @@ class Compiler implements InjectionAwareInterface if exprLevel == 1 { return escapedCode; } + return "'" . escapedCode . "'"; } } return "''"; } - let method = lcfirst(camelize(name)); + let method = lcfirst( + camelize(name) + ); let arrayHelpers = [ - "link_to": true, - "image": true, - "form": true, - "submit_button": true, - "radio_field": true, - "check_field": true, - "file_field": true, - "hidden_field": true, + "link_to": true, + "image": true, + "form": true, + "submit_button": true, + "radio_field": true, + "check_field": true, + "file_field": true, + "hidden_field": true, "password_field": true, - "text_area": true, - "text_field": true, - "email_field": true, - "date_field": true, - "tel_field": true, - "numeric_field": true, - "image_input": true + "text_area": true, + "text_field": true, + "email_field": true, + "date_field": true, + "tel_field": true, + "numeric_field": true, + "image_input": true ]; /** @@ -1891,10 +1926,12 @@ class Compiler implements InjectionAwareInterface public function getOption(string! option) { var value; - if fetch value, this->options[option] { - return value; + + if !fetch value, this->options[option] { + return null; } - return null; + + return value; } /** @@ -1921,7 +1958,7 @@ class Compiler implements InjectionAwareInterface { /** * If the unique prefix is not set we use a hash using the modified - * Berstein algotithm + * Berstein algorithm */ if !this->prefix { let this->prefix = unique_path_key(this->currentPath); @@ -1963,6 +2000,7 @@ class Compiler implements InjectionAwareInterface public function parse(string! viewCode) { var currentPath = "eval code"; + return phvolt_parse_view(viewCode, currentPath); } @@ -1979,7 +2017,6 @@ class Compiler implements InjectionAwareInterface * Check if right part is a single identifier */ if type == PHVOLT_T_IDENTIFIER { - let name = test["value"]; /** @@ -2030,10 +2067,9 @@ class Compiler implements InjectionAwareInterface * Check if right part is a function call */ if type == PHVOLT_T_FCALL { - let testName = test["name"]; - if fetch name, testName["value"] { + if fetch name, testName["value"] { if name == "divisibleby" { return "(((" . left . ") % (" . this->expression(test["arguments"]) . ")) == 0)"; } @@ -2092,6 +2128,7 @@ class Compiler implements InjectionAwareInterface public function setUniquePrefix(string! prefix) -> { let this->prefix = prefix; + return this; } @@ -2101,9 +2138,9 @@ class Compiler implements InjectionAwareInterface */ protected function compileSource(string! viewCode, bool extendsMode = false) -> string { - var currentPath, intermediate, extended, - finalCompilation, blocks, extendedBlocks, name, block, - blockCompilation, localBlock, compilation, options, autoescape; + var currentPath, intermediate, extended, finalCompilation, blocks, + extendedBlocks, name, block, blockCompilation, localBlock, + compilation, options, autoescape; let currentPath = this->currentPath; @@ -2111,8 +2148,8 @@ class Compiler implements InjectionAwareInterface * Check for compilation options */ let options = this->options; - if typeof options == "array" { + if typeof options == "array" { /** * Enable autoescape globally */ @@ -2120,6 +2157,7 @@ class Compiler implements InjectionAwareInterface if typeof autoescape != "boolean" { throw new Exception("'autoescape' must be bool"); } + let this->autoescape = autoescape; } } @@ -2139,8 +2177,8 @@ class Compiler implements InjectionAwareInterface * Check if the template is extending another */ let extended = this->extended; - if extended === true { + if extended === true { /** * Multiple-Inheritance is allowed */ @@ -2154,12 +2192,10 @@ class Compiler implements InjectionAwareInterface let extendedBlocks = this->extendedBlocks; for name, block in extendedBlocks { - /** * If name is a string then is a block name */ if typeof name == "string" { - if isset blocks[name] { /** * The block is set in the local template @@ -2185,7 +2221,6 @@ class Compiler implements InjectionAwareInterface let finalCompilation .= blockCompilation; } } else { - /** * Here the block is an already compiled text */ @@ -2207,6 +2242,7 @@ class Compiler implements InjectionAwareInterface */ return this->blocks; } + return compilation; } @@ -2216,6 +2252,7 @@ class Compiler implements InjectionAwareInterface protected function getFinalPath(string path) { var view, viewsDirs, viewsDir; + let view = this->view; if typeof view == "object" { @@ -2230,7 +2267,6 @@ class Compiler implements InjectionAwareInterface // Otherwise, take the last viewsDir return viewsDir . path; - } else { return viewsDirs . path; } @@ -2244,10 +2280,11 @@ class Compiler implements InjectionAwareInterface */ final protected function resolveFilter(array! filter, string left) -> string { - var code, type, functionName, name, file, line, - extensions, filters, funcArguments, arguments, definition; + var code, type, functionName, name, file, line, extensions, filters, + funcArguments, arguments, definition; - let code = null, type = filter["type"]; + let code = null, + type = filter["type"]; /** * Check if the filter is a single identifier @@ -2255,9 +2292,7 @@ class Compiler implements InjectionAwareInterface if type == PHVOLT_T_IDENTIFIER { let name = filter["value"]; } else { - if type != PHVOLT_T_FCALL { - /** * Unknown filter throw an exception */ @@ -2270,33 +2305,36 @@ class Compiler implements InjectionAwareInterface name = functionName["value"]; } - let funcArguments = null, arguments = null; + let funcArguments = null, + arguments = null; /** * Resolve arguments */ if fetch funcArguments, filter["arguments"] { - /** * "default" filter is not the first argument, improve this! */ if name != "default" { - - let file = filter["file"], line = filter["line"]; + let file = filter["file"], + line = filter["line"]; /** * TODO: Implement this function directly */ - array_unshift(funcArguments, [ - "expr": [ - "type": 364, - "value": left, + array_unshift( + funcArguments, + [ + "expr": [ + "type": 364, + "value": left, + "file": file, + "line": line + ], "file": file, "line": line - ], - "file": file, - "line": line - ]); + ] + ); } let arguments = this->expression(funcArguments); @@ -2309,12 +2347,16 @@ class Compiler implements InjectionAwareInterface * this filter */ let extensions = this->extensions; - if typeof extensions == "array" { + if typeof extensions == "array" { /** * Notify the extensions about being compiling a function */ - let code = this->fireExtensionEvent("compileFilter", [name, arguments, funcArguments]); + let code = this->fireExtensionEvent( + "compileFilter", + [name, arguments, funcArguments] + ); + if typeof code == "string" { return code; } @@ -2324,35 +2366,33 @@ class Compiler implements InjectionAwareInterface * Check if it's a user defined filter */ let filters = this->filters; - if typeof filters == "array" { - if fetch definition, filters[name] { - /** - * The definition is a string - */ - if typeof definition == "string" { - return definition . "(" . arguments . ")"; - } + if fetch definition, filters[name] { + /** + * The definition is a string + */ + if typeof definition == "string" { + return definition . "(" . arguments . ")"; + } - /** - * The definition is a closure - */ - if typeof definition == "object" { - if definition instanceof \Closure { - return call_user_func_array( - definition, - [arguments, funcArguments] - ); - } + /** + * The definition is a closure + */ + if typeof definition == "object" { + if definition instanceof \Closure { + return call_user_func_array( + definition, + [arguments, funcArguments] + ); } - - /** - * Invalid filter definition throw an exception - */ - throw new Exception( - "Invalid definition for user filter '" . name . "' in " . filter["file"] . " on line " . filter["line"] - ); } + + /** + * Invalid filter definition throw an exception + */ + throw new Exception( + "Invalid definition for user filter '" . name . "' in " . filter["file"] . " on line " . filter["line"] + ); } /** @@ -2554,9 +2594,9 @@ class Compiler implements InjectionAwareInterface */ final protected function statementList(array! statements, bool extendsMode = false) -> string { - var extended, blockMode, compilation, extensions, - statement, tempCompilation, type, blockName, blockStatements, - blocks, path, finalPath, subCompiler, level; + var extended, blockMode, compilation, extensions, statement, + tempCompilation, type, blockName, blockStatements, blocks, path, + finalPath, subCompiler, level; /** * Nothing to compile @@ -2570,6 +2610,7 @@ class Compiler implements InjectionAwareInterface */ let extended = this->extended; let blockMode = extended || extendsMode; + if blockMode === true { let this->blockLevel++; } @@ -2579,8 +2620,8 @@ class Compiler implements InjectionAwareInterface let compilation = null; let extensions = this->extensions; - for statement in statements { + for statement in statements { /** * All statements must be arrays */ @@ -2603,13 +2644,17 @@ class Compiler implements InjectionAwareInterface * statement */ if typeof extensions == "array" { - /** * Notify the extensions about being resolving a statement */ - let tempCompilation = this->fireExtensionEvent("compileStatement", [statement]); + let tempCompilation = this->fireExtensionEvent( + "compileStatement", + [statement] + ); + if typeof tempCompilation == "string" { let compilation .= tempCompilation; + continue; } } @@ -2678,8 +2723,8 @@ class Compiler implements InjectionAwareInterface fetch blockStatements, statement["block_statements"]; let blocks = this->blocks; - if blockMode { + if blockMode { if typeof blocks != "array" { let blocks = []; } @@ -2698,7 +2743,6 @@ class Compiler implements InjectionAwareInterface */ let blocks[blockName] = blockStatements; let this->blocks = blocks; - } else { if typeof blockStatements == "array" { let compilation .= this->statementList( @@ -2707,6 +2751,7 @@ class Compiler implements InjectionAwareInterface ); } } + break; case PHVOLT_T_EXTENDS: @@ -2716,7 +2761,9 @@ class Compiler implements InjectionAwareInterface */ let path = statement["path"]; - let finalPath = this->getFinalPath(path["value"]); + let finalPath = this->getFinalPath( + path["value"] + ); let extended = true; @@ -2743,10 +2790,12 @@ class Compiler implements InjectionAwareInterface let this->extended = true; let this->extendedBlocks = tempCompilation; let blockMode = extended; + break; case PHVOLT_T_INCLUDE: let compilation .= this->compileInclude(statement); + break; case PHVOLT_T_CACHE: @@ -2835,11 +2884,13 @@ class Compiler implements InjectionAwareInterface */ if blockMode === true { let level = this->blockLevel; + if level == 1 { if typeof compilation != "null" { let this->blocks[] = compilation; } } + let this->blockLevel--; } @@ -2871,10 +2922,12 @@ class Compiler implements InjectionAwareInterface * statementList */ let isStatementList = true; + if !isset statements["type"] { for statement in statements { if typeof statement != "array" { let isStatementList = false; + break; } } diff --git a/phalcon/Mvc/View/Engine/Volt/Exception.zep b/phalcon/Mvc/View/Engine/Volt/Exception.zep index 267dbd4af08..f813cb9b281 100644 --- a/phalcon/Mvc/View/Engine/Volt/Exception.zep +++ b/phalcon/Mvc/View/Engine/Volt/Exception.zep @@ -36,6 +36,7 @@ class Exception extends BaseException var statement; let statement = this->statement; + if typeof statement !== "array" { let statement = []; } diff --git a/phalcon/Mvc/View/Simple.zep b/phalcon/Mvc/View/Simple.zep index 270d6977999..127866a2481 100644 --- a/phalcon/Mvc/View/Simple.zep +++ b/phalcon/Mvc/View/Simple.zep @@ -47,7 +47,6 @@ use Phalcon\Mvc\View\Engine\Php as PhpEngine; */ class Simple extends Injectable implements ViewBaseInterface { - protected activeRenderPath; protected cache = false; protected cacheOptions; @@ -88,11 +87,12 @@ class Simple extends Injectable implements ViewBaseInterface public function __get(string! key) -> var | null { var value; - if fetch value, this->viewParams[key] { - return value; + + if !fetch value, this->viewParams[key] { + return null; } - return null; + return value; } /** @@ -131,6 +131,7 @@ class Simple extends Injectable implements ViewBaseInterface let this->cache = false; } } + return this; } @@ -183,11 +184,13 @@ class Simple extends Injectable implements ViewBaseInterface */ public function getVar(string! key) -> var | null { - var value; - if fetch value, this->viewParams[key] { - return value; + var value; + + if !fetch value, this->viewParams[key] { + return null; } - return null; + + return value; } /** @@ -230,7 +233,6 @@ class Simple extends Injectable implements ViewBaseInterface * symbol table */ if typeof params == "array" { - let viewParams = this->viewParams; /** @@ -242,7 +244,6 @@ class Simple extends Injectable implements ViewBaseInterface * Create a virtual symbol table */ create_symbol_table(); - } else { let mergedParams = params; } @@ -293,7 +294,8 @@ class Simple extends Injectable implements ViewBaseInterface */ public function render(string! path, array params = []) -> string { - var cache, key, lifetime, cacheOptions, content, viewParams, mergedParams; + var cache, key, lifetime, cacheOptions, content, viewParams, + mergedParams; /** * Create/Get a cache @@ -301,20 +303,20 @@ class Simple extends Injectable implements ViewBaseInterface let cache = this->getCache(); if typeof cache == "object" { - /** * Check if the cache is started, the first time a cache is started * we start the cache */ if !cache->isStarted() { - - let key = null, lifetime = null; + let key = null, + lifetime = null; /** * Check if the user has defined a different options to the * default */ let cacheOptions = this->cacheOptions; + if typeof cacheOptions == "array" { fetch key, cacheOptions["key"]; fetch lifetime, cacheOptions["lifetime"]; @@ -331,12 +333,13 @@ class Simple extends Injectable implements ViewBaseInterface * We start the cache using the key set */ let content = cache->start(key, lifetime); + if content !== null { let this->content = content; + return content; } } - } /** @@ -380,6 +383,7 @@ class Simple extends Injectable implements ViewBaseInterface public function setCacheOptions(array options) -> { let this->cacheOptions = options; + return this; } @@ -393,6 +397,7 @@ class Simple extends Injectable implements ViewBaseInterface public function setContent(string! content) -> { let this->content = content; + return this; } @@ -406,6 +411,7 @@ class Simple extends Injectable implements ViewBaseInterface public function setParamToView(string! key, var value) -> { let this->viewParams[key] = value; + return this; } @@ -419,6 +425,7 @@ class Simple extends Injectable implements ViewBaseInterface public function setVar(string! key, var value) -> { let this->viewParams[key] = value; + return this; } @@ -464,6 +471,7 @@ class Simple extends Injectable implements ViewBaseInterface var container, cacheService, cacheOptions, viewCache; let container = this->container; + if typeof container != "object" { throw new Exception( Exception::containerServiceNotFound("the view cache services") @@ -473,6 +481,7 @@ class Simple extends Injectable implements ViewBaseInterface let cacheService = "viewCache"; let cacheOptions = this->cacheOptions; + if typeof cacheOptions == "array" { if isset cacheOptions["service"] { fetch cacheService, cacheOptions["service"]; @@ -483,6 +492,7 @@ class Simple extends Injectable implements ViewBaseInterface * The injected service must be an object */ let viewCache = container->getShared(cacheService); + if typeof viewCache != "object" { throw new Exception("The injected caching service is invalid"); } @@ -502,23 +512,21 @@ class Simple extends Injectable implements ViewBaseInterface * If the engines aren't initialized 'engines' is false */ let engines = this->engines; - if engines === false { + if engines === false { let di = this->container; let engines = []; let registeredEngines = this->registeredEngines; - if typeof registeredEngines != "array" { + if typeof registeredEngines != "array" { /** * We use Phalcon\Mvc\View\Engine\Php as default * Use .phtml as extension for the PHP engine */ let engines[".phtml"] = new PhpEngine(this, di); - } else { - if typeof di != "object" { throw new Exception( Exception::containerServiceNotFound( @@ -528,7 +536,6 @@ class Simple extends Injectable implements ViewBaseInterface } for extension, engineService in registeredEngines { - if typeof engineService == "object" { /** * Engine can be a closure @@ -608,7 +615,6 @@ class Simple extends Injectable implements ViewBaseInterface * Views are rendered in each engine */ for extension, engine in engines { - if file_exists(viewsDirPath . extension) { let viewEnginePath = viewsDirPath . extension; } elseif substr(viewsDirPath, -strlen(extension)) == extension && file_exists(viewsDirPath) { diff --git a/phalcon/Paginator/Adapter.zep b/phalcon/Paginator/Adapter.zep index 729f98e4ffb..08639850688 100644 --- a/phalcon/Paginator/Adapter.zep +++ b/phalcon/Paginator/Adapter.zep @@ -32,6 +32,7 @@ abstract class Adapter implements AdapterInterface /** * Repository for pagination + * * @var RepositoryInterface */ protected repository; @@ -44,15 +45,21 @@ abstract class Adapter implements AdapterInterface let this->config = config; if isset config["limit"] { - this->setLimit(config["limit"]); + this->setLimit( + config["limit"] + ); } if isset config["page"] { - this->setCurrentPage(config["page"]); + this->setCurrentPage( + config["page"] + ); } if isset config["repository"] { - this->setRepository(config["repository"]); + this->setRepository( + config["repository"] + ); } } @@ -70,6 +77,7 @@ abstract class Adapter implements AdapterInterface public function setCurrentPage(int page) -> { let this->page = page; + return this; } @@ -79,6 +87,7 @@ abstract class Adapter implements AdapterInterface public function setLimit(int limitRows) -> { let this->limitRows = limitRows; + return this; } @@ -88,6 +97,7 @@ abstract class Adapter implements AdapterInterface public function setRepository( repository) -> { let this->repository = repository; + return this; } diff --git a/phalcon/Paginator/Adapter/Model.zep b/phalcon/Paginator/Adapter/Model.zep index f9f360740a6..5b998a22c29 100644 --- a/phalcon/Paginator/Adapter/Model.zep +++ b/phalcon/Paginator/Adapter/Model.zep @@ -42,8 +42,8 @@ class Model extends Adapter public function paginate() -> { var config, items, pageItems; - int pageNumber, show, n, start, lastShowPage, - i, next, totalPages, previous; + int pageNumber, show, n, start, lastShowPage, i, next, totalPages, + previous; let show = (int) this->limitRows, config = this->config, @@ -64,10 +64,10 @@ class Model extends Adapter throw new Exception("The start page number is zero or less"); } - let n = count(items), - lastShowPage = pageNumber - 1, - start = show * lastShowPage, - pageItems = []; + let n = count(items), + lastShowPage = pageNumber - 1, + start = show * lastShowPage, + pageItems = []; if n % show != 0 { let totalPages = (int) (n / show + 1); @@ -76,29 +76,34 @@ class Model extends Adapter } if n > 0 { - //Seek to the desired position if start <= n { items->seek(start); } else { items->seek(0); + let pageNumber = 1; } //The record must be iterable let i = 1; + while items->valid() { let pageItems[] = items->current(); + if i >= show { break; } + let i++; + items->next(); } } //Fix next let next = pageNumber + 1; + if next > totalPages { let next = totalPages; } @@ -109,15 +114,17 @@ class Model extends Adapter let previous = 1; } - return this->getRepository([ - RepositoryInterface::PROPERTY_ITEMS : pageItems, - RepositoryInterface::PROPERTY_TOTAL_ITEMS : n, - RepositoryInterface::PROPERTY_LIMIT : this->limitRows, - RepositoryInterface::PROPERTY_FIRST_PAGE : 1, - RepositoryInterface::PROPERTY_PREVIOUS_PAGE : previous, - RepositoryInterface::PROPERTY_CURRENT_PAGE : pageNumber, - RepositoryInterface::PROPERTY_NEXT_PAGE : next, - RepositoryInterface::PROPERTY_LAST_PAGE : totalPages - ]); + return this->getRepository( + [ + RepositoryInterface::PROPERTY_ITEMS : pageItems, + RepositoryInterface::PROPERTY_TOTAL_ITEMS : n, + RepositoryInterface::PROPERTY_LIMIT : this->limitRows, + RepositoryInterface::PROPERTY_FIRST_PAGE : 1, + RepositoryInterface::PROPERTY_PREVIOUS_PAGE : previous, + RepositoryInterface::PROPERTY_CURRENT_PAGE : pageNumber, + RepositoryInterface::PROPERTY_NEXT_PAGE : next, + RepositoryInterface::PROPERTY_LAST_PAGE : totalPages + ] + ); } } diff --git a/phalcon/Paginator/Adapter/NativeArray.zep b/phalcon/Paginator/Adapter/NativeArray.zep index 392e35b9ad7..52995c80841 100644 --- a/phalcon/Paginator/Adapter/NativeArray.zep +++ b/phalcon/Paginator/Adapter/NativeArray.zep @@ -58,7 +58,7 @@ class NativeArray extends Adapter throw new Exception("Invalid data for paginator"); } - let show = (int) this->limitRows, + let show = (int) this->limitRows, pageNumber = (int) this->page; if pageNumber <= 0 { @@ -91,15 +91,17 @@ class NativeArray extends Adapter let previous = 1; } - return this->getRepository([ - RepositoryInterface::PROPERTY_ITEMS : items, - RepositoryInterface::PROPERTY_TOTAL_ITEMS : number, - RepositoryInterface::PROPERTY_LIMIT : this->limitRows, - RepositoryInterface::PROPERTY_FIRST_PAGE : 1, - RepositoryInterface::PROPERTY_PREVIOUS_PAGE : previous, - RepositoryInterface::PROPERTY_CURRENT_PAGE : pageNumber, - RepositoryInterface::PROPERTY_NEXT_PAGE : next, - RepositoryInterface::PROPERTY_LAST_PAGE : totalPages - ]); + return this->getRepository( + [ + RepositoryInterface::PROPERTY_ITEMS : items, + RepositoryInterface::PROPERTY_TOTAL_ITEMS : number, + RepositoryInterface::PROPERTY_LIMIT : this->limitRows, + RepositoryInterface::PROPERTY_FIRST_PAGE : 1, + RepositoryInterface::PROPERTY_PREVIOUS_PAGE : previous, + RepositoryInterface::PROPERTY_CURRENT_PAGE : pageNumber, + RepositoryInterface::PROPERTY_NEXT_PAGE : next, + RepositoryInterface::PROPERTY_LAST_PAGE : totalPages + ] + ); } } diff --git a/phalcon/Paginator/Adapter/QueryBuilder.zep b/phalcon/Paginator/Adapter/QueryBuilder.zep index 303a2d5fe79..b0f5cdc680e 100644 --- a/phalcon/Paginator/Adapter/QueryBuilder.zep +++ b/phalcon/Paginator/Adapter/QueryBuilder.zep @@ -94,10 +94,10 @@ class QueryBuilder extends Adapter */ public function paginate() -> { - var originalBuilder, builder, totalBuilder, totalPages, - limit, numberPage, number, query, previous, items, totalQuery, - result, row, rowcount, next, sql, columns, db, hasHaving, hasGroup, - model, modelClass, dbService, groups, groupColumn; + var originalBuilder, builder, totalBuilder, totalPages, limit, + numberPage, number, query, previous, items, totalQuery, result, row, + rowcount, next, sql, columns, db, hasHaving, hasGroup, model, + modelClass, dbService, groups, groupColumn; let originalBuilder = this->builder; let columns = this->columns; @@ -160,6 +160,7 @@ class QueryBuilder extends Adapter "option provided for which calculate row count" ); } + totalBuilder->columns(columns); } else { totalBuilder->columns("COUNT(*) [rowcount]"); @@ -202,7 +203,7 @@ class QueryBuilder extends Adapter */ if hasHaving { let sql = totalQuery->getSql(), - modelClass = builder->getModels(); + modelClass = builder->getModels(); if typeof modelClass == "null" { throw new Exception("Model not defined in builder"); @@ -237,16 +238,18 @@ class QueryBuilder extends Adapter let next = totalPages; } - return this->getRepository([ - RepositoryInterface::PROPERTY_ITEMS : items, - RepositoryInterface::PROPERTY_TOTAL_ITEMS : rowcount, - RepositoryInterface::PROPERTY_LIMIT : this->limitRows, - RepositoryInterface::PROPERTY_FIRST_PAGE : 1, - RepositoryInterface::PROPERTY_PREVIOUS_PAGE : previous, - RepositoryInterface::PROPERTY_CURRENT_PAGE : numberPage, - RepositoryInterface::PROPERTY_NEXT_PAGE : next, - RepositoryInterface::PROPERTY_LAST_PAGE : totalPages - ]); + return this->getRepository( + [ + RepositoryInterface::PROPERTY_ITEMS : items, + RepositoryInterface::PROPERTY_TOTAL_ITEMS : rowcount, + RepositoryInterface::PROPERTY_LIMIT : this->limitRows, + RepositoryInterface::PROPERTY_FIRST_PAGE : 1, + RepositoryInterface::PROPERTY_PREVIOUS_PAGE : previous, + RepositoryInterface::PROPERTY_CURRENT_PAGE : numberPage, + RepositoryInterface::PROPERTY_NEXT_PAGE : next, + RepositoryInterface::PROPERTY_LAST_PAGE : totalPages + ] + ); } /** diff --git a/phalcon/Paginator/Repository.zep b/phalcon/Paginator/Repository.zep index 10c7f14953b..679f9c2d1ee 100644 --- a/phalcon/Paginator/Repository.zep +++ b/phalcon/Paginator/Repository.zep @@ -33,6 +33,7 @@ class Repository implements RepositoryInterface public function __get(string property) -> var | null { var method; + let method = "get" . camelize(this->getRealNameProperty(property)); if method_exists(this, method) { @@ -127,6 +128,7 @@ class Repository implements RepositoryInterface public function setAliases(array aliases) -> { let this->aliases = aliases; + return this; } @@ -136,6 +138,7 @@ class Repository implements RepositoryInterface public function setProperties(array properties) -> { let this->properties = properties; + return this; } diff --git a/phalcon/Registry.zep b/phalcon/Registry.zep index fcfd986edbd..e1abead84fb 100644 --- a/phalcon/Registry.zep +++ b/phalcon/Registry.zep @@ -45,9 +45,9 @@ use Phalcon\Collection; * * In addition to ArrayAccess, Phalcon\Registry also implements Countable * (count($registry) will return the number of elements in the registry), - * Serializable and Iterator (you can iterate over the registry - * using a foreach loop) interfaces. For PHP 5.4 and higher, JsonSerializable - * interface is implemented. + * Serializable and Iterator (you can iterate over the registry using a foreach + * loop) interfaces. For PHP 5.4 and higher, JsonSerializable interface is + * implemented. * * Phalcon\Registry is very fast (it is typically faster than any userspace * implementation of the registry); however, this comes at a price: @@ -59,8 +59,8 @@ use Phalcon\Collection; * is several times slower than $registry->property. * * Internally all the magic methods (and interfaces except JsonSerializable) - * are implemented using object handlers or similar techniques: this allows - * to bypass relatively slow method calls. + * are implemented using object handlers or similar techniques: this allows to + * bypass relatively slow method calls. */ final class Registry extends Collection { diff --git a/phalcon/Security.zep b/phalcon/Security.zep index 3527134aec8..34111875f66 100644 --- a/phalcon/Security.zep +++ b/phalcon/Security.zep @@ -89,6 +89,7 @@ class Security implements InjectionAwareInterface let cryptedHash .= passwordHash; let sum = cryptedLength - passwordLength; + for i, ch in passwordHash { let sum = sum | (cryptedHash[i] ^ ch); } @@ -115,7 +116,9 @@ class Security implements InjectionAwareInterface let session = container->getShared("session"); if !tokenKey { - let tokenKey = session->get(this->tokenKeySessionId); + let tokenKey = session->get( + this->tokenKeySessionId + ); } /** @@ -140,6 +143,7 @@ class Security implements InjectionAwareInterface * The value is the same? */ let knownToken = this->getRequestToken(); + let equals = hash_equals(knownToken, userToken); /** @@ -207,6 +211,7 @@ class Security implements InjectionAwareInterface { return this->defaultHash; } + /** * Returns the internal dependency injector */ @@ -240,6 +245,7 @@ class Security implements InjectionAwareInterface if empty this->requestToken { return this->getSessionToken(); } + return this->requestToken; } @@ -327,6 +333,7 @@ class Security implements InjectionAwareInterface if null === this->tokenKey { let container = this->container; + if typeof container != "object" { throw new Exception( Exception::containerServiceNotFound("the 'session' service") @@ -456,6 +463,7 @@ class Security implements InjectionAwareInterface */ let saltBytes = this->getSaltBytes(22); + if typeof saltBytes != "string" { throw new Exception( "Unable to get random bytes for the salt" diff --git a/phalcon/Service/Locator.zep b/phalcon/Service/Locator.zep index 4d17ad5ef77..0ba25d63ca1 100644 --- a/phalcon/Service/Locator.zep +++ b/phalcon/Service/Locator.zep @@ -46,6 +46,7 @@ class Locator implements LocatorInterface var service; let service = this->get(name); + return call_user_func_array(service, parameters); } @@ -57,13 +58,13 @@ class Locator implements LocatorInterface { var definition, service; - if (true !== this->has(name)) { + if !this->has(name) { throw new Exception( "The service " . name . " has not been found in the locator" ); } - if (true !== isset(this->services[name])) { + if !isset(this->services[name]) { let definition = this->mapper[name]; if typeof definition == "string" { diff --git a/phalcon/Session/Adapter/Libmemcached.zep b/phalcon/Session/Adapter/Libmemcached.zep index fc68f908dc8..51343e502bd 100644 --- a/phalcon/Session/Adapter/Libmemcached.zep +++ b/phalcon/Session/Adapter/Libmemcached.zep @@ -80,7 +80,7 @@ class Libmemcached extends Noop ), [ "servers" : servers, - "client" : client, + "client" : client, "prefix" : prefix, "statsKey" : statsKey, "persistent_id" : persistentId @@ -91,6 +91,7 @@ class Libmemcached extends Noop public function destroy(var id) -> bool { var name = this->getPrefixedName(id); + if (true !== empty(name) && this->connection->exists(name)) { return (bool) this->connection->delete(name); } diff --git a/phalcon/Session/Bag.zep b/phalcon/Session/Bag.zep index 00020e2df2b..17ad78d4caf 100644 --- a/phalcon/Session/Bag.zep +++ b/phalcon/Session/Bag.zep @@ -48,8 +48,10 @@ class Bag extends Collection implements InjectionAwareInterface if typeof session != "object" { let container = this->container; + if typeof container != "object" { let container = Di::getDefault(); + if typeof container != "object" { throw new Exception( Exception::containerServiceNotFound( @@ -64,6 +66,7 @@ class Bag extends Collection implements InjectionAwareInterface } let data = session->get(this->name); + if typeof data != "array" { let data = []; } @@ -77,6 +80,7 @@ class Bag extends Collection implements InjectionAwareInterface public function clear() -> void { parent::clear(); + this->session->remove(this->name); } @@ -102,6 +106,7 @@ class Bag extends Collection implements InjectionAwareInterface public function remove(string! element, bool insensitive = true) -> void { parent::remove(element, insensitive); + this->session->set(this->name, this->data); } @@ -111,6 +116,7 @@ class Bag extends Collection implements InjectionAwareInterface public function set(string! element, var value) { parent::set(element, value); + this->session->set(this->name, this->data); } diff --git a/phalcon/Session/Factory.zep b/phalcon/Session/Factory.zep index 3243a07d1cd..8cddf364fab 100644 --- a/phalcon/Session/Factory.zep +++ b/phalcon/Session/Factory.zep @@ -27,6 +27,7 @@ use Phalcon\Factory as BaseFactory; * "prefix" => "my_", * "adapter" => "memcache", * ]; + * * $session = Factory::load($options); * */ diff --git a/phalcon/Session/Manager.zep b/phalcon/Session/Manager.zep index 806fccb059e..ea91a2b6646 100644 --- a/phalcon/Session/Manager.zep +++ b/phalcon/Session/Manager.zep @@ -52,15 +52,12 @@ class Manager implements ManagerInterface, InjectionAwareInterface /** * Manager constructor. - * - * @param array options */ public function __construct(array options = []) -> void { this->setOptions(options); } - /** * Alias: Gets a session variable from an application context */ @@ -100,6 +97,7 @@ class Manager implements ManagerInterface, InjectionAwareInterface { if (true === this->exists()) { session_destroy(); + let _SESSION = []; } } @@ -109,11 +107,7 @@ class Manager implements ManagerInterface, InjectionAwareInterface */ public function exists() -> bool { - if (session_status() === self::SESSION_ACTIVE) { - return true; - } - - return false; + return (session_status() === self::SESSION_ACTIVE); } /** @@ -303,7 +297,7 @@ class Manager implements ManagerInterface, InjectionAwareInterface */ public function setName(string name) -> { - if (this->exists()) { + if this->exists() { throw new InvalidArgumentException( "Cannot set session name after a session has started" ); @@ -316,6 +310,7 @@ class Manager implements ManagerInterface, InjectionAwareInterface } let this->name = name; + session_name(name); return this; @@ -323,8 +318,6 @@ class Manager implements ManagerInterface, InjectionAwareInterface /** * Sets session's options - * - * @param array options */ public function setOptions(array options) -> void { @@ -371,8 +364,6 @@ class Manager implements ManagerInterface, InjectionAwareInterface /** * Returns the status of the current session. - * - * @return int */ public function status() -> int { diff --git a/phalcon/Session/ManagerInterface.zep b/phalcon/Session/ManagerInterface.zep index 1d26b36508c..70dc8a8099b 100644 --- a/phalcon/Session/ManagerInterface.zep +++ b/phalcon/Session/ManagerInterface.zep @@ -109,18 +109,12 @@ interface ManagerInterface * Set the session name. Throw exception if the session has started * and do not allow poop names * - * @param string name - * * @throws InvalidArgumentException - * - * @return Manager */ public function setName(string name) -> ; /** * Sets session's options - * - * @param array options */ public function setOptions(array options) -> void; diff --git a/phalcon/Tag.zep b/phalcon/Tag.zep index 2404439bc48..15d20175d95 100644 --- a/phalcon/Tag.zep +++ b/phalcon/Tag.zep @@ -156,7 +156,7 @@ class Tag } /** - * Alias of Phalcon\Tag::setDefault + * Alias of Phalcon\Tag::setDefault() * * @param string value */ @@ -292,12 +292,12 @@ class Tag } if replace { - if typeof replace != "array" && typeof replace != "string"{ throw new Exception( "Parameter replace must be an array or a string" ); } + if typeof replace == "array" { for search in replace { let text = str_replace(search, " ", text); @@ -307,7 +307,12 @@ class Tag } } - let friendly = preg_replace("/[^a-zA-Z0-9\\/_|+ -]/", "", text); + let friendly = preg_replace( + "/[^a-zA-Z0-9\\/_|+ -]/", + "", + text + ); + if lowercase { let friendly = strtolower(friendly); } @@ -390,10 +395,13 @@ class Tag public static function getDI() -> { var di; + let di = self::container; + if typeof di != "object" { let di = Di::getDefault(); } + return di; } @@ -405,8 +413,8 @@ class Tag var escaper, container; let escaper = self::escaperService; - if typeof escaper != "object" { + if typeof escaper != "object" { let container = self::getDI(); if typeof container != "object" { @@ -418,6 +426,7 @@ class Tag let escaper = container->getShared("escaper"), self::escaperService = escaper; } + return escaper; } @@ -463,6 +472,7 @@ class Tag if !empty documentPrependTitle { var tmp = array_reverse(documentPrependTitle); + for title in tmp { let items[] = escaper->escapeHtml(title); } @@ -522,8 +532,8 @@ class Tag var url, container; let url = self::urlService; - if typeof url != "object" { + if typeof url != "object" { let container = self::getDI(); if typeof container != "object" { @@ -535,6 +545,7 @@ class Tag let url = container->getShared("url"), self::urlService = url; } + return url; } @@ -630,6 +641,7 @@ class Tag let params = [parameters]; } else { let params = parameters; + if isset params[1] { let local = (bool) params[1]; } @@ -722,6 +734,7 @@ class Tag } else { if isset params["local"] { let local = (bool) params["local"]; + unset params["local"]; } } @@ -974,6 +987,7 @@ class Tag ]; let attrs = []; + for key, value in order { if fetch attribute, attributes[key] { let attrs[key] = attribute; @@ -991,6 +1005,7 @@ class Tag unset attrs["escape"]; let newCode = code; + for key, value in attrs { if typeof key == "string" && value !== null { if typeof value == "array" || typeof value == "resource" { @@ -998,11 +1013,13 @@ class Tag "Value at index: '" . key . "' type: '" . gettype(value) . "' cannot be rendered" ); } + if escaper { let escaped = escaper->escapeHtmlAttr(value); } else { let escaped = value; } + let newCode .= " " . key . "=\"" . escaped . "\""; } } @@ -1135,6 +1152,7 @@ class Tag ); } } + let self::displayValues[id] = value; } @@ -1175,7 +1193,7 @@ class Tag */ public static function setDocType(int doctype) -> void { - if (doctype < self::HTML32 || doctype > self::XHTML5) { + if doctype < self::HTML32 || doctype > self::XHTML5 { let self::documentType = self::HTML5; } else { let self::documentType = doctype; @@ -1241,6 +1259,7 @@ class Tag } else { if isset params["local"] { let local = (bool) params["local"]; + unset params["local"]; } } @@ -1360,6 +1379,7 @@ class Tag if useEol { return "" . PHP_EOL; } + return ""; } @@ -1410,10 +1430,12 @@ class Tag } let id = params[0]; + if !isset params["name"] { let params["name"] = id; } else { let name = params["name"]; + if empty name { let params["name"] = id; } @@ -1425,6 +1447,7 @@ class Tag if isset params["value"] { let content = params["value"]; + unset params["value"]; } else { let content = self::getValue(id, params); @@ -1503,7 +1526,6 @@ class Tag } if asValue == false { - if !fetch id, params[0] { let params[0] = params["id"]; } @@ -1526,7 +1548,6 @@ class Tag } let params["value"] = self::getValue(id, params); - } else { /** * Use the "id" as value if the user hadn't set it @@ -1573,10 +1594,12 @@ class Tag } let id = params[0]; + if !isset params["name"] { let params["name"] = id; } else { let name = params["name"]; + if empty name { let params["name"] = id; } @@ -1602,6 +1625,7 @@ class Tag if value != null && currentValue == value { let params["checked"] = "checked"; } + let params["value"] = currentValue; } else { let value = self::getValue(id, params); diff --git a/phalcon/Tag/Exception.zep b/phalcon/Tag/Exception.zep index 23aaca4854d..3bb90ac6836 100644 --- a/phalcon/Tag/Exception.zep +++ b/phalcon/Tag/Exception.zep @@ -14,7 +14,6 @@ namespace Phalcon\Tag; * Phalcon\Tag\Exception * * Exceptions thrown in Phalcon\Tag will use this class - * */ class Exception extends \Phalcon\Exception { diff --git a/phalcon/Tag/Select.zep b/phalcon/Tag/Select.zep index ee455dc2a61..b4cf8d4731b 100644 --- a/phalcon/Tag/Select.zep +++ b/phalcon/Tag/Select.zep @@ -68,7 +68,6 @@ abstract class Select } if fetch useEmpty, params["useEmpty"] { - if !fetch emptyValue, params["emptyValue"] { let emptyValue = ""; } else { @@ -89,7 +88,6 @@ abstract class Select } if typeof options == "object" { - /** * The options is a resultset */ @@ -116,7 +114,6 @@ abstract class Select } if typeof options == "object" { - /** * Create the SELECT's option from a resultset */ @@ -128,7 +125,6 @@ abstract class Select ); } else { if typeof options == "array" { - /** * Create the SELECT's option from an array */ @@ -155,11 +151,11 @@ abstract class Select let code = ""; for optionValue, optionText in data { - let escaped = htmlspecialchars(optionValue); if typeof optionText == "array" { let code .= "\t" . PHP_EOL . self::optionsFromArray(optionText, value, closeOption) . "\t" . PHP_EOL; + continue; } @@ -170,7 +166,6 @@ abstract class Select let code .= "\t