diff --git a/lib/thirdpartylibs.xml b/lib/thirdpartylibs.xml index d560b630485..2eb34700c5c 100644 --- a/lib/thirdpartylibs.xml +++ b/lib/thirdpartylibs.xml @@ -200,7 +200,7 @@ zend Zend Framework BSD - 1.10.6 + 1.12.16 diff --git a/lib/zend/Zend/Acl.php b/lib/zend/Zend/Acl.php new file mode 100644 index 00000000000..a5d169f56ac --- /dev/null +++ b/lib/zend/Zend/Acl.php @@ -0,0 +1,1242 @@ + array( + 'allRoles' => array( + 'allPrivileges' => array( + 'type' => self::TYPE_DENY, + 'assert' => null + ), + 'byPrivilegeId' => array() + ), + 'byRoleId' => array() + ), + 'byResourceId' => array() + ); + + /** + * Adds a Role having an identifier unique to the registry + * + * The $parents parameter may be a reference to, or the string identifier for, + * a Role existing in the registry, or $parents may be passed as an array of + * these - mixing string identifiers and objects is ok - to indicate the Roles + * from which the newly added Role will directly inherit. + * + * In order to resolve potential ambiguities with conflicting rules inherited + * from different parents, the most recently added parent takes precedence over + * parents that were previously added. In other words, the first parent added + * will have the least priority, and the last parent added will have the + * highest priority. + * + * @param Zend_Acl_Role_Interface|string $role + * @param Zend_Acl_Role_Interface|string|array $parents + * @uses Zend_Acl_Role_Registry::add() + * @return Zend_Acl Provides a fluent interface + */ + public function addRole($role, $parents = null) + { + if (is_string($role)) { + $role = new Zend_Acl_Role($role); + } + + if (!$role instanceof Zend_Acl_Role_Interface) { + require_once 'Zend/Acl/Exception.php'; + throw new Zend_Acl_Exception('addRole() expects $role to be of type Zend_Acl_Role_Interface'); + } + + + $this->_getRoleRegistry()->add($role, $parents); + + return $this; + } + + /** + * Returns the identified Role + * + * The $role parameter can either be a Role or Role identifier. + * + * @param Zend_Acl_Role_Interface|string $role + * @uses Zend_Acl_Role_Registry::get() + * @return Zend_Acl_Role_Interface + */ + public function getRole($role) + { + return $this->_getRoleRegistry()->get($role); + } + + /** + * Returns true if and only if the Role exists in the registry + * + * The $role parameter can either be a Role or a Role identifier. + * + * @param Zend_Acl_Role_Interface|string $role + * @uses Zend_Acl_Role_Registry::has() + * @return boolean + */ + public function hasRole($role) + { + return $this->_getRoleRegistry()->has($role); + } + + /** + * Returns true if and only if $role inherits from $inherit + * + * Both parameters may be either a Role or a Role identifier. If + * $onlyParents is true, then $role must inherit directly from + * $inherit in order to return true. By default, this method looks + * through the entire inheritance DAG to determine whether $role + * inherits from $inherit through its ancestor Roles. + * + * @param Zend_Acl_Role_Interface|string $role + * @param Zend_Acl_Role_Interface|string $inherit + * @param boolean $onlyParents + * @uses Zend_Acl_Role_Registry::inherits() + * @return boolean + */ + public function inheritsRole($role, $inherit, $onlyParents = false) + { + return $this->_getRoleRegistry()->inherits($role, $inherit, $onlyParents); + } + + /** + * Removes the Role from the registry + * + * The $role parameter can either be a Role or a Role identifier. + * + * @param Zend_Acl_Role_Interface|string $role + * @uses Zend_Acl_Role_Registry::remove() + * @return Zend_Acl Provides a fluent interface + */ + public function removeRole($role) + { + $this->_getRoleRegistry()->remove($role); + + if ($role instanceof Zend_Acl_Role_Interface) { + $roleId = $role->getRoleId(); + } else { + $roleId = $role; + } + + foreach ($this->_rules['allResources']['byRoleId'] as $roleIdCurrent => $rules) { + if ($roleId === $roleIdCurrent) { + unset($this->_rules['allResources']['byRoleId'][$roleIdCurrent]); + } + } + foreach ($this->_rules['byResourceId'] as $resourceIdCurrent => $visitor) { + if (array_key_exists('byRoleId', $visitor)) { + foreach ($visitor['byRoleId'] as $roleIdCurrent => $rules) { + if ($roleId === $roleIdCurrent) { + unset($this->_rules['byResourceId'][$resourceIdCurrent]['byRoleId'][$roleIdCurrent]); + } + } + } + } + + return $this; + } + + /** + * Removes all Roles from the registry + * + * @uses Zend_Acl_Role_Registry::removeAll() + * @return Zend_Acl Provides a fluent interface + */ + public function removeRoleAll() + { + $this->_getRoleRegistry()->removeAll(); + + foreach ($this->_rules['allResources']['byRoleId'] as $roleIdCurrent => $rules) { + unset($this->_rules['allResources']['byRoleId'][$roleIdCurrent]); + } + foreach ($this->_rules['byResourceId'] as $resourceIdCurrent => $visitor) { + foreach ($visitor['byRoleId'] as $roleIdCurrent => $rules) { + unset($this->_rules['byResourceId'][$resourceIdCurrent]['byRoleId'][$roleIdCurrent]); + } + } + + return $this; + } + + /** + * Adds a Resource having an identifier unique to the ACL + * + * The $parent parameter may be a reference to, or the string identifier for, + * the existing Resource from which the newly added Resource will inherit. + * + * @param Zend_Acl_Resource_Interface|string $resource + * @param Zend_Acl_Resource_Interface|string $parent + * @throws Zend_Acl_Exception + * @return Zend_Acl Provides a fluent interface + */ + public function addResource($resource, $parent = null) + { + if (is_string($resource)) { + $resource = new Zend_Acl_Resource($resource); + } + + if (!$resource instanceof Zend_Acl_Resource_Interface) { + require_once 'Zend/Acl/Exception.php'; + throw new Zend_Acl_Exception('addResource() expects $resource to be of type Zend_Acl_Resource_Interface'); + } + + $resourceId = $resource->getResourceId(); + + if ($this->has($resourceId)) { + require_once 'Zend/Acl/Exception.php'; + throw new Zend_Acl_Exception("Resource id '$resourceId' already exists in the ACL"); + } + + $resourceParent = null; + + if (null !== $parent) { + try { + if ($parent instanceof Zend_Acl_Resource_Interface) { + $resourceParentId = $parent->getResourceId(); + } else { + $resourceParentId = $parent; + } + $resourceParent = $this->get($resourceParentId); + } catch (Zend_Acl_Exception $e) { + require_once 'Zend/Acl/Exception.php'; + throw new Zend_Acl_Exception("Parent Resource id '$resourceParentId' does not exist", 0, $e); + } + $this->_resources[$resourceParentId]['children'][$resourceId] = $resource; + } + + $this->_resources[$resourceId] = array( + 'instance' => $resource, + 'parent' => $resourceParent, + 'children' => array() + ); + + return $this; + } + + /** + * Adds a Resource having an identifier unique to the ACL + * + * The $parent parameter may be a reference to, or the string identifier for, + * the existing Resource from which the newly added Resource will inherit. + * + * @deprecated in version 1.9.1 and will be available till 2.0. New code + * should use addResource() instead. + * + * @param Zend_Acl_Resource_Interface $resource + * @param Zend_Acl_Resource_Interface|string $parent + * @throws Zend_Acl_Exception + * @return Zend_Acl Provides a fluent interface + */ + public function add(Zend_Acl_Resource_Interface $resource, $parent = null) + { + return $this->addResource($resource, $parent); + } + + /** + * Returns the identified Resource + * + * The $resource parameter can either be a Resource or a Resource identifier. + * + * @param Zend_Acl_Resource_Interface|string $resource + * @throws Zend_Acl_Exception + * @return Zend_Acl_Resource_Interface + */ + public function get($resource) + { + if ($resource instanceof Zend_Acl_Resource_Interface) { + $resourceId = $resource->getResourceId(); + } else { + $resourceId = (string) $resource; + } + + if (!$this->has($resource)) { + require_once 'Zend/Acl/Exception.php'; + throw new Zend_Acl_Exception("Resource '$resourceId' not found"); + } + + return $this->_resources[$resourceId]['instance']; + } + + /** + * Returns true if and only if the Resource exists in the ACL + * + * The $resource parameter can either be a Resource or a Resource identifier. + * + * @param Zend_Acl_Resource_Interface|string $resource + * @return boolean + */ + public function has($resource) + { + if ($resource instanceof Zend_Acl_Resource_Interface) { + $resourceId = $resource->getResourceId(); + } else { + $resourceId = (string) $resource; + } + + return isset($this->_resources[$resourceId]); + } + + /** + * Returns true if and only if $resource inherits from $inherit + * + * Both parameters may be either a Resource or a Resource identifier. If + * $onlyParent is true, then $resource must inherit directly from + * $inherit in order to return true. By default, this method looks + * through the entire inheritance tree to determine whether $resource + * inherits from $inherit through its ancestor Resources. + * + * @param Zend_Acl_Resource_Interface|string $resource + * @param Zend_Acl_Resource_Interface|string $inherit + * @param boolean $onlyParent + * @throws Zend_Acl_Resource_Registry_Exception + * @return boolean + */ + public function inherits($resource, $inherit, $onlyParent = false) + { + try { + $resourceId = $this->get($resource)->getResourceId(); + $inheritId = $this->get($inherit)->getResourceId(); + } catch (Zend_Acl_Exception $e) { + require_once 'Zend/Acl/Exception.php'; + throw new Zend_Acl_Exception($e->getMessage(), $e->getCode(), $e); + } + + if (null !== $this->_resources[$resourceId]['parent']) { + $parentId = $this->_resources[$resourceId]['parent']->getResourceId(); + if ($inheritId === $parentId) { + return true; + } else if ($onlyParent) { + return false; + } + } else { + return false; + } + + while (null !== $this->_resources[$parentId]['parent']) { + $parentId = $this->_resources[$parentId]['parent']->getResourceId(); + if ($inheritId === $parentId) { + return true; + } + } + + return false; + } + + /** + * Removes a Resource and all of its children + * + * The $resource parameter can either be a Resource or a Resource identifier. + * + * @param Zend_Acl_Resource_Interface|string $resource + * @throws Zend_Acl_Exception + * @return Zend_Acl Provides a fluent interface + */ + public function remove($resource) + { + try { + $resourceId = $this->get($resource)->getResourceId(); + } catch (Zend_Acl_Exception $e) { + require_once 'Zend/Acl/Exception.php'; + throw new Zend_Acl_Exception($e->getMessage(), $e->getCode(), $e); + } + + $resourcesRemoved = array($resourceId); + if (null !== ($resourceParent = $this->_resources[$resourceId]['parent'])) { + unset($this->_resources[$resourceParent->getResourceId()]['children'][$resourceId]); + } + foreach ($this->_resources[$resourceId]['children'] as $childId => $child) { + $this->remove($childId); + $resourcesRemoved[] = $childId; + } + + foreach ($resourcesRemoved as $resourceIdRemoved) { + foreach ($this->_rules['byResourceId'] as $resourceIdCurrent => $rules) { + if ($resourceIdRemoved === $resourceIdCurrent) { + unset($this->_rules['byResourceId'][$resourceIdCurrent]); + } + } + } + + unset($this->_resources[$resourceId]); + + return $this; + } + + /** + * Removes all Resources + * + * @return Zend_Acl Provides a fluent interface + */ + public function removeAll() + { + foreach ($this->_resources as $resourceId => $resource) { + foreach ($this->_rules['byResourceId'] as $resourceIdCurrent => $rules) { + if ($resourceId === $resourceIdCurrent) { + unset($this->_rules['byResourceId'][$resourceIdCurrent]); + } + } + } + + $this->_resources = array(); + + return $this; + } + + /** + * Adds an "allow" rule to the ACL + * + * @param Zend_Acl_Role_Interface|string|array $roles + * @param Zend_Acl_Resource_Interface|string|array $resources + * @param string|array $privileges + * @param Zend_Acl_Assert_Interface $assert + * @uses Zend_Acl::setRule() + * @return Zend_Acl Provides a fluent interface + */ + public function allow($roles = null, $resources = null, $privileges = null, Zend_Acl_Assert_Interface $assert = null) + { + return $this->setRule(self::OP_ADD, self::TYPE_ALLOW, $roles, $resources, $privileges, $assert); + } + + /** + * Adds a "deny" rule to the ACL + * + * @param Zend_Acl_Role_Interface|string|array $roles + * @param Zend_Acl_Resource_Interface|string|array $resources + * @param string|array $privileges + * @param Zend_Acl_Assert_Interface $assert + * @uses Zend_Acl::setRule() + * @return Zend_Acl Provides a fluent interface + */ + public function deny($roles = null, $resources = null, $privileges = null, Zend_Acl_Assert_Interface $assert = null) + { + return $this->setRule(self::OP_ADD, self::TYPE_DENY, $roles, $resources, $privileges, $assert); + } + + /** + * Removes "allow" permissions from the ACL + * + * @param Zend_Acl_Role_Interface|string|array $roles + * @param Zend_Acl_Resource_Interface|string|array $resources + * @param string|array $privileges + * @uses Zend_Acl::setRule() + * @return Zend_Acl Provides a fluent interface + */ + public function removeAllow($roles = null, $resources = null, $privileges = null) + { + return $this->setRule(self::OP_REMOVE, self::TYPE_ALLOW, $roles, $resources, $privileges); + } + + /** + * Removes "deny" restrictions from the ACL + * + * @param Zend_Acl_Role_Interface|string|array $roles + * @param Zend_Acl_Resource_Interface|string|array $resources + * @param string|array $privileges + * @uses Zend_Acl::setRule() + * @return Zend_Acl Provides a fluent interface + */ + public function removeDeny($roles = null, $resources = null, $privileges = null) + { + return $this->setRule(self::OP_REMOVE, self::TYPE_DENY, $roles, $resources, $privileges); + } + + /** + * Performs operations on ACL rules + * + * The $operation parameter may be either OP_ADD or OP_REMOVE, depending on whether the + * user wants to add or remove a rule, respectively: + * + * OP_ADD specifics: + * + * A rule is added that would allow one or more Roles access to [certain $privileges + * upon] the specified Resource(s). + * + * OP_REMOVE specifics: + * + * The rule is removed only in the context of the given Roles, Resources, and privileges. + * Existing rules to which the remove operation does not apply would remain in the + * ACL. + * + * The $type parameter may be either TYPE_ALLOW or TYPE_DENY, depending on whether the + * rule is intended to allow or deny permission, respectively. + * + * The $roles and $resources parameters may be references to, or the string identifiers for, + * existing Resources/Roles, or they may be passed as arrays of these - mixing string identifiers + * and objects is ok - to indicate the Resources and Roles to which the rule applies. If either + * $roles or $resources is null, then the rule applies to all Roles or all Resources, respectively. + * Both may be null in order to work with the default rule of the ACL. + * + * The $privileges parameter may be used to further specify that the rule applies only + * to certain privileges upon the Resource(s) in question. This may be specified to be a single + * privilege with a string, and multiple privileges may be specified as an array of strings. + * + * If $assert is provided, then its assert() method must return true in order for + * the rule to apply. If $assert is provided with $roles, $resources, and $privileges all + * equal to null, then a rule having a type of: + * + * TYPE_ALLOW will imply a type of TYPE_DENY, and + * + * TYPE_DENY will imply a type of TYPE_ALLOW + * + * when the rule's assertion fails. This is because the ACL needs to provide expected + * behavior when an assertion upon the default ACL rule fails. + * + * @param string $operation + * @param string $type + * @param Zend_Acl_Role_Interface|string|array $roles + * @param Zend_Acl_Resource_Interface|string|array $resources + * @param string|array $privileges + * @param Zend_Acl_Assert_Interface $assert + * @throws Zend_Acl_Exception + * @uses Zend_Acl_Role_Registry::get() + * @uses Zend_Acl::get() + * @return Zend_Acl Provides a fluent interface + */ + public function setRule($operation, $type, $roles = null, $resources = null, $privileges = null, + Zend_Acl_Assert_Interface $assert = null) + { + // ensure that the rule type is valid; normalize input to uppercase + $type = strtoupper($type); + if (self::TYPE_ALLOW !== $type && self::TYPE_DENY !== $type) { + require_once 'Zend/Acl/Exception.php'; + throw new Zend_Acl_Exception("Unsupported rule type; must be either '" . self::TYPE_ALLOW . "' or '" + . self::TYPE_DENY . "'"); + } + + // ensure that all specified Roles exist; normalize input to array of Role objects or null + if (!is_array($roles)) { + $roles = array($roles); + } else if (0 === count($roles)) { + $roles = array(null); + } + $rolesTemp = $roles; + $roles = array(); + foreach ($rolesTemp as $role) { + if (null !== $role) { + $roles[] = $this->_getRoleRegistry()->get($role); + } else { + $roles[] = null; + } + } + unset($rolesTemp); + + // ensure that all specified Resources exist; normalize input to array of Resource objects or null + if ($resources !== null) { + if (!is_array($resources)) { + $resources = array($resources); + } else if (0 === count($resources)) { + $resources = array(null); + } + $resourcesTemp = $resources; + $resources = array(); + foreach ($resourcesTemp as $resource) { + if (null !== $resource) { + $resources[] = $this->get($resource); + } else { + $resources[] = null; + } + } + unset($resourcesTemp, $resource); + } else { + $allResources = array(); // this might be used later if resource iteration is required + foreach ($this->_resources as $rTarget) { + $allResources[] = $rTarget['instance']; + } + unset($rTarget); + } + + // normalize privileges to array + if (null === $privileges) { + $privileges = array(); + } else if (!is_array($privileges)) { + $privileges = array($privileges); + } + + switch ($operation) { + + // add to the rules + case self::OP_ADD: + if ($resources !== null) { + // this block will iterate the provided resources + foreach ($resources as $resource) { + foreach ($roles as $role) { + $rules =& $this->_getRules($resource, $role, true); + if (0 === count($privileges)) { + $rules['allPrivileges']['type'] = $type; + $rules['allPrivileges']['assert'] = $assert; + if (!isset($rules['byPrivilegeId'])) { + $rules['byPrivilegeId'] = array(); + } + } else { + foreach ($privileges as $privilege) { + $rules['byPrivilegeId'][$privilege]['type'] = $type; + $rules['byPrivilegeId'][$privilege]['assert'] = $assert; + } + } + } + } + } else { + // this block will apply to all resources in a global rule + foreach ($roles as $role) { + $rules =& $this->_getRules(null, $role, true); + if (0 === count($privileges)) { + $rules['allPrivileges']['type'] = $type; + $rules['allPrivileges']['assert'] = $assert; + } else { + foreach ($privileges as $privilege) { + $rules['byPrivilegeId'][$privilege]['type'] = $type; + $rules['byPrivilegeId'][$privilege]['assert'] = $assert; + } + } + } + } + break; + + // remove from the rules + case self::OP_REMOVE: + if ($resources !== null) { + // this block will iterate the provided resources + foreach ($resources as $resource) { + foreach ($roles as $role) { + $rules =& $this->_getRules($resource, $role); + if (null === $rules) { + continue; + } + if (0 === count($privileges)) { + if (null === $resource && null === $role) { + if ($type === $rules['allPrivileges']['type']) { + $rules = array( + 'allPrivileges' => array( + 'type' => self::TYPE_DENY, + 'assert' => null + ), + 'byPrivilegeId' => array() + ); + } + continue; + } + + if (isset($rules['allPrivileges']['type']) && + $type === $rules['allPrivileges']['type']) + { + unset($rules['allPrivileges']); + } + } else { + foreach ($privileges as $privilege) { + if (isset($rules['byPrivilegeId'][$privilege]) && + $type === $rules['byPrivilegeId'][$privilege]['type']) + { + unset($rules['byPrivilegeId'][$privilege]); + } + } + } + } + } + } else { + // this block will apply to all resources in a global rule + foreach ($roles as $role) { + /** + * since null (all resources) was passed to this setRule() call, we need + * clean up all the rules for the global allResources, as well as the indivually + * set resources (per privilege as well) + */ + foreach (array_merge(array(null), $allResources) as $resource) { + $rules =& $this->_getRules($resource, $role, true); + if (null === $rules) { + continue; + } + if (0 === count($privileges)) { + if (null === $role) { + if ($type === $rules['allPrivileges']['type']) { + $rules = array( + 'allPrivileges' => array( + 'type' => self::TYPE_DENY, + 'assert' => null + ), + 'byPrivilegeId' => array() + ); + } + continue; + } + + if (isset($rules['allPrivileges']['type']) && $type === $rules['allPrivileges']['type']) { + unset($rules['allPrivileges']); + } + } else { + foreach ($privileges as $privilege) { + if (isset($rules['byPrivilegeId'][$privilege]) && + $type === $rules['byPrivilegeId'][$privilege]['type']) + { + unset($rules['byPrivilegeId'][$privilege]); + } + } + } + } + } + } + break; + + default: + require_once 'Zend/Acl/Exception.php'; + throw new Zend_Acl_Exception("Unsupported operation; must be either '" . self::OP_ADD . "' or '" + . self::OP_REMOVE . "'"); + } + + return $this; + } + + /** + * Returns true if and only if the Role has access to the Resource + * + * The $role and $resource parameters may be references to, or the string identifiers for, + * an existing Resource and Role combination. + * + * If either $role or $resource is null, then the query applies to all Roles or all Resources, + * respectively. Both may be null to query whether the ACL has a "blacklist" rule + * (allow everything to all). By default, Zend_Acl creates a "whitelist" rule (deny + * everything to all), and this method would return false unless this default has + * been overridden (i.e., by executing $acl->allow()). + * + * If a $privilege is not provided, then this method returns false if and only if the + * Role is denied access to at least one privilege upon the Resource. In other words, this + * method returns true if and only if the Role is allowed all privileges on the Resource. + * + * This method checks Role inheritance using a depth-first traversal of the Role registry. + * The highest priority parent (i.e., the parent most recently added) is checked first, + * and its respective parents are checked similarly before the lower-priority parents of + * the Role are checked. + * + * @param Zend_Acl_Role_Interface|string $role + * @param Zend_Acl_Resource_Interface|string $resource + * @param string $privilege + * @uses Zend_Acl::get() + * @uses Zend_Acl_Role_Registry::get() + * @return boolean + */ + public function isAllowed($role = null, $resource = null, $privilege = null) + { + // reset role & resource to null + $this->_isAllowedRole = null; + $this->_isAllowedResource = null; + $this->_isAllowedPrivilege = null; + + if (null !== $role) { + // keep track of originally called role + $this->_isAllowedRole = $role; + $role = $this->_getRoleRegistry()->get($role); + if (!$this->_isAllowedRole instanceof Zend_Acl_Role_Interface) { + $this->_isAllowedRole = $role; + } + } + + if (null !== $resource) { + // keep track of originally called resource + $this->_isAllowedResource = $resource; + $resource = $this->get($resource); + if (!$this->_isAllowedResource instanceof Zend_Acl_Resource_Interface) { + $this->_isAllowedResource = $resource; + } + } + + if (null === $privilege) { + // query on all privileges + do { + // depth-first search on $role if it is not 'allRoles' pseudo-parent + if (null !== $role && null !== ($result = $this->_roleDFSAllPrivileges($role, $resource, $privilege))) { + return $result; + } + + // look for rule on 'allRoles' psuedo-parent + if (null !== ($rules = $this->_getRules($resource, null))) { + foreach ($rules['byPrivilegeId'] as $privilege => $rule) { + if (self::TYPE_DENY === ($ruleTypeOnePrivilege = $this->_getRuleType($resource, null, $privilege))) { + return false; + } + } + if (null !== ($ruleTypeAllPrivileges = $this->_getRuleType($resource, null, null))) { + return self::TYPE_ALLOW === $ruleTypeAllPrivileges; + } + } + + // try next Resource + $resource = $this->_resources[$resource->getResourceId()]['parent']; + + } while (true); // loop terminates at 'allResources' pseudo-parent + } else { + $this->_isAllowedPrivilege = $privilege; + // query on one privilege + do { + // depth-first search on $role if it is not 'allRoles' pseudo-parent + if (null !== $role && null !== ($result = $this->_roleDFSOnePrivilege($role, $resource, $privilege))) { + return $result; + } + + // look for rule on 'allRoles' pseudo-parent + if (null !== ($ruleType = $this->_getRuleType($resource, null, $privilege))) { + return self::TYPE_ALLOW === $ruleType; + } else if (null !== ($ruleTypeAllPrivileges = $this->_getRuleType($resource, null, null))) { + return self::TYPE_ALLOW === $ruleTypeAllPrivileges; + } + + // try next Resource + $resource = $this->_resources[$resource->getResourceId()]['parent']; + + } while (true); // loop terminates at 'allResources' pseudo-parent + } + } + + /** + * Returns the Role registry for this ACL + * + * If no Role registry has been created yet, a new default Role registry + * is created and returned. + * + * @return Zend_Acl_Role_Registry + */ + protected function _getRoleRegistry() + { + if (null === $this->_roleRegistry) { + $this->_roleRegistry = new Zend_Acl_Role_Registry(); + } + return $this->_roleRegistry; + } + + /** + * Performs a depth-first search of the Role DAG, starting at $role, in order to find a rule + * allowing/denying $role access to all privileges upon $resource + * + * This method returns true if a rule is found and allows access. If a rule exists and denies access, + * then this method returns false. If no applicable rule is found, then this method returns null. + * + * @param Zend_Acl_Role_Interface $role + * @param Zend_Acl_Resource_Interface $resource + * @return boolean|null + */ + protected function _roleDFSAllPrivileges(Zend_Acl_Role_Interface $role, Zend_Acl_Resource_Interface $resource = null) + { + $dfs = array( + 'visited' => array(), + 'stack' => array() + ); + + if (null !== ($result = $this->_roleDFSVisitAllPrivileges($role, $resource, $dfs))) { + return $result; + } + + while (null !== ($role = array_pop($dfs['stack']))) { + if (!isset($dfs['visited'][$role->getRoleId()])) { + if (null !== ($result = $this->_roleDFSVisitAllPrivileges($role, $resource, $dfs))) { + return $result; + } + } + } + + return null; + } + + /** + * Visits an $role in order to look for a rule allowing/denying $role access to all privileges upon $resource + * + * This method returns true if a rule is found and allows access. If a rule exists and denies access, + * then this method returns false. If no applicable rule is found, then this method returns null. + * + * This method is used by the internal depth-first search algorithm and may modify the DFS data structure. + * + * @param Zend_Acl_Role_Interface $role + * @param Zend_Acl_Resource_Interface $resource + * @param array $dfs + * @return boolean|null + * @throws Zend_Acl_Exception + */ + protected function _roleDFSVisitAllPrivileges(Zend_Acl_Role_Interface $role, Zend_Acl_Resource_Interface $resource = null, + &$dfs = null) + { + if (null === $dfs) { + /** + * @see Zend_Acl_Exception + */ + require_once 'Zend/Acl/Exception.php'; + throw new Zend_Acl_Exception('$dfs parameter may not be null'); + } + + if (null !== ($rules = $this->_getRules($resource, $role))) { + foreach ($rules['byPrivilegeId'] as $privilege => $rule) { + if (self::TYPE_DENY === ($ruleTypeOnePrivilege = $this->_getRuleType($resource, $role, $privilege))) { + return false; + } + } + if (null !== ($ruleTypeAllPrivileges = $this->_getRuleType($resource, $role, null))) { + return self::TYPE_ALLOW === $ruleTypeAllPrivileges; + } + } + + $dfs['visited'][$role->getRoleId()] = true; + foreach ($this->_getRoleRegistry()->getParents($role) as $roleParentId => $roleParent) { + $dfs['stack'][] = $roleParent; + } + + return null; + } + + /** + * Performs a depth-first search of the Role DAG, starting at $role, in order to find a rule + * allowing/denying $role access to a $privilege upon $resource + * + * This method returns true if a rule is found and allows access. If a rule exists and denies access, + * then this method returns false. If no applicable rule is found, then this method returns null. + * + * @param Zend_Acl_Role_Interface $role + * @param Zend_Acl_Resource_Interface $resource + * @param string $privilege + * @return boolean|null + * @throws Zend_Acl_Exception + */ + protected function _roleDFSOnePrivilege(Zend_Acl_Role_Interface $role, Zend_Acl_Resource_Interface $resource = null, + $privilege = null) + { + if (null === $privilege) { + /** + * @see Zend_Acl_Exception + */ + require_once 'Zend/Acl/Exception.php'; + throw new Zend_Acl_Exception('$privilege parameter may not be null'); + } + + $dfs = array( + 'visited' => array(), + 'stack' => array() + ); + + if (null !== ($result = $this->_roleDFSVisitOnePrivilege($role, $resource, $privilege, $dfs))) { + return $result; + } + + while (null !== ($role = array_pop($dfs['stack']))) { + if (!isset($dfs['visited'][$role->getRoleId()])) { + if (null !== ($result = $this->_roleDFSVisitOnePrivilege($role, $resource, $privilege, $dfs))) { + return $result; + } + } + } + + return null; + } + + /** + * Visits an $role in order to look for a rule allowing/denying $role access to a $privilege upon $resource + * + * This method returns true if a rule is found and allows access. If a rule exists and denies access, + * then this method returns false. If no applicable rule is found, then this method returns null. + * + * This method is used by the internal depth-first search algorithm and may modify the DFS data structure. + * + * @param Zend_Acl_Role_Interface $role + * @param Zend_Acl_Resource_Interface $resource + * @param string $privilege + * @param array $dfs + * @return boolean|null + * @throws Zend_Acl_Exception + */ + protected function _roleDFSVisitOnePrivilege(Zend_Acl_Role_Interface $role, Zend_Acl_Resource_Interface $resource = null, + $privilege = null, &$dfs = null) + { + if (null === $privilege) { + /** + * @see Zend_Acl_Exception + */ + require_once 'Zend/Acl/Exception.php'; + throw new Zend_Acl_Exception('$privilege parameter may not be null'); + } + + if (null === $dfs) { + /** + * @see Zend_Acl_Exception + */ + require_once 'Zend/Acl/Exception.php'; + throw new Zend_Acl_Exception('$dfs parameter may not be null'); + } + + if (null !== ($ruleTypeOnePrivilege = $this->_getRuleType($resource, $role, $privilege))) { + return self::TYPE_ALLOW === $ruleTypeOnePrivilege; + } else if (null !== ($ruleTypeAllPrivileges = $this->_getRuleType($resource, $role, null))) { + return self::TYPE_ALLOW === $ruleTypeAllPrivileges; + } + + $dfs['visited'][$role->getRoleId()] = true; + foreach ($this->_getRoleRegistry()->getParents($role) as $roleParentId => $roleParent) { + $dfs['stack'][] = $roleParent; + } + + return null; + } + + /** + * Returns the rule type associated with the specified Resource, Role, and privilege + * combination. + * + * If a rule does not exist or its attached assertion fails, which means that + * the rule is not applicable, then this method returns null. Otherwise, the + * rule type applies and is returned as either TYPE_ALLOW or TYPE_DENY. + * + * If $resource or $role is null, then this means that the rule must apply to + * all Resources or Roles, respectively. + * + * If $privilege is null, then the rule must apply to all privileges. + * + * If all three parameters are null, then the default ACL rule type is returned, + * based on whether its assertion method passes. + * + * @param Zend_Acl_Resource_Interface $resource + * @param Zend_Acl_Role_Interface $role + * @param string $privilege + * @return string|null + */ + protected function _getRuleType(Zend_Acl_Resource_Interface $resource = null, Zend_Acl_Role_Interface $role = null, + $privilege = null) + { + // get the rules for the $resource and $role + if (null === ($rules = $this->_getRules($resource, $role))) { + return null; + } + + // follow $privilege + if (null === $privilege) { + if (isset($rules['allPrivileges'])) { + $rule = $rules['allPrivileges']; + } else { + return null; + } + } else if (!isset($rules['byPrivilegeId'][$privilege])) { + return null; + } else { + $rule = $rules['byPrivilegeId'][$privilege]; + } + + // check assertion first + if ($rule['assert']) { + $assertion = $rule['assert']; + $assertionValue = $assertion->assert( + $this, + ($this->_isAllowedRole instanceof Zend_Acl_Role_Interface) ? $this->_isAllowedRole : $role, + ($this->_isAllowedResource instanceof Zend_Acl_Resource_Interface) ? $this->_isAllowedResource : $resource, + $this->_isAllowedPrivilege + ); + } + + if (null === $rule['assert'] || $assertionValue) { + return $rule['type']; + } else if (null !== $resource || null !== $role || null !== $privilege) { + return null; + } else if (self::TYPE_ALLOW === $rule['type']) { + return self::TYPE_DENY; + } else { + return self::TYPE_ALLOW; + } + } + + /** + * Returns the rules associated with a Resource and a Role, or null if no such rules exist + * + * If either $resource or $role is null, this means that the rules returned are for all Resources or all Roles, + * respectively. Both can be null to return the default rule set for all Resources and all Roles. + * + * If the $create parameter is true, then a rule set is first created and then returned to the caller. + * + * @param Zend_Acl_Resource_Interface $resource + * @param Zend_Acl_Role_Interface $role + * @param boolean $create + * @return array|null + */ + protected function &_getRules(Zend_Acl_Resource_Interface $resource = null, Zend_Acl_Role_Interface $role = null, + $create = false) + { + // create a reference to null + $null = null; + $nullRef =& $null; + + // follow $resource + do { + if (null === $resource) { + $visitor =& $this->_rules['allResources']; + break; + } + $resourceId = $resource->getResourceId(); + if (!isset($this->_rules['byResourceId'][$resourceId])) { + if (!$create) { + return $nullRef; + } + $this->_rules['byResourceId'][$resourceId] = array(); + } + $visitor =& $this->_rules['byResourceId'][$resourceId]; + } while (false); + + + // follow $role + if (null === $role) { + if (!isset($visitor['allRoles'])) { + if (!$create) { + return $nullRef; + } + $visitor['allRoles']['byPrivilegeId'] = array(); + } + return $visitor['allRoles']; + } + $roleId = $role->getRoleId(); + if (!isset($visitor['byRoleId'][$roleId])) { + if (!$create) { + return $nullRef; + } + $visitor['byRoleId'][$roleId]['byPrivilegeId'] = array(); + $visitor['byRoleId'][$roleId]['allPrivileges'] = array('type' => null, 'assert' => null); + } + return $visitor['byRoleId'][$roleId]; + } + + + /** + * @return array of registered roles (Deprecated) + * @deprecated Deprecated since version 1.10 (December 2009) + */ + public function getRegisteredRoles() + { + trigger_error('The method getRegisteredRoles() was deprecated as of ' + . 'version 1.0, and may be removed. You\'re encouraged ' + . 'to use getRoles() instead.'); + + return $this->_getRoleRegistry()->getRoles(); + } + + /** + * Returns an array of registered roles. + * + * Note that this method does not return instances of registered roles, + * but only the role identifiers. + * + * @return array of registered roles + */ + public function getRoles() + { + return array_keys($this->_getRoleRegistry()->getRoles()); + } + + /** + * @return array of registered resources + */ + public function getResources() + { + return array_keys($this->_resources); + } + +} + diff --git a/lib/zend/Zend/Acl/Assert/Interface.php b/lib/zend/Zend/Acl/Assert/Interface.php new file mode 100644 index 00000000000..e3d02565fc6 --- /dev/null +++ b/lib/zend/Zend/Acl/Assert/Interface.php @@ -0,0 +1,64 @@ +countryCode; + $this->_resourceId = (string) $resourceId; } /** + * Defined by Zend_Acl_Resource_Interface; returns the Resource identifier + * * @return string */ - public function getCityCode() + public function getResourceId() { - return $this->cityCode; + return $this->_resourceId; } /** + * Defined by Zend_Acl_Resource_Interface; returns the Resource identifier + * Proxies to getResourceId() + * * @return string */ - public function getCityName() + public function __toString() { - return $this->cityName; + return $this->getResourceId(); } } diff --git a/lib/zend/Zend/Acl/Resource/Interface.php b/lib/zend/Zend/Acl/Resource/Interface.php new file mode 100644 index 00000000000..dcf10586d51 --- /dev/null +++ b/lib/zend/Zend/Acl/Resource/Interface.php @@ -0,0 +1,37 @@ +return->sessionId)) { - return $this->return->sessionId; - } - return null; + $this->_roleId = (string) $roleId; } /** - * prints the session on casting to string + * Defined by Zend_Acl_Role_Interface; returns the Role identifier + * + * @return string + */ + public function getRoleId() + { + return $this->_roleId; + } + + /** + * Defined by Zend_Acl_Role_Interface; returns the Role identifier + * Proxies to getRoleId() * * @return string */ public function __toString() { - return $this->getSessionId(); + return $this->getRoleId(); } } diff --git a/lib/zend/Zend/Acl/Role/Interface.php b/lib/zend/Zend/Acl/Role/Interface.php new file mode 100644 index 00000000000..e2510003ce5 --- /dev/null +++ b/lib/zend/Zend/Acl/Role/Interface.php @@ -0,0 +1,37 @@ +getRoleId(); + + if ($this->has($roleId)) { + /** + * @see Zend_Acl_Role_Registry_Exception + */ + require_once 'Zend/Acl/Role/Registry/Exception.php'; + throw new Zend_Acl_Role_Registry_Exception("Role id '$roleId' already exists in the registry"); + } + + $roleParents = array(); + + if (null !== $parents) { + if (!is_array($parents)) { + $parents = array($parents); + } + /** + * @see Zend_Acl_Role_Registry_Exception + */ + require_once 'Zend/Acl/Role/Registry/Exception.php'; + foreach ($parents as $parent) { + try { + if ($parent instanceof Zend_Acl_Role_Interface) { + $roleParentId = $parent->getRoleId(); + } else { + $roleParentId = $parent; + } + $roleParent = $this->get($roleParentId); + } catch (Zend_Acl_Role_Registry_Exception $e) { + throw new Zend_Acl_Role_Registry_Exception("Parent Role id '$roleParentId' does not exist", 0, $e); + } + $roleParents[$roleParentId] = $roleParent; + $this->_roles[$roleParentId]['children'][$roleId] = $role; + } + } + + $this->_roles[$roleId] = array( + 'instance' => $role, + 'parents' => $roleParents, + 'children' => array() + ); + + return $this; + } + + /** + * Returns the identified Role + * + * The $role parameter can either be a Role or a Role identifier. + * + * @param Zend_Acl_Role_Interface|string $role + * @throws Zend_Acl_Role_Registry_Exception + * @return Zend_Acl_Role_Interface + */ + public function get($role) + { + if ($role instanceof Zend_Acl_Role_Interface) { + $roleId = $role->getRoleId(); + } else { + $roleId = (string) $role; + } + + if (!$this->has($role)) { + /** + * @see Zend_Acl_Role_Registry_Exception + */ + require_once 'Zend/Acl/Role/Registry/Exception.php'; + throw new Zend_Acl_Role_Registry_Exception("Role '$roleId' not found"); + } + + return $this->_roles[$roleId]['instance']; + } + + /** + * Returns true if and only if the Role exists in the registry + * + * The $role parameter can either be a Role or a Role identifier. + * + * @param Zend_Acl_Role_Interface|string $role + * @return boolean + */ + public function has($role) + { + if ($role instanceof Zend_Acl_Role_Interface) { + $roleId = $role->getRoleId(); + } else { + $roleId = (string) $role; + } + + return isset($this->_roles[$roleId]); + } + + /** + * Returns an array of an existing Role's parents + * + * The array keys are the identifiers of the parent Roles, and the values are + * the parent Role instances. The parent Roles are ordered in this array by + * ascending priority. The highest priority parent Role, last in the array, + * corresponds with the parent Role most recently added. + * + * If the Role does not have any parents, then an empty array is returned. + * + * @param Zend_Acl_Role_Interface|string $role + * @uses Zend_Acl_Role_Registry::get() + * @return array + */ + public function getParents($role) + { + $roleId = $this->get($role)->getRoleId(); + + return $this->_roles[$roleId]['parents']; + } + + /** + * Returns true if and only if $role inherits from $inherit + * + * Both parameters may be either a Role or a Role identifier. If + * $onlyParents is true, then $role must inherit directly from + * $inherit in order to return true. By default, this method looks + * through the entire inheritance DAG to determine whether $role + * inherits from $inherit through its ancestor Roles. + * + * @param Zend_Acl_Role_Interface|string $role + * @param Zend_Acl_Role_Interface|string $inherit + * @param boolean $onlyParents + * @throws Zend_Acl_Role_Registry_Exception + * @return boolean + */ + public function inherits($role, $inherit, $onlyParents = false) + { + /** + * @see Zend_Acl_Role_Registry_Exception + */ + require_once 'Zend/Acl/Role/Registry/Exception.php'; + try { + $roleId = $this->get($role)->getRoleId(); + $inheritId = $this->get($inherit)->getRoleId(); + } catch (Zend_Acl_Role_Registry_Exception $e) { + throw new Zend_Acl_Role_Registry_Exception($e->getMessage(), $e->getCode(), $e); + } + + $inherits = isset($this->_roles[$roleId]['parents'][$inheritId]); + + if ($inherits || $onlyParents) { + return $inherits; + } + + foreach ($this->_roles[$roleId]['parents'] as $parentId => $parent) { + if ($this->inherits($parentId, $inheritId)) { + return true; + } + } + + return false; + } + + /** + * Removes the Role from the registry + * + * The $role parameter can either be a Role or a Role identifier. + * + * @param Zend_Acl_Role_Interface|string $role + * @throws Zend_Acl_Role_Registry_Exception + * @return Zend_Acl_Role_Registry Provides a fluent interface + */ + public function remove($role) + { + /** + * @see Zend_Acl_Role_Registry_Exception + */ + require_once 'Zend/Acl/Role/Registry/Exception.php'; + try { + $roleId = $this->get($role)->getRoleId(); + } catch (Zend_Acl_Role_Registry_Exception $e) { + throw new Zend_Acl_Role_Registry_Exception($e->getMessage(), $e->getCode(), $e); + } + + foreach ($this->_roles[$roleId]['children'] as $childId => $child) { + unset($this->_roles[$childId]['parents'][$roleId]); + } + foreach ($this->_roles[$roleId]['parents'] as $parentId => $parent) { + unset($this->_roles[$parentId]['children'][$roleId]); + } + + unset($this->_roles[$roleId]); + + return $this; + } + + /** + * Removes all Roles from the registry + * + * @return Zend_Acl_Role_Registry Provides a fluent interface + */ + public function removeAll() + { + $this->_roles = array(); + + return $this; + } + + public function getRoles() + { + return $this->_roles; + } + +} diff --git a/lib/zend/Zend/Acl/Role/Registry/Exception.php b/lib/zend/Zend/Acl/Role/Registry/Exception.php new file mode 100644 index 00000000000..a2e906a98a2 --- /dev/null +++ b/lib/zend/Zend/Acl/Role/Registry/Exception.php @@ -0,0 +1,36 @@ +_acl = new Zend_Acl(); - $xml = simplexml_load_file($rolefile); + $xml = Zend_Xml_Security::scanFile($rolefile); /* Roles file format: diff --git a/lib/zend/Zend/Amf/Adobe/DbInspector.php b/lib/zend/Zend/Amf/Adobe/DbInspector.php old mode 100644 new mode 100755 index d756787ad6f..a25c3a2b165 --- a/lib/zend/Zend/Amf/Adobe/DbInspector.php +++ b/lib/zend/Zend/Amf/Adobe/DbInspector.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Amf - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -24,7 +24,7 @@ * * @package Zend_Amf * @subpackage Adobe - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Amf_Adobe_DbInspector diff --git a/lib/zend/Zend/Amf/Adobe/Introspector.php b/lib/zend/Zend/Amf/Adobe/Introspector.php old mode 100644 new mode 100755 index f746e38f470..3eb76c490cc --- a/lib/zend/Zend/Amf/Adobe/Introspector.php +++ b/lib/zend/Zend/Amf/Adobe/Introspector.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Amf - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -33,7 +33,7 @@ require_once 'Zend/Server/Reflection.php'; * * @package Zend_Amf * @subpackage Adobe - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Amf_Adobe_Introspector @@ -283,7 +283,12 @@ class Zend_Amf_Adobe_Introspector return 'Unknown'; } - if (in_array($typename, array('int', 'integer', 'bool', 'boolean', 'float', 'string', 'object', 'Unknown', 'stdClass', 'array'))) { + // Arrays + if ('array' == $typename) { + return 'Unknown[]'; + } + + if (in_array($typename, array('int', 'integer', 'bool', 'boolean', 'float', 'string', 'object', 'Unknown', 'stdClass'))) { return $typename; } diff --git a/lib/zend/Zend/Amf/Auth/Abstract.php b/lib/zend/Zend/Amf/Auth/Abstract.php old mode 100644 new mode 100755 index 617d2b412c4..180568d3fcc --- a/lib/zend/Zend/Amf/Auth/Abstract.php +++ b/lib/zend/Zend/Amf/Auth/Abstract.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Amf - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Auth/Adapter/Interface.php'; * * @package Zend_Amf * @subpackage Auth - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ abstract class Zend_Amf_Auth_Abstract implements Zend_Auth_Adapter_Interface diff --git a/lib/zend/Zend/Amf/Constants.php b/lib/zend/Zend/Amf/Constants.php index 4cf60025a1a..723d8ba4fd3 100644 --- a/lib/zend/Zend/Amf/Constants.php +++ b/lib/zend/Zend/Amf/Constants.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Amf - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -24,7 +24,7 @@ * deserialization to detect the AMF marker and encoding types. * * @package Zend_Amf - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ final class Zend_Amf_Constants diff --git a/lib/zend/Zend/Amf/Exception.php b/lib/zend/Zend/Amf/Exception.php index fa45da335d5..5738cdd95d3 100644 --- a/lib/zend/Zend/Amf/Exception.php +++ b/lib/zend/Zend/Amf/Exception.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Amf - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -26,7 +26,7 @@ require_once 'Zend/Exception.php'; /** * @package Zend_Amf - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Amf_Exception extends Zend_Exception diff --git a/lib/zend/Zend/Amf/Parse/Amf0/Deserializer.php b/lib/zend/Zend/Amf/Parse/Amf0/Deserializer.php index e80492d6b16..6d8fa7f55d9 100644 --- a/lib/zend/Zend/Amf/Parse/Amf0/Deserializer.php +++ b/lib/zend/Zend/Amf/Parse/Amf0/Deserializer.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Amf * @subpackage Parse_Amf0 - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -23,6 +23,9 @@ /** Zend_Amf_Constants */ require_once 'Zend/Amf/Constants.php'; +/** Zend_Xml_Security */ +require_once 'Zend/Xml/Security.php'; + /** @see Zend_Amf_Parse_Deserializer */ require_once 'Zend/Amf/Parse/Deserializer.php'; @@ -33,7 +36,7 @@ require_once 'Zend/Amf/Parse/Deserializer.php'; * @todo Class could be implemented as Factory Class with each data type it's own class * @package Zend_Amf * @subpackage Parse_Amf0 - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Amf_Parse_Amf0_Deserializer extends Zend_Amf_Parse_Deserializer @@ -248,7 +251,7 @@ class Zend_Amf_Parse_Amf0_Deserializer extends Zend_Amf_Parse_Deserializer public function readXmlString() { $string = $this->_stream->readLongUTF(); - return simplexml_load_string($string); + return Zend_Xml_Security::scan($string); //simplexml_load_string($string); } /** diff --git a/lib/zend/Zend/Amf/Parse/Amf0/Serializer.php b/lib/zend/Zend/Amf/Parse/Amf0/Serializer.php index 9ecc352b8e5..0a578c12911 100644 --- a/lib/zend/Zend/Amf/Parse/Amf0/Serializer.php +++ b/lib/zend/Zend/Amf/Parse/Amf0/Serializer.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Amf * @subpackage Parse_Amf0 - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -32,7 +32,7 @@ require_once 'Zend/Amf/Parse/Serializer.php'; * @uses Zend_Amf_Parse_Serializer * @package Zend_Amf * @subpackage Parse_Amf0 - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Amf_Parse_Amf0_Serializer extends Zend_Amf_Parse_Serializer @@ -63,8 +63,8 @@ class Zend_Amf_Parse_Amf0_Serializer extends Zend_Amf_Parse_Serializer */ public function writeTypeMarker(&$data, $markerType = null, $dataByVal = false) { - // Workaround for PHP5 with E_STRICT enabled complaining about "Only - // variables should be passed by reference" + // Workaround for PHP5 with E_STRICT enabled complaining about "Only + // variables should be passed by reference" if ((null === $data) && ($dataByVal !== false)) { $data = &$dataByVal; } @@ -127,7 +127,7 @@ class Zend_Amf_Parse_Amf0_Serializer extends Zend_Amf_Parse_Serializer case (is_bool($data)): $markerType = Zend_Amf_Constants::AMF0_BOOLEAN; break; - case (is_string($data) && (strlen($data) > 65536)): + case (is_string($data) && (($this->_mbStringFunctionsOverloaded ? mb_strlen($data, '8bit') : strlen($data)) > 65536)): $markerType = Zend_Amf_Constants::AMF0_LONGSTRING; break; case (is_string($data)): @@ -187,23 +187,23 @@ class Zend_Amf_Parse_Amf0_Serializer extends Zend_Amf_Parse_Serializer * Check if the given object is in the reference table, write the reference if it exists, * otherwise add the object to the reference table * - * @param mixed $object object reference to check for reference - * @param $markerType AMF type of the object to write - * @param mixed $objectByVal object to check for reference + * @param mixed $object object reference to check for reference + * @param string $markerType AMF type of the object to write + * @param mixed $objectByVal object to check for reference * @return Boolean true, if the reference was written, false otherwise */ - protected function writeObjectReference(&$object, $markerType, $objectByVal = false) + protected function writeObjectReference(&$object, $markerType, $objectByVal = false) { - // Workaround for PHP5 with E_STRICT enabled complaining about "Only + // Workaround for PHP5 with E_STRICT enabled complaining about "Only // variables should be passed by reference" if ((null === $object) && ($objectByVal !== false)) { $object = &$objectByVal; } - if ($markerType == Zend_Amf_Constants::AMF0_OBJECT - || $markerType == Zend_Amf_Constants::AMF0_MIXEDARRAY - || $markerType == Zend_Amf_Constants::AMF0_ARRAY - || $markerType == Zend_Amf_Constants::AMF0_TYPEDOBJECT + if ($markerType == Zend_Amf_Constants::AMF0_OBJECT + || $markerType == Zend_Amf_Constants::AMF0_MIXEDARRAY + || $markerType == Zend_Amf_Constants::AMF0_ARRAY + || $markerType == Zend_Amf_Constants::AMF0_TYPEDOBJECT ) { $ref = array_search($object, $this->_referenceObjects, true); //handle object reference diff --git a/lib/zend/Zend/Amf/Parse/Amf3/Deserializer.php b/lib/zend/Zend/Amf/Parse/Amf3/Deserializer.php index 0144798eb80..9bcc272af30 100644 --- a/lib/zend/Zend/Amf/Parse/Amf3/Deserializer.php +++ b/lib/zend/Zend/Amf/Parse/Amf3/Deserializer.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Amf * @subpackage Parse_Amf3 - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -23,6 +23,9 @@ /** Zend_Amf_Parse_Deserializer */ require_once 'Zend/Amf/Parse/Deserializer.php'; +/** Zend_Xml_Security */ +require_once 'Zend/Xml/Security.php'; + /** Zend_Amf_Parse_TypeLoader */ require_once 'Zend/Amf/Parse/TypeLoader.php'; @@ -34,7 +37,7 @@ require_once 'Zend/Amf/Parse/TypeLoader.php'; * @todo Class could be implemented as Factory Class with each data type it's own class. * @package Zend_Amf * @subpackage Parse_Amf3 - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Amf_Parse_Amf3_Deserializer extends Zend_Amf_Parse_Deserializer @@ -225,7 +228,7 @@ class Zend_Amf_Parse_Amf3_Deserializer extends Zend_Amf_Parse_Deserializer $timestamp = floor($this->_stream->readDouble() / 1000); require_once 'Zend/Date.php'; - $dateTime = new Zend_Date((int) $timestamp); + $dateTime = new Zend_Date($timestamp); $this->_referenceObjects[] = $dateTime; return $dateTime; } @@ -385,6 +388,7 @@ class Zend_Amf_Parse_Amf3_Deserializer extends Zend_Amf_Parse_Deserializer } // Add properties back to the return object. + if (!is_array($properties)) $properties = array(); foreach($properties as $key=>$value) { if($key) { $returnObject->$key = $value; @@ -416,6 +420,6 @@ class Zend_Amf_Parse_Amf3_Deserializer extends Zend_Amf_Parse_Deserializer $xmlReference = $this->readInteger(); $length = $xmlReference >> 1; $string = $this->_stream->readBytes($length); - return simplexml_load_string($string); + return Zend_Xml_Security::scan($string); } } diff --git a/lib/zend/Zend/Amf/Parse/Amf3/Serializer.php b/lib/zend/Zend/Amf/Parse/Amf3/Serializer.php index 80d191bf5aa..3ce47b7f7cb 100644 --- a/lib/zend/Zend/Amf/Parse/Amf3/Serializer.php +++ b/lib/zend/Zend/Amf/Parse/Amf3/Serializer.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Amf * @subpackage Parse_Amf3 - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -35,7 +35,7 @@ require_once 'Zend/Amf/Parse/TypeLoader.php'; * * @package Zend_Amf * @subpackage Parse_Amf3 - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer @@ -45,7 +45,7 @@ class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer * @var string */ protected $_strEmpty = ''; - + /** * An array of reference objects per amf body * @var array @@ -78,7 +78,7 @@ class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer */ public function writeTypeMarker(&$data, $markerType = null, $dataByVal = false) { - // Workaround for PHP5 with E_STRICT enabled complaining about "Only + // Workaround for PHP5 with E_STRICT enabled complaining about "Only // variables should be passed by reference" if ((null === $data) && ($dataByVal !== false)) { $data = &$dataByVal; @@ -215,7 +215,7 @@ class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer * @return Zend_Amf_Parse_Amf3_Serializer */ protected function writeBinaryString(&$string){ - $ref = strlen($string) << 1 | 0x01; + $ref = ($this->_mbStringFunctionsOverloaded ? mb_strlen($string, '8bit') : strlen($string)) << 1 | 0x01; $this->writeInteger($ref); $this->_stream->writeBytes($string); @@ -230,15 +230,17 @@ class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer */ public function writeString(&$string) { - $len = strlen($string); + $len = $this->_mbStringFunctionsOverloaded ? mb_strlen($string, '8bit') : strlen($string); if(!$len){ $this->writeInteger(0x01); return $this; } - $ref = array_search($string, $this->_referenceStrings, true); - if($ref === false){ - $this->_referenceStrings[] = $string; + $ref = array_key_exists($string, $this->_referenceStrings) + ? $this->_referenceStrings[$string] + : false; + if ($ref === false){ + $this->_referenceStrings[$string] = count($this->_referenceStrings); $this->writeBinaryString($string); } else { $ref <<= 1; @@ -380,13 +382,16 @@ class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer */ protected function writeObjectReference(&$object, $objectByVal = false) { - // Workaround for PHP5 with E_STRICT enabled complaining about "Only + // Workaround for PHP5 with E_STRICT enabled complaining about "Only // variables should be passed by reference" if ((null === $object) && ($objectByVal !== false)) { $object = &$objectByVal; } - $ref = array_search($object, $this->_referenceObjects,true); + $hash = spl_object_hash($object); + $ref = array_key_exists($hash, $this->_referenceObjects) + ? $this->_referenceObjects[$hash] + : false; // quickly handle object references if ($ref !== false){ @@ -394,7 +399,7 @@ class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer $this->writeInteger($ref); return true; } - $this->_referenceObjects[] = $object; + $this->_referenceObjects[$hash] = count($this->_referenceObjects); return false; } diff --git a/lib/zend/Zend/Amf/Parse/Deserializer.php b/lib/zend/Zend/Amf/Parse/Deserializer.php index a72aa15ed2f..e6d4b1a853d 100644 --- a/lib/zend/Zend/Amf/Parse/Deserializer.php +++ b/lib/zend/Zend/Amf/Parse/Deserializer.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Amf * @subpackage Parse - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -30,7 +30,7 @@ * @see http://opensource.adobe.com/svn/opensource/blazeds/trunk/modules/core/src/java/flex/messaging/io/amf/ * @package Zend_Amf * @subpackage Parse - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ abstract class Zend_Amf_Parse_Deserializer diff --git a/lib/zend/Zend/Amf/Parse/InputStream.php b/lib/zend/Zend/Amf/Parse/InputStream.php index ec8c88a19a7..25929651549 100644 --- a/lib/zend/Zend/Amf/Parse/InputStream.php +++ b/lib/zend/Zend/Amf/Parse/InputStream.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Amf * @subpackage Parse - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -31,7 +31,7 @@ require_once 'Zend/Amf/Util/BinaryStream.php'; * * @package Zend_Amf * @subpackage Parse - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Amf_Parse_InputStream extends Zend_Amf_Util_BinaryStream diff --git a/lib/zend/Zend/Amf/Parse/OutputStream.php b/lib/zend/Zend/Amf/Parse/OutputStream.php index d06e75076c1..c6979baadce 100644 --- a/lib/zend/Zend/Amf/Parse/OutputStream.php +++ b/lib/zend/Zend/Amf/Parse/OutputStream.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Amf * @subpackage Parse - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -32,7 +32,7 @@ require_once 'Zend/Amf/Util/BinaryStream.php'; * @uses Zend_Amf_Util_BinaryStream * @package Zend_Amf * @subpackage Parse - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Amf_Parse_OutputStream extends Zend_Amf_Util_BinaryStream diff --git a/lib/zend/Zend/Amf/Parse/Resource/MysqlResult.php b/lib/zend/Zend/Amf/Parse/Resource/MysqlResult.php old mode 100644 new mode 100755 index b3e004662f1..aed35a9d3f8 --- a/lib/zend/Zend/Amf/Parse/Resource/MysqlResult.php +++ b/lib/zend/Zend/Amf/Parse/Resource/MysqlResult.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Amf * @subpackage Parse - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -26,7 +26,7 @@ * * @package Zend_Amf * @subpackage Parse - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Amf_Parse_Resource_MysqlResult diff --git a/lib/zend/Zend/Amf/Parse/Resource/MysqliResult.php b/lib/zend/Zend/Amf/Parse/Resource/MysqliResult.php index fbb9caefed3..45f53d4b73d 100644 --- a/lib/zend/Zend/Amf/Parse/Resource/MysqliResult.php +++ b/lib/zend/Zend/Amf/Parse/Resource/MysqliResult.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Amf * @subpackage Parse - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -26,7 +26,7 @@ * * @package Zend_Amf * @subpackage Parse - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Amf_Parse_Resource_MysqliResult diff --git a/lib/zend/Zend/Amf/Parse/Resource/Stream.php b/lib/zend/Zend/Amf/Parse/Resource/Stream.php old mode 100644 new mode 100755 index 3fcd560ef19..b8afa148ac2 --- a/lib/zend/Zend/Amf/Parse/Resource/Stream.php +++ b/lib/zend/Zend/Amf/Parse/Resource/Stream.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Amf * @subpackage Parse - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -25,7 +25,7 @@ * * @package Zend_Amf * @subpackage Parse - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Amf_Parse_Resource_Stream diff --git a/lib/zend/Zend/Amf/Parse/Serializer.php b/lib/zend/Zend/Amf/Parse/Serializer.php index 2a0e4a9bf8c..7bf75f65bd1 100644 --- a/lib/zend/Zend/Amf/Parse/Serializer.php +++ b/lib/zend/Zend/Amf/Parse/Serializer.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Amf * @subpackage Parse - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -25,7 +25,7 @@ * * @package Zend_Amf * @subpackage Parse - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ abstract class Zend_Amf_Parse_Serializer @@ -37,6 +37,13 @@ abstract class Zend_Amf_Parse_Serializer */ protected $_stream; + /** + * str* functions overloaded using mbstring.func_overload + * + * @var bool + */ + protected $mbStringFunctionsOverloaded; + /** * Constructor * @@ -46,6 +53,7 @@ abstract class Zend_Amf_Parse_Serializer public function __construct(Zend_Amf_Parse_OutputStream $stream) { $this->_stream = $stream; + $this->_mbStringFunctionsOverloaded = function_exists('mb_strlen') && (ini_get('mbstring.func_overload') !== '') && ((int)ini_get('mbstring.func_overload') & 2); } /** diff --git a/lib/zend/Zend/Amf/Parse/TypeLoader.php b/lib/zend/Zend/Amf/Parse/TypeLoader.php index 5eda3b0ec2d..05c8db42f92 100644 --- a/lib/zend/Zend/Amf/Parse/TypeLoader.php +++ b/lib/zend/Zend/Amf/Parse/TypeLoader.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Amf * @subpackage Parse - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -47,7 +47,7 @@ require_once 'Zend/Amf/Value/Messaging/RemotingMessage.php'; * @todo PHP 5.3 can drastically change this class w/ namespace and the new call_user_func w/ namespace * @package Zend_Amf * @subpackage Parse - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ final class Zend_Amf_Parse_TypeLoader diff --git a/lib/zend/Zend/Amf/Request.php b/lib/zend/Zend/Amf/Request.php index 0fa7f3e8e70..c5da936ef05 100644 --- a/lib/zend/Zend/Amf/Request.php +++ b/lib/zend/Zend/Amf/Request.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Amf - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -40,7 +40,7 @@ require_once 'Zend/Amf/Value/MessageBody.php'; * * @todo Currently not checking if the object needs to be Type Mapped to a server object. * @package Zend_Amf - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Amf_Request diff --git a/lib/zend/Zend/Amf/Request/Http.php b/lib/zend/Zend/Amf/Request/Http.php index 30059f06045..e5675058e95 100644 --- a/lib/zend/Zend/Amf/Request/Http.php +++ b/lib/zend/Zend/Amf/Request/Http.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Amf * @subpackage Request - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -32,7 +32,7 @@ require_once 'Zend/Amf/Request.php'; * * @package Zend_Amf * @subpackage Request - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Amf_Request_Http extends Zend_Amf_Request diff --git a/lib/zend/Zend/Amf/Response.php b/lib/zend/Zend/Amf/Response.php index d069ecf9cb3..00e75010566 100644 --- a/lib/zend/Zend/Amf/Response.php +++ b/lib/zend/Zend/Amf/Response.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Amf - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -32,7 +32,7 @@ require_once 'Zend/Amf/Parse/Amf0/Serializer.php'; * Handles converting the PHP object ready for response back into AMF * * @package Zend_Amf - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Amf_Response @@ -95,7 +95,7 @@ class Zend_Amf_Response $stream->writeByte($header->mustRead); $stream->writeLong(Zend_Amf_Constants::UNKNOWN_CONTENT_LENGTH); if (is_object($header->data)) { - // Workaround for PHP5 with E_STRICT enabled complaining about + // Workaround for PHP5 with E_STRICT enabled complaining about // "Only variables should be passed by reference" $placeholder = null; $serializer->writeTypeMarker($placeholder, null, $header->data); @@ -115,7 +115,7 @@ class Zend_Amf_Response $bodyData = $body->getData(); $markerType = ($this->_objectEncoding == Zend_Amf_Constants::AMF0_OBJECT_ENCODING) ? null : Zend_Amf_Constants::AMF0_AMF3; if (is_object($bodyData)) { - // Workaround for PHP5 with E_STRICT enabled complaining about + // Workaround for PHP5 with E_STRICT enabled complaining about // "Only variables should be passed by reference" $placeholder = null; $serializer->writeTypeMarker($placeholder, $markerType, $bodyData); diff --git a/lib/zend/Zend/Amf/Response/Http.php b/lib/zend/Zend/Amf/Response/Http.php index 961ffdf84ae..4182f6aa8ad 100644 --- a/lib/zend/Zend/Amf/Response/Http.php +++ b/lib/zend/Zend/Amf/Response/Http.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Amf * @subpackage Response - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -28,7 +28,7 @@ require_once 'Zend/Amf/Response.php'; * * @package Zend_Amf * @subpackage Response - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Amf_Response_Http extends Zend_Amf_Response @@ -41,10 +41,33 @@ class Zend_Amf_Response_Http extends Zend_Amf_Response public function getResponse() { if (!headers_sent()) { - header('Cache-Control: cache, must-revalidate'); - header('Pragma: public'); + if ($this->isIeOverSsl()) { + header('Cache-Control: cache, must-revalidate'); + header('Pragma: public'); + } else { + header('Cache-Control: no-cache, must-revalidate'); + header('Pragma: no-cache'); + } + header('Expires: Thu, 19 Nov 1981 08:52:00 GMT'); header('Content-Type: application/x-amf'); } return parent::getResponse(); } + + protected function isIeOverSsl() + { + $ssl = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : false; + if (!$ssl || ($ssl == 'off')) { + // IIS reports "off", whereas other browsers simply don't populate + return false; + } + + $ua = $_SERVER['HTTP_USER_AGENT']; + if (!preg_match('/; MSIE \d+\.\d+;/', $ua)) { + // Not MicroSoft Internet Explorer + return false; + } + + return true; + } } diff --git a/lib/zend/Zend/Amf/Server.php b/lib/zend/Zend/Amf/Server.php index 241041f3e17..0f87286031d 100644 --- a/lib/zend/Zend/Amf/Server.php +++ b/lib/zend/Zend/Amf/Server.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Amf - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -52,7 +52,7 @@ require_once 'Zend/Auth.php'; * @todo Make the reflection methods cache and autoload. * @package Zend_Amf * @subpackage Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Amf_Server implements Zend_Server_Interface @@ -108,7 +108,7 @@ class Zend_Amf_Server implements Zend_Server_Interface protected $_session = false; /** - * Namespace allows all AMF calls to not clobber other php session variables + * Namespace allows all AMF calls to not clobber other PHP session variables * @var Zend_Session_NameSpace default session namespace zend_amf */ protected $_sesionNamespace = 'zend_amf'; @@ -142,12 +142,18 @@ class Zend_Amf_Server implements Zend_Server_Interface /** * Set authentication adapter * + * If the authentication adapter implements a "getAcl()" method, populate + * the ACL of this instance with it (if none exists already). + * * @param Zend_Amf_Auth_Abstract $auth * @return Zend_Amf_Server */ public function setAuth(Zend_Amf_Auth_Abstract $auth) { $this->_auth = $auth; + if ((null === $this->getAcl()) && method_exists($auth, 'getAcl')) { + $this->setAcl($auth->getAcl()); + } return $this; } /** @@ -300,12 +306,12 @@ class Zend_Amf_Server implements Zend_Server_Interface $source = $mapped; } } - $qualifiedName = empty($source) ? $method : $source.".".$method; + $qualifiedName = empty($source) ? $method : $source . '.' . $method; if (!isset($this->_table[$qualifiedName])) { // if source is null a method that was not defined was called. if ($source) { - $className = str_replace(".", "_", $source); + $className = str_replace('.', '_', $source); if(class_exists($className, false) && !isset($this->_classAllowed[$className])) { require_once 'Zend/Amf/Server/Exception.php'; throw new Zend_Amf_Server_Exception('Can not call "' . $className . '" - use setClass()'); @@ -317,8 +323,12 @@ class Zend_Amf_Server implements Zend_Server_Interface throw new Zend_Amf_Server_Exception('Class "' . $className . '" does not exist: '.$e->getMessage(), 0, $e); } // Add the new loaded class to the server. + require_once 'Zend/Amf/Server/Exception.php'; $this->setClass($className, $source); - } else { + } + + if (!isset($this->_table[$qualifiedName])) { + // Source is null or doesn't contain specified method require_once 'Zend/Amf/Server/Exception.php'; throw new Zend_Amf_Server_Exception('Method "' . $method . '" does not exist'); } @@ -331,6 +341,8 @@ class Zend_Amf_Server implements Zend_Server_Interface $params = array_merge($params, $argv); } + $params = $this->_castParameters($info, $params); + if ($info instanceof Zend_Server_Reflection_Function) { $func = $info->getName(); $this->_checkAcl(null, $func); @@ -491,66 +503,60 @@ class Zend_Amf_Server implements Zend_Server_Interface // set response encoding $response->setObjectEncoding($objectEncoding); - $responseBody = $request->getAmfBodies(); - - $handleAuth = false; - if ($this->_auth) { - $headers = $request->getAmfHeaders(); - if (isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]) && - isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->userid)) { - $handleAuth = true; + // Authenticate, if we have credential headers + $error = false; + $headers = $request->getAmfHeaders(); + if (isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]) + && isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->userid) + && isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->password) + ) { + try { + if ($this->_handleAuth( + $headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->userid, + $headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->password + )) { + // use RequestPersistentHeader to clear credentials + $response->addAmfHeader( + new Zend_Amf_Value_MessageHeader( + Zend_Amf_Constants::PERSISTENT_HEADER, + false, + new Zend_Amf_Value_MessageHeader( + Zend_Amf_Constants::CREDENTIALS_HEADER, + false, null + ) + ) + ); + } + } catch (Exception $e) { + // Error during authentication; report it + $error = $this->_errorMessage( + $objectEncoding, + '', + $e->getMessage(), + $e->getTraceAsString(), + $e->getCode(), + $e->getLine() + ); + $responseType = Zend_AMF_Constants::STATUS_METHOD; } } // Iterate through each of the service calls in the AMF request - foreach($responseBody as $body) + foreach($request->getAmfBodies() as $body) { + if ($error) { + // Error during authentication; just report it and be done + $responseURI = $body->getResponseURI() . $responseType; + $newBody = new Zend_Amf_Value_MessageBody($responseURI, null, $error); + $response->addAmfBody($newBody); + continue; + } try { - if ($handleAuth) { - if ($this->_handleAuth( - $headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->userid, - $headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->password)) { - // use RequestPersistentHeader to clear credentials - $response->addAmfHeader( - new Zend_Amf_Value_MessageHeader( - Zend_Amf_Constants::PERSISTENT_HEADER, - false, - new Zend_Amf_Value_MessageHeader( - Zend_Amf_Constants::CREDENTIALS_HEADER, - false, null))); - $handleAuth = false; - } - } - - if ($objectEncoding == Zend_Amf_Constants::AMF0_OBJECT_ENCODING) { - // AMF0 Object Encoding - $targetURI = $body->getTargetURI(); - $message = ''; - - // Split the target string into its values. - $source = substr($targetURI, 0, strrpos($targetURI, '.')); - - if ($source) { - // Break off method name from namespace into source - $method = substr(strrchr($targetURI, '.'), 1); - $return = $this->_dispatch($method, $body->getData(), $source); - } else { - // Just have a method name. - $return = $this->_dispatch($targetURI, $body->getData()); - } - } else { - // AMF3 read message type - $message = $body->getData(); - if ($message instanceof Zend_Amf_Value_Messaging_CommandMessage) { - // async call with command message - $return = $this->_loadCommandMessage($message); - } elseif ($message instanceof Zend_Amf_Value_Messaging_RemotingMessage) { - require_once 'Zend/Amf/Value/Messaging/AcknowledgeMessage.php'; - $return = new Zend_Amf_Value_Messaging_AcknowledgeMessage($message); - $return->body = $this->_dispatch($message->operation, $message->body, $message->source); - } else { - // Amf3 message sent with netConnection + switch ($objectEncoding) { + case Zend_Amf_Constants::AMF0_OBJECT_ENCODING: + // AMF0 Object Encoding $targetURI = $body->getTargetURI(); + $message = ''; // Split the target string into its values. $source = substr($targetURI, 0, strrpos($targetURI, '.')); @@ -563,7 +569,35 @@ class Zend_Amf_Server implements Zend_Server_Interface // Just have a method name. $return = $this->_dispatch($targetURI, $body->getData()); } - } + break; + case Zend_Amf_Constants::AMF3_OBJECT_ENCODING: + default: + // AMF3 read message type + $message = $body->getData(); + if ($message instanceof Zend_Amf_Value_Messaging_CommandMessage) { + // async call with command message + $return = $this->_loadCommandMessage($message); + } elseif ($message instanceof Zend_Amf_Value_Messaging_RemotingMessage) { + require_once 'Zend/Amf/Value/Messaging/AcknowledgeMessage.php'; + $return = new Zend_Amf_Value_Messaging_AcknowledgeMessage($message); + $return->body = $this->_dispatch($message->operation, $message->body, $message->source); + } else { + // Amf3 message sent with netConnection + $targetURI = $body->getTargetURI(); + + // Split the target string into its values. + $source = substr($targetURI, 0, strrpos($targetURI, '.')); + + if ($source) { + // Break off method name from namespace into source + $method = substr(strrchr($targetURI, '.'), 1); + $return = $this->_dispatch($method, $body->getData(), $source); + } else { + // Just have a method name. + $return = $this->_dispatch($targetURI, $body->getData()); + } + } + break; } $responseType = Zend_AMF_Constants::RESULT_METHOD; } catch (Exception $e) { @@ -607,7 +641,7 @@ class Zend_Amf_Server implements Zend_Server_Interface public function handle($request = null) { // Check if request was passed otherwise get it from the server - if (is_null($request) || !$request instanceof Zend_Amf_Request) { + if ($request === null || !$request instanceof Zend_Amf_Request) { $request = $this->getRequest(); } else { $this->setRequest($request); @@ -733,9 +767,9 @@ class Zend_Amf_Server implements Zend_Server_Interface throw new Zend_Amf_Server_Exception('Invalid method or class; must be a classname or object'); } - $argv = null; + $args = null; if (2 < func_num_args()) { - $argv = array_slice(func_get_args(), 2); + $args = array_slice(func_get_args(), 2); } // Use the class name as the name space by default. @@ -746,7 +780,7 @@ class Zend_Amf_Server implements Zend_Server_Interface $this->_classAllowed[is_object($class) ? get_class($class) : $class] = true; - $this->_methods[] = Zend_Server_Reflection::reflectClass($class, $argv, $namespace); + $this->_methods[] = Zend_Server_Reflection::reflectClass($class, $args, $namespace); $this->_buildDispatchTable(); return $this; @@ -930,4 +964,85 @@ class Zend_Amf_Server implements Zend_Server_Interface { return array_keys($this->_table); } + + /** + * Cast parameters + * + * Takes the provided parameters from the request, and attempts to cast them + * to objects, if the prototype defines any as explicit object types + * + * @param Reflection $reflectionMethod + * @param array $params + * @return array + */ + protected function _castParameters($reflectionMethod, array $params) + { + $prototypes = $reflectionMethod->getPrototypes(); + $nonObjectTypes = array( + 'null', + 'mixed', + 'void', + 'unknown', + 'bool', + 'boolean', + 'number', + 'int', + 'integer', + 'double', + 'float', + 'string', + 'array', + 'object', + 'stdclass', + ); + $types = array(); + foreach ($prototypes as $prototype) { + foreach ($prototype->getParameters() as $parameter) { + $type = $parameter->getType(); + if (in_array(strtolower($type), $nonObjectTypes)) { + continue; + } + $position = $parameter->getPosition(); + $types[$position] = $type; + } + } + + if (empty($types)) { + return $params; + } + + foreach ($params as $position => $value) { + if (!isset($types[$position])) { + // No specific type to cast to? done + continue; + } + + $type = $types[$position]; + + if (!class_exists($type)) { + // Not a class, apparently. done + continue; + } + + if ($value instanceof $type) { + // Already of the right type? done + continue; + } + + if (!is_array($value) && !is_object($value)) { + // Can't cast scalars to objects easily; done + continue; + } + + // Create instance, and loop through value to set + $object = new $type; + foreach ($value as $property => $defined) { + $object->{$property} = $defined; + } + + $params[$position] = $object; + } + + return $params; + } } diff --git a/lib/zend/Zend/Amf/Server/Exception.php b/lib/zend/Zend/Amf/Server/Exception.php index 10fe6762857..d9532ac1123 100644 --- a/lib/zend/Zend/Amf/Server/Exception.php +++ b/lib/zend/Zend/Amf/Server/Exception.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Amf * @subpackage Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -29,7 +29,7 @@ require_once 'Zend/Amf/Exception.php'; * @category Zend * @package Zend_Amf * @subpackage Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Amf_Server_Exception extends Zend_Amf_Exception diff --git a/lib/zend/Zend/Amf/Util/BinaryStream.php b/lib/zend/Zend/Amf/Util/BinaryStream.php index fefc271de99..b56820a62fa 100644 --- a/lib/zend/Zend/Amf/Util/BinaryStream.php +++ b/lib/zend/Zend/Amf/Util/BinaryStream.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Amf * @subpackage Util - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -25,7 +25,7 @@ * * @package Zend_Amf * @subpackage Util - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Amf_Util_BinaryStream @@ -50,6 +50,11 @@ class Zend_Amf_Util_BinaryStream */ protected $_needle; + /** + * @var bool str* functions overloaded using mbstring.func_overload? + */ + protected $_mbStringFunctionsOverloaded; + /** * Constructor * @@ -69,7 +74,8 @@ class Zend_Amf_Util_BinaryStream $this->_stream = $stream; $this->_needle = 0; - $this->_streamLength = strlen($stream); + $this->_mbStringFunctionsOverloaded = function_exists('mb_strlen') && (ini_get('mbstring.func_overload') !== '') && ((int)ini_get('mbstring.func_overload') & 2); + $this->_streamLength = $this->_mbStringFunctionsOverloaded ? mb_strlen($stream, '8bit') : strlen($stream); $this->_bigEndian = (pack('l', 1) === "\x00\x00\x00\x01"); } @@ -97,7 +103,7 @@ class Zend_Amf_Util_BinaryStream require_once 'Zend/Amf/Exception.php'; throw new Zend_Amf_Exception('Buffer underrun at needle position: ' . $this->_needle . ' while requesting length: ' . $length); } - $bytes = substr($this->_stream, $this->_needle, $length); + $bytes = $this->_mbStringFunctionsOverloaded ? mb_substr($this->_stream, $this->_needle, $length, '8bit') : substr($this->_stream, $this->_needle, $length); $this->_needle+= $length; return $bytes; } @@ -120,12 +126,18 @@ class Zend_Amf_Util_BinaryStream * Reads a signed byte * * @return int Value is in the range of -128 to 127. + * @throws Zend_Amf_Exception */ public function readByte() { if (($this->_needle + 1) > $this->_streamLength) { require_once 'Zend/Amf/Exception.php'; - throw new Zend_Amf_Exception('Buffer underrun at needle position: ' . $this->_needle . ' while requesting length: ' . $length); + throw new Zend_Amf_Exception( + 'Buffer underrun at needle position: ' + . $this->_needle + . ' while requesting length: ' + . $this->_streamLength + ); } return ord($this->_stream{$this->_needle++}); @@ -184,7 +196,7 @@ class Zend_Amf_Util_BinaryStream */ public function writeUtf($stream) { - $this->writeInt(strlen($stream)); + $this->writeInt($this->_mbStringFunctionsOverloaded ? mb_strlen($stream, '8bit') : strlen($stream)); $this->_stream.= $stream; return $this; } @@ -209,7 +221,7 @@ class Zend_Amf_Util_BinaryStream */ public function writeLongUtf($stream) { - $this->writeLong(strlen($stream)); + $this->writeLong($this->_mbStringFunctionsOverloaded ? mb_strlen($stream, '8bit') : strlen($stream)); $this->_stream.= $stream; } @@ -255,7 +267,7 @@ class Zend_Amf_Util_BinaryStream */ public function readDouble() { - $bytes = substr($this->_stream, $this->_needle, 8); + $bytes = $this->_mbStringFunctionsOverloaded ? mb_substr($this->_stream, $this->_needle, 8, '8bit') : substr($this->_stream, $this->_needle, 8); $this->_needle+= 8; if (!$this->_bigEndian) { diff --git a/lib/zend/Zend/Amf/Value/ByteArray.php b/lib/zend/Zend/Amf/Value/ByteArray.php index 3555f300f35..32ebf268b81 100644 --- a/lib/zend/Zend/Amf/Value/ByteArray.php +++ b/lib/zend/Zend/Amf/Value/ByteArray.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Amf * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -25,7 +25,7 @@ * * @package Zend_Amf * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Amf_Value_ByteArray diff --git a/lib/zend/Zend/Amf/Value/MessageBody.php b/lib/zend/Zend/Amf/Value/MessageBody.php index 4d4e67ed300..59cacba52be 100644 --- a/lib/zend/Zend/Amf/Value/MessageBody.php +++ b/lib/zend/Zend/Amf/Value/MessageBody.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Amf * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -33,7 +33,7 @@ * * @package Zend_Amf * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Amf_Value_MessageBody diff --git a/lib/zend/Zend/Amf/Value/MessageHeader.php b/lib/zend/Zend/Amf/Value/MessageHeader.php index 3058db1e0f4..bdbbba2a7db 100644 --- a/lib/zend/Zend/Amf/Value/MessageHeader.php +++ b/lib/zend/Zend/Amf/Value/MessageHeader.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Amf * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -28,7 +28,7 @@ * * @package Zend_Amf * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Amf_Value_MessageHeader diff --git a/lib/zend/Zend/Amf/Value/Messaging/AbstractMessage.php b/lib/zend/Zend/Amf/Value/Messaging/AbstractMessage.php index fab2b9d6e5e..acb5a0c6c8e 100644 --- a/lib/zend/Zend/Amf/Value/Messaging/AbstractMessage.php +++ b/lib/zend/Zend/Amf/Value/Messaging/AbstractMessage.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Amf * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -26,7 +26,7 @@ * * @package Zend_Amf * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Amf_Value_Messaging_AbstractMessage diff --git a/lib/zend/Zend/Amf/Value/Messaging/AcknowledgeMessage.php b/lib/zend/Zend/Amf/Value/Messaging/AcknowledgeMessage.php index 8f54c333077..eb081bd4e25 100644 --- a/lib/zend/Zend/Amf/Value/Messaging/AcknowledgeMessage.php +++ b/lib/zend/Zend/Amf/Value/Messaging/AcknowledgeMessage.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Amf * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -32,7 +32,7 @@ require_once 'Zend/Amf/Value/Messaging/AsyncMessage.php'; * * @package Zend_Amf * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Amf_Value_Messaging_AcknowledgeMessage extends Zend_Amf_Value_Messaging_AsyncMessage diff --git a/lib/zend/Zend/Amf/Value/Messaging/ArrayCollection.php b/lib/zend/Zend/Amf/Value/Messaging/ArrayCollection.php old mode 100644 new mode 100755 index 0b1b9301a42..a759f58e53e --- a/lib/zend/Zend/Amf/Value/Messaging/ArrayCollection.php +++ b/lib/zend/Zend/Amf/Value/Messaging/ArrayCollection.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Amf * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,9 +27,9 @@ * * @package Zend_Amf * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class Zend_Amf_Value_Messaging_ArrayCollection +class Zend_Amf_Value_Messaging_ArrayCollection extends ArrayObject { } diff --git a/lib/zend/Zend/Amf/Value/Messaging/AsyncMessage.php b/lib/zend/Zend/Amf/Value/Messaging/AsyncMessage.php index 8787e57ce03..d052cb60ac3 100644 --- a/lib/zend/Zend/Amf/Value/Messaging/AsyncMessage.php +++ b/lib/zend/Zend/Amf/Value/Messaging/AsyncMessage.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Amf * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -30,7 +30,7 @@ require_once 'Zend/Amf/Value/Messaging/AbstractMessage.php'; * * @package Zend_Amf * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Amf_Value_Messaging_AsyncMessage extends Zend_Amf_Value_Messaging_AbstractMessage diff --git a/lib/zend/Zend/Amf/Value/Messaging/CommandMessage.php b/lib/zend/Zend/Amf/Value/Messaging/CommandMessage.php index 05f4534883e..f4500da18dc 100644 --- a/lib/zend/Zend/Amf/Value/Messaging/CommandMessage.php +++ b/lib/zend/Zend/Amf/Value/Messaging/CommandMessage.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Amf * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -36,7 +36,7 @@ require_once 'Zend/Amf/Value/Messaging/AsyncMessage.php'; * * @package Zend_Amf * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Amf_Value_Messaging_CommandMessage extends Zend_Amf_Value_Messaging_AsyncMessage diff --git a/lib/zend/Zend/Amf/Value/Messaging/ErrorMessage.php b/lib/zend/Zend/Amf/Value/Messaging/ErrorMessage.php index d3f7f950e8b..a6eaf166fb4 100644 --- a/lib/zend/Zend/Amf/Value/Messaging/ErrorMessage.php +++ b/lib/zend/Zend/Amf/Value/Messaging/ErrorMessage.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Amf * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -30,7 +30,7 @@ require_once 'Zend/Amf/Value/Messaging/AcknowledgeMessage.php'; * * @package Zend_Amf * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Amf_Value_Messaging_ErrorMessage extends Zend_Amf_Value_Messaging_AcknowledgeMessage diff --git a/lib/zend/Zend/Amf/Value/Messaging/RemotingMessage.php b/lib/zend/Zend/Amf/Value/Messaging/RemotingMessage.php index 075fe9ee125..43c1e1e889b 100644 --- a/lib/zend/Zend/Amf/Value/Messaging/RemotingMessage.php +++ b/lib/zend/Zend/Amf/Value/Messaging/RemotingMessage.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Amf * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -31,7 +31,7 @@ require_once 'Zend/Amf/Value/Messaging/AbstractMessage.php'; * * @package Zend_Amf * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Amf_Value_Messaging_RemotingMessage extends Zend_Amf_Value_Messaging_AbstractMessage diff --git a/lib/zend/Zend/Amf/Value/TraitsInfo.php b/lib/zend/Zend/Amf/Value/TraitsInfo.php index c92ffc21d37..64d3c990ea0 100644 --- a/lib/zend/Zend/Amf/Value/TraitsInfo.php +++ b/lib/zend/Zend/Amf/Value/TraitsInfo.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Amf * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -25,7 +25,7 @@ * * @package Zend_Amf * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Amf_Value_TraitsInfo diff --git a/lib/zend/Zend/Auth.php b/lib/zend/Zend/Auth.php index 39659507e82..0b4b00ffb44 100644 --- a/lib/zend/Zend/Auth.php +++ b/lib/zend/Zend/Auth.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Auth - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -23,7 +23,7 @@ /** * @category Zend * @package Zend_Auth - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Auth diff --git a/lib/zend/Zend/Auth/Adapter/Digest.php b/lib/zend/Zend/Auth/Adapter/Digest.php new file mode 100644 index 00000000000..f52b651e7a6 --- /dev/null +++ b/lib/zend/Zend/Auth/Adapter/Digest.php @@ -0,0 +1,251 @@ +$methodName($$option); + } + } + } + + /** + * Returns the filename option value or null if it has not yet been set + * + * @return string|null + */ + public function getFilename() + { + return $this->_filename; + } + + /** + * Sets the filename option value + * + * @param mixed $filename + * @return Zend_Auth_Adapter_Digest Provides a fluent interface + */ + public function setFilename($filename) + { + $this->_filename = (string) $filename; + return $this; + } + + /** + * Returns the realm option value or null if it has not yet been set + * + * @return string|null + */ + public function getRealm() + { + return $this->_realm; + } + + /** + * Sets the realm option value + * + * @param mixed $realm + * @return Zend_Auth_Adapter_Digest Provides a fluent interface + */ + public function setRealm($realm) + { + $this->_realm = (string) $realm; + return $this; + } + + /** + * Returns the username option value or null if it has not yet been set + * + * @return string|null + */ + public function getUsername() + { + return $this->_username; + } + + /** + * Sets the username option value + * + * @param mixed $username + * @return Zend_Auth_Adapter_Digest Provides a fluent interface + */ + public function setUsername($username) + { + $this->_username = (string) $username; + return $this; + } + + /** + * Returns the password option value or null if it has not yet been set + * + * @return string|null + */ + public function getPassword() + { + return $this->_password; + } + + /** + * Sets the password option value + * + * @param mixed $password + * @return Zend_Auth_Adapter_Digest Provides a fluent interface + */ + public function setPassword($password) + { + $this->_password = (string) $password; + return $this; + } + + /** + * Defined by Zend_Auth_Adapter_Interface + * + * @throws Zend_Auth_Adapter_Exception + * @return Zend_Auth_Result + */ + public function authenticate() + { + $optionsRequired = array('filename', 'realm', 'username', 'password'); + foreach ($optionsRequired as $optionRequired) { + if (null === $this->{"_$optionRequired"}) { + /** + * @see Zend_Auth_Adapter_Exception + */ + require_once 'Zend/Auth/Adapter/Exception.php'; + throw new Zend_Auth_Adapter_Exception("Option '$optionRequired' must be set before authentication"); + } + } + + if (false === ($fileHandle = @fopen($this->_filename, 'r'))) { + /** + * @see Zend_Auth_Adapter_Exception + */ + require_once 'Zend/Auth/Adapter/Exception.php'; + throw new Zend_Auth_Adapter_Exception("Cannot open '$this->_filename' for reading"); + } + + $id = "$this->_username:$this->_realm"; + $idLength = strlen($id); + + $result = array( + 'code' => Zend_Auth_Result::FAILURE, + 'identity' => array( + 'realm' => $this->_realm, + 'username' => $this->_username, + ), + 'messages' => array() + ); + + while ($line = trim(fgets($fileHandle))) { + if (substr($line, 0, $idLength) === $id) { + if ($this->_secureStringCompare(substr($line, -32), md5("$this->_username:$this->_realm:$this->_password"))) { + $result['code'] = Zend_Auth_Result::SUCCESS; + } else { + $result['code'] = Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID; + $result['messages'][] = 'Password incorrect'; + } + return new Zend_Auth_Result($result['code'], $result['identity'], $result['messages']); + } + } + + $result['code'] = Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND; + $result['messages'][] = "Username '$this->_username' and realm '$this->_realm' combination not found"; + return new Zend_Auth_Result($result['code'], $result['identity'], $result['messages']); + } + + /** + * Securely compare two strings for equality while avoided C level memcmp() + * optimisations capable of leaking timing information useful to an attacker + * attempting to iteratively guess the unknown string (e.g. password) being + * compared against. + * + * @param string $a + * @param string $b + * @return bool + */ + protected function _secureStringCompare($a, $b) + { + if (strlen($a) !== strlen($b)) { + return false; + } + $result = 0; + for ($i = 0; $i < strlen($a); $i++) { + $result |= ord($a[$i]) ^ ord($b[$i]); + } + return $result == 0; + } +} diff --git a/lib/zend/Zend/Auth/Adapter/Exception.php b/lib/zend/Zend/Auth/Adapter/Exception.php new file mode 100644 index 00000000000..03216493065 --- /dev/null +++ b/lib/zend/Zend/Auth/Adapter/Exception.php @@ -0,0 +1,38 @@ + 'basic'|'digest'|'basic digest' + * 'realm' => + * 'digest_domains' => Space-delimited list of URIs + * 'nonce_timeout' => + * 'use_opaque' => Whether to send the opaque value in the header + * 'alogrithm' => See $_supportedAlgos. Default: MD5 + * 'proxy_auth' => Whether to do authentication as a Proxy + * @throws Zend_Auth_Adapter_Exception + */ + public function __construct(array $config) + { + if (!extension_loaded('hash')) { + /** + * @see Zend_Auth_Adapter_Exception + */ + require_once 'Zend/Auth/Adapter/Exception.php'; + throw new Zend_Auth_Adapter_Exception(__CLASS__ . ' requires the \'hash\' extension'); + } + + $this->_request = null; + $this->_response = null; + $this->_ieNoOpaque = false; + + + if (empty($config['accept_schemes'])) { + /** + * @see Zend_Auth_Adapter_Exception + */ + require_once 'Zend/Auth/Adapter/Exception.php'; + throw new Zend_Auth_Adapter_Exception('Config key \'accept_schemes\' is required'); + } + + $schemes = explode(' ', $config['accept_schemes']); + $this->_acceptSchemes = array_intersect($schemes, $this->_supportedSchemes); + if (empty($this->_acceptSchemes)) { + /** + * @see Zend_Auth_Adapter_Exception + */ + require_once 'Zend/Auth/Adapter/Exception.php'; + throw new Zend_Auth_Adapter_Exception('No supported schemes given in \'accept_schemes\'. Valid values: ' + . implode(', ', $this->_supportedSchemes)); + } + + // Double-quotes are used to delimit the realm string in the HTTP header, + // and colons are field delimiters in the password file. + if (empty($config['realm']) || + !ctype_print($config['realm']) || + strpos($config['realm'], ':') !== false || + strpos($config['realm'], '"') !== false) { + /** + * @see Zend_Auth_Adapter_Exception + */ + require_once 'Zend/Auth/Adapter/Exception.php'; + throw new Zend_Auth_Adapter_Exception('Config key \'realm\' is required, and must contain only printable ' + . 'characters, excluding quotation marks and colons'); + } else { + $this->_realm = $config['realm']; + } + + if (in_array('digest', $this->_acceptSchemes)) { + if (empty($config['digest_domains']) || + !ctype_print($config['digest_domains']) || + strpos($config['digest_domains'], '"') !== false) { + /** + * @see Zend_Auth_Adapter_Exception + */ + require_once 'Zend/Auth/Adapter/Exception.php'; + throw new Zend_Auth_Adapter_Exception('Config key \'digest_domains\' is required, and must contain ' + . 'only printable characters, excluding quotation marks'); + } else { + $this->_domains = $config['digest_domains']; + } + + if (empty($config['nonce_timeout']) || + !is_numeric($config['nonce_timeout'])) { + /** + * @see Zend_Auth_Adapter_Exception + */ + require_once 'Zend/Auth/Adapter/Exception.php'; + throw new Zend_Auth_Adapter_Exception('Config key \'nonce_timeout\' is required, and must be an ' + . 'integer'); + } else { + $this->_nonceTimeout = (int) $config['nonce_timeout']; + } + + // We use the opaque value unless explicitly told not to + if (isset($config['use_opaque']) && false == (bool) $config['use_opaque']) { + $this->_useOpaque = false; + } else { + $this->_useOpaque = true; + } + + if (isset($config['algorithm']) && in_array($config['algorithm'], $this->_supportedAlgos)) { + $this->_algo = $config['algorithm']; + } else { + $this->_algo = 'MD5'; + } + } + + // Don't be a proxy unless explicitly told to do so + if (isset($config['proxy_auth']) && true == (bool) $config['proxy_auth']) { + $this->_imaProxy = true; // I'm a Proxy + } else { + $this->_imaProxy = false; + } + } + + /** + * Setter for the _basicResolver property + * + * @param Zend_Auth_Adapter_Http_Resolver_Interface $resolver + * @return Zend_Auth_Adapter_Http Provides a fluent interface + */ + public function setBasicResolver(Zend_Auth_Adapter_Http_Resolver_Interface $resolver) + { + $this->_basicResolver = $resolver; + + return $this; + } + + /** + * Getter for the _basicResolver property + * + * @return Zend_Auth_Adapter_Http_Resolver_Interface + */ + public function getBasicResolver() + { + return $this->_basicResolver; + } + + /** + * Setter for the _digestResolver property + * + * @param Zend_Auth_Adapter_Http_Resolver_Interface $resolver + * @return Zend_Auth_Adapter_Http Provides a fluent interface + */ + public function setDigestResolver(Zend_Auth_Adapter_Http_Resolver_Interface $resolver) + { + $this->_digestResolver = $resolver; + + return $this; + } + + /** + * Getter for the _digestResolver property + * + * @return Zend_Auth_Adapter_Http_Resolver_Interface + */ + public function getDigestResolver() + { + return $this->_digestResolver; + } + + /** + * Setter for the Request object + * + * @param Zend_Controller_Request_Http $request + * @return Zend_Auth_Adapter_Http Provides a fluent interface + */ + public function setRequest(Zend_Controller_Request_Http $request) + { + $this->_request = $request; + + return $this; + } + + /** + * Getter for the Request object + * + * @return Zend_Controller_Request_Http + */ + public function getRequest() + { + return $this->_request; + } + + /** + * Setter for the Response object + * + * @param Zend_Controller_Response_Http $response + * @return Zend_Auth_Adapter_Http Provides a fluent interface + */ + public function setResponse(Zend_Controller_Response_Http $response) + { + $this->_response = $response; + + return $this; + } + + /** + * Getter for the Response object + * + * @return Zend_Controller_Response_Http + */ + public function getResponse() + { + return $this->_response; + } + + /** + * Authenticate + * + * @throws Zend_Auth_Adapter_Exception + * @return Zend_Auth_Result + */ + public function authenticate() + { + if (empty($this->_request) || + empty($this->_response)) { + /** + * @see Zend_Auth_Adapter_Exception + */ + require_once 'Zend/Auth/Adapter/Exception.php'; + throw new Zend_Auth_Adapter_Exception('Request and Response objects must be set before calling ' + . 'authenticate()'); + } + + if ($this->_imaProxy) { + $getHeader = 'Proxy-Authorization'; + } else { + $getHeader = 'Authorization'; + } + + $authHeader = $this->_request->getHeader($getHeader); + if (!$authHeader) { + return $this->_challengeClient(); + } + + list($clientScheme) = explode(' ', $authHeader); + $clientScheme = strtolower($clientScheme); + + // The server can issue multiple challenges, but the client should + // answer with only the selected auth scheme. + if (!in_array($clientScheme, $this->_supportedSchemes)) { + $this->_response->setHttpResponseCode(400); + return new Zend_Auth_Result( + Zend_Auth_Result::FAILURE_UNCATEGORIZED, + array(), + array('Client requested an incorrect or unsupported authentication scheme') + ); + } + + // client sent a scheme that is not the one required + if (!in_array($clientScheme, $this->_acceptSchemes)) { + // challenge again the client + return $this->_challengeClient(); + } + + switch ($clientScheme) { + case 'basic': + $result = $this->_basicAuth($authHeader); + break; + case 'digest': + $result = $this->_digestAuth($authHeader); + break; + default: + /** + * @see Zend_Auth_Adapter_Exception + */ + require_once 'Zend/Auth/Adapter/Exception.php'; + throw new Zend_Auth_Adapter_Exception('Unsupported authentication scheme'); + } + + return $result; + } + + /** + * Challenge Client + * + * Sets a 401 or 407 Unauthorized response code, and creates the + * appropriate Authenticate header(s) to prompt for credentials. + * + * @return Zend_Auth_Result Always returns a non-identity Auth result + */ + protected function _challengeClient() + { + if ($this->_imaProxy) { + $statusCode = 407; + $headerName = 'Proxy-Authenticate'; + } else { + $statusCode = 401; + $headerName = 'WWW-Authenticate'; + } + + $this->_response->setHttpResponseCode($statusCode); + + // Send a challenge in each acceptable authentication scheme + if (in_array('basic', $this->_acceptSchemes)) { + $this->_response->setHeader($headerName, $this->_basicHeader()); + } + if (in_array('digest', $this->_acceptSchemes)) { + $this->_response->setHeader($headerName, $this->_digestHeader()); + } + return new Zend_Auth_Result( + Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID, + array(), + array('Invalid or absent credentials; challenging client') + ); + } + + /** + * Basic Header + * + * Generates a Proxy- or WWW-Authenticate header value in the Basic + * authentication scheme. + * + * @return string Authenticate header value + */ + protected function _basicHeader() + { + return 'Basic realm="' . $this->_realm . '"'; + } + + /** + * Digest Header + * + * Generates a Proxy- or WWW-Authenticate header value in the Digest + * authentication scheme. + * + * @return string Authenticate header value + */ + protected function _digestHeader() + { + $wwwauth = 'Digest realm="' . $this->_realm . '", ' + . 'domain="' . $this->_domains . '", ' + . 'nonce="' . $this->_calcNonce() . '", ' + . ($this->_useOpaque ? 'opaque="' . $this->_calcOpaque() . '", ' : '') + . 'algorithm="' . $this->_algo . '", ' + . 'qop="' . implode(',', $this->_supportedQops) . '"'; + + return $wwwauth; + } + + /** + * Basic Authentication + * + * @param string $header Client's Authorization header + * @throws Zend_Auth_Adapter_Exception + * @return Zend_Auth_Result + */ + protected function _basicAuth($header) + { + if (empty($header)) { + /** + * @see Zend_Auth_Adapter_Exception + */ + require_once 'Zend/Auth/Adapter/Exception.php'; + throw new Zend_Auth_Adapter_Exception('The value of the client Authorization header is required'); + } + if (empty($this->_basicResolver)) { + /** + * @see Zend_Auth_Adapter_Exception + */ + require_once 'Zend/Auth/Adapter/Exception.php'; + throw new Zend_Auth_Adapter_Exception('A basicResolver object must be set before doing Basic ' + . 'authentication'); + } + + // Decode the Authorization header + $auth = substr($header, strlen('Basic ')); + $auth = base64_decode($auth); + if (!$auth) { + /** + * @see Zend_Auth_Adapter_Exception + */ + require_once 'Zend/Auth/Adapter/Exception.php'; + throw new Zend_Auth_Adapter_Exception('Unable to base64_decode Authorization header value'); + } + + // See ZF-1253. Validate the credentials the same way the digest + // implementation does. If invalid credentials are detected, + // re-challenge the client. + if (!ctype_print($auth)) { + return $this->_challengeClient(); + } + // Fix for ZF-1515: Now re-challenges on empty username or password + $creds = array_filter(explode(':', $auth)); + if (count($creds) != 2) { + return $this->_challengeClient(); + } + + $password = $this->_basicResolver->resolve($creds[0], $this->_realm); + if ($password && $this->_secureStringCompare($password, $creds[1])) { + $identity = array('username'=>$creds[0], 'realm'=>$this->_realm); + return new Zend_Auth_Result(Zend_Auth_Result::SUCCESS, $identity); + } else { + return $this->_challengeClient(); + } + } + + /** + * Digest Authentication + * + * @param string $header Client's Authorization header + * @throws Zend_Auth_Adapter_Exception + * @return Zend_Auth_Result Valid auth result only on successful auth + */ + protected function _digestAuth($header) + { + if (empty($header)) { + /** + * @see Zend_Auth_Adapter_Exception + */ + require_once 'Zend/Auth/Adapter/Exception.php'; + throw new Zend_Auth_Adapter_Exception('The value of the client Authorization header is required'); + } + if (empty($this->_digestResolver)) { + /** + * @see Zend_Auth_Adapter_Exception + */ + require_once 'Zend/Auth/Adapter/Exception.php'; + throw new Zend_Auth_Adapter_Exception('A digestResolver object must be set before doing Digest authentication'); + } + + $data = $this->_parseDigestAuth($header); + if ($data === false) { + $this->_response->setHttpResponseCode(400); + return new Zend_Auth_Result( + Zend_Auth_Result::FAILURE_UNCATEGORIZED, + array(), + array('Invalid Authorization header format') + ); + } + + // See ZF-1052. This code was a bit too unforgiving of invalid + // usernames. Now, if the username is bad, we re-challenge the client. + if ('::invalid::' == $data['username']) { + return $this->_challengeClient(); + } + + // Verify that the client sent back the same nonce + if ($this->_calcNonce() != $data['nonce']) { + return $this->_challengeClient(); + } + // The opaque value is also required to match, but of course IE doesn't + // play ball. + if (!$this->_ieNoOpaque && $this->_calcOpaque() != $data['opaque']) { + return $this->_challengeClient(); + } + + // Look up the user's password hash. If not found, deny access. + // This makes no assumptions about how the password hash was + // constructed beyond that it must have been built in such a way as + // to be recreatable with the current settings of this object. + $ha1 = $this->_digestResolver->resolve($data['username'], $data['realm']); + if ($ha1 === false) { + return $this->_challengeClient(); + } + + // If MD5-sess is used, a1 value is made of the user's password + // hash with the server and client nonce appended, separated by + // colons. + if ($this->_algo == 'MD5-sess') { + $ha1 = hash('md5', $ha1 . ':' . $data['nonce'] . ':' . $data['cnonce']); + } + + // Calculate h(a2). The value of this hash depends on the qop + // option selected by the client and the supported hash functions + switch ($data['qop']) { + case 'auth': + $a2 = $this->_request->getMethod() . ':' . $data['uri']; + break; + case 'auth-int': + // Should be REQUEST_METHOD . ':' . uri . ':' . hash(entity-body), + // but this isn't supported yet, so fall through to default case + default: + /** + * @see Zend_Auth_Adapter_Exception + */ + require_once 'Zend/Auth/Adapter/Exception.php'; + throw new Zend_Auth_Adapter_Exception('Client requested an unsupported qop option'); + } + // Using hash() should make parameterizing the hash algorithm + // easier + $ha2 = hash('md5', $a2); + + + // Calculate the server's version of the request-digest. This must + // match $data['response']. See RFC 2617, section 3.2.2.1 + $message = $data['nonce'] . ':' . $data['nc'] . ':' . $data['cnonce'] . ':' . $data['qop'] . ':' . $ha2; + $digest = hash('md5', $ha1 . ':' . $message); + + // If our digest matches the client's let them in, otherwise return + // a 401 code and exit to prevent access to the protected resource. + if ($this->_secureStringCompare($digest, $data['response'])) { + $identity = array('username'=>$data['username'], 'realm'=>$data['realm']); + return new Zend_Auth_Result(Zend_Auth_Result::SUCCESS, $identity); + } else { + return $this->_challengeClient(); + } + } + + /** + * Calculate Nonce + * + * @return string The nonce value + */ + protected function _calcNonce() + { + // Once subtle consequence of this timeout calculation is that it + // actually divides all of time into _nonceTimeout-sized sections, such + // that the value of timeout is the point in time of the next + // approaching "boundary" of a section. This allows the server to + // consistently generate the same timeout (and hence the same nonce + // value) across requests, but only as long as one of those + // "boundaries" is not crossed between requests. If that happens, the + // nonce will change on its own, and effectively log the user out. This + // would be surprising if the user just logged in. + $timeout = ceil(time() / $this->_nonceTimeout) * $this->_nonceTimeout; + + $nonce = hash('md5', $timeout . ':' . $this->_request->getServer('HTTP_USER_AGENT') . ':' . __CLASS__); + return $nonce; + } + + /** + * Calculate Opaque + * + * The opaque string can be anything; the client must return it exactly as + * it was sent. It may be useful to store data in this string in some + * applications. Ideally, a new value for this would be generated each time + * a WWW-Authenticate header is sent (in order to reduce predictability), + * but we would have to be able to create the same exact value across at + * least two separate requests from the same client. + * + * @return string The opaque value + */ + protected function _calcOpaque() + { + return hash('md5', 'Opaque Data:' . __CLASS__); + } + + /** + * Parse Digest Authorization header + * + * @param string $header Client's Authorization: HTTP header + * @return array|false Data elements from header, or false if any part of + * the header is invalid + */ + protected function _parseDigestAuth($header) + { + $temp = null; + $data = array(); + + // See ZF-1052. Detect invalid usernames instead of just returning a + // 400 code. + $ret = preg_match('/username="([^"]+)"/', $header, $temp); + if (!$ret || empty($temp[1]) + || !ctype_print($temp[1]) + || strpos($temp[1], ':') !== false) { + $data['username'] = '::invalid::'; + } else { + $data['username'] = $temp[1]; + } + $temp = null; + + $ret = preg_match('/realm="([^"]+)"/', $header, $temp); + if (!$ret || empty($temp[1])) { + return false; + } + if (!ctype_print($temp[1]) || strpos($temp[1], ':') !== false) { + return false; + } else { + $data['realm'] = $temp[1]; + } + $temp = null; + + $ret = preg_match('/nonce="([^"]+)"/', $header, $temp); + if (!$ret || empty($temp[1])) { + return false; + } + if (!ctype_xdigit($temp[1])) { + return false; + } else { + $data['nonce'] = $temp[1]; + } + $temp = null; + + $ret = preg_match('/uri="([^"]+)"/', $header, $temp); + if (!$ret || empty($temp[1])) { + return false; + } + // Section 3.2.2.5 in RFC 2617 says the authenticating server must + // verify that the URI field in the Authorization header is for the + // same resource requested in the Request Line. + $rUri = @parse_url($this->_request->getRequestUri()); + $cUri = @parse_url($temp[1]); + if (false === $rUri || false === $cUri) { + return false; + } else { + // Make sure the path portion of both URIs is the same + if ($rUri['path'] != $cUri['path']) { + return false; + } + // Section 3.2.2.5 seems to suggest that the value of the URI + // Authorization field should be made into an absolute URI if the + // Request URI is absolute, but it's vague, and that's a bunch of + // code I don't want to write right now. + $data['uri'] = $temp[1]; + } + $temp = null; + + $ret = preg_match('/response="([^"]+)"/', $header, $temp); + if (!$ret || empty($temp[1])) { + return false; + } + if (32 != strlen($temp[1]) || !ctype_xdigit($temp[1])) { + return false; + } else { + $data['response'] = $temp[1]; + } + $temp = null; + + // The spec says this should default to MD5 if omitted. OK, so how does + // that square with the algo we send out in the WWW-Authenticate header, + // if it can easily be overridden by the client? + $ret = preg_match('/algorithm="?(' . $this->_algo . ')"?/', $header, $temp); + if ($ret && !empty($temp[1]) + && in_array($temp[1], $this->_supportedAlgos)) { + $data['algorithm'] = $temp[1]; + } else { + $data['algorithm'] = 'MD5'; // = $this->_algo; ? + } + $temp = null; + + // Not optional in this implementation + $ret = preg_match('/cnonce="([^"]+)"/', $header, $temp); + if (!$ret || empty($temp[1])) { + return false; + } + if (!ctype_print($temp[1])) { + return false; + } else { + $data['cnonce'] = $temp[1]; + } + $temp = null; + + // If the server sent an opaque value, the client must send it back + if ($this->_useOpaque) { + $ret = preg_match('/opaque="([^"]+)"/', $header, $temp); + if (!$ret || empty($temp[1])) { + + // Big surprise: IE isn't RFC 2617-compliant. + if (false !== strpos($this->_request->getHeader('User-Agent'), 'MSIE')) { + $temp[1] = ''; + $this->_ieNoOpaque = true; + } else { + return false; + } + } + // This implementation only sends MD5 hex strings in the opaque value + if (!$this->_ieNoOpaque && + (32 != strlen($temp[1]) || !ctype_xdigit($temp[1]))) { + return false; + } else { + $data['opaque'] = $temp[1]; + } + $temp = null; + } + + // Not optional in this implementation, but must be one of the supported + // qop types + $ret = preg_match('/qop="?(' . implode('|', $this->_supportedQops) . ')"?/', $header, $temp); + if (!$ret || empty($temp[1])) { + return false; + } + if (!in_array($temp[1], $this->_supportedQops)) { + return false; + } else { + $data['qop'] = $temp[1]; + } + $temp = null; + + // Not optional in this implementation. The spec says this value + // shouldn't be a quoted string, but apparently some implementations + // quote it anyway. See ZF-1544. + $ret = preg_match('/nc="?([0-9A-Fa-f]{8})"?/', $header, $temp); + if (!$ret || empty($temp[1])) { + return false; + } + if (8 != strlen($temp[1]) || !ctype_xdigit($temp[1])) { + return false; + } else { + $data['nc'] = $temp[1]; + } + $temp = null; + + return $data; + } + + /** + * Securely compare two strings for equality while avoided C level memcmp() + * optimisations capable of leaking timing information useful to an attacker + * attempting to iteratively guess the unknown string (e.g. password) being + * compared against. + * + * @param string $a + * @param string $b + * @return bool + */ + protected function _secureStringCompare($a, $b) + { + if (strlen($a) !== strlen($b)) { + return false; + } + $result = 0; + for ($i = 0; $i < strlen($a); $i++) { + $result |= ord($a[$i]) ^ ord($b[$i]); + } + return $result == 0; + } +} diff --git a/lib/zend/Zend/Auth/Adapter/Http/Resolver/Exception.php b/lib/zend/Zend/Auth/Adapter/Http/Resolver/Exception.php new file mode 100644 index 00000000000..e7e2a4e8262 --- /dev/null +++ b/lib/zend/Zend/Auth/Adapter/Http/Resolver/Exception.php @@ -0,0 +1,40 @@ +setFile($path); + } + } + + /** + * Set the path to the credentials file + * + * @param string $path + * @throws Zend_Auth_Adapter_Http_Resolver_Exception + * @return Zend_Auth_Adapter_Http_Resolver_File Provides a fluent interface + */ + public function setFile($path) + { + if (empty($path) || !is_readable($path)) { + /** + * @see Zend_Auth_Adapter_Http_Resolver_Exception + */ + require_once 'Zend/Auth/Adapter/Http/Resolver/Exception.php'; + throw new Zend_Auth_Adapter_Http_Resolver_Exception('Path not readable: ' . $path); + } + $this->_file = $path; + + return $this; + } + + /** + * Returns the path to the credentials file + * + * @return string + */ + public function getFile() + { + return $this->_file; + } + + /** + * Resolve credentials + * + * Only the first matching username/realm combination in the file is + * returned. If the file contains credentials for Digest authentication, + * the returned string is the password hash, or h(a1) from RFC 2617. The + * returned string is the plain-text password for Basic authentication. + * + * The expected format of the file is: + * username:realm:sharedSecret + * + * That is, each line consists of the user's username, the applicable + * authentication realm, and the password or hash, each delimited by + * colons. + * + * @param string $username Username + * @param string $realm Authentication Realm + * @throws Zend_Auth_Adapter_Http_Resolver_Exception + * @return string|false User's shared secret, if the user is found in the + * realm, false otherwise. + */ + public function resolve($username, $realm) + { + if (empty($username)) { + /** + * @see Zend_Auth_Adapter_Http_Resolver_Exception + */ + require_once 'Zend/Auth/Adapter/Http/Resolver/Exception.php'; + throw new Zend_Auth_Adapter_Http_Resolver_Exception('Username is required'); + } else if (!ctype_print($username) || strpos($username, ':') !== false) { + /** + * @see Zend_Auth_Adapter_Http_Resolver_Exception + */ + require_once 'Zend/Auth/Adapter/Http/Resolver/Exception.php'; + throw new Zend_Auth_Adapter_Http_Resolver_Exception('Username must consist only of printable characters, ' + . 'excluding the colon'); + } + if (empty($realm)) { + /** + * @see Zend_Auth_Adapter_Http_Resolver_Exception + */ + require_once 'Zend/Auth/Adapter/Http/Resolver/Exception.php'; + throw new Zend_Auth_Adapter_Http_Resolver_Exception('Realm is required'); + } else if (!ctype_print($realm) || strpos($realm, ':') !== false) { + /** + * @see Zend_Auth_Adapter_Http_Resolver_Exception + */ + require_once 'Zend/Auth/Adapter/Http/Resolver/Exception.php'; + throw new Zend_Auth_Adapter_Http_Resolver_Exception('Realm must consist only of printable characters, ' + . 'excluding the colon.'); + } + + // Open file, read through looking for matching credentials + $fp = @fopen($this->_file, 'r'); + if (!$fp) { + /** + * @see Zend_Auth_Adapter_Http_Resolver_Exception + */ + require_once 'Zend/Auth/Adapter/Http/Resolver/Exception.php'; + throw new Zend_Auth_Adapter_Http_Resolver_Exception('Unable to open password file: ' . $this->_file); + } + + // No real validation is done on the contents of the password file. The + // assumption is that we trust the administrators to keep it secure. + while (($line = fgetcsv($fp, 512, ':')) !== false) { + if ($line[0] == $username && $line[1] == $realm) { + $password = $line[2]; + fclose($fp); + return $password; + } + } + + fclose($fp); + return false; + } +} diff --git a/lib/zend/Zend/Auth/Adapter/Http/Resolver/Interface.php b/lib/zend/Zend/Auth/Adapter/Http/Resolver/Interface.php new file mode 100644 index 00000000000..4326ee8202f --- /dev/null +++ b/lib/zend/Zend/Auth/Adapter/Http/Resolver/Interface.php @@ -0,0 +1,47 @@ + self::SUCCESS ) { + $code = 1; + } + + $this->_code = $code; + $this->_identity = $identity; + $this->_messages = $messages; + } + + /** + * Returns whether the result represents a successful authentication attempt + * + * @return boolean + */ + public function isValid() + { + return ($this->_code > 0) ? true : false; + } + + /** + * getCode() - Get the result code for this authentication attempt + * + * @return int + */ + public function getCode() + { + return $this->_code; + } + + /** + * Returns the identity used in the authentication attempt + * + * @return mixed + */ + public function getIdentity() + { + return $this->_identity; + } + + /** + * Returns an array of string reasons why the authentication attempt was unsuccessful + * + * If authentication was successful, this method returns an empty array. + * + * @return array + */ + public function getMessages() + { + return $this->_messages; + } +} diff --git a/lib/zend/Zend/Auth/Storage/Exception.php b/lib/zend/Zend/Auth/Storage/Exception.php new file mode 100644 index 00000000000..542b6708a79 --- /dev/null +++ b/lib/zend/Zend/Auth/Storage/Exception.php @@ -0,0 +1,38 @@ +_data); + } + + /** + * Returns the contents of storage + * Behavior is undefined when storage is empty. + * + * @throws Zend_Auth_Storage_Exception If reading contents from storage is impossible + * @return mixed + */ + public function read() + { + return $this->_data; + } + + /** + * Writes $contents to storage + * + * @param mixed $contents + * @throws Zend_Auth_Storage_Exception If writing $contents to storage is impossible + * @return void + */ + public function write($contents) + { + $this->_data = $contents; + } + + /** + * Clears contents from storage + * + * @throws Zend_Auth_Storage_Exception If clearing contents from storage is impossible + * @return void + */ + public function clear() + { + $this->_data = null; + } +} diff --git a/lib/zend/Zend/Auth/Storage/Session.php b/lib/zend/Zend/Auth/Storage/Session.php new file mode 100644 index 00000000000..c3680f6faf7 --- /dev/null +++ b/lib/zend/Zend/Auth/Storage/Session.php @@ -0,0 +1,149 @@ +_namespace = $namespace; + $this->_member = $member; + $this->_session = new Zend_Session_Namespace($this->_namespace); + } + + /** + * Returns the session namespace + * + * @return string + */ + public function getNamespace() + { + return $this->_namespace; + } + + /** + * Returns the name of the session object member + * + * @return string + */ + public function getMember() + { + return $this->_member; + } + + /** + * Defined by Zend_Auth_Storage_Interface + * + * @return boolean + */ + public function isEmpty() + { + return !isset($this->_session->{$this->_member}); + } + + /** + * Defined by Zend_Auth_Storage_Interface + * + * @return mixed + */ + public function read() + { + return $this->_session->{$this->_member}; + } + + /** + * Defined by Zend_Auth_Storage_Interface + * + * @param mixed $contents + * @return void + */ + public function write($contents) + { + $this->_session->{$this->_member} = $contents; + } + + /** + * Defined by Zend_Auth_Storage_Interface + * + * @return void + */ + public function clear() + { + unset($this->_session->{$this->_member}); + } +} diff --git a/lib/zend/Zend/Cache.php b/lib/zend/Zend/Cache.php new file mode 100644 index 00000000000..dc818f30e57 --- /dev/null +++ b/lib/zend/Zend/Cache.php @@ -0,0 +1,250 @@ +setBackend($backendObject); + return $frontendObject; + } + + /** + * Backend Constructor + * + * @param string $backend + * @param array $backendOptions + * @param boolean $customBackendNaming + * @param boolean $autoload + * @return Zend_Cache_Backend + */ + public static function _makeBackend($backend, $backendOptions, $customBackendNaming = false, $autoload = false) + { + if (!$customBackendNaming) { + $backend = self::_normalizeName($backend); + } + if (in_array($backend, Zend_Cache::$standardBackends)) { + // we use a standard backend + $backendClass = 'Zend_Cache_Backend_' . $backend; + // security controls are explicit + require_once str_replace('_', DIRECTORY_SEPARATOR, $backendClass) . '.php'; + } else { + // we use a custom backend + if (!preg_match('~^[\w\\\\]+$~D', $backend)) { + Zend_Cache::throwException("Invalid backend name [$backend]"); + } + if (!$customBackendNaming) { + // we use this boolean to avoid an API break + $backendClass = 'Zend_Cache_Backend_' . $backend; + } else { + $backendClass = $backend; + } + if (!$autoload) { + $file = str_replace('_', DIRECTORY_SEPARATOR, $backendClass) . '.php'; + if (!(self::_isReadable($file))) { + self::throwException("file $file not found in include_path"); + } + require_once $file; + } + } + return new $backendClass($backendOptions); + } + + /** + * Frontend Constructor + * + * @param string $frontend + * @param array $frontendOptions + * @param boolean $customFrontendNaming + * @param boolean $autoload + * @return Zend_Cache_Core|Zend_Cache_Frontend + */ + public static function _makeFrontend($frontend, $frontendOptions = array(), $customFrontendNaming = false, $autoload = false) + { + if (!$customFrontendNaming) { + $frontend = self::_normalizeName($frontend); + } + if (in_array($frontend, self::$standardFrontends)) { + // we use a standard frontend + // For perfs reasons, with frontend == 'Core', we can interact with the Core itself + $frontendClass = 'Zend_Cache_' . ($frontend != 'Core' ? 'Frontend_' : '') . $frontend; + // security controls are explicit + require_once str_replace('_', DIRECTORY_SEPARATOR, $frontendClass) . '.php'; + } else { + // we use a custom frontend + if (!preg_match('~^[\w\\\\]+$~D', $frontend)) { + Zend_Cache::throwException("Invalid frontend name [$frontend]"); + } + if (!$customFrontendNaming) { + // we use this boolean to avoid an API break + $frontendClass = 'Zend_Cache_Frontend_' . $frontend; + } else { + $frontendClass = $frontend; + } + if (!$autoload) { + $file = str_replace('_', DIRECTORY_SEPARATOR, $frontendClass) . '.php'; + if (!(self::_isReadable($file))) { + self::throwException("file $file not found in include_path"); + } + require_once $file; + } + } + return new $frontendClass($frontendOptions); + } + + /** + * Throw an exception + * + * Note : for perf reasons, the "load" of Zend/Cache/Exception is dynamic + * @param string $msg Message for the exception + * @throws Zend_Cache_Exception + */ + public static function throwException($msg, Exception $e = null) + { + // For perfs reasons, we use this dynamic inclusion + require_once 'Zend/Cache/Exception.php'; + throw new Zend_Cache_Exception($msg, 0, $e); + } + + /** + * Normalize frontend and backend names to allow multiple words TitleCased + * + * @param string $name Name to normalize + * @return string + */ + protected static function _normalizeName($name) + { + $name = ucfirst(strtolower($name)); + $name = str_replace(array('-', '_', '.'), ' ', $name); + $name = ucwords($name); + $name = str_replace(' ', '', $name); + if (stripos($name, 'ZendServer') === 0) { + $name = 'ZendServer_' . substr($name, strlen('ZendServer')); + } + + return $name; + } + + /** + * Returns TRUE if the $filename is readable, or FALSE otherwise. + * This function uses the PHP include_path, where PHP's is_readable() + * does not. + * + * Note : this method comes from Zend_Loader (see #ZF-2891 for details) + * + * @param string $filename + * @return boolean + */ + private static function _isReadable($filename) + { + if (!$fh = @fopen($filename, 'r', true)) { + return false; + } + @fclose($fh); + return true; + } + +} diff --git a/lib/zend/Zend/Cache/Backend.php b/lib/zend/Zend/Cache/Backend.php new file mode 100644 index 00000000000..83f1af5f121 --- /dev/null +++ b/lib/zend/Zend/Cache/Backend.php @@ -0,0 +1,288 @@ + (int) lifetime : + * - Cache lifetime (in seconds) + * - If null, the cache is valid forever + * + * =====> (int) logging : + * - if set to true, a logging is activated throw Zend_Log + * + * @var array directives + */ + protected $_directives = array( + 'lifetime' => 3600, + 'logging' => false, + 'logger' => null + ); + + /** + * Available options + * + * @var array available options + */ + protected $_options = array(); + + /** + * Constructor + * + * @param array $options Associative array of options + */ + public function __construct(array $options = array()) + { + foreach ($options as $name => $value) { + $this->setOption($name, $value); + } + } + + /** + * Set the frontend directives + * + * @param array $directives Assoc of directives + * @throws Zend_Cache_Exception + * @return void + */ + public function setDirectives($directives) + { + if (!is_array($directives)) Zend_Cache::throwException('Directives parameter must be an array'); + while (list($name, $value) = each($directives)) { + if (!is_string($name)) { + Zend_Cache::throwException("Incorrect option name : $name"); + } + $name = strtolower($name); + if (array_key_exists($name, $this->_directives)) { + $this->_directives[$name] = $value; + } + + } + + $this->_loggerSanity(); + } + + /** + * Set an option + * + * @param string $name + * @param mixed $value + * @throws Zend_Cache_Exception + * @return void + */ + public function setOption($name, $value) + { + if (!is_string($name)) { + Zend_Cache::throwException("Incorrect option name : $name"); + } + $name = strtolower($name); + if (array_key_exists($name, $this->_options)) { + $this->_options[$name] = $value; + } + } + + /** + * Returns an option + * + * @param string $name Optional, the options name to return + * @throws Zend_Cache_Exceptions + * @return mixed + */ + public function getOption($name) + { + $name = strtolower($name); + + if (array_key_exists($name, $this->_options)) { + return $this->_options[$name]; + } + + if (array_key_exists($name, $this->_directives)) { + return $this->_directives[$name]; + } + + Zend_Cache::throwException("Incorrect option name : {$name}"); + } + + /** + * Get the life time + * + * if $specificLifetime is not false, the given specific life time is used + * else, the global lifetime is used + * + * @param int $specificLifetime + * @return int Cache life time + */ + public function getLifetime($specificLifetime) + { + if ($specificLifetime === false) { + return $this->_directives['lifetime']; + } + return $specificLifetime; + } + + /** + * Return true if the automatic cleaning is available for the backend + * + * DEPRECATED : use getCapabilities() instead + * + * @deprecated + * @return boolean + */ + public function isAutomaticCleaningAvailable() + { + return true; + } + + /** + * Determine system TMP directory and detect if we have read access + * + * inspired from Zend_File_Transfer_Adapter_Abstract + * + * @return string + * @throws Zend_Cache_Exception if unable to determine directory + */ + public function getTmpDir() + { + $tmpdir = array(); + foreach (array($_ENV, $_SERVER) as $tab) { + foreach (array('TMPDIR', 'TEMP', 'TMP', 'windir', 'SystemRoot') as $key) { + if (isset($tab[$key]) && is_string($tab[$key])) { + if (($key == 'windir') or ($key == 'SystemRoot')) { + $dir = realpath($tab[$key] . '\\temp'); + } else { + $dir = realpath($tab[$key]); + } + if ($this->_isGoodTmpDir($dir)) { + return $dir; + } + } + } + } + $upload = ini_get('upload_tmp_dir'); + if ($upload) { + $dir = realpath($upload); + if ($this->_isGoodTmpDir($dir)) { + return $dir; + } + } + if (function_exists('sys_get_temp_dir')) { + $dir = sys_get_temp_dir(); + if ($this->_isGoodTmpDir($dir)) { + return $dir; + } + } + // Attemp to detect by creating a temporary file + $tempFile = tempnam(md5(uniqid(rand(), TRUE)), ''); + if ($tempFile) { + $dir = realpath(dirname($tempFile)); + unlink($tempFile); + if ($this->_isGoodTmpDir($dir)) { + return $dir; + } + } + if ($this->_isGoodTmpDir('/tmp')) { + return '/tmp'; + } + if ($this->_isGoodTmpDir('\\temp')) { + return '\\temp'; + } + Zend_Cache::throwException('Could not determine temp directory, please specify a cache_dir manually'); + } + + /** + * Verify if the given temporary directory is readable and writable + * + * @param string $dir temporary directory + * @return boolean true if the directory is ok + */ + protected function _isGoodTmpDir($dir) + { + if (is_readable($dir)) { + if (is_writable($dir)) { + return true; + } + } + return false; + } + + /** + * Make sure if we enable logging that the Zend_Log class + * is available. + * Create a default log object if none is set. + * + * @throws Zend_Cache_Exception + * @return void + */ + protected function _loggerSanity() + { + if (!isset($this->_directives['logging']) || !$this->_directives['logging']) { + return; + } + + if (isset($this->_directives['logger'])) { + if ($this->_directives['logger'] instanceof Zend_Log) { + return; + } + Zend_Cache::throwException('Logger object is not an instance of Zend_Log class.'); + } + + // Create a default logger to the standard output stream + require_once 'Zend/Log.php'; + require_once 'Zend/Log/Writer/Stream.php'; + require_once 'Zend/Log/Filter/Priority.php'; + $logger = new Zend_Log(new Zend_Log_Writer_Stream('php://output')); + $logger->addFilter(new Zend_Log_Filter_Priority(Zend_Log::WARN, '<=')); + $this->_directives['logger'] = $logger; + } + + /** + * Log a message at the WARN (4) priority. + * + * @param string $message + * @param int $priority + * @return void + */ + protected function _log($message, $priority = 4) + { + if (!$this->_directives['logging']) { + return; + } + + if (!isset($this->_directives['logger'])) { + Zend_Cache::throwException('Logging is enabled but logger is not set.'); + } + $logger = $this->_directives['logger']; + if (!$logger instanceof Zend_Log) { + Zend_Cache::throwException('Logger object is not an instance of Zend_Log class.'); + } + $logger->log($message, $priority); + } +} diff --git a/lib/zend/Zend/Cache/Backend/Apc.php b/lib/zend/Zend/Cache/Backend/Apc.php new file mode 100644 index 00000000000..5a09becdcfd --- /dev/null +++ b/lib/zend/Zend/Cache/Backend/Apc.php @@ -0,0 +1,355 @@ + infinite lifetime) + * @return boolean true if no problem + */ + public function save($data, $id, $tags = array(), $specificLifetime = false) + { + $lifetime = $this->getLifetime($specificLifetime); + $result = apc_store($id, array($data, time(), $lifetime), $lifetime); + if (count($tags) > 0) { + $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_APC_BACKEND); + } + return $result; + } + + /** + * Remove a cache record + * + * @param string $id cache id + * @return boolean true if no problem + */ + public function remove($id) + { + return apc_delete($id); + } + + /** + * Clean some cache records + * + * Available modes are : + * 'all' (default) => remove all cache entries ($tags is not used) + * 'old' => unsupported + * 'matchingTag' => unsupported + * 'notMatchingTag' => unsupported + * 'matchingAnyTag' => unsupported + * + * @param string $mode clean mode + * @param array $tags array of tags + * @throws Zend_Cache_Exception + * @return boolean true if no problem + */ + public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array()) + { + switch ($mode) { + case Zend_Cache::CLEANING_MODE_ALL: + return apc_clear_cache('user'); + break; + case Zend_Cache::CLEANING_MODE_OLD: + $this->_log("Zend_Cache_Backend_Apc::clean() : CLEANING_MODE_OLD is unsupported by the Apc backend"); + break; + case Zend_Cache::CLEANING_MODE_MATCHING_TAG: + case Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG: + case Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG: + $this->_log(self::TAGS_UNSUPPORTED_BY_CLEAN_OF_APC_BACKEND); + break; + default: + Zend_Cache::throwException('Invalid mode for clean() method'); + break; + } + } + + /** + * Return true if the automatic cleaning is available for the backend + * + * DEPRECATED : use getCapabilities() instead + * + * @deprecated + * @return boolean + */ + public function isAutomaticCleaningAvailable() + { + return false; + } + + /** + * Return the filling percentage of the backend storage + * + * @throws Zend_Cache_Exception + * @return int integer between 0 and 100 + */ + public function getFillingPercentage() + { + $mem = apc_sma_info(true); + $memSize = $mem['num_seg'] * $mem['seg_size']; + $memAvailable= $mem['avail_mem']; + $memUsed = $memSize - $memAvailable; + if ($memSize == 0) { + Zend_Cache::throwException('can\'t get apc memory size'); + } + if ($memUsed > $memSize) { + return 100; + } + return ((int) (100. * ($memUsed / $memSize))); + } + + /** + * Return an array of stored tags + * + * @return array array of stored tags (string) + */ + public function getTags() + { + $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_APC_BACKEND); + return array(); + } + + /** + * Return an array of stored cache ids which match given tags + * + * In case of multiple tags, a logical AND is made between tags + * + * @param array $tags array of tags + * @return array array of matching cache ids (string) + */ + public function getIdsMatchingTags($tags = array()) + { + $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_APC_BACKEND); + return array(); + } + + /** + * Return an array of stored cache ids which don't match given tags + * + * In case of multiple tags, a logical OR is made between tags + * + * @param array $tags array of tags + * @return array array of not matching cache ids (string) + */ + public function getIdsNotMatchingTags($tags = array()) + { + $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_APC_BACKEND); + return array(); + } + + /** + * Return an array of stored cache ids which match any given tags + * + * In case of multiple tags, a logical AND is made between tags + * + * @param array $tags array of tags + * @return array array of any matching cache ids (string) + */ + public function getIdsMatchingAnyTags($tags = array()) + { + $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_APC_BACKEND); + return array(); + } + + /** + * Return an array of stored cache ids + * + * @return array array of stored cache ids (string) + */ + public function getIds() + { + $ids = array(); + $iterator = new APCIterator('user', null, APC_ITER_KEY); + foreach ($iterator as $item) { + $ids[] = $item['key']; + } + + return $ids; + } + + /** + * Return an array of metadatas for the given cache id + * + * The array must include these keys : + * - expire : the expire timestamp + * - tags : a string array of tags + * - mtime : timestamp of last modification time + * + * @param string $id cache id + * @return array array of metadatas (false if the cache id is not found) + */ + public function getMetadatas($id) + { + $tmp = apc_fetch($id); + if (is_array($tmp)) { + $data = $tmp[0]; + $mtime = $tmp[1]; + if (!isset($tmp[2])) { + // because this record is only with 1.7 release + // if old cache records are still there... + return false; + } + $lifetime = $tmp[2]; + return array( + 'expire' => $mtime + $lifetime, + 'tags' => array(), + 'mtime' => $mtime + ); + } + return false; + } + + /** + * Give (if possible) an extra lifetime to the given cache id + * + * @param string $id cache id + * @param int $extraLifetime + * @return boolean true if ok + */ + public function touch($id, $extraLifetime) + { + $tmp = apc_fetch($id); + if (is_array($tmp)) { + $data = $tmp[0]; + $mtime = $tmp[1]; + if (!isset($tmp[2])) { + // because this record is only with 1.7 release + // if old cache records are still there... + return false; + } + $lifetime = $tmp[2]; + $newLifetime = $lifetime - (time() - $mtime) + $extraLifetime; + if ($newLifetime <=0) { + return false; + } + apc_store($id, array($data, time(), $newLifetime), $newLifetime); + return true; + } + return false; + } + + /** + * Return an associative array of capabilities (booleans) of the backend + * + * The array must include these keys : + * - automatic_cleaning (is automating cleaning necessary) + * - tags (are tags supported) + * - expired_read (is it possible to read expired cache records + * (for doNotTestCacheValidity option for example)) + * - priority does the backend deal with priority when saving + * - infinite_lifetime (is infinite lifetime can work with this backend) + * - get_list (is it possible to get the list of cache ids and the complete list of tags) + * + * @return array associative of with capabilities + */ + public function getCapabilities() + { + return array( + 'automatic_cleaning' => false, + 'tags' => false, + 'expired_read' => false, + 'priority' => false, + 'infinite_lifetime' => false, + 'get_list' => true + ); + } + +} diff --git a/lib/zend/Zend/Cache/Backend/BlackHole.php b/lib/zend/Zend/Cache/Backend/BlackHole.php new file mode 100644 index 00000000000..0fe1c9d0525 --- /dev/null +++ b/lib/zend/Zend/Cache/Backend/BlackHole.php @@ -0,0 +1,250 @@ + infinite lifetime) + * @return boolean true if no problem + */ + public function save($data, $id, $tags = array(), $specificLifetime = false) + { + return true; + } + + /** + * Remove a cache record + * + * @param string $id cache id + * @return boolean true if no problem + */ + public function remove($id) + { + return true; + } + + /** + * Clean some cache records + * + * Available modes are : + * 'all' (default) => remove all cache entries ($tags is not used) + * 'old' => remove too old cache entries ($tags is not used) + * 'matchingTag' => remove cache entries matching all given tags + * ($tags can be an array of strings or a single string) + * 'notMatchingTag' => remove cache entries not matching one of the given tags + * ($tags can be an array of strings or a single string) + * 'matchingAnyTag' => remove cache entries matching any given tags + * ($tags can be an array of strings or a single string) + * + * @param string $mode clean mode + * @param tags array $tags array of tags + * @return boolean true if no problem + */ + public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array()) + { + return true; + } + + /** + * Return an array of stored cache ids + * + * @return array array of stored cache ids (string) + */ + public function getIds() + { + return array(); + } + + /** + * Return an array of stored tags + * + * @return array array of stored tags (string) + */ + public function getTags() + { + return array(); + } + + /** + * Return an array of stored cache ids which match given tags + * + * In case of multiple tags, a logical AND is made between tags + * + * @param array $tags array of tags + * @return array array of matching cache ids (string) + */ + public function getIdsMatchingTags($tags = array()) + { + return array(); + } + + /** + * Return an array of stored cache ids which don't match given tags + * + * In case of multiple tags, a logical OR is made between tags + * + * @param array $tags array of tags + * @return array array of not matching cache ids (string) + */ + public function getIdsNotMatchingTags($tags = array()) + { + return array(); + } + + /** + * Return an array of stored cache ids which match any given tags + * + * In case of multiple tags, a logical AND is made between tags + * + * @param array $tags array of tags + * @return array array of any matching cache ids (string) + */ + public function getIdsMatchingAnyTags($tags = array()) + { + return array(); + } + + /** + * Return the filling percentage of the backend storage + * + * @return int integer between 0 and 100 + * @throws Zend_Cache_Exception + */ + public function getFillingPercentage() + { + return 0; + } + + /** + * Return an array of metadatas for the given cache id + * + * The array must include these keys : + * - expire : the expire timestamp + * - tags : a string array of tags + * - mtime : timestamp of last modification time + * + * @param string $id cache id + * @return array array of metadatas (false if the cache id is not found) + */ + public function getMetadatas($id) + { + return false; + } + + /** + * Give (if possible) an extra lifetime to the given cache id + * + * @param string $id cache id + * @param int $extraLifetime + * @return boolean true if ok + */ + public function touch($id, $extraLifetime) + { + return false; + } + + /** + * Return an associative array of capabilities (booleans) of the backend + * + * The array must include these keys : + * - automatic_cleaning (is automating cleaning necessary) + * - tags (are tags supported) + * - expired_read (is it possible to read expired cache records + * (for doNotTestCacheValidity option for example)) + * - priority does the backend deal with priority when saving + * - infinite_lifetime (is infinite lifetime can work with this backend) + * - get_list (is it possible to get the list of cache ids and the complete list of tags) + * + * @return array associative of with capabilities + */ + public function getCapabilities() + { + return array( + 'automatic_cleaning' => true, + 'tags' => true, + 'expired_read' => true, + 'priority' => true, + 'infinite_lifetime' => true, + 'get_list' => true, + ); + } + + /** + * PUBLIC METHOD FOR UNIT TESTING ONLY ! + * + * Force a cache record to expire + * + * @param string $id cache id + */ + public function ___expire($id) + { + } +} diff --git a/lib/zend/Zend/Cache/Backend/ExtendedInterface.php b/lib/zend/Zend/Cache/Backend/ExtendedInterface.php new file mode 100644 index 00000000000..0dd8bdf414c --- /dev/null +++ b/lib/zend/Zend/Cache/Backend/ExtendedInterface.php @@ -0,0 +1,126 @@ + (string) cache_dir : + * - Directory where to put the cache files + * + * =====> (boolean) file_locking : + * - Enable / disable file_locking + * - Can avoid cache corruption under bad circumstances but it doesn't work on multithread + * webservers and on NFS filesystems for example + * + * =====> (boolean) read_control : + * - Enable / disable read control + * - If enabled, a control key is embeded in cache file and this key is compared with the one + * calculated after the reading. + * + * =====> (string) read_control_type : + * - Type of read control (only if read control is enabled). Available values are : + * 'md5' for a md5 hash control (best but slowest) + * 'crc32' for a crc32 hash control (lightly less safe but faster, better choice) + * 'adler32' for an adler32 hash control (excellent choice too, faster than crc32) + * 'strlen' for a length only test (fastest) + * + * =====> (int) hashed_directory_level : + * - Hashed directory level + * - Set the hashed directory structure level. 0 means "no hashed directory + * structure", 1 means "one level of directory", 2 means "two levels"... + * This option can speed up the cache only when you have many thousands of + * cache file. Only specific benchs can help you to choose the perfect value + * for you. Maybe, 1 or 2 is a good start. + * + * =====> (int) hashed_directory_umask : + * - deprecated + * - Permissions for hashed directory structure + * + * =====> (int) hashed_directory_perm : + * - Permissions for hashed directory structure + * + * =====> (string) file_name_prefix : + * - prefix for cache files + * - be really carefull with this option because a too generic value in a system cache dir + * (like /tmp) can cause disasters when cleaning the cache + * + * =====> (int) cache_file_umask : + * - deprecated + * - Permissions for cache files + * + * =====> (int) cache_file_perm : + * - Permissions for cache files + * + * =====> (int) metatadatas_array_max_size : + * - max size for the metadatas array (don't change this value unless you + * know what you are doing) + * + * @var array available options + */ + protected $_options = array( + 'cache_dir' => null, + 'file_locking' => true, + 'read_control' => true, + 'read_control_type' => 'crc32', + 'hashed_directory_level' => 0, + 'hashed_directory_perm' => 0700, + 'file_name_prefix' => 'zend_cache', + 'cache_file_perm' => 0600, + 'metadatas_array_max_size' => 100 + ); + + /** + * Array of metadatas (each item is an associative array) + * + * @var array + */ + protected $_metadatasArray = array(); + + + /** + * Constructor + * + * @param array $options associative array of options + * @throws Zend_Cache_Exception + */ + public function __construct(array $options = array()) + { + parent::__construct($options); + if ($this->_options['cache_dir'] !== null) { // particular case for this option + $this->setCacheDir($this->_options['cache_dir']); + } else { + $this->setCacheDir(self::getTmpDir() . DIRECTORY_SEPARATOR, false); + } + if (isset($this->_options['file_name_prefix'])) { // particular case for this option + if (!preg_match('~^[a-zA-Z0-9_]+$~D', $this->_options['file_name_prefix'])) { + Zend_Cache::throwException('Invalid file_name_prefix : must use only [a-zA-Z0-9_]'); + } + } + if ($this->_options['metadatas_array_max_size'] < 10) { + Zend_Cache::throwException('Invalid metadatas_array_max_size, must be > 10'); + } + + if (isset($options['hashed_directory_umask'])) { + // See #ZF-12047 + trigger_error("'hashed_directory_umask' is deprecated -> please use 'hashed_directory_perm' instead", E_USER_NOTICE); + if (!isset($options['hashed_directory_perm'])) { + $options['hashed_directory_perm'] = $options['hashed_directory_umask']; + } + } + if (isset($options['hashed_directory_perm']) && is_string($options['hashed_directory_perm'])) { + // See #ZF-4422 + $this->_options['hashed_directory_perm'] = octdec($this->_options['hashed_directory_perm']); + } + + if (isset($options['cache_file_umask'])) { + // See #ZF-12047 + trigger_error("'cache_file_umask' is deprecated -> please use 'cache_file_perm' instead", E_USER_NOTICE); + if (!isset($options['cache_file_perm'])) { + $options['cache_file_perm'] = $options['cache_file_umask']; + } + } + if (isset($options['cache_file_perm']) && is_string($options['cache_file_perm'])) { + // See #ZF-4422 + $this->_options['cache_file_perm'] = octdec($this->_options['cache_file_perm']); + } + } + + /** + * Set the cache_dir (particular case of setOption() method) + * + * @param string $value + * @param boolean $trailingSeparator If true, add a trailing separator is necessary + * @throws Zend_Cache_Exception + * @return void + */ + public function setCacheDir($value, $trailingSeparator = true) + { + if (!is_dir($value)) { + Zend_Cache::throwException(sprintf('cache_dir "%s" must be a directory', $value)); + } + if (!is_writable($value)) { + Zend_Cache::throwException(sprintf('cache_dir "%s" is not writable', $value)); + } + if ($trailingSeparator) { + // add a trailing DIRECTORY_SEPARATOR if necessary + $value = rtrim(realpath($value), '\\/') . DIRECTORY_SEPARATOR; + } + $this->_options['cache_dir'] = $value; + } + + /** + * Test if a cache is available for the given id and (if yes) return it (false else) + * + * @param string $id cache id + * @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested + * @return string|false cached datas + */ + public function load($id, $doNotTestCacheValidity = false) + { + if (!($this->_test($id, $doNotTestCacheValidity))) { + // The cache is not hit ! + return false; + } + $metadatas = $this->_getMetadatas($id); + $file = $this->_file($id); + $data = $this->_fileGetContents($file); + if ($this->_options['read_control']) { + $hashData = $this->_hash($data, $this->_options['read_control_type']); + $hashControl = $metadatas['hash']; + if ($hashData != $hashControl) { + // Problem detected by the read control ! + $this->_log('Zend_Cache_Backend_File::load() / read_control : stored hash and computed hash do not match'); + $this->remove($id); + return false; + } + } + return $data; + } + + /** + * Test if a cache is available or not (for the given id) + * + * @param string $id cache id + * @return mixed false (a cache is not available) or "last modified" timestamp (int) of the available cache record + */ + public function test($id) + { + clearstatcache(); + return $this->_test($id, false); + } + + /** + * Save some string datas into a cache record + * + * Note : $data is always "string" (serialization is done by the + * core not by the backend) + * + * @param string $data Datas to cache + * @param string $id Cache id + * @param array $tags Array of strings, the cache record will be tagged by each string entry + * @param boolean|int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime) + * @return boolean true if no problem + */ + public function save($data, $id, $tags = array(), $specificLifetime = false) + { + clearstatcache(); + $file = $this->_file($id); + $path = $this->_path($id); + if ($this->_options['hashed_directory_level'] > 0) { + if (!is_writable($path)) { + // maybe, we just have to build the directory structure + $this->_recursiveMkdirAndChmod($id); + } + if (!is_writable($path)) { + return false; + } + } + if ($this->_options['read_control']) { + $hash = $this->_hash($data, $this->_options['read_control_type']); + } else { + $hash = ''; + } + $metadatas = array( + 'hash' => $hash, + 'mtime' => time(), + 'expire' => $this->_expireTime($this->getLifetime($specificLifetime)), + 'tags' => $tags + ); + $res = $this->_setMetadatas($id, $metadatas); + if (!$res) { + $this->_log('Zend_Cache_Backend_File::save() / error on saving metadata'); + return false; + } + $res = $this->_filePutContents($file, $data); + return $res; + } + + /** + * Remove a cache record + * + * @param string $id cache id + * @return boolean true if no problem + */ + public function remove($id) + { + $file = $this->_file($id); + $boolRemove = $this->_remove($file); + $boolMetadata = $this->_delMetadatas($id); + return $boolMetadata && $boolRemove; + } + + /** + * Clean some cache records + * + * Available modes are : + * + * Zend_Cache::CLEANING_MODE_ALL (default) => remove all cache entries ($tags is not used) + * Zend_Cache::CLEANING_MODE_OLD => remove too old cache entries ($tags is not used) + * Zend_Cache::CLEANING_MODE_MATCHING_TAG => remove cache entries matching all given tags + * ($tags can be an array of strings or a single string) + * Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => remove cache entries not {matching one of the given tags} + * ($tags can be an array of strings or a single string) + * Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG => remove cache entries matching any given tags + * ($tags can be an array of strings or a single string) + * + * @param string $mode clean mode + * @param array $tags array of tags + * @return boolean true if no problem + */ + public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array()) + { + // We use this protected method to hide the recursive stuff + clearstatcache(); + return $this->_clean($this->_options['cache_dir'], $mode, $tags); + } + + /** + * Return an array of stored cache ids + * + * @return array array of stored cache ids (string) + */ + public function getIds() + { + return $this->_get($this->_options['cache_dir'], 'ids', array()); + } + + /** + * Return an array of stored tags + * + * @return array array of stored tags (string) + */ + public function getTags() + { + return $this->_get($this->_options['cache_dir'], 'tags', array()); + } + + /** + * Return an array of stored cache ids which match given tags + * + * In case of multiple tags, a logical AND is made between tags + * + * @param array $tags array of tags + * @return array array of matching cache ids (string) + */ + public function getIdsMatchingTags($tags = array()) + { + return $this->_get($this->_options['cache_dir'], 'matching', $tags); + } + + /** + * Return an array of stored cache ids which don't match given tags + * + * In case of multiple tags, a logical OR is made between tags + * + * @param array $tags array of tags + * @return array array of not matching cache ids (string) + */ + public function getIdsNotMatchingTags($tags = array()) + { + return $this->_get($this->_options['cache_dir'], 'notMatching', $tags); + } + + /** + * Return an array of stored cache ids which match any given tags + * + * In case of multiple tags, a logical AND is made between tags + * + * @param array $tags array of tags + * @return array array of any matching cache ids (string) + */ + public function getIdsMatchingAnyTags($tags = array()) + { + return $this->_get($this->_options['cache_dir'], 'matchingAny', $tags); + } + + /** + * Return the filling percentage of the backend storage + * + * @throws Zend_Cache_Exception + * @return int integer between 0 and 100 + */ + public function getFillingPercentage() + { + $free = disk_free_space($this->_options['cache_dir']); + $total = disk_total_space($this->_options['cache_dir']); + if ($total == 0) { + Zend_Cache::throwException('can\'t get disk_total_space'); + } else { + if ($free >= $total) { + return 100; + } + return ((int) (100. * ($total - $free) / $total)); + } + } + + /** + * Return an array of metadatas for the given cache id + * + * The array must include these keys : + * - expire : the expire timestamp + * - tags : a string array of tags + * - mtime : timestamp of last modification time + * + * @param string $id cache id + * @return array array of metadatas (false if the cache id is not found) + */ + public function getMetadatas($id) + { + $metadatas = $this->_getMetadatas($id); + if (!$metadatas) { + return false; + } + if (time() > $metadatas['expire']) { + return false; + } + return array( + 'expire' => $metadatas['expire'], + 'tags' => $metadatas['tags'], + 'mtime' => $metadatas['mtime'] + ); + } + + /** + * Give (if possible) an extra lifetime to the given cache id + * + * @param string $id cache id + * @param int $extraLifetime + * @return boolean true if ok + */ + public function touch($id, $extraLifetime) + { + $metadatas = $this->_getMetadatas($id); + if (!$metadatas) { + return false; + } + if (time() > $metadatas['expire']) { + return false; + } + $newMetadatas = array( + 'hash' => $metadatas['hash'], + 'mtime' => time(), + 'expire' => $metadatas['expire'] + $extraLifetime, + 'tags' => $metadatas['tags'] + ); + $res = $this->_setMetadatas($id, $newMetadatas); + if (!$res) { + return false; + } + return true; + } + + /** + * Return an associative array of capabilities (booleans) of the backend + * + * The array must include these keys : + * - automatic_cleaning (is automating cleaning necessary) + * - tags (are tags supported) + * - expired_read (is it possible to read expired cache records + * (for doNotTestCacheValidity option for example)) + * - priority does the backend deal with priority when saving + * - infinite_lifetime (is infinite lifetime can work with this backend) + * - get_list (is it possible to get the list of cache ids and the complete list of tags) + * + * @return array associative of with capabilities + */ + public function getCapabilities() + { + return array( + 'automatic_cleaning' => true, + 'tags' => true, + 'expired_read' => true, + 'priority' => false, + 'infinite_lifetime' => true, + 'get_list' => true + ); + } + + /** + * PUBLIC METHOD FOR UNIT TESTING ONLY ! + * + * Force a cache record to expire + * + * @param string $id cache id + */ + public function ___expire($id) + { + $metadatas = $this->_getMetadatas($id); + if ($metadatas) { + $metadatas['expire'] = 1; + $this->_setMetadatas($id, $metadatas); + } + } + + /** + * Get a metadatas record + * + * @param string $id Cache id + * @return array|false Associative array of metadatas + */ + protected function _getMetadatas($id) + { + if (isset($this->_metadatasArray[$id])) { + return $this->_metadatasArray[$id]; + } else { + $metadatas = $this->_loadMetadatas($id); + if (!$metadatas) { + return false; + } + $this->_setMetadatas($id, $metadatas, false); + return $metadatas; + } + } + + /** + * Set a metadatas record + * + * @param string $id Cache id + * @param array $metadatas Associative array of metadatas + * @param boolean $save optional pass false to disable saving to file + * @return boolean True if no problem + */ + protected function _setMetadatas($id, $metadatas, $save = true) + { + if (count($this->_metadatasArray) >= $this->_options['metadatas_array_max_size']) { + $n = (int) ($this->_options['metadatas_array_max_size'] / 10); + $this->_metadatasArray = array_slice($this->_metadatasArray, $n); + } + if ($save) { + $result = $this->_saveMetadatas($id, $metadatas); + if (!$result) { + return false; + } + } + $this->_metadatasArray[$id] = $metadatas; + return true; + } + + /** + * Drop a metadata record + * + * @param string $id Cache id + * @return boolean True if no problem + */ + protected function _delMetadatas($id) + { + if (isset($this->_metadatasArray[$id])) { + unset($this->_metadatasArray[$id]); + } + $file = $this->_metadatasFile($id); + return $this->_remove($file); + } + + /** + * Clear the metadatas array + * + * @return void + */ + protected function _cleanMetadatas() + { + $this->_metadatasArray = array(); + } + + /** + * Load metadatas from disk + * + * @param string $id Cache id + * @return array|false Metadatas associative array + */ + protected function _loadMetadatas($id) + { + $file = $this->_metadatasFile($id); + $result = $this->_fileGetContents($file); + if (!$result) { + return false; + } + $tmp = @unserialize($result); + return $tmp; + } + + /** + * Save metadatas to disk + * + * @param string $id Cache id + * @param array $metadatas Associative array + * @return boolean True if no problem + */ + protected function _saveMetadatas($id, $metadatas) + { + $file = $this->_metadatasFile($id); + $result = $this->_filePutContents($file, serialize($metadatas)); + if (!$result) { + return false; + } + return true; + } + + /** + * Make and return a file name (with path) for metadatas + * + * @param string $id Cache id + * @return string Metadatas file name (with path) + */ + protected function _metadatasFile($id) + { + $path = $this->_path($id); + $fileName = $this->_idToFileName('internal-metadatas---' . $id); + return $path . $fileName; + } + + /** + * Check if the given filename is a metadatas one + * + * @param string $fileName File name + * @return boolean True if it's a metadatas one + */ + protected function _isMetadatasFile($fileName) + { + $id = $this->_fileNameToId($fileName); + if (substr($id, 0, 21) == 'internal-metadatas---') { + return true; + } else { + return false; + } + } + + /** + * Remove a file + * + * If we can't remove the file (because of locks or any problem), we will touch + * the file to invalidate it + * + * @param string $file Complete file path + * @return boolean True if ok + */ + protected function _remove($file) + { + if (!is_file($file)) { + return false; + } + if (!@unlink($file)) { + # we can't remove the file (because of locks or any problem) + $this->_log("Zend_Cache_Backend_File::_remove() : we can't remove $file"); + return false; + } + return true; + } + + /** + * Clean some cache records (protected method used for recursive stuff) + * + * Available modes are : + * Zend_Cache::CLEANING_MODE_ALL (default) => remove all cache entries ($tags is not used) + * Zend_Cache::CLEANING_MODE_OLD => remove too old cache entries ($tags is not used) + * Zend_Cache::CLEANING_MODE_MATCHING_TAG => remove cache entries matching all given tags + * ($tags can be an array of strings or a single string) + * Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => remove cache entries not {matching one of the given tags} + * ($tags can be an array of strings or a single string) + * Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG => remove cache entries matching any given tags + * ($tags can be an array of strings or a single string) + * + * @param string $dir Directory to clean + * @param string $mode Clean mode + * @param array $tags Array of tags + * @throws Zend_Cache_Exception + * @return boolean True if no problem + */ + protected function _clean($dir, $mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array()) + { + if (!is_dir($dir)) { + return false; + } + $result = true; + $prefix = $this->_options['file_name_prefix']; + $glob = @glob($dir . $prefix . '--*'); + if ($glob === false) { + // On some systems it is impossible to distinguish between empty match and an error. + return true; + } + $metadataFiles = array(); + foreach ($glob as $file) { + if (is_file($file)) { + $fileName = basename($file); + if ($this->_isMetadatasFile($fileName)) { + // In CLEANING_MODE_ALL, we drop anything, even remainings old metadatas files. + // To do that, we need to save the list of the metadata files first. + if ($mode == Zend_Cache::CLEANING_MODE_ALL) { + $metadataFiles[] = $file; + } + continue; + } + $id = $this->_fileNameToId($fileName); + $metadatas = $this->_getMetadatas($id); + if ($metadatas === FALSE) { + $metadatas = array('expire' => 1, 'tags' => array()); + } + switch ($mode) { + case Zend_Cache::CLEANING_MODE_ALL: + $result = $result && $this->remove($id); + break; + case Zend_Cache::CLEANING_MODE_OLD: + if (time() > $metadatas['expire']) { + $result = $this->remove($id) && $result; + } + break; + case Zend_Cache::CLEANING_MODE_MATCHING_TAG: + $matching = true; + foreach ($tags as $tag) { + if (!in_array($tag, $metadatas['tags'])) { + $matching = false; + break; + } + } + if ($matching) { + $result = $this->remove($id) && $result; + } + break; + case Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG: + $matching = false; + foreach ($tags as $tag) { + if (in_array($tag, $metadatas['tags'])) { + $matching = true; + break; + } + } + if (!$matching) { + $result = $this->remove($id) && $result; + } + break; + case Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG: + $matching = false; + foreach ($tags as $tag) { + if (in_array($tag, $metadatas['tags'])) { + $matching = true; + break; + } + } + if ($matching) { + $result = $this->remove($id) && $result; + } + break; + default: + Zend_Cache::throwException('Invalid mode for clean() method'); + break; + } + } + if ((is_dir($file)) and ($this->_options['hashed_directory_level']>0)) { + // Recursive call + $result = $this->_clean($file . DIRECTORY_SEPARATOR, $mode, $tags) && $result; + if ($mode == Zend_Cache::CLEANING_MODE_ALL) { + // we try to drop the structure too + @rmdir($file); + } + } + } + + // cycle through metadataFiles and delete orphaned ones + foreach ($metadataFiles as $file) { + if (file_exists($file)) { + $result = $this->_remove($file) && $result; + } + } + + return $result; + } + + protected function _get($dir, $mode, $tags = array()) + { + if (!is_dir($dir)) { + return false; + } + $result = array(); + $prefix = $this->_options['file_name_prefix']; + $glob = @glob($dir . $prefix . '--*'); + if ($glob === false) { + // On some systems it is impossible to distinguish between empty match and an error. + return array(); + } + foreach ($glob as $file) { + if (is_file($file)) { + $fileName = basename($file); + $id = $this->_fileNameToId($fileName); + $metadatas = $this->_getMetadatas($id); + if ($metadatas === FALSE) { + continue; + } + if (time() > $metadatas['expire']) { + continue; + } + switch ($mode) { + case 'ids': + $result[] = $id; + break; + case 'tags': + $result = array_unique(array_merge($result, $metadatas['tags'])); + break; + case 'matching': + $matching = true; + foreach ($tags as $tag) { + if (!in_array($tag, $metadatas['tags'])) { + $matching = false; + break; + } + } + if ($matching) { + $result[] = $id; + } + break; + case 'notMatching': + $matching = false; + foreach ($tags as $tag) { + if (in_array($tag, $metadatas['tags'])) { + $matching = true; + break; + } + } + if (!$matching) { + $result[] = $id; + } + break; + case 'matchingAny': + $matching = false; + foreach ($tags as $tag) { + if (in_array($tag, $metadatas['tags'])) { + $matching = true; + break; + } + } + if ($matching) { + $result[] = $id; + } + break; + default: + Zend_Cache::throwException('Invalid mode for _get() method'); + break; + } + } + if ((is_dir($file)) and ($this->_options['hashed_directory_level']>0)) { + // Recursive call + $recursiveRs = $this->_get($file . DIRECTORY_SEPARATOR, $mode, $tags); + if ($recursiveRs === false) { + $this->_log('Zend_Cache_Backend_File::_get() / recursive call : can\'t list entries of "'.$file.'"'); + } else { + $result = array_unique(array_merge($result, $recursiveRs)); + } + } + } + return array_unique($result); + } + + /** + * Compute & return the expire time + * + * @param int $lifetime + * @return int expire time (unix timestamp) + */ + protected function _expireTime($lifetime) + { + if ($lifetime === null) { + return 9999999999; + } + return time() + $lifetime; + } + + /** + * Make a control key with the string containing datas + * + * @param string $data Data + * @param string $controlType Type of control 'md5', 'crc32' or 'strlen' + * @throws Zend_Cache_Exception + * @return string Control key + */ + protected function _hash($data, $controlType) + { + switch ($controlType) { + case 'md5': + return md5($data); + case 'crc32': + return crc32($data); + case 'strlen': + return strlen($data); + case 'adler32': + return hash('adler32', $data); + default: + Zend_Cache::throwException("Incorrect hash function : $controlType"); + } + } + + /** + * Transform a cache id into a file name and return it + * + * @param string $id Cache id + * @return string File name + */ + protected function _idToFileName($id) + { + $prefix = $this->_options['file_name_prefix']; + $result = $prefix . '---' . $id; + return $result; + } + + /** + * Make and return a file name (with path) + * + * @param string $id Cache id + * @return string File name (with path) + */ + protected function _file($id) + { + $path = $this->_path($id); + $fileName = $this->_idToFileName($id); + return $path . $fileName; + } + + /** + * Return the complete directory path of a filename (including hashedDirectoryStructure) + * + * @param string $id Cache id + * @param boolean $parts if true, returns array of directory parts instead of single string + * @return string Complete directory path + */ + protected function _path($id, $parts = false) + { + $partsArray = array(); + $root = $this->_options['cache_dir']; + $prefix = $this->_options['file_name_prefix']; + if ($this->_options['hashed_directory_level']>0) { + $hash = hash('adler32', $id); + for ($i=0 ; $i < $this->_options['hashed_directory_level'] ; $i++) { + $root = $root . $prefix . '--' . substr($hash, 0, $i + 1) . DIRECTORY_SEPARATOR; + $partsArray[] = $root; + } + } + if ($parts) { + return $partsArray; + } else { + return $root; + } + } + + /** + * Make the directory strucuture for the given id + * + * @param string $id cache id + * @return boolean true + */ + protected function _recursiveMkdirAndChmod($id) + { + if ($this->_options['hashed_directory_level'] <=0) { + return true; + } + $partsArray = $this->_path($id, true); + foreach ($partsArray as $part) { + if (!is_dir($part)) { + @mkdir($part, $this->_options['hashed_directory_perm']); + @chmod($part, $this->_options['hashed_directory_perm']); // see #ZF-320 (this line is required in some configurations) + } + } + return true; + } + + /** + * Test if the given cache id is available (and still valid as a cache record) + * + * @param string $id Cache id + * @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested + * @return boolean|mixed false (a cache is not available) or "last modified" timestamp (int) of the available cache record + */ + protected function _test($id, $doNotTestCacheValidity) + { + $metadatas = $this->_getMetadatas($id); + if (!$metadatas) { + return false; + } + if ($doNotTestCacheValidity || (time() <= $metadatas['expire'])) { + return $metadatas['mtime']; + } + return false; + } + + /** + * Return the file content of the given file + * + * @param string $file File complete path + * @return string File content (or false if problem) + */ + protected function _fileGetContents($file) + { + $result = false; + if (!is_file($file)) { + return false; + } + $f = @fopen($file, 'rb'); + if ($f) { + if ($this->_options['file_locking']) @flock($f, LOCK_SH); + $result = stream_get_contents($f); + if ($this->_options['file_locking']) @flock($f, LOCK_UN); + @fclose($f); + } + return $result; + } + + /** + * Put the given string into the given file + * + * @param string $file File complete path + * @param string $string String to put in file + * @return boolean true if no problem + */ + protected function _filePutContents($file, $string) + { + $result = false; + $f = @fopen($file, 'ab+'); + if ($f) { + if ($this->_options['file_locking']) @flock($f, LOCK_EX); + fseek($f, 0); + ftruncate($f, 0); + $tmp = @fwrite($f, $string); + if (!($tmp === FALSE)) { + $result = true; + } + @fclose($f); + } + @chmod($file, $this->_options['cache_file_perm']); + return $result; + } + + /** + * Transform a file name into cache id and return it + * + * @param string $fileName File name + * @return string Cache id + */ + protected function _fileNameToId($fileName) + { + $prefix = $this->_options['file_name_prefix']; + return preg_replace('~^' . $prefix . '---(.*)$~', '$1', $fileName); + } + +} diff --git a/lib/zend/Zend/Cache/Backend/Interface.php b/lib/zend/Zend/Cache/Backend/Interface.php new file mode 100644 index 00000000000..1bd72d8c163 --- /dev/null +++ b/lib/zend/Zend/Cache/Backend/Interface.php @@ -0,0 +1,99 @@ + infinite lifetime) + * @return boolean true if no problem + */ + public function save($data, $id, $tags = array(), $specificLifetime = false); + + /** + * Remove a cache record + * + * @param string $id Cache id + * @return boolean True if no problem + */ + public function remove($id); + + /** + * Clean some cache records + * + * Available modes are : + * Zend_Cache::CLEANING_MODE_ALL (default) => remove all cache entries ($tags is not used) + * Zend_Cache::CLEANING_MODE_OLD => remove too old cache entries ($tags is not used) + * Zend_Cache::CLEANING_MODE_MATCHING_TAG => remove cache entries matching all given tags + * ($tags can be an array of strings or a single string) + * Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => remove cache entries not {matching one of the given tags} + * ($tags can be an array of strings or a single string) + * Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG => remove cache entries matching any given tags + * ($tags can be an array of strings or a single string) + * + * @param string $mode Clean mode + * @param array $tags Array of tags + * @return boolean true if no problem + */ + public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array()); + +} diff --git a/lib/zend/Zend/Cache/Backend/Libmemcached.php b/lib/zend/Zend/Cache/Backend/Libmemcached.php new file mode 100644 index 00000000000..623e75776cc --- /dev/null +++ b/lib/zend/Zend/Cache/Backend/Libmemcached.php @@ -0,0 +1,484 @@ + (array) servers : + * an array of memcached server ; each memcached server is described by an associative array : + * 'host' => (string) : the name of the memcached server + * 'port' => (int) : the port of the memcached server + * 'weight' => (int) : number of buckets to create for this server which in turn control its + * probability of it being selected. The probability is relative to the total + * weight of all servers. + * =====> (array) client : + * an array of memcached client options ; the memcached client is described by an associative array : + * @see http://php.net/manual/memcached.constants.php + * - The option name can be the name of the constant without the prefix 'OPT_' + * or the integer value of this option constant + * + * @var array available options + */ + protected $_options = array( + 'servers' => array(array( + 'host' => self::DEFAULT_HOST, + 'port' => self::DEFAULT_PORT, + 'weight' => self::DEFAULT_WEIGHT, + )), + 'client' => array() + ); + + /** + * Memcached object + * + * @var mixed memcached object + */ + protected $_memcache = null; + + /** + * Constructor + * + * @param array $options associative array of options + * @throws Zend_Cache_Exception + * @return void + */ + public function __construct(array $options = array()) + { + if (!extension_loaded('memcached')) { + Zend_Cache::throwException('The memcached extension must be loaded for using this backend !'); + } + + // override default client options + $this->_options['client'] = array( + Memcached::OPT_DISTRIBUTION => Memcached::DISTRIBUTION_CONSISTENT, + Memcached::OPT_HASH => Memcached::HASH_MD5, + Memcached::OPT_LIBKETAMA_COMPATIBLE => true, + ); + + parent::__construct($options); + + if (isset($this->_options['servers'])) { + $value = $this->_options['servers']; + if (isset($value['host'])) { + // in this case, $value seems to be a simple associative array (one server only) + $value = array(0 => $value); // let's transform it into a classical array of associative arrays + } + $this->setOption('servers', $value); + } + $this->_memcache = new Memcached; + + // setup memcached client options + foreach ($this->_options['client'] as $name => $value) { + $optId = null; + if (is_int($name)) { + $optId = $name; + } else { + $optConst = 'Memcached::OPT_' . strtoupper($name); + if (defined($optConst)) { + $optId = constant($optConst); + } else { + $this->_log("Unknown memcached client option '{$name}' ({$optConst})"); + } + } + if (null !== $optId) { + if (!$this->_memcache->setOption($optId, $value)) { + $this->_log("Setting memcached client option '{$optId}' failed"); + } + } + } + + // setup memcached servers + $servers = array(); + foreach ($this->_options['servers'] as $server) { + if (!array_key_exists('port', $server)) { + $server['port'] = self::DEFAULT_PORT; + } + if (!array_key_exists('weight', $server)) { + $server['weight'] = self::DEFAULT_WEIGHT; + } + + $servers[] = array($server['host'], $server['port'], $server['weight']); + } + $this->_memcache->addServers($servers); + } + + /** + * Test if a cache is available for the given id and (if yes) return it (false else) + * + * @param string $id Cache id + * @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested + * @return string|false cached datas + */ + public function load($id, $doNotTestCacheValidity = false) + { + $tmp = $this->_memcache->get($id); + if (isset($tmp[0])) { + return $tmp[0]; + } + return false; + } + + /** + * Test if a cache is available or not (for the given id) + * + * @param string $id Cache id + * @return int|false (a cache is not available) or "last modified" timestamp (int) of the available cache record + */ + public function test($id) + { + $tmp = $this->_memcache->get($id); + if (isset($tmp[0], $tmp[1])) { + return (int)$tmp[1]; + } + return false; + } + + /** + * Save some string datas into a cache record + * + * Note : $data is always "string" (serialization is done by the + * core not by the backend) + * + * @param string $data Datas to cache + * @param string $id Cache id + * @param array $tags Array of strings, the cache record will be tagged by each string entry + * @param int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime) + * @return boolean True if no problem + */ + public function save($data, $id, $tags = array(), $specificLifetime = false) + { + $lifetime = $this->getLifetime($specificLifetime); + + // ZF-8856: using set because add needs a second request if item already exists + $result = @$this->_memcache->set($id, array($data, time(), $lifetime), $lifetime); + if ($result === false) { + $rsCode = $this->_memcache->getResultCode(); + $rsMsg = $this->_memcache->getResultMessage(); + $this->_log("Memcached::set() failed: [{$rsCode}] {$rsMsg}"); + } + + if (count($tags) > 0) { + $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_LIBMEMCACHED_BACKEND); + } + + return $result; + } + + /** + * Remove a cache record + * + * @param string $id Cache id + * @return boolean True if no problem + */ + public function remove($id) + { + return $this->_memcache->delete($id); + } + + /** + * Clean some cache records + * + * Available modes are : + * 'all' (default) => remove all cache entries ($tags is not used) + * 'old' => unsupported + * 'matchingTag' => unsupported + * 'notMatchingTag' => unsupported + * 'matchingAnyTag' => unsupported + * + * @param string $mode Clean mode + * @param array $tags Array of tags + * @throws Zend_Cache_Exception + * @return boolean True if no problem + */ + public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array()) + { + switch ($mode) { + case Zend_Cache::CLEANING_MODE_ALL: + return $this->_memcache->flush(); + break; + case Zend_Cache::CLEANING_MODE_OLD: + $this->_log("Zend_Cache_Backend_Libmemcached::clean() : CLEANING_MODE_OLD is unsupported by the Libmemcached backend"); + break; + case Zend_Cache::CLEANING_MODE_MATCHING_TAG: + case Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG: + case Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG: + $this->_log(self::TAGS_UNSUPPORTED_BY_CLEAN_OF_LIBMEMCACHED_BACKEND); + break; + default: + Zend_Cache::throwException('Invalid mode for clean() method'); + break; + } + } + + /** + * Return true if the automatic cleaning is available for the backend + * + * @return boolean + */ + public function isAutomaticCleaningAvailable() + { + return false; + } + + /** + * Set the frontend directives + * + * @param array $directives Assoc of directives + * @throws Zend_Cache_Exception + * @return void + */ + public function setDirectives($directives) + { + parent::setDirectives($directives); + $lifetime = $this->getLifetime(false); + if ($lifetime > 2592000) { + // #ZF-3490 : For the memcached backend, there is a lifetime limit of 30 days (2592000 seconds) + $this->_log('memcached backend has a limit of 30 days (2592000 seconds) for the lifetime'); + } + if ($lifetime === null) { + // #ZF-4614 : we tranform null to zero to get the maximal lifetime + parent::setDirectives(array('lifetime' => 0)); + } + } + + /** + * Return an array of stored cache ids + * + * @return array array of stored cache ids (string) + */ + public function getIds() + { + $this->_log("Zend_Cache_Backend_Libmemcached::save() : getting the list of cache ids is unsupported by the Libmemcached backend"); + return array(); + } + + /** + * Return an array of stored tags + * + * @return array array of stored tags (string) + */ + public function getTags() + { + $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_LIBMEMCACHED_BACKEND); + return array(); + } + + /** + * Return an array of stored cache ids which match given tags + * + * In case of multiple tags, a logical AND is made between tags + * + * @param array $tags array of tags + * @return array array of matching cache ids (string) + */ + public function getIdsMatchingTags($tags = array()) + { + $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_LIBMEMCACHED_BACKEND); + return array(); + } + + /** + * Return an array of stored cache ids which don't match given tags + * + * In case of multiple tags, a logical OR is made between tags + * + * @param array $tags array of tags + * @return array array of not matching cache ids (string) + */ + public function getIdsNotMatchingTags($tags = array()) + { + $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_LIBMEMCACHED_BACKEND); + return array(); + } + + /** + * Return an array of stored cache ids which match any given tags + * + * In case of multiple tags, a logical AND is made between tags + * + * @param array $tags array of tags + * @return array array of any matching cache ids (string) + */ + public function getIdsMatchingAnyTags($tags = array()) + { + $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_LIBMEMCACHED_BACKEND); + return array(); + } + + /** + * Return the filling percentage of the backend storage + * + * @throws Zend_Cache_Exception + * @return int integer between 0 and 100 + */ + public function getFillingPercentage() + { + $mems = $this->_memcache->getStats(); + if ($mems === false) { + return 0; + } + + $memSize = null; + $memUsed = null; + foreach ($mems as $key => $mem) { + if ($mem === false) { + $this->_log('can\'t get stat from ' . $key); + continue; + } + + $eachSize = $mem['limit_maxbytes']; + $eachUsed = $mem['bytes']; + if ($eachUsed > $eachSize) { + $eachUsed = $eachSize; + } + + $memSize += $eachSize; + $memUsed += $eachUsed; + } + + if ($memSize === null || $memUsed === null) { + Zend_Cache::throwException('Can\'t get filling percentage'); + } + + return ((int) (100. * ($memUsed / $memSize))); + } + + /** + * Return an array of metadatas for the given cache id + * + * The array must include these keys : + * - expire : the expire timestamp + * - tags : a string array of tags + * - mtime : timestamp of last modification time + * + * @param string $id cache id + * @return array array of metadatas (false if the cache id is not found) + */ + public function getMetadatas($id) + { + $tmp = $this->_memcache->get($id); + if (isset($tmp[0], $tmp[1], $tmp[2])) { + $data = $tmp[0]; + $mtime = $tmp[1]; + $lifetime = $tmp[2]; + return array( + 'expire' => $mtime + $lifetime, + 'tags' => array(), + 'mtime' => $mtime + ); + } + + return false; + } + + /** + * Give (if possible) an extra lifetime to the given cache id + * + * @param string $id cache id + * @param int $extraLifetime + * @return boolean true if ok + */ + public function touch($id, $extraLifetime) + { + $tmp = $this->_memcache->get($id); + if (isset($tmp[0], $tmp[1], $tmp[2])) { + $data = $tmp[0]; + $mtime = $tmp[1]; + $lifetime = $tmp[2]; + $newLifetime = $lifetime - (time() - $mtime) + $extraLifetime; + if ($newLifetime <=0) { + return false; + } + // #ZF-5702 : we try replace() first becase set() seems to be slower + if (!($result = $this->_memcache->replace($id, array($data, time(), $newLifetime), $newLifetime))) { + $result = $this->_memcache->set($id, array($data, time(), $newLifetime), $newLifetime); + if ($result === false) { + $rsCode = $this->_memcache->getResultCode(); + $rsMsg = $this->_memcache->getResultMessage(); + $this->_log("Memcached::set() failed: [{$rsCode}] {$rsMsg}"); + } + } + return $result; + } + return false; + } + + /** + * Return an associative array of capabilities (booleans) of the backend + * + * The array must include these keys : + * - automatic_cleaning (is automating cleaning necessary) + * - tags (are tags supported) + * - expired_read (is it possible to read expired cache records + * (for doNotTestCacheValidity option for example)) + * - priority does the backend deal with priority when saving + * - infinite_lifetime (is infinite lifetime can work with this backend) + * - get_list (is it possible to get the list of cache ids and the complete list of tags) + * + * @return array associative of with capabilities + */ + public function getCapabilities() + { + return array( + 'automatic_cleaning' => false, + 'tags' => false, + 'expired_read' => false, + 'priority' => false, + 'infinite_lifetime' => false, + 'get_list' => false + ); + } + +} diff --git a/lib/zend/Zend/Cache/Backend/Memcached.php b/lib/zend/Zend/Cache/Backend/Memcached.php new file mode 100644 index 00000000000..9cb9916dd87 --- /dev/null +++ b/lib/zend/Zend/Cache/Backend/Memcached.php @@ -0,0 +1,509 @@ + (array) servers : + * an array of memcached server ; each memcached server is described by an associative array : + * 'host' => (string) : the name of the memcached server + * 'port' => (int) : the port of the memcached server + * 'persistent' => (bool) : use or not persistent connections to this memcached server + * 'weight' => (int) : number of buckets to create for this server which in turn control its + * probability of it being selected. The probability is relative to the total + * weight of all servers. + * 'timeout' => (int) : value in seconds which will be used for connecting to the daemon. Think twice + * before changing the default value of 1 second - you can lose all the + * advantages of caching if your connection is too slow. + * 'retry_interval' => (int) : controls how often a failed server will be retried, the default value + * is 15 seconds. Setting this parameter to -1 disables automatic retry. + * 'status' => (bool) : controls if the server should be flagged as online. + * 'failure_callback' => (callback) : Allows the user to specify a callback function to run upon + * encountering an error. The callback is run before failover + * is attempted. The function takes two parameters, the hostname + * and port of the failed server. + * + * =====> (boolean) compression : + * true if you want to use on-the-fly compression + * + * =====> (boolean) compatibility : + * true if you use old memcache server or extension + * + * @var array available options + */ + protected $_options = array( + 'servers' => array(array( + 'host' => self::DEFAULT_HOST, + 'port' => self::DEFAULT_PORT, + 'persistent' => self::DEFAULT_PERSISTENT, + 'weight' => self::DEFAULT_WEIGHT, + 'timeout' => self::DEFAULT_TIMEOUT, + 'retry_interval' => self::DEFAULT_RETRY_INTERVAL, + 'status' => self::DEFAULT_STATUS, + 'failure_callback' => self::DEFAULT_FAILURE_CALLBACK + )), + 'compression' => false, + 'compatibility' => false, + ); + + /** + * Memcache object + * + * @var mixed memcache object + */ + protected $_memcache = null; + + /** + * Constructor + * + * @param array $options associative array of options + * @throws Zend_Cache_Exception + * @return void + */ + public function __construct(array $options = array()) + { + if (!extension_loaded('memcache')) { + Zend_Cache::throwException('The memcache extension must be loaded for using this backend !'); + } + parent::__construct($options); + if (isset($this->_options['servers'])) { + $value= $this->_options['servers']; + if (isset($value['host'])) { + // in this case, $value seems to be a simple associative array (one server only) + $value = array(0 => $value); // let's transform it into a classical array of associative arrays + } + $this->setOption('servers', $value); + } + $this->_memcache = new Memcache; + foreach ($this->_options['servers'] as $server) { + if (!array_key_exists('port', $server)) { + $server['port'] = self::DEFAULT_PORT; + } + if (!array_key_exists('persistent', $server)) { + $server['persistent'] = self::DEFAULT_PERSISTENT; + } + if (!array_key_exists('weight', $server)) { + $server['weight'] = self::DEFAULT_WEIGHT; + } + if (!array_key_exists('timeout', $server)) { + $server['timeout'] = self::DEFAULT_TIMEOUT; + } + if (!array_key_exists('retry_interval', $server)) { + $server['retry_interval'] = self::DEFAULT_RETRY_INTERVAL; + } + if (!array_key_exists('status', $server)) { + $server['status'] = self::DEFAULT_STATUS; + } + if (!array_key_exists('failure_callback', $server)) { + $server['failure_callback'] = self::DEFAULT_FAILURE_CALLBACK; + } + if ($this->_options['compatibility']) { + // No status for compatibility mode (#ZF-5887) + $this->_memcache->addServer($server['host'], $server['port'], $server['persistent'], + $server['weight'], $server['timeout'], + $server['retry_interval']); + } else { + $this->_memcache->addServer($server['host'], $server['port'], $server['persistent'], + $server['weight'], $server['timeout'], + $server['retry_interval'], + $server['status'], $server['failure_callback']); + } + } + } + + /** + * Test if a cache is available for the given id and (if yes) return it (false else) + * + * @param string $id Cache id + * @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested + * @return string|false cached datas + */ + public function load($id, $doNotTestCacheValidity = false) + { + $tmp = $this->_memcache->get($id); + if (is_array($tmp) && isset($tmp[0])) { + return $tmp[0]; + } + return false; + } + + /** + * Test if a cache is available or not (for the given id) + * + * @param string $id Cache id + * @return mixed|false (a cache is not available) or "last modified" timestamp (int) of the available cache record + */ + public function test($id) + { + $tmp = $this->_memcache->get($id); + if (is_array($tmp)) { + return $tmp[1]; + } + return false; + } + + /** + * Save some string datas into a cache record + * + * Note : $data is always "string" (serialization is done by the + * core not by the backend) + * + * @param string $data Datas to cache + * @param string $id Cache id + * @param array $tags Array of strings, the cache record will be tagged by each string entry + * @param int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime) + * @return boolean True if no problem + */ + public function save($data, $id, $tags = array(), $specificLifetime = false) + { + $lifetime = $this->getLifetime($specificLifetime); + if ($this->_options['compression']) { + $flag = MEMCACHE_COMPRESSED; + } else { + $flag = 0; + } + + // ZF-8856: using set because add needs a second request if item already exists + $result = @$this->_memcache->set($id, array($data, time(), $lifetime), $flag, $lifetime); + + if (count($tags) > 0) { + $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_MEMCACHED_BACKEND); + } + + return $result; + } + + /** + * Remove a cache record + * + * @param string $id Cache id + * @return boolean True if no problem + */ + public function remove($id) + { + return $this->_memcache->delete($id, 0); + } + + /** + * Clean some cache records + * + * Available modes are : + * 'all' (default) => remove all cache entries ($tags is not used) + * 'old' => unsupported + * 'matchingTag' => unsupported + * 'notMatchingTag' => unsupported + * 'matchingAnyTag' => unsupported + * + * @param string $mode Clean mode + * @param array $tags Array of tags + * @throws Zend_Cache_Exception + * @return boolean True if no problem + */ + public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array()) + { + switch ($mode) { + case Zend_Cache::CLEANING_MODE_ALL: + return $this->_memcache->flush(); + break; + case Zend_Cache::CLEANING_MODE_OLD: + $this->_log("Zend_Cache_Backend_Memcached::clean() : CLEANING_MODE_OLD is unsupported by the Memcached backend"); + break; + case Zend_Cache::CLEANING_MODE_MATCHING_TAG: + case Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG: + case Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG: + $this->_log(self::TAGS_UNSUPPORTED_BY_CLEAN_OF_MEMCACHED_BACKEND); + break; + default: + Zend_Cache::throwException('Invalid mode for clean() method'); + break; + } + } + + /** + * Return true if the automatic cleaning is available for the backend + * + * @return boolean + */ + public function isAutomaticCleaningAvailable() + { + return false; + } + + /** + * Set the frontend directives + * + * @param array $directives Assoc of directives + * @throws Zend_Cache_Exception + * @return void + */ + public function setDirectives($directives) + { + parent::setDirectives($directives); + $lifetime = $this->getLifetime(false); + if ($lifetime > 2592000) { + // #ZF-3490 : For the memcached backend, there is a lifetime limit of 30 days (2592000 seconds) + $this->_log('memcached backend has a limit of 30 days (2592000 seconds) for the lifetime'); + } + if ($lifetime === null) { + // #ZF-4614 : we tranform null to zero to get the maximal lifetime + parent::setDirectives(array('lifetime' => 0)); + } + } + + /** + * Return an array of stored cache ids + * + * @return array array of stored cache ids (string) + */ + public function getIds() + { + $this->_log("Zend_Cache_Backend_Memcached::save() : getting the list of cache ids is unsupported by the Memcache backend"); + return array(); + } + + /** + * Return an array of stored tags + * + * @return array array of stored tags (string) + */ + public function getTags() + { + $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_MEMCACHED_BACKEND); + return array(); + } + + /** + * Return an array of stored cache ids which match given tags + * + * In case of multiple tags, a logical AND is made between tags + * + * @param array $tags array of tags + * @return array array of matching cache ids (string) + */ + public function getIdsMatchingTags($tags = array()) + { + $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_MEMCACHED_BACKEND); + return array(); + } + + /** + * Return an array of stored cache ids which don't match given tags + * + * In case of multiple tags, a logical OR is made between tags + * + * @param array $tags array of tags + * @return array array of not matching cache ids (string) + */ + public function getIdsNotMatchingTags($tags = array()) + { + $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_MEMCACHED_BACKEND); + return array(); + } + + /** + * Return an array of stored cache ids which match any given tags + * + * In case of multiple tags, a logical AND is made between tags + * + * @param array $tags array of tags + * @return array array of any matching cache ids (string) + */ + public function getIdsMatchingAnyTags($tags = array()) + { + $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_MEMCACHED_BACKEND); + return array(); + } + + /** + * Return the filling percentage of the backend storage + * + * @throws Zend_Cache_Exception + * @return int integer between 0 and 100 + */ + public function getFillingPercentage() + { + $mems = $this->_memcache->getExtendedStats(); + + $memSize = null; + $memUsed = null; + foreach ($mems as $key => $mem) { + if ($mem === false) { + $this->_log('can\'t get stat from ' . $key); + continue; + } + + $eachSize = $mem['limit_maxbytes']; + + /** + * Couchbase 1.x uses 'mem_used' instead of 'bytes' + * @see https://www.couchbase.com/issues/browse/MB-3466 + */ + $eachUsed = isset($mem['bytes']) ? $mem['bytes'] : $mem['mem_used']; + if ($eachUsed > $eachSize) { + $eachUsed = $eachSize; + } + + $memSize += $eachSize; + $memUsed += $eachUsed; + } + + if ($memSize === null || $memUsed === null) { + Zend_Cache::throwException('Can\'t get filling percentage'); + } + + return ((int) (100. * ($memUsed / $memSize))); + } + + /** + * Return an array of metadatas for the given cache id + * + * The array must include these keys : + * - expire : the expire timestamp + * - tags : a string array of tags + * - mtime : timestamp of last modification time + * + * @param string $id cache id + * @return array array of metadatas (false if the cache id is not found) + */ + public function getMetadatas($id) + { + $tmp = $this->_memcache->get($id); + if (is_array($tmp)) { + $data = $tmp[0]; + $mtime = $tmp[1]; + if (!isset($tmp[2])) { + // because this record is only with 1.7 release + // if old cache records are still there... + return false; + } + $lifetime = $tmp[2]; + return array( + 'expire' => $mtime + $lifetime, + 'tags' => array(), + 'mtime' => $mtime + ); + } + return false; + } + + /** + * Give (if possible) an extra lifetime to the given cache id + * + * @param string $id cache id + * @param int $extraLifetime + * @return boolean true if ok + */ + public function touch($id, $extraLifetime) + { + if ($this->_options['compression']) { + $flag = MEMCACHE_COMPRESSED; + } else { + $flag = 0; + } + $tmp = $this->_memcache->get($id); + if (is_array($tmp)) { + $data = $tmp[0]; + $mtime = $tmp[1]; + if (!isset($tmp[2])) { + // because this record is only with 1.7 release + // if old cache records are still there... + return false; + } + $lifetime = $tmp[2]; + $newLifetime = $lifetime - (time() - $mtime) + $extraLifetime; + if ($newLifetime <=0) { + return false; + } + // #ZF-5702 : we try replace() first becase set() seems to be slower + if (!($result = $this->_memcache->replace($id, array($data, time(), $newLifetime), $flag, $newLifetime))) { + $result = $this->_memcache->set($id, array($data, time(), $newLifetime), $flag, $newLifetime); + } + return $result; + } + return false; + } + + /** + * Return an associative array of capabilities (booleans) of the backend + * + * The array must include these keys : + * - automatic_cleaning (is automating cleaning necessary) + * - tags (are tags supported) + * - expired_read (is it possible to read expired cache records + * (for doNotTestCacheValidity option for example)) + * - priority does the backend deal with priority when saving + * - infinite_lifetime (is infinite lifetime can work with this backend) + * - get_list (is it possible to get the list of cache ids and the complete list of tags) + * + * @return array associative of with capabilities + */ + public function getCapabilities() + { + return array( + 'automatic_cleaning' => false, + 'tags' => false, + 'expired_read' => false, + 'priority' => false, + 'infinite_lifetime' => false, + 'get_list' => false + ); + } + +} diff --git a/lib/zend/Zend/Cache/Backend/Sqlite.php b/lib/zend/Zend/Cache/Backend/Sqlite.php new file mode 100644 index 00000000000..3e8ac8276b9 --- /dev/null +++ b/lib/zend/Zend/Cache/Backend/Sqlite.php @@ -0,0 +1,678 @@ + (string) cache_db_complete_path : + * - the complete path (filename included) of the SQLITE database + * + * ====> (int) automatic_vacuum_factor : + * - Disable / Tune the automatic vacuum process + * - The automatic vacuum process defragment the database file (and make it smaller) + * when a clean() or delete() is called + * 0 => no automatic vacuum + * 1 => systematic vacuum (when delete() or clean() methods are called) + * x (integer) > 1 => automatic vacuum randomly 1 times on x clean() or delete() + * + * @var array Available options + */ + protected $_options = array( + 'cache_db_complete_path' => null, + 'automatic_vacuum_factor' => 10 + ); + + /** + * DB ressource + * + * @var mixed $_db + */ + private $_db = null; + + /** + * Boolean to store if the structure has benn checked or not + * + * @var boolean $_structureChecked + */ + private $_structureChecked = false; + + /** + * Constructor + * + * @param array $options Associative array of options + * @throws Zend_cache_Exception + * @return void + */ + public function __construct(array $options = array()) + { + parent::__construct($options); + if ($this->_options['cache_db_complete_path'] === null) { + Zend_Cache::throwException('cache_db_complete_path option has to set'); + } + if (!extension_loaded('sqlite')) { + Zend_Cache::throwException("Cannot use SQLite storage because the 'sqlite' extension is not loaded in the current PHP environment"); + } + $this->_getConnection(); + } + + /** + * Destructor + * + * @return void + */ + public function __destruct() + { + @sqlite_close($this->_getConnection()); + } + + /** + * Test if a cache is available for the given id and (if yes) return it (false else) + * + * @param string $id Cache id + * @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested + * @return string|false Cached datas + */ + public function load($id, $doNotTestCacheValidity = false) + { + $this->_checkAndBuildStructure(); + $sql = "SELECT content FROM cache WHERE id='$id'"; + if (!$doNotTestCacheValidity) { + $sql = $sql . " AND (expire=0 OR expire>" . time() . ')'; + } + $result = $this->_query($sql); + $row = @sqlite_fetch_array($result); + if ($row) { + return $row['content']; + } + return false; + } + + /** + * Test if a cache is available or not (for the given id) + * + * @param string $id Cache id + * @return mixed|false (a cache is not available) or "last modified" timestamp (int) of the available cache record + */ + public function test($id) + { + $this->_checkAndBuildStructure(); + $sql = "SELECT lastModified FROM cache WHERE id='$id' AND (expire=0 OR expire>" . time() . ')'; + $result = $this->_query($sql); + $row = @sqlite_fetch_array($result); + if ($row) { + return ((int) $row['lastModified']); + } + return false; + } + + /** + * Save some string datas into a cache record + * + * Note : $data is always "string" (serialization is done by the + * core not by the backend) + * + * @param string $data Datas to cache + * @param string $id Cache id + * @param array $tags Array of strings, the cache record will be tagged by each string entry + * @param int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime) + * @throws Zend_Cache_Exception + * @return boolean True if no problem + */ + public function save($data, $id, $tags = array(), $specificLifetime = false) + { + $this->_checkAndBuildStructure(); + $lifetime = $this->getLifetime($specificLifetime); + $data = @sqlite_escape_string($data); + $mktime = time(); + if ($lifetime === null) { + $expire = 0; + } else { + $expire = $mktime + $lifetime; + } + $this->_query("DELETE FROM cache WHERE id='$id'"); + $sql = "INSERT INTO cache (id, content, lastModified, expire) VALUES ('$id', '$data', $mktime, $expire)"; + $res = $this->_query($sql); + if (!$res) { + $this->_log("Zend_Cache_Backend_Sqlite::save() : impossible to store the cache id=$id"); + return false; + } + $res = true; + foreach ($tags as $tag) { + $res = $this->_registerTag($id, $tag) && $res; + } + return $res; + } + + /** + * Remove a cache record + * + * @param string $id Cache id + * @return boolean True if no problem + */ + public function remove($id) + { + $this->_checkAndBuildStructure(); + $res = $this->_query("SELECT COUNT(*) AS nbr FROM cache WHERE id='$id'"); + $result1 = @sqlite_fetch_single($res); + $result2 = $this->_query("DELETE FROM cache WHERE id='$id'"); + $result3 = $this->_query("DELETE FROM tag WHERE id='$id'"); + $this->_automaticVacuum(); + return ($result1 && $result2 && $result3); + } + + /** + * Clean some cache records + * + * Available modes are : + * Zend_Cache::CLEANING_MODE_ALL (default) => remove all cache entries ($tags is not used) + * Zend_Cache::CLEANING_MODE_OLD => remove too old cache entries ($tags is not used) + * Zend_Cache::CLEANING_MODE_MATCHING_TAG => remove cache entries matching all given tags + * ($tags can be an array of strings or a single string) + * Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => remove cache entries not {matching one of the given tags} + * ($tags can be an array of strings or a single string) + * Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG => remove cache entries matching any given tags + * ($tags can be an array of strings or a single string) + * + * @param string $mode Clean mode + * @param array $tags Array of tags + * @return boolean True if no problem + */ + public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array()) + { + $this->_checkAndBuildStructure(); + $return = $this->_clean($mode, $tags); + $this->_automaticVacuum(); + return $return; + } + + /** + * Return an array of stored cache ids + * + * @return array array of stored cache ids (string) + */ + public function getIds() + { + $this->_checkAndBuildStructure(); + $res = $this->_query("SELECT id FROM cache WHERE (expire=0 OR expire>" . time() . ")"); + $result = array(); + while ($id = @sqlite_fetch_single($res)) { + $result[] = $id; + } + return $result; + } + + /** + * Return an array of stored tags + * + * @return array array of stored tags (string) + */ + public function getTags() + { + $this->_checkAndBuildStructure(); + $res = $this->_query("SELECT DISTINCT(name) AS name FROM tag"); + $result = array(); + while ($id = @sqlite_fetch_single($res)) { + $result[] = $id; + } + return $result; + } + + /** + * Return an array of stored cache ids which match given tags + * + * In case of multiple tags, a logical AND is made between tags + * + * @param array $tags array of tags + * @return array array of matching cache ids (string) + */ + public function getIdsMatchingTags($tags = array()) + { + $first = true; + $ids = array(); + foreach ($tags as $tag) { + $res = $this->_query("SELECT DISTINCT(id) AS id FROM tag WHERE name='$tag'"); + if (!$res) { + return array(); + } + $rows = @sqlite_fetch_all($res, SQLITE_ASSOC); + $ids2 = array(); + foreach ($rows as $row) { + $ids2[] = $row['id']; + } + if ($first) { + $ids = $ids2; + $first = false; + } else { + $ids = array_intersect($ids, $ids2); + } + } + $result = array(); + foreach ($ids as $id) { + $result[] = $id; + } + return $result; + } + + /** + * Return an array of stored cache ids which don't match given tags + * + * In case of multiple tags, a logical OR is made between tags + * + * @param array $tags array of tags + * @return array array of not matching cache ids (string) + */ + public function getIdsNotMatchingTags($tags = array()) + { + $res = $this->_query("SELECT id FROM cache"); + $rows = @sqlite_fetch_all($res, SQLITE_ASSOC); + $result = array(); + foreach ($rows as $row) { + $id = $row['id']; + $matching = false; + foreach ($tags as $tag) { + $res = $this->_query("SELECT COUNT(*) AS nbr FROM tag WHERE name='$tag' AND id='$id'"); + if (!$res) { + return array(); + } + $nbr = (int) @sqlite_fetch_single($res); + if ($nbr > 0) { + $matching = true; + } + } + if (!$matching) { + $result[] = $id; + } + } + return $result; + } + + /** + * Return an array of stored cache ids which match any given tags + * + * In case of multiple tags, a logical AND is made between tags + * + * @param array $tags array of tags + * @return array array of any matching cache ids (string) + */ + public function getIdsMatchingAnyTags($tags = array()) + { + $first = true; + $ids = array(); + foreach ($tags as $tag) { + $res = $this->_query("SELECT DISTINCT(id) AS id FROM tag WHERE name='$tag'"); + if (!$res) { + return array(); + } + $rows = @sqlite_fetch_all($res, SQLITE_ASSOC); + $ids2 = array(); + foreach ($rows as $row) { + $ids2[] = $row['id']; + } + if ($first) { + $ids = $ids2; + $first = false; + } else { + $ids = array_merge($ids, $ids2); + } + } + $result = array(); + foreach ($ids as $id) { + $result[] = $id; + } + return $result; + } + + /** + * Return the filling percentage of the backend storage + * + * @throws Zend_Cache_Exception + * @return int integer between 0 and 100 + */ + public function getFillingPercentage() + { + $dir = dirname($this->_options['cache_db_complete_path']); + $free = disk_free_space($dir); + $total = disk_total_space($dir); + if ($total == 0) { + Zend_Cache::throwException('can\'t get disk_total_space'); + } else { + if ($free >= $total) { + return 100; + } + return ((int) (100. * ($total - $free) / $total)); + } + } + + /** + * Return an array of metadatas for the given cache id + * + * The array must include these keys : + * - expire : the expire timestamp + * - tags : a string array of tags + * - mtime : timestamp of last modification time + * + * @param string $id cache id + * @return array array of metadatas (false if the cache id is not found) + */ + public function getMetadatas($id) + { + $tags = array(); + $res = $this->_query("SELECT name FROM tag WHERE id='$id'"); + if ($res) { + $rows = @sqlite_fetch_all($res, SQLITE_ASSOC); + foreach ($rows as $row) { + $tags[] = $row['name']; + } + } + $this->_query('CREATE TABLE cache (id TEXT PRIMARY KEY, content BLOB, lastModified INTEGER, expire INTEGER)'); + $res = $this->_query("SELECT lastModified,expire FROM cache WHERE id='$id'"); + if (!$res) { + return false; + } + $row = @sqlite_fetch_array($res, SQLITE_ASSOC); + return array( + 'tags' => $tags, + 'mtime' => $row['lastModified'], + 'expire' => $row['expire'] + ); + } + + /** + * Give (if possible) an extra lifetime to the given cache id + * + * @param string $id cache id + * @param int $extraLifetime + * @return boolean true if ok + */ + public function touch($id, $extraLifetime) + { + $sql = "SELECT expire FROM cache WHERE id='$id' AND (expire=0 OR expire>" . time() . ')'; + $res = $this->_query($sql); + if (!$res) { + return false; + } + $expire = @sqlite_fetch_single($res); + $newExpire = $expire + $extraLifetime; + $res = $this->_query("UPDATE cache SET lastModified=" . time() . ", expire=$newExpire WHERE id='$id'"); + if ($res) { + return true; + } else { + return false; + } + } + + /** + * Return an associative array of capabilities (booleans) of the backend + * + * The array must include these keys : + * - automatic_cleaning (is automating cleaning necessary) + * - tags (are tags supported) + * - expired_read (is it possible to read expired cache records + * (for doNotTestCacheValidity option for example)) + * - priority does the backend deal with priority when saving + * - infinite_lifetime (is infinite lifetime can work with this backend) + * - get_list (is it possible to get the list of cache ids and the complete list of tags) + * + * @return array associative of with capabilities + */ + public function getCapabilities() + { + return array( + 'automatic_cleaning' => true, + 'tags' => true, + 'expired_read' => true, + 'priority' => false, + 'infinite_lifetime' => true, + 'get_list' => true + ); + } + + /** + * PUBLIC METHOD FOR UNIT TESTING ONLY ! + * + * Force a cache record to expire + * + * @param string $id Cache id + */ + public function ___expire($id) + { + $time = time() - 1; + $this->_query("UPDATE cache SET lastModified=$time, expire=$time WHERE id='$id'"); + } + + /** + * Return the connection resource + * + * If we are not connected, the connection is made + * + * @throws Zend_Cache_Exception + * @return resource Connection resource + */ + private function _getConnection() + { + if (is_resource($this->_db)) { + return $this->_db; + } else { + $this->_db = @sqlite_open($this->_options['cache_db_complete_path']); + if (!(is_resource($this->_db))) { + Zend_Cache::throwException("Impossible to open " . $this->_options['cache_db_complete_path'] . " cache DB file"); + } + return $this->_db; + } + } + + /** + * Execute an SQL query silently + * + * @param string $query SQL query + * @return mixed|false query results + */ + private function _query($query) + { + $db = $this->_getConnection(); + if (is_resource($db)) { + $res = @sqlite_query($db, $query); + if ($res === false) { + return false; + } else { + return $res; + } + } + return false; + } + + /** + * Deal with the automatic vacuum process + * + * @return void + */ + private function _automaticVacuum() + { + if ($this->_options['automatic_vacuum_factor'] > 0) { + $rand = rand(1, $this->_options['automatic_vacuum_factor']); + if ($rand == 1) { + $this->_query('VACUUM'); + } + } + } + + /** + * Register a cache id with the given tag + * + * @param string $id Cache id + * @param string $tag Tag + * @return boolean True if no problem + */ + private function _registerTag($id, $tag) { + $res = $this->_query("DELETE FROM TAG WHERE name='$tag' AND id='$id'"); + $res = $this->_query("INSERT INTO tag (name, id) VALUES ('$tag', '$id')"); + if (!$res) { + $this->_log("Zend_Cache_Backend_Sqlite::_registerTag() : impossible to register tag=$tag on id=$id"); + return false; + } + return true; + } + + /** + * Build the database structure + * + * @return false + */ + private function _buildStructure() + { + $this->_query('DROP INDEX tag_id_index'); + $this->_query('DROP INDEX tag_name_index'); + $this->_query('DROP INDEX cache_id_expire_index'); + $this->_query('DROP TABLE version'); + $this->_query('DROP TABLE cache'); + $this->_query('DROP TABLE tag'); + $this->_query('CREATE TABLE version (num INTEGER PRIMARY KEY)'); + $this->_query('CREATE TABLE cache (id TEXT PRIMARY KEY, content BLOB, lastModified INTEGER, expire INTEGER)'); + $this->_query('CREATE TABLE tag (name TEXT, id TEXT)'); + $this->_query('CREATE INDEX tag_id_index ON tag(id)'); + $this->_query('CREATE INDEX tag_name_index ON tag(name)'); + $this->_query('CREATE INDEX cache_id_expire_index ON cache(id, expire)'); + $this->_query('INSERT INTO version (num) VALUES (1)'); + } + + /** + * Check if the database structure is ok (with the good version) + * + * @return boolean True if ok + */ + private function _checkStructureVersion() + { + $result = $this->_query("SELECT num FROM version"); + if (!$result) return false; + $row = @sqlite_fetch_array($result); + if (!$row) { + return false; + } + if (((int) $row['num']) != 1) { + // old cache structure + $this->_log('Zend_Cache_Backend_Sqlite::_checkStructureVersion() : old cache structure version detected => the cache is going to be dropped'); + return false; + } + return true; + } + + /** + * Clean some cache records + * + * Available modes are : + * Zend_Cache::CLEANING_MODE_ALL (default) => remove all cache entries ($tags is not used) + * Zend_Cache::CLEANING_MODE_OLD => remove too old cache entries ($tags is not used) + * Zend_Cache::CLEANING_MODE_MATCHING_TAG => remove cache entries matching all given tags + * ($tags can be an array of strings or a single string) + * Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => remove cache entries not {matching one of the given tags} + * ($tags can be an array of strings or a single string) + * Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG => remove cache entries matching any given tags + * ($tags can be an array of strings or a single string) + * + * @param string $mode Clean mode + * @param array $tags Array of tags + * @return boolean True if no problem + */ + private function _clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array()) + { + switch ($mode) { + case Zend_Cache::CLEANING_MODE_ALL: + $res1 = $this->_query('DELETE FROM cache'); + $res2 = $this->_query('DELETE FROM tag'); + return $res1 && $res2; + break; + case Zend_Cache::CLEANING_MODE_OLD: + $mktime = time(); + $res1 = $this->_query("DELETE FROM tag WHERE id IN (SELECT id FROM cache WHERE expire>0 AND expire<=$mktime)"); + $res2 = $this->_query("DELETE FROM cache WHERE expire>0 AND expire<=$mktime"); + return $res1 && $res2; + break; + case Zend_Cache::CLEANING_MODE_MATCHING_TAG: + $ids = $this->getIdsMatchingTags($tags); + $result = true; + foreach ($ids as $id) { + $result = $this->remove($id) && $result; + } + return $result; + break; + case Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG: + $ids = $this->getIdsNotMatchingTags($tags); + $result = true; + foreach ($ids as $id) { + $result = $this->remove($id) && $result; + } + return $result; + break; + case Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG: + $ids = $this->getIdsMatchingAnyTags($tags); + $result = true; + foreach ($ids as $id) { + $result = $this->remove($id) && $result; + } + return $result; + break; + default: + break; + } + return false; + } + + /** + * Check if the database structure is ok (with the good version), if no : build it + * + * @throws Zend_Cache_Exception + * @return boolean True if ok + */ + private function _checkAndBuildStructure() + { + if (!($this->_structureChecked)) { + if (!$this->_checkStructureVersion()) { + $this->_buildStructure(); + if (!$this->_checkStructureVersion()) { + Zend_Cache::throwException("Impossible to build cache structure in " . $this->_options['cache_db_complete_path']); + } + } + $this->_structureChecked = true; + } + return true; + } + +} diff --git a/lib/zend/Zend/Cache/Backend/Static.php b/lib/zend/Zend/Cache/Backend/Static.php new file mode 100644 index 00000000000..9e3c99036fb --- /dev/null +++ b/lib/zend/Zend/Cache/Backend/Static.php @@ -0,0 +1,579 @@ + null, + 'sub_dir' => 'html', + 'file_extension' => '.html', + 'index_filename' => 'index', + 'file_locking' => true, + 'cache_file_perm' => 0600, + 'cache_directory_perm' => 0700, + 'debug_header' => false, + 'tag_cache' => null, + 'disable_caching' => false + ); + + /** + * Cache for handling tags + * @var Zend_Cache_Core + */ + protected $_tagCache = null; + + /** + * Tagged items + * @var array + */ + protected $_tagged = null; + + /** + * Interceptor child method to handle the case where an Inner + * Cache object is being set since it's not supported by the + * standard backend interface + * + * @param string $name + * @param mixed $value + * @return Zend_Cache_Backend_Static + */ + public function setOption($name, $value) + { + if ($name == 'tag_cache') { + $this->setInnerCache($value); + } else { + // See #ZF-12047 and #GH-91 + if ($name == 'cache_file_umask') { + trigger_error( + "'cache_file_umask' is deprecated -> please use 'cache_file_perm' instead", + E_USER_NOTICE + ); + + $name = 'cache_file_perm'; + } + if ($name == 'cache_directory_umask') { + trigger_error( + "'cache_directory_umask' is deprecated -> please use 'cache_directory_perm' instead", + E_USER_NOTICE + ); + + $name = 'cache_directory_perm'; + } + + parent::setOption($name, $value); + } + return $this; + } + + /** + * Retrieve any option via interception of the parent's statically held + * options including the local option for a tag cache. + * + * @param string $name + * @return mixed + */ + public function getOption($name) + { + $name = strtolower($name); + + if ($name == 'tag_cache') { + return $this->getInnerCache(); + } + + return parent::getOption($name); + } + + /** + * Test if a cache is available for the given id and (if yes) return it (false else) + * + * Note : return value is always "string" (unserialization is done by the core not by the backend) + * + * @param string $id Cache id + * @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested + * @return string|false cached datas + */ + public function load($id, $doNotTestCacheValidity = false) + { + if (($id = (string)$id) === '') { + $id = $this->_detectId(); + } else { + $id = $this->_decodeId($id); + } + if (!$this->_verifyPath($id)) { + Zend_Cache::throwException('Invalid cache id: does not match expected public_dir path'); + } + if ($doNotTestCacheValidity) { + $this->_log("Zend_Cache_Backend_Static::load() : \$doNotTestCacheValidity=true is unsupported by the Static backend"); + } + + $fileName = basename($id); + if ($fileName === '') { + $fileName = $this->_options['index_filename']; + } + $pathName = $this->_options['public_dir'] . dirname($id); + $file = rtrim($pathName, '/') . '/' . $fileName . $this->_options['file_extension']; + if (file_exists($file)) { + $content = file_get_contents($file); + return $content; + } + + return false; + } + + /** + * Test if a cache is available or not (for the given id) + * + * @param string $id cache id + * @return bool + */ + public function test($id) + { + $id = $this->_decodeId($id); + if (!$this->_verifyPath($id)) { + Zend_Cache::throwException('Invalid cache id: does not match expected public_dir path'); + } + + $fileName = basename($id); + if ($fileName === '') { + $fileName = $this->_options['index_filename']; + } + if ($this->_tagged === null && $tagged = $this->getInnerCache()->load(self::INNER_CACHE_NAME)) { + $this->_tagged = $tagged; + } elseif (!$this->_tagged) { + return false; + } + $pathName = $this->_options['public_dir'] . dirname($id); + + // Switch extension if needed + if (isset($this->_tagged[$id])) { + $extension = $this->_tagged[$id]['extension']; + } else { + $extension = $this->_options['file_extension']; + } + $file = $pathName . '/' . $fileName . $extension; + if (file_exists($file)) { + return true; + } + return false; + } + + /** + * Save some string datas into a cache record + * + * Note : $data is always "string" (serialization is done by the + * core not by the backend) + * + * @param string $data Datas to cache + * @param string $id Cache id + * @param array $tags Array of strings, the cache record will be tagged by each string entry + * @param int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime) + * @return boolean true if no problem + */ + public function save($data, $id, $tags = array(), $specificLifetime = false) + { + if ($this->_options['disable_caching']) { + return true; + } + $extension = null; + if ($this->_isSerialized($data)) { + $data = unserialize($data); + $extension = '.' . ltrim($data[1], '.'); + $data = $data[0]; + } + + clearstatcache(); + if (($id = (string)$id) === '') { + $id = $this->_detectId(); + } else { + $id = $this->_decodeId($id); + } + + $fileName = basename($id); + if ($fileName === '') { + $fileName = $this->_options['index_filename']; + } + + $pathName = realpath($this->_options['public_dir']) . dirname($id); + $this->_createDirectoriesFor($pathName); + + if ($id === null || strlen($id) == 0) { + $dataUnserialized = unserialize($data); + $data = $dataUnserialized['data']; + } + $ext = $this->_options['file_extension']; + if ($extension) $ext = $extension; + $file = rtrim($pathName, '/') . '/' . $fileName . $ext; + if ($this->_options['file_locking']) { + $result = file_put_contents($file, $data, LOCK_EX); + } else { + $result = file_put_contents($file, $data); + } + @chmod($file, $this->_octdec($this->_options['cache_file_perm'])); + + if ($this->_tagged === null && $tagged = $this->getInnerCache()->load(self::INNER_CACHE_NAME)) { + $this->_tagged = $tagged; + } elseif ($this->_tagged === null) { + $this->_tagged = array(); + } + if (!isset($this->_tagged[$id])) { + $this->_tagged[$id] = array(); + } + if (!isset($this->_tagged[$id]['tags'])) { + $this->_tagged[$id]['tags'] = array(); + } + $this->_tagged[$id]['tags'] = array_unique(array_merge($this->_tagged[$id]['tags'], $tags)); + $this->_tagged[$id]['extension'] = $ext; + $this->getInnerCache()->save($this->_tagged, self::INNER_CACHE_NAME); + return (bool) $result; + } + + /** + * Recursively create the directories needed to write the static file + */ + protected function _createDirectoriesFor($path) + { + if (!is_dir($path)) { + $oldUmask = umask(0); + if ( !@mkdir($path, $this->_octdec($this->_options['cache_directory_perm']), true)) { + $lastErr = error_get_last(); + umask($oldUmask); + Zend_Cache::throwException("Can't create directory: {$lastErr['message']}"); + } + umask($oldUmask); + } + } + + /** + * Detect serialization of data (cannot predict since this is the only way + * to obey the interface yet pass in another parameter). + * + * In future, ZF 2.0, check if we can just avoid the interface restraints. + * + * This format is the only valid one possible for the class, so it's simple + * to just run a regular expression for the starting serialized format. + */ + protected function _isSerialized($data) + { + return preg_match("/a:2:\{i:0;s:\d+:\"/", $data); + } + + /** + * Remove a cache record + * + * @param string $id Cache id + * @return boolean True if no problem + */ + public function remove($id) + { + if (!$this->_verifyPath($id)) { + Zend_Cache::throwException('Invalid cache id: does not match expected public_dir path'); + } + $fileName = basename($id); + if ($this->_tagged === null && $tagged = $this->getInnerCache()->load(self::INNER_CACHE_NAME)) { + $this->_tagged = $tagged; + } elseif (!$this->_tagged) { + return false; + } + if (isset($this->_tagged[$id])) { + $extension = $this->_tagged[$id]['extension']; + } else { + $extension = $this->_options['file_extension']; + } + if ($fileName === '') { + $fileName = $this->_options['index_filename']; + } + $pathName = $this->_options['public_dir'] . dirname($id); + $file = realpath($pathName) . '/' . $fileName . $extension; + if (!file_exists($file)) { + return false; + } + return unlink($file); + } + + /** + * Remove a cache record recursively for the given directory matching a + * REQUEST_URI based relative path (deletes the actual file matching this + * in addition to the matching directory) + * + * @param string $id Cache id + * @return boolean True if no problem + */ + public function removeRecursively($id) + { + if (!$this->_verifyPath($id)) { + Zend_Cache::throwException('Invalid cache id: does not match expected public_dir path'); + } + $fileName = basename($id); + if ($fileName === '') { + $fileName = $this->_options['index_filename']; + } + $pathName = $this->_options['public_dir'] . dirname($id); + $file = $pathName . '/' . $fileName . $this->_options['file_extension']; + $directory = $pathName . '/' . $fileName; + if (file_exists($directory)) { + if (!is_writable($directory)) { + return false; + } + if (is_dir($directory)) { + foreach (new DirectoryIterator($directory) as $file) { + if (true === $file->isFile()) { + if (false === unlink($file->getPathName())) { + return false; + } + } + } + } + rmdir($directory); + } + if (file_exists($file)) { + if (!is_writable($file)) { + return false; + } + return unlink($file); + } + return true; + } + + /** + * Clean some cache records + * + * Available modes are : + * Zend_Cache::CLEANING_MODE_ALL (default) => remove all cache entries ($tags is not used) + * Zend_Cache::CLEANING_MODE_OLD => remove too old cache entries ($tags is not used) + * Zend_Cache::CLEANING_MODE_MATCHING_TAG => remove cache entries matching all given tags + * ($tags can be an array of strings or a single string) + * Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => remove cache entries not {matching one of the given tags} + * ($tags can be an array of strings or a single string) + * Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG => remove cache entries matching any given tags + * ($tags can be an array of strings or a single string) + * + * @param string $mode Clean mode + * @param array $tags Array of tags + * @return boolean true if no problem + * @throws Zend_Exception + */ + public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array()) + { + $result = false; + switch ($mode) { + case Zend_Cache::CLEANING_MODE_MATCHING_TAG: + case Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG: + if (empty($tags)) { + throw new Zend_Exception('Cannot use tag matching modes as no tags were defined'); + } + if ($this->_tagged === null && $tagged = $this->getInnerCache()->load(self::INNER_CACHE_NAME)) { + $this->_tagged = $tagged; + } elseif (!$this->_tagged) { + return true; + } + foreach ($tags as $tag) { + $urls = array_keys($this->_tagged); + foreach ($urls as $url) { + if (isset($this->_tagged[$url]['tags']) && in_array($tag, $this->_tagged[$url]['tags'])) { + $this->remove($url); + unset($this->_tagged[$url]); + } + } + } + $this->getInnerCache()->save($this->_tagged, self::INNER_CACHE_NAME); + $result = true; + break; + case Zend_Cache::CLEANING_MODE_ALL: + if ($this->_tagged === null) { + $tagged = $this->getInnerCache()->load(self::INNER_CACHE_NAME); + $this->_tagged = $tagged; + } + if ($this->_tagged === null || empty($this->_tagged)) { + return true; + } + $urls = array_keys($this->_tagged); + foreach ($urls as $url) { + $this->remove($url); + unset($this->_tagged[$url]); + } + $this->getInnerCache()->save($this->_tagged, self::INNER_CACHE_NAME); + $result = true; + break; + case Zend_Cache::CLEANING_MODE_OLD: + $this->_log("Zend_Cache_Backend_Static : Selected Cleaning Mode Currently Unsupported By This Backend"); + break; + case Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG: + if (empty($tags)) { + throw new Zend_Exception('Cannot use tag matching modes as no tags were defined'); + } + if ($this->_tagged === null) { + $tagged = $this->getInnerCache()->load(self::INNER_CACHE_NAME); + $this->_tagged = $tagged; + } + if ($this->_tagged === null || empty($this->_tagged)) { + return true; + } + $urls = array_keys($this->_tagged); + foreach ($urls as $url) { + $difference = array_diff($tags, $this->_tagged[$url]['tags']); + if (count($tags) == count($difference)) { + $this->remove($url); + unset($this->_tagged[$url]); + } + } + $this->getInnerCache()->save($this->_tagged, self::INNER_CACHE_NAME); + $result = true; + break; + default: + Zend_Cache::throwException('Invalid mode for clean() method'); + break; + } + return $result; + } + + /** + * Set an Inner Cache, used here primarily to store Tags associated + * with caches created by this backend. Note: If Tags are lost, the cache + * should be completely cleaned as the mapping of tags to caches will + * have been irrevocably lost. + * + * @param Zend_Cache_Core + * @return void + */ + public function setInnerCache(Zend_Cache_Core $cache) + { + $this->_tagCache = $cache; + $this->_options['tag_cache'] = $cache; + } + + /** + * Get the Inner Cache if set + * + * @return Zend_Cache_Core + */ + public function getInnerCache() + { + if ($this->_tagCache === null) { + Zend_Cache::throwException('An Inner Cache has not been set; use setInnerCache()'); + } + return $this->_tagCache; + } + + /** + * Verify path exists and is non-empty + * + * @param string $path + * @return bool + */ + protected function _verifyPath($path) + { + $path = realpath($path); + $base = realpath($this->_options['public_dir']); + return strncmp($path, $base, strlen($base)) !== 0; + } + + /** + * Determine the page to save from the request + * + * @return string + */ + protected function _detectId() + { + return $_SERVER['REQUEST_URI']; + } + + /** + * Validate a cache id or a tag (security, reliable filenames, reserved prefixes...) + * + * Throw an exception if a problem is found + * + * @param string $string Cache id or tag + * @throws Zend_Cache_Exception + * @return void + * @deprecated Not usable until perhaps ZF 2.0 + */ + protected static function _validateIdOrTag($string) + { + if (!is_string($string)) { + Zend_Cache::throwException('Invalid id or tag : must be a string'); + } + + // Internal only checked in Frontend - not here! + if (substr($string, 0, 9) == 'internal-') { + return; + } + + // Validation assumes no query string, fragments or scheme included - only the path + if (!preg_match( + '/^(?:\/(?:(?:%[[:xdigit:]]{2}|[A-Za-z0-9-_.!~*\'()\[\]:@&=+$,;])*)?)+$/', + $string + ) + ) { + Zend_Cache::throwException("Invalid id or tag '$string' : must be a valid URL path"); + } + } + + /** + * Detect an octal string and return its octal value for file permission ops + * otherwise return the non-string (assumed octal or decimal int already) + * + * @param string $val The potential octal in need of conversion + * @return int + */ + protected function _octdec($val) + { + if (is_string($val) && decoct(octdec($val)) == $val) { + return octdec($val); + } + return $val; + } + + /** + * Decode a request URI from the provided ID + * + * @param string $id + * @return string + */ + protected function _decodeId($id) + { + return pack('H*', $id); + } +} diff --git a/lib/zend/Zend/Cache/Backend/Test.php b/lib/zend/Zend/Cache/Backend/Test.php new file mode 100644 index 00000000000..d94e9734410 --- /dev/null +++ b/lib/zend/Zend/Cache/Backend/Test.php @@ -0,0 +1,416 @@ +_addLog('construct', array($options)); + } + + /** + * Set the frontend directives + * + * @param array $directives assoc of directives + * @return void + */ + public function setDirectives($directives) + { + $this->_addLog('setDirectives', array($directives)); + } + + /** + * Test if a cache is available for the given id and (if yes) return it (false else) + * + * For this test backend only, if $id == 'false', then the method will return false + * if $id == 'serialized', the method will return a serialized array + * ('foo' else) + * + * @param string $id Cache id + * @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested + * @return string Cached datas (or false) + */ + public function load($id, $doNotTestCacheValidity = false) + { + $this->_addLog('get', array($id, $doNotTestCacheValidity)); + + if ( $id == 'false' + || $id == 'd8523b3ee441006261eeffa5c3d3a0a7' + || $id == 'e83249ea22178277d5befc2c5e2e9ace' + || $id == '40f649b94977c0a6e76902e2a0b43587' + || $id == '88161989b73a4cbfd0b701c446115a99' + || $id == '205fc79cba24f0f0018eb92c7c8b3ba4' + || $id == '170720e35f38150b811f68a937fb042d') + { + return false; + } + if ($id=='serialized') { + return serialize(array('foo')); + } + if ($id=='serialized2') { + return serialize(array('headers' => array(), 'data' => 'foo')); + } + if ( $id == '71769f39054f75894288e397df04e445' || $id == '615d222619fb20b527168340cebd0578' + || $id == '8a02d218a5165c467e7a5747cc6bd4b6' || $id == '648aca1366211d17cbf48e65dc570bee' + || $id == '4a923ef02d7f997ca14d56dfeae25ea7') { + return serialize(array('foo', 'bar')); + } + if ( $id == 'f53c7d912cc523d9a65834c8286eceb9') { + return serialize(array('foobar')); + } + return 'foo'; + } + + /** + * Test if a cache is available or not (for the given id) + * + * For this test backend only, if $id == 'false', then the method will return false + * (123456 else) + * + * @param string $id Cache id + * @return mixed|false false (a cache is not available) or "last modified" timestamp (int) of the available cache record + */ + public function test($id) + { + $this->_addLog('test', array($id)); + if ($id=='false') { + return false; + } + if (($id=='3c439c922209e2cb0b54d6deffccd75a')) { + return false; + } + return 123456; + } + + /** + * Save some string datas into a cache record + * + * For this test backend only, if $id == 'false', then the method will return false + * (true else) + * + * @param string $data Datas to cache + * @param string $id Cache id + * @param array $tags Array of strings, the cache record will be tagged by each string entry + * @param int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime) + * @return boolean True if no problem + */ + public function save($data, $id, $tags = array(), $specificLifetime = false) + { + $this->_addLog('save', array($data, $id, $tags)); + if (substr($id,-5)=='false') { + return false; + } + return true; + } + + /** + * Remove a cache record + * + * For this test backend only, if $id == 'false', then the method will return false + * (true else) + * + * @param string $id Cache id + * @return boolean True if no problem + */ + public function remove($id) + { + $this->_addLog('remove', array($id)); + if (substr($id,-5)=='false') { + return false; + } + return true; + } + + /** + * Clean some cache records + * + * For this test backend only, if $mode == 'false', then the method will return false + * (true else) + * + * Available modes are : + * Zend_Cache::CLEANING_MODE_ALL (default) => remove all cache entries ($tags is not used) + * Zend_Cache::CLEANING_MODE_OLD => remove too old cache entries ($tags is not used) + * Zend_Cache::CLEANING_MODE_MATCHING_TAG => remove cache entries matching all given tags + * ($tags can be an array of strings or a single string) + * Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => remove cache entries not {matching one of the given tags} + * ($tags can be an array of strings or a single string) + * + * @param string $mode Clean mode + * @param array $tags Array of tags + * @return boolean True if no problem + */ + public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array()) + { + $this->_addLog('clean', array($mode, $tags)); + if ($mode=='false') { + return false; + } + return true; + } + + /** + * Get the last log + * + * @return string The last log + */ + public function getLastLog() + { + return $this->_log[$this->_index - 1]; + } + + /** + * Get the log index + * + * @return int Log index + */ + public function getLogIndex() + { + return $this->_index; + } + + /** + * Get the complete log array + * + * @return array Complete log array + */ + public function getAllLogs() + { + return $this->_log; + } + + /** + * Return true if the automatic cleaning is available for the backend + * + * @return boolean + */ + public function isAutomaticCleaningAvailable() + { + return true; + } + + /** + * Return an array of stored cache ids + * + * @return array array of stored cache ids (string) + */ + public function getIds() + { + return array( + 'prefix_id1', 'prefix_id2' + ); + } + + /** + * Return an array of stored tags + * + * @return array array of stored tags (string) + */ + public function getTags() + { + return array( + 'tag1', 'tag2' + ); + } + + /** + * Return an array of stored cache ids which match given tags + * + * In case of multiple tags, a logical AND is made between tags + * + * @param array $tags array of tags + * @return array array of matching cache ids (string) + */ + public function getIdsMatchingTags($tags = array()) + { + if ($tags == array('tag1', 'tag2')) { + return array('prefix_id1', 'prefix_id2'); + } + + return array(); + } + + /** + * Return an array of stored cache ids which don't match given tags + * + * In case of multiple tags, a logical OR is made between tags + * + * @param array $tags array of tags + * @return array array of not matching cache ids (string) + */ + public function getIdsNotMatchingTags($tags = array()) + { + if ($tags == array('tag3', 'tag4')) { + return array('prefix_id3', 'prefix_id4'); + } + + return array(); + } + + /** + * Return an array of stored cache ids which match any given tags + * + * In case of multiple tags, a logical AND is made between tags + * + * @param array $tags array of tags + * @return array array of any matching cache ids (string) + */ + public function getIdsMatchingAnyTags($tags = array()) + { + if ($tags == array('tag5', 'tag6')) { + return array('prefix_id5', 'prefix_id6'); + } + + return array(); + } + + /** + * Return the filling percentage of the backend storage + * + * @return int integer between 0 and 100 + */ + public function getFillingPercentage() + { + return 50; + } + + /** + * Return an array of metadatas for the given cache id + * + * The array must include these keys : + * - expire : the expire timestamp + * - tags : a string array of tags + * - mtime : timestamp of last modification time + * + * @param string $id cache id + * @return array array of metadatas (false if the cache id is not found) + */ + public function getMetadatas($id) + { + return false; + } + + /** + * Give (if possible) an extra lifetime to the given cache id + * + * @param string $id cache id + * @param int $extraLifetime + * @return boolean true if ok + */ + public function touch($id, $extraLifetime) + { + return true; + } + + /** + * Return an associative array of capabilities (booleans) of the backend + * + * The array must include these keys : + * - automatic_cleaning (is automating cleaning necessary) + * - tags (are tags supported) + * - expired_read (is it possible to read expired cache records + * (for doNotTestCacheValidity option for example)) + * - priority does the backend deal with priority when saving + * - infinite_lifetime (is infinite lifetime can work with this backend) + * - get_list (is it possible to get the list of cache ids and the complete list of tags) + * + * @return array associative of with capabilities + */ + public function getCapabilities() + { + return array( + 'automatic_cleaning' => true, + 'tags' => true, + 'expired_read' => false, + 'priority' => true, + 'infinite_lifetime' => true, + 'get_list' => true + ); + } + + /** + * Add an event to the log array + * + * @param string $methodName MethodName + * @param array $args Arguments + * @return void + */ + private function _addLog($methodName, $args) + { + $this->_log[$this->_index] = array( + 'methodName' => $methodName, + 'args' => $args + ); + $this->_index = $this->_index + 1; + } + +} diff --git a/lib/zend/Zend/Cache/Backend/TwoLevels.php b/lib/zend/Zend/Cache/Backend/TwoLevels.php new file mode 100644 index 00000000000..135ff6ad8de --- /dev/null +++ b/lib/zend/Zend/Cache/Backend/TwoLevels.php @@ -0,0 +1,548 @@ + (string) slow_backend : + * - Slow backend name + * - Must implement the Zend_Cache_Backend_ExtendedInterface + * - Should provide a big storage + * + * =====> (string) fast_backend : + * - Flow backend name + * - Must implement the Zend_Cache_Backend_ExtendedInterface + * - Must be much faster than slow_backend + * + * =====> (array) slow_backend_options : + * - Slow backend options (see corresponding backend) + * + * =====> (array) fast_backend_options : + * - Fast backend options (see corresponding backend) + * + * =====> (int) stats_update_factor : + * - Disable / Tune the computation of the fast backend filling percentage + * - When saving a record into cache : + * 1 => systematic computation of the fast backend filling percentage + * x (integer) > 1 => computation of the fast backend filling percentage randomly 1 times on x cache write + * + * =====> (boolean) slow_backend_custom_naming : + * =====> (boolean) fast_backend_custom_naming : + * =====> (boolean) slow_backend_autoload : + * =====> (boolean) fast_backend_autoload : + * - See Zend_Cache::factory() method + * + * =====> (boolean) auto_fill_fast_cache + * - If true, automatically fill the fast cache when a cache record was not found in fast cache, but did + * exist in slow cache. This can be usefull when a non-persistent cache like APC or Memcached got + * purged for whatever reason. + * + * =====> (boolean) auto_refresh_fast_cache + * - If true, auto refresh the fast cache when a cache record is hit + * + * @var array available options + */ + protected $_options = array( + 'slow_backend' => 'File', + 'fast_backend' => 'Apc', + 'slow_backend_options' => array(), + 'fast_backend_options' => array(), + 'stats_update_factor' => 10, + 'slow_backend_custom_naming' => false, + 'fast_backend_custom_naming' => false, + 'slow_backend_autoload' => false, + 'fast_backend_autoload' => false, + 'auto_fill_fast_cache' => true, + 'auto_refresh_fast_cache' => true + ); + + /** + * Slow Backend + * + * @var Zend_Cache_Backend_ExtendedInterface + */ + protected $_slowBackend; + + /** + * Fast Backend + * + * @var Zend_Cache_Backend_ExtendedInterface + */ + protected $_fastBackend; + + /** + * Cache for the fast backend filling percentage + * + * @var int + */ + protected $_fastBackendFillingPercentage = null; + + /** + * Constructor + * + * @param array $options Associative array of options + * @throws Zend_Cache_Exception + * @return void + */ + public function __construct(array $options = array()) + { + parent::__construct($options); + + if ($this->_options['slow_backend'] === null) { + Zend_Cache::throwException('slow_backend option has to set'); + } elseif ($this->_options['slow_backend'] instanceof Zend_Cache_Backend_ExtendedInterface) { + $this->_slowBackend = $this->_options['slow_backend']; + } else { + $this->_slowBackend = Zend_Cache::_makeBackend( + $this->_options['slow_backend'], + $this->_options['slow_backend_options'], + $this->_options['slow_backend_custom_naming'], + $this->_options['slow_backend_autoload'] + ); + if (!in_array('Zend_Cache_Backend_ExtendedInterface', class_implements($this->_slowBackend))) { + Zend_Cache::throwException('slow_backend must implement the Zend_Cache_Backend_ExtendedInterface interface'); + } + } + + if ($this->_options['fast_backend'] === null) { + Zend_Cache::throwException('fast_backend option has to set'); + } elseif ($this->_options['fast_backend'] instanceof Zend_Cache_Backend_ExtendedInterface) { + $this->_fastBackend = $this->_options['fast_backend']; + } else { + $this->_fastBackend = Zend_Cache::_makeBackend( + $this->_options['fast_backend'], + $this->_options['fast_backend_options'], + $this->_options['fast_backend_custom_naming'], + $this->_options['fast_backend_autoload'] + ); + if (!in_array('Zend_Cache_Backend_ExtendedInterface', class_implements($this->_fastBackend))) { + Zend_Cache::throwException('fast_backend must implement the Zend_Cache_Backend_ExtendedInterface interface'); + } + } + + $this->_slowBackend->setDirectives($this->_directives); + $this->_fastBackend->setDirectives($this->_directives); + } + + /** + * Test if a cache is available or not (for the given id) + * + * @param string $id cache id + * @return mixed|false (a cache is not available) or "last modified" timestamp (int) of the available cache record + */ + public function test($id) + { + $fastTest = $this->_fastBackend->test($id); + if ($fastTest) { + return $fastTest; + } else { + return $this->_slowBackend->test($id); + } + } + + /** + * Save some string datas into a cache record + * + * Note : $data is always "string" (serialization is done by the + * core not by the backend) + * + * @param string $data Datas to cache + * @param string $id Cache id + * @param array $tags Array of strings, the cache record will be tagged by each string entry + * @param int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime) + * @param int $priority integer between 0 (very low priority) and 10 (maximum priority) used by some particular backends + * @return boolean true if no problem + */ + public function save($data, $id, $tags = array(), $specificLifetime = false, $priority = 8) + { + $usage = $this->_getFastFillingPercentage('saving'); + $boolFast = true; + $lifetime = $this->getLifetime($specificLifetime); + $preparedData = $this->_prepareData($data, $lifetime, $priority); + if (($priority > 0) && (10 * $priority >= $usage)) { + $fastLifetime = $this->_getFastLifetime($lifetime, $priority); + $boolFast = $this->_fastBackend->save($preparedData, $id, array(), $fastLifetime); + $boolSlow = $this->_slowBackend->save($preparedData, $id, $tags, $lifetime); + } else { + $boolSlow = $this->_slowBackend->save($preparedData, $id, $tags, $lifetime); + if ($boolSlow === true) { + $boolFast = $this->_fastBackend->remove($id); + if (!$boolFast && !$this->_fastBackend->test($id)) { + // some backends return false on remove() even if the key never existed. (and it won't if fast is full) + // all we care about is that the key doesn't exist now + $boolFast = true; + } + } + } + + return ($boolFast && $boolSlow); + } + + /** + * Test if a cache is available for the given id and (if yes) return it (false else) + * + * Note : return value is always "string" (unserialization is done by the core not by the backend) + * + * @param string $id Cache id + * @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested + * @return string|false cached datas + */ + public function load($id, $doNotTestCacheValidity = false) + { + $resultFast = $this->_fastBackend->load($id, $doNotTestCacheValidity); + if ($resultFast === false) { + $resultSlow = $this->_slowBackend->load($id, $doNotTestCacheValidity); + if ($resultSlow === false) { + // there is no cache at all for this id + return false; + } + } + $array = $resultFast !== false ? unserialize($resultFast) : unserialize($resultSlow); + + //In case no cache entry was found in the FastCache and auto-filling is enabled, copy data to FastCache + if ($resultFast === false && $this->_options['auto_fill_fast_cache']) { + $preparedData = $this->_prepareData($array['data'], $array['lifetime'], $array['priority']); + $this->_fastBackend->save($preparedData, $id, array(), $array['lifetime']); + } + // maybe, we have to refresh the fast cache ? + elseif ($this->_options['auto_refresh_fast_cache']) { + if ($array['priority'] == 10) { + // no need to refresh the fast cache with priority = 10 + return $array['data']; + } + $newFastLifetime = $this->_getFastLifetime($array['lifetime'], $array['priority'], time() - $array['expire']); + // we have the time to refresh the fast cache + $usage = $this->_getFastFillingPercentage('loading'); + if (($array['priority'] > 0) && (10 * $array['priority'] >= $usage)) { + // we can refresh the fast cache + $preparedData = $this->_prepareData($array['data'], $array['lifetime'], $array['priority']); + $this->_fastBackend->save($preparedData, $id, array(), $newFastLifetime); + } + } + return $array['data']; + } + + /** + * Remove a cache record + * + * @param string $id Cache id + * @return boolean True if no problem + */ + public function remove($id) + { + $boolFast = $this->_fastBackend->remove($id); + $boolSlow = $this->_slowBackend->remove($id); + return $boolFast && $boolSlow; + } + + /** + * Clean some cache records + * + * Available modes are : + * Zend_Cache::CLEANING_MODE_ALL (default) => remove all cache entries ($tags is not used) + * Zend_Cache::CLEANING_MODE_OLD => remove too old cache entries ($tags is not used) + * Zend_Cache::CLEANING_MODE_MATCHING_TAG => remove cache entries matching all given tags + * ($tags can be an array of strings or a single string) + * Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => remove cache entries not {matching one of the given tags} + * ($tags can be an array of strings or a single string) + * Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG => remove cache entries matching any given tags + * ($tags can be an array of strings or a single string) + * + * @param string $mode Clean mode + * @param array $tags Array of tags + * @throws Zend_Cache_Exception + * @return boolean true if no problem + */ + public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array()) + { + switch($mode) { + case Zend_Cache::CLEANING_MODE_ALL: + $boolFast = $this->_fastBackend->clean(Zend_Cache::CLEANING_MODE_ALL); + $boolSlow = $this->_slowBackend->clean(Zend_Cache::CLEANING_MODE_ALL); + return $boolFast && $boolSlow; + break; + case Zend_Cache::CLEANING_MODE_OLD: + return $this->_slowBackend->clean(Zend_Cache::CLEANING_MODE_OLD); + case Zend_Cache::CLEANING_MODE_MATCHING_TAG: + $ids = $this->_slowBackend->getIdsMatchingTags($tags); + $res = true; + foreach ($ids as $id) { + $bool = $this->remove($id); + $res = $res && $bool; + } + return $res; + break; + case Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG: + $ids = $this->_slowBackend->getIdsNotMatchingTags($tags); + $res = true; + foreach ($ids as $id) { + $bool = $this->remove($id); + $res = $res && $bool; + } + return $res; + break; + case Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG: + $ids = $this->_slowBackend->getIdsMatchingAnyTags($tags); + $res = true; + foreach ($ids as $id) { + $bool = $this->remove($id); + $res = $res && $bool; + } + return $res; + break; + default: + Zend_Cache::throwException('Invalid mode for clean() method'); + break; + } + } + + /** + * Return an array of stored cache ids + * + * @return array array of stored cache ids (string) + */ + public function getIds() + { + return $this->_slowBackend->getIds(); + } + + /** + * Return an array of stored tags + * + * @return array array of stored tags (string) + */ + public function getTags() + { + return $this->_slowBackend->getTags(); + } + + /** + * Return an array of stored cache ids which match given tags + * + * In case of multiple tags, a logical AND is made between tags + * + * @param array $tags array of tags + * @return array array of matching cache ids (string) + */ + public function getIdsMatchingTags($tags = array()) + { + return $this->_slowBackend->getIdsMatchingTags($tags); + } + + /** + * Return an array of stored cache ids which don't match given tags + * + * In case of multiple tags, a logical OR is made between tags + * + * @param array $tags array of tags + * @return array array of not matching cache ids (string) + */ + public function getIdsNotMatchingTags($tags = array()) + { + return $this->_slowBackend->getIdsNotMatchingTags($tags); + } + + /** + * Return an array of stored cache ids which match any given tags + * + * In case of multiple tags, a logical AND is made between tags + * + * @param array $tags array of tags + * @return array array of any matching cache ids (string) + */ + public function getIdsMatchingAnyTags($tags = array()) + { + return $this->_slowBackend->getIdsMatchingAnyTags($tags); + } + + /** + * Return the filling percentage of the backend storage + * + * @return int integer between 0 and 100 + */ + public function getFillingPercentage() + { + return $this->_slowBackend->getFillingPercentage(); + } + + /** + * Return an array of metadatas for the given cache id + * + * The array must include these keys : + * - expire : the expire timestamp + * - tags : a string array of tags + * - mtime : timestamp of last modification time + * + * @param string $id cache id + * @return array array of metadatas (false if the cache id is not found) + */ + public function getMetadatas($id) + { + return $this->_slowBackend->getMetadatas($id); + } + + /** + * Give (if possible) an extra lifetime to the given cache id + * + * @param string $id cache id + * @param int $extraLifetime + * @return boolean true if ok + */ + public function touch($id, $extraLifetime) + { + return $this->_slowBackend->touch($id, $extraLifetime); + } + + /** + * Return an associative array of capabilities (booleans) of the backend + * + * The array must include these keys : + * - automatic_cleaning (is automating cleaning necessary) + * - tags (are tags supported) + * - expired_read (is it possible to read expired cache records + * (for doNotTestCacheValidity option for example)) + * - priority does the backend deal with priority when saving + * - infinite_lifetime (is infinite lifetime can work with this backend) + * - get_list (is it possible to get the list of cache ids and the complete list of tags) + * + * @return array associative of with capabilities + */ + public function getCapabilities() + { + $slowBackendCapabilities = $this->_slowBackend->getCapabilities(); + return array( + 'automatic_cleaning' => $slowBackendCapabilities['automatic_cleaning'], + 'tags' => $slowBackendCapabilities['tags'], + 'expired_read' => $slowBackendCapabilities['expired_read'], + 'priority' => $slowBackendCapabilities['priority'], + 'infinite_lifetime' => $slowBackendCapabilities['infinite_lifetime'], + 'get_list' => $slowBackendCapabilities['get_list'] + ); + } + + /** + * Prepare a serialized array to store datas and metadatas informations + * + * @param string $data data to store + * @param int $lifetime original lifetime + * @param int $priority priority + * @return string serialize array to store into cache + */ + private function _prepareData($data, $lifetime, $priority) + { + $lt = $lifetime; + if ($lt === null) { + $lt = 9999999999; + } + return serialize(array( + 'data' => $data, + 'lifetime' => $lifetime, + 'expire' => time() + $lt, + 'priority' => $priority + )); + } + + /** + * Compute and return the lifetime for the fast backend + * + * @param int $lifetime original lifetime + * @param int $priority priority + * @param int $maxLifetime maximum lifetime + * @return int lifetime for the fast backend + */ + private function _getFastLifetime($lifetime, $priority, $maxLifetime = null) + { + if ($lifetime <= 0) { + // if no lifetime, we have an infinite lifetime + // we need to use arbitrary lifetimes + $fastLifetime = (int) (2592000 / (11 - $priority)); + } else { + // prevent computed infinite lifetime (0) by ceil + $fastLifetime = (int) ceil($lifetime / (11 - $priority)); + } + + if ($maxLifetime >= 0 && $fastLifetime > $maxLifetime) { + return $maxLifetime; + } + + return $fastLifetime; + } + + /** + * PUBLIC METHOD FOR UNIT TESTING ONLY ! + * + * Force a cache record to expire + * + * @param string $id cache id + */ + public function ___expire($id) + { + $this->_fastBackend->remove($id); + $this->_slowBackend->___expire($id); + } + + private function _getFastFillingPercentage($mode) + { + + if ($mode == 'saving') { + // mode saving + if ($this->_fastBackendFillingPercentage === null) { + $this->_fastBackendFillingPercentage = $this->_fastBackend->getFillingPercentage(); + } else { + $rand = rand(1, $this->_options['stats_update_factor']); + if ($rand == 1) { + // we force a refresh + $this->_fastBackendFillingPercentage = $this->_fastBackend->getFillingPercentage(); + } + } + } else { + // mode loading + // we compute the percentage only if it's not available in cache + if ($this->_fastBackendFillingPercentage === null) { + $this->_fastBackendFillingPercentage = $this->_fastBackend->getFillingPercentage(); + } + } + return $this->_fastBackendFillingPercentage; + } + +} diff --git a/lib/zend/Zend/Cache/Backend/WinCache.php b/lib/zend/Zend/Cache/Backend/WinCache.php new file mode 100644 index 00000000000..06843fa39af --- /dev/null +++ b/lib/zend/Zend/Cache/Backend/WinCache.php @@ -0,0 +1,349 @@ + infinite lifetime) + * @return boolean true if no problem + */ + public function save($data, $id, $tags = array(), $specificLifetime = false) + { + $lifetime = $this->getLifetime($specificLifetime); + $result = wincache_ucache_set($id, array($data, time(), $lifetime), $lifetime); + if (count($tags) > 0) { + $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_WINCACHE_BACKEND); + } + return $result; + } + + /** + * Remove a cache record + * + * @param string $id cache id + * @return boolean true if no problem + */ + public function remove($id) + { + return wincache_ucache_delete($id); + } + + /** + * Clean some cache records + * + * Available modes are : + * 'all' (default) => remove all cache entries ($tags is not used) + * 'old' => unsupported + * 'matchingTag' => unsupported + * 'notMatchingTag' => unsupported + * 'matchingAnyTag' => unsupported + * + * @param string $mode clean mode + * @param array $tags array of tags + * @throws Zend_Cache_Exception + * @return boolean true if no problem + */ + public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array()) + { + switch ($mode) { + case Zend_Cache::CLEANING_MODE_ALL: + return wincache_ucache_clear(); + break; + case Zend_Cache::CLEANING_MODE_OLD: + $this->_log("Zend_Cache_Backend_WinCache::clean() : CLEANING_MODE_OLD is unsupported by the WinCache backend"); + break; + case Zend_Cache::CLEANING_MODE_MATCHING_TAG: + case Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG: + case Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG: + $this->_log(self::TAGS_UNSUPPORTED_BY_CLEAN_OF_WINCACHE_BACKEND); + break; + default: + Zend_Cache::throwException('Invalid mode for clean() method'); + break; + } + } + + /** + * Return true if the automatic cleaning is available for the backend + * + * DEPRECATED : use getCapabilities() instead + * + * @deprecated + * @return boolean + */ + public function isAutomaticCleaningAvailable() + { + return false; + } + + /** + * Return the filling percentage of the backend storage + * + * @throws Zend_Cache_Exception + * @return int integer between 0 and 100 + */ + public function getFillingPercentage() + { + $mem = wincache_ucache_meminfo(); + $memSize = $mem['memory_total']; + $memUsed = $memSize - $mem['memory_free']; + if ($memSize == 0) { + Zend_Cache::throwException('can\'t get WinCache memory size'); + } + if ($memUsed > $memSize) { + return 100; + } + return ((int) (100. * ($memUsed / $memSize))); + } + + /** + * Return an array of stored tags + * + * @return array array of stored tags (string) + */ + public function getTags() + { + $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_WINCACHE_BACKEND); + return array(); + } + + /** + * Return an array of stored cache ids which match given tags + * + * In case of multiple tags, a logical AND is made between tags + * + * @param array $tags array of tags + * @return array array of matching cache ids (string) + */ + public function getIdsMatchingTags($tags = array()) + { + $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_WINCACHE_BACKEND); + return array(); + } + + /** + * Return an array of stored cache ids which don't match given tags + * + * In case of multiple tags, a logical OR is made between tags + * + * @param array $tags array of tags + * @return array array of not matching cache ids (string) + */ + public function getIdsNotMatchingTags($tags = array()) + { + $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_WINCACHE_BACKEND); + return array(); + } + + /** + * Return an array of stored cache ids which match any given tags + * + * In case of multiple tags, a logical AND is made between tags + * + * @param array $tags array of tags + * @return array array of any matching cache ids (string) + */ + public function getIdsMatchingAnyTags($tags = array()) + { + $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_WINCACHE_BACKEND); + return array(); + } + + /** + * Return an array of stored cache ids + * + * @return array array of stored cache ids (string) + */ + public function getIds() + { + $res = array(); + $array = wincache_ucache_info(); + $records = $array['ucache_entries']; + foreach ($records as $record) { + $res[] = $record['key_name']; + } + return $res; + } + + /** + * Return an array of metadatas for the given cache id + * + * The array must include these keys : + * - expire : the expire timestamp + * - tags : a string array of tags + * - mtime : timestamp of last modification time + * + * @param string $id cache id + * @return array array of metadatas (false if the cache id is not found) + */ + public function getMetadatas($id) + { + $tmp = wincache_ucache_get($id); + if (is_array($tmp)) { + $data = $tmp[0]; + $mtime = $tmp[1]; + if (!isset($tmp[2])) { + return false; + } + $lifetime = $tmp[2]; + return array( + 'expire' => $mtime + $lifetime, + 'tags' => array(), + 'mtime' => $mtime + ); + } + return false; + } + + /** + * Give (if possible) an extra lifetime to the given cache id + * + * @param string $id cache id + * @param int $extraLifetime + * @return boolean true if ok + */ + public function touch($id, $extraLifetime) + { + $tmp = wincache_ucache_get($id); + if (is_array($tmp)) { + $data = $tmp[0]; + $mtime = $tmp[1]; + if (!isset($tmp[2])) { + return false; + } + $lifetime = $tmp[2]; + $newLifetime = $lifetime - (time() - $mtime) + $extraLifetime; + if ($newLifetime <=0) { + return false; + } + return wincache_ucache_set($id, array($data, time(), $newLifetime), $newLifetime); + } + return false; + } + + /** + * Return an associative array of capabilities (booleans) of the backend + * + * The array must include these keys : + * - automatic_cleaning (is automating cleaning necessary) + * - tags (are tags supported) + * - expired_read (is it possible to read expired cache records + * (for doNotTestCacheValidity option for example)) + * - priority does the backend deal with priority when saving + * - infinite_lifetime (is infinite lifetime can work with this backend) + * - get_list (is it possible to get the list of cache ids and the complete list of tags) + * + * @return array associative of with capabilities + */ + public function getCapabilities() + { + return array( + 'automatic_cleaning' => false, + 'tags' => false, + 'expired_read' => false, + 'priority' => false, + 'infinite_lifetime' => false, + 'get_list' => true + ); + } + +} diff --git a/lib/zend/Zend/Cache/Backend/Xcache.php b/lib/zend/Zend/Cache/Backend/Xcache.php new file mode 100644 index 00000000000..4bc077fc923 --- /dev/null +++ b/lib/zend/Zend/Cache/Backend/Xcache.php @@ -0,0 +1,221 @@ + (string) user : + * xcache.admin.user (necessary for the clean() method) + * + * =====> (string) password : + * xcache.admin.pass (clear, not MD5) (necessary for the clean() method) + * + * @var array available options + */ + protected $_options = array( + 'user' => null, + 'password' => null + ); + + /** + * Constructor + * + * @param array $options associative array of options + * @throws Zend_Cache_Exception + * @return void + */ + public function __construct(array $options = array()) + { + if (!extension_loaded('xcache')) { + Zend_Cache::throwException('The xcache extension must be loaded for using this backend !'); + } + parent::__construct($options); + } + + /** + * Test if a cache is available for the given id and (if yes) return it (false else) + * + * WARNING $doNotTestCacheValidity=true is unsupported by the Xcache backend + * + * @param string $id cache id + * @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested + * @return string cached datas (or false) + */ + public function load($id, $doNotTestCacheValidity = false) + { + if ($doNotTestCacheValidity) { + $this->_log("Zend_Cache_Backend_Xcache::load() : \$doNotTestCacheValidity=true is unsupported by the Xcache backend"); + } + $tmp = xcache_get($id); + if (is_array($tmp)) { + return $tmp[0]; + } + return false; + } + + /** + * Test if a cache is available or not (for the given id) + * + * @param string $id cache id + * @return mixed false (a cache is not available) or "last modified" timestamp (int) of the available cache record + */ + public function test($id) + { + if (xcache_isset($id)) { + $tmp = xcache_get($id); + if (is_array($tmp)) { + return $tmp[1]; + } + } + return false; + } + + /** + * Save some string datas into a cache record + * + * Note : $data is always "string" (serialization is done by the + * core not by the backend) + * + * @param string $data datas to cache + * @param string $id cache id + * @param array $tags array of strings, the cache record will be tagged by each string entry + * @param int $specificLifetime if != false, set a specific lifetime for this cache record (null => infinite lifetime) + * @return boolean true if no problem + */ + public function save($data, $id, $tags = array(), $specificLifetime = false) + { + $lifetime = $this->getLifetime($specificLifetime); + $result = xcache_set($id, array($data, time()), $lifetime); + if (count($tags) > 0) { + $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_XCACHE_BACKEND); + } + return $result; + } + + /** + * Remove a cache record + * + * @param string $id cache id + * @return boolean true if no problem + */ + public function remove($id) + { + return xcache_unset($id); + } + + /** + * Clean some cache records + * + * Available modes are : + * 'all' (default) => remove all cache entries ($tags is not used) + * 'old' => unsupported + * 'matchingTag' => unsupported + * 'notMatchingTag' => unsupported + * 'matchingAnyTag' => unsupported + * + * @param string $mode clean mode + * @param array $tags array of tags + * @throws Zend_Cache_Exception + * @return boolean true if no problem + */ + public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array()) + { + switch ($mode) { + case Zend_Cache::CLEANING_MODE_ALL: + // Necessary because xcache_clear_cache() need basic authentification + $backup = array(); + if (isset($_SERVER['PHP_AUTH_USER'])) { + $backup['PHP_AUTH_USER'] = $_SERVER['PHP_AUTH_USER']; + } + if (isset($_SERVER['PHP_AUTH_PW'])) { + $backup['PHP_AUTH_PW'] = $_SERVER['PHP_AUTH_PW']; + } + if ($this->_options['user']) { + $_SERVER['PHP_AUTH_USER'] = $this->_options['user']; + } + if ($this->_options['password']) { + $_SERVER['PHP_AUTH_PW'] = $this->_options['password']; + } + + $cnt = xcache_count(XC_TYPE_VAR); + for ($i=0; $i < $cnt; $i++) { + xcache_clear_cache(XC_TYPE_VAR, $i); + } + + if (isset($backup['PHP_AUTH_USER'])) { + $_SERVER['PHP_AUTH_USER'] = $backup['PHP_AUTH_USER']; + $_SERVER['PHP_AUTH_PW'] = $backup['PHP_AUTH_PW']; + } + return true; + break; + case Zend_Cache::CLEANING_MODE_OLD: + $this->_log("Zend_Cache_Backend_Xcache::clean() : CLEANING_MODE_OLD is unsupported by the Xcache backend"); + break; + case Zend_Cache::CLEANING_MODE_MATCHING_TAG: + case Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG: + case Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG: + $this->_log(self::TAGS_UNSUPPORTED_BY_CLEAN_OF_XCACHE_BACKEND); + break; + default: + Zend_Cache::throwException('Invalid mode for clean() method'); + break; + } + } + + /** + * Return true if the automatic cleaning is available for the backend + * + * @return boolean + */ + public function isAutomaticCleaningAvailable() + { + return false; + } + +} diff --git a/lib/zend/Zend/Cache/Backend/ZendPlatform.php b/lib/zend/Zend/Cache/Backend/ZendPlatform.php new file mode 100644 index 00000000000..31e9a7a22af --- /dev/null +++ b/lib/zend/Zend/Cache/Backend/ZendPlatform.php @@ -0,0 +1,317 @@ +_directives['lifetime']; + } + $res = output_cache_get($id, $lifetime); + if($res) { + return $res[0]; + } else { + return false; + } + } + + + /** + * Test if a cache is available or not (for the given id) + * + * @param string $id Cache id + * @return mixed|false false (a cache is not available) or "last modified" timestamp (int) of the available cache record + */ + public function test($id) + { + $result = output_cache_get($id, $this->_directives['lifetime']); + if ($result) { + return $result[1]; + } + return false; + } + + /** + * Save some string datas into a cache record + * + * Note : $data is always "string" (serialization is done by the + * core not by the backend) + * + * @param string $data Data to cache + * @param string $id Cache id + * @param array $tags Array of strings, the cache record will be tagged by each string entry + * @param int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime) + * @return boolean true if no problem + */ + public function save($data, $id, $tags = array(), $specificLifetime = false) + { + if (!($specificLifetime === false)) { + $this->_log("Zend_Cache_Backend_ZendPlatform::save() : non false specifc lifetime is unsuported for this backend"); + } + + $lifetime = $this->_directives['lifetime']; + $result1 = output_cache_put($id, array($data, time())); + $result2 = (count($tags) == 0); + + foreach ($tags as $tag) { + $tagid = self::TAGS_PREFIX.$tag; + $old_tags = output_cache_get($tagid, $lifetime); + if ($old_tags === false) { + $old_tags = array(); + } + $old_tags[$id] = $id; + output_cache_remove_key($tagid); + $result2 = output_cache_put($tagid, $old_tags); + } + + return $result1 && $result2; + } + + + /** + * Remove a cache record + * + * @param string $id Cache id + * @return boolean True if no problem + */ + public function remove($id) + { + return output_cache_remove_key($id); + } + + + /** + * Clean some cache records + * + * Available modes are : + * Zend_Cache::CLEANING_MODE_ALL (default) => remove all cache entries ($tags is not used) + * Zend_Cache::CLEANING_MODE_OLD => remove too old cache entries ($tags is not used) + * This mode is not supported in this backend + * Zend_Cache::CLEANING_MODE_MATCHING_TAG => remove cache entries matching all given tags + * ($tags can be an array of strings or a single string) + * Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => unsupported + * Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG => remove cache entries matching any given tags + * ($tags can be an array of strings or a single string) + * + * @param string $mode Clean mode + * @param array $tags Array of tags + * @throws Zend_Cache_Exception + * @return boolean True if no problem + */ + public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array()) + { + switch ($mode) { + case Zend_Cache::CLEANING_MODE_ALL: + case Zend_Cache::CLEANING_MODE_OLD: + $cache_dir = ini_get('zend_accelerator.output_cache_dir'); + if (!$cache_dir) { + return false; + } + $cache_dir .= '/.php_cache_api/'; + return $this->_clean($cache_dir, $mode); + break; + case Zend_Cache::CLEANING_MODE_MATCHING_TAG: + $idlist = null; + foreach ($tags as $tag) { + $next_idlist = output_cache_get(self::TAGS_PREFIX.$tag, $this->_directives['lifetime']); + if ($idlist) { + $idlist = array_intersect_assoc($idlist, $next_idlist); + } else { + $idlist = $next_idlist; + } + if (count($idlist) == 0) { + // if ID list is already empty - we may skip checking other IDs + $idlist = null; + break; + } + } + if ($idlist) { + foreach ($idlist as $id) { + output_cache_remove_key($id); + } + } + return true; + break; + case Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG: + $this->_log("Zend_Cache_Backend_ZendPlatform::clean() : CLEANING_MODE_NOT_MATCHING_TAG is not supported by the Zend Platform backend"); + return false; + break; + case Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG: + $idlist = null; + foreach ($tags as $tag) { + $next_idlist = output_cache_get(self::TAGS_PREFIX.$tag, $this->_directives['lifetime']); + if ($idlist) { + $idlist = array_merge_recursive($idlist, $next_idlist); + } else { + $idlist = $next_idlist; + } + if (count($idlist) == 0) { + // if ID list is already empty - we may skip checking other IDs + $idlist = null; + break; + } + } + if ($idlist) { + foreach ($idlist as $id) { + output_cache_remove_key($id); + } + } + return true; + break; + default: + Zend_Cache::throwException('Invalid mode for clean() method'); + break; + } + } + + /** + * Clean a directory and recursivly go over it's subdirectories + * + * Remove all the cached files that need to be cleaned (according to mode and files mtime) + * + * @param string $dir Path of directory ot clean + * @param string $mode The same parameter as in Zend_Cache_Backend_ZendPlatform::clean() + * @return boolean True if ok + */ + private function _clean($dir, $mode) + { + $d = @dir($dir); + if (!$d) { + return false; + } + $result = true; + while (false !== ($file = $d->read())) { + if ($file == '.' || $file == '..') { + continue; + } + $file = $d->path . $file; + if (is_dir($file)) { + $result = ($this->_clean($file .'/', $mode)) && ($result); + } else { + if ($mode == Zend_Cache::CLEANING_MODE_ALL) { + $result = ($this->_remove($file)) && ($result); + } else if ($mode == Zend_Cache::CLEANING_MODE_OLD) { + // Files older than lifetime get deleted from cache + if ($this->_directives['lifetime'] !== null) { + if ((time() - @filemtime($file)) > $this->_directives['lifetime']) { + $result = ($this->_remove($file)) && ($result); + } + } + } + } + } + $d->close(); + return $result; + } + + /** + * Remove a file + * + * If we can't remove the file (because of locks or any problem), we will touch + * the file to invalidate it + * + * @param string $file Complete file path + * @return boolean True if ok + */ + private function _remove($file) + { + if (!@unlink($file)) { + # If we can't remove the file (because of locks or any problem), we will touch + # the file to invalidate it + $this->_log("Zend_Cache_Backend_ZendPlatform::_remove() : we can't remove $file => we are going to try to invalidate it"); + if ($this->_directives['lifetime'] === null) { + return false; + } + if (!file_exists($file)) { + return false; + } + return @touch($file, time() - 2*abs($this->_directives['lifetime'])); + } + return true; + } + +} diff --git a/lib/zend/Zend/Cache/Backend/ZendServer.php b/lib/zend/Zend/Cache/Backend/ZendServer.php new file mode 100755 index 00000000000..ededaf5a9bc --- /dev/null +++ b/lib/zend/Zend/Cache/Backend/ZendServer.php @@ -0,0 +1,207 @@ + (string) namespace : + * Namespace to be used for chaching operations + * + * @var array available options + */ + protected $_options = array( + 'namespace' => 'zendframework' + ); + + /** + * Store data + * + * @param mixed $data Object to store + * @param string $id Cache id + * @param int $timeToLive Time to live in seconds + * @throws Zend_Cache_Exception + */ + abstract protected function _store($data, $id, $timeToLive); + + /** + * Fetch data + * + * @param string $id Cache id + * @throws Zend_Cache_Exception + */ + abstract protected function _fetch($id); + + /** + * Unset data + * + * @param string $id Cache id + */ + abstract protected function _unset($id); + + /** + * Clear cache + */ + abstract protected function _clear(); + + /** + * Test if a cache is available for the given id and (if yes) return it (false else) + * + * @param string $id cache id + * @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested + * @return string cached datas (or false) + */ + public function load($id, $doNotTestCacheValidity = false) + { + $tmp = $this->_fetch($id); + if ($tmp !== null) { + return $tmp; + } + return false; + } + + /** + * Test if a cache is available or not (for the given id) + * + * @param string $id cache id + * @return mixed false (a cache is not available) or "last modified" timestamp (int) of the available cache record + * @throws Zend_Cache_Exception + */ + public function test($id) + { + $tmp = $this->_fetch('internal-metadatas---' . $id); + if ($tmp !== false) { + if (!is_array($tmp) || !isset($tmp['mtime'])) { + Zend_Cache::throwException('Cache metadata for \'' . $id . '\' id is corrupted' ); + } + return $tmp['mtime']; + } + return false; + } + + /** + * Compute & return the expire time + * + * @return int expire time (unix timestamp) + */ + private function _expireTime($lifetime) + { + if ($lifetime === null) { + return 9999999999; + } + return time() + $lifetime; + } + + /** + * Save some string datas into a cache record + * + * Note : $data is always "string" (serialization is done by the + * core not by the backend) + * + * @param string $data datas to cache + * @param string $id cache id + * @param array $tags array of strings, the cache record will be tagged by each string entry + * @param int $specificLifetime if != false, set a specific lifetime for this cache record (null => infinite lifetime) + * @return boolean true if no problem + */ + public function save($data, $id, $tags = array(), $specificLifetime = false) + { + $lifetime = $this->getLifetime($specificLifetime); + $metadatas = array( + 'mtime' => time(), + 'expire' => $this->_expireTime($lifetime), + ); + + if (count($tags) > 0) { + $this->_log('Zend_Cache_Backend_ZendServer::save() : tags are unsupported by the ZendServer backends'); + } + + return $this->_store($data, $id, $lifetime) && + $this->_store($metadatas, 'internal-metadatas---' . $id, $lifetime); + } + + /** + * Remove a cache record + * + * @param string $id cache id + * @return boolean true if no problem + */ + public function remove($id) + { + $result1 = $this->_unset($id); + $result2 = $this->_unset('internal-metadatas---' . $id); + + return $result1 && $result2; + } + + /** + * Clean some cache records + * + * Available modes are : + * 'all' (default) => remove all cache entries ($tags is not used) + * 'old' => unsupported + * 'matchingTag' => unsupported + * 'notMatchingTag' => unsupported + * 'matchingAnyTag' => unsupported + * + * @param string $mode clean mode + * @param array $tags array of tags + * @throws Zend_Cache_Exception + * @return boolean true if no problem + */ + public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array()) + { + switch ($mode) { + case Zend_Cache::CLEANING_MODE_ALL: + $this->_clear(); + return true; + break; + case Zend_Cache::CLEANING_MODE_OLD: + $this->_log("Zend_Cache_Backend_ZendServer::clean() : CLEANING_MODE_OLD is unsupported by the Zend Server backends."); + break; + case Zend_Cache::CLEANING_MODE_MATCHING_TAG: + case Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG: + case Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG: + $this->_clear(); + $this->_log('Zend_Cache_Backend_ZendServer::clean() : tags are unsupported by the Zend Server backends.'); + break; + default: + Zend_Cache::throwException('Invalid mode for clean() method'); + break; + } + } +} diff --git a/lib/zend/Zend/Cache/Backend/ZendServer/Disk.php b/lib/zend/Zend/Cache/Backend/ZendServer/Disk.php new file mode 100755 index 00000000000..54914fefff4 --- /dev/null +++ b/lib/zend/Zend/Cache/Backend/ZendServer/Disk.php @@ -0,0 +1,101 @@ +_options['namespace'] . '::' . $id, + $data, + $timeToLive) === false) { + $this->_log('Store operation failed.'); + return false; + } + return true; + } + + /** + * Fetch data + * + * @param string $id Cache id + * @return mixed|null + */ + protected function _fetch($id) + { + return zend_disk_cache_fetch($this->_options['namespace'] . '::' . $id); + } + + /** + * Unset data + * + * @param string $id Cache id + * @return boolean true if no problem + */ + protected function _unset($id) + { + return zend_disk_cache_delete($this->_options['namespace'] . '::' . $id); + } + + /** + * Clear cache + */ + protected function _clear() + { + zend_disk_cache_clear($this->_options['namespace']); + } +} diff --git a/lib/zend/Zend/Cache/Backend/ZendServer/ShMem.php b/lib/zend/Zend/Cache/Backend/ZendServer/ShMem.php new file mode 100755 index 00000000000..83086dcd4ea --- /dev/null +++ b/lib/zend/Zend/Cache/Backend/ZendServer/ShMem.php @@ -0,0 +1,101 @@ +_options['namespace'] . '::' . $id, + $data, + $timeToLive) === false) { + $this->_log('Store operation failed.'); + return false; + } + return true; + } + + /** + * Fetch data + * + * @param string $id Cache id + * @return mixed|null + */ + protected function _fetch($id) + { + return zend_shm_cache_fetch($this->_options['namespace'] . '::' . $id); + } + + /** + * Unset data + * + * @param string $id Cache id + * @return boolean true if no problem + */ + protected function _unset($id) + { + return zend_shm_cache_delete($this->_options['namespace'] . '::' . $id); + } + + /** + * Clear cache + */ + protected function _clear() + { + zend_shm_cache_clear($this->_options['namespace']); + } +} diff --git a/lib/zend/Zend/Cache/Core.php b/lib/zend/Zend/Cache/Core.php new file mode 100644 index 00000000000..685d5d52b65 --- /dev/null +++ b/lib/zend/Zend/Cache/Core.php @@ -0,0 +1,765 @@ + (boolean) write_control : + * - Enable / disable write control (the cache is read just after writing to detect corrupt entries) + * - Enable write control will lightly slow the cache writing but not the cache reading + * Write control can detect some corrupt cache files but maybe it's not a perfect control + * + * ====> (boolean) caching : + * - Enable / disable caching + * (can be very useful for the debug of cached scripts) + * + * =====> (string) cache_id_prefix : + * - prefix for cache ids (namespace) + * + * ====> (boolean) automatic_serialization : + * - Enable / disable automatic serialization + * - It can be used to save directly datas which aren't strings (but it's slower) + * + * ====> (int) automatic_cleaning_factor : + * - Disable / Tune the automatic cleaning process + * - The automatic cleaning process destroy too old (for the given life time) + * cache files when a new cache file is written : + * 0 => no automatic cache cleaning + * 1 => systematic cache cleaning + * x (integer) > 1 => automatic cleaning randomly 1 times on x cache write + * + * ====> (int) lifetime : + * - Cache lifetime (in seconds) + * - If null, the cache is valid forever. + * + * ====> (boolean) logging : + * - If set to true, logging is activated (but the system is slower) + * + * ====> (boolean) ignore_user_abort + * - If set to true, the core will set the ignore_user_abort PHP flag inside the + * save() method to avoid cache corruptions in some cases (default false) + * + * @var array $_options available options + */ + protected $_options = array( + 'write_control' => true, + 'caching' => true, + 'cache_id_prefix' => null, + 'automatic_serialization' => false, + 'automatic_cleaning_factor' => 10, + 'lifetime' => 3600, + 'logging' => false, + 'logger' => null, + 'ignore_user_abort' => false + ); + + /** + * Array of options which have to be transfered to backend + * + * @var array $_directivesList + */ + protected static $_directivesList = array('lifetime', 'logging', 'logger'); + + /** + * Not used for the core, just a sort a hint to get a common setOption() method (for the core and for frontends) + * + * @var array $_specificOptions + */ + protected $_specificOptions = array(); + + /** + * Last used cache id + * + * @var string $_lastId + */ + private $_lastId = null; + + /** + * True if the backend implements Zend_Cache_Backend_ExtendedInterface + * + * @var boolean $_extendedBackend + */ + protected $_extendedBackend = false; + + /** + * Array of capabilities of the backend (only if it implements Zend_Cache_Backend_ExtendedInterface) + * + * @var array + */ + protected $_backendCapabilities = array(); + + /** + * Constructor + * + * @param array|Zend_Config $options Associative array of options or Zend_Config instance + * @throws Zend_Cache_Exception + * @return void + */ + public function __construct($options = array()) + { + if ($options instanceof Zend_Config) { + $options = $options->toArray(); + } + if (!is_array($options)) { + Zend_Cache::throwException("Options passed were not an array" + . " or Zend_Config instance."); + } + foreach ($options as $name => $value) { + $this->setOption($name, $value); + } + $this->_loggerSanity(); + } + + /** + * Set options using an instance of type Zend_Config + * + * @param Zend_Config $config + * @return Zend_Cache_Core + */ + public function setConfig(Zend_Config $config) + { + $options = $config->toArray(); + foreach ($options as $name => $value) { + $this->setOption($name, $value); + } + return $this; + } + + /** + * Set the backend + * + * @param Zend_Cache_Backend $backendObject + * @throws Zend_Cache_Exception + * @return void + */ + public function setBackend(Zend_Cache_Backend $backendObject) + { + $this->_backend= $backendObject; + // some options (listed in $_directivesList) have to be given + // to the backend too (even if they are not "backend specific") + $directives = array(); + foreach (Zend_Cache_Core::$_directivesList as $directive) { + $directives[$directive] = $this->_options[$directive]; + } + $this->_backend->setDirectives($directives); + if (in_array('Zend_Cache_Backend_ExtendedInterface', class_implements($this->_backend))) { + $this->_extendedBackend = true; + $this->_backendCapabilities = $this->_backend->getCapabilities(); + } + + } + + /** + * Returns the backend + * + * @return Zend_Cache_Backend backend object + */ + public function getBackend() + { + return $this->_backend; + } + + /** + * Public frontend to set an option + * + * There is an additional validation (relatively to the protected _setOption method) + * + * @param string $name Name of the option + * @param mixed $value Value of the option + * @throws Zend_Cache_Exception + * @return void + */ + public function setOption($name, $value) + { + if (!is_string($name)) { + Zend_Cache::throwException("Incorrect option name!"); + } + $name = strtolower($name); + if (array_key_exists($name, $this->_options)) { + // This is a Core option + $this->_setOption($name, $value); + return; + } + if (array_key_exists($name, $this->_specificOptions)) { + // This a specic option of this frontend + $this->_specificOptions[$name] = $value; + return; + } + } + + /** + * Public frontend to get an option value + * + * @param string $name Name of the option + * @throws Zend_Cache_Exception + * @return mixed option value + */ + public function getOption($name) + { + $name = strtolower($name); + + if (array_key_exists($name, $this->_options)) { + // This is a Core option + return $this->_options[$name]; + } + + if (array_key_exists($name, $this->_specificOptions)) { + // This a specic option of this frontend + return $this->_specificOptions[$name]; + } + + Zend_Cache::throwException("Incorrect option name : $name"); + } + + /** + * Set an option + * + * @param string $name Name of the option + * @param mixed $value Value of the option + * @throws Zend_Cache_Exception + * @return void + */ + private function _setOption($name, $value) + { + if (!is_string($name) || !array_key_exists($name, $this->_options)) { + Zend_Cache::throwException("Incorrect option name : $name"); + } + if ($name == 'lifetime' && empty($value)) { + $value = null; + } + $this->_options[$name] = $value; + } + + /** + * Force a new lifetime + * + * The new value is set for the core/frontend but for the backend too (directive) + * + * @param int $newLifetime New lifetime (in seconds) + * @return void + */ + public function setLifetime($newLifetime) + { + $this->_options['lifetime'] = $newLifetime; + $this->_backend->setDirectives(array( + 'lifetime' => $newLifetime + )); + } + + /** + * Test if a cache is available for the given id and (if yes) return it (false else) + * + * @param string $id Cache id + * @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested + * @param boolean $doNotUnserialize Do not serialize (even if automatic_serialization is true) => for internal use + * @return mixed|false Cached datas + */ + public function load($id, $doNotTestCacheValidity = false, $doNotUnserialize = false) + { + if (!$this->_options['caching']) { + return false; + } + $id = $this->_id($id); // cache id may need prefix + $this->_lastId = $id; + $this->_validateIdOrTag($id); + + $this->_log("Zend_Cache_Core: load item '{$id}'", 7); + $data = $this->_backend->load($id, $doNotTestCacheValidity); + if ($data===false) { + // no cache available + return false; + } + if ((!$doNotUnserialize) && $this->_options['automatic_serialization']) { + // we need to unserialize before sending the result + return unserialize($data); + } + return $data; + } + + /** + * Test if a cache is available for the given id + * + * @param string $id Cache id + * @return int|false Last modified time of cache entry if it is available, false otherwise + */ + public function test($id) + { + if (!$this->_options['caching']) { + return false; + } + $id = $this->_id($id); // cache id may need prefix + $this->_validateIdOrTag($id); + $this->_lastId = $id; + + $this->_log("Zend_Cache_Core: test item '{$id}'", 7); + return $this->_backend->test($id); + } + + /** + * Save some data in a cache + * + * @param mixed $data Data to put in cache (can be another type than string if automatic_serialization is on) + * @param string $id Cache id (if not set, the last cache id will be used) + * @param array $tags Cache tags + * @param int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime) + * @param int $priority integer between 0 (very low priority) and 10 (maximum priority) used by some particular backends + * @throws Zend_Cache_Exception + * @return boolean True if no problem + */ + public function save($data, $id = null, $tags = array(), $specificLifetime = false, $priority = 8) + { + if (!$this->_options['caching']) { + return true; + } + if ($id === null) { + $id = $this->_lastId; + } else { + $id = $this->_id($id); + } + $this->_validateIdOrTag($id); + $this->_validateTagsArray($tags); + if ($this->_options['automatic_serialization']) { + // we need to serialize datas before storing them + $data = serialize($data); + } else { + if (!is_string($data)) { + Zend_Cache::throwException("Datas must be string or set automatic_serialization = true"); + } + } + + // automatic cleaning + if ($this->_options['automatic_cleaning_factor'] > 0) { + $rand = rand(1, $this->_options['automatic_cleaning_factor']); + if ($rand==1) { + // new way || deprecated way + if ($this->_extendedBackend || method_exists($this->_backend, 'isAutomaticCleaningAvailable')) { + $this->_log("Zend_Cache_Core::save(): automatic cleaning running", 7); + $this->clean(Zend_Cache::CLEANING_MODE_OLD); + } else { + $this->_log("Zend_Cache_Core::save(): automatic cleaning is not available/necessary with current backend", 4); + } + } + } + + $this->_log("Zend_Cache_Core: save item '{$id}'", 7); + if ($this->_options['ignore_user_abort']) { + $abort = ignore_user_abort(true); + } + if (($this->_extendedBackend) && ($this->_backendCapabilities['priority'])) { + $result = $this->_backend->save($data, $id, $tags, $specificLifetime, $priority); + } else { + $result = $this->_backend->save($data, $id, $tags, $specificLifetime); + } + if ($this->_options['ignore_user_abort']) { + ignore_user_abort($abort); + } + + if (!$result) { + // maybe the cache is corrupted, so we remove it ! + $this->_log("Zend_Cache_Core::save(): failed to save item '{$id}' -> removing it", 4); + $this->_backend->remove($id); + return false; + } + + if ($this->_options['write_control']) { + $data2 = $this->_backend->load($id, true); + if ($data!=$data2) { + $this->_log("Zend_Cache_Core::save(): write control of item '{$id}' failed -> removing it", 4); + $this->_backend->remove($id); + return false; + } + } + + return true; + } + + /** + * Remove a cache + * + * @param string $id Cache id to remove + * @return boolean True if ok + */ + public function remove($id) + { + if (!$this->_options['caching']) { + return true; + } + $id = $this->_id($id); // cache id may need prefix + $this->_validateIdOrTag($id); + + $this->_log("Zend_Cache_Core: remove item '{$id}'", 7); + return $this->_backend->remove($id); + } + + /** + * Clean cache entries + * + * Available modes are : + * 'all' (default) => remove all cache entries ($tags is not used) + * 'old' => remove too old cache entries ($tags is not used) + * 'matchingTag' => remove cache entries matching all given tags + * ($tags can be an array of strings or a single string) + * 'notMatchingTag' => remove cache entries not matching one of the given tags + * ($tags can be an array of strings or a single string) + * 'matchingAnyTag' => remove cache entries matching any given tags + * ($tags can be an array of strings or a single string) + * + * @param string $mode + * @param array|string $tags + * @throws Zend_Cache_Exception + * @return boolean True if ok + */ + public function clean($mode = 'all', $tags = array()) + { + if (!$this->_options['caching']) { + return true; + } + if (!in_array($mode, array(Zend_Cache::CLEANING_MODE_ALL, + Zend_Cache::CLEANING_MODE_OLD, + Zend_Cache::CLEANING_MODE_MATCHING_TAG, + Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG, + Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG))) { + Zend_Cache::throwException('Invalid cleaning mode'); + } + $this->_validateTagsArray($tags); + + return $this->_backend->clean($mode, $tags); + } + + /** + * Return an array of stored cache ids which match given tags + * + * In case of multiple tags, a logical AND is made between tags + * + * @param array $tags array of tags + * @return array array of matching cache ids (string) + */ + public function getIdsMatchingTags($tags = array()) + { + if (!$this->_extendedBackend) { + Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF); + } + if (!($this->_backendCapabilities['tags'])) { + Zend_Cache::throwException(self::BACKEND_NOT_SUPPORTS_TAG); + } + + $ids = $this->_backend->getIdsMatchingTags($tags); + + // we need to remove cache_id_prefix from ids (see #ZF-6178, #ZF-7600) + if (isset($this->_options['cache_id_prefix']) && $this->_options['cache_id_prefix'] !== '') { + $prefix = & $this->_options['cache_id_prefix']; + $prefixLen = strlen($prefix); + foreach ($ids as &$id) { + if (strpos($id, $prefix) === 0) { + $id = substr($id, $prefixLen); + } + } + } + + return $ids; + } + + /** + * Return an array of stored cache ids which don't match given tags + * + * In case of multiple tags, a logical OR is made between tags + * + * @param array $tags array of tags + * @return array array of not matching cache ids (string) + */ + public function getIdsNotMatchingTags($tags = array()) + { + if (!$this->_extendedBackend) { + Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF); + } + if (!($this->_backendCapabilities['tags'])) { + Zend_Cache::throwException(self::BACKEND_NOT_SUPPORTS_TAG); + } + + $ids = $this->_backend->getIdsNotMatchingTags($tags); + + // we need to remove cache_id_prefix from ids (see #ZF-6178, #ZF-7600) + if (isset($this->_options['cache_id_prefix']) && $this->_options['cache_id_prefix'] !== '') { + $prefix = & $this->_options['cache_id_prefix']; + $prefixLen = strlen($prefix); + foreach ($ids as &$id) { + if (strpos($id, $prefix) === 0) { + $id = substr($id, $prefixLen); + } + } + } + + return $ids; + } + + /** + * Return an array of stored cache ids which match any given tags + * + * In case of multiple tags, a logical OR is made between tags + * + * @param array $tags array of tags + * @return array array of matching any cache ids (string) + */ + public function getIdsMatchingAnyTags($tags = array()) + { + if (!$this->_extendedBackend) { + Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF); + } + if (!($this->_backendCapabilities['tags'])) { + Zend_Cache::throwException(self::BACKEND_NOT_SUPPORTS_TAG); + } + + $ids = $this->_backend->getIdsMatchingAnyTags($tags); + + // we need to remove cache_id_prefix from ids (see #ZF-6178, #ZF-7600) + if (isset($this->_options['cache_id_prefix']) && $this->_options['cache_id_prefix'] !== '') { + $prefix = & $this->_options['cache_id_prefix']; + $prefixLen = strlen($prefix); + foreach ($ids as &$id) { + if (strpos($id, $prefix) === 0) { + $id = substr($id, $prefixLen); + } + } + } + + return $ids; + } + + /** + * Return an array of stored cache ids + * + * @return array array of stored cache ids (string) + */ + public function getIds() + { + if (!$this->_extendedBackend) { + Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF); + } + + $ids = $this->_backend->getIds(); + + // we need to remove cache_id_prefix from ids (see #ZF-6178, #ZF-7600) + if (isset($this->_options['cache_id_prefix']) && $this->_options['cache_id_prefix'] !== '') { + $prefix = & $this->_options['cache_id_prefix']; + $prefixLen = strlen($prefix); + foreach ($ids as &$id) { + if (strpos($id, $prefix) === 0) { + $id = substr($id, $prefixLen); + } + } + } + + return $ids; + } + + /** + * Return an array of stored tags + * + * @return array array of stored tags (string) + */ + public function getTags() + { + if (!$this->_extendedBackend) { + Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF); + } + if (!($this->_backendCapabilities['tags'])) { + Zend_Cache::throwException(self::BACKEND_NOT_SUPPORTS_TAG); + } + return $this->_backend->getTags(); + } + + /** + * Return the filling percentage of the backend storage + * + * @return int integer between 0 and 100 + */ + public function getFillingPercentage() + { + if (!$this->_extendedBackend) { + Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF); + } + return $this->_backend->getFillingPercentage(); + } + + /** + * Return an array of metadatas for the given cache id + * + * The array will include these keys : + * - expire : the expire timestamp + * - tags : a string array of tags + * - mtime : timestamp of last modification time + * + * @param string $id cache id + * @return array array of metadatas (false if the cache id is not found) + */ + public function getMetadatas($id) + { + if (!$this->_extendedBackend) { + Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF); + } + $id = $this->_id($id); // cache id may need prefix + return $this->_backend->getMetadatas($id); + } + + /** + * Give (if possible) an extra lifetime to the given cache id + * + * @param string $id cache id + * @param int $extraLifetime + * @return boolean true if ok + */ + public function touch($id, $extraLifetime) + { + if (!$this->_extendedBackend) { + Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF); + } + $id = $this->_id($id); // cache id may need prefix + + $this->_log("Zend_Cache_Core: touch item '{$id}'", 7); + return $this->_backend->touch($id, $extraLifetime); + } + + /** + * Validate a cache id or a tag (security, reliable filenames, reserved prefixes...) + * + * Throw an exception if a problem is found + * + * @param string $string Cache id or tag + * @throws Zend_Cache_Exception + * @return void + */ + protected function _validateIdOrTag($string) + { + if (!is_string($string)) { + Zend_Cache::throwException('Invalid id or tag : must be a string'); + } + if (substr($string, 0, 9) == 'internal-') { + Zend_Cache::throwException('"internal-*" ids or tags are reserved'); + } + if (!preg_match('~^[a-zA-Z0-9_]+$~D', $string)) { + Zend_Cache::throwException("Invalid id or tag '$string' : must use only [a-zA-Z0-9_]"); + } + } + + /** + * Validate a tags array (security, reliable filenames, reserved prefixes...) + * + * Throw an exception if a problem is found + * + * @param array $tags Array of tags + * @throws Zend_Cache_Exception + * @return void + */ + protected function _validateTagsArray($tags) + { + if (!is_array($tags)) { + Zend_Cache::throwException('Invalid tags array : must be an array'); + } + foreach($tags as $tag) { + $this->_validateIdOrTag($tag); + } + reset($tags); + } + + /** + * Make sure if we enable logging that the Zend_Log class + * is available. + * Create a default log object if none is set. + * + * @throws Zend_Cache_Exception + * @return void + */ + protected function _loggerSanity() + { + if (!isset($this->_options['logging']) || !$this->_options['logging']) { + return; + } + + if (isset($this->_options['logger']) && $this->_options['logger'] instanceof Zend_Log) { + return; + } + + // Create a default logger to the standard output stream + require_once 'Zend/Log.php'; + require_once 'Zend/Log/Writer/Stream.php'; + require_once 'Zend/Log/Filter/Priority.php'; + $logger = new Zend_Log(new Zend_Log_Writer_Stream('php://output')); + $logger->addFilter(new Zend_Log_Filter_Priority(Zend_Log::WARN, '<=')); + $this->_options['logger'] = $logger; + } + + /** + * Log a message at the WARN (4) priority. + * + * @param string $message + * @throws Zend_Cache_Exception + * @return void + */ + protected function _log($message, $priority = 4) + { + if (!$this->_options['logging']) { + return; + } + if (!(isset($this->_options['logger']) || $this->_options['logger'] instanceof Zend_Log)) { + Zend_Cache::throwException('Logging is enabled but logger is not set'); + } + $logger = $this->_options['logger']; + $logger->log($message, $priority); + } + + /** + * Make and return a cache id + * + * Checks 'cache_id_prefix' and returns new id with prefix or simply the id if null + * + * @param string $id Cache id + * @return string Cache id (with or without prefix) + */ + protected function _id($id) + { + if (($id !== null) && isset($this->_options['cache_id_prefix'])) { + return $this->_options['cache_id_prefix'] . $id; // return with prefix + } + return $id; // no prefix, just return the $id passed + } + +} diff --git a/lib/zend/Zend/Cache/Exception.php b/lib/zend/Zend/Cache/Exception.php new file mode 100644 index 00000000000..ee53b20671b --- /dev/null +++ b/lib/zend/Zend/Cache/Exception.php @@ -0,0 +1,32 @@ +_tags = $tags; + $this->_extension = $extension; + ob_start(array($this, '_flush')); + ob_implicit_flush(false); + $this->_idStack[] = $id; + return false; + } + + /** + * callback for output buffering + * (shouldn't really be called manually) + * + * @param string $data Buffered output + * @return string Data to send to browser + */ + public function _flush($data) + { + $id = array_pop($this->_idStack); + if ($id === null) { + Zend_Cache::throwException('use of _flush() without a start()'); + } + if ($this->_extension) { + $this->save(serialize(array($data, $this->_extension)), $id, $this->_tags); + } else { + $this->save($data, $id, $this->_tags); + } + return $data; + } +} diff --git a/lib/zend/Zend/Cache/Frontend/Class.php b/lib/zend/Zend/Cache/Frontend/Class.php new file mode 100644 index 00000000000..4740402ac73 --- /dev/null +++ b/lib/zend/Zend/Cache/Frontend/Class.php @@ -0,0 +1,275 @@ + (mixed) cached_entity : + * - if set to a class name, we will cache an abstract class and will use only static calls + * - if set to an object, we will cache this object methods + * + * ====> (boolean) cache_by_default : + * - if true, method calls will be cached by default + * + * ====> (array) cached_methods : + * - an array of method names which will be cached (even if cache_by_default = false) + * + * ====> (array) non_cached_methods : + * - an array of method names which won't be cached (even if cache_by_default = true) + * + * @var array available options + */ + protected $_specificOptions = array( + 'cached_entity' => null, + 'cache_by_default' => true, + 'cached_methods' => array(), + 'non_cached_methods' => array() + ); + + /** + * Tags array + * + * @var array + */ + protected $_tags = array(); + + /** + * SpecificLifetime value + * + * false => no specific life time + * + * @var bool|int + */ + protected $_specificLifetime = false; + + /** + * The cached object or the name of the cached abstract class + * + * @var mixed + */ + protected $_cachedEntity = null; + + /** + * The class name of the cached object or cached abstract class + * + * Used to differentiate between different classes with the same method calls. + * + * @var string + */ + protected $_cachedEntityLabel = ''; + + /** + * Priority (used by some particular backends) + * + * @var int + */ + protected $_priority = 8; + + /** + * Constructor + * + * @param array $options Associative array of options + * @throws Zend_Cache_Exception + */ + public function __construct(array $options = array()) + { + foreach ($options as $name => $value) { + $this->setOption($name, $value); + } + if ($this->_specificOptions['cached_entity'] === null) { + Zend_Cache::throwException('cached_entity must be set !'); + } + $this->setCachedEntity($this->_specificOptions['cached_entity']); + $this->setOption('automatic_serialization', true); + } + + /** + * Set a specific life time + * + * @param bool|int $specificLifetime + * @return void + */ + public function setSpecificLifetime($specificLifetime = false) + { + $this->_specificLifetime = $specificLifetime; + } + + /** + * Set the priority (used by some particular backends) + * + * @param int $priority integer between 0 (very low priority) and 10 (maximum priority) + */ + public function setPriority($priority) + { + $this->_priority = $priority; + } + + /** + * Public frontend to set an option + * + * Just a wrapper to get a specific behaviour for cached_entity + * + * @param string $name Name of the option + * @param mixed $value Value of the option + * @throws Zend_Cache_Exception + * @return void + */ + public function setOption($name, $value) + { + if ($name == 'cached_entity') { + $this->setCachedEntity($value); + } else { + parent::setOption($name, $value); + } + } + + /** + * Specific method to set the cachedEntity + * + * if set to a class name, we will cache an abstract class and will use only static calls + * if set to an object, we will cache this object methods + * + * @param mixed $cachedEntity + */ + public function setCachedEntity($cachedEntity) + { + if (!is_string($cachedEntity) && !is_object($cachedEntity)) { + Zend_Cache::throwException( + 'cached_entity must be an object or a class name' + ); + } + + $this->_cachedEntity = $cachedEntity; + $this->_specificOptions['cached_entity'] = $cachedEntity; + + if (is_string($this->_cachedEntity)) { + $this->_cachedEntityLabel = $this->_cachedEntity; + } else { + $ro = new ReflectionObject($this->_cachedEntity); + $this->_cachedEntityLabel = $ro->getName(); + } + } + + /** + * Set the cache array + * + * @param array $tags + * @return void + */ + public function setTagsArray($tags = array()) + { + $this->_tags = $tags; + } + + /** + * Main method : call the specified method or get the result from cache + * + * @param string $name Method name + * @param array $parameters Method parameters + * @return mixed Result + * @throws Exception + */ + public function __call($name, $parameters) + { + $callback = array($this->_cachedEntity, $name); + + if (!is_callable($callback, false)) { + Zend_Cache::throwException('Invalid callback'); + } + + $cacheBool1 = $this->_specificOptions['cache_by_default']; + $cacheBool2 = in_array($name, $this->_specificOptions['cached_methods']); + $cacheBool3 = in_array($name, $this->_specificOptions['non_cached_methods']); + $cache = (($cacheBool1 || $cacheBool2) && (!$cacheBool3)); + + if (!$cache) { + // We do not have not cache + return call_user_func_array($callback, $parameters); + } + + $id = $this->makeId($name, $parameters); + if (($rs = $this->load($id)) && (array_key_exists(0, $rs)) + && (array_key_exists(1, $rs)) + ) { + // A cache is available + $output = $rs[0]; + $return = $rs[1]; + } else { + // A cache is not available (or not valid for this frontend) + ob_start(); + ob_implicit_flush(false); + + try { + $return = call_user_func_array($callback, $parameters); + $output = ob_get_clean(); + $data = array($output, $return); + + $this->save( + $data, $id, $this->_tags, $this->_specificLifetime, + $this->_priority + ); + } catch (Exception $e) { + ob_end_clean(); + throw $e; + } + } + + echo $output; + return $return; + } + + /** + * ZF-9970 + * + * @deprecated + */ + private function _makeId($name, $args) + { + return $this->makeId($name, $args); + } + + /** + * Make a cache id from the method name and parameters + * + * @param string $name Method name + * @param array $args Method parameters + * @return string Cache id + */ + public function makeId($name, array $args = array()) + { + return md5($this->_cachedEntityLabel . '__' . $name . '__' . serialize($args)); + } +} diff --git a/lib/zend/Zend/Cache/Frontend/File.php b/lib/zend/Zend/Cache/Frontend/File.php new file mode 100644 index 00000000000..e5017c631ca --- /dev/null +++ b/lib/zend/Zend/Cache/Frontend/File.php @@ -0,0 +1,222 @@ + (string) master_file : + * - a complete path of the master file + * - deprecated (see master_files) + * + * ====> (array) master_files : + * - an array of complete path of master files + * - this option has to be set ! + * + * ====> (string) master_files_mode : + * - Zend_Cache_Frontend_File::MODE_AND or Zend_Cache_Frontend_File::MODE_OR + * - if MODE_AND, then all master files have to be touched to get a cache invalidation + * - if MODE_OR (default), then a single touched master file is enough to get a cache invalidation + * + * ====> (boolean) ignore_missing_master_files + * - if set to true, missing master files are ignored silently + * - if set to false (default), an exception is thrown if there is a missing master file + * @var array available options + */ + protected $_specificOptions = array( + 'master_file' => null, + 'master_files' => null, + 'master_files_mode' => 'OR', + 'ignore_missing_master_files' => false + ); + + /** + * Master file mtimes + * + * Array of int + * + * @var array + */ + private $_masterFile_mtimes = null; + + /** + * Constructor + * + * @param array $options Associative array of options + * @throws Zend_Cache_Exception + * @return void + */ + public function __construct(array $options = array()) + { + foreach ($options as $name => $value) { + $this->setOption($name, $value); + } + if (!isset($this->_specificOptions['master_files'])) { + Zend_Cache::throwException('master_files option must be set'); + } + } + + /** + * Change the master_files option + * + * @param array $masterFiles the complete paths and name of the master files + */ + public function setMasterFiles(array $masterFiles) + { + $this->_specificOptions['master_file'] = null; // to keep a compatibility + $this->_specificOptions['master_files'] = null; + $this->_masterFile_mtimes = array(); + + clearstatcache(); + $i = 0; + foreach ($masterFiles as $masterFile) { + if (file_exists($masterFile)) { + $mtime = filemtime($masterFile); + } else { + $mtime = false; + } + + if (!$this->_specificOptions['ignore_missing_master_files'] && !$mtime) { + Zend_Cache::throwException('Unable to read master_file : ' . $masterFile); + } + + $this->_masterFile_mtimes[$i] = $mtime; + $this->_specificOptions['master_files'][$i] = $masterFile; + if ($i === 0) { // to keep a compatibility + $this->_specificOptions['master_file'] = $masterFile; + } + + $i++; + } + } + + /** + * Change the master_file option + * + * To keep the compatibility + * + * @deprecated + * @param string $masterFile the complete path and name of the master file + */ + public function setMasterFile($masterFile) + { + $this->setMasterFiles(array($masterFile)); + } + + /** + * Public frontend to set an option + * + * Just a wrapper to get a specific behaviour for master_file + * + * @param string $name Name of the option + * @param mixed $value Value of the option + * @throws Zend_Cache_Exception + * @return void + */ + public function setOption($name, $value) + { + if ($name == 'master_file') { + $this->setMasterFile($value); + } else if ($name == 'master_files') { + $this->setMasterFiles($value); + } else { + parent::setOption($name, $value); + } + } + + /** + * Test if a cache is available for the given id and (if yes) return it (false else) + * + * @param string $id Cache id + * @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested + * @param boolean $doNotUnserialize Do not serialize (even if automatic_serialization is true) => for internal use + * @return mixed|false Cached datas + */ + public function load($id, $doNotTestCacheValidity = false, $doNotUnserialize = false) + { + if (!$doNotTestCacheValidity) { + if ($this->test($id)) { + return parent::load($id, true, $doNotUnserialize); + } + return false; + } + return parent::load($id, true, $doNotUnserialize); + } + + /** + * Test if a cache is available for the given id + * + * @param string $id Cache id + * @return int|false Last modified time of cache entry if it is available, false otherwise + */ + public function test($id) + { + $lastModified = parent::test($id); + if ($lastModified) { + if ($this->_specificOptions['master_files_mode'] == self::MODE_AND) { + // MODE_AND + foreach($this->_masterFile_mtimes as $masterFileMTime) { + if ($masterFileMTime) { + if ($lastModified > $masterFileMTime) { + return $lastModified; + } + } + } + } else { + // MODE_OR + $res = true; + foreach($this->_masterFile_mtimes as $masterFileMTime) { + if ($masterFileMTime) { + if ($lastModified <= $masterFileMTime) { + return false; + } + } + } + return $lastModified; + } + } + return false; + } + +} + diff --git a/lib/zend/Zend/Cache/Frontend/Function.php b/lib/zend/Zend/Cache/Frontend/Function.php new file mode 100644 index 00000000000..8af521bda69 --- /dev/null +++ b/lib/zend/Zend/Cache/Frontend/Function.php @@ -0,0 +1,179 @@ + (boolean) cache_by_default : + * - if true, function calls will be cached by default + * + * ====> (array) cached_functions : + * - an array of function names which will be cached (even if cache_by_default = false) + * + * ====> (array) non_cached_functions : + * - an array of function names which won't be cached (even if cache_by_default = true) + * + * @var array options + */ + protected $_specificOptions = array( + 'cache_by_default' => true, + 'cached_functions' => array(), + 'non_cached_functions' => array() + ); + + /** + * Constructor + * + * @param array $options Associative array of options + * @return void + */ + public function __construct(array $options = array()) + { + foreach ($options as $name => $value) { + $this->setOption($name, $value); + } + $this->setOption('automatic_serialization', true); + } + + /** + * Main method : call the specified function or get the result from cache + * + * @param callback $callback A valid callback + * @param array $parameters Function parameters + * @param array $tags Cache tags + * @param int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime) + * @param int $priority integer between 0 (very low priority) and 10 (maximum priority) used by some particular backends + * @return mixed Result + */ + public function call($callback, array $parameters = array(), $tags = array(), $specificLifetime = false, $priority = 8) + { + if (!is_callable($callback, true, $name)) { + Zend_Cache::throwException('Invalid callback'); + } + + $cacheBool1 = $this->_specificOptions['cache_by_default']; + $cacheBool2 = in_array($name, $this->_specificOptions['cached_functions']); + $cacheBool3 = in_array($name, $this->_specificOptions['non_cached_functions']); + $cache = (($cacheBool1 || $cacheBool2) && (!$cacheBool3)); + if (!$cache) { + // Caching of this callback is disabled + return call_user_func_array($callback, $parameters); + } + + $id = $this->_makeId($callback, $parameters); + if ( ($rs = $this->load($id)) && isset($rs[0], $rs[1])) { + // A cache is available + $output = $rs[0]; + $return = $rs[1]; + } else { + // A cache is not available (or not valid for this frontend) + ob_start(); + ob_implicit_flush(false); + $return = call_user_func_array($callback, $parameters); + $output = ob_get_clean(); + $data = array($output, $return); + $this->save($data, $id, $tags, $specificLifetime, $priority); + } + + echo $output; + return $return; + } + + /** + * ZF-9970 + * + * @deprecated + */ + private function _makeId($callback, array $args) + { + return $this->makeId($callback, $args); + } + + /** + * Make a cache id from the function name and parameters + * + * @param callback $callback A valid callback + * @param array $args Function parameters + * @throws Zend_Cache_Exception + * @return string Cache id + */ + public function makeId($callback, array $args = array()) + { + if (!is_callable($callback, true, $name)) { + Zend_Cache::throwException('Invalid callback'); + } + + // functions, methods and classnames are case-insensitive + $name = strtolower($name); + + // generate a unique id for object callbacks + if (is_object($callback)) { // Closures & __invoke + $object = $callback; + } elseif (isset($callback[0])) { // array($object, 'method') + $object = $callback[0]; + } + if (isset($object)) { + try { + $tmp = @serialize($callback); + } catch (Exception $e) { + Zend_Cache::throwException($e->getMessage()); + } + if (!$tmp) { + $lastErr = error_get_last(); + Zend_Cache::throwException("Can't serialize callback object to generate id: {$lastErr['message']}"); + } + $name.= '__' . $tmp; + } + + // generate a unique id for arguments + $argsStr = ''; + if ($args) { + try { + $argsStr = @serialize(array_values($args)); + } catch (Exception $e) { + Zend_Cache::throwException($e->getMessage()); + } + if (!$argsStr) { + $lastErr = error_get_last(); + throw Zend_Cache::throwException("Can't serialize arguments to generate id: {$lastErr['message']}"); + } + } + + return md5($name . $argsStr); + } + +} diff --git a/lib/zend/Zend/Cache/Frontend/Output.php b/lib/zend/Zend/Cache/Frontend/Output.php new file mode 100644 index 00000000000..99a8a64c9d8 --- /dev/null +++ b/lib/zend/Zend/Cache/Frontend/Output.php @@ -0,0 +1,105 @@ +_idStack = array(); + } + + /** + * Start the cache + * + * @param string $id Cache id + * @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested + * @param boolean $echoData If set to true, datas are sent to the browser if the cache is hit (simply returned else) + * @return mixed True if the cache is hit (false else) with $echoData=true (default) ; string else (datas) + */ + public function start($id, $doNotTestCacheValidity = false, $echoData = true) + { + $data = $this->load($id, $doNotTestCacheValidity); + if ($data !== false) { + if ( $echoData ) { + echo($data); + return true; + } else { + return $data; + } + } + ob_start(); + ob_implicit_flush(false); + $this->_idStack[] = $id; + return false; + } + + /** + * Stop the cache + * + * @param array $tags Tags array + * @param int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime) + * @param string $forcedDatas If not null, force written datas with this + * @param boolean $echoData If set to true, datas are sent to the browser + * @param int $priority integer between 0 (very low priority) and 10 (maximum priority) used by some particular backends + * @return void + */ + public function end($tags = array(), $specificLifetime = false, $forcedDatas = null, $echoData = true, $priority = 8) + { + if ($forcedDatas === null) { + $data = ob_get_clean(); + } else { + $data =& $forcedDatas; + } + $id = array_pop($this->_idStack); + if ($id === null) { + Zend_Cache::throwException('use of end() without a start()'); + } + $this->save($data, $id, $tags, $specificLifetime, $priority); + if ($echoData) { + echo($data); + } + } + +} diff --git a/lib/zend/Zend/Cache/Frontend/Page.php b/lib/zend/Zend/Cache/Frontend/Page.php new file mode 100644 index 00000000000..cc253d559c8 --- /dev/null +++ b/lib/zend/Zend/Cache/Frontend/Page.php @@ -0,0 +1,404 @@ + (boolean) http_conditional : + * - if true, http conditional mode is on + * WARNING : http_conditional OPTION IS NOT IMPLEMENTED FOR THE MOMENT (TODO) + * + * ====> (boolean) debug_header : + * - if true, a debug text is added before each cached pages + * + * ====> (boolean) content_type_memorization : + * - deprecated => use memorize_headers instead + * - if the Content-Type header is sent after the cache was started, the + * corresponding value can be memorized and replayed when the cache is hit + * (if false (default), the frontend doesn't take care of Content-Type header) + * + * ====> (array) memorize_headers : + * - an array of strings corresponding to some HTTP headers name. Listed headers + * will be stored with cache datas and "replayed" when the cache is hit + * + * ====> (array) default_options : + * - an associative array of default options : + * - (boolean) cache : cache is on by default if true + * - (boolean) cacheWithXXXVariables (XXXX = 'Get', 'Post', 'Session', 'Files' or 'Cookie') : + * if true, cache is still on even if there are some variables in this superglobal array + * if false, cache is off if there are some variables in this superglobal array + * - (boolean) makeIdWithXXXVariables (XXXX = 'Get', 'Post', 'Session', 'Files' or 'Cookie') : + * if true, we have to use the content of this superglobal array to make a cache id + * if false, the cache id won't be dependent of the content of this superglobal array + * - (int) specific_lifetime : cache specific lifetime + * (false => global lifetime is used, null => infinite lifetime, + * integer => this lifetime is used), this "lifetime" is probably only + * usefull when used with "regexps" array + * - (array) tags : array of tags (strings) + * - (int) priority : integer between 0 (very low priority) and 10 (maximum priority) used by + * some particular backends + * + * ====> (array) regexps : + * - an associative array to set options only for some REQUEST_URI + * - keys are (pcre) regexps + * - values are associative array with specific options to set if the regexp matchs on $_SERVER['REQUEST_URI'] + * (see default_options for the list of available options) + * - if several regexps match the $_SERVER['REQUEST_URI'], only the last one will be used + * + * @var array options + */ + protected $_specificOptions = array( + 'http_conditional' => false, + 'debug_header' => false, + 'content_type_memorization' => false, + 'memorize_headers' => array(), + 'default_options' => array( + 'cache_with_get_variables' => false, + 'cache_with_post_variables' => false, + 'cache_with_session_variables' => false, + 'cache_with_files_variables' => false, + 'cache_with_cookie_variables' => false, + 'make_id_with_get_variables' => true, + 'make_id_with_post_variables' => true, + 'make_id_with_session_variables' => true, + 'make_id_with_files_variables' => true, + 'make_id_with_cookie_variables' => true, + 'cache' => true, + 'specific_lifetime' => false, + 'tags' => array(), + 'priority' => null + ), + 'regexps' => array() + ); + + /** + * Internal array to store some options + * + * @var array associative array of options + */ + protected $_activeOptions = array(); + + /** + * If true, the page won't be cached + * + * @var boolean + */ + protected $_cancel = false; + + /** + * Constructor + * + * @param array $options Associative array of options + * @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested + * @throws Zend_Cache_Exception + * @return void + */ + public function __construct(array $options = array()) + { + foreach ($options as $name => $value) { + $name = strtolower($name); + switch ($name) { + case 'regexps': + $this->_setRegexps($value); + break; + case 'default_options': + $this->_setDefaultOptions($value); + break; + case 'content_type_memorization': + $this->_setContentTypeMemorization($value); + break; + default: + $this->setOption($name, $value); + } + } + if (isset($this->_specificOptions['http_conditional'])) { + if ($this->_specificOptions['http_conditional']) { + Zend_Cache::throwException('http_conditional is not implemented for the moment !'); + } + } + $this->setOption('automatic_serialization', true); + } + + /** + * Specific setter for the 'default_options' option (with some additional tests) + * + * @param array $options Associative array + * @throws Zend_Cache_Exception + * @return void + */ + protected function _setDefaultOptions($options) + { + if (!is_array($options)) { + Zend_Cache::throwException('default_options must be an array !'); + } + foreach ($options as $key=>$value) { + if (!is_string($key)) { + Zend_Cache::throwException("invalid option [$key] !"); + } + $key = strtolower($key); + if (isset($this->_specificOptions['default_options'][$key])) { + $this->_specificOptions['default_options'][$key] = $value; + } + } + } + + /** + * Set the deprecated contentTypeMemorization option + * + * @param boolean $value value + * @return void + * @deprecated + */ + protected function _setContentTypeMemorization($value) + { + $found = null; + foreach ($this->_specificOptions['memorize_headers'] as $key => $value) { + if (strtolower($value) == 'content-type') { + $found = $key; + } + } + if ($value) { + if (!$found) { + $this->_specificOptions['memorize_headers'][] = 'Content-Type'; + } + } else { + if ($found) { + unset($this->_specificOptions['memorize_headers'][$found]); + } + } + } + + /** + * Specific setter for the 'regexps' option (with some additional tests) + * + * @param array $options Associative array + * @throws Zend_Cache_Exception + * @return void + */ + protected function _setRegexps($regexps) + { + if (!is_array($regexps)) { + Zend_Cache::throwException('regexps option must be an array !'); + } + foreach ($regexps as $regexp=>$conf) { + if (!is_array($conf)) { + Zend_Cache::throwException('regexps option must be an array of arrays !'); + } + $validKeys = array_keys($this->_specificOptions['default_options']); + foreach ($conf as $key=>$value) { + if (!is_string($key)) { + Zend_Cache::throwException("unknown option [$key] !"); + } + $key = strtolower($key); + if (!in_array($key, $validKeys)) { + unset($regexps[$regexp][$key]); + } + } + } + $this->setOption('regexps', $regexps); + } + + /** + * Start the cache + * + * @param string $id (optional) A cache id (if you set a value here, maybe you have to use Output frontend instead) + * @param boolean $doNotDie For unit testing only ! + * @return boolean True if the cache is hit (false else) + */ + public function start($id = false, $doNotDie = false) + { + $this->_cancel = false; + $lastMatchingRegexp = null; + if (isset($_SERVER['REQUEST_URI'])) { + foreach ($this->_specificOptions['regexps'] as $regexp => $conf) { + if (preg_match("`$regexp`", $_SERVER['REQUEST_URI'])) { + $lastMatchingRegexp = $regexp; + } + } + } + $this->_activeOptions = $this->_specificOptions['default_options']; + if ($lastMatchingRegexp !== null) { + $conf = $this->_specificOptions['regexps'][$lastMatchingRegexp]; + foreach ($conf as $key=>$value) { + $this->_activeOptions[$key] = $value; + } + } + if (!($this->_activeOptions['cache'])) { + return false; + } + if (!$id) { + $id = $this->_makeId(); + if (!$id) { + return false; + } + } + $array = $this->load($id); + if ($array !== false) { + $data = $array['data']; + $headers = $array['headers']; + if (!headers_sent()) { + foreach ($headers as $key=>$headerCouple) { + $name = $headerCouple[0]; + $value = $headerCouple[1]; + header("$name: $value"); + } + } + if ($this->_specificOptions['debug_header']) { + echo 'DEBUG HEADER : This is a cached page !'; + } + echo $data; + if ($doNotDie) { + return true; + } + die(); + } + ob_start(array($this, '_flush')); + ob_implicit_flush(false); + return false; + } + + /** + * Cancel the current caching process + */ + public function cancel() + { + $this->_cancel = true; + } + + /** + * callback for output buffering + * (shouldn't really be called manually) + * + * @param string $data Buffered output + * @return string Data to send to browser + */ + public function _flush($data) + { + if ($this->_cancel) { + return $data; + } + $contentType = null; + $storedHeaders = array(); + $headersList = headers_list(); + foreach($this->_specificOptions['memorize_headers'] as $key=>$headerName) { + foreach ($headersList as $headerSent) { + $tmp = explode(':', $headerSent); + $headerSentName = trim(array_shift($tmp)); + if (strtolower($headerName) == strtolower($headerSentName)) { + $headerSentValue = trim(implode(':', $tmp)); + $storedHeaders[] = array($headerSentName, $headerSentValue); + } + } + } + $array = array( + 'data' => $data, + 'headers' => $storedHeaders + ); + $this->save($array, null, $this->_activeOptions['tags'], $this->_activeOptions['specific_lifetime'], $this->_activeOptions['priority']); + return $data; + } + + /** + * Make an id depending on REQUEST_URI and superglobal arrays (depending on options) + * + * @return mixed|false a cache id (string), false if the cache should have not to be used + */ + protected function _makeId() + { + $tmp = $_SERVER['REQUEST_URI']; + $array = explode('?', $tmp, 2); + $tmp = $array[0]; + foreach (array('Get', 'Post', 'Session', 'Files', 'Cookie') as $arrayName) { + $tmp2 = $this->_makePartialId($arrayName, $this->_activeOptions['cache_with_' . strtolower($arrayName) . '_variables'], $this->_activeOptions['make_id_with_' . strtolower($arrayName) . '_variables']); + if ($tmp2===false) { + return false; + } + $tmp = $tmp . $tmp2; + } + return md5($tmp); + } + + /** + * Make a partial id depending on options + * + * @param string $arrayName Superglobal array name + * @param bool $bool1 If true, cache is still on even if there are some variables in the superglobal array + * @param bool $bool2 If true, we have to use the content of the superglobal array to make a partial id + * @return mixed|false Partial id (string) or false if the cache should have not to be used + */ + protected function _makePartialId($arrayName, $bool1, $bool2) + { + switch ($arrayName) { + case 'Get': + $var = $_GET; + break; + case 'Post': + $var = $_POST; + break; + case 'Session': + if (isset($_SESSION)) { + $var = $_SESSION; + } else { + $var = null; + } + break; + case 'Cookie': + if (isset($_COOKIE)) { + $var = $_COOKIE; + } else { + $var = null; + } + break; + case 'Files': + $var = $_FILES; + break; + default: + return false; + } + if ($bool1) { + if ($bool2) { + return serialize($var); + } + return ''; + } + if (count($var) > 0) { + return false; + } + return ''; + } + +} diff --git a/lib/zend/Zend/Cache/Manager.php b/lib/zend/Zend/Cache/Manager.php new file mode 100644 index 00000000000..330ea954e85 --- /dev/null +++ b/lib/zend/Zend/Cache/Manager.php @@ -0,0 +1,308 @@ + array( + 'frontend' => array( + 'name' => 'Core', + 'options' => array( + 'automatic_serialization' => true, + ), + ), + 'backend' => array( + 'name' => 'File', + 'options' => array( + // use system temp dir by default of file backend + // 'cache_dir' => '../cache', + ), + ), + ), + + // Static Page HTML Cache + 'page' => array( + 'frontend' => array( + 'name' => 'Capture', + 'options' => array( + 'ignore_user_abort' => true, + ), + ), + 'backend' => array( + 'name' => 'Static', + 'options' => array( + 'public_dir' => '../public', + ), + ), + ), + + // Tag Cache + 'pagetag' => array( + 'frontend' => array( + 'name' => 'Core', + 'options' => array( + 'automatic_serialization' => true, + 'lifetime' => null + ), + ), + 'backend' => array( + 'name' => 'File', + 'options' => array( + // use system temp dir by default of file backend + // 'cache_dir' => '../cache', + // use default umask of file backend + // 'cache_file_umask' => 0644 + ), + ), + ), + ); + + /** + * Set a new cache for the Cache Manager to contain + * + * @param string $name + * @param Zend_Cache_Core $cache + * @return Zend_Cache_Manager + */ + public function setCache($name, Zend_Cache_Core $cache) + { + $this->_caches[$name] = $cache; + return $this; + } + + /** + * Check if the Cache Manager contains the named cache object, or a named + * configuration template to lazy load the cache object + * + * @param string $name + * @return bool + */ + public function hasCache($name) + { + if (isset($this->_caches[$name]) + || $this->hasCacheTemplate($name) + ) { + return true; + } + return false; + } + + /** + * Fetch the named cache object, or instantiate and return a cache object + * using a named configuration template + * + * @param string $name + * @return Zend_Cache_Core + */ + public function getCache($name) + { + if (isset($this->_caches[$name])) { + return $this->_caches[$name]; + } + if (isset($this->_optionTemplates[$name])) { + if ($name == self::PAGECACHE + && (!isset($this->_optionTemplates[$name]['backend']['options']['tag_cache']) + || !$this->_optionTemplates[$name]['backend']['options']['tag_cache'] instanceof Zend_Cache_Core) + ) { + $this->_optionTemplates[$name]['backend']['options']['tag_cache'] + = $this->getCache(self::PAGETAGCACHE); + } + + $this->_caches[$name] = Zend_Cache::factory( + $this->_optionTemplates[$name]['frontend']['name'], + $this->_optionTemplates[$name]['backend']['name'], + isset($this->_optionTemplates[$name]['frontend']['options']) ? $this->_optionTemplates[$name]['frontend']['options'] : array(), + isset($this->_optionTemplates[$name]['backend']['options']) ? $this->_optionTemplates[$name]['backend']['options'] : array(), + isset($this->_optionTemplates[$name]['frontend']['customFrontendNaming']) ? $this->_optionTemplates[$name]['frontend']['customFrontendNaming'] : false, + isset($this->_optionTemplates[$name]['backend']['customBackendNaming']) ? $this->_optionTemplates[$name]['backend']['customBackendNaming'] : false, + isset($this->_optionTemplates[$name]['frontendBackendAutoload']) ? $this->_optionTemplates[$name]['frontendBackendAutoload'] : false + ); + + return $this->_caches[$name]; + } + } + + /** + * Fetch all available caches + * + * @return array An array of all available caches with it's names as key + */ + public function getCaches() + { + $caches = $this->_caches; + foreach ($this->_optionTemplates as $name => $tmp) { + if (!isset($caches[$name])) { + $caches[$name] = $this->getCache($name); + } + } + return $caches; + } + + /** + * Set a named configuration template from which a cache object can later + * be lazy loaded + * + * @param string $name + * @param array $options + * @return Zend_Cache_Manager + * @throws Zend_Cache_Exception + */ + public function setCacheTemplate($name, $options) + { + if ($options instanceof Zend_Config) { + $options = $options->toArray(); + } elseif (!is_array($options)) { + require_once 'Zend/Cache/Exception.php'; + throw new Zend_Cache_Exception('Options passed must be in' + . ' an associative array or instance of Zend_Config'); + } + $this->_optionTemplates[$name] = $options; + return $this; + } + + /** + * Check if the named configuration template + * + * @param string $name + * @return bool + */ + public function hasCacheTemplate($name) + { + if (isset($this->_optionTemplates[$name])) { + return true; + } + return false; + } + + /** + * Get the named configuration template + * + * @param string $name + * @return array + */ + public function getCacheTemplate($name) + { + if (isset($this->_optionTemplates[$name])) { + return $this->_optionTemplates[$name]; + } + } + + /** + * Pass an array containing changes to be applied to a named + * configuration + * template + * + * @param string $name + * @param array $options + * @return Zend_Cache_Manager + * @throws Zend_Cache_Exception for invalid options format or if option templates do not have $name + */ + public function setTemplateOptions($name, $options) + { + if ($options instanceof Zend_Config) { + $options = $options->toArray(); + } elseif (!is_array($options)) { + require_once 'Zend/Cache/Exception.php'; + throw new Zend_Cache_Exception('Options passed must be in' + . ' an associative array or instance of Zend_Config'); + } + if (!isset($this->_optionTemplates[$name])) { + throw new Zend_Cache_Exception('A cache configuration template' + . 'does not exist with the name "' . $name . '"'); + } + $this->_optionTemplates[$name] + = $this->_mergeOptions($this->_optionTemplates[$name], $options); + return $this; + } + + /** + * Simple method to merge two configuration arrays + * + * @param array $current + * @param array $options + * @return array + */ + protected function _mergeOptions(array $current, array $options) + { + if (isset($options['frontend']['name'])) { + $current['frontend']['name'] = $options['frontend']['name']; + } + if (isset($options['backend']['name'])) { + $current['backend']['name'] = $options['backend']['name']; + } + if (isset($options['frontend']['options'])) { + foreach ($options['frontend']['options'] as $key => $value) { + $current['frontend']['options'][$key] = $value; + } + } + if (isset($options['backend']['options'])) { + foreach ($options['backend']['options'] as $key => $value) { + $current['backend']['options'][$key] = $value; + } + } + if (isset($options['frontend']['customFrontendNaming'])) { + $current['frontend']['customFrontendNaming'] = $options['frontend']['customFrontendNaming']; + } + if (isset($options['backend']['customBackendNaming'])) { + $current['backend']['customBackendNaming'] = $options['backend']['customBackendNaming']; + } + if (isset($options['frontendBackendAutoload'])) { + $current['frontendBackendAutoload'] = $options['frontendBackendAutoload']; + } + return $current; + } +} diff --git a/lib/zend/Zend/Config.php b/lib/zend/Zend/Config.php new file mode 100644 index 00000000000..a39a1f22559 --- /dev/null +++ b/lib/zend/Zend/Config.php @@ -0,0 +1,484 @@ +_allowModifications = (boolean) $allowModifications; + $this->_loadedSection = null; + $this->_index = 0; + $this->_data = array(); + foreach ($array as $key => $value) { + if (is_array($value)) { + $this->_data[$key] = new self($value, $this->_allowModifications); + } else { + $this->_data[$key] = $value; + } + } + $this->_count = count($this->_data); + } + + /** + * Retrieve a value and return $default if there is no element set. + * + * @param string $name + * @param mixed $default + * @return mixed + */ + public function get($name, $default = null) + { + $result = $default; + if (array_key_exists($name, $this->_data)) { + $result = $this->_data[$name]; + } + return $result; + } + + /** + * Magic function so that $obj->value will work. + * + * @param string $name + * @return mixed + */ + public function __get($name) + { + return $this->get($name); + } + + /** + * Only allow setting of a property if $allowModifications + * was set to true on construction. Otherwise, throw an exception. + * + * @param string $name + * @param mixed $value + * @throws Zend_Config_Exception + * @return void + */ + public function __set($name, $value) + { + if ($this->_allowModifications) { + if (is_array($value)) { + $this->_data[$name] = new self($value, true); + } else { + $this->_data[$name] = $value; + } + $this->_count = count($this->_data); + } else { + /** @see Zend_Config_Exception */ + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception('Zend_Config is read only'); + } + } + + /** + * Deep clone of this instance to ensure that nested Zend_Configs + * are also cloned. + * + * @return void + */ + public function __clone() + { + $array = array(); + foreach ($this->_data as $key => $value) { + if ($value instanceof Zend_Config) { + $array[$key] = clone $value; + } else { + $array[$key] = $value; + } + } + $this->_data = $array; + } + + /** + * Return an associative array of the stored data. + * + * @return array + */ + public function toArray() + { + $array = array(); + $data = $this->_data; + foreach ($data as $key => $value) { + if ($value instanceof Zend_Config) { + $array[$key] = $value->toArray(); + } else { + $array[$key] = $value; + } + } + return $array; + } + + /** + * Support isset() overloading on PHP 5.1 + * + * @param string $name + * @return boolean + */ + public function __isset($name) + { + return isset($this->_data[$name]); + } + + /** + * Support unset() overloading on PHP 5.1 + * + * @param string $name + * @throws Zend_Config_Exception + * @return void + */ + public function __unset($name) + { + if ($this->_allowModifications) { + unset($this->_data[$name]); + $this->_count = count($this->_data); + $this->_skipNextIteration = true; + } else { + /** @see Zend_Config_Exception */ + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception('Zend_Config is read only'); + } + + } + + /** + * Defined by Countable interface + * + * @return int + */ + public function count() + { + return $this->_count; + } + + /** + * Defined by Iterator interface + * + * @return mixed + */ + public function current() + { + $this->_skipNextIteration = false; + return current($this->_data); + } + + /** + * Defined by Iterator interface + * + * @return mixed + */ + public function key() + { + return key($this->_data); + } + + /** + * Defined by Iterator interface + * + */ + public function next() + { + if ($this->_skipNextIteration) { + $this->_skipNextIteration = false; + return; + } + next($this->_data); + $this->_index++; + } + + /** + * Defined by Iterator interface + * + */ + public function rewind() + { + $this->_skipNextIteration = false; + reset($this->_data); + $this->_index = 0; + } + + /** + * Defined by Iterator interface + * + * @return boolean + */ + public function valid() + { + return $this->_index < $this->_count; + } + + /** + * Returns the section name(s) loaded. + * + * @return mixed + */ + public function getSectionName() + { + if(is_array($this->_loadedSection) && count($this->_loadedSection) == 1) { + $this->_loadedSection = $this->_loadedSection[0]; + } + return $this->_loadedSection; + } + + /** + * Returns true if all sections were loaded + * + * @return boolean + */ + public function areAllSectionsLoaded() + { + return $this->_loadedSection === null; + } + + + /** + * Merge another Zend_Config with this one. The items + * in $merge will override the same named items in + * the current config. + * + * @param Zend_Config $merge + * @return Zend_Config + */ + public function merge(Zend_Config $merge) + { + foreach($merge as $key => $item) { + if(array_key_exists($key, $this->_data)) { + if($item instanceof Zend_Config && $this->$key instanceof Zend_Config) { + $this->$key = $this->$key->merge(new Zend_Config($item->toArray(), !$this->readOnly())); + } else { + $this->$key = $item; + } + } else { + if($item instanceof Zend_Config) { + $this->$key = new Zend_Config($item->toArray(), !$this->readOnly()); + } else { + $this->$key = $item; + } + } + } + + return $this; + } + + /** + * Prevent any more modifications being made to this instance. Useful + * after merge() has been used to merge multiple Zend_Config objects + * into one object which should then not be modified again. + * + */ + public function setReadOnly() + { + $this->_allowModifications = false; + foreach ($this->_data as $key => $value) { + if ($value instanceof Zend_Config) { + $value->setReadOnly(); + } + } + } + + /** + * Returns if this Zend_Config object is read only or not. + * + * @return boolean + */ + public function readOnly() + { + return !$this->_allowModifications; + } + + /** + * Get the current extends + * + * @return array + */ + public function getExtends() + { + return $this->_extends; + } + + /** + * Set an extend for Zend_Config_Writer + * + * @param string $extendingSection + * @param string $extendedSection + * @return void + */ + public function setExtend($extendingSection, $extendedSection = null) + { + if ($extendedSection === null && isset($this->_extends[$extendingSection])) { + unset($this->_extends[$extendingSection]); + } else if ($extendedSection !== null) { + $this->_extends[$extendingSection] = $extendedSection; + } + } + + /** + * Throws an exception if $extendingSection may not extend $extendedSection, + * and tracks the section extension if it is valid. + * + * @param string $extendingSection + * @param string $extendedSection + * @throws Zend_Config_Exception + * @return void + */ + protected function _assertValidExtend($extendingSection, $extendedSection) + { + // detect circular section inheritance + $extendedSectionCurrent = $extendedSection; + while (array_key_exists($extendedSectionCurrent, $this->_extends)) { + if ($this->_extends[$extendedSectionCurrent] == $extendingSection) { + /** @see Zend_Config_Exception */ + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception('Illegal circular inheritance detected'); + } + $extendedSectionCurrent = $this->_extends[$extendedSectionCurrent]; + } + // remember that this section extends another section + $this->_extends[$extendingSection] = $extendedSection; + } + + /** + * Handle any errors from simplexml_load_file or parse_ini_file + * + * @param integer $errno + * @param string $errstr + * @param string $errfile + * @param integer $errline + */ + public function _loadFileErrorHandler($errno, $errstr, $errfile, $errline) + { + if ($this->_loadFileErrorStr === null) { + $this->_loadFileErrorStr = $errstr; + } else { + $this->_loadFileErrorStr .= (PHP_EOL . $errstr); + } + } + + /** + * Merge two arrays recursively, overwriting keys of the same name + * in $firstArray with the value in $secondArray. + * + * @param mixed $firstArray First array + * @param mixed $secondArray Second array to merge into first array + * @return array + */ + protected function _arrayMergeRecursive($firstArray, $secondArray) + { + if (is_array($firstArray) && is_array($secondArray)) { + foreach ($secondArray as $key => $value) { + if (isset($firstArray[$key])) { + $firstArray[$key] = $this->_arrayMergeRecursive($firstArray[$key], $value); + } else { + if($key === 0) { + $firstArray= array(0=>$this->_arrayMergeRecursive($firstArray, $value)); + } else { + $firstArray[$key] = $value; + } + } + } + } else { + $firstArray = $secondArray; + } + + return $firstArray; + } +} diff --git a/lib/zend/Zend/Config/Exception.php b/lib/zend/Zend/Config/Exception.php new file mode 100644 index 00000000000..253b3346825 --- /dev/null +++ b/lib/zend/Zend/Config/Exception.php @@ -0,0 +1,33 @@ +hostname === "staging" + * $data->db->connection === "database" + * + * The $options parameter may be provided as either a boolean or an array. + * If provided as a boolean, this sets the $allowModifications option of + * Zend_Config. If provided as an array, there are three configuration + * directives that may be set. For example: + * + * $options = array( + * 'allowModifications' => false, + * 'nestSeparator' => ':', + * 'skipExtends' => false, + * ); + * + * @param string $filename + * @param mixed $section + * @param boolean|array $options + * @throws Zend_Config_Exception + * @return void + */ + public function __construct($filename, $section = null, $options = false) + { + if (empty($filename)) { + /** + * @see Zend_Config_Exception + */ + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception('Filename is not set'); + } + + $allowModifications = false; + if (is_bool($options)) { + $allowModifications = $options; + } elseif (is_array($options)) { + if (isset($options['allowModifications'])) { + $allowModifications = (bool) $options['allowModifications']; + } + if (isset($options['nestSeparator'])) { + $this->_nestSeparator = (string) $options['nestSeparator']; + } + if (isset($options['skipExtends'])) { + $this->_skipExtends = (bool) $options['skipExtends']; + } + } + + $iniArray = $this->_loadIniFile($filename); + + if (null === $section) { + // Load entire file + $dataArray = array(); + foreach ($iniArray as $sectionName => $sectionData) { + if(!is_array($sectionData)) { + $dataArray = $this->_arrayMergeRecursive($dataArray, $this->_processKey(array(), $sectionName, $sectionData)); + } else { + $dataArray[$sectionName] = $this->_processSection($iniArray, $sectionName); + } + } + parent::__construct($dataArray, $allowModifications); + } else { + // Load one or more sections + if (!is_array($section)) { + $section = array($section); + } + $dataArray = array(); + foreach ($section as $sectionName) { + if (!isset($iniArray[$sectionName])) { + /** + * @see Zend_Config_Exception + */ + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception("Section '$sectionName' cannot be found in $filename"); + } + $dataArray = $this->_arrayMergeRecursive($this->_processSection($iniArray, $sectionName), $dataArray); + + } + parent::__construct($dataArray, $allowModifications); + } + + $this->_loadedSection = $section; + } + + /** + * Load the INI file from disk using parse_ini_file(). Use a private error + * handler to convert any loading errors into a Zend_Config_Exception + * + * @param string $filename + * @throws Zend_Config_Exception + * @return array + */ + protected function _parseIniFile($filename) + { + set_error_handler(array($this, '_loadFileErrorHandler')); + $iniArray = parse_ini_file($filename, true); // Warnings and errors are suppressed + restore_error_handler(); + + // Check if there was a error while loading file + if ($this->_loadFileErrorStr !== null) { + /** + * @see Zend_Config_Exception + */ + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception($this->_loadFileErrorStr); + } + + return $iniArray; + } + + /** + * Load the ini file and preprocess the section separator (':' in the + * section name (that is used for section extension) so that the resultant + * array has the correct section names and the extension information is + * stored in a sub-key called ';extends'. We use ';extends' as this can + * never be a valid key name in an INI file that has been loaded using + * parse_ini_file(). + * + * @param string $filename + * @throws Zend_Config_Exception + * @return array + */ + protected function _loadIniFile($filename) + { + $loaded = $this->_parseIniFile($filename); + $iniArray = array(); + foreach ($loaded as $key => $data) + { + $pieces = explode($this->_sectionSeparator, $key); + $thisSection = trim($pieces[0]); + switch (count($pieces)) { + case 1: + $iniArray[$thisSection] = $data; + break; + + case 2: + $extendedSection = trim($pieces[1]); + $iniArray[$thisSection] = array_merge(array(';extends'=>$extendedSection), $data); + break; + + default: + /** + * @see Zend_Config_Exception + */ + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception("Section '$thisSection' may not extend multiple sections in $filename"); + } + } + + return $iniArray; + } + + /** + * Process each element in the section and handle the ";extends" inheritance + * key. Passes control to _processKey() to handle the nest separator + * sub-property syntax that may be used within the key name. + * + * @param array $iniArray + * @param string $section + * @param array $config + * @throws Zend_Config_Exception + * @return array + */ + protected function _processSection($iniArray, $section, $config = array()) + { + $thisSection = $iniArray[$section]; + + foreach ($thisSection as $key => $value) { + if (strtolower($key) == ';extends') { + if (isset($iniArray[$value])) { + $this->_assertValidExtend($section, $value); + + if (!$this->_skipExtends) { + $config = $this->_processSection($iniArray, $value, $config); + } + } else { + /** + * @see Zend_Config_Exception + */ + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception("Parent section '$section' cannot be found"); + } + } else { + $config = $this->_processKey($config, $key, $value); + } + } + return $config; + } + + /** + * Assign the key's value to the property list. Handles the + * nest separator for sub-properties. + * + * @param array $config + * @param string $key + * @param string $value + * @throws Zend_Config_Exception + * @return array + */ + protected function _processKey($config, $key, $value) + { + if (strpos($key, $this->_nestSeparator) !== false) { + $pieces = explode($this->_nestSeparator, $key, 2); + if (strlen($pieces[0]) && strlen($pieces[1])) { + if (!isset($config[$pieces[0]])) { + if ($pieces[0] === '0' && !empty($config)) { + // convert the current values in $config into an array + $config = array($pieces[0] => $config); + } else { + $config[$pieces[0]] = array(); + } + } elseif (!is_array($config[$pieces[0]])) { + /** + * @see Zend_Config_Exception + */ + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception("Cannot create sub-key for '{$pieces[0]}' as key already exists"); + } + $config[$pieces[0]] = $this->_processKey($config[$pieces[0]], $pieces[1], $value); + } else { + /** + * @see Zend_Config_Exception + */ + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception("Invalid key '$key'"); + } + } else { + $config[$key] = $value; + } + return $config; + } +} diff --git a/lib/zend/Zend/Config/Json.php b/lib/zend/Zend/Config/Json.php new file mode 100755 index 00000000000..2c31fdc0140 --- /dev/null +++ b/lib/zend/Zend/Config/Json.php @@ -0,0 +1,242 @@ + $value) { + switch (strtolower($key)) { + case 'allow_modifications': + case 'allowmodifications': + $allowModifications = (bool) $value; + break; + case 'skip_extends': + case 'skipextends': + $this->_skipExtends = (bool) $value; + break; + case 'ignore_constants': + case 'ignoreconstants': + $this->_ignoreConstants = (bool) $value; + break; + default: + break; + } + } + } + + set_error_handler(array($this, '_loadFileErrorHandler')); // Warnings and errors are suppressed + if ($json[0] != '{') { + $json = file_get_contents($json); + } + restore_error_handler(); + + // Check if there was a error while loading file + if ($this->_loadFileErrorStr !== null) { + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception($this->_loadFileErrorStr); + } + + // Replace constants + if (!$this->_ignoreConstants) { + $json = $this->_replaceConstants($json); + } + + // Parse/decode + try { + $config = Zend_Json::decode($json); + } catch (Zend_Json_Exception $e) { + // decode failed + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception("Error parsing JSON data"); + } + + if ($section === null) { + $dataArray = array(); + foreach ($config as $sectionName => $sectionData) { + $dataArray[$sectionName] = $this->_processExtends($config, $sectionName); + } + + parent::__construct($dataArray, $allowModifications); + } elseif (is_array($section)) { + $dataArray = array(); + foreach ($section as $sectionName) { + if (!isset($config[$sectionName])) { + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception(sprintf('Section "%s" cannot be found', $sectionName)); + } + + $dataArray = array_merge($this->_processExtends($config, $sectionName), $dataArray); + } + + parent::__construct($dataArray, $allowModifications); + } else { + if (!isset($config[$section])) { + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception(sprintf('Section "%s" cannot be found', $section)); + } + + $dataArray = $this->_processExtends($config, $section); + if (!is_array($dataArray)) { + // Section in the JSON data contains just one top level string + $dataArray = array($section => $dataArray); + } + + parent::__construct($dataArray, $allowModifications); + } + + $this->_loadedSection = $section; + } + + /** + * Helper function to process each element in the section and handle + * the "_extends" inheritance attribute. + * + * @param array $data Data array to process + * @param string $section Section to process + * @param array $config Configuration which was parsed yet + * @throws Zend_Config_Exception When $section cannot be found + * @return array + */ + protected function _processExtends(array $data, $section, array $config = array()) + { + if (!isset($data[$section])) { + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception(sprintf('Section "%s" cannot be found', $section)); + } + + $thisSection = $data[$section]; + + if (is_array($thisSection) && isset($thisSection[self::EXTENDS_NAME])) { + if (is_array($thisSection[self::EXTENDS_NAME])) { + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception('Invalid extends clause: must be a string; array received'); + } + $this->_assertValidExtend($section, $thisSection[self::EXTENDS_NAME]); + + if (!$this->_skipExtends) { + $config = $this->_processExtends($data, $thisSection[self::EXTENDS_NAME], $config); + } + unset($thisSection[self::EXTENDS_NAME]); + } + + $config = $this->_arrayMergeRecursive($config, $thisSection); + + return $config; + } + + /** + * Replace any constants referenced in a string with their values + * + * @param string $value + * @return string + */ + protected function _replaceConstants($value) + { + foreach ($this->_getConstants() as $constant) { + if (strstr($value, $constant)) { + // handle backslashes that may represent windows path names for instance + $replacement = str_replace('\\', '\\\\', constant($constant)); + $value = str_replace($constant, $replacement, $value); + } + } + return $value; + } + + /** + * Get (reverse) sorted list of defined constant names + * + * @return array + */ + protected function _getConstants() + { + $constants = array_keys(get_defined_constants()); + rsort($constants, SORT_STRING); + return $constants; + } +} diff --git a/lib/zend/Zend/Config/Writer.php b/lib/zend/Zend/Config/Writer.php new file mode 100644 index 00000000000..8c255b3c847 --- /dev/null +++ b/lib/zend/Zend/Config/Writer.php @@ -0,0 +1,101 @@ +setOptions($options); + } + } + + /** + * Set options via a Zend_Config instance + * + * @param Zend_Config $config + * @return Zend_Config_Writer + */ + public function setConfig(Zend_Config $config) + { + $this->_config = $config; + + return $this; + } + + /** + * Set options via an array + * + * @param array $options + * @return Zend_Config_Writer + */ + public function setOptions(array $options) + { + foreach ($options as $key => $value) { + if (in_array(strtolower($key), $this->_skipOptions)) { + continue; + } + + $method = 'set' . ucfirst($key); + if (method_exists($this, $method)) { + $this->$method($value); + } + } + + return $this; + } + + /** + * Write a Zend_Config object to it's target + * + * @return void + */ + abstract public function write(); +} diff --git a/lib/zend/Zend/Service/DeveloperGarden/Response/VoiceButler/TearDownCallResponse.php b/lib/zend/Zend/Config/Writer/Array.php similarity index 51% rename from lib/zend/Zend/Service/DeveloperGarden/Response/VoiceButler/TearDownCallResponse.php rename to lib/zend/Zend/Config/Writer/Array.php index 6ea614a9d22..50c260e0cf0 100644 --- a/lib/zend/Zend/Service/DeveloperGarden/Response/VoiceButler/TearDownCallResponse.php +++ b/lib/zend/Zend/Config/Writer/Array.php @@ -13,38 +13,43 @@ * to license@zend.com so we can send you a copy immediately. * * @category Zend - * @package Zend_Service - * @subpackage DeveloperGarden - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @package Zend_Config + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ /** - * @see Zend_Service_DeveloperGarden_Response_VoiceButler_VoiceButlerAbstract + * @see Zend_Config_Writer */ -require_once 'Zend/Service/DeveloperGarden/Response/VoiceButler/VoiceButlerAbstract.php'; +require_once 'Zend/Config/Writer/FileAbstract.php'; /** * @category Zend - * @package Zend_Service - * @subpackage DeveloperGarden - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @author Marco Kaiser + * @package Zend_Config + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class Zend_Service_DeveloperGarden_Response_VoiceButler_TearDownCallResponse - extends Zend_Service_DeveloperGarden_Response_VoiceButler_VoiceButlerAbstract +class Zend_Config_Writer_Array extends Zend_Config_Writer_FileAbstract { /** - * returns the session id + * Render a Zend_Config into a PHP Array config string. + * + * @since 1.10 * @return string */ - public function getSessionId() + public function render() { - if (isset($this->return->sessionId)) { - return $this->return->sessionId; + $data = $this->_config->toArray(); + $sectionName = $this->_config->getSectionName(); + + if (is_string($sectionName)) { + $data = array($sectionName => $data); } - return null; + + $arrayString = "_filename = $filename; + + return $this; + } + + /** + * Set wether to exclusively lock the file or not + * + * @param boolean $exclusiveLock + * @return Zend_Config_Writer_Array + */ + public function setExclusiveLock($exclusiveLock) + { + $this->_exclusiveLock = $exclusiveLock; + + return $this; + } + + /** + * Write configuration to file. + * + * @param string $filename + * @param Zend_Config $config + * @param bool $exclusiveLock + * @return void + */ + public function write($filename = null, Zend_Config $config = null, $exclusiveLock = null) + { + if ($filename !== null) { + $this->setFilename($filename); + } + + if ($config !== null) { + $this->setConfig($config); + } + + if ($exclusiveLock !== null) { + $this->setExclusiveLock($exclusiveLock); + } + + if ($this->_filename === null) { + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception('No filename was set'); + } + + if ($this->_config === null) { + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception('No config was set'); + } + + $configString = $this->render(); + + $flags = 0; + + if ($this->_exclusiveLock) { + $flags |= LOCK_EX; + } + + $result = @file_put_contents($this->_filename, $configString, $flags); + + if ($result === false) { + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception('Could not write to file "' . $this->_filename . '"'); + } + } + + /** + * Render a Zend_Config into a config file string. + * + * @since 1.10 + * @todo For 2.0 this should be redone into an abstract method. + * @return string + */ + public function render() + { + return ""; + } +} diff --git a/lib/zend/Zend/Config/Writer/Ini.php b/lib/zend/Zend/Config/Writer/Ini.php new file mode 100644 index 00000000000..15344a5b740 --- /dev/null +++ b/lib/zend/Zend/Config/Writer/Ini.php @@ -0,0 +1,193 @@ +_nestSeparator = $separator; + + return $this; + } + + /** + * Set if rendering should occour without sections or not. + * + * If set to true, the INI file is rendered without sections completely + * into the global namespace of the INI file. + * + * @param bool $withoutSections + * @return Zend_Config_Writer_Ini + */ + public function setRenderWithoutSections($withoutSections=true) + { + $this->_renderWithoutSections = (bool)$withoutSections; + return $this; + } + + /** + * Render a Zend_Config into a INI config string. + * + * @since 1.10 + * @return string + */ + public function render() + { + $iniString = ''; + $extends = $this->_config->getExtends(); + $sectionName = $this->_config->getSectionName(); + + if($this->_renderWithoutSections == true) { + $iniString .= $this->_addBranch($this->_config); + } else if (is_string($sectionName)) { + $iniString .= '[' . $sectionName . ']' . "\n" + . $this->_addBranch($this->_config) + . "\n"; + } else { + $config = $this->_sortRootElements($this->_config); + foreach ($config as $sectionName => $data) { + if (!($data instanceof Zend_Config)) { + $iniString .= $sectionName + . ' = ' + . $this->_prepareValue($data) + . "\n"; + } else { + if (isset($extends[$sectionName])) { + $sectionName .= ' : ' . $extends[$sectionName]; + } + + $iniString .= '[' . $sectionName . ']' . "\n" + . $this->_addBranch($data) + . "\n"; + } + } + } + + return $iniString; + } + + /** + * Add a branch to an INI string recursively + * + * @param Zend_Config $config + * @return void + */ + protected function _addBranch(Zend_Config $config, $parents = array()) + { + $iniString = ''; + + foreach ($config as $key => $value) { + $group = array_merge($parents, array($key)); + + if ($value instanceof Zend_Config) { + $iniString .= $this->_addBranch($value, $group); + } else { + $iniString .= implode($this->_nestSeparator, $group) + . ' = ' + . $this->_prepareValue($value) + . "\n"; + } + } + + return $iniString; + } + + /** + * Prepare a value for INI + * + * @param mixed $value + * @return string + */ + protected function _prepareValue($value) + { + if (is_integer($value) || is_float($value)) { + return $value; + } elseif (is_bool($value)) { + return ($value ? 'true' : 'false'); + } elseif (strpos($value, '"') === false) { + return '"' . $value . '"'; + } else { + /** @see Zend_Config_Exception */ + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception('Value can not contain double quotes "'); + } + } + + /** + * Root elements that are not assigned to any section needs to be + * on the top of config. + * + * @see http://framework.zend.com/issues/browse/ZF-6289 + * @param Zend_Config + * @return Zend_Config + */ + protected function _sortRootElements(Zend_Config $config) + { + $configArray = $config->toArray(); + $sections = array(); + + // remove sections from config array + foreach ($configArray as $key => $value) { + if (is_array($value)) { + $sections[$key] = $value; + unset($configArray[$key]); + } + } + + // readd sections to the end + foreach ($sections as $key => $value) { + $configArray[$key] = $value; + } + + return new Zend_Config($configArray); + } +} diff --git a/lib/zend/Zend/Config/Writer/Json.php b/lib/zend/Zend/Config/Writer/Json.php new file mode 100755 index 00000000000..25da4a9038c --- /dev/null +++ b/lib/zend/Zend/Config/Writer/Json.php @@ -0,0 +1,106 @@ +_prettyPrint; + } + + /** + * Set prettyPrint flag + * + * @param bool $prettyPrint PrettyPrint flag + * @return Zend_Config_Writer_Json + */ + public function setPrettyPrint($flag) + { + $this->_prettyPrint = (bool) $flag; + return $this; + } + + /** + * Render a Zend_Config into a JSON config string. + * + * @since 1.10 + * @return string + */ + public function render() + { + $data = $this->_config->toArray(); + $sectionName = $this->_config->getSectionName(); + $extends = $this->_config->getExtends(); + + if (is_string($sectionName)) { + $data = array($sectionName => $data); + } + + foreach ($extends as $section => $parentSection) { + $data[$section][Zend_Config_Json::EXTENDS_NAME] = $parentSection; + } + + // Ensure that each "extends" section actually exists + foreach ($data as $section => $sectionData) { + if (is_array($sectionData) && isset($sectionData[Zend_Config_Json::EXTENDS_NAME])) { + $sectionExtends = $sectionData[Zend_Config_Json::EXTENDS_NAME]; + if (!isset($data[$sectionExtends])) { + // Remove "extends" declaration if section does not exist + unset($data[$section][Zend_Config_Json::EXTENDS_NAME]); + } + } + } + + $out = Zend_Json::encode($data); + if ($this->prettyPrint()) { + $out = Zend_Json::prettyPrint($out); + } + return $out; + } +} diff --git a/lib/zend/Zend/Config/Writer/Xml.php b/lib/zend/Zend/Config/Writer/Xml.php new file mode 100644 index 00000000000..c73564b2190 --- /dev/null +++ b/lib/zend/Zend/Config/Writer/Xml.php @@ -0,0 +1,127 @@ +'); + $extends = $this->_config->getExtends(); + $sectionName = $this->_config->getSectionName(); + + if (is_string($sectionName)) { + $child = $xml->addChild($sectionName); + + $this->_addBranch($this->_config, $child, $xml); + } else { + foreach ($this->_config as $sectionName => $data) { + if (!($data instanceof Zend_Config)) { + $xml->addChild($sectionName, (string) $data); + } else { + $child = $xml->addChild($sectionName); + + if (isset($extends[$sectionName])) { + $child->addAttribute('zf:extends', $extends[$sectionName], Zend_Config_Xml::XML_NAMESPACE); + } + + $this->_addBranch($data, $child, $xml); + } + } + } + + $dom = dom_import_simplexml($xml)->ownerDocument; + $dom->formatOutput = true; + + $xmlString = $dom->saveXML(); + + return $xmlString; + } + + /** + * Add a branch to an XML object recursively + * + * @param Zend_Config $config + * @param SimpleXMLElement $xml + * @param SimpleXMLElement $parent + * @return void + */ + protected function _addBranch(Zend_Config $config, SimpleXMLElement $xml, SimpleXMLElement $parent) + { + $branchType = null; + + foreach ($config as $key => $value) { + if ($branchType === null) { + if (is_numeric($key)) { + $branchType = 'numeric'; + $branchName = $xml->getName(); + $xml = $parent; + + unset($parent->{$branchName}); + } else { + $branchType = 'string'; + } + } else if ($branchType !== (is_numeric($key) ? 'numeric' : 'string')) { + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception('Mixing of string and numeric keys is not allowed'); + } + + if ($branchType === 'numeric') { + if ($value instanceof Zend_Config) { + $child = $parent->addChild($branchName); + + $this->_addBranch($value, $child, $parent); + } else { + $parent->addChild($branchName, (string) $value); + } + } else { + if ($value instanceof Zend_Config) { + $child = $xml->addChild($key); + + $this->_addBranch($value, $child, $xml); + } else { + $xml->addChild($key, (string) $value); + } + } + } + } +} diff --git a/lib/zend/Zend/Config/Writer/Yaml.php b/lib/zend/Zend/Config/Writer/Yaml.php new file mode 100755 index 00000000000..4d2b1fed442 --- /dev/null +++ b/lib/zend/Zend/Config/Writer/Yaml.php @@ -0,0 +1,144 @@ +_yamlEncoder; + } + + /** + * Set callback for decoding YAML + * + * @param callable $yamlEncoder the decoder to set + * @return Zend_Config_Yaml + */ + public function setYamlEncoder($yamlEncoder) + { + if (!is_callable($yamlEncoder)) { + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception('Invalid parameter to setYamlEncoder - must be callable'); + } + + $this->_yamlEncoder = $yamlEncoder; + return $this; + } + + /** + * Render a Zend_Config into a YAML config string. + * + * @since 1.10 + * @return string + */ + public function render() + { + $data = $this->_config->toArray(); + $sectionName = $this->_config->getSectionName(); + $extends = $this->_config->getExtends(); + + if (is_string($sectionName)) { + $data = array($sectionName => $data); + } + + foreach ($extends as $section => $parentSection) { + $data[$section][Zend_Config_Yaml::EXTENDS_NAME] = $parentSection; + } + + // Ensure that each "extends" section actually exists + foreach ($data as $section => $sectionData) { + if (is_array($sectionData) && isset($sectionData[Zend_Config_Yaml::EXTENDS_NAME])) { + $sectionExtends = $sectionData[Zend_Config_Yaml::EXTENDS_NAME]; + if (!isset($data[$sectionExtends])) { + // Remove "extends" declaration if section does not exist + unset($data[$section][Zend_Config_Yaml::EXTENDS_NAME]); + } + } + } + + return call_user_func($this->getYamlEncoder(), $data); + } + + /** + * Very dumb YAML encoder + * + * Until we have Zend_Yaml... + * + * @param array $data YAML data + * @return string + */ + public static function encode($data) + { + return self::_encodeYaml(0, $data); + } + + /** + * Service function for encoding YAML + * + * @param int $indent Current indent level + * @param array $data Data to encode + * @return string + */ + protected static function _encodeYaml($indent, $data) + { + reset($data); + $result = ""; + $numeric = is_numeric(key($data)); + + foreach($data as $key => $value) { + if(is_array($value)) { + $encoded = "\n".self::_encodeYaml($indent+1, $value); + } else { + $encoded = (string)$value."\n"; + } + $result .= str_repeat(" ", $indent).($numeric?"- ":"$key: ").$encoded; + } + return $result; + } +} diff --git a/lib/zend/Zend/Config/Xml.php b/lib/zend/Zend/Config/Xml.php new file mode 100644 index 00000000000..4425a8b7059 --- /dev/null +++ b/lib/zend/Zend/Config/Xml.php @@ -0,0 +1,314 @@ + false, + * 'skipExtends' => false + * ); + * + * @param string $xml XML file or string to process + * @param mixed $section Section to process + * @param array|boolean $options + * @throws Zend_Config_Exception When xml is not set or cannot be loaded + * @throws Zend_Config_Exception When section $sectionName cannot be found in $xml + */ + public function __construct($xml, $section = null, $options = false) + { + if (empty($xml)) { + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception('Filename is not set'); + } + + $allowModifications = false; + if (is_bool($options)) { + $allowModifications = $options; + } elseif (is_array($options)) { + if (isset($options['allowModifications'])) { + $allowModifications = (bool) $options['allowModifications']; + } + if (isset($options['skipExtends'])) { + $this->_skipExtends = (bool) $options['skipExtends']; + } + } + + set_error_handler(array($this, '_loadFileErrorHandler')); // Warnings and errors are suppressed + if (strstr($xml, 'getMessage() + ); + } + } + + restore_error_handler(); + // Check if there was a error while loading file + if ($this->_loadFileErrorStr !== null) { + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception($this->_loadFileErrorStr); + } + + if ($section === null) { + $dataArray = array(); + foreach ($config as $sectionName => $sectionData) { + $dataArray[$sectionName] = $this->_processExtends($config, $sectionName); + } + + parent::__construct($dataArray, $allowModifications); + } else if (is_array($section)) { + $dataArray = array(); + foreach ($section as $sectionName) { + if (!isset($config->$sectionName)) { + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception("Section '$sectionName' cannot be found in $xml"); + } + + $dataArray = array_merge($this->_processExtends($config, $sectionName), $dataArray); + } + + parent::__construct($dataArray, $allowModifications); + } else { + if (!isset($config->$section)) { + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception("Section '$section' cannot be found in $xml"); + } + + $dataArray = $this->_processExtends($config, $section); + if (!is_array($dataArray)) { + // Section in the XML file contains just one top level string + $dataArray = array($section => $dataArray); + } + + parent::__construct($dataArray, $allowModifications); + } + + $this->_loadedSection = $section; + } + + /** + * Helper function to process each element in the section and handle + * the "extends" inheritance attribute. + * + * @param SimpleXMLElement $element XML Element to process + * @param string $section Section to process + * @param array $config Configuration which was parsed yet + * @throws Zend_Config_Exception When $section cannot be found + * @return array + */ + protected function _processExtends(SimpleXMLElement $element, $section, array $config = array()) + { + if (!isset($element->$section)) { + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception("Section '$section' cannot be found"); + } + + $thisSection = $element->$section; + $nsAttributes = $thisSection->attributes(self::XML_NAMESPACE); + + if (isset($thisSection['extends']) || isset($nsAttributes['extends'])) { + $extendedSection = (string) (isset($nsAttributes['extends']) ? $nsAttributes['extends'] : $thisSection['extends']); + $this->_assertValidExtend($section, $extendedSection); + + if (!$this->_skipExtends) { + $config = $this->_processExtends($element, $extendedSection, $config); + } + } + + $config = $this->_arrayMergeRecursive($config, $this->_toArray($thisSection)); + + return $config; + } + + /** + * Returns a string or an associative and possibly multidimensional array from + * a SimpleXMLElement. + * + * @param SimpleXMLElement $xmlObject Convert a SimpleXMLElement into an array + * @return array|string + */ + protected function _toArray(SimpleXMLElement $xmlObject) + { + $config = array(); + $nsAttributes = $xmlObject->attributes(self::XML_NAMESPACE); + + // Search for parent node values + if (count($xmlObject->attributes()) > 0) { + foreach ($xmlObject->attributes() as $key => $value) { + if ($key === 'extends') { + continue; + } + + $value = (string) $value; + + if (array_key_exists($key, $config)) { + if (!is_array($config[$key])) { + $config[$key] = array($config[$key]); + } + + $config[$key][] = $value; + } else { + $config[$key] = $value; + } + } + } + + // Search for local 'const' nodes and replace them + if (count($xmlObject->children(self::XML_NAMESPACE)) > 0) { + if (count($xmlObject->children()) > 0) { + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception("A node with a 'const' childnode may not have any other children"); + } + + $dom = dom_import_simplexml($xmlObject); + $namespaceChildNodes = array(); + + // We have to store them in an array, as replacing nodes will + // confuse the DOMNodeList later + foreach ($dom->childNodes as $node) { + if ($node instanceof DOMElement && $node->namespaceURI === self::XML_NAMESPACE) { + $namespaceChildNodes[] = $node; + } + } + + foreach ($namespaceChildNodes as $node) { + switch ($node->localName) { + case 'const': + if (!$node->hasAttributeNS(self::XML_NAMESPACE, 'name')) { + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception("Misssing 'name' attribute in 'const' node"); + } + + $constantName = $node->getAttributeNS(self::XML_NAMESPACE, 'name'); + + if (!defined($constantName)) { + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception("Constant with name '$constantName' was not defined"); + } + + $constantValue = constant($constantName); + + $dom->replaceChild($dom->ownerDocument->createTextNode($constantValue), $node); + break; + + default: + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception("Unknown node with name '$node->localName' found"); + } + } + + return (string) simplexml_import_dom($dom); + } + + // Search for children + if (count($xmlObject->children()) > 0) { + foreach ($xmlObject->children() as $key => $value) { + if (count($value->children()) > 0 || count($value->children(self::XML_NAMESPACE)) > 0) { + $value = $this->_toArray($value); + } else if (count($value->attributes()) > 0) { + $attributes = $value->attributes(); + if (isset($attributes['value'])) { + $value = (string) $attributes['value']; + } else { + $value = $this->_toArray($value); + } + } else { + $value = (string) $value; + } + + if (array_key_exists($key, $config)) { + if (!is_array($config[$key]) || !array_key_exists(0, $config[$key])) { + $config[$key] = array($config[$key]); + } + + $config[$key][] = $value; + } else { + $config[$key] = $value; + } + } + } else if (!isset($xmlObject['extends']) && !isset($nsAttributes['extends']) && (count($config) === 0)) { + // Object has no children nor attributes and doesn't use the extends + // attribute: it's a string + $config = (string) $xmlObject; + } + + return $config; + } +} diff --git a/lib/zend/Zend/Config/Yaml.php b/lib/zend/Zend/Config/Yaml.php new file mode 100755 index 00000000000..0d107033eb8 --- /dev/null +++ b/lib/zend/Zend/Config/Yaml.php @@ -0,0 +1,415 @@ +_yamlDecoder; + } + + /** + * Set callback for decoding YAML + * + * @param callable $yamlDecoder the decoder to set + * @return Zend_Config_Yaml + */ + public function setYamlDecoder($yamlDecoder) + { + if (!is_callable($yamlDecoder)) { + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception('Invalid parameter to setYamlDecoder() - must be callable'); + } + + $this->_yamlDecoder = $yamlDecoder; + return $this; + } + + /** + * Loads the section $section from the config file encoded as YAML + * + * Sections are defined as properties of the main object + * + * In order to extend another section, a section defines the "_extends" + * property having a value of the section name from which the extending + * section inherits values. + * + * Note that the keys in $section will override any keys of the same + * name in the sections that have been included via "_extends". + * + * Options may include: + * - allow_modifications: whether or not the config object is mutable + * - skip_extends: whether or not to skip processing of parent configuration + * - yaml_decoder: a callback to use to decode the Yaml source + * + * @param string $yaml YAML file to process + * @param mixed $section Section to process + * @param array|boolean $options + */ + public function __construct($yaml, $section = null, $options = false) + { + if (empty($yaml)) { + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception('Filename is not set'); + } + + $ignoreConstants = $staticIgnoreConstants = self::ignoreConstants(); + $allowModifications = false; + if (is_bool($options)) { + $allowModifications = $options; + } elseif (is_array($options)) { + foreach ($options as $key => $value) { + switch (strtolower($key)) { + case 'allow_modifications': + case 'allowmodifications': + $allowModifications = (bool) $value; + break; + case 'skip_extends': + case 'skipextends': + $this->_skipExtends = (bool) $value; + break; + case 'ignore_constants': + case 'ignoreconstants': + $ignoreConstants = (bool) $value; + break; + case 'yaml_decoder': + case 'yamldecoder': + $this->setYamlDecoder($value); + break; + default: + break; + } + } + } + + // Suppress warnings and errors while loading file + set_error_handler(array($this, '_loadFileErrorHandler')); + $yaml = file_get_contents($yaml); + restore_error_handler(); + + // Check if there was a error while loading file + if ($this->_loadFileErrorStr !== null) { + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception($this->_loadFileErrorStr); + } + + // Override static value for ignore_constants if provided in $options + self::setIgnoreConstants($ignoreConstants); + + // Parse YAML + $config = call_user_func($this->getYamlDecoder(), $yaml); + + // Reset original static state of ignore_constants + self::setIgnoreConstants($staticIgnoreConstants); + + if (null === $config) { + // decode failed + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception("Error parsing YAML data"); + } + + if (null === $section) { + $dataArray = array(); + foreach ($config as $sectionName => $sectionData) { + $dataArray[$sectionName] = $this->_processExtends($config, $sectionName); + } + parent::__construct($dataArray, $allowModifications); + } elseif (is_array($section)) { + $dataArray = array(); + foreach ($section as $sectionName) { + if (!isset($config[$sectionName])) { + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception(sprintf( + 'Section "%s" cannot be found', + implode(' ', (array)$section) + )); + } + + $dataArray = array_merge($this->_processExtends($config, $sectionName), $dataArray); + } + parent::__construct($dataArray, $allowModifications); + } else { + if (!isset($config[$section])) { + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception(sprintf( + 'Section "%s" cannot be found', + implode(' ', (array)$section) + )); + } + + $dataArray = $this->_processExtends($config, $section); + if (!is_array($dataArray)) { + // Section in the yaml data contains just one top level string + $dataArray = array($section => $dataArray); + } + parent::__construct($dataArray, $allowModifications); + } + + $this->_loadedSection = $section; + } + + /** + * Helper function to process each element in the section and handle + * the "_extends" inheritance attribute. + * + * @param array $data Data array to process + * @param string $section Section to process + * @param array $config Configuration which was parsed yet + * @return array + * @throws Zend_Config_Exception When $section cannot be found + */ + protected function _processExtends(array $data, $section, array $config = array()) + { + if (!isset($data[$section])) { + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception(sprintf('Section "%s" cannot be found', $section)); + } + + $thisSection = $data[$section]; + + if (is_array($thisSection) && isset($thisSection[self::EXTENDS_NAME])) { + $this->_assertValidExtend($section, $thisSection[self::EXTENDS_NAME]); + + if (!$this->_skipExtends) { + $config = $this->_processExtends($data, $thisSection[self::EXTENDS_NAME], $config); + } + unset($thisSection[self::EXTENDS_NAME]); + } + + $config = $this->_arrayMergeRecursive($config, $thisSection); + + return $config; + } + + /** + * Very dumb YAML parser + * + * Until we have Zend_Yaml... + * + * @param string $yaml YAML source + * @return array Decoded data + */ + public static function decode($yaml) + { + $lines = explode("\n", $yaml); + reset($lines); + return self::_decodeYaml(0, $lines); + } + + /** + * Service function to decode YAML + * + * @param int $currentIndent Current indent level + * @param array $lines YAML lines + * @return array|string + */ + protected static function _decodeYaml($currentIndent, &$lines) + { + $config = array(); + $inIndent = false; + while (list($n, $line) = each($lines)) { + $lineno = $n + 1; + + $line = rtrim(preg_replace("/#.*$/", "", $line)); + if (strlen($line) == 0) { + continue; + } + + $indent = strspn($line, " "); + + // line without the spaces + $line = trim($line); + if (strlen($line) == 0) { + continue; + } + + if ($indent < $currentIndent) { + // this level is done + prev($lines); + return $config; + } + + if (!$inIndent) { + $currentIndent = $indent; + $inIndent = true; + } + + if (preg_match("/(?!-)([\w\-]+):\s*(.*)/", $line, $m)) { + // key: value + if (strlen($m[2])) { + // simple key: value + $value = preg_replace("/#.*$/", "", $m[2]); + $value = self::_parseValue($value); + } else { + // key: and then values on new lines + $value = self::_decodeYaml($currentIndent + 1, $lines); + if (is_array($value) && !count($value)) { + $value = ""; + } + } + $config[$m[1]] = $value; + } elseif ($line[0] == "-") { + // item in the list: + // - FOO + if (strlen($line) > 2) { + $value = substr($line, 2); + + $config[] = self::_parseValue($value); + } else { + $config[] = self::_decodeYaml($currentIndent + 1, $lines); + } + } else { + require_once 'Zend/Config/Exception.php'; + throw new Zend_Config_Exception(sprintf( + 'Error parsing YAML at line %d - unsupported syntax: "%s"', + $lineno, $line + )); + } + } + return $config; + } + + /** + * Parse values + * + * @param string $value + * @return string + */ + protected static function _parseValue($value) + { + $value = trim($value); + + // remove quotes from string. + if ('"' == $value['0']) { + if ('"' == $value[count($value) -1]) { + $value = substr($value, 1, -1); + } + } elseif ('\'' == $value['0'] && '\'' == $value[count($value) -1]) { + $value = strtr($value, array("''" => "'", "'" => '')); + } + + // Check for booleans and constants + if (preg_match('/^(t(rue)?|on|y(es)?)$/i', $value)) { + $value = true; + } elseif (preg_match('/^(f(alse)?|off|n(o)?)$/i', $value)) { + $value = false; + } elseif (strcasecmp($value, 'null') === 0) { + $value = null; + } elseif (!self::$_ignoreConstants) { + // test for constants + $value = self::_replaceConstants($value); + } + + return $value; + } + + /** + * Replace any constants referenced in a string with their values + * + * @param string $value + * @return string + */ + protected static function _replaceConstants($value) + { + foreach (self::_getConstants() as $constant) { + if (strstr($value, $constant)) { + $value = str_replace($constant, constant($constant), $value); + } + } + return $value; + } + + /** + * Get (reverse) sorted list of defined constant names + * + * @return array + */ + protected static function _getConstants() + { + $constants = array_keys(get_defined_constants()); + rsort($constants, SORT_STRING); + return $constants; + } +} diff --git a/lib/zend/Zend/Controller/Action.php b/lib/zend/Zend/Controller/Action.php new file mode 100644 index 00000000000..9508e747119 --- /dev/null +++ b/lib/zend/Zend/Controller/Action.php @@ -0,0 +1,798 @@ +setRequest($request) + ->setResponse($response) + ->_setInvokeArgs($invokeArgs); + $this->_helper = new Zend_Controller_Action_HelperBroker($this); + $this->init(); + } + + /** + * Initialize object + * + * Called from {@link __construct()} as final step of object instantiation. + * + * @return void + */ + public function init() + { + } + + /** + * Initialize View object + * + * Initializes {@link $view} if not otherwise a Zend_View_Interface. + * + * If {@link $view} is not otherwise set, instantiates a new Zend_View + * object, using the 'views' subdirectory at the same level as the + * controller directory for the current module as the base directory. + * It uses this to set the following: + * - script path = views/scripts/ + * - helper path = views/helpers/ + * - filter path = views/filters/ + * + * @return Zend_View_Interface + * @throws Zend_Controller_Exception if base view directory does not exist + */ + public function initView() + { + if (!$this->getInvokeArg('noViewRenderer') && $this->_helper->hasHelper('viewRenderer')) { + return $this->view; + } + + require_once 'Zend/View/Interface.php'; + if (isset($this->view) && ($this->view instanceof Zend_View_Interface)) { + return $this->view; + } + + $request = $this->getRequest(); + $module = $request->getModuleName(); + $dirs = $this->getFrontController()->getControllerDirectory(); + if (empty($module) || !isset($dirs[$module])) { + $module = $this->getFrontController()->getDispatcher()->getDefaultModule(); + } + $baseDir = dirname($dirs[$module]) . DIRECTORY_SEPARATOR . 'views'; + if (!file_exists($baseDir) || !is_dir($baseDir)) { + require_once 'Zend/Controller/Exception.php'; + throw new Zend_Controller_Exception('Missing base view directory ("' . $baseDir . '")'); + } + + require_once 'Zend/View.php'; + $this->view = new Zend_View(array('basePath' => $baseDir)); + + return $this->view; + } + + /** + * Render a view + * + * Renders a view. By default, views are found in the view script path as + * /.phtml. You may change the script suffix by + * resetting {@link $viewSuffix}. You may omit the controller directory + * prefix by specifying boolean true for $noController. + * + * By default, the rendered contents are appended to the response. You may + * specify the named body content segment to set by specifying a $name. + * + * @see Zend_Controller_Response_Abstract::appendBody() + * @param string|null $action Defaults to action registered in request object + * @param string|null $name Response object named path segment to use; defaults to null + * @param bool $noController Defaults to false; i.e. use controller name as subdir in which to search for view script + * @return void + */ + public function render($action = null, $name = null, $noController = false) + { + if (!$this->getInvokeArg('noViewRenderer') && $this->_helper->hasHelper('viewRenderer')) { + return $this->_helper->viewRenderer->render($action, $name, $noController); + } + + $view = $this->initView(); + $script = $this->getViewScript($action, $noController); + + $this->getResponse()->appendBody( + $view->render($script), + $name + ); + } + + /** + * Render a given view script + * + * Similar to {@link render()}, this method renders a view script. Unlike render(), + * however, it does not autodetermine the view script via {@link getViewScript()}, + * but instead renders the script passed to it. Use this if you know the + * exact view script name and path you wish to use, or if using paths that do not + * conform to the spec defined with getViewScript(). + * + * By default, the rendered contents are appended to the response. You may + * specify the named body content segment to set by specifying a $name. + * + * @param string $script + * @param string $name + * @return void + */ + public function renderScript($script, $name = null) + { + if (!$this->getInvokeArg('noViewRenderer') && $this->_helper->hasHelper('viewRenderer')) { + return $this->_helper->viewRenderer->renderScript($script, $name); + } + + $view = $this->initView(); + $this->getResponse()->appendBody( + $view->render($script), + $name + ); + } + + /** + * Construct view script path + * + * Used by render() to determine the path to the view script. + * + * @param string $action Defaults to action registered in request object + * @param bool $noController Defaults to false; i.e. use controller name as subdir in which to search for view script + * @return string + * @throws Zend_Controller_Exception with bad $action + */ + public function getViewScript($action = null, $noController = null) + { + if (!$this->getInvokeArg('noViewRenderer') && $this->_helper->hasHelper('viewRenderer')) { + $viewRenderer = $this->_helper->getHelper('viewRenderer'); + if (null !== $noController) { + $viewRenderer->setNoController($noController); + } + return $viewRenderer->getViewScript($action); + } + + $request = $this->getRequest(); + if (null === $action) { + $action = $request->getActionName(); + } elseif (!is_string($action)) { + require_once 'Zend/Controller/Exception.php'; + throw new Zend_Controller_Exception('Invalid action specifier for view render'); + } + + if (null === $this->_delimiters) { + $dispatcher = Zend_Controller_Front::getInstance()->getDispatcher(); + $wordDelimiters = $dispatcher->getWordDelimiter(); + $pathDelimiters = $dispatcher->getPathDelimiter(); + $this->_delimiters = array_unique(array_merge($wordDelimiters, (array) $pathDelimiters)); + } + + $action = str_replace($this->_delimiters, '-', $action); + $script = $action . '.' . $this->viewSuffix; + + if (!$noController) { + $controller = $request->getControllerName(); + $controller = str_replace($this->_delimiters, '-', $controller); + $script = $controller . DIRECTORY_SEPARATOR . $script; + } + + return $script; + } + + /** + * Return the Request object + * + * @return Zend_Controller_Request_Abstract + */ + public function getRequest() + { + return $this->_request; + } + + /** + * Set the Request object + * + * @param Zend_Controller_Request_Abstract $request + * @return Zend_Controller_Action + */ + public function setRequest(Zend_Controller_Request_Abstract $request) + { + $this->_request = $request; + return $this; + } + + /** + * Return the Response object + * + * @return Zend_Controller_Response_Abstract + */ + public function getResponse() + { + return $this->_response; + } + + /** + * Set the Response object + * + * @param Zend_Controller_Response_Abstract $response + * @return Zend_Controller_Action + */ + public function setResponse(Zend_Controller_Response_Abstract $response) + { + $this->_response = $response; + return $this; + } + + /** + * Set invocation arguments + * + * @param array $args + * @return Zend_Controller_Action + */ + protected function _setInvokeArgs(array $args = array()) + { + $this->_invokeArgs = $args; + return $this; + } + + /** + * Return the array of constructor arguments (minus the Request object) + * + * @return array + */ + public function getInvokeArgs() + { + return $this->_invokeArgs; + } + + /** + * Return a single invocation argument + * + * @param string $key + * @return mixed + */ + public function getInvokeArg($key) + { + if (isset($this->_invokeArgs[$key])) { + return $this->_invokeArgs[$key]; + } + + return null; + } + + /** + * Get a helper by name + * + * @param string $helperName + * @return Zend_Controller_Action_Helper_Abstract + */ + public function getHelper($helperName) + { + return $this->_helper->{$helperName}; + } + + /** + * Get a clone of a helper by name + * + * @param string $helperName + * @return Zend_Controller_Action_Helper_Abstract + */ + public function getHelperCopy($helperName) + { + return clone $this->_helper->{$helperName}; + } + + /** + * Set the front controller instance + * + * @param Zend_Controller_Front $front + * @return Zend_Controller_Action + */ + public function setFrontController(Zend_Controller_Front $front) + { + $this->_frontController = $front; + return $this; + } + + /** + * Retrieve Front Controller + * + * @return Zend_Controller_Front + */ + public function getFrontController() + { + // Used cache version if found + if (null !== $this->_frontController) { + return $this->_frontController; + } + + // Grab singleton instance, if class has been loaded + if (class_exists('Zend_Controller_Front')) { + $this->_frontController = Zend_Controller_Front::getInstance(); + return $this->_frontController; + } + + // Throw exception in all other cases + require_once 'Zend/Controller/Exception.php'; + throw new Zend_Controller_Exception('Front controller class has not been loaded'); + } + + /** + * Pre-dispatch routines + * + * Called before action method. If using class with + * {@link Zend_Controller_Front}, it may modify the + * {@link $_request Request object} and reset its dispatched flag in order + * to skip processing the current action. + * + * @return void + */ + public function preDispatch() + { + } + + /** + * Post-dispatch routines + * + * Called after action method execution. If using class with + * {@link Zend_Controller_Front}, it may modify the + * {@link $_request Request object} and reset its dispatched flag in order + * to process an additional action. + * + * Common usages for postDispatch() include rendering content in a sitewide + * template, link url correction, setting headers, etc. + * + * @return void + */ + public function postDispatch() + { + } + + /** + * Proxy for undefined methods. Default behavior is to throw an + * exception on undefined methods, however this function can be + * overridden to implement magic (dynamic) actions, or provide run-time + * dispatching. + * + * @param string $methodName + * @param array $args + * @return void + * @throws Zend_Controller_Action_Exception + */ + public function __call($methodName, $args) + { + require_once 'Zend/Controller/Action/Exception.php'; + if ('Action' == substr($methodName, -6)) { + $action = substr($methodName, 0, strlen($methodName) - 6); + throw new Zend_Controller_Action_Exception(sprintf('Action "%s" does not exist and was not trapped in __call()', $action), 404); + } + + throw new Zend_Controller_Action_Exception(sprintf('Method "%s" does not exist and was not trapped in __call()', $methodName), 500); + } + + /** + * Dispatch the requested action + * + * @param string $action Method name of action + * @return void + */ + public function dispatch($action) + { + // Notify helpers of action preDispatch state + $this->_helper->notifyPreDispatch(); + + $this->preDispatch(); + if ($this->getRequest()->isDispatched()) { + if (null === $this->_classMethods) { + $this->_classMethods = get_class_methods($this); + } + + // If pre-dispatch hooks introduced a redirect then stop dispatch + // @see ZF-7496 + if (!($this->getResponse()->isRedirect())) { + // preDispatch() didn't change the action, so we can continue + if ($this->getInvokeArg('useCaseSensitiveActions') || in_array($action, $this->_classMethods)) { + if ($this->getInvokeArg('useCaseSensitiveActions')) { + trigger_error('Using case sensitive actions without word separators is deprecated; please do not rely on this "feature"'); + } + $this->$action(); + } else { + $this->__call($action, array()); + } + } + $this->postDispatch(); + } + + // whats actually important here is that this action controller is + // shutting down, regardless of dispatching; notify the helpers of this + // state + $this->_helper->notifyPostDispatch(); + } + + /** + * Call the action specified in the request object, and return a response + * + * Not used in the Action Controller implementation, but left for usage in + * Page Controller implementations. Dispatches a method based on the + * request. + * + * Returns a Zend_Controller_Response_Abstract object, instantiating one + * prior to execution if none exists in the controller. + * + * {@link preDispatch()} is called prior to the action, + * {@link postDispatch()} is called following it. + * + * @param null|Zend_Controller_Request_Abstract $request Optional request + * object to use + * @param null|Zend_Controller_Response_Abstract $response Optional response + * object to use + * @return Zend_Controller_Response_Abstract + */ + public function run(Zend_Controller_Request_Abstract $request = null, Zend_Controller_Response_Abstract $response = null) + { + if (null !== $request) { + $this->setRequest($request); + } else { + $request = $this->getRequest(); + } + + if (null !== $response) { + $this->setResponse($response); + } + + $action = $request->getActionName(); + if (empty($action)) { + $action = 'index'; + } + $action = $action . 'Action'; + + $request->setDispatched(true); + $this->dispatch($action); + + return $this->getResponse(); + } + + /** + * Gets a parameter from the {@link $_request Request object}. If the + * parameter does not exist, NULL will be returned. + * + * If the parameter does not exist and $default is set, then + * $default will be returned instead of NULL. + * + * @param string $paramName + * @param mixed $default + * @return mixed + */ + protected function _getParam($paramName, $default = null) + { + return $this->getParam($paramName, $default); + } + + /** + * Gets a parameter from the {@link $_request Request object}. If the + * parameter does not exist, NULL will be returned. + * + * If the parameter does not exist and $default is set, then + * $default will be returned instead of NULL. + * + * @param string $paramName + * @param mixed $default + * @return mixed + */ + public function getParam($paramName, $default = null) + { + $value = $this->getRequest()->getParam($paramName); + if ((null === $value || '' === $value) && (null !== $default)) { + $value = $default; + } + + return $value; + } + + /** + * Set a parameter in the {@link $_request Request object}. + * + * @param string $paramName + * @param mixed $value + * @return Zend_Controller_Action + * @deprecated Deprecated as of Zend Framework 1.7. Use + * setParam() instead. + */ + protected function _setParam($paramName, $value) + { + return $this->setParam($paramName, $value); + } + + /** + * Set a parameter in the {@link $_request Request object}. + * + * @param string $paramName + * @param mixed $value + * @return Zend_Controller_Action + */ + public function setParam($paramName, $value) + { + $this->getRequest()->setParam($paramName, $value); + + return $this; + } + + /** + * Determine whether a given parameter exists in the + * {@link $_request Request object}. + * + * @param string $paramName + * @return boolean + * @deprecated Deprecated as of Zend Framework 1.7. Use + * hasParam() instead. + */ + protected function _hasParam($paramName) + { + return $this->hasParam($paramName); + } + + /** + * Determine whether a given parameter exists in the + * {@link $_request Request object}. + * + * @param string $paramName + * @return boolean + */ + public function hasParam($paramName) + { + return null !== $this->getRequest()->getParam($paramName); + } + + /** + * Return all parameters in the {@link $_request Request object} + * as an associative array. + * + * @return array + * @deprecated Deprecated as of Zend Framework 1.7. Use + * getAllParams() instead. + */ + protected function _getAllParams() + { + return $this->getAllParams(); + } + + /** + * Return all parameters in the {@link $_request Request object} + * as an associative array. + * + * @return array + */ + public function getAllParams() + { + return $this->getRequest()->getParams(); + } + + + /** + * Forward to another controller/action. + * + * It is important to supply the unformatted names, i.e. "article" + * rather than "ArticleController". The dispatcher will do the + * appropriate formatting when the request is received. + * + * If only an action name is provided, forwards to that action in this + * controller. + * + * If an action and controller are specified, forwards to that action and + * controller in this module. + * + * Specifying an action, controller, and module is the most specific way to + * forward. + * + * A fourth argument, $params, will be used to set the request parameters. + * If either the controller or module are unnecessary for forwarding, + * simply pass null values for them before specifying the parameters. + * + * @param string $action + * @param string $controller + * @param string $module + * @param array $params + * @return void + * @deprecated Deprecated as of Zend Framework 1.7. Use + * forward() instead. + */ + final protected function _forward($action, $controller = null, $module = null, array $params = null) + { + $this->forward($action, $controller, $module, $params); + } + + /** + * Forward to another controller/action. + * + * It is important to supply the unformatted names, i.e. "article" + * rather than "ArticleController". The dispatcher will do the + * appropriate formatting when the request is received. + * + * If only an action name is provided, forwards to that action in this + * controller. + * + * If an action and controller are specified, forwards to that action and + * controller in this module. + * + * Specifying an action, controller, and module is the most specific way to + * forward. + * + * A fourth argument, $params, will be used to set the request parameters. + * If either the controller or module are unnecessary for forwarding, + * simply pass null values for them before specifying the parameters. + * + * @param string $action + * @param string $controller + * @param string $module + * @param array $params + * @return void + */ + final public function forward($action, $controller = null, $module = null, array $params = null) + { + $request = $this->getRequest(); + + if (null !== $params) { + $request->setParams($params); + } + + if (null !== $controller) { + $request->setControllerName($controller); + + // Module should only be reset if controller has been specified + if (null !== $module) { + $request->setModuleName($module); + } + } + + $request->setActionName($action) + ->setDispatched(false); + } + + /** + * Redirect to another URL + * + * Proxies to {@link Zend_Controller_Action_Helper_Redirector::gotoUrl()}. + * + * @param string $url + * @param array $options Options to be used when redirecting + * @return void + * @deprecated Deprecated as of Zend Framework 1.7. Use + * redirect() instead. + */ + protected function _redirect($url, array $options = array()) + { + $this->redirect($url, $options); + } + + /** + * Redirect to another URL + * + * Proxies to {@link Zend_Controller_Action_Helper_Redirector::gotoUrl()}. + * + * @param string $url + * @param array $options Options to be used when redirecting + * @return void + */ + public function redirect($url, array $options = array()) + { + $this->_helper->redirector->gotoUrl($url, $options); + } +} diff --git a/lib/zend/Zend/Controller/Action/Exception.php b/lib/zend/Zend/Controller/Action/Exception.php new file mode 100644 index 00000000000..4cd9ce2a74b --- /dev/null +++ b/lib/zend/Zend/Controller/Action/Exception.php @@ -0,0 +1,38 @@ +_actionController = $actionController; + return $this; + } + + /** + * Retrieve current action controller + * + * @return Zend_Controller_Action + */ + public function getActionController() + { + return $this->_actionController; + } + + /** + * Retrieve front controller instance + * + * @return Zend_Controller_Front + */ + public function getFrontController() + { + return Zend_Controller_Front::getInstance(); + } + + /** + * Hook into action controller initialization + * + * @return void + */ + public function init() + { + } + + /** + * Hook into action controller preDispatch() workflow + * + * @return void + */ + public function preDispatch() + { + } + + /** + * Hook into action controller postDispatch() workflow + * + * @return void + */ + public function postDispatch() + { + } + + /** + * getRequest() - + * + * @return Zend_Controller_Request_Abstract $request + */ + public function getRequest() + { + $controller = $this->getActionController(); + if (null === $controller) { + $controller = $this->getFrontController(); + } + + return $controller->getRequest(); + } + + /** + * getResponse() - + * + * @return Zend_Controller_Response_Abstract $response + */ + public function getResponse() + { + $controller = $this->getActionController(); + if (null === $controller) { + $controller = $this->getFrontController(); + } + + return $controller->getResponse(); + } + + /** + * getName() + * + * @return string + */ + public function getName() + { + $fullClassName = get_class($this); + if (strpos($fullClassName, '_') !== false) { + $helperName = strrchr($fullClassName, '_'); + return ltrim($helperName, '_'); + } elseif (strpos($fullClassName, '\\') !== false) { + $helperName = strrchr($fullClassName, '\\'); + return ltrim($helperName, '\\'); + } else { + return $fullClassName; + } + } +} diff --git a/lib/zend/Zend/Controller/Action/Helper/ActionStack.php b/lib/zend/Zend/Controller/Action/Helper/ActionStack.php new file mode 100644 index 00000000000..e22e8b8e7e4 --- /dev/null +++ b/lib/zend/Zend/Controller/Action/Helper/ActionStack.php @@ -0,0 +1,138 @@ +hasPlugin('Zend_Controller_Plugin_ActionStack')) { + /** + * @see Zend_Controller_Plugin_ActionStack + */ + require_once 'Zend/Controller/Plugin/ActionStack.php'; + $this->_actionStack = new Zend_Controller_Plugin_ActionStack(); + $front->registerPlugin($this->_actionStack, 97); + } else { + $this->_actionStack = $front->getPlugin('Zend_Controller_Plugin_ActionStack'); + } + } + + /** + * Push onto the stack + * + * @param Zend_Controller_Request_Abstract $next + * @return Zend_Controller_Action_Helper_ActionStack Provides a fluent interface + */ + public function pushStack(Zend_Controller_Request_Abstract $next) + { + $this->_actionStack->pushStack($next); + return $this; + } + + /** + * Push a new action onto the stack + * + * @param string $action + * @param string $controller + * @param string $module + * @param array $params + * @throws Zend_Controller_Action_Exception + * @return Zend_Controller_Action_Helper_ActionStack + */ + public function actionToStack($action, $controller = null, $module = null, array $params = array()) + { + if ($action instanceof Zend_Controller_Request_Abstract) { + return $this->pushStack($action); + } elseif (!is_string($action)) { + /** + * @see Zend_Controller_Action_Exception + */ + require_once 'Zend/Controller/Action/Exception.php'; + throw new Zend_Controller_Action_Exception('ActionStack requires either a request object or minimally a string action'); + } + + $request = $this->getRequest(); + + if ($request instanceof Zend_Controller_Request_Abstract === false){ + /** + * @see Zend_Controller_Action_Exception + */ + require_once 'Zend/Controller/Action/Exception.php'; + throw new Zend_Controller_Action_Exception('Request object not set yet'); + } + + $controller = (null === $controller) ? $request->getControllerName() : $controller; + $module = (null === $module) ? $request->getModuleName() : $module; + + /** + * @see Zend_Controller_Request_Simple + */ + require_once 'Zend/Controller/Request/Simple.php'; + $newRequest = new Zend_Controller_Request_Simple($action, $controller, $module, $params); + + return $this->pushStack($newRequest); + } + + /** + * Perform helper when called as $this->_helper->actionStack() from an action controller + * + * Proxies to {@link simple()} + * + * @param string $action + * @param string $controller + * @param string $module + * @param array $params + * @return boolean + */ + public function direct($action, $controller = null, $module = null, array $params = array()) + { + return $this->actionToStack($action, $controller, $module, $params); + } +} diff --git a/lib/zend/Zend/Controller/Action/Helper/AjaxContext.php b/lib/zend/Zend/Controller/Action/Helper/AjaxContext.php new file mode 100644 index 00000000000..dd4ca426d67 --- /dev/null +++ b/lib/zend/Zend/Controller/Action/Helper/AjaxContext.php @@ -0,0 +1,80 @@ +addContext('html', array('suffix' => 'ajax')); + } + + /** + * Initialize AJAX context switching + * + * Checks for XHR requests; if detected, attempts to perform context switch. + * + * @param string $format + * @return void + */ + public function initContext($format = null) + { + $this->_currentContext = null; + + $request = $this->getRequest(); + if (!method_exists($request, 'isXmlHttpRequest') || + !$this->getRequest()->isXmlHttpRequest()) + { + return; + } + + return parent::initContext($format); + } +} diff --git a/lib/zend/Zend/Controller/Action/Helper/AutoComplete/Abstract.php b/lib/zend/Zend/Controller/Action/Helper/AutoComplete/Abstract.php new file mode 100644 index 00000000000..707545434b2 --- /dev/null +++ b/lib/zend/Zend/Controller/Action/Helper/AutoComplete/Abstract.php @@ -0,0 +1,149 @@ +disableLayout(); + } + + Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer')->setNoRender(true); + + return $this; + } + + /** + * Encode data to JSON + * + * @param mixed $data + * @param bool $keepLayouts + * @throws Zend_Controller_Action_Exception + * @return string + */ + public function encodeJson($data, $keepLayouts = false) + { + if ($this->validateData($data)) { + return Zend_Controller_Action_HelperBroker::getStaticHelper('Json')->encodeJson($data, $keepLayouts); + } + + /** + * @see Zend_Controller_Action_Exception + */ + require_once 'Zend/Controller/Action/Exception.php'; + throw new Zend_Controller_Action_Exception('Invalid data passed for autocompletion'); + } + + /** + * Send autocompletion data + * + * Calls prepareAutoCompletion, populates response body with this + * information, and sends response. + * + * @param mixed $data + * @param bool $keepLayouts + * @return string|void + */ + public function sendAutoCompletion($data, $keepLayouts = false) + { + $data = $this->prepareAutoCompletion($data, $keepLayouts); + + $response = $this->getResponse(); + $response->setBody($data); + + if (!$this->suppressExit) { + $response->sendResponse(); + exit; + } + + return $data; + } + + /** + * Strategy pattern: allow calling helper as broker method + * + * Prepares autocompletion data and, if $sendNow is true, immediately sends + * response. + * + * @param mixed $data + * @param bool $sendNow + * @param bool $keepLayouts + * @return string|void + */ + public function direct($data, $sendNow = true, $keepLayouts = false) + { + if ($sendNow) { + return $this->sendAutoCompletion($data, $keepLayouts); + } + + return $this->prepareAutoCompletion($data, $keepLayouts); + } +} diff --git a/lib/zend/Zend/Controller/Action/Helper/AutoCompleteDojo.php b/lib/zend/Zend/Controller/Action/Helper/AutoCompleteDojo.php new file mode 100644 index 00000000000..9027f0f8e62 --- /dev/null +++ b/lib/zend/Zend/Controller/Action/Helper/AutoCompleteDojo.php @@ -0,0 +1,87 @@ + $value) { + $items[] = array('label' => $value, 'name' => $value); + } + $data = new Zend_Dojo_Data('name', $items); + } + + if (!$keepLayouts) { + require_once 'Zend/Controller/Action/HelperBroker.php'; + Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer')->setNoRender(true); + + require_once 'Zend/Layout.php'; + $layout = Zend_Layout::getMvcInstance(); + if ($layout instanceof Zend_Layout) { + $layout->disableLayout(); + } + } + + $response = Zend_Controller_Front::getInstance()->getResponse(); + $response->setHeader('Content-Type', 'application/json'); + + return $data->toJson(); + } +} diff --git a/lib/zend/Zend/Controller/Action/Helper/AutoCompleteScriptaculous.php b/lib/zend/Zend/Controller/Action/Helper/AutoCompleteScriptaculous.php new file mode 100644 index 00000000000..098aed8b10c --- /dev/null +++ b/lib/zend/Zend/Controller/Action/Helper/AutoCompleteScriptaculous.php @@ -0,0 +1,82 @@ +validateData($data)) { + /** + * @see Zend_Controller_Action_Exception + */ + require_once 'Zend/Controller/Action/Exception.php'; + throw new Zend_Controller_Action_Exception('Invalid data passed for autocompletion'); + } + + $data = (array) $data; + $data = '
  • ' . implode('
  • ', $data) . '
'; + + if (!$keepLayouts) { + $this->disableLayouts(); + } + + return $data; + } +} diff --git a/lib/zend/Zend/Controller/Action/Helper/Cache.php b/lib/zend/Zend/Controller/Action/Helper/Cache.php new file mode 100644 index 00000000000..61c089ff591 --- /dev/null +++ b/lib/zend/Zend/Controller/Action/Helper/Cache.php @@ -0,0 +1,289 @@ +getRequest()->getControllerName(); + $actions = array_unique($actions); + if (!isset($this->_caching[$controller])) { + $this->_caching[$controller] = array(); + } + if (!empty($tags)) { + $tags = array_unique($tags); + if (!isset($this->_tags[$controller])) { + $this->_tags[$controller] = array(); + } + } + foreach ($actions as $action) { + $this->_caching[$controller][] = $action; + if (!empty($tags)) { + $this->_tags[$controller][$action] = array(); + foreach ($tags as $tag) { + $this->_tags[$controller][$action][] = $tag; + } + } + } + if ($extension) { + if (!isset($this->_extensions[$controller])) { + $this->_extensions[$controller] = array(); + } + foreach ($actions as $action) { + $this->_extensions[$controller][$action] = $extension; + } + } + } + + /** + * Remove a specific page cache static file based on its + * relative URL from the application's public directory. + * The file extension is not required here; usually matches + * the original REQUEST_URI that was cached. + * + * @param string $relativeUrl + * @param bool $recursive + * @return mixed + */ + public function removePage($relativeUrl, $recursive = false) + { + $cache = $this->getCache(Zend_Cache_Manager::PAGECACHE); + $encodedCacheId = $this->_encodeCacheId($relativeUrl); + + if ($recursive) { + $backend = $cache->getBackend(); + if (($backend instanceof Zend_Cache_Backend) + && method_exists($backend, 'removeRecursively') + ) { + $result = $backend->removeRecursively($encodedCacheId); + if (is_null($result) ) { + $result = $backend->removeRecursively($relativeUrl); + } + return $result; + } + } + + $result = $cache->remove($encodedCacheId); + if (is_null($result) ) { + $result = $cache->remove($relativeUrl); + } + return $result; + } + + /** + * Remove a specific page cache static file based on its + * relative URL from the application's public directory. + * The file extension is not required here; usually matches + * the original REQUEST_URI that was cached. + * + * @param array $tags + * @return mixed + */ + public function removePagesTagged(array $tags) + { + return $this->getCache(Zend_Cache_Manager::PAGECACHE) + ->clean(Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG, $tags); + } + + /** + * Commence page caching for any cacheable actions + * + * @return void + */ + public function preDispatch() + { + $controller = $this->getRequest()->getControllerName(); + $action = $this->getRequest()->getActionName(); + $stats = ob_get_status(true); + foreach ($stats as $status) { + if ($status['name'] == 'Zend_Cache_Frontend_Page::_flush' + || $status['name'] == 'Zend_Cache_Frontend_Capture::_flush') { + $obStarted = true; + } + } + if (!isset($obStarted) && isset($this->_caching[$controller]) && + in_array($action, $this->_caching[$controller])) { + $reqUri = $this->getRequest()->getRequestUri(); + $tags = array(); + if (isset($this->_tags[$controller][$action]) + && !empty($this->_tags[$controller][$action])) { + $tags = array_unique($this->_tags[$controller][$action]); + } + $extension = null; + if (isset($this->_extensions[$controller][$action])) { + $extension = $this->_extensions[$controller][$action]; + } + $this->getCache(Zend_Cache_Manager::PAGECACHE) + ->start($this->_encodeCacheId($reqUri), $tags, $extension); + } + } + + /** + * Encode a Cache ID as hexadecimal. This is a workaround because Backend ID validation + * is trapped in the Frontend classes. Will try to get this reversed for ZF 2.0 + * because it's a major annoyance to have IDs so restricted! + * + * @return string + * @param string $requestUri + */ + protected function _encodeCacheId($requestUri) + { + return bin2hex($requestUri); + } + + /** + * Set an instance of the Cache Manager for this helper + * + * @param Zend_Cache_Manager $manager + * @return void + */ + public function setManager(Zend_Cache_Manager $manager) + { + $this->_manager = $manager; + return $this; + } + + /** + * Get the Cache Manager instance or instantiate the object if not + * exists. Attempts to load from bootstrap if available. + * + * @return Zend_Cache_Manager + */ + public function getManager() + { + if ($this->_manager !== null) { + return $this->_manager; + } + $front = Zend_Controller_Front::getInstance(); + if ($front->getParam('bootstrap') + && $front->getParam('bootstrap')->getResource('CacheManager')) { + return $front->getParam('bootstrap') + ->getResource('CacheManager'); + } + $this->_manager = new Zend_Cache_Manager; + return $this->_manager; + } + + /** + * Return a list of actions for the current Controller marked for + * caching + * + * @return array + */ + public function getCacheableActions() + { + return $this->_caching; + } + + /** + * Return a list of tags set for all cacheable actions + * + * @return array + */ + public function getCacheableTags() + { + return $this->_tags; + } + + /** + * Proxy non-matched methods back to Zend_Cache_Manager where + * appropriate + * + * @param string $method + * @param array $args + * @return mixed + */ + public function __call($method, $args) + { + if (method_exists($this->getManager(), $method)) { + return call_user_func_array( + array($this->getManager(), $method), $args + ); + } + throw new Zend_Controller_Action_Exception('Method does not exist:' + . $method); + } + +} diff --git a/lib/zend/Zend/Controller/Action/Helper/ContextSwitch.php b/lib/zend/Zend/Controller/Action/Helper/ContextSwitch.php new file mode 100644 index 00000000000..fe9114bc6eb --- /dev/null +++ b/lib/zend/Zend/Controller/Action/Helper/ContextSwitch.php @@ -0,0 +1,1394 @@ +setConfig($options); + } elseif (is_array($options)) { + $this->setOptions($options); + } + + if (empty($this->_contexts)) { + $this->addContexts(array( + 'json' => array( + 'suffix' => 'json', + 'headers' => array('Content-Type' => 'application/json'), + 'callbacks' => array( + 'init' => 'initJsonContext', + 'post' => 'postJsonContext' + ) + ), + 'xml' => array( + 'suffix' => 'xml', + 'headers' => array('Content-Type' => 'application/xml'), + ) + )); + } + + $this->init(); + } + + /** + * Initialize at start of action controller + * + * Reset the view script suffix to the original state, or store the + * original state. + * + * @return void + */ + public function init() + { + if (null === $this->_viewSuffixOrig) { + $this->_viewSuffixOrig = $this->_getViewRenderer()->getViewSuffix(); + } else { + $this->_getViewRenderer()->setViewSuffix($this->_viewSuffixOrig); + } + } + + /** + * Configure object from array of options + * + * @param array $options + * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface + */ + public function setOptions(array $options) + { + if (isset($options['contexts'])) { + $this->setContexts($options['contexts']); + unset($options['contexts']); + } + + foreach ($options as $key => $value) { + $method = 'set' . ucfirst($key); + if (in_array($method, $this->_unconfigurable)) { + continue; + } + + if (in_array($method, $this->_specialConfig)) { + $method = '_' . $method; + } + + if (method_exists($this, $method)) { + $this->$method($value); + } + } + return $this; + } + + /** + * Set object state from config object + * + * @param Zend_Config $config + * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface + */ + public function setConfig(Zend_Config $config) + { + return $this->setOptions($config->toArray()); + } + + /** + * Strategy pattern: return object + * + * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface + */ + public function direct() + { + return $this; + } + + /** + * Initialize context detection and switching + * + * @param mixed $format + * @throws Zend_Controller_Action_Exception + * @return void + */ + public function initContext($format = null) + { + $this->_currentContext = null; + + $controller = $this->getActionController(); + $request = $this->getRequest(); + $action = $request->getActionName(); + + // Return if no context switching enabled, or no context switching + // enabled for this action + $contexts = $this->getActionContexts($action); + if (empty($contexts)) { + return; + } + + // Return if no context parameter provided + if (!$context = $request->getParam($this->getContextParam())) { + if ($format === null) { + return; + } + $context = $format; + $format = null; + } + + // Check if context allowed by action controller + if (!$this->hasActionContext($action, $context)) { + return; + } + + // Return if invalid context parameter provided and no format or invalid + // format provided + if (!$this->hasContext($context)) { + if (empty($format) || !$this->hasContext($format)) { + + return; + } + } + + // Use provided format if passed + if (!empty($format) && $this->hasContext($format)) { + $context = $format; + } + + $suffix = $this->getSuffix($context); + + $this->_getViewRenderer()->setViewSuffix($suffix); + + $headers = $this->getHeaders($context); + if (!empty($headers)) { + $response = $this->getResponse(); + foreach ($headers as $header => $content) { + $response->setHeader($header, $content); + } + } + + if ($this->getAutoDisableLayout()) { + /** + * @see Zend_Layout + */ + require_once 'Zend/Layout.php'; + $layout = Zend_Layout::getMvcInstance(); + if (null !== $layout) { + $layout->disableLayout(); + } + } + + if (null !== ($callback = $this->getCallback($context, self::TRIGGER_INIT))) { + if (is_string($callback) && method_exists($this, $callback)) { + $this->$callback(); + } elseif (is_string($callback) && function_exists($callback)) { + $callback(); + } elseif (is_array($callback)) { + call_user_func($callback); + } else { + /** + * @see Zend_Controller_Action_Exception + */ + require_once 'Zend/Controller/Action/Exception.php'; + throw new Zend_Controller_Action_Exception(sprintf('Invalid context callback registered for context "%s"', $context)); + } + } + + $this->_currentContext = $context; + } + + /** + * JSON context extra initialization + * + * Turns off viewRenderer auto-rendering + * + * @return void + */ + public function initJsonContext() + { + if (!$this->getAutoJsonSerialization()) { + return; + } + + $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer'); + $view = $viewRenderer->view; + if ($view instanceof Zend_View_Interface) { + $viewRenderer->setNoRender(true); + } + } + + /** + * Should JSON contexts auto-serialize? + * + * @param boolean $flag + * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface + */ + public function setAutoJsonSerialization($flag) + { + $this->_autoJsonSerialization = (bool) $flag; + return $this; + } + + /** + * Get JSON context auto-serialization flag + * + * @return boolean + */ + public function getAutoJsonSerialization() + { + return $this->_autoJsonSerialization; + } + + /** + * Set suffix from array + * + * @param array $spec + * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface + */ + protected function _setSuffix(array $spec) + { + foreach ($spec as $context => $suffixInfo) { + if (!is_string($context)) { + $context = null; + } + + if (is_string($suffixInfo)) { + $this->setSuffix($context, $suffixInfo); + continue; + } elseif (is_array($suffixInfo)) { + if (isset($suffixInfo['suffix'])) { + $suffix = $suffixInfo['suffix']; + $prependViewRendererSuffix = true; + + if ((null === $context) && isset($suffixInfo['context'])) { + $context = $suffixInfo['context']; + } + + if (isset($suffixInfo['prependViewRendererSuffix'])) { + $prependViewRendererSuffix = $suffixInfo['prependViewRendererSuffix']; + } + + $this->setSuffix($context, $suffix, $prependViewRendererSuffix); + continue; + } + + $count = count($suffixInfo); + switch (true) { + case (($count < 2) && (null === $context)): + /** + * @see Zend_Controller_Action_Exception + */ + require_once 'Zend/Controller/Action/Exception.php'; + throw new Zend_Controller_Action_Exception('Invalid suffix information provided in config'); + case ($count < 2): + $suffix = array_shift($suffixInfo); + $this->setSuffix($context, $suffix); + break; + case (($count < 3) && (null === $context)): + $context = array_shift($suffixInfo); + $suffix = array_shift($suffixInfo); + $this->setSuffix($context, $suffix); + break; + case (($count == 3) && (null === $context)): + $context = array_shift($suffixInfo); + $suffix = array_shift($suffixInfo); + $prependViewRendererSuffix = array_shift($suffixInfo); + $this->setSuffix($context, $suffix, $prependViewRendererSuffix); + break; + case ($count >= 2): + $suffix = array_shift($suffixInfo); + $prependViewRendererSuffix = array_shift($suffixInfo); + $this->setSuffix($context, $suffix, $prependViewRendererSuffix); + break; + } + } + } + return $this; + } + + /** + * Customize view script suffix to use when switching context. + * + * Passing an empty suffix value to the setters disables the view script + * suffix change. + * + * @param string $context Context type for which to set suffix + * @param string $suffix Suffix to use + * @param boolean $prependViewRendererSuffix Whether or not to prepend the new suffix to the viewrenderer suffix + * @throws Zend_Controller_Action_Exception + * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface + */ + public function setSuffix($context, $suffix, $prependViewRendererSuffix = true) + { + if (!isset($this->_contexts[$context])) { + /** + * @see Zend_Controller_Action_Exception + */ + require_once 'Zend/Controller/Action/Exception.php'; + throw new Zend_Controller_Action_Exception(sprintf('Cannot set suffix; invalid context type "%s"', $context)); + } + + if (empty($suffix)) { + $suffix = ''; + } + + if (is_array($suffix)) { + if (isset($suffix['prependViewRendererSuffix'])) { + $prependViewRendererSuffix = $suffix['prependViewRendererSuffix']; + } + if (isset($suffix['suffix'])) { + $suffix = $suffix['suffix']; + } else { + $suffix = ''; + } + } + + $suffix = (string) $suffix; + + if ($prependViewRendererSuffix) { + if (empty($suffix)) { + $suffix = $this->_getViewRenderer()->getViewSuffix(); + } else { + $suffix .= '.' . $this->_getViewRenderer()->getViewSuffix(); + } + } + + $this->_contexts[$context]['suffix'] = $suffix; + return $this; + } + + /** + * Retrieve suffix for given context type + * + * @param string $type Context type + * @throws Zend_Controller_Action_Exception + * @return string + */ + public function getSuffix($type) + { + if (!isset($this->_contexts[$type])) { + /** + * @see Zend_Controller_Action_Exception + */ + require_once 'Zend/Controller/Action/Exception.php'; + throw new Zend_Controller_Action_Exception(sprintf('Cannot retrieve suffix; invalid context type "%s"', $type)); + } + + return $this->_contexts[$type]['suffix']; + } + + /** + * Does the given context exist? + * + * @param string $context + * @param boolean $throwException + * @throws Zend_Controller_Action_Exception if context does not exist and throwException is true + * @return bool + */ + public function hasContext($context, $throwException = false) + { + if (is_string($context)) { + if (isset($this->_contexts[$context])) { + return true; + } + } elseif (is_array($context)) { + $error = false; + foreach ($context as $test) { + if (!isset($this->_contexts[$test])) { + $error = (string) $test; + break; + } + } + if (false === $error) { + return true; + } + $context = $error; + } elseif (true === $context) { + return true; + } + + if ($throwException) { + /** + * @see Zend_Controller_Action_Exception + */ + require_once 'Zend/Controller/Action/Exception.php'; + throw new Zend_Controller_Action_Exception(sprintf('Context "%s" does not exist', $context)); + } + + return false; + } + + /** + * Add header to context + * + * @param string $context + * @param string $header + * @param string $content + * @throws Zend_Controller_Action_Exception + * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface + */ + public function addHeader($context, $header, $content) + { + $context = (string) $context; + $this->hasContext($context, true); + + $header = (string) $header; + $content = (string) $content; + + if (isset($this->_contexts[$context]['headers'][$header])) { + /** + * @see Zend_Controller_Action_Exception + */ + require_once 'Zend/Controller/Action/Exception.php'; + throw new Zend_Controller_Action_Exception(sprintf('Cannot add "%s" header to context "%s": already exists', $header, $context)); + } + + $this->_contexts[$context]['headers'][$header] = $content; + return $this; + } + + /** + * Customize response header to use when switching context + * + * Passing an empty header value to the setters disables the response + * header. + * + * @param string $type Context type for which to set suffix + * @param string $header Header to set + * @param string $content Header content + * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface + */ + public function setHeader($context, $header, $content) + { + $this->hasContext($context, true); + $context = (string) $context; + $header = (string) $header; + $content = (string) $content; + + $this->_contexts[$context]['headers'][$header] = $content; + return $this; + } + + /** + * Add multiple headers at once for a given context + * + * @param string $context + * @param array $headers + * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface + */ + public function addHeaders($context, array $headers) + { + foreach ($headers as $header => $content) { + $this->addHeader($context, $header, $content); + } + + return $this; + } + + /** + * Set headers from context => headers pairs + * + * @param array $options + * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface + */ + protected function _setHeaders(array $options) + { + foreach ($options as $context => $headers) { + if (!is_array($headers)) { + continue; + } + $this->setHeaders($context, $headers); + } + + return $this; + } + + /** + * Set multiple headers at once for a given context + * + * @param string $context + * @param array $headers + * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface + */ + public function setHeaders($context, array $headers) + { + $this->clearHeaders($context); + foreach ($headers as $header => $content) { + $this->setHeader($context, $header, $content); + } + + return $this; + } + + /** + * Retrieve context header + * + * Returns the value of a given header for a given context type + * + * @param string $context + * @param string $header + * @return string|null + */ + public function getHeader($context, $header) + { + $this->hasContext($context, true); + $context = (string) $context; + $header = (string) $header; + if (isset($this->_contexts[$context]['headers'][$header])) { + return $this->_contexts[$context]['headers'][$header]; + } + + return null; + } + + /** + * Retrieve context headers + * + * Returns all headers for a context as key/value pairs + * + * @param string $context + * @return array + */ + public function getHeaders($context) + { + $this->hasContext($context, true); + $context = (string) $context; + return $this->_contexts[$context]['headers']; + } + + /** + * Remove a single header from a context + * + * @param string $context + * @param string $header + * @return boolean + */ + public function removeHeader($context, $header) + { + $this->hasContext($context, true); + $context = (string) $context; + $header = (string) $header; + if (isset($this->_contexts[$context]['headers'][$header])) { + unset($this->_contexts[$context]['headers'][$header]); + return true; + } + + return false; + } + + /** + * Clear all headers for a given context + * + * @param string $context + * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface + */ + public function clearHeaders($context) + { + $this->hasContext($context, true); + $context = (string) $context; + $this->_contexts[$context]['headers'] = array(); + return $this; + } + + /** + * Validate trigger and return in normalized form + * + * @param string $trigger + * @throws Zend_Controller_Action_Exception + * @return string + */ + protected function _validateTrigger($trigger) + { + $trigger = strtoupper($trigger); + if ('TRIGGER_' !== substr($trigger, 0, 8)) { + $trigger = 'TRIGGER_' . $trigger; + } + + if (!in_array($trigger, array(self::TRIGGER_INIT, self::TRIGGER_POST))) { + /** + * @see Zend_Controller_Action_Exception + */ + require_once 'Zend/Controller/Action/Exception.php'; + throw new Zend_Controller_Action_Exception(sprintf('Invalid trigger "%s"', $trigger)); + } + + return $trigger; + } + + /** + * Set a callback for a given context and trigger + * + * @param string $context + * @param string $trigger + * @param string|array $callback + * @throws Zend_Controller_Action_Exception + * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface + */ + public function setCallback($context, $trigger, $callback) + { + $this->hasContext($context, true); + $trigger = $this->_validateTrigger($trigger); + + if (!is_string($callback)) { + if (!is_array($callback) || (2 != count($callback))) { + /** + * @see Zend_Controller_Action_Exception + */ + require_once 'Zend/Controller/Action/Exception.php'; + throw new Zend_Controller_Action_Exception('Invalid callback specified'); + } + } + + $this->_contexts[$context]['callbacks'][$trigger] = $callback; + return $this; + } + + /** + * Set callbacks from array of context => callbacks pairs + * + * @param array $options + * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface + */ + protected function _setCallbacks(array $options) + { + foreach ($options as $context => $callbacks) { + if (!is_array($callbacks)) { + continue; + } + + $this->setCallbacks($context, $callbacks); + } + return $this; + } + + /** + * Set callbacks for a given context + * + * Callbacks should be in trigger/callback pairs. + * + * @param string $context + * @param array $callbacks + * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface + */ + public function setCallbacks($context, array $callbacks) + { + $this->hasContext($context, true); + $context = (string) $context; + if (!isset($this->_contexts[$context]['callbacks'])) { + $this->_contexts[$context]['callbacks'] = array(); + } + + foreach ($callbacks as $trigger => $callback) { + $this->setCallback($context, $trigger, $callback); + } + return $this; + } + + /** + * Get a single callback for a given context and trigger + * + * @param string $context + * @param string $trigger + * @return string|array|null + */ + public function getCallback($context, $trigger) + { + $this->hasContext($context, true); + $trigger = $this->_validateTrigger($trigger); + if (isset($this->_contexts[$context]['callbacks'][$trigger])) { + return $this->_contexts[$context]['callbacks'][$trigger]; + } + + return null; + } + + /** + * Get all callbacks for a given context + * + * @param string $context + * @return array + */ + public function getCallbacks($context) + { + $this->hasContext($context, true); + return $this->_contexts[$context]['callbacks']; + } + + /** + * Clear a callback for a given context and trigger + * + * @param string $context + * @param string $trigger + * @return boolean + */ + public function removeCallback($context, $trigger) + { + $this->hasContext($context, true); + $trigger = $this->_validateTrigger($trigger); + if (isset($this->_contexts[$context]['callbacks'][$trigger])) { + unset($this->_contexts[$context]['callbacks'][$trigger]); + return true; + } + + return false; + } + + /** + * Clear all callbacks for a given context + * + * @param string $context + * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface + */ + public function clearCallbacks($context) + { + $this->hasContext($context, true); + $this->_contexts[$context]['callbacks'] = array(); + return $this; + } + + /** + * Set name of parameter to use when determining context format + * + * @param string $name + * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface + */ + public function setContextParam($name) + { + $this->_contextParam = (string) $name; + return $this; + } + + /** + * Return context format request parameter name + * + * @return string + */ + public function getContextParam() + { + return $this->_contextParam; + } + + /** + * Indicate default context to use when no context format provided + * + * @param string $type + * @throws Zend_Controller_Action_Exception + * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface + */ + public function setDefaultContext($type) + { + if (!isset($this->_contexts[$type])) { + /** + * @see Zend_Controller_Action_Exception + */ + require_once 'Zend/Controller/Action/Exception.php'; + throw new Zend_Controller_Action_Exception(sprintf('Cannot set default context; invalid context type "%s"', $type)); + } + + $this->_defaultContext = $type; + return $this; + } + + /** + * Return default context + * + * @return string + */ + public function getDefaultContext() + { + return $this->_defaultContext; + } + + /** + * Set flag indicating if layout should be disabled + * + * @param boolean $flag + * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface + */ + public function setAutoDisableLayout($flag) + { + $this->_disableLayout = ($flag) ? true : false; + return $this; + } + + /** + * Retrieve auto layout disable flag + * + * @return boolean + */ + public function getAutoDisableLayout() + { + return $this->_disableLayout; + } + + /** + * Add new context + * + * @param string $context Context type + * @param array $spec Context specification + * @throws Zend_Controller_Action_Exception + * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface + */ + public function addContext($context, array $spec) + { + if ($this->hasContext($context)) { + /** + * @see Zend_Controller_Action_Exception + */ + require_once 'Zend/Controller/Action/Exception.php'; + throw new Zend_Controller_Action_Exception(sprintf('Cannot add context "%s"; already exists', $context)); + } + $context = (string) $context; + + $this->_contexts[$context] = array(); + + $this->setSuffix($context, (isset($spec['suffix']) ? $spec['suffix'] : '')) + ->setHeaders($context, (isset($spec['headers']) ? $spec['headers'] : array())) + ->setCallbacks($context, (isset($spec['callbacks']) ? $spec['callbacks'] : array())); + return $this; + } + + /** + * Overwrite existing context + * + * @param string $context Context type + * @param array $spec Context specification + * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface + */ + public function setContext($context, array $spec) + { + $this->removeContext($context); + return $this->addContext($context, $spec); + } + + /** + * Add multiple contexts + * + * @param array $contexts + * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface + */ + public function addContexts(array $contexts) + { + foreach ($contexts as $context => $spec) { + $this->addContext($context, $spec); + } + return $this; + } + + /** + * Set multiple contexts, after first removing all + * + * @param array $contexts + * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface + */ + public function setContexts(array $contexts) + { + $this->clearContexts(); + foreach ($contexts as $context => $spec) { + $this->addContext($context, $spec); + } + return $this; + } + + /** + * Retrieve context specification + * + * @param string $context + * @return array|null + */ + public function getContext($context) + { + if ($this->hasContext($context)) { + return $this->_contexts[(string) $context]; + } + return null; + } + + /** + * Retrieve context definitions + * + * @return array + */ + public function getContexts() + { + return $this->_contexts; + } + + /** + * Remove a context + * + * @param string $context + * @return boolean + */ + public function removeContext($context) + { + if ($this->hasContext($context)) { + unset($this->_contexts[(string) $context]); + return true; + } + return false; + } + + /** + * Remove all contexts + * + * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface + */ + public function clearContexts() + { + $this->_contexts = array(); + return $this; + } + + /** + * Return current context, if any + * + * @return null|string + */ + public function getCurrentContext() + { + return $this->_currentContext; + } + + /** + * Post dispatch processing + * + * Execute postDispatch callback for current context, if available + * + * @throws Zend_Controller_Action_Exception + * @return void + */ + public function postDispatch() + { + $context = $this->getCurrentContext(); + if (null !== $context) { + if (null !== ($callback = $this->getCallback($context, self::TRIGGER_POST))) { + if (is_string($callback) && method_exists($this, $callback)) { + $this->$callback(); + } elseif (is_string($callback) && function_exists($callback)) { + $callback(); + } elseif (is_array($callback)) { + call_user_func($callback); + } else { + /** + * @see Zend_Controller_Action_Exception + */ + require_once 'Zend/Controller/Action/Exception.php'; + throw new Zend_Controller_Action_Exception(sprintf('Invalid postDispatch context callback registered for context "%s"', $context)); + } + } + } + } + + /** + * JSON post processing + * + * JSON serialize view variables to response body + * + * @return void + */ + public function postJsonContext() + { + if (!$this->getAutoJsonSerialization()) { + return; + } + + $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer'); + $view = $viewRenderer->view; + if ($view instanceof Zend_View_Interface) { + /** + * @see Zend_Json + */ + if(method_exists($view, 'getVars')) { + require_once 'Zend/Json.php'; + $vars = Zend_Json::encode($view->getVars()); + $this->getResponse()->setBody($vars); + } else { + require_once 'Zend/Controller/Action/Exception.php'; + throw new Zend_Controller_Action_Exception('View does not implement the getVars() method needed to encode the view into JSON'); + } + } + } + + /** + * Add one or more contexts to an action + * + * @param string $action + * @param string|array $context + * @return Zend_Controller_Action_Helper_ContextSwitch|void Provides a fluent interface + */ + public function addActionContext($action, $context) + { + $this->hasContext($context, true); + $controller = $this->getActionController(); + if (null === $controller) { + return; + } + $action = (string) $action; + $contextKey = $this->_contextKey; + + if (!isset($controller->$contextKey)) { + $controller->$contextKey = array(); + } + + if (true === $context) { + $contexts = $this->getContexts(); + $controller->{$contextKey}[$action] = array_keys($contexts); + return $this; + } + + $context = (array) $context; + if (!isset($controller->{$contextKey}[$action])) { + $controller->{$contextKey}[$action] = $context; + } else { + $controller->{$contextKey}[$action] = array_merge( + $controller->{$contextKey}[$action], + $context + ); + } + + return $this; + } + + /** + * Set a context as available for a given controller action + * + * @param string $action + * @param string|array $context + * @return Zend_Controller_Action_Helper_ContextSwitch|void Provides a fluent interface + */ + public function setActionContext($action, $context) + { + $this->hasContext($context, true); + $controller = $this->getActionController(); + if (null === $controller) { + return; + } + $action = (string) $action; + $contextKey = $this->_contextKey; + + if (!isset($controller->$contextKey)) { + $controller->$contextKey = array(); + } + + if (true === $context) { + $contexts = $this->getContexts(); + $controller->{$contextKey}[$action] = array_keys($contexts); + } else { + $controller->{$contextKey}[$action] = (array) $context; + } + + return $this; + } + + /** + * Add multiple action/context pairs at once + * + * @param array $contexts + * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface + */ + public function addActionContexts(array $contexts) + { + foreach ($contexts as $action => $context) { + $this->addActionContext($action, $context); + } + return $this; + } + + /** + * Overwrite and set multiple action contexts at once + * + * @param array $contexts + * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface + */ + public function setActionContexts(array $contexts) + { + foreach ($contexts as $action => $context) { + $this->setActionContext($action, $context); + } + return $this; + } + + /** + * Does a particular controller action have the given context(s)? + * + * @param string $action + * @param string|array $context + * @throws Zend_Controller_Action_Exception + * @return boolean + */ + public function hasActionContext($action, $context) + { + $this->hasContext($context, true); + $controller = $this->getActionController(); + if (null === $controller) { + return false; + } + $action = (string) $action; + $contextKey = $this->_contextKey; + + if (!isset($controller->{$contextKey})) { + return false; + } + + $allContexts = $controller->{$contextKey}; + + if (!is_array($allContexts)) { + /** + * @see Zend_Controller_Action_Exception + */ + require_once 'Zend/Controller/Action/Exception.php'; + throw new Zend_Controller_Action_Exception("Invalid contexts found for controller"); + } + + if (!isset($allContexts[$action])) { + return false; + } + + if (true === $allContexts[$action]) { + return true; + } + + $contexts = $allContexts[$action]; + + if (!is_array($contexts)) { + /** + * @see Zend_Controller_Action_Exception + */ + require_once 'Zend/Controller/Action/Exception.php'; + throw new Zend_Controller_Action_Exception(sprintf("Invalid contexts found for action '%s'", $action)); + } + + if (is_string($context) && in_array($context, $contexts)) { + return true; + } elseif (is_array($context)) { + $found = true; + foreach ($context as $test) { + if (!in_array($test, $contexts)) { + $found = false; + break; + } + } + return $found; + } + + return false; + } + + /** + * Get contexts for a given action or all actions in the controller + * + * @param string $action + * @return array + */ + public function getActionContexts($action = null) + { + $controller = $this->getActionController(); + if (null === $controller) { + return array(); + } + $contextKey = $this->_contextKey; + + if (!isset($controller->$contextKey)) { + return array(); + } + + if (null !== $action) { + $action = (string) $action; + if (isset($controller->{$contextKey}[$action])) { + return $controller->{$contextKey}[$action]; + } else { + return array(); + } + } + + return $controller->$contextKey; + } + + /** + * Remove one or more contexts for a given controller action + * + * @param string $action + * @param string|array $context + * @return boolean + */ + public function removeActionContext($action, $context) + { + if ($this->hasActionContext($action, $context)) { + $controller = $this->getActionController(); + $contextKey = $this->_contextKey; + $action = (string) $action; + $contexts = $controller->$contextKey; + $actionContexts = $contexts[$action]; + $contexts = (array) $context; + foreach ($contexts as $context) { + $index = array_search($context, $actionContexts); + if (false !== $index) { + unset($controller->{$contextKey}[$action][$index]); + } + } + return true; + } + return false; + } + + /** + * Clear all contexts for a given controller action or all actions + * + * @param string $action + * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface + */ + public function clearActionContexts($action = null) + { + $controller = $this->getActionController(); + $contextKey = $this->_contextKey; + + if (!isset($controller->$contextKey) || empty($controller->$contextKey)) { + return $this; + } + + if (null === $action) { + $controller->$contextKey = array(); + return $this; + } + + $action = (string) $action; + if (isset($controller->{$contextKey}[$action])) { + unset($controller->{$contextKey}[$action]); + } + + return $this; + } + + /** + * Retrieve ViewRenderer + * + * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface + */ + protected function _getViewRenderer() + { + if (null === $this->_viewRenderer) { + $this->_viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer'); + } + + return $this->_viewRenderer; + } +} + diff --git a/lib/zend/Zend/Controller/Action/Helper/FlashMessenger.php b/lib/zend/Zend/Controller/Action/Helper/FlashMessenger.php new file mode 100644 index 00000000000..57fe9ecdeeb --- /dev/null +++ b/lib/zend/Zend/Controller/Action/Helper/FlashMessenger.php @@ -0,0 +1,313 @@ +getName()); + foreach (self::$_session as $namespace => $messages) { + self::$_messages[$namespace] = $messages; + unset(self::$_session->{$namespace}); + } + } + } + + /** + * postDispatch() - runs after action is dispatched, in this + * case, it is resetting the namespace in case we have forwarded to a different + * action, Flashmessage will be 'clean' (default namespace) + * + * @return Zend_Controller_Action_Helper_FlashMessenger Provides a fluent interface + */ + public function postDispatch() + { + $this->resetNamespace(); + return $this; + } + + /** + * setNamespace() - change the namespace messages are added to, useful for + * per action controller messaging between requests + * + * @param string $namespace + * @return Zend_Controller_Action_Helper_FlashMessenger Provides a fluent interface + */ + public function setNamespace($namespace = 'default') + { + $this->_namespace = $namespace; + return $this; + } + + /** + * getNamespace() - return the current namepsace + * + * @return string + */ + public function getNamespace() + { + return $this->_namespace; + } + + /** + * resetNamespace() - reset the namespace to the default + * + * @return Zend_Controller_Action_Helper_FlashMessenger Provides a fluent interface + */ + public function resetNamespace() + { + $this->setNamespace(); + return $this; + } + + /** + * addMessage() - Add a message to flash message + * + * @param string $message + * @return Zend_Controller_Action_Helper_FlashMessenger Provides a fluent interface + */ + public function addMessage($message, $namespace = null) + { + if (!is_string($namespace) || $namespace == '') { + $namespace = $this->getNamespace(); + } + + if (self::$_messageAdded === false) { + self::$_session->setExpirationHops(1, null, true); + } + + if (!is_array(self::$_session->{$namespace})) { + self::$_session->{$namespace} = array(); + } + + self::$_session->{$namespace}[] = $message; + self::$_messageAdded = true; + + return $this; + } + + /** + * hasMessages() - Wether a specific namespace has messages + * + * @return boolean + */ + public function hasMessages($namespace = null) + { + if (!is_string($namespace) || $namespace == '') { + $namespace = $this->getNamespace(); + } + + return isset(self::$_messages[$namespace]); + } + + /** + * getMessages() - Get messages from a specific namespace + * + * @return array + */ + public function getMessages($namespace = null) + { + if (!is_string($namespace) || $namespace == '') { + $namespace = $this->getNamespace(); + } + + if ($this->hasMessages($namespace)) { + return self::$_messages[$namespace]; + } + + return array(); + } + + /** + * Clear all messages from the previous request & current namespace + * + * @return boolean True if messages were cleared, false if none existed + */ + public function clearMessages($namespace = null) + { + if (!is_string($namespace) || $namespace == '') { + $namespace = $this->getNamespace(); + } + + if ($this->hasMessages($namespace)) { + unset(self::$_messages[$namespace]); + return true; + } + + return false; + } + + /** + * hasCurrentMessages() - check to see if messages have been added to current + * namespace within this request + * + * @return boolean + */ + public function hasCurrentMessages($namespace = null) + { + if (!is_string($namespace) || $namespace == '') { + $namespace = $this->getNamespace(); + } + + return isset(self::$_session->{$namespace}); + } + + /** + * getCurrentMessages() - get messages that have been added to the current + * namespace within this request + * + * @return array + */ + public function getCurrentMessages($namespace = null) + { + if (!is_string($namespace) || $namespace == '') { + $namespace = $this->getNamespace(); + } + + if ($this->hasCurrentMessages($namespace)) { + return self::$_session->{$namespace}; + } + + return array(); + } + + /** + * clear messages from the current request & current namespace + * + * @return boolean + */ + public function clearCurrentMessages($namespace = null) + { + if (!is_string($namespace) || $namespace == '') { + $namespace = $this->getNamespace(); + } + + if ($this->hasCurrentMessages($namespace)) { + unset(self::$_session->{$namespace}); + return true; + } + + return false; + } + + /** + * getIterator() - complete the IteratorAggregate interface, for iterating + * + * @return ArrayObject + */ + public function getIterator($namespace = null) + { + if (!is_string($namespace) || $namespace == '') { + $namespace = $this->getNamespace(); + } + + if ($this->hasMessages($namespace)) { + return new ArrayObject($this->getMessages($namespace)); + } + + return new ArrayObject(); + } + + /** + * count() - Complete the countable interface + * + * @return int + */ + public function count($namespace = null) + { + if (!is_string($namespace) || $namespace == '') { + $namespace = $this->getNamespace(); + } + + if ($this->hasMessages($namespace)) { + return count($this->getMessages($namespace)); + } + + return 0; + } + + /** + * Strategy pattern: proxy to addMessage() + * + * @param string $message + * @return void + */ + public function direct($message, $namespace=NULL) + { + return $this->addMessage($message, $namespace); + } +} diff --git a/lib/zend/Zend/Controller/Action/Helper/Json.php b/lib/zend/Zend/Controller/Action/Helper/Json.php new file mode 100644 index 00000000000..86a8b113c17 --- /dev/null +++ b/lib/zend/Zend/Controller/Action/Helper/Json.php @@ -0,0 +1,133 @@ +true|false + * if $keepLayouts and parmas for Zend_Json::encode are required + * then, the array can contains a 'keepLayout'=>true|false and/or 'encodeData'=>true|false + * that will not be passed to Zend_Json::encode method but will be passed + * to Zend_View_Helper_Json + * @throws Zend_Controller_Action_Helper_Json + * @return string + */ + public function encodeJson($data, $keepLayouts = false, $encodeData = true) + { + /** + * @see Zend_View_Helper_Json + */ + require_once 'Zend/View/Helper/Json.php'; + $jsonHelper = new Zend_View_Helper_Json(); + $data = $jsonHelper->json($data, $keepLayouts, $encodeData); + + if (!$keepLayouts) { + /** + * @see Zend_Controller_Action_HelperBroker + */ + require_once 'Zend/Controller/Action/HelperBroker.php'; + Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer')->setNoRender(true); + } + + return $data; + } + + /** + * Encode JSON response and immediately send + * + * @param mixed $data + * @param boolean|array $keepLayouts + * @param $encodeData Encode $data as JSON? + * NOTE: if boolean, establish $keepLayouts to true|false + * if array, admit params for Zend_Json::encode as enableJsonExprFinder=>true|false + * if $keepLayouts and parmas for Zend_Json::encode are required + * then, the array can contains a 'keepLayout'=>true|false and/or 'encodeData'=>true|false + * that will not be passed to Zend_Json::encode method but will be passed + * to Zend_View_Helper_Json + * @return string|void + */ + public function sendJson($data, $keepLayouts = false, $encodeData = true) + { + $data = $this->encodeJson($data, $keepLayouts, $encodeData); + $response = $this->getResponse(); + $response->setBody($data); + + if (!$this->suppressExit) { + $response->sendResponse(); + exit; + } + + return $data; + } + + /** + * Strategy pattern: call helper as helper broker method + * + * Allows encoding JSON. If $sendNow is true, immediately sends JSON + * response. + * + * @param mixed $data + * @param boolean $sendNow + * @param boolean $keepLayouts + * @param boolean $encodeData Encode $data as JSON? + * @return string|void + */ + public function direct($data, $sendNow = true, $keepLayouts = false, $encodeData = true) + { + if ($sendNow) { + return $this->sendJson($data, $keepLayouts, $encodeData); + } + return $this->encodeJson($data, $keepLayouts, $encodeData); + } +} diff --git a/lib/zend/Zend/Controller/Action/Helper/Redirector.php b/lib/zend/Zend/Controller/Action/Helper/Redirector.php new file mode 100644 index 00000000000..8c81646224d --- /dev/null +++ b/lib/zend/Zend/Controller/Action/Helper/Redirector.php @@ -0,0 +1,534 @@ +_code; + } + + /** + * Validate HTTP status redirect code + * + * @param int $code + * @throws Zend_Controller_Action_Exception on invalid HTTP status code + * @return true + */ + protected function _checkCode($code) + { + $code = (int)$code; + if ((300 > $code) || (307 < $code) || (304 == $code) || (306 == $code)) { + require_once 'Zend/Controller/Action/Exception.php'; + throw new Zend_Controller_Action_Exception('Invalid redirect HTTP status code (' . $code . ')'); + } + + return true; + } + + /** + * Set HTTP status code for {@link _redirect()} behaviour + * + * @param int $code + * @return Zend_Controller_Action_Helper_Redirector Provides a fluent interface + */ + public function setCode($code) + { + $this->_checkCode($code); + $this->_code = $code; + return $this; + } + + /** + * Retrieve flag for whether or not {@link _redirect()} will exit when finished. + * + * @return boolean + */ + public function getExit() + { + return $this->_exit; + } + + /** + * Set exit flag for {@link _redirect()} behaviour + * + * @param boolean $flag + * @return Zend_Controller_Action_Helper_Redirector Provides a fluent interface + */ + public function setExit($flag) + { + $this->_exit = ($flag) ? true : false; + return $this; + } + + /** + * Retrieve flag for whether or not {@link _redirect()} will prepend the + * base URL on relative URLs + * + * @return boolean + */ + public function getPrependBase() + { + return $this->_prependBase; + } + + /** + * Set 'prepend base' flag for {@link _redirect()} behaviour + * + * @param boolean $flag + * @return Zend_Controller_Action_Helper_Redirector Provides a fluent interface + */ + public function setPrependBase($flag) + { + $this->_prependBase = ($flag) ? true : false; + return $this; + } + + /** + * Retrieve flag for whether or not {@link redirectAndExit()} shall close the session before + * exiting. + * + * @return boolean + */ + public function getCloseSessionOnExit() + { + return $this->_closeSessionOnExit; + } + + /** + * Set flag for whether or not {@link redirectAndExit()} shall close the session before exiting. + * + * @param boolean $flag + * @return Zend_Controller_Action_Helper_Redirector Provides a fluent interface + */ + public function setCloseSessionOnExit($flag) + { + $this->_closeSessionOnExit = ($flag) ? true : false; + return $this; + } + + /** + * Return use absolute URI flag + * + * @return boolean + */ + public function getUseAbsoluteUri() + { + return $this->_useAbsoluteUri; + } + + /** + * Set use absolute URI flag + * + * @param boolean $flag + * @return Zend_Controller_Action_Helper_Redirector Provides a fluent interface + */ + public function setUseAbsoluteUri($flag = true) + { + $this->_useAbsoluteUri = ($flag) ? true : false; + return $this; + } + + /** + * Set redirect in response object + * + * @return void + */ + protected function _redirect($url) + { + if ($this->getUseAbsoluteUri() && !preg_match('#^(https?|ftp)://#', $url)) { + $host = (isset($_SERVER['HTTP_HOST'])?$_SERVER['HTTP_HOST']:''); + $proto = (isset($_SERVER['HTTPS'])&&$_SERVER['HTTPS']!=="off") ? 'https' : 'http'; + $port = (isset($_SERVER['SERVER_PORT'])?$_SERVER['SERVER_PORT']:80); + $uri = $proto . '://' . $host; + if ((('http' == $proto) && (80 != $port)) || (('https' == $proto) && (443 != $port))) { + // do not append if HTTP_HOST already contains port + if (strrchr($host, ':') === false) { + $uri .= ':' . $port; + } + } + $url = $uri . '/' . ltrim($url, '/'); + } + $this->_redirectUrl = $url; + $this->getResponse()->setRedirect($url, $this->getCode()); + } + + /** + * Retrieve currently set URL for redirect + * + * @return string + */ + public function getRedirectUrl() + { + return $this->_redirectUrl; + } + + /** + * Determine if the baseUrl should be prepended, and prepend if necessary + * + * @param string $url + * @return string + */ + protected function _prependBase($url) + { + if ($this->getPrependBase()) { + $request = $this->getRequest(); + if ($request instanceof Zend_Controller_Request_Http) { + $base = rtrim($request->getBaseUrl(), '/'); + if (!empty($base) && ('/' != $base)) { + $url = $base . '/' . ltrim($url, '/'); + } else { + $url = '/' . ltrim($url, '/'); + } + } + } + + return $url; + } + + /** + * Set a redirect URL of the form /module/controller/action/params + * + * @param string $action + * @param string $controller + * @param string $module + * @param array $params + * @return void + */ + public function setGotoSimple($action, $controller = null, $module = null, array $params = array()) + { + $dispatcher = $this->getFrontController()->getDispatcher(); + $request = $this->getRequest(); + $curModule = $request->getModuleName(); + $useDefaultController = false; + + if (null === $controller && null !== $module) { + $useDefaultController = true; + } + + if (null === $module) { + $module = $curModule; + } + + if ($module == $dispatcher->getDefaultModule()) { + $module = ''; + } + + if (null === $controller && !$useDefaultController) { + $controller = $request->getControllerName(); + if (empty($controller)) { + $controller = $dispatcher->getDefaultControllerName(); + } + } + + $params[$request->getModuleKey()] = $module; + $params[$request->getControllerKey()] = $controller; + $params[$request->getActionKey()] = $action; + + $router = $this->getFrontController()->getRouter(); + $url = $router->assemble($params, 'default', true); + + $this->_redirect($url); + } + + /** + * Build a URL based on a route + * + * @param array $urlOptions + * @param string $name Route name + * @param boolean $reset + * @param boolean $encode + * @return void + */ + public function setGotoRoute(array $urlOptions = array(), $name = null, $reset = false, $encode = true) + { + $router = $this->getFrontController()->getRouter(); + $url = $router->assemble($urlOptions, $name, $reset, $encode); + + $this->_redirect($url); + } + + /** + * Set a redirect URL string + * + * By default, emits a 302 HTTP status header, prepends base URL as defined + * in request object if url is relative, and halts script execution by + * calling exit(). + * + * $options is an optional associative array that can be used to control + * redirect behaviour. The available option keys are: + * - exit: boolean flag indicating whether or not to halt script execution when done + * - prependBase: boolean flag indicating whether or not to prepend the base URL when a relative URL is provided + * - code: integer HTTP status code to use with redirect. Should be between 300 and 307. + * + * _redirect() sets the Location header in the response object. If you set + * the exit flag to false, you can override this header later in code + * execution. + * + * If the exit flag is true (true by default), _redirect() will write and + * close the current session, if any. + * + * @param string $url + * @param array $options + * @return void + */ + public function setGotoUrl($url, array $options = array()) + { + // prevent header injections + $url = str_replace(array("\n", "\r"), '', $url); + + if (null !== $options) { + if (isset($options['exit'])) { + $this->setExit(($options['exit']) ? true : false); + } + if (isset($options['prependBase'])) { + $this->setPrependBase(($options['prependBase']) ? true : false); + } + if (isset($options['code'])) { + $this->setCode($options['code']); + } + } + + // If relative URL, decide if we should prepend base URL + if (!preg_match('|^[a-z]+://|', $url)) { + $url = $this->_prependBase($url); + } + + $this->_redirect($url); + } + + /** + * Perform a redirect to an action/controller/module with params + * + * @param string $action + * @param string $controller + * @param string $module + * @param array $params + * @return void + */ + public function gotoSimple($action, $controller = null, $module = null, array $params = array()) + { + $this->setGotoSimple($action, $controller, $module, $params); + + if ($this->getExit()) { + $this->redirectAndExit(); + } + } + + /** + * Perform a redirect to an action/controller/module with params, forcing an immdiate exit + * + * @param mixed $action + * @param mixed $controller + * @param mixed $module + * @param array $params + * @return void + */ + public function gotoSimpleAndExit($action, $controller = null, $module = null, array $params = array()) + { + $this->setGotoSimple($action, $controller, $module, $params); + $this->redirectAndExit(); + } + + /** + * Redirect to a route-based URL + * + * Uses route's assemble method to build the URL; route is specified by $name; + * default route is used if none provided. + * + * @param array $urlOptions Array of key/value pairs used to assemble URL + * @param string $name + * @param boolean $reset + * @param boolean $encode + * @return void + */ + public function gotoRoute(array $urlOptions = array(), $name = null, $reset = false, $encode = true) + { + $this->setGotoRoute($urlOptions, $name, $reset, $encode); + + if ($this->getExit()) { + $this->redirectAndExit(); + } + } + + /** + * Redirect to a route-based URL, and immediately exit + * + * Uses route's assemble method to build the URL; route is specified by $name; + * default route is used if none provided. + * + * @param array $urlOptions Array of key/value pairs used to assemble URL + * @param string $name + * @param boolean $reset + * @return void + */ + public function gotoRouteAndExit(array $urlOptions = array(), $name = null, $reset = false) + { + $this->setGotoRoute($urlOptions, $name, $reset); + $this->redirectAndExit(); + } + + /** + * Perform a redirect to a url + * + * @param string $url + * @param array $options + * @return void + */ + public function gotoUrl($url, array $options = array()) + { + $this->setGotoUrl($url, $options); + + if ($this->getExit()) { + $this->redirectAndExit(); + } + } + + /** + * Set a URL string for a redirect, perform redirect, and immediately exit + * + * @param string $url + * @param array $options + * @return void + */ + public function gotoUrlAndExit($url, array $options = array()) + { + $this->setGotoUrl($url, $options); + $this->redirectAndExit(); + } + + /** + * exit(): Perform exit for redirector + * + * @return void + */ + public function redirectAndExit() + { + if ($this->getCloseSessionOnExit()) { + // Close session, if started + if (class_exists('Zend_Session', false) && Zend_Session::isStarted()) { + Zend_Session::writeClose(); + } elseif (isset($_SESSION)) { + session_write_close(); + } + } + + $this->getResponse()->sendHeaders(); + exit(); + } + + /** + * direct(): Perform helper when called as + * $this->_helper->redirector($action, $controller, $module, $params) + * + * @param string $action + * @param string $controller + * @param string $module + * @param array $params + * @return void + */ + public function direct($action, $controller = null, $module = null, array $params = array()) + { + $this->gotoSimple($action, $controller, $module, $params); + } + + /** + * Overloading + * + * Overloading for old 'goto', 'setGoto', and 'gotoAndExit' methods + * + * @param string $method + * @param array $args + * @return mixed + * @throws Zend_Controller_Action_Exception for invalid methods + */ + public function __call($method, $args) + { + $method = strtolower($method); + if ('goto' == $method) { + return call_user_func_array(array($this, 'gotoSimple'), $args); + } + if ('setgoto' == $method) { + return call_user_func_array(array($this, 'setGotoSimple'), $args); + } + if ('gotoandexit' == $method) { + return call_user_func_array(array($this, 'gotoSimpleAndExit'), $args); + } + + require_once 'Zend/Controller/Action/Exception.php'; + throw new Zend_Controller_Action_Exception(sprintf('Invalid method "%s" called on redirector', $method)); + } +} diff --git a/lib/zend/Zend/Controller/Action/Helper/Url.php b/lib/zend/Zend/Controller/Action/Helper/Url.php new file mode 100644 index 00000000000..7b8c69ac12a --- /dev/null +++ b/lib/zend/Zend/Controller/Action/Helper/Url.php @@ -0,0 +1,117 @@ +getRequest(); + + if (null === $controller) { + $controller = $request->getControllerName(); + } + + if (null === $module) { + $module = $request->getModuleName(); + } + + $url = $controller . '/' . $action; + if ($module != $this->getFrontController()->getDispatcher()->getDefaultModule()) { + $url = $module . '/' . $url; + } + + if ('' !== ($baseUrl = $this->getFrontController()->getBaseUrl())) { + $url = $baseUrl . '/' . $url; + } + + if (null !== $params) { + $paramPairs = array(); + foreach ($params as $key => $value) { + $paramPairs[] = urlencode($key) . '/' . urlencode($value); + } + $paramString = implode('/', $paramPairs); + $url .= '/' . $paramString; + } + + $url = '/' . ltrim($url, '/'); + + return $url; + } + + /** + * Assembles a URL based on a given route + * + * This method will typically be used for more complex operations, as it + * ties into the route objects registered with the router. + * + * @param array $urlOptions Options passed to the assemble method of the Route object. + * @param mixed $name The name of a Route to use. If null it will use the current Route + * @param boolean $reset + * @param boolean $encode + * @return string Url for the link href attribute. + */ + public function url($urlOptions = array(), $name = null, $reset = false, $encode = true) + { + $router = $this->getFrontController()->getRouter(); + return $router->assemble($urlOptions, $name, $reset, $encode); + } + + /** + * Perform helper when called as $this->_helper->url() from an action controller + * + * Proxies to {@link simple()} + * + * @param string $action + * @param string $controller + * @param string $module + * @param array $params + * @return string + */ + public function direct($action, $controller = null, $module = null, array $params = null) + { + return $this->simple($action, $controller, $module, $params); + } +} diff --git a/lib/zend/Zend/Controller/Action/Helper/ViewRenderer.php b/lib/zend/Zend/Controller/Action/Helper/ViewRenderer.php new file mode 100644 index 00000000000..a66c12a4665 --- /dev/null +++ b/lib/zend/Zend/Controller/Action/Helper/ViewRenderer.php @@ -0,0 +1,1004 @@ + + * // In your bootstrap: + * Zend_Controller_Action_HelperBroker::addHelper(new Zend_Controller_Action_Helper_ViewRenderer()); + * + * // In your action controller methods: + * $viewHelper = $this->_helper->getHelper('view'); + * + * // Don't use controller subdirectories + * $viewHelper->setNoController(true); + * + * // Specify a different script to render: + * $this->_helper->viewRenderer('form'); + * + * + * + * @uses Zend_Controller_Action_Helper_Abstract + * @package Zend_Controller + * @subpackage Zend_Controller_Action_Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_Controller_Action_Helper_ViewRenderer extends Zend_Controller_Action_Helper_Abstract +{ + /** + * @var Zend_View_Interface + */ + public $view; + + /** + * Word delimiters + * @var array + */ + protected $_delimiters; + + /** + * @var Zend_Filter_Inflector + */ + protected $_inflector; + + /** + * Inflector target + * @var string + */ + protected $_inflectorTarget = ''; + + /** + * Current module directory + * @var string + */ + protected $_moduleDir = ''; + + /** + * Whether or not to autorender using controller name as subdirectory; + * global setting (not reset at next invocation) + * @var boolean + */ + protected $_neverController = false; + + /** + * Whether or not to autorender postDispatch; global setting (not reset at + * next invocation) + * @var boolean + */ + protected $_neverRender = false; + + /** + * Whether or not to use a controller name as a subdirectory when rendering + * @var boolean + */ + protected $_noController = false; + + /** + * Whether or not to autorender postDispatch; per controller/action setting (reset + * at next invocation) + * @var boolean + */ + protected $_noRender = false; + + /** + * Characters representing path delimiters in the controller + * @var string|array + */ + protected $_pathDelimiters; + + /** + * Which named segment of the response to utilize + * @var string + */ + protected $_responseSegment = null; + + /** + * Which action view script to render + * @var string + */ + protected $_scriptAction = null; + + /** + * View object basePath + * @var string + */ + protected $_viewBasePathSpec = ':moduleDir/views'; + + /** + * View script path specification string + * @var string + */ + protected $_viewScriptPathSpec = ':controller/:action.:suffix'; + + /** + * View script path specification string, minus controller segment + * @var string + */ + protected $_viewScriptPathNoControllerSpec = ':action.:suffix'; + + /** + * View script suffix + * @var string + */ + protected $_viewSuffix = 'phtml'; + + /** + * Constructor + * + * Optionally set view object and options. + * + * @param Zend_View_Interface $view + * @param array $options + * @return void + */ + public function __construct(Zend_View_Interface $view = null, array $options = array()) + { + if (null !== $view) { + $this->setView($view); + } + + if (!empty($options)) { + $this->_setOptions($options); + } + } + + /** + * Clone - also make sure the view is cloned. + * + * @return void + */ + public function __clone() + { + if (isset($this->view) && $this->view instanceof Zend_View_Interface) { + $this->view = clone $this->view; + + } + } + + /** + * Set the view object + * + * @param Zend_View_Interface $view + * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface + */ + public function setView(Zend_View_Interface $view) + { + $this->view = $view; + return $this; + } + + /** + * Get current module name + * + * @return string + */ + public function getModule() + { + $request = $this->getRequest(); + $module = $request->getModuleName(); + if (null === $module) { + $module = $this->getFrontController()->getDispatcher()->getDefaultModule(); + } + + return $module; + } + + /** + * Get module directory + * + * @throws Zend_Controller_Action_Exception + * @return string + */ + public function getModuleDirectory() + { + $module = $this->getModule(); + $moduleDir = $this->getFrontController()->getControllerDirectory($module); + if ((null === $moduleDir) || is_array($moduleDir)) { + /** + * @see Zend_Controller_Action_Exception + */ + require_once 'Zend/Controller/Action/Exception.php'; + throw new Zend_Controller_Action_Exception('ViewRenderer cannot locate module directory for module "' . $module . '"'); + } + $this->_moduleDir = dirname($moduleDir); + return $this->_moduleDir; + } + + /** + * Get inflector + * + * @return Zend_Filter_Inflector + */ + public function getInflector() + { + if (null === $this->_inflector) { + /** + * @see Zend_Filter_Inflector + */ + require_once 'Zend/Filter/Inflector.php'; + /** + * @see Zend_Filter_PregReplace + */ + require_once 'Zend/Filter/PregReplace.php'; + /** + * @see Zend_Filter_Word_UnderscoreToSeparator + */ + require_once 'Zend/Filter/Word/UnderscoreToSeparator.php'; + $this->_inflector = new Zend_Filter_Inflector(); + $this->_inflector->setStaticRuleReference('moduleDir', $this->_moduleDir) // moduleDir must be specified before the less specific 'module' + ->addRules(array( + ':module' => array('Word_CamelCaseToDash', 'StringToLower'), + ':controller' => array('Word_CamelCaseToDash', new Zend_Filter_Word_UnderscoreToSeparator('/'), 'StringToLower', new Zend_Filter_PregReplace('/\./', '-')), + ':action' => array('Word_CamelCaseToDash', new Zend_Filter_PregReplace('#[^a-z0-9' . preg_quote('/', '#') . ']+#i', '-'), 'StringToLower'), + )) + ->setStaticRuleReference('suffix', $this->_viewSuffix) + ->setTargetReference($this->_inflectorTarget); + } + + // Ensure that module directory is current + $this->getModuleDirectory(); + + return $this->_inflector; + } + + /** + * Set inflector + * + * @param Zend_Filter_Inflector $inflector + * @param boolean $reference Whether the moduleDir, target, and suffix should be set as references to ViewRenderer properties + * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface + */ + public function setInflector(Zend_Filter_Inflector $inflector, $reference = false) + { + $this->_inflector = $inflector; + if ($reference) { + $this->_inflector->setStaticRuleReference('suffix', $this->_viewSuffix) + ->setStaticRuleReference('moduleDir', $this->_moduleDir) + ->setTargetReference($this->_inflectorTarget); + } + return $this; + } + + /** + * Set inflector target + * + * @param string $target + * @return void + */ + protected function _setInflectorTarget($target) + { + $this->_inflectorTarget = (string) $target; + } + + /** + * Set internal module directory representation + * + * @param string $dir + * @return void + */ + protected function _setModuleDir($dir) + { + $this->_moduleDir = (string) $dir; + } + + /** + * Get internal module directory representation + * + * @return string + */ + protected function _getModuleDir() + { + return $this->_moduleDir; + } + + /** + * Generate a class prefix for helper and filter classes + * + * @return string + */ + protected function _generateDefaultPrefix() + { + $default = 'Zend_View'; + if (null === $this->_actionController) { + return $default; + } + + $class = get_class($this->_actionController); + + if (!strstr($class, '_')) { + return $default; + } + + $module = $this->getModule(); + if ('default' == $module) { + return $default; + } + + $prefix = substr($class, 0, strpos($class, '_')) . '_View'; + + return $prefix; + } + + /** + * Retrieve base path based on location of current action controller + * + * @return string + */ + protected function _getBasePath() + { + if (null === $this->_actionController) { + return './views'; + } + + $inflector = $this->getInflector(); + $this->_setInflectorTarget($this->getViewBasePathSpec()); + + $dispatcher = $this->getFrontController()->getDispatcher(); + $request = $this->getRequest(); + + $parts = array( + 'module' => (($moduleName = $request->getModuleName()) != '') ? $dispatcher->formatModuleName($moduleName) : $moduleName, + 'controller' => $request->getControllerName(), + 'action' => $dispatcher->formatActionName($request->getActionName()) + ); + + $path = $inflector->filter($parts); + return $path; + } + + /** + * Set options + * + * @param array $options + * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface + */ + protected function _setOptions(array $options) + { + foreach ($options as $key => $value) + { + switch ($key) { + case 'neverRender': + case 'neverController': + case 'noController': + case 'noRender': + $property = '_' . $key; + $this->{$property} = ($value) ? true : false; + break; + case 'responseSegment': + case 'scriptAction': + case 'viewBasePathSpec': + case 'viewScriptPathSpec': + case 'viewScriptPathNoControllerSpec': + case 'viewSuffix': + $property = '_' . $key; + $this->{$property} = (string) $value; + break; + default: + break; + } + } + + return $this; + } + + /** + * Initialize the view object + * + * $options may contain the following keys: + * - neverRender - flag dis/enabling postDispatch() autorender (affects all subsequent calls) + * - noController - flag indicating whether or not to look for view scripts in subdirectories named after the controller + * - noRender - flag indicating whether or not to autorender postDispatch() + * - responseSegment - which named response segment to render a view script to + * - scriptAction - what action script to render + * - viewBasePathSpec - specification to use for determining view base path + * - viewScriptPathSpec - specification to use for determining view script paths + * - viewScriptPathNoControllerSpec - specification to use for determining view script paths when noController flag is set + * - viewSuffix - what view script filename suffix to use + * + * @param string $path + * @param string $prefix + * @param array $options + * @throws Zend_Controller_Action_Exception + * @return void + */ + public function initView($path = null, $prefix = null, array $options = array()) + { + if (null === $this->view) { + $this->setView(new Zend_View()); + } + + // Reset some flags every time + $options['noController'] = (isset($options['noController'])) ? $options['noController'] : false; + $options['noRender'] = (isset($options['noRender'])) ? $options['noRender'] : false; + $this->_scriptAction = null; + $this->_responseSegment = null; + + // Set options first; may be used to determine other initializations + $this->_setOptions($options); + + // Get base view path + if (empty($path)) { + $path = $this->_getBasePath(); + if (empty($path)) { + /** + * @see Zend_Controller_Action_Exception + */ + require_once 'Zend/Controller/Action/Exception.php'; + throw new Zend_Controller_Action_Exception('ViewRenderer initialization failed: retrieved view base path is empty'); + } + } + + if (null === $prefix) { + $prefix = $this->_generateDefaultPrefix(); + } + + // Determine if this path has already been registered + $currentPaths = $this->view->getScriptPaths(); + $path = str_replace(array('/', '\\'), '/', $path); + $pathExists = false; + foreach ($currentPaths as $tmpPath) { + $tmpPath = str_replace(array('/', '\\'), '/', $tmpPath); + if (strstr($tmpPath, $path)) { + $pathExists = true; + break; + } + } + if (!$pathExists) { + $this->view->addBasePath($path, $prefix); + } + + // Register view with action controller (unless already registered) + if ((null !== $this->_actionController) && (null === $this->_actionController->view)) { + $this->_actionController->view = $this->view; + $this->_actionController->viewSuffix = $this->_viewSuffix; + } + } + + /** + * init - initialize view + * + * @return void + */ + public function init() + { + if ($this->getFrontController()->getParam('noViewRenderer')) { + return; + } + + $this->initView(); + } + + /** + * Set view basePath specification + * + * Specification can contain one or more of the following: + * - :moduleDir - current module directory + * - :controller - name of current controller in the request + * - :action - name of current action in the request + * - :module - name of current module in the request + * + * @param string $path + * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface + */ + public function setViewBasePathSpec($path) + { + $this->_viewBasePathSpec = (string) $path; + return $this; + } + + /** + * Retrieve the current view basePath specification string + * + * @return string + */ + public function getViewBasePathSpec() + { + return $this->_viewBasePathSpec; + } + + /** + * Set view script path specification + * + * Specification can contain one or more of the following: + * - :moduleDir - current module directory + * - :controller - name of current controller in the request + * - :action - name of current action in the request + * - :module - name of current module in the request + * + * @param string $path + * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface + */ + public function setViewScriptPathSpec($path) + { + $this->_viewScriptPathSpec = (string) $path; + return $this; + } + + /** + * Retrieve the current view script path specification string + * + * @return string + */ + public function getViewScriptPathSpec() + { + return $this->_viewScriptPathSpec; + } + + /** + * Set view script path specification (no controller variant) + * + * Specification can contain one or more of the following: + * - :moduleDir - current module directory + * - :controller - name of current controller in the request + * - :action - name of current action in the request + * - :module - name of current module in the request + * + * :controller will likely be ignored in this variant. + * + * @param string $path + * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface + */ + public function setViewScriptPathNoControllerSpec($path) + { + $this->_viewScriptPathNoControllerSpec = (string) $path; + return $this; + } + + /** + * Retrieve the current view script path specification string (no controller variant) + * + * @return string + */ + public function getViewScriptPathNoControllerSpec() + { + return $this->_viewScriptPathNoControllerSpec; + } + + /** + * Get a view script based on an action and/or other variables + * + * Uses values found in current request if no values passed in $vars. + * + * If {@link $_noController} is set, uses {@link $_viewScriptPathNoControllerSpec}; + * otherwise, uses {@link $_viewScriptPathSpec}. + * + * @param string $action + * @param array $vars + * @return string + */ + public function getViewScript($action = null, array $vars = array()) + { + $request = $this->getRequest(); + if ((null === $action) && (!isset($vars['action']))) { + $action = $this->getScriptAction(); + if (null === $action) { + $action = $request->getActionName(); + } + $vars['action'] = $action; + } elseif (null !== $action) { + $vars['action'] = $action; + } + + $replacePattern = array('/[^a-z0-9]+$/i', '/^[^a-z0-9]+/i'); + $vars['action'] = preg_replace($replacePattern, '', $vars['action']); + + $inflector = $this->getInflector(); + if ($this->getNoController() || $this->getNeverController()) { + $this->_setInflectorTarget($this->getViewScriptPathNoControllerSpec()); + } else { + $this->_setInflectorTarget($this->getViewScriptPathSpec()); + } + return $this->_translateSpec($vars); + } + + /** + * Set the neverRender flag (i.e., globally dis/enable autorendering) + * + * @param boolean $flag + * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface + */ + public function setNeverRender($flag = true) + { + $this->_neverRender = ($flag) ? true : false; + return $this; + } + + /** + * Retrieve neverRender flag value + * + * @return boolean + */ + public function getNeverRender() + { + return $this->_neverRender; + } + + /** + * Set the noRender flag (i.e., whether or not to autorender) + * + * @param boolean $flag + * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface + */ + public function setNoRender($flag = true) + { + $this->_noRender = ($flag) ? true : false; + return $this; + } + + /** + * Retrieve noRender flag value + * + * @return boolean + */ + public function getNoRender() + { + return $this->_noRender; + } + + /** + * Set the view script to use + * + * @param string $name + * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface + */ + public function setScriptAction($name) + { + $this->_scriptAction = (string) $name; + return $this; + } + + /** + * Retrieve view script name + * + * @return string + */ + public function getScriptAction() + { + return $this->_scriptAction; + } + + /** + * Set the response segment name + * + * @param string $name + * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface + */ + public function setResponseSegment($name) + { + if (null === $name) { + $this->_responseSegment = null; + } else { + $this->_responseSegment = (string) $name; + } + + return $this; + } + + /** + * Retrieve named response segment name + * + * @return string + */ + public function getResponseSegment() + { + return $this->_responseSegment; + } + + /** + * Set the noController flag (i.e., whether or not to render into controller subdirectories) + * + * @param boolean $flag + * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface + */ + public function setNoController($flag = true) + { + $this->_noController = ($flag) ? true : false; + return $this; + } + + /** + * Retrieve noController flag value + * + * @return boolean + */ + public function getNoController() + { + return $this->_noController; + } + + /** + * Set the neverController flag (i.e., whether or not to render into controller subdirectories) + * + * @param boolean $flag + * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface + */ + public function setNeverController($flag = true) + { + $this->_neverController = ($flag) ? true : false; + return $this; + } + + /** + * Retrieve neverController flag value + * + * @return boolean + */ + public function getNeverController() + { + return $this->_neverController; + } + + /** + * Set view script suffix + * + * @param string $suffix + * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface + */ + public function setViewSuffix($suffix) + { + $this->_viewSuffix = (string) $suffix; + return $this; + } + + /** + * Get view script suffix + * + * @return string + */ + public function getViewSuffix() + { + return $this->_viewSuffix; + } + + /** + * Set options for rendering a view script + * + * @param string $action View script to render + * @param string $name Response named segment to render to + * @param boolean $noController Whether or not to render within a subdirectory named after the controller + * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface + */ + public function setRender($action = null, $name = null, $noController = null) + { + if (null !== $action) { + $this->setScriptAction($action); + } + + if (null !== $name) { + $this->setResponseSegment($name); + } + + if (null !== $noController) { + $this->setNoController($noController); + } + + return $this; + } + + /** + * Inflect based on provided vars + * + * Allowed variables are: + * - :moduleDir - current module directory + * - :module - current module name + * - :controller - current controller name + * - :action - current action name + * - :suffix - view script file suffix + * + * @param array $vars + * @return string + */ + protected function _translateSpec(array $vars = array()) + { + $inflector = $this->getInflector(); + $request = $this->getRequest(); + $dispatcher = $this->getFrontController()->getDispatcher(); + + // Format module name + $module = $dispatcher->formatModuleName($request->getModuleName()); + + // Format controller name + require_once 'Zend/Filter/Word/CamelCaseToDash.php'; + $filter = new Zend_Filter_Word_CamelCaseToDash(); + $controller = $filter->filter($request->getControllerName()); + $controller = $dispatcher->formatControllerName($controller); + if ('Controller' == substr($controller, -10)) { + $controller = substr($controller, 0, -10); + } + + // Format action name + $action = $dispatcher->formatActionName($request->getActionName()); + + $params = compact('module', 'controller', 'action'); + foreach ($vars as $key => $value) { + switch ($key) { + case 'module': + case 'controller': + case 'action': + case 'moduleDir': + case 'suffix': + $params[$key] = (string) $value; + break; + default: + break; + } + } + + if (isset($params['suffix'])) { + $origSuffix = $this->getViewSuffix(); + $this->setViewSuffix($params['suffix']); + } + if (isset($params['moduleDir'])) { + $origModuleDir = $this->_getModuleDir(); + $this->_setModuleDir($params['moduleDir']); + } + + $filtered = $inflector->filter($params); + + if (isset($params['suffix'])) { + $this->setViewSuffix($origSuffix); + } + if (isset($params['moduleDir'])) { + $this->_setModuleDir($origModuleDir); + } + + return $filtered; + } + + /** + * Render a view script (optionally to a named response segment) + * + * Sets the noRender flag to true when called. + * + * @param string $script + * @param string $name + * @return void + */ + public function renderScript($script, $name = null) + { + if (null === $name) { + $name = $this->getResponseSegment(); + } + + $this->getResponse()->appendBody( + $this->view->render($script), + $name + ); + + $this->setNoRender(); + } + + /** + * Render a view based on path specifications + * + * Renders a view based on the view script path specifications. + * + * @param string $action + * @param string $name + * @param boolean $noController + * @return void + */ + public function render($action = null, $name = null, $noController = null) + { + $this->setRender($action, $name, $noController); + $path = $this->getViewScript(); + $this->renderScript($path, $name); + } + + /** + * Render a script based on specification variables + * + * Pass an action, and one or more specification variables (view script suffix) + * to determine the view script path, and render that script. + * + * @param string $action + * @param array $vars + * @param string $name + * @return void + */ + public function renderBySpec($action = null, array $vars = array(), $name = null) + { + if (null !== $name) { + $this->setResponseSegment($name); + } + + $path = $this->getViewScript($action, $vars); + + $this->renderScript($path); + } + + /** + * postDispatch - auto render a view + * + * Only autorenders if: + * - _noRender is false + * - action controller is present + * - request has not been re-dispatched (i.e., _forward() has not been called) + * - response is not a redirect + * + * @return void + */ + public function postDispatch() + { + if ($this->_shouldRender()) { + $this->render(); + } + } + + /** + * Should the ViewRenderer render a view script? + * + * @return boolean + */ + protected function _shouldRender() + { + return (!$this->getFrontController()->getParam('noViewRenderer') + && !$this->_neverRender + && !$this->_noRender + && (null !== $this->_actionController) + && $this->getRequest()->isDispatched() + && !$this->getResponse()->isRedirect() + ); + } + + /** + * Use this helper as a method; proxies to setRender() + * + * @param string $action + * @param string $name + * @param boolean $noController + * @return void + */ + public function direct($action = null, $name = null, $noController = null) + { + $this->setRender($action, $name, $noController); + } +} diff --git a/lib/zend/Zend/Controller/Action/HelperBroker.php b/lib/zend/Zend/Controller/Action/HelperBroker.php new file mode 100644 index 00000000000..f911c7035e6 --- /dev/null +++ b/lib/zend/Zend/Controller/Action/HelperBroker.php @@ -0,0 +1,381 @@ + 'Zend/Controller/Action/Helper/', + )); + } + return self::$_pluginLoader; + } + + /** + * addPrefix() - Add repository of helpers by prefix + * + * @param string $prefix + */ + static public function addPrefix($prefix) + { + $prefix = rtrim($prefix, '_'); + $path = str_replace('_', DIRECTORY_SEPARATOR, $prefix); + self::getPluginLoader()->addPrefixPath($prefix, $path); + } + + /** + * addPath() - Add path to repositories where Action_Helpers could be found. + * + * @param string $path + * @param string $prefix Optional; defaults to 'Zend_Controller_Action_Helper' + * @return void + */ + static public function addPath($path, $prefix = 'Zend_Controller_Action_Helper') + { + self::getPluginLoader()->addPrefixPath($prefix, $path); + } + + /** + * addHelper() - Add helper objects + * + * @param Zend_Controller_Action_Helper_Abstract $helper + * @return void + */ + static public function addHelper(Zend_Controller_Action_Helper_Abstract $helper) + { + self::getStack()->push($helper); + return; + } + + /** + * resetHelpers() + * + * @return void + */ + static public function resetHelpers() + { + self::$_stack = null; + return; + } + + /** + * Retrieve or initialize a helper statically + * + * Retrieves a helper object statically, loading on-demand if the helper + * does not already exist in the stack. Always returns a helper, unless + * the helper class cannot be found. + * + * @param string $name + * @return Zend_Controller_Action_Helper_Abstract + */ + public static function getStaticHelper($name) + { + $name = self::_normalizeHelperName($name); + $stack = self::getStack(); + + if (!isset($stack->{$name})) { + self::_loadHelper($name); + } + + return $stack->{$name}; + } + + /** + * getExistingHelper() - get helper by name + * + * Static method to retrieve helper object. Only retrieves helpers already + * initialized with the broker (either via addHelper() or on-demand loading + * via getHelper()). + * + * Throws an exception if the referenced helper does not exist in the + * stack; use {@link hasHelper()} to check if the helper is registered + * prior to retrieving it. + * + * @param string $name + * @return Zend_Controller_Action_Helper_Abstract + * @throws Zend_Controller_Action_Exception + */ + public static function getExistingHelper($name) + { + $name = self::_normalizeHelperName($name); + $stack = self::getStack(); + + if (!isset($stack->{$name})) { + require_once 'Zend/Controller/Action/Exception.php'; + throw new Zend_Controller_Action_Exception('Action helper "' . $name . '" has not been registered with the helper broker'); + } + + return $stack->{$name}; + } + + /** + * Return all registered helpers as helper => object pairs + * + * @return array + */ + public static function getExistingHelpers() + { + return self::getStack()->getHelpersByName(); + } + + /** + * Is a particular helper loaded in the broker? + * + * @param string $name + * @return boolean + */ + public static function hasHelper($name) + { + $name = self::_normalizeHelperName($name); + return isset(self::getStack()->{$name}); + } + + /** + * Remove a particular helper from the broker + * + * @param string $name + * @return boolean + */ + public static function removeHelper($name) + { + $name = self::_normalizeHelperName($name); + $stack = self::getStack(); + if (isset($stack->{$name})) { + unset($stack->{$name}); + } + + return false; + } + + /** + * Lazy load the priority stack and return it + * + * @return Zend_Controller_Action_HelperBroker_PriorityStack + */ + public static function getStack() + { + if (self::$_stack == null) { + self::$_stack = new Zend_Controller_Action_HelperBroker_PriorityStack(); + } + + return self::$_stack; + } + + /** + * Constructor + * + * @param Zend_Controller_Action $actionController + * @return void + */ + public function __construct(Zend_Controller_Action $actionController) + { + $this->_actionController = $actionController; + foreach (self::getStack() as $helper) { + $helper->setActionController($actionController); + $helper->init(); + } + } + + /** + * notifyPreDispatch() - called by action controller dispatch method + * + * @return void + */ + public function notifyPreDispatch() + { + foreach (self::getStack() as $helper) { + $helper->preDispatch(); + } + } + + /** + * notifyPostDispatch() - called by action controller dispatch method + * + * @return void + */ + public function notifyPostDispatch() + { + foreach (self::getStack() as $helper) { + $helper->postDispatch(); + } + } + + /** + * getHelper() - get helper by name + * + * @param string $name + * @return Zend_Controller_Action_Helper_Abstract + */ + public function getHelper($name) + { + $name = self::_normalizeHelperName($name); + $stack = self::getStack(); + + if (!isset($stack->{$name})) { + self::_loadHelper($name); + } + + $helper = $stack->{$name}; + + $initialize = false; + if (null === ($actionController = $helper->getActionController())) { + $initialize = true; + } elseif ($actionController !== $this->_actionController) { + $initialize = true; + } + + if ($initialize) { + $helper->setActionController($this->_actionController) + ->init(); + } + + return $helper; + } + + /** + * Method overloading + * + * @param string $method + * @param array $args + * @return mixed + * @throws Zend_Controller_Action_Exception if helper does not have a direct() method + */ + public function __call($method, $args) + { + $helper = $this->getHelper($method); + if (!method_exists($helper, 'direct')) { + require_once 'Zend/Controller/Action/Exception.php'; + throw new Zend_Controller_Action_Exception('Helper "' . $method . '" does not support overloading via direct()'); + } + return call_user_func_array(array($helper, 'direct'), $args); + } + + /** + * Retrieve helper by name as object property + * + * @param string $name + * @return Zend_Controller_Action_Helper_Abstract + */ + public function __get($name) + { + return $this->getHelper($name); + } + + /** + * Normalize helper name for lookups + * + * @param string $name + * @return string + */ + protected static function _normalizeHelperName($name) + { + if (strpos($name, '_') !== false) { + $name = str_replace(' ', '', ucwords(str_replace('_', ' ', $name))); + } + + return ucfirst($name); + } + + /** + * Load a helper + * + * @param string $name + * @return void + */ + protected static function _loadHelper($name) + { + try { + $class = self::getPluginLoader()->load($name); + } catch (Zend_Loader_PluginLoader_Exception $e) { + require_once 'Zend/Controller/Action/Exception.php'; + throw new Zend_Controller_Action_Exception('Action Helper by name ' . $name . ' not found', 0, $e); + } + + $helper = new $class(); + + if (!$helper instanceof Zend_Controller_Action_Helper_Abstract) { + require_once 'Zend/Controller/Action/Exception.php'; + throw new Zend_Controller_Action_Exception('Helper name ' . $name . ' -> class ' . $class . ' is not of type Zend_Controller_Action_Helper_Abstract'); + } + + self::getStack()->push($helper); + } +} diff --git a/lib/zend/Zend/Controller/Action/HelperBroker/PriorityStack.php b/lib/zend/Zend/Controller/Action/HelperBroker/PriorityStack.php new file mode 100644 index 00000000000..d510b74ee58 --- /dev/null +++ b/lib/zend/Zend/Controller/Action/HelperBroker/PriorityStack.php @@ -0,0 +1,280 @@ +_helpersByNameRef)) { + return false; + } + + return $this->_helpersByNameRef[$helperName]; + } + + /** + * Magic property overloading for returning if helper is set by name + * + * @param string $helperName The helper name + * @return Zend_Controller_Action_Helper_Abstract + */ + public function __isset($helperName) + { + return array_key_exists($helperName, $this->_helpersByNameRef); + } + + /** + * Magic property overloading for unsetting if helper is exists by name + * + * @param string $helperName The helper name + * @return Zend_Controller_Action_Helper_Abstract + */ + public function __unset($helperName) + { + return $this->offsetUnset($helperName); + } + + /** + * push helper onto the stack + * + * @param Zend_Controller_Action_Helper_Abstract $helper + * @return Zend_Controller_Action_HelperBroker_PriorityStack + */ + public function push(Zend_Controller_Action_Helper_Abstract $helper) + { + $this->offsetSet($this->getNextFreeHigherPriority(), $helper); + return $this; + } + + /** + * Return something iterable + * + * @return array + */ + public function getIterator() + { + return new ArrayObject($this->_helpersByPriority); + } + + /** + * offsetExists() + * + * @param int|string $priorityOrHelperName + * @return Zend_Controller_Action_HelperBroker_PriorityStack + */ + public function offsetExists($priorityOrHelperName) + { + if (is_string($priorityOrHelperName)) { + return array_key_exists($priorityOrHelperName, $this->_helpersByNameRef); + } else { + return array_key_exists($priorityOrHelperName, $this->_helpersByPriority); + } + } + + /** + * offsetGet() + * + * @param int|string $priorityOrHelperName + * @return Zend_Controller_Action_HelperBroker_PriorityStack + */ + public function offsetGet($priorityOrHelperName) + { + if (!$this->offsetExists($priorityOrHelperName)) { + require_once 'Zend/Controller/Action/Exception.php'; + throw new Zend_Controller_Action_Exception('A helper with priority ' . $priorityOrHelperName . ' does not exist.'); + } + + if (is_string($priorityOrHelperName)) { + return $this->_helpersByNameRef[$priorityOrHelperName]; + } else { + return $this->_helpersByPriority[$priorityOrHelperName]; + } + } + + /** + * offsetSet() + * + * @param int $priority + * @param Zend_Controller_Action_Helper_Abstract $helper + * @return Zend_Controller_Action_HelperBroker_PriorityStack + */ + public function offsetSet($priority, $helper) + { + $priority = (int) $priority; + + if (!$helper instanceof Zend_Controller_Action_Helper_Abstract) { + require_once 'Zend/Controller/Action/Exception.php'; + throw new Zend_Controller_Action_Exception('$helper must extend Zend_Controller_Action_Helper_Abstract.'); + } + + if (array_key_exists($helper->getName(), $this->_helpersByNameRef)) { + // remove any object with the same name to retain BC compailitbility + // @todo At ZF 2.0 time throw an exception here. + $this->offsetUnset($helper->getName()); + } + + if (array_key_exists($priority, $this->_helpersByPriority)) { + $priority = $this->getNextFreeHigherPriority($priority); // ensures LIFO + trigger_error("A helper with the same priority already exists, reassigning to $priority", E_USER_WARNING); + } + + $this->_helpersByPriority[$priority] = $helper; + $this->_helpersByNameRef[$helper->getName()] = $helper; + + if ($priority == ($nextFreeDefault = $this->getNextFreeHigherPriority($this->_nextDefaultPriority))) { + $this->_nextDefaultPriority = $nextFreeDefault; + } + + krsort($this->_helpersByPriority); // always make sure priority and LIFO are both enforced + return $this; + } + + /** + * offsetUnset() + * + * @param int|string $priorityOrHelperName Priority integer or the helper name + * @return Zend_Controller_Action_HelperBroker_PriorityStack + */ + public function offsetUnset($priorityOrHelperName) + { + if (!$this->offsetExists($priorityOrHelperName)) { + require_once 'Zend/Controller/Action/Exception.php'; + throw new Zend_Controller_Action_Exception('A helper with priority or name ' . $priorityOrHelperName . ' does not exist.'); + } + + if (is_string($priorityOrHelperName)) { + $helperName = $priorityOrHelperName; + $helper = $this->_helpersByNameRef[$helperName]; + $priority = array_search($helper, $this->_helpersByPriority, true); + } else { + $priority = $priorityOrHelperName; + $helperName = $this->_helpersByPriority[$priorityOrHelperName]->getName(); + } + + unset($this->_helpersByNameRef[$helperName]); + unset($this->_helpersByPriority[$priority]); + return $this; + } + + /** + * return the count of helpers + * + * @return int + */ + public function count() + { + return count($this->_helpersByPriority); + } + + /** + * Find the next free higher priority. If an index is given, it will + * find the next free highest priority after it. + * + * @param int $indexPriority OPTIONAL + * @return int + */ + public function getNextFreeHigherPriority($indexPriority = null) + { + if ($indexPriority == null) { + $indexPriority = $this->_nextDefaultPriority; + } + + $priorities = array_keys($this->_helpersByPriority); + + while (in_array($indexPriority, $priorities)) { + $indexPriority++; + } + + return $indexPriority; + } + + /** + * Find the next free lower priority. If an index is given, it will + * find the next free lower priority before it. + * + * @param int $indexPriority + * @return int + */ + public function getNextFreeLowerPriority($indexPriority = null) + { + if ($indexPriority == null) { + $indexPriority = $this->_nextDefaultPriority; + } + + $priorities = array_keys($this->_helpersByPriority); + + while (in_array($indexPriority, $priorities)) { + $indexPriority--; + } + + return $indexPriority; + } + + /** + * return the highest priority + * + * @return int + */ + public function getHighestPriority() + { + return max(array_keys($this->_helpersByPriority)); + } + + /** + * return the lowest priority + * + * @return int + */ + public function getLowestPriority() + { + return min(array_keys($this->_helpersByPriority)); + } + + /** + * return the helpers referenced by name + * + * @return array + */ + public function getHelpersByName() + { + return $this->_helpersByNameRef; + } + +} diff --git a/lib/zend/Zend/Controller/Action/Interface.php b/lib/zend/Zend/Controller/Action/Interface.php new file mode 100644 index 00000000000..db354637a10 --- /dev/null +++ b/lib/zend/Zend/Controller/Action/Interface.php @@ -0,0 +1,69 @@ +setParams($params); + } + + /** + * Formats a string into a controller name. This is used to take a raw + * controller name, such as one stored inside a Zend_Controller_Request_Abstract + * object, and reformat it to a proper class name that a class extending + * Zend_Controller_Action would use. + * + * @param string $unformatted + * @return string + */ + public function formatControllerName($unformatted) + { + return ucfirst($this->_formatName($unformatted)) . 'Controller'; + } + + /** + * Formats a string into an action name. This is used to take a raw + * action name, such as one that would be stored inside a Zend_Controller_Request_Abstract + * object, and reformat into a proper method name that would be found + * inside a class extending Zend_Controller_Action. + * + * @param string $unformatted + * @return string + */ + public function formatActionName($unformatted) + { + $formatted = $this->_formatName($unformatted, true); + return strtolower(substr($formatted, 0, 1)) . substr($formatted, 1) . 'Action'; + } + + /** + * Verify delimiter + * + * Verify a delimiter to use in controllers or actions. May be a single + * string or an array of strings. + * + * @param string|array $spec + * @return array + * @throws Zend_Controller_Dispatcher_Exception with invalid delimiters + */ + public function _verifyDelimiter($spec) + { + if (is_string($spec)) { + return (array) $spec; + } elseif (is_array($spec)) { + $allStrings = true; + foreach ($spec as $delim) { + if (!is_string($delim)) { + $allStrings = false; + break; + } + } + + if (!$allStrings) { + require_once 'Zend/Controller/Dispatcher/Exception.php'; + throw new Zend_Controller_Dispatcher_Exception('Word delimiter array must contain only strings'); + } + + return $spec; + } + + require_once 'Zend/Controller/Dispatcher/Exception.php'; + throw new Zend_Controller_Dispatcher_Exception('Invalid word delimiter'); + } + + /** + * Retrieve the word delimiter character(s) used in + * controller or action names + * + * @return array + */ + public function getWordDelimiter() + { + return $this->_wordDelimiter; + } + + /** + * Set word delimiter + * + * Set the word delimiter to use in controllers and actions. May be a + * single string or an array of strings. + * + * @param string|array $spec + * @return Zend_Controller_Dispatcher_Abstract + */ + public function setWordDelimiter($spec) + { + $spec = $this->_verifyDelimiter($spec); + $this->_wordDelimiter = $spec; + + return $this; + } + + /** + * Retrieve the path delimiter character(s) used in + * controller names + * + * @return array + */ + public function getPathDelimiter() + { + return $this->_pathDelimiter; + } + + /** + * Set path delimiter + * + * Set the path delimiter to use in controllers. May be a single string or + * an array of strings. + * + * @param string $spec + * @return Zend_Controller_Dispatcher_Abstract + */ + public function setPathDelimiter($spec) + { + if (!is_string($spec)) { + require_once 'Zend/Controller/Dispatcher/Exception.php'; + throw new Zend_Controller_Dispatcher_Exception('Invalid path delimiter'); + } + $this->_pathDelimiter = $spec; + + return $this; + } + + /** + * Formats a string from a URI into a PHP-friendly name. + * + * By default, replaces words separated by the word separator character(s) + * with camelCaps. If $isAction is false, it also preserves replaces words + * separated by the path separation character with an underscore, making + * the following word Title cased. All non-alphanumeric characters are + * removed. + * + * @param string $unformatted + * @param boolean $isAction Defaults to false + * @return string + */ + protected function _formatName($unformatted, $isAction = false) + { + // preserve directories + if (!$isAction) { + $segments = explode($this->getPathDelimiter(), $unformatted); + } else { + $segments = (array) $unformatted; + } + + foreach ($segments as $key => $segment) { + $segment = str_replace($this->getWordDelimiter(), ' ', strtolower($segment)); + $segment = preg_replace('/[^a-z0-9 ]/', '', $segment); + $segments[$key] = str_replace(' ', '', ucwords($segment)); + } + + return implode('_', $segments); + } + + /** + * Retrieve front controller instance + * + * @return Zend_Controller_Front + */ + public function getFrontController() + { + if (null === $this->_frontController) { + require_once 'Zend/Controller/Front.php'; + $this->_frontController = Zend_Controller_Front::getInstance(); + } + + return $this->_frontController; + } + + /** + * Set front controller instance + * + * @param Zend_Controller_Front $controller + * @return Zend_Controller_Dispatcher_Abstract + */ + public function setFrontController(Zend_Controller_Front $controller) + { + $this->_frontController = $controller; + return $this; + } + + /** + * Add or modify a parameter to use when instantiating an action controller + * + * @param string $name + * @param mixed $value + * @return Zend_Controller_Dispatcher_Abstract + */ + public function setParam($name, $value) + { + $name = (string) $name; + $this->_invokeParams[$name] = $value; + return $this; + } + + /** + * Set parameters to pass to action controller constructors + * + * @param array $params + * @return Zend_Controller_Dispatcher_Abstract + */ + public function setParams(array $params) + { + $this->_invokeParams = array_merge($this->_invokeParams, $params); + return $this; + } + + /** + * Retrieve a single parameter from the controller parameter stack + * + * @param string $name + * @return mixed + */ + public function getParam($name) + { + if(isset($this->_invokeParams[$name])) { + return $this->_invokeParams[$name]; + } + + return null; + } + + /** + * Retrieve action controller instantiation parameters + * + * @return array + */ + public function getParams() + { + return $this->_invokeParams; + } + + /** + * Clear the controller parameter stack + * + * By default, clears all parameters. If a parameter name is given, clears + * only that parameter; if an array of parameter names is provided, clears + * each. + * + * @param null|string|array single key or array of keys for params to clear + * @return Zend_Controller_Dispatcher_Abstract + */ + public function clearParams($name = null) + { + if (null === $name) { + $this->_invokeParams = array(); + } elseif (is_string($name) && isset($this->_invokeParams[$name])) { + unset($this->_invokeParams[$name]); + } elseif (is_array($name)) { + foreach ($name as $key) { + if (is_string($key) && isset($this->_invokeParams[$key])) { + unset($this->_invokeParams[$key]); + } + } + } + + return $this; + } + + /** + * Set response object to pass to action controllers + * + * @param Zend_Controller_Response_Abstract|null $response + * @return Zend_Controller_Dispatcher_Abstract + */ + public function setResponse(Zend_Controller_Response_Abstract $response = null) + { + $this->_response = $response; + return $this; + } + + /** + * Return the registered response object + * + * @return Zend_Controller_Response_Abstract|null + */ + public function getResponse() + { + return $this->_response; + } + + /** + * Set the default controller (minus any formatting) + * + * @param string $controller + * @return Zend_Controller_Dispatcher_Abstract + */ + public function setDefaultControllerName($controller) + { + $this->_defaultController = (string) $controller; + return $this; + } + + /** + * Retrieve the default controller name (minus formatting) + * + * @return string + */ + public function getDefaultControllerName() + { + return $this->_defaultController; + } + + /** + * Set the default action (minus any formatting) + * + * @param string $action + * @return Zend_Controller_Dispatcher_Abstract + */ + public function setDefaultAction($action) + { + $this->_defaultAction = (string) $action; + return $this; + } + + /** + * Retrieve the default action name (minus formatting) + * + * @return string + */ + public function getDefaultAction() + { + return $this->_defaultAction; + } + + /** + * Set the default module + * + * @param string $module + * @return Zend_Controller_Dispatcher_Abstract + */ + public function setDefaultModule($module) + { + $this->_defaultModule = (string) $module; + return $this; + } + + /** + * Retrieve the default module + * + * @return string + */ + public function getDefaultModule() + { + return $this->_defaultModule; + } +} diff --git a/lib/zend/Zend/Controller/Dispatcher/Exception.php b/lib/zend/Zend/Controller/Dispatcher/Exception.php new file mode 100644 index 00000000000..42404449663 --- /dev/null +++ b/lib/zend/Zend/Controller/Dispatcher/Exception.php @@ -0,0 +1,37 @@ +_curModule = $this->getDefaultModule(); + } + + /** + * Add a single path to the controller directory stack + * + * @param string $path + * @param string $module + * @return Zend_Controller_Dispatcher_Standard + */ + public function addControllerDirectory($path, $module = null) + { + if (null === $module) { + $module = $this->_defaultModule; + } + + $module = (string) $module; + $path = rtrim((string) $path, '/\\'); + + $this->_controllerDirectory[$module] = $path; + return $this; + } + + /** + * Set controller directory + * + * @param array|string $directory + * @return Zend_Controller_Dispatcher_Standard + */ + public function setControllerDirectory($directory, $module = null) + { + $this->_controllerDirectory = array(); + + if (is_string($directory)) { + $this->addControllerDirectory($directory, $module); + } elseif (is_array($directory)) { + foreach ((array) $directory as $module => $path) { + $this->addControllerDirectory($path, $module); + } + } else { + require_once 'Zend/Controller/Exception.php'; + throw new Zend_Controller_Exception('Controller directory spec must be either a string or an array'); + } + + return $this; + } + + /** + * Return the currently set directories for Zend_Controller_Action class + * lookup + * + * If a module is specified, returns just that directory. + * + * @param string $module Module name + * @return array|string Returns array of all directories by default, single + * module directory if module argument provided + */ + public function getControllerDirectory($module = null) + { + if (null === $module) { + return $this->_controllerDirectory; + } + + $module = (string) $module; + if (array_key_exists($module, $this->_controllerDirectory)) { + return $this->_controllerDirectory[$module]; + } + + return null; + } + + /** + * Remove a controller directory by module name + * + * @param string $module + * @return bool + */ + public function removeControllerDirectory($module) + { + $module = (string) $module; + if (array_key_exists($module, $this->_controllerDirectory)) { + unset($this->_controllerDirectory[$module]); + return true; + } + return false; + } + + /** + * Format the module name. + * + * @param string $unformatted + * @return string + */ + public function formatModuleName($unformatted) + { + if (($this->_defaultModule == $unformatted) && !$this->getParam('prefixDefaultModule')) { + return $unformatted; + } + + return ucfirst($this->_formatName($unformatted)); + } + + /** + * Format action class name + * + * @param string $moduleName Name of the current module + * @param string $className Name of the action class + * @return string Formatted class name + */ + public function formatClassName($moduleName, $className) + { + return $this->formatModuleName($moduleName) . '_' . $className; + } + + /** + * Convert a class name to a filename + * + * @param string $class + * @return string + */ + public function classToFilename($class) + { + return str_replace('_', DIRECTORY_SEPARATOR, $class) . '.php'; + } + + /** + * Returns TRUE if the Zend_Controller_Request_Abstract object can be + * dispatched to a controller. + * + * Use this method wisely. By default, the dispatcher will fall back to the + * default controller (either in the module specified or the global default) + * if a given controller does not exist. This method returning false does + * not necessarily indicate the dispatcher will not still dispatch the call. + * + * @param Zend_Controller_Request_Abstract $action + * @return boolean + */ + public function isDispatchable(Zend_Controller_Request_Abstract $request) + { + $className = $this->getControllerClass($request); + if (!$className) { + return false; + } + + $finalClass = $className; + if (($this->_defaultModule != $this->_curModule) + || $this->getParam('prefixDefaultModule')) + { + $finalClass = $this->formatClassName($this->_curModule, $className); + } + if (class_exists($finalClass, false)) { + return true; + } + + $fileSpec = $this->classToFilename($className); + $dispatchDir = $this->getDispatchDirectory(); + $test = $dispatchDir . DIRECTORY_SEPARATOR . $fileSpec; + return Zend_Loader::isReadable($test); + } + + /** + * Dispatch to a controller/action + * + * By default, if a controller is not dispatchable, dispatch() will throw + * an exception. If you wish to use the default controller instead, set the + * param 'useDefaultControllerAlways' via {@link setParam()}. + * + * @param Zend_Controller_Request_Abstract $request + * @param Zend_Controller_Response_Abstract $response + * @return void + * @throws Zend_Controller_Dispatcher_Exception + */ + public function dispatch(Zend_Controller_Request_Abstract $request, Zend_Controller_Response_Abstract $response) + { + $this->setResponse($response); + + /** + * Get controller class + */ + if (!$this->isDispatchable($request)) { + $controller = $request->getControllerName(); + if (!$this->getParam('useDefaultControllerAlways') && !empty($controller)) { + require_once 'Zend/Controller/Dispatcher/Exception.php'; + throw new Zend_Controller_Dispatcher_Exception('Invalid controller specified (' . $request->getControllerName() . ')'); + } + + $className = $this->getDefaultControllerClass($request); + } else { + $className = $this->getControllerClass($request); + if (!$className) { + $className = $this->getDefaultControllerClass($request); + } + } + + /** + * If we're in a module or prefixDefaultModule is on, we must add the module name + * prefix to the contents of $className, as getControllerClass does not do that automatically. + * We must keep a separate variable because modules are not strictly PSR-0: We need the no-module-prefix + * class name to do the class->file mapping, but the full class name to insantiate the controller + */ + $moduleClassName = $className; + if (($this->_defaultModule != $this->_curModule) + || $this->getParam('prefixDefaultModule')) + { + $moduleClassName = $this->formatClassName($this->_curModule, $className); + } + + /** + * Load the controller class file + */ + $className = $this->loadClass($className); + + /** + * Instantiate controller with request, response, and invocation + * arguments; throw exception if it's not an action controller + */ + $controller = new $moduleClassName($request, $this->getResponse(), $this->getParams()); + if (!($controller instanceof Zend_Controller_Action_Interface) && + !($controller instanceof Zend_Controller_Action)) { + require_once 'Zend/Controller/Dispatcher/Exception.php'; + throw new Zend_Controller_Dispatcher_Exception( + 'Controller "' . $moduleClassName . '" is not an instance of Zend_Controller_Action_Interface' + ); + } + + /** + * Retrieve the action name + */ + $action = $this->getActionMethod($request); + + /** + * Dispatch the method call + */ + $request->setDispatched(true); + + // by default, buffer output + $disableOb = $this->getParam('disableOutputBuffering'); + $obLevel = ob_get_level(); + if (empty($disableOb)) { + ob_start(); + } + + try { + $controller->dispatch($action); + } catch (Exception $e) { + // Clean output buffer on error + $curObLevel = ob_get_level(); + if ($curObLevel > $obLevel) { + do { + ob_get_clean(); + $curObLevel = ob_get_level(); + } while ($curObLevel > $obLevel); + } + throw $e; + } + + if (empty($disableOb)) { + $content = ob_get_clean(); + $response->appendBody($content); + } + + // Destroy the page controller instance and reflection objects + $controller = null; + } + + /** + * Load a controller class + * + * Attempts to load the controller class file from + * {@link getControllerDirectory()}. If the controller belongs to a + * module, looks for the module prefix to the controller class. + * + * @param string $className + * @return string Class name loaded + * @throws Zend_Controller_Dispatcher_Exception if class not loaded + */ + public function loadClass($className) + { + $finalClass = $className; + if (($this->_defaultModule != $this->_curModule) + || $this->getParam('prefixDefaultModule')) + { + $finalClass = $this->formatClassName($this->_curModule, $className); + } + if (class_exists($finalClass, false)) { + return $finalClass; + } + + $dispatchDir = $this->getDispatchDirectory(); + $loadFile = $dispatchDir . DIRECTORY_SEPARATOR . $this->classToFilename($className); + + if (Zend_Loader::isReadable($loadFile)) { + include_once $loadFile; + } else { + require_once 'Zend/Controller/Dispatcher/Exception.php'; + throw new Zend_Controller_Dispatcher_Exception('Cannot load controller class "' . $className . '" from file "' . $loadFile . "'"); + } + + if (!class_exists($finalClass, false)) { + require_once 'Zend/Controller/Dispatcher/Exception.php'; + throw new Zend_Controller_Dispatcher_Exception('Invalid controller class ("' . $finalClass . '")'); + } + + return $finalClass; + } + + /** + * Get controller class name + * + * Try request first; if not found, try pulling from request parameter; + * if still not found, fallback to default + * + * @param Zend_Controller_Request_Abstract $request + * @return string|false Returns class name on success + */ + public function getControllerClass(Zend_Controller_Request_Abstract $request) + { + $controllerName = $request->getControllerName(); + if (empty($controllerName)) { + if (!$this->getParam('useDefaultControllerAlways')) { + return false; + } + $controllerName = $this->getDefaultControllerName(); + $request->setControllerName($controllerName); + } + + $className = $this->formatControllerName($controllerName); + + $controllerDirs = $this->getControllerDirectory(); + $module = $request->getModuleName(); + if ($this->isValidModule($module)) { + $this->_curModule = $module; + $this->_curDirectory = $controllerDirs[$module]; + } elseif ($this->isValidModule($this->_defaultModule)) { + $request->setModuleName($this->_defaultModule); + $this->_curModule = $this->_defaultModule; + $this->_curDirectory = $controllerDirs[$this->_defaultModule]; + } else { + require_once 'Zend/Controller/Exception.php'; + throw new Zend_Controller_Exception('No default module defined for this application'); + } + + return $className; + } + + /** + * Determine if a given module is valid + * + * @param string $module + * @return bool + */ + public function isValidModule($module) + { + if (!is_string($module)) { + return false; + } + + $module = strtolower($module); + $controllerDir = $this->getControllerDirectory(); + foreach (array_keys($controllerDir) as $moduleName) { + if ($module == strtolower($moduleName)) { + return true; + } + } + + return false; + } + + /** + * Retrieve default controller class + * + * Determines whether the default controller to use lies within the + * requested module, or if the global default should be used. + * + * By default, will only use the module default unless that controller does + * not exist; if this is the case, it falls back to the default controller + * in the default module. + * + * @param Zend_Controller_Request_Abstract $request + * @return string + */ + public function getDefaultControllerClass(Zend_Controller_Request_Abstract $request) + { + $controller = $this->getDefaultControllerName(); + $default = $this->formatControllerName($controller); + $request->setControllerName($controller) + ->setActionName(null); + + $module = $request->getModuleName(); + $controllerDirs = $this->getControllerDirectory(); + $this->_curModule = $this->_defaultModule; + $this->_curDirectory = $controllerDirs[$this->_defaultModule]; + if ($this->isValidModule($module)) { + $found = false; + if (class_exists($default, false)) { + $found = true; + } else { + $moduleDir = $controllerDirs[$module]; + $fileSpec = $moduleDir . DIRECTORY_SEPARATOR . $this->classToFilename($default); + if (Zend_Loader::isReadable($fileSpec)) { + $found = true; + $this->_curDirectory = $moduleDir; + } + } + if ($found) { + $request->setModuleName($module); + $this->_curModule = $this->formatModuleName($module); + } + } else { + $request->setModuleName($this->_defaultModule); + } + + return $default; + } + + /** + * Return the value of the currently selected dispatch directory (as set by + * {@link getController()}) + * + * @return string + */ + public function getDispatchDirectory() + { + return $this->_curDirectory; + } + + /** + * Determine the action name + * + * First attempt to retrieve from request; then from request params + * using action key; default to default action + * + * Returns formatted action name + * + * @param Zend_Controller_Request_Abstract $request + * @return string + */ + public function getActionMethod(Zend_Controller_Request_Abstract $request) + { + $action = $request->getActionName(); + if (empty($action)) { + $action = $this->getDefaultAction(); + $request->setActionName($action); + } + + return $this->formatActionName($action); + } +} diff --git a/lib/zend/Zend/Controller/Exception.php b/lib/zend/Zend/Controller/Exception.php new file mode 100644 index 00000000000..b36853c425c --- /dev/null +++ b/lib/zend/Zend/Controller/Exception.php @@ -0,0 +1,35 @@ +_plugins = new Zend_Controller_Plugin_Broker(); + } + + /** + * Enforce singleton; disallow cloning + * + * @return void + */ + private function __clone() + { + } + + /** + * Singleton instance + * + * @return Zend_Controller_Front + */ + public static function getInstance() + { + if (null === self::$_instance) { + self::$_instance = new self(); + } + + return self::$_instance; + } + + /** + * Resets all object properties of the singleton instance + * + * Primarily used for testing; could be used to chain front controllers. + * + * Also resets action helper broker, clearing all registered helpers. + * + * @return void + */ + public function resetInstance() + { + $reflection = new ReflectionObject($this); + foreach ($reflection->getProperties() as $property) { + $name = $property->getName(); + switch ($name) { + case '_instance': + break; + case '_controllerDir': + case '_invokeParams': + $this->{$name} = array(); + break; + case '_plugins': + $this->{$name} = new Zend_Controller_Plugin_Broker(); + break; + case '_throwExceptions': + case '_returnResponse': + $this->{$name} = false; + break; + case '_moduleControllerDirectoryName': + $this->{$name} = 'controllers'; + break; + default: + $this->{$name} = null; + break; + } + } + Zend_Controller_Action_HelperBroker::resetHelpers(); + } + + /** + * Convenience feature, calls setControllerDirectory()->setRouter()->dispatch() + * + * In PHP 5.1.x, a call to a static method never populates $this -- so run() + * may actually be called after setting up your front controller. + * + * @param string|array $controllerDirectory Path to Zend_Controller_Action + * controller classes or array of such paths + * @return void + * @throws Zend_Controller_Exception if called from an object instance + */ + public static function run($controllerDirectory) + { + self::getInstance() + ->setControllerDirectory($controllerDirectory) + ->dispatch(); + } + + /** + * Add a controller directory to the controller directory stack + * + * If $args is presented and is a string, uses it for the array key mapping + * to the directory specified. + * + * @param string $directory + * @param string $module Optional argument; module with which to associate directory. If none provided, assumes 'default' + * @return Zend_Controller_Front + * @throws Zend_Controller_Exception if directory not found or readable + */ + public function addControllerDirectory($directory, $module = null) + { + $this->getDispatcher()->addControllerDirectory($directory, $module); + return $this; + } + + /** + * Set controller directory + * + * Stores controller directory(ies) in dispatcher. May be an array of + * directories or a string containing a single directory. + * + * @param string|array $directory Path to Zend_Controller_Action controller + * classes or array of such paths + * @param string $module Optional module name to use with string $directory + * @return Zend_Controller_Front + */ + public function setControllerDirectory($directory, $module = null) + { + $this->getDispatcher()->setControllerDirectory($directory, $module); + return $this; + } + + /** + * Retrieve controller directory + * + * Retrieves: + * - Array of all controller directories if no $name passed + * - String path if $name passed and exists as a key in controller directory array + * - null if $name passed but does not exist in controller directory keys + * + * @param string $name Default null + * @return array|string|null + */ + public function getControllerDirectory($name = null) + { + return $this->getDispatcher()->getControllerDirectory($name); + } + + /** + * Remove a controller directory by module name + * + * @param string $module + * @return bool + */ + public function removeControllerDirectory($module) + { + return $this->getDispatcher()->removeControllerDirectory($module); + } + + /** + * Specify a directory as containing modules + * + * Iterates through the directory, adding any subdirectories as modules; + * the subdirectory within each module named after {@link $_moduleControllerDirectoryName} + * will be used as the controller directory path. + * + * @param string $path + * @return Zend_Controller_Front + */ + public function addModuleDirectory($path) + { + try{ + $dir = new DirectoryIterator($path); + } catch(Exception $e) { + require_once 'Zend/Controller/Exception.php'; + throw new Zend_Controller_Exception("Directory $path not readable", 0, $e); + } + foreach ($dir as $file) { + if ($file->isDot() || !$file->isDir()) { + continue; + } + + $module = $file->getFilename(); + + // Don't use SCCS directories as modules + if (preg_match('/^[^a-z]/i', $module) || ('CVS' == $module)) { + continue; + } + + $moduleDir = $file->getPathname() . DIRECTORY_SEPARATOR . $this->getModuleControllerDirectoryName(); + $this->addControllerDirectory($moduleDir, $module); + } + + return $this; + } + + /** + * Return the path to a module directory (but not the controllers directory within) + * + * @param string $module + * @return string|null + */ + public function getModuleDirectory($module = null) + { + if (null === $module) { + $request = $this->getRequest(); + if (null !== $request) { + $module = $this->getRequest()->getModuleName(); + } + if (empty($module)) { + $module = $this->getDispatcher()->getDefaultModule(); + } + } + + $controllerDir = $this->getControllerDirectory($module); + + if ((null === $controllerDir) || !is_string($controllerDir)) { + return null; + } + + return dirname($controllerDir); + } + + /** + * Set the directory name within a module containing controllers + * + * @param string $name + * @return Zend_Controller_Front + */ + public function setModuleControllerDirectoryName($name = 'controllers') + { + $this->_moduleControllerDirectoryName = (string) $name; + + return $this; + } + + /** + * Return the directory name within a module containing controllers + * + * @return string + */ + public function getModuleControllerDirectoryName() + { + return $this->_moduleControllerDirectoryName; + } + + /** + * Set the default controller (unformatted string) + * + * @param string $controller + * @return Zend_Controller_Front + */ + public function setDefaultControllerName($controller) + { + $dispatcher = $this->getDispatcher(); + $dispatcher->setDefaultControllerName($controller); + return $this; + } + + /** + * Retrieve the default controller (unformatted string) + * + * @return string + */ + public function getDefaultControllerName() + { + return $this->getDispatcher()->getDefaultControllerName(); + } + + /** + * Set the default action (unformatted string) + * + * @param string $action + * @return Zend_Controller_Front + */ + public function setDefaultAction($action) + { + $dispatcher = $this->getDispatcher(); + $dispatcher->setDefaultAction($action); + return $this; + } + + /** + * Retrieve the default action (unformatted string) + * + * @return string + */ + public function getDefaultAction() + { + return $this->getDispatcher()->getDefaultAction(); + } + + /** + * Set the default module name + * + * @param string $module + * @return Zend_Controller_Front + */ + public function setDefaultModule($module) + { + $dispatcher = $this->getDispatcher(); + $dispatcher->setDefaultModule($module); + return $this; + } + + /** + * Retrieve the default module + * + * @return string + */ + public function getDefaultModule() + { + return $this->getDispatcher()->getDefaultModule(); + } + + /** + * Set request class/object + * + * Set the request object. The request holds the request environment. + * + * If a class name is provided, it will instantiate it + * + * @param string|Zend_Controller_Request_Abstract $request + * @throws Zend_Controller_Exception if invalid request class + * @return Zend_Controller_Front + */ + public function setRequest($request) + { + if (is_string($request)) { + if (!class_exists($request)) { + require_once 'Zend/Loader.php'; + Zend_Loader::loadClass($request); + } + $request = new $request(); + } + if (!$request instanceof Zend_Controller_Request_Abstract) { + require_once 'Zend/Controller/Exception.php'; + throw new Zend_Controller_Exception('Invalid request class'); + } + + $this->_request = $request; + + return $this; + } + + /** + * Return the request object. + * + * @return null|Zend_Controller_Request_Abstract + */ + public function getRequest() + { + return $this->_request; + } + + /** + * Set router class/object + * + * Set the router object. The router is responsible for mapping + * the request to a controller and action. + * + * If a class name is provided, instantiates router with any parameters + * registered via {@link setParam()} or {@link setParams()}. + * + * @param string|Zend_Controller_Router_Interface $router + * @throws Zend_Controller_Exception if invalid router class + * @return Zend_Controller_Front + */ + public function setRouter($router) + { + if (is_string($router)) { + if (!class_exists($router)) { + require_once 'Zend/Loader.php'; + Zend_Loader::loadClass($router); + } + $router = new $router(); + } + + if (!$router instanceof Zend_Controller_Router_Interface) { + require_once 'Zend/Controller/Exception.php'; + throw new Zend_Controller_Exception('Invalid router class'); + } + + $router->setFrontController($this); + $this->_router = $router; + + return $this; + } + + /** + * Return the router object. + * + * Instantiates a Zend_Controller_Router_Rewrite object if no router currently set. + * + * @return Zend_Controller_Router_Interface + */ + public function getRouter() + { + if (null == $this->_router) { + require_once 'Zend/Controller/Router/Rewrite.php'; + $this->setRouter(new Zend_Controller_Router_Rewrite()); + } + + return $this->_router; + } + + /** + * Set the base URL used for requests + * + * Use to set the base URL segment of the REQUEST_URI to use when + * determining PATH_INFO, etc. Examples: + * - /admin + * - /myapp + * - /subdir/index.php + * + * Note that the URL should not include the full URI. Do not use: + * - http://example.com/admin + * - http://example.com/myapp + * - http://example.com/subdir/index.php + * + * If a null value is passed, this can be used as well for autodiscovery (default). + * + * @param string $base + * @return Zend_Controller_Front + * @throws Zend_Controller_Exception for non-string $base + */ + public function setBaseUrl($base = null) + { + if (!is_string($base) && (null !== $base)) { + require_once 'Zend/Controller/Exception.php'; + throw new Zend_Controller_Exception('Rewrite base must be a string'); + } + + $this->_baseUrl = $base; + + if ((null !== ($request = $this->getRequest())) && (method_exists($request, 'setBaseUrl'))) { + $request->setBaseUrl($base); + } + + return $this; + } + + /** + * Retrieve the currently set base URL + * + * @return string + */ + public function getBaseUrl() + { + $request = $this->getRequest(); + if ((null !== $request) && method_exists($request, 'getBaseUrl')) { + return $request->getBaseUrl(); + } + + return $this->_baseUrl; + } + + /** + * Set the dispatcher object. The dispatcher is responsible for + * taking a Zend_Controller_Dispatcher_Token object, instantiating the controller, and + * call the action method of the controller. + * + * @param Zend_Controller_Dispatcher_Interface $dispatcher + * @return Zend_Controller_Front + */ + public function setDispatcher(Zend_Controller_Dispatcher_Interface $dispatcher) + { + $this->_dispatcher = $dispatcher; + return $this; + } + + /** + * Return the dispatcher object. + * + * @return Zend_Controller_Dispatcher_Interface + */ + public function getDispatcher() + { + /** + * Instantiate the default dispatcher if one was not set. + */ + if (!$this->_dispatcher instanceof Zend_Controller_Dispatcher_Interface) { + require_once 'Zend/Controller/Dispatcher/Standard.php'; + $this->_dispatcher = new Zend_Controller_Dispatcher_Standard(); + } + return $this->_dispatcher; + } + + /** + * Set response class/object + * + * Set the response object. The response is a container for action + * responses and headers. Usage is optional. + * + * If a class name is provided, instantiates a response object. + * + * @param string|Zend_Controller_Response_Abstract $response + * @throws Zend_Controller_Exception if invalid response class + * @return Zend_Controller_Front + */ + public function setResponse($response) + { + if (is_string($response)) { + if (!class_exists($response)) { + require_once 'Zend/Loader.php'; + Zend_Loader::loadClass($response); + } + $response = new $response(); + } + if (!$response instanceof Zend_Controller_Response_Abstract) { + require_once 'Zend/Controller/Exception.php'; + throw new Zend_Controller_Exception('Invalid response class'); + } + + $this->_response = $response; + + return $this; + } + + /** + * Return the response object. + * + * @return null|Zend_Controller_Response_Abstract + */ + public function getResponse() + { + return $this->_response; + } + + /** + * Add or modify a parameter to use when instantiating an action controller + * + * @param string $name + * @param mixed $value + * @return Zend_Controller_Front + */ + public function setParam($name, $value) + { + $name = (string) $name; + $this->_invokeParams[$name] = $value; + return $this; + } + + /** + * Set parameters to pass to action controller constructors + * + * @param array $params + * @return Zend_Controller_Front + */ + public function setParams(array $params) + { + $this->_invokeParams = array_merge($this->_invokeParams, $params); + return $this; + } + + /** + * Retrieve a single parameter from the controller parameter stack + * + * @param string $name + * @return mixed + */ + public function getParam($name) + { + if(isset($this->_invokeParams[$name])) { + return $this->_invokeParams[$name]; + } + + return null; + } + + /** + * Retrieve action controller instantiation parameters + * + * @return array + */ + public function getParams() + { + return $this->_invokeParams; + } + + /** + * Clear the controller parameter stack + * + * By default, clears all parameters. If a parameter name is given, clears + * only that parameter; if an array of parameter names is provided, clears + * each. + * + * @param null|string|array single key or array of keys for params to clear + * @return Zend_Controller_Front + */ + public function clearParams($name = null) + { + if (null === $name) { + $this->_invokeParams = array(); + } elseif (is_string($name) && isset($this->_invokeParams[$name])) { + unset($this->_invokeParams[$name]); + } elseif (is_array($name)) { + foreach ($name as $key) { + if (is_string($key) && isset($this->_invokeParams[$key])) { + unset($this->_invokeParams[$key]); + } + } + } + + return $this; + } + + /** + * Register a plugin. + * + * @param Zend_Controller_Plugin_Abstract $plugin + * @param int $stackIndex Optional; stack index for plugin + * @return Zend_Controller_Front + */ + public function registerPlugin(Zend_Controller_Plugin_Abstract $plugin, $stackIndex = null) + { + $this->_plugins->registerPlugin($plugin, $stackIndex); + return $this; + } + + /** + * Unregister a plugin. + * + * @param string|Zend_Controller_Plugin_Abstract $plugin Plugin class or object to unregister + * @return Zend_Controller_Front + */ + public function unregisterPlugin($plugin) + { + $this->_plugins->unregisterPlugin($plugin); + return $this; + } + + /** + * Is a particular plugin registered? + * + * @param string $class + * @return bool + */ + public function hasPlugin($class) + { + return $this->_plugins->hasPlugin($class); + } + + /** + * Retrieve a plugin or plugins by class + * + * @param string $class + * @return false|Zend_Controller_Plugin_Abstract|array + */ + public function getPlugin($class) + { + return $this->_plugins->getPlugin($class); + } + + /** + * Retrieve all plugins + * + * @return array + */ + public function getPlugins() + { + return $this->_plugins->getPlugins(); + } + + /** + * Set the throwExceptions flag and retrieve current status + * + * Set whether exceptions encounted in the dispatch loop should be thrown + * or caught and trapped in the response object. + * + * Default behaviour is to trap them in the response object; call this + * method to have them thrown. + * + * Passing no value will return the current value of the flag; passing a + * boolean true or false value will set the flag and return the current + * object instance. + * + * @param boolean $flag Defaults to null (return flag state) + * @return boolean|Zend_Controller_Front Used as a setter, returns object; as a getter, returns boolean + */ + public function throwExceptions($flag = null) + { + if ($flag !== null) { + $this->_throwExceptions = (bool) $flag; + return $this; + } + + return $this->_throwExceptions; + } + + /** + * Set whether {@link dispatch()} should return the response without first + * rendering output. By default, output is rendered and dispatch() returns + * nothing. + * + * @param boolean $flag + * @return boolean|Zend_Controller_Front Used as a setter, returns object; as a getter, returns boolean + */ + public function returnResponse($flag = null) + { + if (true === $flag) { + $this->_returnResponse = true; + return $this; + } elseif (false === $flag) { + $this->_returnResponse = false; + return $this; + } + + return $this->_returnResponse; + } + + /** + * Dispatch an HTTP request to a controller/action. + * + * @param Zend_Controller_Request_Abstract|null $request + * @param Zend_Controller_Response_Abstract|null $response + * @return void|Zend_Controller_Response_Abstract Returns response object if returnResponse() is true + */ + public function dispatch(Zend_Controller_Request_Abstract $request = null, Zend_Controller_Response_Abstract $response = null) + { + if (!$this->getParam('noErrorHandler') && !$this->_plugins->hasPlugin('Zend_Controller_Plugin_ErrorHandler')) { + // Register with stack index of 100 + require_once 'Zend/Controller/Plugin/ErrorHandler.php'; + $this->_plugins->registerPlugin(new Zend_Controller_Plugin_ErrorHandler(), 100); + } + + if (!$this->getParam('noViewRenderer') && !Zend_Controller_Action_HelperBroker::hasHelper('viewRenderer')) { + require_once 'Zend/Controller/Action/Helper/ViewRenderer.php'; + Zend_Controller_Action_HelperBroker::getStack()->offsetSet(-80, new Zend_Controller_Action_Helper_ViewRenderer()); + } + + /** + * Instantiate default request object (HTTP version) if none provided + */ + if (null !== $request) { + $this->setRequest($request); + } elseif ((null === $request) && (null === ($request = $this->getRequest()))) { + require_once 'Zend/Controller/Request/Http.php'; + $request = new Zend_Controller_Request_Http(); + $this->setRequest($request); + } + + /** + * Set base URL of request object, if available + */ + if (is_callable(array($this->_request, 'setBaseUrl'))) { + if (null !== $this->_baseUrl) { + $this->_request->setBaseUrl($this->_baseUrl); + } + } + + /** + * Instantiate default response object (HTTP version) if none provided + */ + if (null !== $response) { + $this->setResponse($response); + } elseif ((null === $this->_response) && (null === ($this->_response = $this->getResponse()))) { + require_once 'Zend/Controller/Response/Http.php'; + $response = new Zend_Controller_Response_Http(); + $this->setResponse($response); + } + + /** + * Register request and response objects with plugin broker + */ + $this->_plugins + ->setRequest($this->_request) + ->setResponse($this->_response); + + /** + * Initialize router + */ + $router = $this->getRouter(); + $router->setParams($this->getParams()); + + /** + * Initialize dispatcher + */ + $dispatcher = $this->getDispatcher(); + $dispatcher->setParams($this->getParams()) + ->setResponse($this->_response); + + // Begin dispatch + try { + /** + * Route request to controller/action, if a router is provided + */ + + /** + * Notify plugins of router startup + */ + $this->_plugins->routeStartup($this->_request); + + try { + $router->route($this->_request); + } catch (Exception $e) { + if ($this->throwExceptions()) { + throw $e; + } + + $this->_response->setException($e); + } + + /** + * Notify plugins of router completion + */ + $this->_plugins->routeShutdown($this->_request); + + /** + * Notify plugins of dispatch loop startup + */ + $this->_plugins->dispatchLoopStartup($this->_request); + + /** + * Attempt to dispatch the controller/action. If the $this->_request + * indicates that it needs to be dispatched, move to the next + * action in the request. + */ + do { + $this->_request->setDispatched(true); + + /** + * Notify plugins of dispatch startup + */ + $this->_plugins->preDispatch($this->_request); + + /** + * Skip requested action if preDispatch() has reset it + */ + if (!$this->_request->isDispatched()) { + continue; + } + + /** + * Dispatch request + */ + try { + $dispatcher->dispatch($this->_request, $this->_response); + } catch (Exception $e) { + if ($this->throwExceptions()) { + throw $e; + } + $this->_response->setException($e); + } + + /** + * Notify plugins of dispatch completion + */ + $this->_plugins->postDispatch($this->_request); + } while (!$this->_request->isDispatched()); + } catch (Exception $e) { + if ($this->throwExceptions()) { + throw $e; + } + + $this->_response->setException($e); + } + + /** + * Notify plugins of dispatch loop completion + */ + try { + $this->_plugins->dispatchLoopShutdown(); + } catch (Exception $e) { + if ($this->throwExceptions()) { + throw $e; + } + + $this->_response->setException($e); + } + + if ($this->returnResponse()) { + return $this->_response; + } + + $this->_response->sendResponse(); + } +} diff --git a/lib/zend/Zend/Controller/Plugin/Abstract.php b/lib/zend/Zend/Controller/Plugin/Abstract.php new file mode 100644 index 00000000000..7e590b7eef0 --- /dev/null +++ b/lib/zend/Zend/Controller/Plugin/Abstract.php @@ -0,0 +1,151 @@ +_request = $request; + return $this; + } + + /** + * Get request object + * + * @return Zend_Controller_Request_Abstract $request + */ + public function getRequest() + { + return $this->_request; + } + + /** + * Set response object + * + * @param Zend_Controller_Response_Abstract $response + * @return Zend_Controller_Plugin_Abstract + */ + public function setResponse(Zend_Controller_Response_Abstract $response) + { + $this->_response = $response; + return $this; + } + + /** + * Get response object + * + * @return Zend_Controller_Response_Abstract $response + */ + public function getResponse() + { + return $this->_response; + } + + /** + * Called before Zend_Controller_Front begins evaluating the + * request against its routes. + * + * @param Zend_Controller_Request_Abstract $request + * @return void + */ + public function routeStartup(Zend_Controller_Request_Abstract $request) + {} + + /** + * Called after Zend_Controller_Router exits. + * + * Called after Zend_Controller_Front exits from the router. + * + * @param Zend_Controller_Request_Abstract $request + * @return void + */ + public function routeShutdown(Zend_Controller_Request_Abstract $request) + {} + + /** + * Called before Zend_Controller_Front enters its dispatch loop. + * + * @param Zend_Controller_Request_Abstract $request + * @return void + */ + public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request) + {} + + /** + * Called before an action is dispatched by Zend_Controller_Dispatcher. + * + * This callback allows for proxy or filter behavior. By altering the + * request and resetting its dispatched flag (via + * {@link Zend_Controller_Request_Abstract::setDispatched() setDispatched(false)}), + * the current action may be skipped. + * + * @param Zend_Controller_Request_Abstract $request + * @return void + */ + public function preDispatch(Zend_Controller_Request_Abstract $request) + {} + + /** + * Called after an action is dispatched by Zend_Controller_Dispatcher. + * + * This callback allows for proxy or filter behavior. By altering the + * request and resetting its dispatched flag (via + * {@link Zend_Controller_Request_Abstract::setDispatched() setDispatched(false)}), + * a new action may be specified for dispatching. + * + * @param Zend_Controller_Request_Abstract $request + * @return void + */ + public function postDispatch(Zend_Controller_Request_Abstract $request) + {} + + /** + * Called before Zend_Controller_Front exits its dispatch loop. + * + * @return void + */ + public function dispatchLoopShutdown() + {} +} diff --git a/lib/zend/Zend/Controller/Plugin/ActionStack.php b/lib/zend/Zend/Controller/Plugin/ActionStack.php new file mode 100644 index 00000000000..12c62de1127 --- /dev/null +++ b/lib/zend/Zend/Controller/Plugin/ActionStack.php @@ -0,0 +1,280 @@ +setRegistry($registry); + + if (null !== $key) { + $this->setRegistryKey($key); + } else { + $key = $this->getRegistryKey(); + } + + $registry[$key] = array(); + } + + /** + * Set registry object + * + * @param Zend_Registry $registry + * @return Zend_Controller_Plugin_ActionStack + */ + public function setRegistry(Zend_Registry $registry) + { + $this->_registry = $registry; + return $this; + } + + /** + * Retrieve registry object + * + * @return Zend_Registry + */ + public function getRegistry() + { + return $this->_registry; + } + + /** + * Retrieve registry key + * + * @return string + */ + public function getRegistryKey() + { + return $this->_registryKey; + } + + /** + * Set registry key + * + * @param string $key + * @return Zend_Controller_Plugin_ActionStack + */ + public function setRegistryKey($key) + { + $this->_registryKey = (string) $key; + return $this; + } + + /** + * Set clearRequestParams flag + * + * @param bool $clearRequestParams + * @return Zend_Controller_Plugin_ActionStack + */ + public function setClearRequestParams($clearRequestParams) + { + $this->_clearRequestParams = (bool) $clearRequestParams; + return $this; + } + + /** + * Retrieve clearRequestParams flag + * + * @return bool + */ + public function getClearRequestParams() + { + return $this->_clearRequestParams; + } + + /** + * Retrieve action stack + * + * @return array + */ + public function getStack() + { + $registry = $this->getRegistry(); + $stack = $registry[$this->getRegistryKey()]; + return $stack; + } + + /** + * Save stack to registry + * + * @param array $stack + * @return Zend_Controller_Plugin_ActionStack + */ + protected function _saveStack(array $stack) + { + $registry = $this->getRegistry(); + $registry[$this->getRegistryKey()] = $stack; + return $this; + } + + /** + * Push an item onto the stack + * + * @param Zend_Controller_Request_Abstract $next + * @return Zend_Controller_Plugin_ActionStack + */ + public function pushStack(Zend_Controller_Request_Abstract $next) + { + $stack = $this->getStack(); + array_push($stack, $next); + return $this->_saveStack($stack); + } + + /** + * Pop an item off the action stack + * + * @return false|Zend_Controller_Request_Abstract + */ + public function popStack() + { + $stack = $this->getStack(); + if (0 == count($stack)) { + return false; + } + + $next = array_pop($stack); + $this->_saveStack($stack); + + if (!$next instanceof Zend_Controller_Request_Abstract) { + require_once 'Zend/Controller/Exception.php'; + throw new Zend_Controller_Exception('ArrayStack should only contain request objects'); + } + $action = $next->getActionName(); + if (empty($action)) { + return $this->popStack($stack); + } + + $request = $this->getRequest(); + $controller = $next->getControllerName(); + if (empty($controller)) { + $next->setControllerName($request->getControllerName()); + } + + $module = $next->getModuleName(); + if (empty($module)) { + $next->setModuleName($request->getModuleName()); + } + + return $next; + } + + /** + * postDispatch() plugin hook -- check for actions in stack, and dispatch if any found + * + * @param Zend_Controller_Request_Abstract $request + * @return void + */ + public function postDispatch(Zend_Controller_Request_Abstract $request) + { + // Don't move on to next request if this is already an attempt to + // forward + if (!$request->isDispatched()) { + return; + } + + $this->setRequest($request); + $stack = $this->getStack(); + if (empty($stack)) { + return; + } + $next = $this->popStack(); + if (!$next) { + return; + } + + $this->forward($next); + } + + /** + * Forward request with next action + * + * @param array $next + * @return void + */ + public function forward(Zend_Controller_Request_Abstract $next) + { + $request = $this->getRequest(); + if ($this->getClearRequestParams()) { + $request->clearParams(); + } + + $request->setModuleName($next->getModuleName()) + ->setControllerName($next->getControllerName()) + ->setActionName($next->getActionName()) + ->setParams($next->getParams()) + ->setDispatched(false); + } +} diff --git a/lib/zend/Zend/Controller/Plugin/Broker.php b/lib/zend/Zend/Controller/Plugin/Broker.php new file mode 100644 index 00000000000..1214583eb30 --- /dev/null +++ b/lib/zend/Zend/Controller/Plugin/Broker.php @@ -0,0 +1,365 @@ +_plugins, true)) { + require_once 'Zend/Controller/Exception.php'; + throw new Zend_Controller_Exception('Plugin already registered'); + } + + $stackIndex = (int) $stackIndex; + + if ($stackIndex) { + if (isset($this->_plugins[$stackIndex])) { + require_once 'Zend/Controller/Exception.php'; + throw new Zend_Controller_Exception('Plugin with stackIndex "' . $stackIndex . '" already registered'); + } + $this->_plugins[$stackIndex] = $plugin; + } else { + $stackIndex = count($this->_plugins); + while (isset($this->_plugins[$stackIndex])) { + ++$stackIndex; + } + $this->_plugins[$stackIndex] = $plugin; + } + + $request = $this->getRequest(); + if ($request) { + $this->_plugins[$stackIndex]->setRequest($request); + } + $response = $this->getResponse(); + if ($response) { + $this->_plugins[$stackIndex]->setResponse($response); + } + + ksort($this->_plugins); + + return $this; + } + + /** + * Unregister a plugin. + * + * @param string|Zend_Controller_Plugin_Abstract $plugin Plugin object or class name + * @return Zend_Controller_Plugin_Broker + */ + public function unregisterPlugin($plugin) + { + if ($plugin instanceof Zend_Controller_Plugin_Abstract) { + // Given a plugin object, find it in the array + $key = array_search($plugin, $this->_plugins, true); + if (false === $key) { + require_once 'Zend/Controller/Exception.php'; + throw new Zend_Controller_Exception('Plugin never registered.'); + } + unset($this->_plugins[$key]); + } elseif (is_string($plugin)) { + // Given a plugin class, find all plugins of that class and unset them + foreach ($this->_plugins as $key => $_plugin) { + $type = get_class($_plugin); + if ($plugin == $type) { + unset($this->_plugins[$key]); + } + } + } + return $this; + } + + /** + * Is a plugin of a particular class registered? + * + * @param string $class + * @return bool + */ + public function hasPlugin($class) + { + foreach ($this->_plugins as $plugin) { + $type = get_class($plugin); + if ($class == $type) { + return true; + } + } + + return false; + } + + /** + * Retrieve a plugin or plugins by class + * + * @param string $class Class name of plugin(s) desired + * @return false|Zend_Controller_Plugin_Abstract|array Returns false if none found, plugin if only one found, and array of plugins if multiple plugins of same class found + */ + public function getPlugin($class) + { + $found = array(); + foreach ($this->_plugins as $plugin) { + $type = get_class($plugin); + if ($class == $type) { + $found[] = $plugin; + } + } + + switch (count($found)) { + case 0: + return false; + case 1: + return $found[0]; + default: + return $found; + } + } + + /** + * Retrieve all plugins + * + * @return array + */ + public function getPlugins() + { + return $this->_plugins; + } + + /** + * Set request object, and register with each plugin + * + * @param Zend_Controller_Request_Abstract $request + * @return Zend_Controller_Plugin_Broker + */ + public function setRequest(Zend_Controller_Request_Abstract $request) + { + $this->_request = $request; + + foreach ($this->_plugins as $plugin) { + $plugin->setRequest($request); + } + + return $this; + } + + /** + * Get request object + * + * @return Zend_Controller_Request_Abstract $request + */ + public function getRequest() + { + return $this->_request; + } + + /** + * Set response object + * + * @param Zend_Controller_Response_Abstract $response + * @return Zend_Controller_Plugin_Broker + */ + public function setResponse(Zend_Controller_Response_Abstract $response) + { + $this->_response = $response; + + foreach ($this->_plugins as $plugin) { + $plugin->setResponse($response); + } + + + return $this; + } + + /** + * Get response object + * + * @return Zend_Controller_Response_Abstract $response + */ + public function getResponse() + { + return $this->_response; + } + + + /** + * Called before Zend_Controller_Front begins evaluating the + * request against its routes. + * + * @param Zend_Controller_Request_Abstract $request + * @return void + */ + public function routeStartup(Zend_Controller_Request_Abstract $request) + { + foreach ($this->_plugins as $plugin) { + try { + $plugin->routeStartup($request); + } catch (Exception $e) { + if (Zend_Controller_Front::getInstance()->throwExceptions()) { + throw new Zend_Controller_Exception($e->getMessage() . $e->getTraceAsString(), $e->getCode(), $e); + } else { + $this->getResponse()->setException($e); + } + } + } + } + + + /** + * Called before Zend_Controller_Front exits its iterations over + * the route set. + * + * @param Zend_Controller_Request_Abstract $request + * @return void + */ + public function routeShutdown(Zend_Controller_Request_Abstract $request) + { + foreach ($this->_plugins as $plugin) { + try { + $plugin->routeShutdown($request); + } catch (Exception $e) { + if (Zend_Controller_Front::getInstance()->throwExceptions()) { + throw new Zend_Controller_Exception($e->getMessage() . $e->getTraceAsString(), $e->getCode(), $e); + } else { + $this->getResponse()->setException($e); + } + } + } + } + + + /** + * Called before Zend_Controller_Front enters its dispatch loop. + * + * During the dispatch loop, Zend_Controller_Front keeps a + * Zend_Controller_Request_Abstract object, and uses + * Zend_Controller_Dispatcher to dispatch the + * Zend_Controller_Request_Abstract object to controllers/actions. + * + * @param Zend_Controller_Request_Abstract $request + * @return void + */ + public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request) + { + foreach ($this->_plugins as $plugin) { + try { + $plugin->dispatchLoopStartup($request); + } catch (Exception $e) { + if (Zend_Controller_Front::getInstance()->throwExceptions()) { + throw new Zend_Controller_Exception($e->getMessage() . $e->getTraceAsString(), $e->getCode(), $e); + } else { + $this->getResponse()->setException($e); + } + } + } + } + + + /** + * Called before an action is dispatched by Zend_Controller_Dispatcher. + * + * @param Zend_Controller_Request_Abstract $request + * @return void + */ + public function preDispatch(Zend_Controller_Request_Abstract $request) + { + foreach ($this->_plugins as $plugin) { + try { + $plugin->preDispatch($request); + } catch (Exception $e) { + if (Zend_Controller_Front::getInstance()->throwExceptions()) { + throw new Zend_Controller_Exception($e->getMessage() . $e->getTraceAsString(), $e->getCode(), $e); + } else { + $this->getResponse()->setException($e); + // skip rendering of normal dispatch give the error handler a try + $this->getRequest()->setDispatched(false); + } + } + } + } + + + /** + * Called after an action is dispatched by Zend_Controller_Dispatcher. + * + * @param Zend_Controller_Request_Abstract $request + * @return void + */ + public function postDispatch(Zend_Controller_Request_Abstract $request) + { + foreach ($this->_plugins as $plugin) { + try { + $plugin->postDispatch($request); + } catch (Exception $e) { + if (Zend_Controller_Front::getInstance()->throwExceptions()) { + throw new Zend_Controller_Exception($e->getMessage() . $e->getTraceAsString(), $e->getCode(), $e); + } else { + $this->getResponse()->setException($e); + } + } + } + } + + + /** + * Called before Zend_Controller_Front exits its dispatch loop. + * + * @param Zend_Controller_Request_Abstract $request + * @return void + */ + public function dispatchLoopShutdown() + { + foreach ($this->_plugins as $plugin) { + try { + $plugin->dispatchLoopShutdown(); + } catch (Exception $e) { + if (Zend_Controller_Front::getInstance()->throwExceptions()) { + throw new Zend_Controller_Exception($e->getMessage() . $e->getTraceAsString(), $e->getCode(), $e); + } else { + $this->getResponse()->setException($e); + } + } + } + } +} diff --git a/lib/zend/Zend/Controller/Plugin/ErrorHandler.php b/lib/zend/Zend/Controller/Plugin/ErrorHandler.php new file mode 100644 index 00000000000..42da1633c64 --- /dev/null +++ b/lib/zend/Zend/Controller/Plugin/ErrorHandler.php @@ -0,0 +1,300 @@ +setErrorHandler($options); + } + + /** + * setErrorHandler() - setup the error handling options + * + * @param array $options + * @return Zend_Controller_Plugin_ErrorHandler + */ + public function setErrorHandler(Array $options = array()) + { + if (isset($options['module'])) { + $this->setErrorHandlerModule($options['module']); + } + if (isset($options['controller'])) { + $this->setErrorHandlerController($options['controller']); + } + if (isset($options['action'])) { + $this->setErrorHandlerAction($options['action']); + } + return $this; + } + + /** + * Set the module name for the error handler + * + * @param string $module + * @return Zend_Controller_Plugin_ErrorHandler + */ + public function setErrorHandlerModule($module) + { + $this->_errorModule = (string) $module; + return $this; + } + + /** + * Retrieve the current error handler module + * + * @return string + */ + public function getErrorHandlerModule() + { + if (null === $this->_errorModule) { + $this->_errorModule = Zend_Controller_Front::getInstance()->getDispatcher()->getDefaultModule(); + } + return $this->_errorModule; + } + + /** + * Set the controller name for the error handler + * + * @param string $controller + * @return Zend_Controller_Plugin_ErrorHandler + */ + public function setErrorHandlerController($controller) + { + $this->_errorController = (string) $controller; + return $this; + } + + /** + * Retrieve the current error handler controller + * + * @return string + */ + public function getErrorHandlerController() + { + return $this->_errorController; + } + + /** + * Set the action name for the error handler + * + * @param string $action + * @return Zend_Controller_Plugin_ErrorHandler + */ + public function setErrorHandlerAction($action) + { + $this->_errorAction = (string) $action; + return $this; + } + + /** + * Retrieve the current error handler action + * + * @return string + */ + public function getErrorHandlerAction() + { + return $this->_errorAction; + } + + /** + * Route shutdown hook -- Ccheck for router exceptions + * + * @param Zend_Controller_Request_Abstract $request + */ + public function routeShutdown(Zend_Controller_Request_Abstract $request) + { + $this->_handleError($request); + } + + /** + * Pre dispatch hook -- check for exceptions and dispatch error handler if + * necessary + * + * @param Zend_Controller_Request_Abstract $request + */ + public function preDispatch(Zend_Controller_Request_Abstract $request) + { + $this->_handleError($request); + } + + /** + * Post dispatch hook -- check for exceptions and dispatch error handler if + * necessary + * + * @param Zend_Controller_Request_Abstract $request + */ + public function postDispatch(Zend_Controller_Request_Abstract $request) + { + $this->_handleError($request); + } + + /** + * Handle errors and exceptions + * + * If the 'noErrorHandler' front controller flag has been set, + * returns early. + * + * @param Zend_Controller_Request_Abstract $request + * @return void + */ + protected function _handleError(Zend_Controller_Request_Abstract $request) + { + $frontController = Zend_Controller_Front::getInstance(); + if ($frontController->getParam('noErrorHandler')) { + return; + } + + $response = $this->getResponse(); + + if ($this->_isInsideErrorHandlerLoop) { + $exceptions = $response->getException(); + if (count($exceptions) > $this->_exceptionCountAtFirstEncounter) { + // Exception thrown by error handler; tell the front controller to throw it + $frontController->throwExceptions(true); + throw array_pop($exceptions); + } + } + + // check for an exception AND allow the error handler controller the option to forward + if (($response->isException()) && (!$this->_isInsideErrorHandlerLoop)) { + $this->_isInsideErrorHandlerLoop = true; + + // Get exception information + $error = new ArrayObject(array(), ArrayObject::ARRAY_AS_PROPS); + $exceptions = $response->getException(); + $exception = $exceptions[0]; + $exceptionType = get_class($exception); + $error->exception = $exception; + switch ($exceptionType) { + case 'Zend_Controller_Router_Exception': + if (404 == $exception->getCode()) { + $error->type = self::EXCEPTION_NO_ROUTE; + } else { + $error->type = self::EXCEPTION_OTHER; + } + break; + case 'Zend_Controller_Dispatcher_Exception': + $error->type = self::EXCEPTION_NO_CONTROLLER; + break; + case 'Zend_Controller_Action_Exception': + if (404 == $exception->getCode()) { + $error->type = self::EXCEPTION_NO_ACTION; + } else { + $error->type = self::EXCEPTION_OTHER; + } + break; + default: + $error->type = self::EXCEPTION_OTHER; + break; + } + + // Keep a copy of the original request + $error->request = clone $request; + + // get a count of the number of exceptions encountered + $this->_exceptionCountAtFirstEncounter = count($exceptions); + + // Forward to the error handler + $request->setParam('error_handler', $error) + ->setModuleName($this->getErrorHandlerModule()) + ->setControllerName($this->getErrorHandlerController()) + ->setActionName($this->getErrorHandlerAction()) + ->setDispatched(false); + } + } +} diff --git a/lib/zend/Zend/Controller/Plugin/PutHandler.php b/lib/zend/Zend/Controller/Plugin/PutHandler.php new file mode 100644 index 00000000000..3b5f57b9102 --- /dev/null +++ b/lib/zend/Zend/Controller/Plugin/PutHandler.php @@ -0,0 +1,60 @@ +_request->isPut()) { + $putParams = array(); + parse_str($this->_request->getRawBody(), $putParams); + $request->setParams($putParams); + } + } +} diff --git a/lib/zend/Zend/Controller/Request/Abstract.php b/lib/zend/Zend/Controller/Request/Abstract.php new file mode 100644 index 00000000000..d57238f46be --- /dev/null +++ b/lib/zend/Zend/Controller/Request/Abstract.php @@ -0,0 +1,356 @@ +_module) { + $this->_module = $this->getParam($this->getModuleKey()); + } + + return $this->_module; + } + + /** + * Set the module name to use + * + * @param string $value + * @return Zend_Controller_Request_Abstract + */ + public function setModuleName($value) + { + $this->_module = $value; + return $this; + } + + /** + * Retrieve the controller name + * + * @return string + */ + public function getControllerName() + { + if (null === $this->_controller) { + $this->_controller = $this->getParam($this->getControllerKey()); + } + + return $this->_controller; + } + + /** + * Set the controller name to use + * + * @param string $value + * @return Zend_Controller_Request_Abstract + */ + public function setControllerName($value) + { + $this->_controller = $value; + return $this; + } + + /** + * Retrieve the action name + * + * @return string + */ + public function getActionName() + { + if (null === $this->_action) { + $this->_action = $this->getParam($this->getActionKey()); + } + + return $this->_action; + } + + /** + * Set the action name + * + * @param string $value + * @return Zend_Controller_Request_Abstract + */ + public function setActionName($value) + { + $this->_action = $value; + /** + * @see ZF-3465 + */ + if (null === $value) { + $this->setParam($this->getActionKey(), $value); + } + return $this; + } + + /** + * Retrieve the module key + * + * @return string + */ + public function getModuleKey() + { + return $this->_moduleKey; + } + + /** + * Set the module key + * + * @param string $key + * @return Zend_Controller_Request_Abstract + */ + public function setModuleKey($key) + { + $this->_moduleKey = (string) $key; + return $this; + } + + /** + * Retrieve the controller key + * + * @return string + */ + public function getControllerKey() + { + return $this->_controllerKey; + } + + /** + * Set the controller key + * + * @param string $key + * @return Zend_Controller_Request_Abstract + */ + public function setControllerKey($key) + { + $this->_controllerKey = (string) $key; + return $this; + } + + /** + * Retrieve the action key + * + * @return string + */ + public function getActionKey() + { + return $this->_actionKey; + } + + /** + * Set the action key + * + * @param string $key + * @return Zend_Controller_Request_Abstract + */ + public function setActionKey($key) + { + $this->_actionKey = (string) $key; + return $this; + } + + /** + * Get an action parameter + * + * @param string $key + * @param mixed $default Default value to use if key not found + * @return mixed + */ + public function getParam($key, $default = null) + { + $key = (string) $key; + if (isset($this->_params[$key])) { + return $this->_params[$key]; + } + + return $default; + } + + /** + * Retrieve only user params (i.e, any param specific to the object and not the environment) + * + * @return array + */ + public function getUserParams() + { + return $this->_params; + } + + /** + * Retrieve a single user param (i.e, a param specific to the object and not the environment) + * + * @param string $key + * @param string $default Default value to use if key not found + * @return mixed + */ + public function getUserParam($key, $default = null) + { + if (isset($this->_params[$key])) { + return $this->_params[$key]; + } + + return $default; + } + + /** + * Set an action parameter + * + * A $value of null will unset the $key if it exists + * + * @param string $key + * @param mixed $value + * @return Zend_Controller_Request_Abstract + */ + public function setParam($key, $value) + { + $key = (string) $key; + + if ((null === $value) && isset($this->_params[$key])) { + unset($this->_params[$key]); + } elseif (null !== $value) { + $this->_params[$key] = $value; + } + + return $this; + } + + /** + * Get all action parameters + * + * @return array + */ + public function getParams() + { + return $this->_params; + } + + /** + * Set action parameters en masse; does not overwrite + * + * Null values will unset the associated key. + * + * @param array $array + * @return Zend_Controller_Request_Abstract + */ + public function setParams(array $array) + { + $this->_params = $this->_params + (array) $array; + + foreach ($array as $key => $value) { + if (null === $value) { + unset($this->_params[$key]); + } + } + + return $this; + } + + /** + * Unset all user parameters + * + * @return Zend_Controller_Request_Abstract + */ + public function clearParams() + { + $this->_params = array(); + return $this; + } + + /** + * Set flag indicating whether or not request has been dispatched + * + * @param boolean $flag + * @return Zend_Controller_Request_Abstract + */ + public function setDispatched($flag = true) + { + $this->_dispatched = $flag ? true : false; + return $this; + } + + /** + * Determine if the request has been dispatched + * + * @return boolean + */ + public function isDispatched() + { + return $this->_dispatched; + } +} diff --git a/lib/zend/Zend/Controller/Request/Apache404.php b/lib/zend/Zend/Controller/Request/Apache404.php new file mode 100644 index 00000000000..3c4dd7ac487 --- /dev/null +++ b/lib/zend/Zend/Controller/Request/Apache404.php @@ -0,0 +1,82 @@ +_requestUri = $requestUri; + return $this; + } +} diff --git a/lib/zend/Zend/Controller/Request/Exception.php b/lib/zend/Zend/Controller/Request/Exception.php new file mode 100644 index 00000000000..a7e3629fdab --- /dev/null +++ b/lib/zend/Zend/Controller/Request/Exception.php @@ -0,0 +1,37 @@ +valid()) { + $path = $uri->getPath(); + $query = $uri->getQuery(); + if (!empty($query)) { + $path .= '?' . $query; + } + + $this->setRequestUri($path); + } else { + require_once 'Zend/Controller/Request/Exception.php'; + throw new Zend_Controller_Request_Exception('Invalid URI provided to constructor'); + } + } else { + $this->setRequestUri(); + } + } + + /** + * Access values contained in the superglobals as public members + * Order of precedence: 1. GET, 2. POST, 3. COOKIE, 4. SERVER, 5. ENV + * + * @see http://msdn.microsoft.com/en-us/library/system.web.httprequest.item.aspx + * @param string $key + * @return mixed + */ + public function __get($key) + { + switch (true) { + case isset($this->_params[$key]): + return $this->_params[$key]; + case isset($_GET[$key]): + return $_GET[$key]; + case isset($_POST[$key]): + return $_POST[$key]; + case isset($_COOKIE[$key]): + return $_COOKIE[$key]; + case ($key == 'REQUEST_URI'): + return $this->getRequestUri(); + case ($key == 'PATH_INFO'): + return $this->getPathInfo(); + case isset($_SERVER[$key]): + return $_SERVER[$key]; + case isset($_ENV[$key]): + return $_ENV[$key]; + default: + return null; + } + } + + /** + * Alias to __get + * + * @param string $key + * @return mixed + */ + public function get($key) + { + return $this->__get($key); + } + + /** + * Set values + * + * In order to follow {@link __get()}, which operates on a number of + * superglobals, setting values through overloading is not allowed and will + * raise an exception. Use setParam() instead. + * + * @param string $key + * @param mixed $value + * @return void + * @throws Zend_Controller_Request_Exception + */ + public function __set($key, $value) + { + require_once 'Zend/Controller/Request/Exception.php'; + throw new Zend_Controller_Request_Exception('Setting values in superglobals not allowed; please use setParam()'); + } + + /** + * Alias to __set() + * + * @param string $key + * @param mixed $value + * @return void + */ + public function set($key, $value) + { + return $this->__set($key, $value); + } + + /** + * Check to see if a property is set + * + * @param string $key + * @return boolean + */ + public function __isset($key) + { + switch (true) { + case isset($this->_params[$key]): + return true; + case isset($_GET[$key]): + return true; + case isset($_POST[$key]): + return true; + case isset($_COOKIE[$key]): + return true; + case isset($_SERVER[$key]): + return true; + case isset($_ENV[$key]): + return true; + default: + return false; + } + } + + /** + * Alias to __isset() + * + * @param string $key + * @return boolean + */ + public function has($key) + { + return $this->__isset($key); + } + + /** + * Set GET values + * + * @param string|array $spec + * @param null|mixed $value + * @return Zend_Controller_Request_Http + */ + public function setQuery($spec, $value = null) + { + if ((null === $value) && !is_array($spec)) { + require_once 'Zend/Controller/Exception.php'; + throw new Zend_Controller_Exception('Invalid value passed to setQuery(); must be either array of values or key/value pair'); + } + if ((null === $value) && is_array($spec)) { + foreach ($spec as $key => $value) { + $this->setQuery($key, $value); + } + return $this; + } + $_GET[(string) $spec] = $value; + return $this; + } + + /** + * Retrieve a member of the $_GET superglobal + * + * If no $key is passed, returns the entire $_GET array. + * + * @todo How to retrieve from nested arrays + * @param string $key + * @param mixed $default Default value to use if key not found + * @return mixed Returns null if key does not exist + */ + public function getQuery($key = null, $default = null) + { + if (null === $key) { + return $_GET; + } + + return (isset($_GET[$key])) ? $_GET[$key] : $default; + } + + /** + * Set POST values + * + * @param string|array $spec + * @param null|mixed $value + * @return Zend_Controller_Request_Http + */ + public function setPost($spec, $value = null) + { + if ((null === $value) && !is_array($spec)) { + require_once 'Zend/Controller/Exception.php'; + throw new Zend_Controller_Exception('Invalid value passed to setPost(); must be either array of values or key/value pair'); + } + if ((null === $value) && is_array($spec)) { + foreach ($spec as $key => $value) { + $this->setPost($key, $value); + } + return $this; + } + $_POST[(string) $spec] = $value; + return $this; + } + + /** + * Retrieve a member of the $_POST superglobal + * + * If no $key is passed, returns the entire $_POST array. + * + * @todo How to retrieve from nested arrays + * @param string $key + * @param mixed $default Default value to use if key not found + * @return mixed Returns null if key does not exist + */ + public function getPost($key = null, $default = null) + { + if (null === $key) { + return $_POST; + } + + return (isset($_POST[$key])) ? $_POST[$key] : $default; + } + + /** + * Retrieve a member of the $_COOKIE superglobal + * + * If no $key is passed, returns the entire $_COOKIE array. + * + * @todo How to retrieve from nested arrays + * @param string $key + * @param mixed $default Default value to use if key not found + * @return mixed Returns null if key does not exist + */ + public function getCookie($key = null, $default = null) + { + if (null === $key) { + return $_COOKIE; + } + + return (isset($_COOKIE[$key])) ? $_COOKIE[$key] : $default; + } + + /** + * Retrieve a member of the $_SERVER superglobal + * + * If no $key is passed, returns the entire $_SERVER array. + * + * @param string $key + * @param mixed $default Default value to use if key not found + * @return mixed Returns null if key does not exist + */ + public function getServer($key = null, $default = null) + { + if (null === $key) { + return $_SERVER; + } + + return (isset($_SERVER[$key])) ? $_SERVER[$key] : $default; + } + + /** + * Retrieve a member of the $_ENV superglobal + * + * If no $key is passed, returns the entire $_ENV array. + * + * @param string $key + * @param mixed $default Default value to use if key not found + * @return mixed Returns null if key does not exist + */ + public function getEnv($key = null, $default = null) + { + if (null === $key) { + return $_ENV; + } + + return (isset($_ENV[$key])) ? $_ENV[$key] : $default; + } + + /** + * Set the REQUEST_URI on which the instance operates + * + * If no request URI is passed, uses the value in $_SERVER['REQUEST_URI'], + * $_SERVER['HTTP_X_REWRITE_URL'], or $_SERVER['ORIG_PATH_INFO'] + $_SERVER['QUERY_STRING']. + * + * @param string $requestUri + * @return Zend_Controller_Request_Http + */ + public function setRequestUri($requestUri = null) + { + if ($requestUri === null) { + if (isset($_SERVER['HTTP_X_ORIGINAL_URL'])) { + // IIS with Microsoft Rewrite Module + $requestUri = $_SERVER['HTTP_X_ORIGINAL_URL']; + } elseif (isset($_SERVER['HTTP_X_REWRITE_URL'])) { + // IIS with ISAPI_Rewrite + $requestUri = $_SERVER['HTTP_X_REWRITE_URL']; + } elseif ( + // IIS7 with URL Rewrite: make sure we get the unencoded url (double slash problem) + isset($_SERVER['IIS_WasUrlRewritten']) + && $_SERVER['IIS_WasUrlRewritten'] == '1' + && isset($_SERVER['UNENCODED_URL']) + && $_SERVER['UNENCODED_URL'] != '' + ) { + $requestUri = $_SERVER['UNENCODED_URL']; + } elseif (isset($_SERVER['REQUEST_URI'])) { + $requestUri = $_SERVER['REQUEST_URI']; + // Http proxy reqs setup request uri with scheme and host [and port] + the url path, only use url path + $schemeAndHttpHost = $this->getScheme() . '://' . $this->getHttpHost(); + if (strpos($requestUri, $schemeAndHttpHost) === 0) { + $requestUri = substr($requestUri, strlen($schemeAndHttpHost)); + } + } elseif (isset($_SERVER['ORIG_PATH_INFO'])) { // IIS 5.0, PHP as CGI + $requestUri = $_SERVER['ORIG_PATH_INFO']; + if (!empty($_SERVER['QUERY_STRING'])) { + $requestUri .= '?' . $_SERVER['QUERY_STRING']; + } + } else { + return $this; + } + } elseif (!is_string($requestUri)) { + return $this; + } else { + // Set GET items, if available + if (false !== ($pos = strpos($requestUri, '?'))) { + // Get key => value pairs and set $_GET + $query = substr($requestUri, $pos + 1); + parse_str($query, $vars); + $this->setQuery($vars); + } + } + + $this->_requestUri = $requestUri; + return $this; + } + + /** + * Returns the REQUEST_URI taking into account + * platform differences between Apache and IIS + * + * @return string + */ + public function getRequestUri() + { + if (empty($this->_requestUri)) { + $this->setRequestUri(); + } + + return $this->_requestUri; + } + + /** + * Set the base URL of the request; i.e., the segment leading to the script name + * + * E.g.: + * - /admin + * - /myapp + * - /subdir/index.php + * + * Do not use the full URI when providing the base. The following are + * examples of what not to use: + * - http://example.com/admin (should be just /admin) + * - http://example.com/subdir/index.php (should be just /subdir/index.php) + * + * If no $baseUrl is provided, attempts to determine the base URL from the + * environment, using SCRIPT_FILENAME, SCRIPT_NAME, PHP_SELF, and + * ORIG_SCRIPT_NAME in its determination. + * + * @param mixed $baseUrl + * @return Zend_Controller_Request_Http + */ + public function setBaseUrl($baseUrl = null) + { + if ((null !== $baseUrl) && !is_string($baseUrl)) { + return $this; + } + + if ($baseUrl === null) { + $filename = (isset($_SERVER['SCRIPT_FILENAME'])) ? basename($_SERVER['SCRIPT_FILENAME']) : ''; + + if (isset($_SERVER['SCRIPT_NAME']) && basename($_SERVER['SCRIPT_NAME']) === $filename) { + $baseUrl = $_SERVER['SCRIPT_NAME']; + } elseif (isset($_SERVER['PHP_SELF']) && basename($_SERVER['PHP_SELF']) === $filename) { + $baseUrl = $_SERVER['PHP_SELF']; + } elseif (isset($_SERVER['ORIG_SCRIPT_NAME']) && basename($_SERVER['ORIG_SCRIPT_NAME']) === $filename) { + $baseUrl = $_SERVER['ORIG_SCRIPT_NAME']; // 1and1 shared hosting compatibility + } else { + // Backtrack up the script_filename to find the portion matching + // php_self + $path = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : ''; + $file = isset($_SERVER['SCRIPT_FILENAME']) ? $_SERVER['SCRIPT_FILENAME'] : ''; + $segs = explode('/', trim($file, '/')); + $segs = array_reverse($segs); + $index = 0; + $last = count($segs); + $baseUrl = ''; + do { + $seg = $segs[$index]; + $baseUrl = '/' . $seg . $baseUrl; + ++$index; + } while (($last > $index) && (false !== ($pos = strpos($path, $baseUrl))) && (0 != $pos)); + } + + // Does the baseUrl have anything in common with the request_uri? + $requestUri = $this->getRequestUri(); + + if (0 === strpos($requestUri, $baseUrl)) { + // full $baseUrl matches + $this->_baseUrl = $baseUrl; + return $this; + } + + if (0 === strpos($requestUri, dirname($baseUrl))) { + // directory portion of $baseUrl matches + $this->_baseUrl = rtrim(dirname($baseUrl), '/'); + return $this; + } + + $truncatedRequestUri = $requestUri; + if (($pos = strpos($requestUri, '?')) !== false) { + $truncatedRequestUri = substr($requestUri, 0, $pos); + } + + $basename = basename($baseUrl); + if (empty($basename) || !strpos($truncatedRequestUri, $basename)) { + // no match whatsoever; set it blank + $this->_baseUrl = ''; + return $this; + } + + // If using mod_rewrite or ISAPI_Rewrite strip the script filename + // out of baseUrl. $pos !== 0 makes sure it is not matching a value + // from PATH_INFO or QUERY_STRING + if ((strlen($requestUri) >= strlen($baseUrl)) + && ((false !== ($pos = strpos($requestUri, $baseUrl))) && ($pos !== 0))) + { + $baseUrl = substr($requestUri, 0, $pos + strlen($baseUrl)); + } + } + + $this->_baseUrl = rtrim($baseUrl, '/'); + return $this; + } + + /** + * Everything in REQUEST_URI before PATH_INFO + *
+ * + * @return string + */ + public function getBaseUrl($raw = false) + { + if (null === $this->_baseUrl) { + $this->setBaseUrl(); + } + + return (($raw == false) ? urldecode($this->_baseUrl) : $this->_baseUrl); + } + + /** + * Set the base path for the URL + * + * @param string|null $basePath + * @return Zend_Controller_Request_Http + */ + public function setBasePath($basePath = null) + { + if ($basePath === null) { + $filename = (isset($_SERVER['SCRIPT_FILENAME'])) + ? basename($_SERVER['SCRIPT_FILENAME']) + : ''; + + $baseUrl = $this->getBaseUrl(); + if (empty($baseUrl)) { + $this->_basePath = ''; + return $this; + } + + if (basename($baseUrl) === $filename) { + $basePath = dirname($baseUrl); + } else { + $basePath = $baseUrl; + } + } + + if (substr(PHP_OS, 0, 3) === 'WIN') { + $basePath = str_replace('\\', '/', $basePath); + } + + $this->_basePath = rtrim($basePath, '/'); + return $this; + } + + /** + * Everything in REQUEST_URI before PATH_INFO not including the filename + * + * + * @return string + */ + public function getBasePath() + { + if (null === $this->_basePath) { + $this->setBasePath(); + } + + return $this->_basePath; + } + + /** + * Set the PATH_INFO string + * + * @param string|null $pathInfo + * @return Zend_Controller_Request_Http + */ + public function setPathInfo($pathInfo = null) + { + if ($pathInfo === null) { + $baseUrl = $this->getBaseUrl(); // this actually calls setBaseUrl() & setRequestUri() + $baseUrlRaw = $this->getBaseUrl(false); + $baseUrlEncoded = urlencode($baseUrlRaw); + + if (null === ($requestUri = $this->getRequestUri())) { + return $this; + } + + // Remove the query string from REQUEST_URI + if ($pos = strpos($requestUri, '?')) { + $requestUri = substr($requestUri, 0, $pos); + } + + if (!empty($baseUrl) || !empty($baseUrlRaw)) { + if (strpos($requestUri, $baseUrl) === 0) { + $pathInfo = substr($requestUri, strlen($baseUrl)); + } elseif (strpos($requestUri, $baseUrlRaw) === 0) { + $pathInfo = substr($requestUri, strlen($baseUrlRaw)); + } elseif (strpos($requestUri, $baseUrlEncoded) === 0) { + $pathInfo = substr($requestUri, strlen($baseUrlEncoded)); + } else { + $pathInfo = $requestUri; + } + } else { + $pathInfo = $requestUri; + } + + } + + $this->_pathInfo = (string) $pathInfo; + return $this; + } + + /** + * Returns everything between the BaseUrl and QueryString. + * This value is calculated instead of reading PATH_INFO + * directly from $_SERVER due to cross-platform differences. + * + * @return string + */ + public function getPathInfo() + { + if (empty($this->_pathInfo)) { + $this->setPathInfo(); + } + + return $this->_pathInfo; + } + + /** + * Set allowed parameter sources + * + * Can be empty array, or contain one or more of '_GET' or '_POST'. + * + * @param array $paramSoures + * @return Zend_Controller_Request_Http + */ + public function setParamSources(array $paramSources = array()) + { + $this->_paramSources = $paramSources; + return $this; + } + + /** + * Get list of allowed parameter sources + * + * @return array + */ + public function getParamSources() + { + return $this->_paramSources; + } + + /** + * Set a userland parameter + * + * Uses $key to set a userland parameter. If $key is an alias, the actual + * key will be retrieved and used to set the parameter. + * + * @param mixed $key + * @param mixed $value + * @return Zend_Controller_Request_Http + */ + public function setParam($key, $value) + { + $key = (null !== ($alias = $this->getAlias($key))) ? $alias : $key; + parent::setParam($key, $value); + return $this; + } + + /** + * Retrieve a parameter + * + * Retrieves a parameter from the instance. Priority is in the order of + * userland parameters (see {@link setParam()}), $_GET, $_POST. If a + * parameter matching the $key is not found, null is returned. + * + * If the $key is an alias, the actual key aliased will be used. + * + * @param mixed $key + * @param mixed $default Default value to use if key not found + * @return mixed + */ + public function getParam($key, $default = null) + { + $keyName = (null !== ($alias = $this->getAlias($key))) ? $alias : $key; + + $paramSources = $this->getParamSources(); + if (isset($this->_params[$keyName])) { + return $this->_params[$keyName]; + } elseif (in_array('_GET', $paramSources) && (isset($_GET[$keyName]))) { + return $_GET[$keyName]; + } elseif (in_array('_POST', $paramSources) && (isset($_POST[$keyName]))) { + return $_POST[$keyName]; + } + + return $default; + } + + /** + * Retrieve an array of parameters + * + * Retrieves a merged array of parameters, with precedence of userland + * params (see {@link setParam()}), $_GET, $_POST (i.e., values in the + * userland params will take precedence over all others). + * + * @return array + */ + public function getParams() + { + $return = $this->_params; + $paramSources = $this->getParamSources(); + if (in_array('_GET', $paramSources) + && isset($_GET) + && is_array($_GET) + ) { + $return += $_GET; + } + if (in_array('_POST', $paramSources) + && isset($_POST) + && is_array($_POST) + ) { + $return += $_POST; + } + return $return; + } + + /** + * Set parameters + * + * Set one or more parameters. Parameters are set as userland parameters, + * using the keys specified in the array. + * + * @param array $params + * @return Zend_Controller_Request_Http + */ + public function setParams(array $params) + { + foreach ($params as $key => $value) { + $this->setParam($key, $value); + } + return $this; + } + + /** + * Set a key alias + * + * Set an alias used for key lookups. $name specifies the alias, $target + * specifies the actual key to use. + * + * @param string $name + * @param string $target + * @return Zend_Controller_Request_Http + */ + public function setAlias($name, $target) + { + $this->_aliases[$name] = $target; + return $this; + } + + /** + * Retrieve an alias + * + * Retrieve the actual key represented by the alias $name. + * + * @param string $name + * @return string|null Returns null when no alias exists + */ + public function getAlias($name) + { + if (isset($this->_aliases[$name])) { + return $this->_aliases[$name]; + } + + return null; + } + + /** + * Retrieve the list of all aliases + * + * @return array + */ + public function getAliases() + { + return $this->_aliases; + } + + /** + * Return the method by which the request was made + * + * @return string + */ + public function getMethod() + { + return $this->getServer('REQUEST_METHOD'); + } + + /** + * Was the request made by POST? + * + * @return boolean + */ + public function isPost() + { + if ('POST' == $this->getMethod()) { + return true; + } + + return false; + } + + /** + * Was the request made by GET? + * + * @return boolean + */ + public function isGet() + { + if ('GET' == $this->getMethod()) { + return true; + } + + return false; + } + + /** + * Was the request made by PUT? + * + * @return boolean + */ + public function isPut() + { + if ('PUT' == $this->getMethod()) { + return true; + } + + return false; + } + + /** + * Was the request made by DELETE? + * + * @return boolean + */ + public function isDelete() + { + if ('DELETE' == $this->getMethod()) { + return true; + } + + return false; + } + + /** + * Was the request made by HEAD? + * + * @return boolean + */ + public function isHead() + { + if ('HEAD' == $this->getMethod()) { + return true; + } + + return false; + } + + /** + * Was the request made by OPTIONS? + * + * @return boolean + */ + public function isOptions() + { + if ('OPTIONS' == $this->getMethod()) { + return true; + } + + return false; + } + + /** + * Was the request made by PATCH? + * + * @return boolean + */ + public function isPatch() + { + if ('PATCH' == $this->getMethod()) { + return true; + } + + return false; + } + + /** + * Is the request a Javascript XMLHttpRequest? + * + * Should work with Prototype/Script.aculo.us, possibly others. + * + * @return boolean + */ + public function isXmlHttpRequest() + { + return ($this->getHeader('X_REQUESTED_WITH') == 'XMLHttpRequest'); + } + + /** + * Is this a Flash request? + * + * @return boolean + */ + public function isFlashRequest() + { + $header = strtolower($this->getHeader('USER_AGENT')); + return (strstr($header, ' flash')) ? true : false; + } + + /** + * Is https secure request + * + * @return boolean + */ + public function isSecure() + { + return ($this->getScheme() === self::SCHEME_HTTPS); + } + + /** + * Return the raw body of the request, if present + * + * @return string|false Raw body, or false if not present + */ + public function getRawBody() + { + if (null === $this->_rawBody) { + $body = file_get_contents('php://input'); + + if (strlen(trim($body)) > 0) { + $this->_rawBody = $body; + } else { + $this->_rawBody = false; + } + } + return $this->_rawBody; + } + + /** + * Return the value of the given HTTP header. Pass the header name as the + * plain, HTTP-specified header name. Ex.: Ask for 'Accept' to get the + * Accept header, 'Accept-Encoding' to get the Accept-Encoding header. + * + * @param string $header HTTP header name + * @return string|false HTTP header value, or false if not found + * @throws Zend_Controller_Request_Exception + */ + public function getHeader($header) + { + if (empty($header)) { + require_once 'Zend/Controller/Request/Exception.php'; + throw new Zend_Controller_Request_Exception('An HTTP header name is required'); + } + + // Try to get it from the $_SERVER array first + $temp = strtoupper(str_replace('-', '_', $header)); + if (isset($_SERVER['HTTP_' . $temp])) { + return $_SERVER['HTTP_' . $temp]; + } + + /* + * Try to get it from the $_SERVER array on POST request or CGI environment + * @see https://www.ietf.org/rfc/rfc3875 (4.1.2. and 4.1.3.) + */ + if (isset($_SERVER[$temp]) + && in_array($temp, array('CONTENT_TYPE', 'CONTENT_LENGTH')) + ) { + return $_SERVER[$temp]; + } + + // This seems to be the only way to get the Authorization header on + // Apache + if (function_exists('apache_request_headers')) { + $headers = apache_request_headers(); + if (isset($headers[$header])) { + return $headers[$header]; + } + $header = strtolower($header); + foreach ($headers as $key => $value) { + if (strtolower($key) == $header) { + return $value; + } + } + } + + return false; + } + + /** + * Get the request URI scheme + * + * @return string + */ + public function getScheme() + { + return ($this->getServer('HTTPS') == 'on') ? self::SCHEME_HTTPS : self::SCHEME_HTTP; + } + + /** + * Get the HTTP host. + * + * "Host" ":" host [ ":" port ] ; Section 3.2.2 + * Note the HTTP Host header is not the same as the URI host. + * It includes the port while the URI host doesn't. + * + * @return string + */ + public function getHttpHost() + { + $host = $this->getServer('HTTP_HOST'); + if (!empty($host)) { + return $host; + } + + $scheme = $this->getScheme(); + $name = $this->getServer('SERVER_NAME'); + $port = $this->getServer('SERVER_PORT'); + + if(null === $name) { + return ''; + } + elseif (($scheme == self::SCHEME_HTTP && $port == 80) || ($scheme == self::SCHEME_HTTPS && $port == 443)) { + return $name; + } else { + return $name . ':' . $port; + } + } + + /** + * Get the client's IP addres + * + * @param boolean $checkProxy + * @return string + */ + public function getClientIp($checkProxy = true) + { + if ($checkProxy && $this->getServer('HTTP_CLIENT_IP') != null) { + $ip = $this->getServer('HTTP_CLIENT_IP'); + } else if ($checkProxy && $this->getServer('HTTP_X_FORWARDED_FOR') != null) { + $ip = $this->getServer('HTTP_X_FORWARDED_FOR'); + } else { + $ip = $this->getServer('REMOTE_ADDR'); + } + + return $ip; + } +} diff --git a/lib/zend/Zend/Controller/Request/HttpTestCase.php b/lib/zend/Zend/Controller/Request/HttpTestCase.php new file mode 100644 index 00000000000..58b9bd3936a --- /dev/null +++ b/lib/zend/Zend/Controller/Request/HttpTestCase.php @@ -0,0 +1,277 @@ +_rawBody = (string) $content; + return $this; + } + + /** + * Get RAW POST body + * + * @return string|null + */ + public function getRawBody() + { + return $this->_rawBody; + } + + /** + * Clear raw POST body + * + * @return Zend_Controller_Request_HttpTestCase + */ + public function clearRawBody() + { + $this->_rawBody = null; + return $this; + } + + /** + * Set a cookie + * + * @param string $key + * @param mixed $value + * @return Zend_Controller_Request_HttpTestCase + */ + public function setCookie($key, $value) + { + $_COOKIE[(string) $key] = $value; + return $this; + } + + /** + * Set multiple cookies at once + * + * @param array $cookies + * @return void + */ + public function setCookies(array $cookies) + { + foreach ($cookies as $key => $value) { + $_COOKIE[$key] = $value; + } + return $this; + } + + /** + * Clear all cookies + * + * @return Zend_Controller_Request_HttpTestCase + */ + public function clearCookies() + { + $_COOKIE = array(); + return $this; + } + + /** + * Set request method + * + * @param string $type + * @return Zend_Controller_Request_HttpTestCase + */ + public function setMethod($type) + { + $type = strtoupper(trim((string) $type)); + if (!in_array($type, $this->_validMethodTypes)) { + require_once 'Zend/Controller/Exception.php'; + throw new Zend_Controller_Exception('Invalid request method specified'); + } + $this->_method = $type; + return $this; + } + + /** + * Get request method + * + * @return string|null + */ + public function getMethod() + { + return $this->_method; + } + + /** + * Set a request header + * + * @param string $key + * @param string $value + * @return Zend_Controller_Request_HttpTestCase + */ + public function setHeader($key, $value) + { + $key = $this->_normalizeHeaderName($key); + $this->_headers[$key] = (string) $value; + return $this; + } + + /** + * Set request headers + * + * @param array $headers + * @return Zend_Controller_Request_HttpTestCase + */ + public function setHeaders(array $headers) + { + foreach ($headers as $key => $value) { + $this->setHeader($key, $value); + } + return $this; + } + + /** + * Get request header + * + * @param string $header + * @param mixed $default + * @return string|null + */ + public function getHeader($header, $default = null) + { + $header = $this->_normalizeHeaderName($header); + if (array_key_exists($header, $this->_headers)) { + return $this->_headers[$header]; + } + return $default; + } + + /** + * Get all request headers + * + * @return array + */ + public function getHeaders() + { + return $this->_headers; + } + + /** + * Clear request headers + * + * @return Zend_Controller_Request_HttpTestCase + */ + public function clearHeaders() + { + $this->_headers = array(); + return $this; + } + + /** + * Get REQUEST_URI + * + * @return null|string + */ + public function getRequestUri() + { + return $this->_requestUri; + } + + /** + * Normalize a header name for setting and retrieval + * + * @param string $name + * @return string + */ + protected function _normalizeHeaderName($name) + { + $name = strtoupper((string) $name); + $name = str_replace('-', '_', $name); + return $name; + } +} diff --git a/lib/zend/Zend/Controller/Request/Simple.php b/lib/zend/Zend/Controller/Request/Simple.php new file mode 100644 index 00000000000..74e4b0c4a10 --- /dev/null +++ b/lib/zend/Zend/Controller/Request/Simple.php @@ -0,0 +1,55 @@ +setActionName($action); + } + + if ($controller) { + $this->setControllerName($controller); + } + + if ($module) { + $this->setModuleName($module); + } + + if ($params) { + $this->setParams($params); + } + } + +} diff --git a/lib/zend/Zend/Controller/Response/Abstract.php b/lib/zend/Zend/Controller/Response/Abstract.php new file mode 100644 index 00000000000..9fcc22693e5 --- /dev/null +++ b/lib/zend/Zend/Controller/Response/Abstract.php @@ -0,0 +1,796 @@ +canSendHeaders(true); + $name = $this->_normalizeHeader($name); + $value = (string) $value; + + if ($replace) { + foreach ($this->_headers as $key => $header) { + if ($name == $header['name']) { + unset($this->_headers[$key]); + } + } + } + + $this->_headers[] = array( + 'name' => $name, + 'value' => $value, + 'replace' => $replace + ); + + return $this; + } + + /** + * Set redirect URL + * + * Sets Location header and response code. Forces replacement of any prior + * redirects. + * + * @param string $url + * @param int $code + * @return Zend_Controller_Response_Abstract + */ + public function setRedirect($url, $code = 302) + { + $this->canSendHeaders(true); + $this->setHeader('Location', $url, true) + ->setHttpResponseCode($code); + + return $this; + } + + /** + * Is this a redirect? + * + * @return boolean + */ + public function isRedirect() + { + return $this->_isRedirect; + } + + /** + * Return array of headers; see {@link $_headers} for format + * + * @return array + */ + public function getHeaders() + { + return $this->_headers; + } + + /** + * Clear headers + * + * @return Zend_Controller_Response_Abstract + */ + public function clearHeaders() + { + $this->_headers = array(); + + return $this; + } + + /** + * Clears the specified HTTP header + * + * @param string $name + * @return Zend_Controller_Response_Abstract + */ + public function clearHeader($name) + { + if (! count($this->_headers)) { + return $this; + } + + foreach ($this->_headers as $index => $header) { + if ($name == $header['name']) { + unset($this->_headers[$index]); + } + } + + return $this; + } + + /** + * Set raw HTTP header + * + * Allows setting non key => value headers, such as status codes + * + * @param string $value + * @return Zend_Controller_Response_Abstract + */ + public function setRawHeader($value) + { + $this->canSendHeaders(true); + if ('Location' == substr($value, 0, 8)) { + $this->_isRedirect = true; + } + $this->_headersRaw[] = (string) $value; + return $this; + } + + /** + * Retrieve all {@link setRawHeader() raw HTTP headers} + * + * @return array + */ + public function getRawHeaders() + { + return $this->_headersRaw; + } + + /** + * Clear all {@link setRawHeader() raw HTTP headers} + * + * @return Zend_Controller_Response_Abstract + */ + public function clearRawHeaders() + { + $this->_headersRaw = array(); + return $this; + } + + /** + * Clears the specified raw HTTP header + * + * @param string $headerRaw + * @return Zend_Controller_Response_Abstract + */ + public function clearRawHeader($headerRaw) + { + if (! count($this->_headersRaw)) { + return $this; + } + + $key = array_search($headerRaw, $this->_headersRaw); + if ($key !== false) { + unset($this->_headersRaw[$key]); + } + + return $this; + } + + /** + * Clear all headers, normal and raw + * + * @return Zend_Controller_Response_Abstract + */ + public function clearAllHeaders() + { + return $this->clearHeaders() + ->clearRawHeaders(); + } + + /** + * Set HTTP response code to use with headers + * + * @param int $code + * @return Zend_Controller_Response_Abstract + */ + public function setHttpResponseCode($code) + { + if (!is_int($code) || (100 > $code) || (599 < $code)) { + require_once 'Zend/Controller/Response/Exception.php'; + throw new Zend_Controller_Response_Exception('Invalid HTTP response code'); + } + + if ((300 <= $code) && (307 >= $code)) { + $this->_isRedirect = true; + } else { + $this->_isRedirect = false; + } + + $this->_httpResponseCode = $code; + return $this; + } + + /** + * Retrieve HTTP response code + * + * @return int + */ + public function getHttpResponseCode() + { + return $this->_httpResponseCode; + } + + /** + * Can we send headers? + * + * @param boolean $throw Whether or not to throw an exception if headers have been sent; defaults to false + * @return boolean + * @throws Zend_Controller_Response_Exception + */ + public function canSendHeaders($throw = false) + { + $ok = headers_sent($file, $line); + if ($ok && $throw && $this->headersSentThrowsException) { + require_once 'Zend/Controller/Response/Exception.php'; + throw new Zend_Controller_Response_Exception('Cannot send headers; headers already sent in ' . $file . ', line ' . $line); + } + + return !$ok; + } + + /** + * Send all headers + * + * Sends any headers specified. If an {@link setHttpResponseCode() HTTP response code} + * has been specified, it is sent with the first header. + * + * @return Zend_Controller_Response_Abstract + */ + public function sendHeaders() + { + // Only check if we can send headers if we have headers to send + if (count($this->_headersRaw) || count($this->_headers) || (200 != $this->_httpResponseCode)) { + $this->canSendHeaders(true); + } elseif (200 == $this->_httpResponseCode) { + // Haven't changed the response code, and we have no headers + return $this; + } + + $httpCodeSent = false; + + foreach ($this->_headersRaw as $header) { + if (!$httpCodeSent && $this->_httpResponseCode) { + header($header, true, $this->_httpResponseCode); + $httpCodeSent = true; + } else { + header($header); + } + } + + foreach ($this->_headers as $header) { + if (!$httpCodeSent && $this->_httpResponseCode) { + header($header['name'] . ': ' . $header['value'], $header['replace'], $this->_httpResponseCode); + $httpCodeSent = true; + } else { + header($header['name'] . ': ' . $header['value'], $header['replace']); + } + } + + if (!$httpCodeSent) { + header('HTTP/1.1 ' . $this->_httpResponseCode); + $httpCodeSent = true; + } + + return $this; + } + + /** + * Set body content + * + * If $name is not passed, or is not a string, resets the entire body and + * sets the 'default' key to $content. + * + * If $name is a string, sets the named segment in the body array to + * $content. + * + * @param string $content + * @param null|string $name + * @return Zend_Controller_Response_Abstract + */ + public function setBody($content, $name = null) + { + if ((null === $name) || !is_string($name)) { + $this->_body = array('default' => (string) $content); + } else { + $this->_body[$name] = (string) $content; + } + + return $this; + } + + /** + * Append content to the body content + * + * @param string $content + * @param null|string $name + * @return Zend_Controller_Response_Abstract + */ + public function appendBody($content, $name = null) + { + if ((null === $name) || !is_string($name)) { + if (isset($this->_body['default'])) { + $this->_body['default'] .= (string) $content; + } else { + return $this->append('default', $content); + } + } elseif (isset($this->_body[$name])) { + $this->_body[$name] .= (string) $content; + } else { + return $this->append($name, $content); + } + + return $this; + } + + /** + * Clear body array + * + * With no arguments, clears the entire body array. Given a $name, clears + * just that named segment; if no segment matching $name exists, returns + * false to indicate an error. + * + * @param string $name Named segment to clear + * @return boolean + */ + public function clearBody($name = null) + { + if (null !== $name) { + $name = (string) $name; + if (isset($this->_body[$name])) { + unset($this->_body[$name]); + return true; + } + + return false; + } + + $this->_body = array(); + return true; + } + + /** + * Return the body content + * + * If $spec is false, returns the concatenated values of the body content + * array. If $spec is boolean true, returns the body content array. If + * $spec is a string and matches a named segment, returns the contents of + * that segment; otherwise, returns null. + * + * @param boolean $spec + * @return string|array|null + */ + public function getBody($spec = false) + { + if (false === $spec) { + ob_start(); + $this->outputBody(); + return ob_get_clean(); + } elseif (true === $spec) { + return $this->_body; + } elseif (is_string($spec) && isset($this->_body[$spec])) { + return $this->_body[$spec]; + } + + return null; + } + + /** + * Append a named body segment to the body content array + * + * If segment already exists, replaces with $content and places at end of + * array. + * + * @param string $name + * @param string $content + * @return Zend_Controller_Response_Abstract + */ + public function append($name, $content) + { + if (!is_string($name)) { + require_once 'Zend/Controller/Response/Exception.php'; + throw new Zend_Controller_Response_Exception('Invalid body segment key ("' . gettype($name) . '")'); + } + + if (isset($this->_body[$name])) { + unset($this->_body[$name]); + } + $this->_body[$name] = (string) $content; + return $this; + } + + /** + * Prepend a named body segment to the body content array + * + * If segment already exists, replaces with $content and places at top of + * array. + * + * @param string $name + * @param string $content + * @return void + */ + public function prepend($name, $content) + { + if (!is_string($name)) { + require_once 'Zend/Controller/Response/Exception.php'; + throw new Zend_Controller_Response_Exception('Invalid body segment key ("' . gettype($name) . '")'); + } + + if (isset($this->_body[$name])) { + unset($this->_body[$name]); + } + + $new = array($name => (string) $content); + $this->_body = $new + $this->_body; + + return $this; + } + + /** + * Insert a named segment into the body content array + * + * @param string $name + * @param string $content + * @param string $parent + * @param boolean $before Whether to insert the new segment before or + * after the parent. Defaults to false (after) + * @return Zend_Controller_Response_Abstract + */ + public function insert($name, $content, $parent = null, $before = false) + { + if (!is_string($name)) { + require_once 'Zend/Controller/Response/Exception.php'; + throw new Zend_Controller_Response_Exception('Invalid body segment key ("' . gettype($name) . '")'); + } + + if ((null !== $parent) && !is_string($parent)) { + require_once 'Zend/Controller/Response/Exception.php'; + throw new Zend_Controller_Response_Exception('Invalid body segment parent key ("' . gettype($parent) . '")'); + } + + if (isset($this->_body[$name])) { + unset($this->_body[$name]); + } + + if ((null === $parent) || !isset($this->_body[$parent])) { + return $this->append($name, $content); + } + + $ins = array($name => (string) $content); + $keys = array_keys($this->_body); + $loc = array_search($parent, $keys); + if (!$before) { + // Increment location if not inserting before + ++$loc; + } + + if (0 === $loc) { + // If location of key is 0, we're prepending + $this->_body = $ins + $this->_body; + } elseif ($loc >= (count($this->_body))) { + // If location of key is maximal, we're appending + $this->_body = $this->_body + $ins; + } else { + // Otherwise, insert at location specified + $pre = array_slice($this->_body, 0, $loc); + $post = array_slice($this->_body, $loc); + $this->_body = $pre + $ins + $post; + } + + return $this; + } + + /** + * Echo the body segments + * + * @return void + */ + public function outputBody() + { + $body = implode('', $this->_body); + echo $body; + } + + /** + * Register an exception with the response + * + * @param Exception $e + * @return Zend_Controller_Response_Abstract + */ + public function setException(Exception $e) + { + $this->_exceptions[] = $e; + return $this; + } + + /** + * Retrieve the exception stack + * + * @return array + */ + public function getException() + { + return $this->_exceptions; + } + + /** + * Has an exception been registered with the response? + * + * @return boolean + */ + public function isException() + { + return !empty($this->_exceptions); + } + + /** + * Does the response object contain an exception of a given type? + * + * @param string $type + * @return boolean + */ + public function hasExceptionOfType($type) + { + foreach ($this->_exceptions as $e) { + if ($e instanceof $type) { + return true; + } + } + + return false; + } + + /** + * Does the response object contain an exception with a given message? + * + * @param string $message + * @return boolean + */ + public function hasExceptionOfMessage($message) + { + foreach ($this->_exceptions as $e) { + if ($message == $e->getMessage()) { + return true; + } + } + + return false; + } + + /** + * Does the response object contain an exception with a given code? + * + * @param int $code + * @return boolean + */ + public function hasExceptionOfCode($code) + { + $code = (int) $code; + foreach ($this->_exceptions as $e) { + if ($code == $e->getCode()) { + return true; + } + } + + return false; + } + + /** + * Retrieve all exceptions of a given type + * + * @param string $type + * @return false|array + */ + public function getExceptionByType($type) + { + $exceptions = array(); + foreach ($this->_exceptions as $e) { + if ($e instanceof $type) { + $exceptions[] = $e; + } + } + + if (empty($exceptions)) { + $exceptions = false; + } + + return $exceptions; + } + + /** + * Retrieve all exceptions of a given message + * + * @param string $message + * @return false|array + */ + public function getExceptionByMessage($message) + { + $exceptions = array(); + foreach ($this->_exceptions as $e) { + if ($message == $e->getMessage()) { + $exceptions[] = $e; + } + } + + if (empty($exceptions)) { + $exceptions = false; + } + + return $exceptions; + } + + /** + * Retrieve all exceptions of a given code + * + * @param mixed $code + * @return void + */ + public function getExceptionByCode($code) + { + $code = (int) $code; + $exceptions = array(); + foreach ($this->_exceptions as $e) { + if ($code == $e->getCode()) { + $exceptions[] = $e; + } + } + + if (empty($exceptions)) { + $exceptions = false; + } + + return $exceptions; + } + + /** + * Whether or not to render exceptions (off by default) + * + * If called with no arguments or a null argument, returns the value of the + * flag; otherwise, sets it and returns the current value. + * + * @param boolean $flag Optional + * @return boolean + */ + public function renderExceptions($flag = null) + { + if (null !== $flag) { + $this->_renderExceptions = $flag ? true : false; + } + + return $this->_renderExceptions; + } + + /** + * Send the response, including all headers, rendering exceptions if so + * requested. + * + * @return void + */ + public function sendResponse() + { + $this->sendHeaders(); + + if ($this->isException() && $this->renderExceptions()) { + $exceptions = ''; + foreach ($this->getException() as $e) { + $exceptions .= $e->__toString() . "\n"; + } + echo $exceptions; + return; + } + + $this->outputBody(); + } + + /** + * Magic __toString functionality + * + * Proxies to {@link sendResponse()} and returns response value as string + * using output buffering. + * + * @return string + */ + public function __toString() + { + ob_start(); + $this->sendResponse(); + return ob_get_clean(); + } +} diff --git a/lib/zend/Zend/Controller/Response/Cli.php b/lib/zend/Zend/Controller/Response/Cli.php new file mode 100644 index 00000000000..ed141659fa8 --- /dev/null +++ b/lib/zend/Zend/Controller/Response/Cli.php @@ -0,0 +1,68 @@ +isException() && $this->renderExceptions()) { + $exceptions = ''; + foreach ($this->getException() as $e) { + $exceptions .= $e->__toString() . "\n"; + } + return $exceptions; + } + + return $this->_body; + } +} diff --git a/lib/zend/Zend/Controller/Response/Exception.php b/lib/zend/Zend/Controller/Response/Exception.php new file mode 100644 index 00000000000..9829fb66bc4 --- /dev/null +++ b/lib/zend/Zend/Controller/Response/Exception.php @@ -0,0 +1,36 @@ +_headersRaw as $header) { + $headers[] = $header; + } + foreach ($this->_headers as $header) { + $name = $header['name']; + $key = strtolower($name); + if (array_key_exists($name, $headers)) { + if ($header['replace']) { + $headers[$key] = $header['name'] . ': ' . $header['value']; + } + } else { + $headers[$key] = $header['name'] . ': ' . $header['value']; + } + } + return $headers; + } + + /** + * Can we send headers? + * + * @param bool $throw + * @return void + */ + public function canSendHeaders($throw = false) + { + return true; + } + + /** + * Return the concatenated body segments + * + * @return string + */ + public function outputBody() + { + $fullContent = ''; + foreach ($this->_body as $content) { + $fullContent .= $content; + } + return $fullContent; + } + + /** + * Get body and/or body segments + * + * @param bool|string $spec + * @return string|array|null + */ + public function getBody($spec = false) + { + if (false === $spec) { + return $this->outputBody(); + } elseif (true === $spec) { + return $this->_body; + } elseif (is_string($spec) && isset($this->_body[$spec])) { + return $this->_body[$spec]; + } + + return null; + } + + /** + * "send" Response + * + * Concats all response headers, and then final body (separated by two + * newlines) + * + * @return string + */ + public function sendResponse() + { + $headers = $this->sendHeaders(); + $content = implode("\n", $headers) . "\n\n"; + + if ($this->isException() && $this->renderExceptions()) { + $exceptions = ''; + foreach ($this->getException() as $e) { + $exceptions .= $e->__toString() . "\n"; + } + $content .= $exceptions; + } else { + $content .= $this->outputBody(); + } + + return $content; + } +} diff --git a/lib/zend/Zend/Controller/Router/Abstract.php b/lib/zend/Zend/Controller/Router/Abstract.php new file mode 100644 index 00000000000..71ed9473de5 --- /dev/null +++ b/lib/zend/Zend/Controller/Router/Abstract.php @@ -0,0 +1,178 @@ +setParams($params); + } + + /** + * Add or modify a parameter to use when instantiating an action controller + * + * @param string $name + * @param mixed $value + * @return Zend_Controller_Router_Abstract + */ + public function setParam($name, $value) + { + $name = (string)$name; + $this->_invokeParams[$name] = $value; + + return $this; + } + + /** + * Set parameters to pass to action controller constructors + * + * @param array $params + * @return Zend_Controller_Router_Abstract + */ + public function setParams(array $params) + { + $this->_invokeParams = array_merge($this->_invokeParams, $params); + + return $this; + } + + /** + * Retrieve a single parameter from the controller parameter stack + * + * @param string $name + * @return mixed + */ + public function getParam($name) + { + if (isset($this->_invokeParams[$name])) { + return $this->_invokeParams[$name]; + } + + return null; + } + + /** + * Retrieve action controller instantiation parameters + * + * @return array + */ + public function getParams() + { + return $this->_invokeParams; + } + + /** + * Clear the controller parameter stack + * + * By default, clears all parameters. If a parameter name is given, clears + * only that parameter; if an array of parameter names is provided, clears + * each. + * + * @param null|string|array single key or array of keys for params to clear + * @return Zend_Controller_Router_Abstract + */ + public function clearParams($name = null) + { + if (null === $name) { + $this->_invokeParams = array(); + } elseif (is_string($name) && isset($this->_invokeParams[$name])) { + unset($this->_invokeParams[$name]); + } elseif (is_array($name)) { + foreach ($name as $key) { + if (is_string($key) && isset($this->_invokeParams[$key])) { + unset($this->_invokeParams[$key]); + } + } + } + + return $this; + } + + /** + * Retrieve Front Controller + * + * @return Zend_Controller_Front + */ + public function getFrontController() + { + // Used cache version if found + if (null !== $this->_frontController) { + return $this->_frontController; + } + + require_once 'Zend/Controller/Front.php'; + $this->_frontController = Zend_Controller_Front::getInstance(); + + return $this->_frontController; + } + + /** + * Set Front Controller + * + * @param Zend_Controller_Front $controller + * @return Zend_Controller_Router_Interface + */ + public function setFrontController(Zend_Controller_Front $controller) + { + $this->_frontController = $controller; + + return $this; + } +} diff --git a/lib/zend/Zend/Controller/Router/Exception.php b/lib/zend/Zend/Controller/Router/Exception.php new file mode 100644 index 00000000000..2d036333060 --- /dev/null +++ b/lib/zend/Zend/Controller/Router/Exception.php @@ -0,0 +1,35 @@ +hasRoute('default')) { + $dispatcher = $this->getFrontController()->getDispatcher(); + $request = $this->getFrontController()->getRequest(); + + require_once 'Zend/Controller/Router/Route/Module.php'; + $compat = new Zend_Controller_Router_Route_Module(array(), $dispatcher, $request); + + $this->_routes = array('default' => $compat) + $this->_routes; + } + + return $this; + } + + /** + * Add route to the route chain + * + * If route contains method setRequest(), it is initialized with a request object + * + * @param string $name Name of the route + * @param Zend_Controller_Router_Route_Interface $route Instance of the route + * @return Zend_Controller_Router_Rewrite + */ + public function addRoute($name, Zend_Controller_Router_Route_Interface $route) + { + if (method_exists($route, 'setRequest')) { + $route->setRequest($this->getFrontController()->getRequest()); + } + + $this->_routes[$name] = $route; + + return $this; + } + + /** + * Add routes to the route chain + * + * @param array $routes Array of routes with names as keys and routes as values + * @return Zend_Controller_Router_Rewrite + */ + public function addRoutes($routes) + { + foreach ($routes as $name => $route) { + $this->addRoute($name, $route); + } + + return $this; + } + + /** + * Create routes out of Zend_Config configuration + * + * Example INI: + * routes.archive.route = "archive/:year/*" + * routes.archive.defaults.controller = archive + * routes.archive.defaults.action = show + * routes.archive.defaults.year = 2000 + * routes.archive.reqs.year = "\d+" + * + * routes.news.type = "Zend_Controller_Router_Route_Static" + * routes.news.route = "news" + * routes.news.defaults.controller = "news" + * routes.news.defaults.action = "list" + * + * And finally after you have created a Zend_Config with above ini: + * $router = new Zend_Controller_Router_Rewrite(); + * $router->addConfig($config, 'routes'); + * + * @param Zend_Config $config Configuration object + * @param string $section Name of the config section containing route's definitions + * @throws Zend_Controller_Router_Exception + * @return Zend_Controller_Router_Rewrite + */ + public function addConfig(Zend_Config $config, $section = null) + { + if ($section !== null) { + if ($config->{$section} === null) { + require_once 'Zend/Controller/Router/Exception.php'; + throw new Zend_Controller_Router_Exception("No route configuration in section '{$section}'"); + } + + $config = $config->{$section}; + } + + foreach ($config as $name => $info) { + $route = $this->_getRouteFromConfig($info); + + if ($route instanceof Zend_Controller_Router_Route_Chain) { + if (!isset($info->chain)) { + require_once 'Zend/Controller/Router/Exception.php'; + throw new Zend_Controller_Router_Exception("No chain defined"); + } + + if ($info->chain instanceof Zend_Config) { + $childRouteNames = $info->chain; + } else { + $childRouteNames = explode(',', $info->chain); + } + + foreach ($childRouteNames as $childRouteName) { + $childRoute = $this->getRoute(trim($childRouteName)); + $route->chain($childRoute); + } + + $this->addRoute($name, $route); + } elseif (isset($info->chains) && $info->chains instanceof Zend_Config) { + $this->_addChainRoutesFromConfig($name, $route, $info->chains); + } else { + $this->addRoute($name, $route); + } + } + + return $this; + } + + /** + * Get a route frm a config instance + * + * @param Zend_Config $info + * @return Zend_Controller_Router_Route_Interface + */ + protected function _getRouteFromConfig(Zend_Config $info) + { + $class = (isset($info->type)) ? $info->type : 'Zend_Controller_Router_Route'; + if (!class_exists($class)) { + require_once 'Zend/Loader.php'; + Zend_Loader::loadClass($class); + } + + $route = call_user_func( + array( + $class, + 'getInstance' + ), $info + ); + + if (isset($info->abstract) && $info->abstract && method_exists($route, 'isAbstract')) { + $route->isAbstract(true); + } + + return $route; + } + + /** + * Add chain routes from a config route + * + * @param string $name + * @param Zend_Controller_Router_Route_Interface $route + * @param Zend_Config $childRoutesInfo + * @return void + */ + protected function _addChainRoutesFromConfig( + $name, + Zend_Controller_Router_Route_Interface $route, + Zend_Config $childRoutesInfo + ) + { + foreach ($childRoutesInfo as $childRouteName => $childRouteInfo) { + if (is_string($childRouteInfo)) { + $childRouteName = $childRouteInfo; + $childRoute = $this->getRoute($childRouteName); + } else { + $childRoute = $this->_getRouteFromConfig($childRouteInfo); + } + + if ($route instanceof Zend_Controller_Router_Route_Chain) { + $chainRoute = clone $route; + $chainRoute->chain($childRoute); + } else { + $chainRoute = $route->chain($childRoute); + } + + $chainName = $name . $this->_chainNameSeparator . $childRouteName; + + if (isset($childRouteInfo->chains)) { + $this->_addChainRoutesFromConfig($chainName, $chainRoute, $childRouteInfo->chains); + } else { + $this->addRoute($chainName, $chainRoute); + } + } + } + + /** + * Remove a route from the route chain + * + * @param string $name Name of the route + * @throws Zend_Controller_Router_Exception + * @return Zend_Controller_Router_Rewrite + */ + public function removeRoute($name) + { + if (!isset($this->_routes[$name])) { + require_once 'Zend/Controller/Router/Exception.php'; + throw new Zend_Controller_Router_Exception("Route $name is not defined"); + } + + unset($this->_routes[$name]); + + return $this; + } + + /** + * Remove all standard default routes + * + * @return Zend_Controller_Router_Rewrite + */ + public function removeDefaultRoutes() + { + $this->_useDefaultRoutes = false; + + return $this; + } + + /** + * Check if named route exists + * + * @param string $name Name of the route + * @return boolean + */ + public function hasRoute($name) + { + return isset($this->_routes[$name]); + } + + /** + * Retrieve a named route + * + * @param string $name Name of the route + * @throws Zend_Controller_Router_Exception + * @return Zend_Controller_Router_Route_Interface Route object + */ + public function getRoute($name) + { + if (!isset($this->_routes[$name])) { + require_once 'Zend/Controller/Router/Exception.php'; + throw new Zend_Controller_Router_Exception("Route $name is not defined"); + } + + return $this->_routes[$name]; + } + + /** + * Retrieve a currently matched route + * + * @throws Zend_Controller_Router_Exception + * @return Zend_Controller_Router_Route_Interface Route object + */ + public function getCurrentRoute() + { + if (!isset($this->_currentRoute)) { + require_once 'Zend/Controller/Router/Exception.php'; + throw new Zend_Controller_Router_Exception("Current route is not defined"); + } + + return $this->getRoute($this->_currentRoute); + } + + /** + * Retrieve a name of currently matched route + * + * @throws Zend_Controller_Router_Exception + * @return string Route name + */ + public function getCurrentRouteName() + { + if (!isset($this->_currentRoute)) { + require_once 'Zend/Controller/Router/Exception.php'; + throw new Zend_Controller_Router_Exception("Current route is not defined"); + } + + return $this->_currentRoute; + } + + /** + * Retrieve an array of routes added to the route chain + * + * @return array All of the defined routes + */ + public function getRoutes() + { + return $this->_routes; + } + + /** + * Find a matching route to the current PATH_INFO and inject + * returning values to the Request object. + * + * @param Zend_Controller_Request_Abstract $request + * @throws Zend_Controller_Router_Exception + * @return Zend_Controller_Request_Abstract Request object + */ + public function route(Zend_Controller_Request_Abstract $request) + { + if (!$request instanceof Zend_Controller_Request_Http) { + require_once 'Zend/Controller/Router/Exception.php'; + throw new Zend_Controller_Router_Exception( + 'Zend_Controller_Router_Rewrite requires a Zend_Controller_Request_Http-based request object' + ); + } + + if ($this->_useDefaultRoutes) { + $this->addDefaultRoutes(); + } + + // Find the matching route + $routeMatched = false; + + foreach (array_reverse($this->_routes, true) as $name => $route) { + // TODO: Should be an interface method. Hack for 1.0 BC + if (method_exists($route, 'isAbstract') && $route->isAbstract()) { + continue; + } + + // TODO: Should be an interface method. Hack for 1.0 BC + if (!method_exists($route, 'getVersion') || $route->getVersion() == 1) { + $match = $request->getPathInfo(); + } else { + $match = $request; + } + + if ($params = $route->match($match)) { + $this->_setRequestParams($request, $params); + $this->_currentRoute = $name; + $routeMatched = true; + break; + } + } + + if (!$routeMatched) { + require_once 'Zend/Controller/Router/Exception.php'; + throw new Zend_Controller_Router_Exception('No route matched the request', 404); + } + + if ($this->_useCurrentParamsAsGlobal) { + $params = $request->getParams(); + foreach ($params as $param => $value) { + $this->setGlobalParam($param, $value); + } + } + + return $request; + } + + /** + * Sets parameters for request object + * + * Module name, controller name and action name + * + * @param Zend_Controller_Request_Abstract $request + * @param array $params + */ + protected function _setRequestParams($request, $params) + { + foreach ($params as $param => $value) { + + $request->setParam($param, $value); + + if ($param === $request->getModuleKey()) { + $request->setModuleName($value); + } + if ($param === $request->getControllerKey()) { + $request->setControllerName($value); + } + if ($param === $request->getActionKey()) { + $request->setActionName($value); + } + } + } + + /** + * Generates a URL path that can be used in URL creation, redirection, etc. + * + * @param array $userParams Options passed by a user used to override parameters + * @param mixed $name The name of a Route to use + * @param bool $reset Whether to reset to the route defaults ignoring URL params + * @param bool $encode Tells to encode URL parts on output + * @throws Zend_Controller_Router_Exception + * @return string Resulting absolute URL path + */ + public function assemble($userParams, $name = null, $reset = false, $encode = true) + { + if (!is_array($userParams)) { + require_once 'Zend/Controller/Router/Exception.php'; + throw new Zend_Controller_Router_Exception('userParams must be an array'); + } + + if ($name == null) { + try { + $name = $this->getCurrentRouteName(); + } catch (Zend_Controller_Router_Exception $e) { + $name = 'default'; + } + } + + // Use UNION (+) in order to preserve numeric keys + $params = $userParams + $this->_globalParams; + + $route = $this->getRoute($name); + $url = $route->assemble($params, $reset, $encode); + + if (!preg_match('|^[a-z]+://|', $url)) { + $url = rtrim($this->getFrontController()->getBaseUrl(), self::URI_DELIMITER) . self::URI_DELIMITER . $url; + } + + return $url; + } + + /** + * Set a global parameter + * + * @param string $name + * @param mixed $value + * @return Zend_Controller_Router_Rewrite + */ + public function setGlobalParam($name, $value) + { + $this->_globalParams[$name] = $value; + + return $this; + } + + /** + * Set the separator to use with chain names + * + * @param string $separator The separator to use + * @return Zend_Controller_Router_Rewrite + */ + public function setChainNameSeparator($separator) + { + $this->_chainNameSeparator = $separator; + + return $this; + } + + /** + * Get the separator to use for chain names + * + * @return string + */ + public function getChainNameSeparator() + { + return $this->_chainNameSeparator; + } + + /** + * Determines/returns whether to use the request parameters as global parameters. + * + * @param boolean|null $use + * Null/unset when you want to retrieve the current state. + * True when request parameters should be global, false otherwise + * @return boolean|Zend_Controller_Router_Rewrite + * Returns a boolean if first param isn't set, returns an + * instance of Zend_Controller_Router_Rewrite otherwise. + * + */ + public function useRequestParametersAsGlobal($use = null) + { + if ($use === null) { + return $this->_useCurrentParamsAsGlobal; + } + + $this->_useCurrentParamsAsGlobal = (bool)$use; + + return $this; + } +} diff --git a/lib/zend/Zend/Controller/Router/Route.php b/lib/zend/Zend/Controller/Router/Route.php new file mode 100644 index 00000000000..927b97b3d34 --- /dev/null +++ b/lib/zend/Zend/Controller/Router/Route.php @@ -0,0 +1,605 @@ +reqs instanceof Zend_Config) ? $config->reqs->toArray() : array(); + $defs = ($config->defaults instanceof Zend_Config) ? $config->defaults->toArray() : array(); + + return new self($config->route, $defs, $reqs); + } + + /** + * Prepares the route for mapping by splitting (exploding) it + * to a corresponding atomic parts. These parts are assigned + * a position which is later used for matching and preparing values. + * + * @param string $route Map used to match with later submitted URL path + * @param array $defaults Defaults for map variables with keys as variable names + * @param array $reqs Regular expression requirements for variables (keys as variable names) + * @param Zend_Translate $translator Translator to use for this instance + * @param mixed|null $locale + */ + public function __construct( + $route, $defaults = array(), $reqs = array(), Zend_Translate $translator = null, $locale = null + ) + { + $route = trim($route, $this->_urlDelimiter); + $this->_defaults = (array)$defaults; + $this->_requirements = (array)$reqs; + $this->_translator = $translator; + $this->_locale = $locale; + + if ($route !== '') { + foreach (explode($this->_urlDelimiter, $route) as $pos => $part) { + if (substr($part, 0, 1) == $this->_urlVariable && substr($part, 1, 1) != $this->_urlVariable) { + $name = substr($part, 1); + + if (substr($name, 0, 1) === '@' && substr($name, 1, 1) !== '@') { + $name = substr($name, 1); + $this->_translatable[] = $name; + $this->_isTranslated = true; + } + + $this->_parts[$pos] = (isset($reqs[$name]) ? $reqs[$name] : $this->_defaultRegex); + $this->_variables[$pos] = $name; + } else { + if (substr($part, 0, 1) == $this->_urlVariable) { + $part = substr($part, 1); + } + + if (substr($part, 0, 1) === '@' && substr($part, 1, 1) !== '@') { + $this->_isTranslated = true; + } + + $this->_parts[$pos] = $part; + + if ($part !== '*') { + $this->_staticCount++; + } + } + } + } + } + + /** + * Matches a user submitted path with parts defined by a map. Assigns and + * returns an array of variables on a successful match. + * + * @param string $path Path used to match against this routing map + * @param boolean $partial + * @throws Zend_Controller_Router_Exception + * @return array|false An array of assigned values or a false on a mismatch + */ + public function match($path, $partial = false) + { + if ($this->_isTranslated) { + $translateMessages = $this->getTranslator()->getMessages(); + } + + $pathStaticCount = 0; + $values = array(); + $matchedPath = ''; + + if (!$partial) { + $path = trim($path, $this->_urlDelimiter); + } + + if ($path !== '') { + $path = explode($this->_urlDelimiter, $path); + + foreach ($path as $pos => $pathPart) { + // Path is longer than a route, it's not a match + if (!array_key_exists($pos, $this->_parts)) { + if ($partial) { + break; + } else { + return false; + } + } + + $matchedPath .= $pathPart . $this->_urlDelimiter; + + // If it's a wildcard, get the rest of URL as wildcard data and stop matching + if ($this->_parts[$pos] == '*') { + $count = count($path); + for ($i = $pos; $i < $count; $i += 2) { + $var = urldecode($path[$i]); + if (!isset($this->_wildcardData[$var]) && !isset($this->_defaults[$var]) + && !isset($values[$var]) + ) { + $this->_wildcardData[$var] = (isset($path[$i + 1])) ? urldecode($path[$i + 1]) : null; + } + } + + $matchedPath = implode($this->_urlDelimiter, $path); + break; + } + + $name = isset($this->_variables[$pos]) ? $this->_variables[$pos] : null; + $pathPart = urldecode($pathPart); + + // Translate value if required + $part = $this->_parts[$pos]; + if ($this->_isTranslated + && (substr($part, 0, 1) === '@' && substr($part, 1, 1) !== '@' + && $name === null) + || $name !== null && in_array($name, $this->_translatable) + ) { + if (substr($part, 0, 1) === '@') { + $part = substr($part, 1); + } + + if (($originalPathPart = array_search($pathPart, $translateMessages)) !== false) { + $pathPart = $originalPathPart; + } + } + + if (substr($part, 0, 2) === '@@') { + $part = substr($part, 1); + } + + // If it's a static part, match directly + if ($name === null && $part != $pathPart) { + return false; + } + + // If it's a variable with requirement, match a regex. If not - everything matches + if ($part !== null + && !preg_match( + $this->_regexDelimiter . '^' . $part . '$' . $this->_regexDelimiter . 'iu', $pathPart + ) + ) { + return false; + } + + // If it's a variable store it's value for later + if ($name !== null) { + $values[$name] = $pathPart; + } else { + $pathStaticCount++; + } + } + } + + // Check if all static mappings have been matched + if ($this->_staticCount != $pathStaticCount) { + return false; + } + + $return = $values + $this->_wildcardData + $this->_defaults; + + // Check if all map variables have been initialized + foreach ($this->_variables as $var) { + if (!array_key_exists($var, $return)) { + return false; + } elseif ($return[$var] == '' || $return[$var] === null) { + // Empty variable? Replace with the default value. + $return[$var] = $this->_defaults[$var]; + } + } + + $this->setMatchedPath(rtrim($matchedPath, $this->_urlDelimiter)); + + $this->_values = $values; + + return $return; + } + + /** + * Assembles user submitted parameters forming a URL path defined by this route + * + * @param array $data An array of variable and value pairs used as parameters + * @param boolean $reset Whether or not to set route defaults with those provided in $data + * @param boolean $encode + * @param boolean $partial + * @throws Zend_Controller_Router_Exception + * @return string Route path with user submitted parameters + */ + public function assemble($data = array(), $reset = false, $encode = false, $partial = false) + { + if ($this->_isTranslated) { + $translator = $this->getTranslator(); + + if (isset($data['@locale'])) { + $locale = $data['@locale']; + unset($data['@locale']); + } else { + $locale = $this->getLocale(); + } + } + + $url = array(); + $flag = false; + + foreach ($this->_parts as $key => $part) { + $name = isset($this->_variables[$key]) ? $this->_variables[$key] : null; + + $useDefault = false; + if (isset($name) && array_key_exists($name, $data) && $data[$name] === null) { + $useDefault = true; + } + + if (isset($name)) { + if (isset($data[$name]) && !$useDefault) { + $value = $data[$name]; + unset($data[$name]); + } elseif (!$reset && !$useDefault && isset($this->_values[$name])) { + $value = $this->_values[$name]; + } elseif (!$reset && !$useDefault && isset($this->_wildcardData[$name])) { + $value = $this->_wildcardData[$name]; + } elseif (array_key_exists($name, $this->_defaults)) { + $value = $this->_defaults[$name]; + } else { + require_once 'Zend/Controller/Router/Exception.php'; + throw new Zend_Controller_Router_Exception($name . ' is not specified'); + } + + if ($this->_isTranslated && in_array($name, $this->_translatable)) { + $url[$key] = $translator->translate($value, $locale); + } else { + $url[$key] = $value; + } + } elseif ($part != '*') { + if ($this->_isTranslated && substr($part, 0, 1) === '@') { + if (substr($part, 1, 1) !== '@') { + $url[$key] = $translator->translate(substr($part, 1), $locale); + } else { + $url[$key] = substr($part, 1); + } + } else { + if (substr($part, 0, 2) === '@@') { + $part = substr($part, 1); + } + + $url[$key] = $part; + } + } else { + if (!$reset) { + $data += $this->_wildcardData; + } + $defaults = $this->getDefaults(); + foreach ($data as $var => $value) { + if ($value !== null && (!isset($defaults[$var]) || $value != $defaults[$var])) { + $url[$key++] = $var; + $url[$key++] = $value; + $flag = true; + } + } + } + } + + $return = ''; + + foreach (array_reverse($url, true) as $key => $value) { + $defaultValue = null; + + if (isset($this->_variables[$key])) { + $defaultValue = $this->getDefault($this->_variables[$key]); + + if ($this->_isTranslated && $defaultValue !== null + && isset($this->_translatable[$this->_variables[$key]]) + ) { + $defaultValue = $translator->translate($defaultValue, $locale); + } + } + + if ($flag || $value !== $defaultValue || $partial) { + if ($encode) { + $value = urlencode($value); + } + $return = $this->_urlDelimiter . $value . $return; + $flag = true; + } + } + + return trim($return, $this->_urlDelimiter); + } + + /** + * Return a single parameter of route's defaults + * + * @param string $name Array key of the parameter + * @return string Previously set default + */ + public function getDefault($name) + { + if (isset($this->_defaults[$name])) { + return $this->_defaults[$name]; + } + + return null; + } + + /** + * Return an array of defaults + * + * @return array Route defaults + */ + public function getDefaults() + { + return $this->_defaults; + } + + /** + * Get all variables which are used by the route + * + * @return array + */ + public function getVariables() + { + return $this->_variables; + } + + /** + * Set a default translator + * + * @param Zend_Translate $translator + * @return void + */ + public static function setDefaultTranslator(Zend_Translate $translator = null) + { + self::$_defaultTranslator = $translator; + } + + /** + * Get the default translator + * + * @return Zend_Translate + */ + public static function getDefaultTranslator() + { + return self::$_defaultTranslator; + } + + /** + * Set a translator + * + * @param Zend_Translate $translator + * @return void + */ + public function setTranslator(Zend_Translate $translator) + { + $this->_translator = $translator; + } + + /** + * Get the translator + * + * @throws Zend_Controller_Router_Exception When no translator can be found + * @return Zend_Translate + */ + public function getTranslator() + { + if ($this->_translator !== null) { + return $this->_translator; + } else { + if (($translator = self::getDefaultTranslator()) !== null) { + return $translator; + } else { + try { + $translator = Zend_Registry::get('Zend_Translate'); + } catch (Zend_Exception $e) { + $translator = null; + } + + if ($translator instanceof Zend_Translate) { + return $translator; + } + } + } + + require_once 'Zend/Controller/Router/Exception.php'; + throw new Zend_Controller_Router_Exception('Could not find a translator'); + } + + /** + * Set a default locale + * + * @param mixed $locale + * @return void + */ + public static function setDefaultLocale($locale = null) + { + self::$_defaultLocale = $locale; + } + + /** + * Get the default locale + * + * @return mixed + */ + public static function getDefaultLocale() + { + return self::$_defaultLocale; + } + + /** + * Set a locale + * + * @param mixed $locale + * @return void + */ + public function setLocale($locale) + { + $this->_locale = $locale; + } + + /** + * Get the locale + * + * @return mixed + */ + public function getLocale() + { + if ($this->_locale !== null) { + return $this->_locale; + } else { + if (($locale = self::getDefaultLocale()) !== null) { + return $locale; + } else { + try { + $locale = Zend_Registry::get('Zend_Locale'); + } catch (Zend_Exception $e) { + $locale = null; + } + + if ($locale !== null) { + return $locale; + } + } + } + + return null; + } +} diff --git a/lib/zend/Zend/Controller/Router/Route/Abstract.php b/lib/zend/Zend/Controller/Router/Route/Abstract.php new file mode 100644 index 00000000000..2f6dc84807f --- /dev/null +++ b/lib/zend/Zend/Controller/Router/Route/Abstract.php @@ -0,0 +1,121 @@ +_matchedPath = $path; + } + + /** + * Get partially matched path + * + * @return string + */ + public function getMatchedPath() + { + return $this->_matchedPath; + } + + /** + * Check or set wether this is an abstract route or not + * + * @param boolean $flag + * @return boolean + */ + public function isAbstract($flag = null) + { + if ($flag !== null) { + $this->_isAbstract = $flag; + } + + return $this->_isAbstract; + } + + /** + * Create a new chain + * + * @param Zend_Controller_Router_Route_Abstract $route + * @param string $separator + * @return Zend_Controller_Router_Route_Chain + */ + public function chain(Zend_Controller_Router_Route_Abstract $route, $separator = '/') + { + require_once 'Zend/Controller/Router/Route/Chain.php'; + + $chain = new Zend_Controller_Router_Route_Chain(); + $chain->chain($this)->chain($route, $separator); + + return $chain; + } +} diff --git a/lib/zend/Zend/Controller/Router/Route/Chain.php b/lib/zend/Zend/Controller/Router/Route/Chain.php new file mode 100644 index 00000000000..a474931ac51 --- /dev/null +++ b/lib/zend/Zend/Controller/Router/Route/Chain.php @@ -0,0 +1,229 @@ +defaults instanceof Zend_Config) ? $config->defaults->toArray() : array(); + + return new self($config->route, $defs); + } + + /** + * Add a route to this chain + * + * @param Zend_Controller_Router_Route_Abstract $route + * @param string $separator + * @return Zend_Controller_Router_Route_Chain + */ + public function chain(Zend_Controller_Router_Route_Abstract $route, $separator = self::URI_DELIMITER) + { + $this->_routes[] = $route; + $this->_separators[] = $separator; + + return $this; + } + + /** + * Matches a user submitted path with a previously defined route. + * Assigns and returns an array of defaults on a successful match. + * + * @param Zend_Controller_Request_Http $request Request to get the path info from + * @param null $partial + * @return array|false An array of assigned values or a false on a mismatch + */ + public function match($request, $partial = null) + { + $rawPath = $request->getPathInfo(); + $path = trim($request->getPathInfo(), self::URI_DELIMITER); + $subPath = $path; + $values = array(); + $matchedPath = null; + + foreach ($this->_routes as $key => $route) { + if ($key > 0 + && $matchedPath !== null + && $subPath !== '' + && $subPath !== false + ) { + $separator = substr($subPath, 0, strlen($this->_separators[$key])); + + if ($separator !== $this->_separators[$key]) { + $request->setPathInfo($rawPath); + return false; + } + + $subPath = substr($subPath, strlen($separator)); + } + // TODO: Should be an interface method. Hack for 1.0 BC + if (!method_exists($route, 'getVersion') || $route->getVersion() == 1) { + $match = $subPath; + } else { + $request->setPathInfo($subPath); + $match = $request; + } + + $res = $route->match($match, true); + + if ($res === false) { + $request->setPathInfo($rawPath); + return false; + } + + $matchedPath = $route->getMatchedPath(); + + if ($matchedPath !== null) { + $subPath = substr($subPath, strlen($matchedPath)); + } + + $values = $res + $values; + } + + $request->setPathInfo($path); + + if ($subPath !== '' && $subPath !== false) { + return false; + } + + return $values; + } + + /** + * Assembles a URL path defined by this route + * + * @param array $data An array of variable and value pairs used as parameters + * @param bool $reset + * @param bool $encode + * @return string Route path with user submitted parameters + */ + public function assemble($data = array(), $reset = false, $encode = false) + { + $value = ''; + $numRoutes = count($this->_routes); + + foreach ($this->_routes as $key => $route) { + if ($key > 0) { + $value .= $this->_separators[$key]; + } + + $value .= $route->assemble($data, $reset, $encode, (($numRoutes - 1) > $key)); + + if (method_exists($route, 'getVariables')) { + $variables = $route->getVariables(); + + foreach ($variables as $variable) { + $data[$variable] = null; + } + } + } + + return $value; + } + + /** + * Set the request object for this and the child routes + * + * @param Zend_Controller_Request_Abstract|null $request + * @return void + */ + public function setRequest(Zend_Controller_Request_Abstract $request = null) + { + $this->_request = $request; + + foreach ($this->_routes as $route) { + if (method_exists($route, 'setRequest')) { + $route->setRequest($request); + } + } + } + + /** + * Return a single parameter of route's defaults + * + * @param string $name Array key of the parameter + * @return string Previously set default + */ + public function getDefault($name) + { + $default = null; + foreach ($this->_routes as $route) { + if (method_exists($route, 'getDefault')) { + $current = $route->getDefault($name); + if (null !== $current) { + $default = $current; + } + } + } + + return $default; + } + + /** + * Return an array of defaults + * + * @return array Route defaults + */ + public function getDefaults() + { + $defaults = array(); + foreach ($this->_routes as $route) { + if (method_exists($route, 'getDefaults')) { + $defaults = array_merge($defaults, $route->getDefaults()); + } + } + + return $defaults; + } +} diff --git a/lib/zend/Zend/Controller/Router/Route/Hostname.php b/lib/zend/Zend/Controller/Router/Route/Hostname.php new file mode 100644 index 00000000000..2d33c61811a --- /dev/null +++ b/lib/zend/Zend/Controller/Router/Route/Hostname.php @@ -0,0 +1,380 @@ +_request = $request; + } + + /** + * Get the request object + * + * @return Zend_Controller_Request_Abstract $request + */ + public function getRequest() + { + if ($this->_request === null) { + require_once 'Zend/Controller/Front.php'; + $this->_request = Zend_Controller_Front::getInstance()->getRequest(); + } + + return $this->_request; + } + + /** + * Instantiates route based on passed Zend_Config structure + * + * @param Zend_Config $config Configuration object + * @return Zend_Controller_Router_Route_Hostname + */ + public static function getInstance(Zend_Config $config) + { + $reqs = ($config->reqs instanceof Zend_Config) ? $config->reqs->toArray() : array(); + $defs = ($config->defaults instanceof Zend_Config) ? $config->defaults->toArray() : array(); + $scheme = (isset($config->scheme)) ? $config->scheme : null; + + return new self($config->route, $defs, $reqs, $scheme); + } + + /** + * Prepares the route for mapping by splitting (exploding) it + * to a corresponding atomic parts. These parts are assigned + * a position which is later used for matching and preparing values. + * + * @param string $route Map used to match with later submitted hostname + * @param array $defaults Defaults for map variables with keys as variable names + * @param array $reqs Regular expression requirements for variables (keys as variable names) + * @param string $scheme + */ + public function __construct($route, $defaults = array(), $reqs = array(), $scheme = null) + { + $route = trim($route, '.'); + $this->_defaults = (array) $defaults; + $this->_requirements = (array) $reqs; + $this->_scheme = $scheme; + + if ($route != '') { + foreach (explode('.', $route) as $pos => $part) { + if (substr($part, 0, 1) == $this->_hostVariable) { + $name = substr($part, 1); + $this->_parts[$pos] = (isset($reqs[$name]) ? $reqs[$name] : $this->_defaultRegex); + $this->_variables[$pos] = $name; + } else { + $this->_parts[$pos] = $part; + $this->_staticCount++; + } + } + } + } + + /** + * Matches a user submitted path with parts defined by a map. Assigns and + * returns an array of variables on a successful match. + * + * @param Zend_Controller_Request_Http $request Request to get the host from + * @return array|false An array of assigned values or a false on a mismatch + */ + public function match($request) + { + // Check the scheme if required + if ($this->_scheme !== null) { + $scheme = $request->getScheme(); + + if ($scheme !== $this->_scheme) { + return false; + } + } + + // Get the host and remove unnecessary port information + $host = $request->getHttpHost(); + if (preg_match('#:\d+$#', $host, $result) === 1) { + $host = substr($host, 0, -strlen($result[0])); + } + + $hostStaticCount = 0; + $values = array(); + + $host = trim($host, '.'); + + if ($host != '') { + $host = explode('.', $host); + + foreach ($host as $pos => $hostPart) { + // Host is longer than a route, it's not a match + if (!array_key_exists($pos, $this->_parts)) { + return false; + } + + $name = isset($this->_variables[$pos]) ? $this->_variables[$pos] : null; + $hostPart = urldecode($hostPart); + + // If it's a static part, match directly + if ($name === null && $this->_parts[$pos] != $hostPart) { + return false; + } + + // If it's a variable with requirement, match a regex. If not - everything matches + if ($this->_parts[$pos] !== null + && !preg_match( + $this->_regexDelimiter . '^' . $this->_parts[$pos] . '$' . $this->_regexDelimiter . 'iu', + $hostPart + ) + ) { + return false; + } + + // If it's a variable store it's value for later + if ($name !== null) { + $values[$name] = $hostPart; + } else { + $hostStaticCount++; + } + } + } + + // Check if all static mappings have been matched + if ($this->_staticCount != $hostStaticCount) { + return false; + } + + $return = $values + $this->_defaults; + + // Check if all map variables have been initialized + foreach ($this->_variables as $var) { + if (!array_key_exists($var, $return)) { + return false; + } + } + + $this->_values = $values; + + return $return; + } + + /** + * Assembles user submitted parameters forming a hostname defined by this route + * + * @param array $data An array of variable and value pairs used as parameters + * @param boolean $reset Whether or not to set route defaults with those provided in $data + * @param boolean $encode + * @param boolean $partial + * @throws Zend_Controller_Router_Exception + * @return string Route path with user submitted parameters + */ + public function assemble($data = array(), $reset = false, $encode = false, $partial = false) + { + $host = array(); + $flag = false; + + foreach ($this->_parts as $key => $part) { + $name = isset($this->_variables[$key]) ? $this->_variables[$key] : null; + + $useDefault = false; + if (isset($name) && array_key_exists($name, $data) && $data[$name] === null) { + $useDefault = true; + } + + if (isset($name)) { + if (isset($data[$name]) && !$useDefault) { + $host[$key] = $data[$name]; + unset($data[$name]); + } elseif (!$reset && !$useDefault && isset($this->_values[$name])) { + $host[$key] = $this->_values[$name]; + } elseif (isset($this->_defaults[$name])) { + $host[$key] = $this->_defaults[$name]; + } else { + require_once 'Zend/Controller/Router/Exception.php'; + throw new Zend_Controller_Router_Exception($name . ' is not specified'); + } + } else { + $host[$key] = $part; + } + } + + $return = ''; + + foreach (array_reverse($host, true) as $key => $value) { + if ($flag || !isset($this->_variables[$key]) || $value !== $this->getDefault($this->_variables[$key]) + || $partial + ) { + if ($encode) { + $value = urlencode($value); + } + $return = '.' . $value . $return; + $flag = true; + } + } + + $url = trim($return, '.'); + + if ($this->_scheme !== null) { + $scheme = $this->_scheme; + } else { + $request = $this->getRequest(); + if ($request instanceof Zend_Controller_Request_Http) { + $scheme = $request->getScheme(); + } else { + $scheme = 'http'; + } + } + + $url = $scheme . '://' . $url; + + return $url; + } + + /** + * Return a single parameter of route's defaults + * + * @param string $name Array key of the parameter + * @return string Previously set default + */ + public function getDefault($name) + { + if (isset($this->_defaults[$name])) { + return $this->_defaults[$name]; + } + + return null; + } + + /** + * Return an array of defaults + * + * @return array Route defaults + */ + public function getDefaults() + { + return $this->_defaults; + } + + /** + * Get all variables which are used by the route + * + * @return array + */ + public function getVariables() + { + return $this->_variables; + } +} diff --git a/lib/zend/Zend/Controller/Router/Route/Interface.php b/lib/zend/Zend/Controller/Router/Route/Interface.php new file mode 100644 index 00000000000..6e82990f557 --- /dev/null +++ b/lib/zend/Zend/Controller/Router/Route/Interface.php @@ -0,0 +1,39 @@ +defaults instanceof Zend_Config) ? $config->defaults->toArray() : array(); + $dispatcher = $frontController->getDispatcher(); + $request = $frontController->getRequest(); + + return new self($defs, $dispatcher, $request); + } + + /** + * Constructor + * + * @param array $defaults Defaults for map variables with keys as variable names + * @param Zend_Controller_Dispatcher_Interface $dispatcher Dispatcher object + * @param Zend_Controller_Request_Abstract $request Request object + */ + public function __construct( + array $defaults = array(), + Zend_Controller_Dispatcher_Interface $dispatcher = null, + Zend_Controller_Request_Abstract $request = null + ) + { + $this->_defaults = $defaults; + + if (isset($request)) { + $this->_request = $request; + } + + if (isset($dispatcher)) { + $this->_dispatcher = $dispatcher; + } + } + + /** + * Set request keys based on values in request object + * + * @return void + */ + protected function _setRequestKeys() + { + if (null !== $this->_request) { + $this->_moduleKey = $this->_request->getModuleKey(); + $this->_controllerKey = $this->_request->getControllerKey(); + $this->_actionKey = $this->_request->getActionKey(); + } + + if (null !== $this->_dispatcher) { + $this->_defaults += array( + $this->_controllerKey => $this->_dispatcher->getDefaultControllerName(), + $this->_actionKey => $this->_dispatcher->getDefaultAction(), + $this->_moduleKey => $this->_dispatcher->getDefaultModule() + ); + } + + $this->_keysSet = true; + } + + /** + * Matches a user submitted path. Assigns and returns an array of variables + * on a successful match. + * + * If a request object is registered, it uses its setModuleName(), + * setControllerName(), and setActionName() accessors to set those values. + * Always returns the values as an array. + * + * @param string $path Path used to match against this routing map + * @param boolean $partial + * @return array An array of assigned values or a false on a mismatch + */ + public function match($path, $partial = false) + { + $this->_setRequestKeys(); + + $values = array(); + $params = array(); + + if (!$partial) { + $path = trim($path, self::URI_DELIMITER); + } else { + $matchedPath = $path; + } + + if ($path != '') { + $path = explode(self::URI_DELIMITER, $path); + + if ($this->_dispatcher && $this->_dispatcher->isValidModule($path[0])) { + $values[$this->_moduleKey] = array_shift($path); + $this->_moduleValid = true; + } + + if (count($path) && !empty($path[0])) { + $values[$this->_controllerKey] = array_shift($path); + } + + if (count($path) && !empty($path[0])) { + $values[$this->_actionKey] = array_shift($path); + } + + if ($numSegs = count($path)) { + for ($i = 0; $i < $numSegs; $i = $i + 2) { + $key = urldecode($path[$i]); + $val = isset($path[$i + 1]) ? urldecode($path[$i + 1]) : null; + $params[$key] = (isset($params[$key]) ? (array_merge((array)$params[$key], array($val))) : $val); + } + } + } + + if ($partial) { + $this->setMatchedPath($matchedPath); + } + + $this->_values = $values + $params; + + return $this->_values + $this->_defaults; + } + + /** + * Assembles user submitted parameters forming a URL path defined by this route + * + * @param array $data An array of variable and value pairs used as parameters + * @param boolean $reset Weither to reset the current params + * @param boolean $encode + * @param boolean $partial + * @return string Route path with user submitted parameters + */ + public function assemble($data = array(), $reset = false, $encode = true, $partial = false) + { + if (!$this->_keysSet) { + $this->_setRequestKeys(); + } + + $params = (!$reset) ? $this->_values : array(); + + foreach ($data as $key => $value) { + if ($value !== null) { + $params[$key] = $value; + } elseif (isset($params[$key])) { + unset($params[$key]); + } + } + + $params += $this->_defaults; + + $url = ''; + + if ($this->_moduleValid || array_key_exists($this->_moduleKey, $data)) { + if ($params[$this->_moduleKey] != $this->_defaults[$this->_moduleKey]) { + $module = $params[$this->_moduleKey]; + } + } + unset($params[$this->_moduleKey]); + + $controller = $params[$this->_controllerKey]; + unset($params[$this->_controllerKey]); + + $action = $params[$this->_actionKey]; + unset($params[$this->_actionKey]); + + foreach ($params as $key => $value) { + $key = ($encode) ? urlencode($key) : $key; + if (is_array($value)) { + foreach ($value as $arrayValue) { + $arrayValue = ($encode) ? urlencode($arrayValue) : $arrayValue; + $url .= self::URI_DELIMITER . $key; + $url .= self::URI_DELIMITER . $arrayValue; + } + } else { + if ($encode) { + $value = urlencode($value); + } + $url .= self::URI_DELIMITER . $key; + $url .= self::URI_DELIMITER . $value; + } + } + + if (!empty($url) || $action !== $this->_defaults[$this->_actionKey]) { + if ($encode) { + $action = urlencode($action); + } + $url = self::URI_DELIMITER . $action . $url; + } + + if (!empty($url) || $controller !== $this->_defaults[$this->_controllerKey]) { + if ($encode) { + $controller = urlencode($controller); + } + $url = self::URI_DELIMITER . $controller . $url; + } + + if (isset($module)) { + if ($encode) { + $module = urlencode($module); + } + $url = self::URI_DELIMITER . $module . $url; + } + + return ltrim($url, self::URI_DELIMITER); + } + + /** + * Return a single parameter of route's defaults + * + * @param string $name Array key of the parameter + * @return string Previously set default + */ + public function getDefault($name) + { + if (isset($this->_defaults[$name])) { + return $this->_defaults[$name]; + } + } + + /** + * Return an array of defaults + * + * @return array Route defaults + */ + public function getDefaults() + { + return $this->_defaults; + } +} diff --git a/lib/zend/Zend/Controller/Router/Route/Regex.php b/lib/zend/Zend/Controller/Router/Route/Regex.php new file mode 100644 index 00000000000..e012357d7b3 --- /dev/null +++ b/lib/zend/Zend/Controller/Router/Route/Regex.php @@ -0,0 +1,319 @@ +defaults instanceof Zend_Config) ? $config->defaults->toArray() : array(); + $map = ($config->map instanceof Zend_Config) ? $config->map->toArray() : array(); + $reverse = (isset($config->reverse)) ? $config->reverse : null; + + return new self($config->route, $defs, $map, $reverse); + } + + /** + * Constructor + * + * @param $route + * @param array $defaults + * @param array $map + * @param null $reverse + */ + public function __construct($route, $defaults = array(), $map = array(), $reverse = null) + { + $this->_regex = $route; + $this->_defaults = (array) $defaults; + $this->_map = (array) $map; + $this->_reverse = $reverse; + } + + /** + * Get the version of the route + * + * @return int + */ + public function getVersion() + { + return 1; + } + + /** + * Matches a user submitted path with a previously defined route. + * Assigns and returns an array of defaults on a successful match. + * + * @param string $path Path used to match against this routing map + * @return array|false An array of assigned values or a false on a mismatch + */ + public function match($path, $partial = false) + { + if (!$partial) { + $path = trim(urldecode($path), self::URI_DELIMITER); + $regex = '#^' . $this->_regex . '$#i'; + } else { + $regex = '#^' . $this->_regex . '#i'; + } + + $res = preg_match($regex, $path, $values); + + if ($res === 0) { + return false; + } + + if ($partial) { + $this->setMatchedPath($values[0]); + } + + // array_filter_key()? Why isn't this in a standard PHP function set yet? :) + foreach ($values as $i => $value) { + if (!is_int($i) || $i === 0) { + unset($values[$i]); + } + } + + $this->_values = $values; + + $values = $this->_getMappedValues($values); + $defaults = $this->_getMappedValues($this->_defaults, false, true); + $return = $values + $defaults; + + return $return; + } + + /** + * Maps numerically indexed array values to it's associative mapped counterpart. + * Or vice versa. Uses user provided map array which consists of index => name + * parameter mapping. If map is not found, it returns original array. + * + * Method strips destination type of keys form source array. Ie. if source array is + * indexed numerically then every associative key will be stripped. Vice versa if reversed + * is set to true. + * + * @param array $values Indexed or associative array of values to map + * @param boolean $reversed False means translation of index to association. True means reverse. + * @param boolean $preserve Should wrong type of keys be preserved or stripped. + * @return array An array of mapped values + */ + protected function _getMappedValues($values, $reversed = false, $preserve = false) + { + if (count($this->_map) == 0) { + return $values; + } + + $return = array(); + + foreach ($values as $key => $value) { + if (is_int($key) && !$reversed) { + if (array_key_exists($key, $this->_map)) { + $index = $this->_map[$key]; + } elseif (false === ($index = array_search($key, $this->_map))) { + $index = $key; + } + $return[$index] = $values[$key]; + } elseif ($reversed) { + $index = $key; + if (!is_int($key)) { + if (array_key_exists($key, $this->_map)) { + $index = $this->_map[$key]; + } else { + $index = array_search($key, $this->_map, true); + } + } + if (false !== $index) { + $return[$index] = $values[$key]; + } + } elseif ($preserve) { + $return[$key] = $value; + } + } + + return $return; + } + + /** + * Assembles a URL path defined by this route + * + * @param array $data An array of name (or index) and value pairs used as parameters + * @param boolean $reset + * @param boolean $encode + * @param boolean $partial + * @throws Zend_Controller_Router_Exception + * @return string Route path with user submitted parameters + */ + public function assemble($data = array(), $reset = false, $encode = false, $partial = false) + { + if ($this->_reverse === null) { + require_once 'Zend/Controller/Router/Exception.php'; + throw new Zend_Controller_Router_Exception('Cannot assemble. Reversed route is not specified.'); + } + + $defaultValuesMapped = $this->_getMappedValues($this->_defaults, true, false); + $matchedValuesMapped = $this->_getMappedValues($this->_values, true, false); + $dataValuesMapped = $this->_getMappedValues($data, true, false); + + // handle resets, if so requested (By null value) to do so + if (($resetKeys = array_search(null, $dataValuesMapped, true)) !== false) { + foreach ((array)$resetKeys as $resetKey) { + if (isset($matchedValuesMapped[$resetKey])) { + unset($matchedValuesMapped[$resetKey]); + unset($dataValuesMapped[$resetKey]); + } + } + } + + // merge all the data together, first defaults, then values matched, then supplied + $mergedData = $defaultValuesMapped; + $mergedData = $this->_arrayMergeNumericKeys($mergedData, $matchedValuesMapped); + $mergedData = $this->_arrayMergeNumericKeys($mergedData, $dataValuesMapped); + + if ($encode) { + foreach ($mergedData as $key => &$value) { + $value = urlencode($value); + } + } + + ksort($mergedData); + + $return = @vsprintf($this->_reverse, $mergedData); + + if ($return === false) { + require_once 'Zend/Controller/Router/Exception.php'; + throw new Zend_Controller_Router_Exception('Cannot assemble. Too few arguments?'); + } + + return $return; + } + + /** + * Return a single parameter of route's defaults + * + * @param string $name Array key of the parameter + * @return string Previously set default + */ + public function getDefault($name) + { + if (isset($this->_defaults[$name])) { + return $this->_defaults[$name]; + } + } + + /** + * Return an array of defaults + * + * @return array Route defaults + */ + public function getDefaults() + { + return $this->_defaults; + } + + /** + * Get all variables which are used by the route + * + * @return array + */ + public function getVariables() + { + $variables = array(); + + foreach ($this->_map as $key => $value) { + if (is_numeric($key)) { + $variables[] = $value; + } else { + $variables[] = $key; + } + } + + return $variables; + } + + /** + * _arrayMergeNumericKeys() - allows for a strict key (numeric's included) array_merge. + * php's array_merge() lacks the ability to merge with numeric keys. + * + * @param array $array1 + * @param array $array2 + * @return array + */ + protected function _arrayMergeNumericKeys(Array $array1, Array $array2) + { + $returnArray = $array1; + foreach ($array2 as $array2Index => $array2Value) { + $returnArray[$array2Index] = $array2Value; + } + + return $returnArray; + } +} diff --git a/lib/zend/Zend/Controller/Router/Route/Static.php b/lib/zend/Zend/Controller/Router/Route/Static.php new file mode 100644 index 00000000000..4acd9f572ed --- /dev/null +++ b/lib/zend/Zend/Controller/Router/Route/Static.php @@ -0,0 +1,149 @@ +defaults instanceof Zend_Config) ? $config->defaults->toArray() : array(); + + return new self($config->route, $defs); + } + + /** + * Prepares the route for mapping. + * + * @param string $route Map used to match with later submitted URL path + * @param array $defaults Defaults for map variables with keys as variable names + */ + public function __construct($route, $defaults = array()) + { + $this->_route = trim($route, self::URI_DELIMITER); + $this->_defaults = (array) $defaults; + } + + /** + * Matches a user submitted path with a previously defined route. + * Assigns and returns an array of defaults on a successful match. + * + * @param string $path Path used to match against this routing map + * @return array|false An array of assigned values or a false on a mismatch + */ + public function match($path, $partial = false) + { + if ($partial) { + if ((empty($path) && empty($this->_route)) + || (substr($path, 0, strlen($this->_route)) === $this->_route) + ) { + $this->setMatchedPath($this->_route); + + return $this->_defaults; + } + } else { + if (trim($path, self::URI_DELIMITER) == $this->_route) { + return $this->_defaults; + } + } + + return false; + } + + /** + * Assembles a URL path defined by this route + * + * @param array $data An array of variable and value pairs used as parameters + * @return string Route path with user submitted parameters + */ + public function assemble($data = array(), $reset = false, $encode = false, $partial = false) + { + return $this->_route; + } + + /** + * Return a single parameter of route's defaults + * + * @param string $name Array key of the parameter + * @return string Previously set default + */ + public function getDefault($name) + { + if (isset($this->_defaults[$name])) { + return $this->_defaults[$name]; + } + + return null; + } + + /** + * Return an array of defaults + * + * @return array Route defaults + */ + public function getDefaults() + { + return $this->_defaults; + } +} diff --git a/lib/zend/Zend/Crypt.php b/lib/zend/Zend/Crypt.php new file mode 100644 index 00000000000..0ceeac71e33 --- /dev/null +++ b/lib/zend/Zend/Crypt.php @@ -0,0 +1,168 @@ +setPrime($prime); + $this->setGenerator($generator); + if ($privateKey !== null) { + $this->setPrivateKey($privateKey, $privateKeyType); + } + $this->setBigIntegerMath(); + } + + /** + * Generate own public key. If a private number has not already been + * set, one will be generated at this stage. + * + * @return Zend_Crypt_DiffieHellman + */ + public function generateKeys() + { + if (function_exists('openssl_dh_compute_key') && self::$useOpenssl !== false) { + $details = array(); + $details['p'] = $this->getPrime(); + $details['g'] = $this->getGenerator(); + if ($this->hasPrivateKey()) { + $details['priv_key'] = $this->getPrivateKey(); + } + $opensslKeyResource = openssl_pkey_new( array('dh' => $details) ); + $data = openssl_pkey_get_details($opensslKeyResource); + $this->setPrivateKey($data['dh']['priv_key'], self::BINARY); + $this->setPublicKey($data['dh']['pub_key'], self::BINARY); + } else { + // Private key is lazy generated in the absence of PHP 5.3's ext/openssl + $publicKey = $this->_math->powmod($this->getGenerator(), $this->getPrivateKey(), $this->getPrime()); + $this->setPublicKey($publicKey); + } + return $this; + } + + /** + * Setter for the value of the public number + * + * @param string $number + * @param string $type + * @throws Zend_Crypt_DiffieHellman_Exception + * @return Zend_Crypt_DiffieHellman + */ + public function setPublicKey($number, $type = self::NUMBER) + { + if ($type == self::BINARY) { + $number = $this->_math->fromBinary($number); + } + if (!preg_match("/^\d+$/", $number)) { + require_once('Zend/Crypt/DiffieHellman/Exception.php'); + throw new Zend_Crypt_DiffieHellman_Exception('invalid parameter; not a positive natural number'); + } + $this->_publicKey = (string) $number; + return $this; + } + + /** + * Returns own public key for communication to the second party to this + * transaction. + * + * @param string $type + * @throws Zend_Crypt_DiffieHellman_Exception + * @return string + */ + public function getPublicKey($type = self::NUMBER) + { + if ($this->_publicKey === null) { + require_once 'Zend/Crypt/DiffieHellman/Exception.php'; + throw new Zend_Crypt_DiffieHellman_Exception('A public key has not yet been generated using a prior call to generateKeys()'); + } + if ($type == self::BINARY) { + return $this->_math->toBinary($this->_publicKey); + } elseif ($type == self::BTWOC) { + return $this->_math->btwoc($this->_math->toBinary($this->_publicKey)); + } + return $this->_publicKey; + } + + /** + * Compute the shared secret key based on the public key received from the + * the second party to this transaction. This should agree to the secret + * key the second party computes on our own public key. + * Once in agreement, the key is known to only to both parties. + * By default, the function expects the public key to be in binary form + * which is the typical format when being transmitted. + * + * If you need the binary form of the shared secret key, call + * getSharedSecretKey() with the optional parameter for Binary output. + * + * @param string $publicKey + * @param string $type + * @param string $output + * @throws Zend_Crypt_DiffieHellman_Exception + * @return mixed + */ + public function computeSecretKey($publicKey, $type = self::NUMBER, $output = self::NUMBER) + { + if ($type == self::BINARY) { + $publicKey = $this->_math->fromBinary($publicKey); + } + if (!preg_match("/^\d+$/", $publicKey)) { + require_once('Zend/Crypt/DiffieHellman/Exception.php'); + throw new Zend_Crypt_DiffieHellman_Exception('invalid parameter; not a positive natural number'); + } + if (function_exists('openssl_dh_compute_key') && self::$useOpenssl !== false) { + $this->_secretKey = openssl_dh_compute_key($publicKey, $this->getPublicKey()); + } else { + $this->_secretKey = $this->_math->powmod($publicKey, $this->getPrivateKey(), $this->getPrime()); + } + return $this->getSharedSecretKey($output); + } + + /** + * Return the computed shared secret key from the DiffieHellman transaction + * + * @param string $type + * @throws Zend_Crypt_DiffieHellman_Exception + * @return string + */ + public function getSharedSecretKey($type = self::NUMBER) + { + if (!isset($this->_secretKey)) { + require_once('Zend/Crypt/DiffieHellman/Exception.php'); + throw new Zend_Crypt_DiffieHellman_Exception('A secret key has not yet been computed; call computeSecretKey()'); + } + if ($type == self::BINARY) { + return $this->_math->toBinary($this->_secretKey); + } elseif ($type == self::BTWOC) { + return $this->_math->btwoc($this->_math->toBinary($this->_secretKey)); + } + return $this->_secretKey; + } + + /** + * Setter for the value of the prime number + * + * @param string $number + * @throws Zend_Crypt_DiffieHellman_Exception + * @return Zend_Crypt_DiffieHellman + */ + public function setPrime($number) + { + if (!preg_match("/^\d+$/", $number) || $number < 11) { + require_once('Zend/Crypt/DiffieHellman/Exception.php'); + throw new Zend_Crypt_DiffieHellman_Exception('invalid parameter; not a positive natural number or too small: should be a large natural number prime'); + } + $this->_prime = (string) $number; + return $this; + } + + /** + * Getter for the value of the prime number + * + * @throws Zend_Crypt_DiffieHellman_Exception + * @return string + */ + public function getPrime() + { + if (!isset($this->_prime)) { + require_once('Zend/Crypt/DiffieHellman/Exception.php'); + throw new Zend_Crypt_DiffieHellman_Exception('No prime number has been set'); + } + return $this->_prime; + } + + /** + * Setter for the value of the generator number + * + * @param string $number + * @throws Zend_Crypt_DiffieHellman_Exception + * @return Zend_Crypt_DiffieHellman + */ + public function setGenerator($number) + { + if (!preg_match("/^\d+$/", $number) || $number < 2) { + require_once('Zend/Crypt/DiffieHellman/Exception.php'); + throw new Zend_Crypt_DiffieHellman_Exception('invalid parameter; not a positive natural number greater than 1'); + } + $this->_generator = (string) $number; + return $this; + } + + /** + * Getter for the value of the generator number + * + * @throws Zend_Crypt_DiffieHellman_Exception + * @return string + */ + public function getGenerator() + { + if (!isset($this->_generator)) { + require_once('Zend/Crypt/DiffieHellman/Exception.php'); + throw new Zend_Crypt_DiffieHellman_Exception('No generator number has been set'); + } + return $this->_generator; + } + + /** + * Setter for the value of the private number + * + * @param string $number + * @param string $type + * @throws Zend_Crypt_DiffieHellman_Exception + * @return Zend_Crypt_DiffieHellman + */ + public function setPrivateKey($number, $type = self::NUMBER) + { + if ($type == self::BINARY) { + $number = $this->_math->fromBinary($number); + } + if (!preg_match("/^\d+$/", $number)) { + require_once('Zend/Crypt/DiffieHellman/Exception.php'); + throw new Zend_Crypt_DiffieHellman_Exception('invalid parameter; not a positive natural number'); + } + $this->_privateKey = (string) $number; + return $this; + } + + /** + * Getter for the value of the private number + * + * @param string $type + * @return string + */ + public function getPrivateKey($type = self::NUMBER) + { + if (!$this->hasPrivateKey()) { + $this->setPrivateKey($this->_generatePrivateKey(), self::BINARY); + } + if ($type == self::BINARY) { + return $this->_math->toBinary($this->_privateKey); + } elseif ($type == self::BTWOC) { + return $this->_math->btwoc($this->_math->toBinary($this->_privateKey)); + } + return $this->_privateKey; + } + + /** + * Check whether a private key currently exists. + * + * @return boolean + */ + public function hasPrivateKey() + { + return isset($this->_privateKey); + } + + /** + * Setter to pass an extension parameter which is used to create + * a specific BigInteger instance for a specific extension type. + * Allows manual setting of the class in case of an extension + * problem or bug. + * + * @param string $extension + * @return void + */ + public function setBigIntegerMath($extension = null) + { + /** + * @see Zend_Crypt_Math + */ + require_once 'Zend/Crypt/Math.php'; + $this->_math = new Zend_Crypt_Math($extension); + } + + /** + * In the event a private number/key has not been set by the user, + * or generated by ext/openssl, a best attempt will be made to + * generate a random key. Having a random number generator installed + * on linux/bsd is highly recommended! The alternative is not recommended + * for production unless without any other option. + * + * @return string + */ + protected function _generatePrivateKey() + { + $rand = $this->_math->rand($this->getGenerator(), $this->getPrime()); + return $rand; + } + +} diff --git a/lib/zend/Zend/Crypt/DiffieHellman/Exception.php b/lib/zend/Zend/Crypt/DiffieHellman/Exception.php new file mode 100644 index 00000000000..9afa43d6713 --- /dev/null +++ b/lib/zend/Zend/Crypt/DiffieHellman/Exception.php @@ -0,0 +1,36 @@ +80 using internal algo) + * @todo Check if mhash() is a required alternative (will be PECL-only soon) + * @category Zend + * @package Zend_Crypt + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_Crypt_Hmac extends Zend_Crypt +{ + + /** + * The key to use for the hash + * + * @var string + */ + protected static $_key = null; + + /** + * pack() format to be used for current hashing method + * + * @var string + */ + protected static $_packFormat = null; + + /** + * Hashing algorithm; can be the md5/sha1 functions or any algorithm name + * listed in the output of PHP 5.1.2+ hash_algos(). + * + * @var string + */ + protected static $_hashAlgorithm = 'md5'; + + /** + * List of algorithms supported my mhash() + * + * @var array + */ + protected static $_supportedMhashAlgorithms = array('adler32',' crc32', 'crc32b', 'gost', + 'haval128', 'haval160', 'haval192', 'haval256', 'md4', 'md5', 'ripemd160', + 'sha1', 'sha256', 'tiger', 'tiger128', 'tiger160'); + + /** + * Constants representing the output mode of the hash algorithm + */ + const STRING = 'string'; + const BINARY = 'binary'; + + /** + * Performs a HMAC computation given relevant details such as Key, Hashing + * algorithm, the data to compute MAC of, and an output format of String, + * Binary notation or BTWOC. + * + * @param string $key + * @param string $hash + * @param string $data + * @param string $output + * @throws Zend_Crypt_Hmac_Exception + * @return string + */ + public static function compute($key, $hash, $data, $output = self::STRING) + { + // set the key + if (!isset($key) || empty($key)) { + require_once 'Zend/Crypt/Hmac/Exception.php'; + throw new Zend_Crypt_Hmac_Exception('provided key is null or empty'); + } + self::$_key = $key; + + // set the hash + self::_setHashAlgorithm($hash); + + // perform hashing and return + return self::_hash($data, $output); + } + + /** + * Setter for the hash method. + * + * @param string $hash + * @throws Zend_Crypt_Hmac_Exception + * @return Zend_Crypt_Hmac + */ + protected static function _setHashAlgorithm($hash) + { + if (!isset($hash) || empty($hash)) { + require_once 'Zend/Crypt/Hmac/Exception.php'; + throw new Zend_Crypt_Hmac_Exception('provided hash string is null or empty'); + } + + $hash = strtolower($hash); + $hashSupported = false; + + if (function_exists('hash_algos') && in_array($hash, hash_algos())) { + $hashSupported = true; + } + + if ($hashSupported === false && function_exists('mhash') && in_array($hash, self::$_supportedAlgosMhash)) { + $hashSupported = true; + } + + if ($hashSupported === false) { + require_once 'Zend/Crypt/Hmac/Exception.php'; + throw new Zend_Crypt_Hmac_Exception('hash algorithm provided is not supported on this PHP installation; please enable the hash or mhash extensions'); + } + self::$_hashAlgorithm = $hash; + } + + /** + * Perform HMAC and return the keyed data + * + * @param string $data + * @param string $output + * @param bool $internal Option to not use hash() functions for testing + * @return string + */ + protected static function _hash($data, $output = self::STRING, $internal = false) + { + if (function_exists('hash_hmac')) { + if ($output == self::BINARY) { + return hash_hmac(self::$_hashAlgorithm, $data, self::$_key, true); + } + return hash_hmac(self::$_hashAlgorithm, $data, self::$_key); + } + + if (function_exists('mhash')) { + if ($output == self::BINARY) { + return mhash(self::_getMhashDefinition(self::$_hashAlgorithm), $data, self::$_key); + } + $bin = mhash(self::_getMhashDefinition(self::$_hashAlgorithm), $data, self::$_key); + return bin2hex($bin); + } + } + + /** + * Since MHASH accepts an integer constant representing the hash algorithm + * we need to make a small detour to get the correct integer matching our + * algorithm's name. + * + * @param string $hashAlgorithm + * @return integer + */ + protected static function _getMhashDefinition($hashAlgorithm) + { + for ($i = 0; $i <= mhash_count(); $i++) + { + $types[mhash_get_hash_name($i)] = $i; + } + return $types[strtoupper($hashAlgorithm)]; + } + +} diff --git a/lib/zend/Zend/Crypt/Hmac/Exception.php b/lib/zend/Zend/Crypt/Hmac/Exception.php new file mode 100644 index 00000000000..36acda37e76 --- /dev/null +++ b/lib/zend/Zend/Crypt/Hmac/Exception.php @@ -0,0 +1,36 @@ + 127) { + return "\x00" . $long; + } + return $long; + } + + /** + * Translate a binary form into a big integer string + * + * @param string $binary + * @return string + */ + public function fromBinary($binary) { + return $this->_math->binaryToInteger($binary); + } + + /** + * Translate a big integer string into a binary form + * + * @param string $integer + * @return string + */ + public function toBinary($integer) + { + return $this->_math->integerToBinary($integer); + } + +} diff --git a/lib/zend/Zend/Crypt/Math/BigInteger.php b/lib/zend/Zend/Crypt/Math/BigInteger.php new file mode 100644 index 00000000000..e066f608513 --- /dev/null +++ b/lib/zend/Zend/Crypt/Math/BigInteger.php @@ -0,0 +1,118 @@ +_loadAdapter($extension); + } + + /** + * Redirect all public method calls to the wrapped extension object. + * + * @param string $methodName + * @param array $args + * @return mixed + * @throws Zend_Crypt_Math_BigInteger_Exception + */ + public function __call($methodName, $args) + { + if(!method_exists($this->_math, $methodName)) { + require_once 'Zend/Crypt/Math/BigInteger/Exception.php'; + throw new Zend_Crypt_Math_BigInteger_Exception('invalid method call: ' . get_class($this->_math) . '::' . $methodName . '() does not exist'); + } + return call_user_func_array(array($this->_math, $methodName), $args); + } + + /** + * @param string $extension + * @throws Zend_Crypt_Math_BigInteger_Exception + */ + protected function _loadAdapter($extension = null) + { + if ($extension === null) { + if (extension_loaded('gmp')) { + $extension = 'gmp'; + //} elseif (extension_loaded('big_int')) { + // $extension = 'big_int'; + } else { + $extension = 'bcmath'; + } + } + if($extension == 'gmp' && extension_loaded('gmp')) { + require_once 'Zend/Crypt/Math/BigInteger/Gmp.php'; + $this->_math = new Zend_Crypt_Math_BigInteger_Gmp(); + //} elseif($extension == 'bigint' && extension_loaded('big_int')) { + // require_once 'Zend/Crypt_Math/BigInteger/Bigint.php'; + // $this->_math = new Zend_Crypt_Math_BigInteger_Bigint(); + } elseif ($extension == 'bcmath' && extension_loaded('bcmath')) { + require_once 'Zend/Crypt/Math/BigInteger/Bcmath.php'; + $this->_math = new Zend_Crypt_Math_BigInteger_Bcmath(); + } else { + require_once 'Zend/Crypt/Math/BigInteger/Exception.php'; + throw new Zend_Crypt_Math_BigInteger_Exception($extension . ' big integer precision math support not detected'); + } + } + +} diff --git a/lib/zend/Zend/Crypt/Math/BigInteger/Bcmath.php b/lib/zend/Zend/Crypt/Math/BigInteger/Bcmath.php new file mode 100644 index 00000000000..40154b6fbb0 --- /dev/null +++ b/lib/zend/Zend/Crypt/Math/BigInteger/Bcmath.php @@ -0,0 +1,227 @@ + 0) { + $return = chr(bcmod($operand, 256)) . $return; + $operand = bcdiv($operand, 256); + } + if (ord($return[0]) > 127) { + $return = "\0" . $return; + } + return $return; + } + + /**public function integerToBinary($operand) + { + $return = ''; + while(bccomp($operand, '0')) { + $return .= chr(bcmod($operand, '256')); + $operand = bcdiv($operand, '256'); + } + return $return; + }**/ // Prior version for referenced offset + + /** + * @param string $operand + * @return string + */ + public function hexToDecimal($operand) + { + $return = '0'; + while(strlen($hex)) { + $hex = hexdec(substr($operand, 0, 4)); + $dec = bcadd(bcmul($return, 65536), $hex); + $operand = substr($operand, 4); + } + return $return; + } +} diff --git a/lib/zend/Zend/Crypt/Math/BigInteger/Exception.php b/lib/zend/Zend/Crypt/Math/BigInteger/Exception.php new file mode 100644 index 00000000000..d5ee2e6ddf0 --- /dev/null +++ b/lib/zend/Zend/Crypt/Math/BigInteger/Exception.php @@ -0,0 +1,36 @@ + '7') { + $bigInt = '00' . $bigInt; + } + $return = pack("H*", $bigInt); + return $return; + } + + /** + * @param string $operand + * @return string + */ + public function hexToDecimal($operand) + { + $return = '0'; + while(strlen($hex)) { + $hex = hexdec(substr($operand, 0, 4)); + $dec = gmp_add(gmp_mul($return, 65536), $hex); + $operand = substr($operand, 4); + } + return $return; + } + +} diff --git a/lib/zend/Zend/Crypt/Math/BigInteger/Interface.php b/lib/zend/Zend/Crypt/Math/BigInteger/Interface.php new file mode 100644 index 00000000000..9fa92815e30 --- /dev/null +++ b/lib/zend/Zend/Crypt/Math/BigInteger/Interface.php @@ -0,0 +1,51 @@ +_hashAlgorithm = OPENSSL_ALGO_SHA1; + + if (isset($options)) { + $this->setOptions($options); + } + } + + public function setOptions(array $options) + { + if (isset($options['passPhrase'])) { + $this->_passPhrase = $options['passPhrase']; + } + foreach ($options as $option=>$value) { + switch ($option) { + case 'pemString': + $this->setPemString($value); + break; + case 'pemPath': + $this->setPemPath($value); + break; + case 'certificateString': + $this->setCertificateString($value); + break; + case 'certificatePath': + $this->setCertificatePath($value); + break; + case 'hashAlgorithm': + $this->setHashAlgorithm($value); + break; + } + } + } + + public function getPrivateKey() + { + return $this->_privateKey; + } + + public function getPublicKey() + { + return $this->_publicKey; + } + + /** + * @param string $data + * @param Zend_Crypt_Rsa_Key_Private $privateKey + * @param string $format + * @return string + */ + public function sign($data, Zend_Crypt_Rsa_Key_Private $privateKey = null, $format = null) + { + $signature = ''; + if (isset($privateKey)) { + $opensslKeyResource = $privateKey->getOpensslKeyResource(); + } else { + $opensslKeyResource = $this->_privateKey->getOpensslKeyResource(); + } + $result = openssl_sign( + $data, $signature, + $opensslKeyResource, + $this->getHashAlgorithm() + ); + if ($format == self::BASE64) { + return base64_encode($signature); + } + return $signature; + } + + /** + * @param string $data + * @param string $signature + * @param string $format + * @return string + */ + public function verifySignature($data, $signature, $format = null) + { + if ($format == self::BASE64) { + $signature = base64_decode($signature); + } + $result = openssl_verify($data, $signature, + $this->getPublicKey()->getOpensslKeyResource(), + $this->getHashAlgorithm()); + return $result; + } + + /** + * @param string $data + * @param Zend_Crypt_Rsa_Key $key + * @param string $format + * @return string + */ + public function encrypt($data, Zend_Crypt_Rsa_Key $key, $format = null) + { + $encrypted = ''; + $function = 'openssl_public_encrypt'; + if ($key instanceof Zend_Crypt_Rsa_Key_Private) { + $function = 'openssl_private_encrypt'; + } + $function($data, $encrypted, $key->getOpensslKeyResource()); + if ($format == self::BASE64) { + return base64_encode($encrypted); + } + return $encrypted; + } + + /** + * @param string $data + * @param Zend_Crypt_Rsa_Key $key + * @param string $format + * @return string + */ + public function decrypt($data, Zend_Crypt_Rsa_Key $key, $format = null) + { + $decrypted = ''; + if ($format == self::BASE64) { + $data = base64_decode($data); + } + $function = 'openssl_private_decrypt'; + if ($key instanceof Zend_Crypt_Rsa_Key_Public) { + $function = 'openssl_public_decrypt'; + } + $function($data, $decrypted, $key->getOpensslKeyResource()); + return $decrypted; + } + + /** + * @param array $configargs + * + * @throws Zend_Crypt_Rsa_Exception + * + * @return ArrayObject + */ + public function generateKeys(array $configargs = null) + { + $config = null; + $passPhrase = null; + if ($configargs !== null) { + if (isset($configargs['passPhrase'])) { + $passPhrase = $configargs['passPhrase']; + unset($configargs['passPhrase']); + } + $config = $this->_parseConfigArgs($configargs); + } + $privateKey = null; + $publicKey = null; + $resource = openssl_pkey_new($config); + if (!$resource) { + require_once 'Zend/Crypt/Rsa/Exception.php'; + throw new Zend_Crypt_Rsa_Exception('Failed to generate a new private key'); + } + // above fails on PHP 5.3 + openssl_pkey_export($resource, $private, $passPhrase); + $privateKey = new Zend_Crypt_Rsa_Key_Private($private, $passPhrase); + $details = openssl_pkey_get_details($resource); + $publicKey = new Zend_Crypt_Rsa_Key_Public($details['key']); + $return = new ArrayObject(array( + 'privateKey'=>$privateKey, + 'publicKey'=>$publicKey + ), ArrayObject::ARRAY_AS_PROPS); + return $return; + } + + /** + * @param string $value + */ + public function setPemString($value) + { + $this->_pemString = $value; + try { + $this->_privateKey = new Zend_Crypt_Rsa_Key_Private($this->_pemString, $this->_passPhrase); + $this->_publicKey = $this->_privateKey->getPublicKey(); + } catch (Zend_Crypt_Exception $e) { + $this->_privateKey = null; + $this->_publicKey = new Zend_Crypt_Rsa_Key_Public($this->_pemString); + } + } + + public function setPemPath($value) + { + $this->_pemPath = $value; + $this->setPemString(file_get_contents($this->_pemPath)); + } + + public function setCertificateString($value) + { + $this->_certificateString = $value; + $this->_publicKey = new Zend_Crypt_Rsa_Key_Public($this->_certificateString, $this->_passPhrase); + } + + public function setCertificatePath($value) + { + $this->_certificatePath = $value; + $this->setCertificateString(file_get_contents($this->_certificatePath)); + } + + public function setHashAlgorithm($name) + { + switch (strtolower($name)) { + case 'md2': + $this->_hashAlgorithm = OPENSSL_ALGO_MD2; + break; + case 'md4': + $this->_hashAlgorithm = OPENSSL_ALGO_MD4; + break; + case 'md5': + $this->_hashAlgorithm = OPENSSL_ALGO_MD5; + break; + case 'sha1': + $this->_hashAlgorithm = OPENSSL_ALGO_SHA1; + break; + case 'dss1': + $this->_hashAlgorithm = OPENSSL_ALGO_DSS1; + break; + } + } + + /** + * @return string + */ + public function getPemString() + { + return $this->_pemString; + } + + public function getPemPath() + { + return $this->_pemPath; + } + + public function getCertificateString() + { + return $this->_certificateString; + } + + public function getCertificatePath() + { + return $this->_certificatePath; + } + + public function getHashAlgorithm() + { + return $this->_hashAlgorithm; + } + + protected function _parseConfigArgs(array $config = null) + { + $configs = array(); + if (isset($config['private_key_bits'])) { + $configs['private_key_bits'] = $config['private_key_bits']; + } + if (isset($config['privateKeyBits'])) { + $configs['private_key_bits'] = $config['privateKeyBits']; + } + if (!empty($configs)) { + return $configs; + } + return null; + } + +} diff --git a/lib/zend/Zend/Crypt/Rsa/Exception.php b/lib/zend/Zend/Crypt/Rsa/Exception.php new file mode 100644 index 00000000000..f1cf65e86ac --- /dev/null +++ b/lib/zend/Zend/Crypt/Rsa/Exception.php @@ -0,0 +1,36 @@ +_opensslKeyResource; + } + + /** + * @return string + * @throws Zend_Crypt_Exception + */ + public function toString() + { + if (!empty($this->_pemString)) { + return $this->_pemString; + } elseif (!empty($this->_certificateString)) { + return $this->_certificateString; + } + /** + * @see Zend_Crypt_Exception + */ + require_once 'Zend/Crypt/Exception.php'; + throw new Zend_Crypt_Exception('No public key string representation is available'); + } + + /** + * @return string + */ + public function __toString() + { + return $this->toString(); + } + + public function count() + { + return $this->_details['bits']; + } + + public function getType() + { + return $this->_details['type']; + } +} diff --git a/lib/zend/Zend/Crypt/Rsa/Key/Private.php b/lib/zend/Zend/Crypt/Rsa/Key/Private.php new file mode 100644 index 00000000000..98b2e026c24 --- /dev/null +++ b/lib/zend/Zend/Crypt/Rsa/Key/Private.php @@ -0,0 +1,75 @@ +_pemString = $pemString; + $this->_parse($passPhrase); + } + + /** + * @param string $passPhrase + * @throws Zend_Crypt_Exception + */ + protected function _parse($passPhrase) + { + $result = openssl_get_privatekey($this->_pemString, $passPhrase); + if (!$result) { + /** + * @see Zend_Crypt_Exception + */ + require_once 'Zend/Crypt/Exception.php'; + throw new Zend_Crypt_Exception('Unable to load private key'); + } + $this->_opensslKeyResource = $result; + $this->_details = openssl_pkey_get_details($this->_opensslKeyResource); + } + + public function getPublicKey() + { + if ($this->_publicKey === null) { + /** + * @see Zend_Crypt_Rsa_Key_Public + */ + require_once 'Zend/Crypt/Rsa/Key/Public.php'; + $this->_publicKey = new Zend_Crypt_Rsa_Key_Public($this->_details['key']); + } + return $this->_publicKey; + } + +} diff --git a/lib/zend/Zend/Crypt/Rsa/Key/Public.php b/lib/zend/Zend/Crypt/Rsa/Key/Public.php new file mode 100644 index 00000000000..9694342d17b --- /dev/null +++ b/lib/zend/Zend/Crypt/Rsa/Key/Public.php @@ -0,0 +1,74 @@ +_parse($string); + } + + /** + * @param string $string + * @throws Zend_Crypt_Exception + */ + protected function _parse($string) + { + if (preg_match("/^-----BEGIN CERTIFICATE-----/", $string)) { + $this->_certificateString = $string; + } else { + $this->_pemString = $string; + } + $result = openssl_get_publickey($string); + if (!$result) { + /** + * @see Zend_Crypt_Exception + */ + require_once 'Zend/Crypt/Exception.php'; + throw new Zend_Crypt_Exception('Unable to load public key'); + } + //openssl_pkey_export($result, $public); + //$this->_pemString = $public; + $this->_opensslKeyResource = $result; + $this->_details = openssl_pkey_get_details($this->_opensslKeyResource); + } + + public function getCertificate() + { + return $this->_certificateString; + } + +} diff --git a/lib/zend/Zend/Currency.php b/lib/zend/Zend/Currency.php new file mode 100644 index 00000000000..9abc8b19989 --- /dev/null +++ b/lib/zend/Zend/Currency.php @@ -0,0 +1,902 @@ + Position for the currency sign + * 'script' => Script for the output + * 'format' => Locale for numeric output + * 'display' => Currency detail to show + * 'precision' => Precision for the currency + * 'name' => Name for this currency + * 'currency' => 3 lettered international abbreviation + * 'symbol' => Currency symbol + * 'locale' => Locale for this currency + * 'value' => Money value + * 'service' => Exchange service to use + * + * @var array + * @see Zend_Locale + */ + protected $_options = array( + 'position' => self::STANDARD, + 'script' => null, + 'format' => null, + 'display' => self::NO_SYMBOL, + 'precision' => 2, + 'name' => null, + 'currency' => null, + 'symbol' => null, + 'locale' => null, + 'value' => 0, + 'service' => null, + 'tag' => 'Zend_Locale' + ); + + /** + * Creates a currency instance. Every supressed parameter is used from the actual or the given locale. + * + * @param string|array $options OPTIONAL Options array or currency short name + * when string is given + * @param string|Zend_Locale $locale OPTIONAL locale name + * @throws Zend_Currency_Exception When currency is invalid + */ + public function __construct($options = null, $locale = null) + { + $calloptions = $options; + if (is_array($options) && isset($options['display'])) { + $this->_options['display'] = $options['display']; + } + + if (is_array($options)) { + $this->setLocale($locale); + $this->setFormat($options); + } else if (Zend_Locale::isLocale($options, false, false)) { + $this->setLocale($options); + $options = $locale; + } else { + $this->setLocale($locale); + } + + // Get currency details + if (!isset($this->_options['currency']) || !is_array($options)) { + $this->_options['currency'] = self::getShortName($options, $this->_options['locale']); + } + + if (!isset($this->_options['name']) || !is_array($options)) { + $this->_options['name'] = self::getName($options, $this->_options['locale']); + } + + if (!isset($this->_options['symbol']) || !is_array($options)) { + $this->_options['symbol'] = self::getSymbol($options, $this->_options['locale']); + } + + if (($this->_options['currency'] === null) and ($this->_options['name'] === null)) { + require_once 'Zend/Currency/Exception.php'; + throw new Zend_Currency_Exception("Currency '$options' not found"); + } + + // Get the format + if ((is_array($calloptions) && !isset($calloptions['display'])) + || (!is_array($calloptions) && $this->_options['display'] == self::NO_SYMBOL)) { + if (!empty($this->_options['symbol'])) { + $this->_options['display'] = self::USE_SYMBOL; + } else if (!empty($this->_options['currency'])) { + $this->_options['display'] = self::USE_SHORTNAME; + } + } + } + + /** + * Returns a localized currency string + * + * @param integer|float $value OPTIONAL Currency value + * @param array $options OPTIONAL options to set temporary + * @throws Zend_Currency_Exception When the value is not a number + * @return string + */ + public function toCurrency($value = null, array $options = array()) + { + if ($value === null) { + if (is_array($options) && isset($options['value'])) { + $value = $options['value']; + } else { + $value = $this->_options['value']; + } + } + + if (is_array($value)) { + $options += $value; + if (isset($options['value'])) { + $value = $options['value']; + } + } + + // Validate the passed number + if (!(isset($value)) or (is_numeric($value) === false)) { + require_once 'Zend/Currency/Exception.php'; + throw new Zend_Currency_Exception("Value '$value' has to be numeric"); + } + + if (isset($options['currency'])) { + if (!isset($options['locale'])) { + $options['locale'] = $this->_options['locale']; + } + + $options['currency'] = self::getShortName($options['currency'], $options['locale']); + $options['name'] = self::getName($options['currency'], $options['locale']); + $options['symbol'] = self::getSymbol($options['currency'], $options['locale']); + } + + $options = $this->_checkOptions($options) + $this->_options; + + // Format the number + $format = $options['format']; + $locale = $options['locale']; + if (empty($format)) { + $format = Zend_Locale_Data::getContent($locale, 'currencynumber'); + } else if (Zend_Locale::isLocale($format, true, false)) { + $locale = $format; + $format = Zend_Locale_Data::getContent($format, 'currencynumber'); + } + + $original = $value; + $value = Zend_Locale_Format::toNumber($value, array('locale' => $locale, + 'number_format' => $format, + 'precision' => $options['precision'])); + + if ($options['position'] !== self::STANDARD) { + $value = str_replace('¤', '', $value); + $space = ''; + if (iconv_strpos($value, ' ') !== false) { + $value = str_replace(' ', '', $value); + $space = ' '; + } + + if ($options['position'] == self::LEFT) { + $value = '¤' . $space . $value; + } else { + $value = $value . $space . '¤'; + } + } + + // Localize the number digits + if (empty($options['script']) === false) { + $value = Zend_Locale_Format::convertNumerals($value, 'Latn', $options['script']); + } + + // Get the sign to be placed next to the number + if (is_numeric($options['display']) === false) { + $sign = $options['display']; + } else { + switch($options['display']) { + case self::USE_SYMBOL: + $sign = $this->_extractPattern($options['symbol'], $original); + break; + + case self::USE_SHORTNAME: + $sign = $options['currency']; + break; + + case self::USE_NAME: + $sign = $options['name']; + break; + + default: + $sign = ''; + $value = str_replace(' ', '', $value); + break; + } + } + + $value = str_replace('¤', $sign, $value); + return $value; + } + + /** + * Internal method to extract the currency pattern + * when a choice is given based on the given value + * + * @param string $pattern + * @param float|integer $value + * @return string + */ + private function _extractPattern($pattern, $value) + { + if (strpos($pattern, '|') === false) { + return $pattern; + } + + $patterns = explode('|', $pattern); + $token = $pattern; + $value = trim(str_replace('¤', '', $value)); + krsort($patterns); + foreach($patterns as $content) { + if (strpos($content, '<') !== false) { + $check = iconv_substr($content, 0, iconv_strpos($content, '<')); + $token = iconv_substr($content, iconv_strpos($content, '<') + 1); + if ($check < $value) { + return $token; + } + } else { + $check = iconv_substr($content, 0, iconv_strpos($content, '≤')); + $token = iconv_substr($content, iconv_strpos($content, '≤') + 1); + if ($check <= $value) { + return $token; + } + } + + } + + return $token; + } + + /** + * Sets the formating options of the localized currency string + * If no parameter is passed, the standard setting of the + * actual set locale will be used + * + * @param array $options (Optional) Options to set + * @return Zend_Currency + */ + public function setFormat(array $options = array()) + { + $this->_options = $this->_checkOptions($options) + $this->_options; + return $this; + } + + /** + * Internal function for checking static given locale parameter + * + * @param string $currency (Optional) Currency name + * @param string|Zend_Locale $locale (Optional) Locale to display informations + * @throws Zend_Currency_Exception When locale contains no region + * @return string The extracted locale representation as string + */ + private function _checkParams($currency = null, $locale = null) + { + // Manage the params + if ((empty($locale)) and (!empty($currency)) and + (Zend_Locale::isLocale($currency, true, false))) { + $locale = $currency; + $currency = null; + } + + // Validate the locale and get the country short name + $country = null; + if ((Zend_Locale::isLocale($locale, true, false)) and (strlen($locale) > 4)) { + $country = substr($locale, (strpos($locale, '_') + 1)); + } else { + require_once 'Zend/Currency/Exception.php'; + throw new Zend_Currency_Exception("No region found within the locale '" . (string) $locale . "'"); + } + + // Get the available currencies for this country + $data = Zend_Locale_Data::getContent($locale, 'currencytoregion', $country); + if ((empty($currency) === false) and (empty($data) === false)) { + $abbreviation = $currency; + } else { + $abbreviation = $data; + } + + return array('locale' => $locale, 'currency' => $currency, 'name' => $abbreviation, 'country' => $country); + } + + /** + * Returns the actual or details of other currency symbols, + * when no symbol is available it returns the currency shortname (f.e. FIM for Finnian Mark) + * + * @param string $currency (Optional) Currency name + * @param string|Zend_Locale $locale (Optional) Locale to display informations + * @return string + */ + public function getSymbol($currency = null, $locale = null) + { + if (($currency === null) and ($locale === null)) { + return $this->_options['symbol']; + } + + $params = self::_checkParams($currency, $locale); + + // Get the symbol + $symbol = Zend_Locale_Data::getContent($params['locale'], 'currencysymbol', $params['currency']); + if (empty($symbol) === true) { + $symbol = Zend_Locale_Data::getContent($params['locale'], 'currencysymbol', $params['name']); + } + + if (empty($symbol) === true) { + return null; + } + + return $symbol; + } + + /** + * Returns the actual or details of other currency shortnames + * + * @param string $currency OPTIONAL Currency's name + * @param string|Zend_Locale $locale OPTIONAL The locale + * @return string + */ + public function getShortName($currency = null, $locale = null) + { + if (($currency === null) and ($locale === null)) { + return $this->_options['currency']; + } + + $params = self::_checkParams($currency, $locale); + + // Get the shortname + if (empty($params['currency']) === true) { + return $params['name']; + } + + $list = Zend_Locale_Data::getContent($params['locale'], 'currencytoname', $params['currency']); + if (empty($list) === true) { + $list = Zend_Locale_Data::getContent($params['locale'], 'nametocurrency', $params['currency']); + if (empty($list) === false) { + $list = $params['currency']; + } + } + + if (empty($list) === true) { + return null; + } + + return $list; + } + + /** + * Returns the actual or details of other currency names + * + * @param string $currency (Optional) Currency's short name + * @param string|Zend_Locale $locale (Optional) The locale + * @return string + */ + public function getName($currency = null, $locale = null) + { + if (($currency === null) and ($locale === null)) { + return $this->_options['name']; + } + + $params = self::_checkParams($currency, $locale); + + // Get the name + $name = Zend_Locale_Data::getContent($params['locale'], 'nametocurrency', $params['currency']); + if (empty($name) === true) { + $name = Zend_Locale_Data::getContent($params['locale'], 'nametocurrency', $params['name']); + } + + if (empty($name) === true) { + return null; + } + + return $name; + } + + /** + * Returns a list of regions where this currency is or was known + * + * @param string $currency OPTIONAL Currency's short name + * @throws Zend_Currency_Exception When no currency was defined + * @return array List of regions + */ + public function getRegionList($currency = null) + { + if ($currency === null) { + $currency = $this->_options['currency']; + } + + if (empty($currency) === true) { + require_once 'Zend/Currency/Exception.php'; + throw new Zend_Currency_Exception('No currency defined'); + } + + $data = Zend_Locale_Data::getContent($this->_options['locale'], 'regiontocurrency', $currency); + + $result = explode(' ', $data); + return $result; + } + + /** + * Returns a list of currencies which are used in this region + * a region name should be 2 charachters only (f.e. EG, DE, US) + * If no region is given, the actual region is used + * + * @param string $region OPTIONAL Region to return the currencies for + * @return array List of currencies + */ + public function getCurrencyList($region = null) + { + if (empty($region) === true) { + if (strlen($this->_options['locale']) > 4) { + $region = substr($this->_options['locale'], (strpos($this->_options['locale'], '_') + 1)); + } + } + + $data = Zend_Locale_Data::getContent($this->_options['locale'], 'currencytoregion', $region); + + $result = explode(' ', $data); + return $result; + } + + /** + * Returns the actual currency name + * + * @return string + */ + public function toString() + { + return $this->toCurrency(); + } + + /** + * Returns the currency name + * + * @return string + */ + public function __toString() + { + return $this->toString(); + } + + /** + * Returns the set cache + * + * @return Zend_Cache_Core The set cache + */ + public static function getCache() + { + return Zend_Locale_Data::getCache(); + } + + /** + * Sets a cache for Zend_Currency + * + * @param Zend_Cache_Core $cache Cache to set + * @return void + */ + public static function setCache(Zend_Cache_Core $cache) + { + Zend_Locale_Data::setCache($cache); + } + + /** + * Returns true when a cache is set + * + * @return boolean + */ + public static function hasCache() + { + return Zend_Locale_Data::hasCache(); + } + + /** + * Removes any set cache + * + * @return void + */ + public static function removeCache() + { + Zend_Locale_Data::removeCache(); + } + + /** + * Clears all set cache data + * + * @param string $tag Tag to clear when the default tag name is not used + * @return void + */ + public static function clearCache($tag = null) + { + Zend_Locale_Data::clearCache($tag); + } + + /** + * Sets a new locale for data retreivement + * Example: 'de_XX' will be set to 'de' because 'de_XX' does not exist + * 'xx_YY' will be set to 'root' because 'xx' does not exist + * + * @param string|Zend_Locale $locale (Optional) Locale for parsing input + * @throws Zend_Currency_Exception When the given locale does not exist + * @return Zend_Currency Provides fluent interface + */ + public function setLocale($locale = null) + { + require_once 'Zend/Locale.php'; + try { + $locale = Zend_Locale::findLocale($locale); + if (strlen($locale) > 4) { + $this->_options['locale'] = $locale; + } else { + require_once 'Zend/Currency/Exception.php'; + throw new Zend_Currency_Exception("No region found within the locale '" . (string) $locale . "'"); + } + } catch (Zend_Locale_Exception $e) { + require_once 'Zend/Currency/Exception.php'; + throw new Zend_Currency_Exception($e->getMessage()); + } + + // Get currency details + $this->_options['currency'] = $this->getShortName(null, $this->_options['locale']); + $this->_options['name'] = $this->getName(null, $this->_options['locale']); + $this->_options['symbol'] = $this->getSymbol(null, $this->_options['locale']); + + return $this; + } + + /** + * Returns the actual set locale + * + * @return string + */ + public function getLocale() + { + return $this->_options['locale']; + } + + /** + * Returns the value + * + * @return float + */ + public function getValue() + { + return $this->_options['value']; + } + + /** + * Adds a currency + * + * @param float|integer|Zend_Currency $value Add this value to currency + * @param string|Zend_Currency $currency The currency to add + * @return Zend_Currency + */ + public function setValue($value, $currency = null) + { + $this->_options['value'] = $this->_exchangeCurrency($value, $currency); + return $this; + } + + /** + * Adds a currency + * + * @param float|integer|Zend_Currency $value Add this value to currency + * @param string|Zend_Currency $currency The currency to add + * @return Zend_Currency + */ + public function add($value, $currency = null) + { + $value = $this->_exchangeCurrency($value, $currency); + $this->_options['value'] += (float) $value; + return $this; + } + + /** + * Substracts a currency + * + * @param float|integer|Zend_Currency $value Substracts this value from currency + * @param string|Zend_Currency $currency The currency to substract + * @return Zend_Currency + */ + public function sub($value, $currency = null) + { + $value = $this->_exchangeCurrency($value, $currency); + $this->_options['value'] -= (float) $value; + return $this; + } + + /** + * Divides a currency + * + * @param float|integer|Zend_Currency $value Divides this value from currency + * @param string|Zend_Currency $currency The currency to divide + * @return Zend_Currency + */ + public function div($value, $currency = null) + { + $value = $this->_exchangeCurrency($value, $currency); + $this->_options['value'] /= (float) $value; + return $this; + } + + /** + * Multiplies a currency + * + * @param float|integer|Zend_Currency $value Multiplies this value from currency + * @param string|Zend_Currency $currency The currency to multiply + * @return Zend_Currency + */ + public function mul($value, $currency = null) + { + $value = $this->_exchangeCurrency($value, $currency); + $this->_options['value'] *= (float) $value; + return $this; + } + + /** + * Calculates the modulo from a currency + * + * @param float|integer|Zend_Currency $value Calculate modulo from this value + * @param string|Zend_Currency $currency The currency to calculate the modulo + * @return Zend_Currency + */ + public function mod($value, $currency = null) + { + $value = $this->_exchangeCurrency($value, $currency); + $this->_options['value'] %= (float) $value; + return $this; + } + + /** + * Compares two currencies + * + * @param float|integer|Zend_Currency $value Compares the currency with this value + * @param string|Zend_Currency $currency The currency to compare this value from + * @return Zend_Currency + */ + public function compare($value, $currency = null) + { + $value = $this->_exchangeCurrency($value, $currency); + $value = $this->_options['value'] - $value; + if ($value < 0) { + return -1; + } else if ($value > 0) { + return 1; + } + + return 0; + } + + /** + * Returns true when the two currencies are equal + * + * @param float|integer|Zend_Currency $value Compares the currency with this value + * @param string|Zend_Currency $currency The currency to compare this value from + * @return boolean + */ + public function equals($value, $currency = null) + { + $value = $this->_exchangeCurrency($value, $currency); + if ($this->_options['value'] == $value) { + return true; + } + + return false; + } + + /** + * Returns true when the currency is more than the given value + * + * @param float|integer|Zend_Currency $value Compares the currency with this value + * @param string|Zend_Currency $currency The currency to compare this value from + * @return boolean + */ + public function isMore($value, $currency = null) + { + $value = $this->_exchangeCurrency($value, $currency); + if ($this->_options['value'] > $value) { + return true; + } + + return false; + } + + /** + * Returns true when the currency is less than the given value + * + * @param float|integer|Zend_Currency $value Compares the currency with this value + * @param string|Zend_Currency $currency The currency to compare this value from + * @return boolean + */ + public function isLess($value, $currency = null) + { + $value = $this->_exchangeCurrency($value, $currency); + if ($this->_options['value'] < $value) { + return true; + } + + return false; + + } + + /** + * Internal method which calculates the exchanges currency + * + * @param float|integer|Zend_Currency $value Compares the currency with this value + * @param string|Zend_Currency $currency The currency to compare this value from + * @return unknown + */ + protected function _exchangeCurrency($value, $currency) + { + if ($value instanceof Zend_Currency) { + $currency = $value->getShortName(); + $value = $value->getValue(); + } else { + $currency = $this->getShortName($currency, $this->getLocale()); + } + + $rate = 1; + if ($currency !== $this->getShortName()) { + $service = $this->getService(); + if (!($service instanceof Zend_Currency_CurrencyInterface)) { + require_once 'Zend/Currency/Exception.php'; + throw new Zend_Currency_Exception('No exchange service applied'); + } + + $rate = $service->getRate($currency, $this->getShortName()); + } + + $value *= $rate; + return $value; + } + + /** + * Returns the set service class + * + * @return Zend_Service + */ + public function getService() + { + return $this->_options['service']; + } + + /** + * Sets a new exchange service + * + * @param string|Zend_Currency_CurrencyInterface $service Service class + * @return Zend_Currency + */ + public function setService($service) + { + if (is_string($service)) { + require_once 'Zend/Loader.php'; + if (!class_exists($service)) { + $file = str_replace('_', DIRECTORY_SEPARATOR, $service) . '.php'; + if (Zend_Loader::isReadable($file)) { + Zend_Loader::loadClass($service); + } + } + + $service = new $service; + } + + if (!($service instanceof Zend_Currency_CurrencyInterface)) { + require_once 'Zend/Currency/Exception.php'; + throw new Zend_Currency_Exception('A currency service must implement Zend_Currency_CurrencyInterface'); + } + + $this->_options['service'] = $service; + return $this; + } + + /** + * Internal method for checking the options array + * + * @param array $options Options to check + * @throws Zend_Currency_Exception On unknown position + * @throws Zend_Currency_Exception On unknown locale + * @throws Zend_Currency_Exception On unknown display + * @throws Zend_Currency_Exception On precision not between -1 and 30 + * @throws Zend_Currency_Exception On problem with script conversion + * @throws Zend_Currency_Exception On unknown options + * @return array + */ + protected function _checkOptions(array $options = array()) + { + if (count($options) === 0) { + return $this->_options; + } + + foreach ($options as $name => $value) { + $name = strtolower($name); + if ($name !== 'format') { + if (gettype($value) === 'string') { + $value = strtolower($value); + } + } + + switch($name) { + case 'position': + if (($value !== self::STANDARD) and ($value !== self::RIGHT) and ($value !== self::LEFT)) { + require_once 'Zend/Currency/Exception.php'; + throw new Zend_Currency_Exception("Unknown position '" . $value . "'"); + } + + break; + + case 'format': + if ((empty($value) === false) and (Zend_Locale::isLocale($value, null, false) === false)) { + if (!is_string($value) || (strpos($value, '0') === false)) { + require_once 'Zend/Currency/Exception.php'; + throw new Zend_Currency_Exception("'" . + ((gettype($value) === 'object') ? get_class($value) : $value) + . "' is no format token"); + } + } + break; + + case 'display': + if (is_numeric($value) and ($value !== self::NO_SYMBOL) and ($value !== self::USE_SYMBOL) and + ($value !== self::USE_SHORTNAME) and ($value !== self::USE_NAME)) { + require_once 'Zend/Currency/Exception.php'; + throw new Zend_Currency_Exception("Unknown display '$value'"); + } + break; + + case 'precision': + if ($value === null) { + $value = -1; + } + + if (($value < -1) or ($value > 30)) { + require_once 'Zend/Currency/Exception.php'; + throw new Zend_Currency_Exception("'$value' precision has to be between -1 and 30."); + } + break; + + case 'script': + try { + Zend_Locale_Format::convertNumerals(0, $options['script']); + } catch (Zend_Locale_Exception $e) { + require_once 'Zend/Currency/Exception.php'; + throw new Zend_Currency_Exception($e->getMessage()); + } + break; + + default: + break; + } + } + + return $options; + } +} diff --git a/lib/zend/Zend/Currency/CurrencyInterface.php b/lib/zend/Zend/Currency/CurrencyInterface.php new file mode 100644 index 00000000000..8e828864b8c --- /dev/null +++ b/lib/zend/Zend/Currency/CurrencyInterface.php @@ -0,0 +1,39 @@ += -12)) { + if (!empty($match) and ($match[count($match) - 1] <= 14) and ($match[count($match) - 1] >= -12)) { $zone = "Etc/GMT"; $zone .= ($match[count($match) - 1] < 0) ? "+" : "-"; $zone .= (int) abs($match[count($match) - 1]); return $zone; } - preg_match('/([[:alpha:]\/]{3,30})(?!.*([[:alpha:]\/]{3,30}))/', $zone, $match); + preg_match('/([[:alpha:]\/_]{3,30})(?!.*([[:alpha:]\/]{3,30}))/', $zone, $match); try { if (!empty($match) and (!is_int($match[count($match) - 1]))) { $oldzone = $this->getTimezone(); @@ -2066,9 +2067,18 @@ class Zend_Date extends Zend_Date_DateObject } // (T)hh:mm:ss preg_match('/[T,\s]{0,1}(\d{2}):(\d{2}):(\d{2})/', $tmpdate, $timematch); + // (T)hhmmss if (empty($timematch)) { preg_match('/[T,\s]{0,1}(\d{2})(\d{2})(\d{2})/', $tmpdate, $timematch); } + // (T)hh:mm + if (empty($timematch)) { + preg_match('/[T,\s]{0,1}(\d{2}):(\d{2})/', $tmpdate, $timematch); + } + // (T)hhmm + if (empty($timematch)) { + preg_match('/[T,\s]{0,1}(\d{2})(\d{2})/', $tmpdate, $timematch); + } if (empty($datematch) and empty($timematch)) { require_once 'Zend/Date/Exception.php'; throw new Zend_Date_Exception("unsupported ISO8601 format ($date)", 0, null, $date); @@ -2092,6 +2102,9 @@ class Zend_Date extends Zend_Date_DateObject $timematch[2] = 0; $timematch[3] = 0; } + if (!isset($timematch[3])) { + $timematch[3] = 0; + } if (($calc == 'set') || ($calc == 'cmp')) { --$datematch[2]; @@ -2106,7 +2119,10 @@ class Zend_Date extends Zend_Date_DateObject break; case self::RFC_2822: - $result = preg_match('/^\w{3},\s(\d{1,2})\s(\w{3})\s(\d{4})\s(\d{2}):(\d{2}):{0,1}(\d{0,2})\s([+-]{1}\d{4})$/', $date, $match); + $result = preg_match('/^\w{3},\s(\d{1,2})\s(\w{3})\s(\d{4})\s' + . '(\d{2}):(\d{2}):{0,1}(\d{0,2})\s([+-]' + . '{1}\d{4}|\w{1,20})$/', $date, $match); + if (!$result) { require_once 'Zend/Date/Exception.php'; throw new Zend_Date_Exception("no RFC 2822 format ($date)", 0, null, $date); @@ -2640,10 +2656,8 @@ class Zend_Date extends Zend_Date_DateObject $parsed['day'] = 0; } - if (isset($parsed['year'])) { - $parsed['year'] -= 1970; - } else { - $parsed['year'] = 0; + if (!isset($parsed['year'])) { + $parsed['year'] = 1970; } } @@ -2653,7 +2667,7 @@ class Zend_Date extends Zend_Date_DateObject isset($parsed['second']) ? $parsed['second'] : 0, isset($parsed['month']) ? (1 + $parsed['month']) : 1, isset($parsed['day']) ? (1 + $parsed['day']) : 1, - isset($parsed['year']) ? (1970 + $parsed['year']) : 1970, + $parsed['year'], false), $this->getUnixTimestamp(), false); } catch (Zend_Locale_Exception $e) { if (!is_numeric($date)) { @@ -2834,7 +2848,7 @@ class Zend_Date extends Zend_Date_DateObject * @param string|integer|array|Zend_Date $time Time to set * @param string $format OPTIONAL Timeformat for parsing input * @param string|Zend_Locale $locale OPTIONAL Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function setTime($time, $format = null, $locale = null) @@ -2852,7 +2866,7 @@ class Zend_Date extends Zend_Date_DateObject * @param string|integer|array|Zend_Date $time Time to add * @param string $format OPTIONAL Timeformat for parsing input * @param string|Zend_Locale $locale OPTIONAL Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function addTime($time, $format = null, $locale = null) @@ -2870,7 +2884,7 @@ class Zend_Date extends Zend_Date_DateObject * @param string|integer|array|Zend_Date $time Time to sub * @param string $format OPTIONAL Timeformat for parsing input * @param string|Zend_Locale $locale OPTIONAL Locale for parsing input - * @return Zend_Date Provides fluid inteface + * @return Zend_Date Provides a fluent inteface * @throws Zend_Date_Exception */ public function subTime($time, $format = null, $locale = null) @@ -2996,7 +3010,7 @@ class Zend_Date extends Zend_Date_DateObject * @param string|integer|array|Zend_Date $date Date to set * @param string $format OPTIONAL Date format for parsing * @param string|Zend_Locale $locale OPTIONAL Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function setDate($date, $format = null, $locale = null) @@ -3014,7 +3028,7 @@ class Zend_Date extends Zend_Date_DateObject * @param string|integer|array|Zend_Date $date Date to add * @param string $format OPTIONAL Date format for parsing input * @param string|Zend_Locale $locale OPTIONAL Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function addDate($date, $format = null, $locale = null) @@ -3033,7 +3047,7 @@ class Zend_Date extends Zend_Date_DateObject * @param string|integer|array|Zend_Date $date Date to sub * @param string $format OPTIONAL Date format for parsing input * @param string|Zend_Locale $locale OPTIONAL Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function subDate($date, $format = null, $locale = null) @@ -3084,7 +3098,7 @@ class Zend_Date extends Zend_Date_DateObject * * @param string|integer|Zend_Date $date ISO Date to set * @param string|Zend_Locale $locale OPTIONAL Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function setIso($date, $locale = null) @@ -3101,7 +3115,7 @@ class Zend_Date extends Zend_Date_DateObject * * @param string|integer|Zend_Date $date ISO Date to add * @param string|Zend_Locale $locale OPTIONAL Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function addIso($date, $locale = null) @@ -3118,7 +3132,7 @@ class Zend_Date extends Zend_Date_DateObject * * @param string|integer|Zend_Date $date ISO Date to sub * @param string|Zend_Locale $locale OPTIONAL Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function subIso($date, $locale = null) @@ -3171,7 +3185,7 @@ class Zend_Date extends Zend_Date_DateObject * * @param string|integer|Zend_Date $date RFC 822 to set * @param string|Zend_Locale $locale OPTIONAL Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function setArpa($date, $locale = null) @@ -3189,7 +3203,7 @@ class Zend_Date extends Zend_Date_DateObject * * @param string|integer|Zend_Date $date RFC 822 Date to add * @param string|Zend_Locale $locale OPTIONAL Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function addArpa($date, $locale = null) @@ -3207,7 +3221,7 @@ class Zend_Date extends Zend_Date_DateObject * * @param string|integer|Zend_Date $date RFC 822 Date to sub * @param string|Zend_Locale $locale OPTIONAL Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function subArpa($date, $locale = null) @@ -3233,12 +3247,12 @@ class Zend_Date extends Zend_Date_DateObject return $this->_calcvalue('cmp', $date, 'arpa', self::RFC_822, $locale); } - /** * Check if location is supported * - * @param $location array - locations array - * @return $horizon float + * @param array $location locations array + * @throws Zend_Date_Exception + * @return float $horizon float */ private function _checkLocation($location) { @@ -3280,7 +3294,7 @@ class Zend_Date extends Zend_Date_DateObject * Returns the time of sunrise for this date and a given location as new date object * For a list of cities and correct locations use the class Zend_Date_Cities * - * @param $location array - location of sunrise + * @param array $location location of sunrise * ['horizon'] -> civil, nautic, astronomical, effective (default) * ['longitude'] -> longitude of location * ['latitude'] -> latitude of location @@ -3300,7 +3314,7 @@ class Zend_Date extends Zend_Date_DateObject * Returns the time of sunset for this date and a given location as new date object * For a list of cities and correct locations use the class Zend_Date_Cities * - * @param $location array - location of sunset + * @param array $location location of sunset * ['horizon'] -> civil, nautic, astronomical, effective (default) * ['longitude'] -> longitude of location * ['latitude'] -> latitude of location @@ -3320,7 +3334,7 @@ class Zend_Date extends Zend_Date_DateObject * Returns an array with the sunset and sunrise dates for all horizon types * For a list of cities and correct locations use the class Zend_Date_Cities * - * @param $location array - location of suninfo + * @param array $location location of suninfo * ['horizon'] -> civil, nautic, astronomical, effective (default) * ['longitude'] -> longitude of location * ['latitude'] -> latitude of location @@ -3356,11 +3370,11 @@ class Zend_Date extends Zend_Date_DateObject return $suninfo; } - /** * Check a given year for leap year. * - * @param integer|array|Zend_Date $year Year to check + * @param integer|array|Zend_Date $year Year to check + * @throws Zend_Date_Exception * @return boolean */ public static function checkLeapYear($year) @@ -3456,7 +3470,7 @@ class Zend_Date extends Zend_Date_DateObject * * @param string $calc Calculation to make * @param string|integer|array|Zend_Date $date Date or Part to calculate - * @param string $part Datepart for Calculation + * @param string $type Datepart for Calculation * @param string|Zend_Locale $locale Locale for parsing input * @return integer|string new date * @throws Zend_Date_Exception @@ -3494,11 +3508,13 @@ class Zend_Date extends Zend_Date_DateObject /** * Internal calculation, returns the requested date type * - * @param string $calc Calculation to make - * @param string|integer|Zend_Date $value Datevalue to calculate with, if null the actual value is taken - * @param string|Zend_Locale $locale Locale for parsing input - * @return integer|Zend_Date new date + * @param string $calc Calculation to make + * @param string|integer|Zend_Date $value Datevalue to calculate with, if null the actual value is taken + * @param string $type + * @param string $parameter + * @param string|Zend_Locale $locale Locale for parsing input * @throws Zend_Date_Exception + * @return integer|Zend_Date new date */ private function _calcvalue($calc, $value, $type, $parameter, $locale) { @@ -3554,9 +3570,9 @@ class Zend_Date extends Zend_Date_DateObject * use set() instead. * Returned is the new date object * - * @param string|integer|array|Zend_Date $date Year to set + * @param string|integer|array|Zend_Date $year Year to set * @param string|Zend_Locale $locale OPTIONAL Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function setYear($year, $locale = null) @@ -3573,9 +3589,9 @@ class Zend_Date extends Zend_Date_DateObject * use add() instead. * Returned is the new date object * - * @param string|integer|array|Zend_Date $date Year to add + * @param string|integer|array|Zend_Date $year Year to add * @param string|Zend_Locale $locale OPTIONAL Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function addYear($year, $locale = null) @@ -3592,9 +3608,9 @@ class Zend_Date extends Zend_Date_DateObject * use sub() instead. * Returned is the new date object * - * @param string|integer|array|Zend_Date $date Year to sub + * @param string|integer|array|Zend_Date $year Year to sub * @param string|Zend_Locale $locale OPTIONAL Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function subYear($year, $locale = null) @@ -3718,7 +3734,7 @@ class Zend_Date extends Zend_Date_DateObject * * @param string|integer|array|Zend_Date $month Month to set * @param string|Zend_Locale $locale OPTIONAL Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function setMonth($month, $locale = null) @@ -3737,7 +3753,7 @@ class Zend_Date extends Zend_Date_DateObject * * @param string|integer|array|Zend_Date $month Month to add * @param string|Zend_Locale $locale OPTIONAL Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function addMonth($month, $locale = null) @@ -3756,7 +3772,7 @@ class Zend_Date extends Zend_Date_DateObject * * @param string|integer|array|Zend_Date $month Month to sub * @param string|Zend_Locale $locale OPTIONAL Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function subMonth($month, $locale = null) @@ -3785,7 +3801,7 @@ class Zend_Date extends Zend_Date_DateObject * Returns the day as new date object * Example: 20.May.1986 -> 20.Jan.1970 00:00:00 * - * @param $locale string|Zend_Locale OPTIONAL Locale for parsing input + * @param Zend_Locale $locale OPTIONAL Locale for parsing input * @return Zend_Date */ public function getDay($locale = null) @@ -3793,13 +3809,13 @@ class Zend_Date extends Zend_Date_DateObject return $this->copyPart(self::DAY_SHORT, $locale); } - /** * Returns the calculated day * - * @param $calc string Type of calculation to make - * @param $day string|integer|Zend_Date Day to calculate, when null the actual day is calculated - * @param $locale string|Zend_Locale Locale for parsing input + * @param string $calc Type of calculation to make + * @param Zend_Date $day Day to calculate, when null the actual day is calculated + * @param Zend_Locale $locale Locale for parsing input + * @throws Zend_Date_Exception * @return Zend_Date|integer */ private function _day($calc, $day, $locale) @@ -3860,9 +3876,9 @@ class Zend_Date extends Zend_Date_DateObject * Returned is the new date object * Example: setDay('Montag', 'de_AT'); will set the monday of this week as day. * - * @param string|integer|array|Zend_Date $month Day to set + * @param string|integer|array|Zend_Date $day Day to set * @param string|Zend_Locale $locale OPTIONAL Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function setDay($day, $locale = null) @@ -3878,9 +3894,9 @@ class Zend_Date extends Zend_Date_DateObject * If a localized dayname is given it will be parsed with the default locale or the optional * set locale. * - * @param string|integer|array|Zend_Date $month Day to add + * @param string|integer|array|Zend_Date $day Day to add * @param string|Zend_Locale $locale OPTIONAL Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function addDay($day, $locale = null) @@ -3896,9 +3912,9 @@ class Zend_Date extends Zend_Date_DateObject * If a localized dayname is given it will be parsed with the default locale or the optional * set locale. * - * @param string|integer|array|Zend_Date $month Day to sub + * @param string|integer|array|Zend_Date $day Day to sub * @param string|Zend_Locale $locale OPTIONAL Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function subDay($day, $locale = null) @@ -3928,7 +3944,7 @@ class Zend_Date extends Zend_Date_DateObject * Weekday is always from 1-7 * Example: 09-Jan-2007 -> 2 = Tuesday -> 02-Jan-1970 (when 02.01.1970 is also Tuesday) * - * @param $locale string|Zend_Locale OPTIONAL Locale for parsing input + * @param Zend_Locale $locale OPTIONAL Locale for parsing input * @return Zend_Date */ public function getWeekday($locale = null) @@ -3946,9 +3962,9 @@ class Zend_Date extends Zend_Date_DateObject /** * Returns the calculated weekday * - * @param $calc string Type of calculation to make - * @param $weekday string|integer|array|Zend_Date Weekday to calculate, when null the actual weekday is calculated - * @param $locale string|Zend_Locale Locale for parsing input + * @param string $calc Type of calculation to make + * @param Zend_Date $weekday Weekday to calculate, when null the actual weekday is calculated + * @param Zend_Locale $locale Locale for parsing input * @return Zend_Date|integer * @throws Zend_Date_Exception */ @@ -4008,9 +4024,9 @@ class Zend_Date extends Zend_Date_DateObject * Returned is the new date object. * Example: setWeekday(3); will set the wednesday of this week as day. * - * @param string|integer|array|Zend_Date $month Weekday to set + * @param string|integer|array|Zend_Date $weekday Weekday to set * @param string|Zend_Locale $locale OPTIONAL Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function setWeekday($weekday, $locale = null) @@ -4028,9 +4044,9 @@ class Zend_Date extends Zend_Date_DateObject * Example: addWeekday(3); will add the difference of days from the begining of the month until * wednesday. * - * @param string|integer|array|Zend_Date $month Weekday to add + * @param string|integer|array|Zend_Date $weekday Weekday to add * @param string|Zend_Locale $locale OPTIONAL Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function addWeekday($weekday, $locale = null) @@ -4048,9 +4064,9 @@ class Zend_Date extends Zend_Date_DateObject * Example: subWeekday(3); will subtract the difference of days from the begining of the month until * wednesday. * - * @param string|integer|array|Zend_Date $month Weekday to sub + * @param string|integer|array|Zend_Date $weekday Weekday to sub * @param string|Zend_Locale $locale OPTIONAL Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function subWeekday($weekday, $locale = null) @@ -4102,7 +4118,7 @@ class Zend_Date extends Zend_Date_DateObject * * @param string|integer|array|Zend_Date $day Day of Year to set * @param string|Zend_Locale $locale OPTIONAL Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function setDayOfYear($day, $locale = null) @@ -4119,7 +4135,7 @@ class Zend_Date extends Zend_Date_DateObject * * @param string|integer|array|Zend_Date $day Day of Year to add * @param string|Zend_Locale $locale OPTIONAL Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function addDayOfYear($day, $locale = null) @@ -4136,7 +4152,7 @@ class Zend_Date extends Zend_Date_DateObject * * @param string|integer|array|Zend_Date $day Day of Year to sub * @param string|Zend_Locale $locale OPTIONAL Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function subDayOfYear($day, $locale = null) @@ -4165,7 +4181,7 @@ class Zend_Date extends Zend_Date_DateObject * Returns the hour as new date object * Example: 02.Feb.1986 10:30:25 -> 01.Jan.1970 10:00:00 * - * @param $locale string|Zend_Locale OPTIONAL Locale for parsing input + * @param Zend_Locale $locale OPTIONAL Locale for parsing input * @return Zend_Date */ public function getHour($locale = null) @@ -4182,7 +4198,7 @@ class Zend_Date extends Zend_Date_DateObject * * @param string|integer|array|Zend_Date $hour Hour to set * @param string|Zend_Locale $locale OPTIONAL Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function setHour($hour, $locale = null) @@ -4199,7 +4215,7 @@ class Zend_Date extends Zend_Date_DateObject * * @param string|integer|array|Zend_Date $hour Hour to add * @param string|Zend_Locale $locale OPTIONAL Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function addHour($hour, $locale = null) @@ -4216,7 +4232,7 @@ class Zend_Date extends Zend_Date_DateObject * * @param string|integer|array|Zend_Date $hour Hour to sub * @param string|Zend_Locale $locale OPTIONAL Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function subHour($hour, $locale = null) @@ -4268,7 +4284,7 @@ class Zend_Date extends Zend_Date_DateObject * * @param string|integer|array|Zend_Date $minute Minute to set * @param string|Zend_Locale $locale OPTIONAL Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function setMinute($minute, $locale = null) @@ -4285,7 +4301,7 @@ class Zend_Date extends Zend_Date_DateObject * * @param string|integer|array|Zend_Date $minute Minute to add * @param string|Zend_Locale $locale OPTIONAL Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function addMinute($minute, $locale = null) @@ -4302,7 +4318,7 @@ class Zend_Date extends Zend_Date_DateObject * * @param string|integer|array|Zend_Date $minute Minute to sub * @param string|Zend_Locale $locale OPTIONAL Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function subMinute($minute, $locale = null) @@ -4354,7 +4370,7 @@ class Zend_Date extends Zend_Date_DateObject * * @param string|integer|array|Zend_Date $second Second to set * @param string|Zend_Locale $locale (Optional) Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function setSecond($second, $locale = null) @@ -4371,7 +4387,7 @@ class Zend_Date extends Zend_Date_DateObject * * @param string|integer|array|Zend_Date $second Second to add * @param string|Zend_Locale $locale (Optional) Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function addSecond($second, $locale = null) @@ -4388,7 +4404,7 @@ class Zend_Date extends Zend_Date_DateObject * * @param string|integer|array|Zend_Date $second Second to sub * @param string|Zend_Locale $locale (Optional) Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function subSecond($second, $locale = null) @@ -4429,7 +4445,7 @@ class Zend_Date extends Zend_Date_DateObject * * @param integer $precision Precision for the fractional datepart 3 = milliseconds * @throws Zend_Date_Exception - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface */ public function setFractionalPrecision($precision) { @@ -4459,14 +4475,14 @@ class Zend_Date extends Zend_Date_DateObject return $this->_fractional; } - /** * Sets new milliseconds for the date object * Example: setMilliSecond(550, 2) -> equals +5 Sec +50 MilliSec * * @param integer|Zend_Date $milli (Optional) Millisecond to set, when null the actual millisecond is set * @param integer $precision (Optional) Fraction precision of the given milliseconds - * @return Zend_Date Provides fluid interface + * @throws Zend_Date_Exception + * @return Zend_Date Provides a fluent interface */ public function setMilliSecond($milli = null, $precision = null) { @@ -4493,13 +4509,13 @@ class Zend_Date extends Zend_Date_DateObject return $this; } - /** * Adds milliseconds to the date object * * @param integer|Zend_Date $milli (Optional) Millisecond to add, when null the actual millisecond is added * @param integer $precision (Optional) Fractional precision for the given milliseconds - * @return Zend_Date Provides fluid interface + * @throws Zend_Date_Exception + * @return Zend_Date Provides a fluent interface */ public function addMilliSecond($milli = null, $precision = null) { @@ -4512,15 +4528,24 @@ class Zend_Date extends Zend_Date_DateObject } if ($precision === null) { - $precision = strlen($milli); - if ($milli < 0) { - --$precision; - } + // Use internal default precision + // Is not as logic as using the length of the input. But this would break tests and maybe other things + // as an input value of integer 10, which is used in tests, must be parsed as 10 milliseconds (real milliseconds, precision 3) + // but with auto-detect of precision, 100 milliseconds would be added. + $precision = $this->_precision; } if (!is_int($precision) || $precision < 1 || $precision > 9) { require_once 'Zend/Date/Exception.php'; - throw new Zend_Date_Exception("precision ($precision) must be a positive integer less than 10", 0, null, $precision); + throw new Zend_Date_Exception( + "precision ($precision) must be a positive integer less than 10", 0, null, $precision + ); + } + + if ($this->_precision > $precision) { + $milli = $milli * pow(10, $this->_precision - $precision); + } elseif ($this->_precision < $precision) { + $milli = round($milli / pow(10, $precision - $this->_precision)); } $this->_fractional += $milli; @@ -4555,7 +4580,7 @@ class Zend_Date extends Zend_Date_DateObject * * @param integer|Zend_Date $milli (Optional) Millisecond to sub, when null the actual millisecond is subtracted * @param integer $precision (Optional) Fractional precision for the given milliseconds - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface */ public function subMilliSecond($milli = null, $precision = null) { @@ -4616,7 +4641,7 @@ class Zend_Date extends Zend_Date_DateObject * Returns the week as new date object using monday as begining of the week * Example: 12.Jan.2007 -> 08.Jan.1970 00:00:00 * - * @param $locale string|Zend_Locale OPTIONAL Locale for parsing input + * @param Zend_Locale $locale OPTIONAL Locale for parsing input * @return Zend_Date */ public function getWeek($locale = null) @@ -4637,7 +4662,7 @@ class Zend_Date extends Zend_Date_DateObject * * @param string|integer|array|Zend_Date $week Week to set * @param string|Zend_Locale $locale OPTIONAL Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function setWeek($week, $locale = null) @@ -4652,7 +4677,7 @@ class Zend_Date extends Zend_Date_DateObject * * @param string|integer|array|Zend_Date $week Week to add * @param string|Zend_Locale $locale OPTIONAL Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function addWeek($week, $locale = null) @@ -4667,7 +4692,7 @@ class Zend_Date extends Zend_Date_DateObject * * @param string|integer|array|Zend_Date $week Week to sub * @param string|Zend_Locale $locale OPTIONAL Locale for parsing input - * @return Zend_Date Provides fluid interface + * @return Zend_Date Provides a fluent interface * @throws Zend_Date_Exception */ public function subWeek($week, $locale = null) diff --git a/lib/zend/Zend/Date/Cities.php b/lib/zend/Zend/Date/Cities.php index 70bc0592dc0..6934d690e05 100644 --- a/lib/zend/Zend/Date/Cities.php +++ b/lib/zend/Zend/Date/Cities.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Date - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -28,7 +28,7 @@ * @category Zend * @package Zend_Date * @subpackage Zend_Date_Cities - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Date_Cities diff --git a/lib/zend/Zend/Date/DateObject.php b/lib/zend/Zend/Date/DateObject.php index 5435eb4a506..0ec9fce9fc2 100644 --- a/lib/zend/Zend/Date/DateObject.php +++ b/lib/zend/Zend/Date/DateObject.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Date - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @version $Id$ * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -23,7 +23,7 @@ * @category Zend * @package Zend_Date * @subpackage Zend_Date_DateObject - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ abstract class Zend_Date_DateObject { @@ -33,6 +33,7 @@ abstract class Zend_Date_DateObject { */ private $_unixTimestamp; protected static $_cache = null; + protected static $_cacheTags = false; protected static $_defaultOffset = 0; /** @@ -254,7 +255,11 @@ abstract class Zend_Date_DateObject { } if (isset(self::$_cache)) { - self::$_cache->save( serialize($date), $id); + if (self::$_cacheTags) { + self::$_cache->save( serialize($date), $id, array('Zend_Date')); + } else { + self::$_cache->save( serialize($date), $id); + } } return $date; @@ -307,6 +312,13 @@ abstract class Zend_Date_DateObject { } if (abs($timestamp) <= 0x7FFFFFFF) { + // See ZF-11992 + // "o" will sometimes resolve to the previous year (see + // http://php.net/date ; it's part of the ISO 8601 + // standard). However, this is not desired, so replacing + // all occurrences of "o" not preceded by a backslash + // with "Y" + $format = preg_replace('/(?save( serialize($timestamp), $idstamp); + if (self::$_cacheTags) { + self::$_cache->save( serialize($timestamp), $idstamp, array('Zend_Date')); + } else { + self::$_cache->save( serialize($timestamp), $idstamp); + } } } @@ -828,7 +844,11 @@ abstract class Zend_Date_DateObject { } if (isset(self::$_cache)) { - self::$_cache->save( serialize($array), $id); + if (self::$_cacheTags) { + self::$_cache->save( serialize($array), $id, array('Zend_Date')); + } else { + self::$_cache->save( serialize($array), $id); + } } return $array; @@ -1055,4 +1075,22 @@ abstract class Zend_Date_DateObject { return $offset; } + + /** + * Internal method to check if the given cache supports tags + * + * @param Zend_Cache $cache + */ + protected static function _getTagSupportForCache() + { + $backend = self::$_cache->getBackend(); + if ($backend instanceof Zend_Cache_Backend_ExtendedInterface) { + $cacheOptions = $backend->getCapabilities(); + self::$_cacheTags = $cacheOptions['tags']; + } else { + self::$_cacheTags = false; + } + + return self::$_cacheTags; + } } diff --git a/lib/zend/Zend/Date/Exception.php b/lib/zend/Zend/Date/Exception.php index bcbfd20be52..f4573b38ce5 100644 --- a/lib/zend/Zend/Date/Exception.php +++ b/lib/zend/Zend/Date/Exception.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Date - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @version $Id$ * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -29,7 +29,7 @@ require_once 'Zend/Exception.php'; /** * @category Zend * @package Zend_Date - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Date_Exception extends Zend_Exception diff --git a/lib/zend/Zend/Exception.php b/lib/zend/Zend/Exception.php index bbfb792e936..d97acb0f92c 100644 --- a/lib/zend/Zend/Exception.php +++ b/lib/zend/Zend/Exception.php @@ -14,14 +14,15 @@ * * @category Zend * @package Zend - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License + * @version $Id$ */ /** * @category Zend * @package Zend -* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) +* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Exception extends Exception @@ -53,9 +54,9 @@ class Zend_Exception extends Exception * Overloading * * For PHP < 5.3.0, provides access to the getPrevious() method. - * - * @param string $method - * @param array $args + * + * @param string $method + * @param array $args * @return mixed */ public function __call($method, array $args) @@ -75,8 +76,8 @@ class Zend_Exception extends Exception { if (version_compare(PHP_VERSION, '5.3.0', '<')) { if (null !== ($e = $this->getPrevious())) { - return $e->__toString() - . "\n\nNext " + return $e->__toString() + . "\n\nNext " . parent::__toString(); } } diff --git a/lib/zend/Zend/Filter.php b/lib/zend/Zend/Filter.php new file mode 100644 index 00000000000..1256ff9bd6b --- /dev/null +++ b/lib/zend/Zend/Filter.php @@ -0,0 +1,239 @@ +_filters, $filter); + } else { + $this->_filters[] = $filter; + } + return $this; + } + + /** + * Add a filter to the end of the chain + * + * @param Zend_Filter_Interface $filter + * @return Zend_Filter Provides a fluent interface + */ + public function appendFilter(Zend_Filter_Interface $filter) + { + return $this->addFilter($filter, self::CHAIN_APPEND); + } + + /** + * Add a filter to the start of the chain + * + * @param Zend_Filter_Interface $filter + * @return Zend_Filter Provides a fluent interface + */ + public function prependFilter(Zend_Filter_Interface $filter) + { + return $this->addFilter($filter, self::CHAIN_PREPEND); + } + + /** + * Get all the filters + * + * @return array + */ + public function getFilters() + { + return $this->_filters; + } + + /** + * Returns $value filtered through each filter in the chain + * + * Filters are run in the order in which they were added to the chain (FIFO) + * + * @param mixed $value + * @return mixed + */ + public function filter($value) + { + $valueFiltered = $value; + foreach ($this->_filters as $filter) { + $valueFiltered = $filter->filter($valueFiltered); + } + return $valueFiltered; + } + + /** + * Returns the set default namespaces + * + * @return array + */ + public static function getDefaultNamespaces() + { + return self::$_defaultNamespaces; + } + + /** + * Sets new default namespaces + * + * @param array|string $namespace + * @return null + */ + public static function setDefaultNamespaces($namespace) + { + if (!is_array($namespace)) { + $namespace = array((string) $namespace); + } + + self::$_defaultNamespaces = $namespace; + } + + /** + * Adds a new default namespace + * + * @param array|string $namespace + * @return null + */ + public static function addDefaultNamespaces($namespace) + { + if (!is_array($namespace)) { + $namespace = array((string) $namespace); + } + + self::$_defaultNamespaces = array_unique(array_merge(self::$_defaultNamespaces, $namespace)); + } + + /** + * Returns true when defaultNamespaces are set + * + * @return boolean + */ + public static function hasDefaultNamespaces() + { + return (!empty(self::$_defaultNamespaces)); + } + + /** + * @deprecated + * @see Zend_Filter::filterStatic() + * + * @param mixed $value + * @param string $classBaseName + * @param array $args OPTIONAL + * @param array|string $namespaces OPTIONAL + * @return mixed + * @throws Zend_Filter_Exception + */ + public static function get($value, $classBaseName, array $args = array(), $namespaces = array()) + { + trigger_error( + 'Zend_Filter::get() is deprecated as of 1.9.0; please update your code to utilize Zend_Filter::filterStatic()', + E_USER_NOTICE + ); + + return self::filterStatic($value, $classBaseName, $args, $namespaces); + } + + /** + * Returns a value filtered through a specified filter class, without requiring separate + * instantiation of the filter object. + * + * The first argument of this method is a data input value, that you would have filtered. + * The second argument is a string, which corresponds to the basename of the filter class, + * relative to the Zend_Filter namespace. This method automatically loads the class, + * creates an instance, and applies the filter() method to the data input. You can also pass + * an array of constructor arguments, if they are needed for the filter class. + * + * @param mixed $value + * @param string $classBaseName + * @param array $args OPTIONAL + * @param array|string $namespaces OPTIONAL + * @return mixed + * @throws Zend_Filter_Exception + */ + public static function filterStatic($value, $classBaseName, array $args = array(), $namespaces = array()) + { + require_once 'Zend/Loader.php'; + $namespaces = array_merge((array) $namespaces, self::$_defaultNamespaces, array('Zend_Filter')); + foreach ($namespaces as $namespace) { + $className = $namespace . '_' . ucfirst($classBaseName); + if (!class_exists($className, false)) { + try { + $file = str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php'; + if (Zend_Loader::isReadable($file)) { + Zend_Loader::loadClass($className); + } else { + continue; + } + } catch (Zend_Exception $ze) { + continue; + } + } + + $class = new ReflectionClass($className); + if ($class->implementsInterface('Zend_Filter_Interface')) { + if ($class->hasMethod('__construct')) { + $object = $class->newInstanceArgs($args); + } else { + $object = $class->newInstance(); + } + return $object->filter($value); + } + } + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("Filter class not found from basename '$classBaseName'"); + } +} diff --git a/lib/zend/Zend/Filter/Alnum.php b/lib/zend/Zend/Filter/Alnum.php new file mode 100644 index 00000000000..7455dafe45c --- /dev/null +++ b/lib/zend/Zend/Filter/Alnum.php @@ -0,0 +1,146 @@ +toArray(); + } else if (is_array($allowWhiteSpace)) { + if (array_key_exists('allowwhitespace', $allowWhiteSpace)) { + $allowWhiteSpace = $allowWhiteSpace['allowwhitespace']; + } else { + $allowWhiteSpace = false; + } + } + + $this->allowWhiteSpace = (boolean) $allowWhiteSpace; + if (null === self::$_unicodeEnabled) { + self::$_unicodeEnabled = (@preg_match('/\pL/u', 'a')) ? true : false; + } + + if (null === self::$_meansEnglishAlphabet) { + $this->_locale = new Zend_Locale('auto'); + self::$_meansEnglishAlphabet = in_array($this->_locale->getLanguage(), + array('ja', 'ko', 'zh') + ); + } + + } + + /** + * Returns the allowWhiteSpace option + * + * @return boolean + */ + public function getAllowWhiteSpace() + { + return $this->allowWhiteSpace; + } + + /** + * Sets the allowWhiteSpace option + * + * @param boolean $allowWhiteSpace + * @return Zend_Filter_Alnum Provides a fluent interface + */ + public function setAllowWhiteSpace($allowWhiteSpace) + { + $this->allowWhiteSpace = (boolean) $allowWhiteSpace; + return $this; + } + + /** + * Defined by Zend_Filter_Interface + * + * Returns the string $value, removing all but alphabetic and digit characters + * + * @param string $value + * @return string + */ + public function filter($value) + { + $whiteSpace = $this->allowWhiteSpace ? '\s' : ''; + if (!self::$_unicodeEnabled) { + // POSIX named classes are not supported, use alternative a-zA-Z0-9 match + $pattern = '/[^a-zA-Z0-9' . $whiteSpace . ']/'; + } else if (self::$_meansEnglishAlphabet) { + //The Alphabet means english alphabet. + $pattern = '/[^a-zA-Z0-9' . $whiteSpace . ']/u'; + } else { + //The Alphabet means each language's alphabet. + $pattern = '/[^\p{L}\p{N}' . $whiteSpace . ']/u'; + } + + return preg_replace($pattern, '', (string) $value); + } +} diff --git a/lib/zend/Zend/Filter/Alpha.php b/lib/zend/Zend/Filter/Alpha.php new file mode 100644 index 00000000000..7374da1665e --- /dev/null +++ b/lib/zend/Zend/Filter/Alpha.php @@ -0,0 +1,146 @@ +toArray(); + } else if (is_array($allowWhiteSpace)) { + if (array_key_exists('allowwhitespace', $allowWhiteSpace)) { + $allowWhiteSpace = $allowWhiteSpace['allowwhitespace']; + } else { + $allowWhiteSpace = false; + } + } + + $this->allowWhiteSpace = (boolean) $allowWhiteSpace; + if (null === self::$_unicodeEnabled) { + self::$_unicodeEnabled = (@preg_match('/\pL/u', 'a')) ? true : false; + } + + if (null === self::$_meansEnglishAlphabet) { + $this->_locale = new Zend_Locale('auto'); + self::$_meansEnglishAlphabet = in_array($this->_locale->getLanguage(), + array('ja', 'ko', 'zh') + ); + } + + } + + /** + * Returns the allowWhiteSpace option + * + * @return boolean + */ + public function getAllowWhiteSpace() + { + return $this->allowWhiteSpace; + } + + /** + * Sets the allowWhiteSpace option + * + * @param boolean $allowWhiteSpace + * @return Zend_Filter_Alpha Provides a fluent interface + */ + public function setAllowWhiteSpace($allowWhiteSpace) + { + $this->allowWhiteSpace = (boolean) $allowWhiteSpace; + return $this; + } + + /** + * Defined by Zend_Filter_Interface + * + * Returns the string $value, removing all but alphabetic characters + * + * @param string $value + * @return string + */ + public function filter($value) + { + $whiteSpace = $this->allowWhiteSpace ? '\s' : ''; + if (!self::$_unicodeEnabled) { + // POSIX named classes are not supported, use alternative a-zA-Z match + $pattern = '/[^a-zA-Z' . $whiteSpace . ']/'; + } else if (self::$_meansEnglishAlphabet) { + //The Alphabet means english alphabet. + $pattern = '/[^a-zA-Z' . $whiteSpace . ']/u'; + } else { + //The Alphabet means each language's alphabet. + $pattern = '/[^\p{L}' . $whiteSpace . ']/u'; + } + + return preg_replace($pattern, '', (string) $value); + } +} diff --git a/lib/zend/Zend/Service/DeveloperGarden/Request/VoiceButler/VoiceButlerAbstract.php b/lib/zend/Zend/Filter/BaseName.php similarity index 57% rename from lib/zend/Zend/Service/DeveloperGarden/Request/VoiceButler/VoiceButlerAbstract.php rename to lib/zend/Zend/Filter/BaseName.php index c907f4c96d6..8d6a6da5607 100644 --- a/lib/zend/Zend/Service/DeveloperGarden/Request/VoiceButler/VoiceButlerAbstract.php +++ b/lib/zend/Zend/Filter/BaseName.php @@ -1,4 +1,5 @@ 'boolean', + self::INTEGER => 'integer', + self::FLOAT => 'float', + self::STRING => 'string', + self::ZERO => 'zero', + self::EMPTY_ARRAY => 'array', + self::NULL => 'null', + self::PHP => 'php', + self::FALSE_STRING => 'false', + self::YES => 'yes', + self::ALL => 'all', + ); + + /** + * Internal type to detect + * + * @var integer + */ + protected $_type = self::PHP; + + /** + * Internal locale + * + * @var array + */ + protected $_locale = array('auto'); + + /** + * Internal mode + * + * @var boolean + */ + protected $_casting = true; + + /** + * Constructor + * + * @param string|array|Zend_Config $options OPTIONAL + */ + public function __construct($options = null) + { + if ($options instanceof Zend_Config) { + $options = $options->toArray(); + } elseif (!is_array($options)) { + $options = func_get_args(); + $temp = array(); + if (!empty($options)) { + $temp['type'] = array_shift($options); + } + + if (!empty($options)) { + $temp['casting'] = array_shift($options); + } + + if (!empty($options)) { + $temp['locale'] = array_shift($options); + } + + $options = $temp; + } + + if (array_key_exists('type', $options)) { + $this->setType($options['type']); + } + + if (array_key_exists('casting', $options)) { + $this->setCasting($options['casting']); + } + + if (array_key_exists('locale', $options)) { + $this->setLocale($options['locale']); + } + } + + /** + * Returns the set null types + * + * @return int + */ + public function getType() + { + return $this->_type; + } + + /** + * Set the null types + * + * @param integer|array $type + * @throws Zend_Filter_Exception + * @return Zend_Filter_Boolean + */ + public function setType($type = null) + { + if (is_array($type)) { + $detected = 0; + foreach($type as $value) { + if (is_int($value)) { + $detected += $value; + } elseif (in_array($value, $this->_constants)) { + $detected += array_search($value, $this->_constants); + } + } + + $type = $detected; + } elseif (is_string($type) && in_array($type, $this->_constants)) { + $type = array_search($type, $this->_constants); + } + + if (!is_int($type) || ($type < 0) || ($type > self::ALL)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('Unknown type'); + } + + $this->_type = $type; + return $this; + } + + /** + * Returns the set locale + * + * @return array + */ + public function getLocale() + { + return $this->_locale; + } + + /** + * Set the locales which are accepted + * + * @param string|array|Zend_Locale $locale + * @throws Zend_Filter_Exception + * @return Zend_Filter_Boolean + */ + public function setLocale($locale = null) + { + if (is_string($locale)) { + $locale = array($locale); + } elseif ($locale instanceof Zend_Locale) { + $locale = array($locale->toString()); + } elseif (!is_array($locale)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('Locale has to be string, array or an instance of Zend_Locale'); + } + + require_once 'Zend/Locale.php'; + foreach ($locale as $single) { + if (!Zend_Locale::isLocale($single)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("Unknown locale '$single'"); + } + } + + $this->_locale = $locale; + return $this; + } + + /** + * Returns the casting option + * + * @return boolean + */ + public function getCasting() + { + return $this->_casting; + } + + /** + * Set the working mode + * + * @param boolean $locale When true this filter works like cast + * When false it recognises only true and false + * and all other values are returned as is + * @throws Zend_Filter_Exception + * @return Zend_Filter_Boolean + */ + public function setCasting($casting = true) + { + $this->_casting = (boolean) $casting; + return $this; + } + + /** + * Defined by Zend_Filter_Interface + * + * Returns a boolean representation of $value + * + * @param string $value + * @return string + */ + public function filter($value) + { + $type = $this->getType(); + $casting = $this->getCasting(); + + // STRING YES (Localized) + if ($type >= self::YES) { + $type -= self::YES; + if (is_string($value)) { + require_once 'Zend/Locale.php'; + $locales = $this->getLocale(); + foreach ($locales as $locale) { + if ($this->_getLocalizedQuestion($value, false, $locale) === false) { + return false; + } + + if (!$casting && ($this->_getLocalizedQuestion($value, true, $locale) === true)) { + return true; + } + } + } + } + + // STRING FALSE ('false') + if ($type >= self::FALSE_STRING) { + $type -= self::FALSE_STRING; + if (is_string($value) && (strtolower($value) == 'false')) { + return false; + } + + if ((!$casting) && is_string($value) && (strtolower($value) == 'true')) { + return true; + } + } + + // NULL (null) + if ($type >= self::NULL) { + $type -= self::NULL; + if ($value === null) { + return false; + } + } + + // EMPTY_ARRAY (array()) + if ($type >= self::EMPTY_ARRAY) { + $type -= self::EMPTY_ARRAY; + if (is_array($value) && ($value == array())) { + return false; + } + } + + // ZERO ('0') + if ($type >= self::ZERO) { + $type -= self::ZERO; + if (is_string($value) && ($value == '0')) { + return false; + } + + if ((!$casting) && (is_string($value)) && ($value == '1')) { + return true; + } + } + + // STRING ('') + if ($type >= self::STRING) { + $type -= self::STRING; + if (is_string($value) && ($value == '')) { + return false; + } + } + + // FLOAT (0.0) + if ($type >= self::FLOAT) { + $type -= self::FLOAT; + if (is_float($value) && ($value == 0.0)) { + return false; + } + + if ((!$casting) && is_float($value) && ($value == 1.0)) { + return true; + } + } + + // INTEGER (0) + if ($type >= self::INTEGER) { + $type -= self::INTEGER; + if (is_int($value) && ($value == 0)) { + return false; + } + + if ((!$casting) && is_int($value) && ($value == 1)) { + return true; + } + } + + // BOOLEAN (false) + if ($type >= self::BOOLEAN) { + $type -= self::BOOLEAN; + if (is_bool($value)) { + return $value; + } + } + + if ($casting) { + return true; + } + + return $value; + } + + /** + * Determine the value of a localized string, and compare it to a given value + * + * @param string $value + * @param boolean $yes + * @param array $locale + * @return boolean + */ + protected function _getLocalizedQuestion($value, $yes, $locale) + { + if ($yes == true) { + $question = 'yes'; + $return = true; + } else { + $question = 'no'; + $return = false; + } + $str = Zend_Locale::getTranslation($question, 'question', $locale); + $str = explode(':', $str); + if (!empty($str)) { + foreach($str as $no) { + if (($no == $value) || (strtolower($no) == strtolower($value))) { + return $return; + } + } + } + } +} diff --git a/lib/zend/Zend/Filter/Callback.php b/lib/zend/Zend/Filter/Callback.php new file mode 100644 index 00000000000..f7961ea5110 --- /dev/null +++ b/lib/zend/Zend/Filter/Callback.php @@ -0,0 +1,152 @@ +toArray(); + } else if (!is_array($options) || !array_key_exists('callback', $options)) { + $options = func_get_args(); + $temp['callback'] = array_shift($options); + if (!empty($options)) { + $temp['options'] = array_shift($options); + } + + $options = $temp; + } + + if (!array_key_exists('callback', $options)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('Missing callback to use'); + } + + $this->setCallback($options['callback']); + if (array_key_exists('options', $options)) { + $this->setOptions($options['options']); + } + } + + /** + * Returns the set callback + * + * @return string|array Set callback + */ + public function getCallback() + { + return $this->_callback; + } + + /** + * Sets a new callback for this filter + * + * @param unknown_type $callback + * @return unknown + */ + public function setCallback($callback, $options = null) + { + if (!is_callable($callback)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('Callback can not be accessed'); + } + + $this->_callback = $callback; + $this->setOptions($options); + return $this; + } + + /** + * Returns the set default options + * + * @return mixed + */ + public function getOptions() + { + return $this->_options; + } + + /** + * Sets new default options to the callback filter + * + * @param mixed $options Default options to set + * @return Zend_Filter_Callback + */ + public function setOptions($options) + { + $this->_options = $options; + return $this; + } + + /** + * Calls the filter per callback + * + * @param mixed $value Options for the set callback + * @return mixed Result from the filter which was callbacked + */ + public function filter($value) + { + $options = array(); + + if ($this->_options !== null) { + if (!is_array($this->_options)) { + $options = array($this->_options); + } else { + $options = $this->_options; + } + } + + array_unshift($options, $value); + + return call_user_func_array($this->_callback, $options); + } +} diff --git a/lib/zend/Zend/Filter/Compress.php b/lib/zend/Zend/Filter/Compress.php new file mode 100644 index 00000000000..e9361f7a437 --- /dev/null +++ b/lib/zend/Zend/Filter/Compress.php @@ -0,0 +1,197 @@ +toArray(); + } + if (is_string($options)) { + $this->setAdapter($options); + } elseif ($options instanceof Zend_Filter_Compress_CompressInterface) { + $this->setAdapter($options); + } elseif (is_array($options)) { + $this->setOptions($options); + } + } + + /** + * Set filter setate + * + * @param array $options + * @return Zend_Filter_Compress + */ + public function setOptions(array $options) + { + foreach ($options as $key => $value) { + if ($key == 'options') { + $key = 'adapterOptions'; + } + $method = 'set' . ucfirst($key); + if (method_exists($this, $method)) { + $this->$method($value); + } + } + return $this; + } + + /** + * Returns the current adapter, instantiating it if necessary + * + * @return string + */ + public function getAdapter() + { + if ($this->_adapter instanceof Zend_Filter_Compress_CompressInterface) { + return $this->_adapter; + } + + $adapter = $this->_adapter; + $options = $this->getAdapterOptions(); + if (!class_exists($adapter)) { + require_once 'Zend/Loader.php'; + if (Zend_Loader::isReadable('Zend/Filter/Compress/' . ucfirst($adapter) . '.php')) { + $adapter = 'Zend_Filter_Compress_' . ucfirst($adapter); + } + Zend_Loader::loadClass($adapter); + } + + $this->_adapter = new $adapter($options); + if (!$this->_adapter instanceof Zend_Filter_Compress_CompressInterface) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("Compression adapter '" . $adapter . "' does not implement Zend_Filter_Compress_CompressInterface"); + } + return $this->_adapter; + } + + /** + * Retrieve adapter name + * + * @return string + */ + public function getAdapterName() + { + return $this->getAdapter()->toString(); + } + + /** + * Sets compression adapter + * + * @param string|Zend_Filter_Compress_CompressInterface $adapter Adapter to use + * @return Zend_Filter_Compress + */ + public function setAdapter($adapter) + { + if ($adapter instanceof Zend_Filter_Compress_CompressInterface) { + $this->_adapter = $adapter; + return $this; + } + if (!is_string($adapter)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('Invalid adapter provided; must be string or instance of Zend_Filter_Compress_CompressInterface'); + } + $this->_adapter = $adapter; + + return $this; + } + + /** + * Retrieve adapter options + * + * @return array + */ + public function getAdapterOptions() + { + return $this->_adapterOptions; + } + + /** + * Set adapter options + * + * @param array $options + * @return void + */ + public function setAdapterOptions(array $options) + { + $this->_adapterOptions = $options; + return $this; + } + + /** + * Calls adapter methods + * + * @param string $method Method to call + * @param string|array $options Options for this method + */ + public function __call($method, $options) + { + $adapter = $this->getAdapter(); + if (!method_exists($adapter, $method)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("Unknown method '{$method}'"); + } + + return call_user_func_array(array($adapter, $method), $options); + } + + /** + * Defined by Zend_Filter_Interface + * + * Compresses the content $value with the defined settings + * + * @param string $value Content to compress + * @return string The compressed content + */ + public function filter($value) + { + return $this->getAdapter()->compress($value); + } +} diff --git a/lib/zend/Zend/Filter/Compress/Bz2.php b/lib/zend/Zend/Filter/Compress/Bz2.php new file mode 100644 index 00000000000..6bd4451f7bd --- /dev/null +++ b/lib/zend/Zend/Filter/Compress/Bz2.php @@ -0,0 +1,188 @@ + Blocksize to use from 0-9 + * 'archive' => Archive to use + * ) + * + * @var array + */ + protected $_options = array( + 'blocksize' => 4, + 'archive' => null, + ); + + /** + * Class constructor + * + * @param array|Zend_Config $options (Optional) Options to set + */ + public function __construct($options = null) + { + if (!extension_loaded('bz2')) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('This filter needs the bz2 extension'); + } + parent::__construct($options); + } + + /** + * Returns the set blocksize + * + * @return integer + */ + public function getBlocksize() + { + return $this->_options['blocksize']; + } + + /** + * Sets a new blocksize + * + * @param integer $level + * @return Zend_Filter_Compress_Bz2 + */ + public function setBlocksize($blocksize) + { + if (($blocksize < 0) || ($blocksize > 9)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('Blocksize must be between 0 and 9'); + } + + $this->_options['blocksize'] = (int) $blocksize; + return $this; + } + + /** + * Returns the set archive + * + * @return string + */ + public function getArchive() + { + return $this->_options['archive']; + } + + /** + * Sets the archive to use for de-/compression + * + * @param string $archive Archive to use + * @return Zend_Filter_Compress_Bz2 + */ + public function setArchive($archive) + { + $this->_options['archive'] = (string) $archive; + return $this; + } + + /** + * Compresses the given content + * + * @param string $content + * @return string + */ + public function compress($content) + { + $archive = $this->getArchive(); + if (!empty($archive)) { + $file = bzopen($archive, 'w'); + if (!$file) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("Error opening the archive '" . $archive . "'"); + } + + bzwrite($file, $content); + bzclose($file); + $compressed = true; + } else { + $compressed = bzcompress($content, $this->getBlocksize()); + } + + if (is_int($compressed)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('Error during compression'); + } + + return $compressed; + } + + /** + * Decompresses the given content + * + * @param string $content + * @return string + */ + public function decompress($content) + { + $archive = $this->getArchive(); + if (@file_exists($content)) { + $archive = $content; + } + + if (@file_exists($archive)) { + $file = bzopen($archive, 'r'); + if (!$file) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("Error opening the archive '" . $content . "'"); + } + + $compressed = bzread($file); + bzclose($file); + } else { + $compressed = bzdecompress($content); + } + + if (is_int($compressed)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('Error during decompression'); + } + + return $compressed; + } + + /** + * Returns the adapter name + * + * @return string + */ + public function toString() + { + return 'Bz2'; + } +} diff --git a/lib/zend/Zend/Filter/Compress/CompressAbstract.php b/lib/zend/Zend/Filter/Compress/CompressAbstract.php new file mode 100644 index 00000000000..2b20ac6f071 --- /dev/null +++ b/lib/zend/Zend/Filter/Compress/CompressAbstract.php @@ -0,0 +1,89 @@ +toArray(); + } + + if (is_array($options)) { + $this->setOptions($options); + } + } + + /** + * Returns one or all set options + * + * @param string $option (Optional) Option to return + * @return mixed + */ + public function getOptions($option = null) + { + if ($option === null) { + return $this->_options; + } + + if (!array_key_exists($option, $this->_options)) { + return null; + } + + return $this->_options[$option]; + } + + /** + * Sets all or one option + * + * @param array $options + * @return Zend_Filter_Compress_Bz2 + */ + public function setOptions(array $options) + { + foreach ($options as $key => $option) { + $method = 'set' . $key; + if (method_exists($this, $method)) { + $this->$method($option); + } + } + + return $this; + } +} diff --git a/lib/zend/Zend/Service/DeveloperGarden/ConferenceCall/ConferenceAccount.php b/lib/zend/Zend/Filter/Compress/CompressInterface.php similarity index 54% rename from lib/zend/Zend/Service/DeveloperGarden/ConferenceCall/ConferenceAccount.php rename to lib/zend/Zend/Filter/Compress/CompressInterface.php index 37c609ba15e..75f0a4063bc 100644 --- a/lib/zend/Zend/Service/DeveloperGarden/ConferenceCall/ConferenceAccount.php +++ b/lib/zend/Zend/Filter/Compress/CompressInterface.php @@ -13,50 +13,42 @@ * to license@zend.com so we can send you a copy immediately. * * @category Zend - * @package Zend_Service - * @subpackage DeveloperGarden - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @package Zend_Filter + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ /** + * Compression interface + * * @category Zend - * @package Zend_Service - * @subpackage DeveloperGarden - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @author Marco Kaiser + * @package Zend_Filter + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class Zend_Service_DeveloperGarden_ConferenceCall_ConferenceAccount +interface Zend_Filter_Compress_CompressInterface { /** - * type of billing + * Compresses $value with the defined settings * - * @var string + * @param string $value Data to compress + * @return string The compressed data */ - public $billingtype = null; + public function compress($value); /** - * account id + * Decompresses $value with the defined settings * - * @var integer + * @param string $value Data to decompress + * @return string The decompressed data */ - public $account = null; - - /** - * @return integer - */ - public function getAccount() - { - return $this->account; - } + public function decompress($value); /** + * Return the adapter name + * * @return string */ - public function getBillingType() - { - return $this->billingtype; - } + public function toString(); } diff --git a/lib/zend/Zend/Filter/Compress/Gz.php b/lib/zend/Zend/Filter/Compress/Gz.php new file mode 100644 index 00000000000..819795c5c97 --- /dev/null +++ b/lib/zend/Zend/Filter/Compress/Gz.php @@ -0,0 +1,228 @@ + Compression level 0-9 + * 'mode' => Compression mode, can be 'compress', 'deflate' + * 'archive' => Archive to use + * ) + * + * @var array + */ + protected $_options = array( + 'level' => 9, + 'mode' => 'compress', + 'archive' => null, + ); + + /** + * Class constructor + * + * @param array|Zend_Config|null $options (Optional) Options to set + */ + public function __construct($options = null) + { + if (!extension_loaded('zlib')) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('This filter needs the zlib extension'); + } + parent::__construct($options); + } + + /** + * Returns the set compression level + * + * @return integer + */ + public function getLevel() + { + return $this->_options['level']; + } + + /** + * Sets a new compression level + * + * @param integer $level + * @return Zend_Filter_Compress_Gz + */ + public function setLevel($level) + { + if (($level < 0) || ($level > 9)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('Level must be between 0 and 9'); + } + + $this->_options['level'] = (int) $level; + return $this; + } + + /** + * Returns the set compression mode + * + * @return string + */ + public function getMode() + { + return $this->_options['mode']; + } + + /** + * Sets a new compression mode + * + * @param string $mode Supported are 'compress', 'deflate' and 'file' + */ + public function setMode($mode) + { + if (($mode != 'compress') && ($mode != 'deflate')) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('Given compression mode not supported'); + } + + $this->_options['mode'] = $mode; + return $this; + } + + /** + * Returns the set archive + * + * @return string + */ + public function getArchive() + { + return $this->_options['archive']; + } + + /** + * Sets the archive to use for de-/compression + * + * @param string $archive Archive to use + * @return Zend_Filter_Compress_Gz + */ + public function setArchive($archive) + { + $this->_options['archive'] = (string) $archive; + return $this; + } + + /** + * Compresses the given content + * + * @param string $content + * @return string + */ + public function compress($content) + { + $archive = $this->getArchive(); + if (!empty($archive)) { + $file = gzopen($archive, 'w' . $this->getLevel()); + if (!$file) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("Error opening the archive '" . $this->_options['archive'] . "'"); + } + + gzwrite($file, $content); + gzclose($file); + $compressed = true; + } else if ($this->_options['mode'] == 'deflate') { + $compressed = gzdeflate($content, $this->getLevel()); + } else { + $compressed = gzcompress($content, $this->getLevel()); + } + + if (!$compressed) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('Error during compression'); + } + + return $compressed; + } + + /** + * Decompresses the given content + * + * @param string $content + * @return string + */ + public function decompress($content) + { + $archive = $this->getArchive(); + $mode = $this->getMode(); + if (@file_exists($content)) { + $archive = $content; + } + + if (@file_exists($archive)) { + $handler = fopen($archive, "rb"); + if (!$handler) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("Error opening the archive '" . $archive . "'"); + } + + fseek($handler, -4, SEEK_END); + $packet = fread($handler, 4); + $bytes = unpack("V", $packet); + $size = end($bytes); + fclose($handler); + + $file = gzopen($archive, 'r'); + $compressed = gzread($file, $size); + gzclose($file); + } else if ($mode == 'deflate') { + $compressed = gzinflate($content); + } else { + $compressed = gzuncompress($content); + } + + if (!$compressed) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('Error during compression'); + } + + return $compressed; + } + + /** + * Returns the adapter name + * + * @return string + */ + public function toString() + { + return 'Gz'; + } +} diff --git a/lib/zend/Zend/Filter/Compress/Lzf.php b/lib/zend/Zend/Filter/Compress/Lzf.php new file mode 100644 index 00000000000..33115105a00 --- /dev/null +++ b/lib/zend/Zend/Filter/Compress/Lzf.php @@ -0,0 +1,91 @@ + Callback for compression + * 'archive' => Archive to use + * 'password' => Password to use + * 'target' => Target to write the files to + * ) + * + * @var array + */ + protected $_options = array( + 'callback' => null, + 'archive' => null, + 'password' => null, + 'target' => '.', + ); + + /** + * Class constructor + * + * @param array $options (Optional) Options to set + */ + public function __construct($options = null) + { + if (!extension_loaded('rar')) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('This filter needs the rar extension'); + } + parent::__construct($options); + } + + /** + * Returns the set callback for compression + * + * @return string + */ + public function getCallback() + { + return $this->_options['callback']; + } + + /** + * Sets the callback to use + * + * @param string $callback + * @return Zend_Filter_Compress_Rar + */ + public function setCallback($callback) + { + if (!is_callable($callback)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('Callback can not be accessed'); + } + + $this->_options['callback'] = $callback; + return $this; + } + + /** + * Returns the set archive + * + * @return string + */ + public function getArchive() + { + return $this->_options['archive']; + } + + /** + * Sets the archive to use for de-/compression + * + * @param string $archive Archive to use + * @return Zend_Filter_Compress_Rar + */ + public function setArchive($archive) + { + $archive = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $archive); + $this->_options['archive'] = (string) $archive; + + return $this; + } + + /** + * Returns the set password + * + * @return string + */ + public function getPassword() + { + return $this->_options['password']; + } + + /** + * Sets the password to use + * + * @param string $password + * @return Zend_Filter_Compress_Rar + */ + public function setPassword($password) + { + $this->_options['password'] = (string) $password; + return $this; + } + + /** + * Returns the set targetpath + * + * @return string + */ + public function getTarget() + { + return $this->_options['target']; + } + + /** + * Sets the targetpath to use + * + * @param string $target + * @return Zend_Filter_Compress_Rar + */ + public function setTarget($target) + { + if (!file_exists(dirname($target))) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("The directory '$target' does not exist"); + } + + $target = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $target); + $this->_options['target'] = (string) $target; + return $this; + } + + /** + * Compresses the given content + * + * @param string|array $content + * @return string + */ + public function compress($content) + { + $callback = $this->getCallback(); + if ($callback === null) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('No compression callback available'); + } + + $options = $this->getOptions(); + unset($options['callback']); + + $result = call_user_func($callback, $options, $content); + if ($result !== true) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('Error compressing the RAR Archive'); + } + + return $this->getArchive(); + } + + /** + * Decompresses the given content + * + * @param string $content + * @return boolean + */ + public function decompress($content) + { + $archive = $this->getArchive(); + if (file_exists($content)) { + $archive = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, realpath($content)); + } elseif (empty($archive) || !file_exists($archive)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('RAR Archive not found'); + } + + $password = $this->getPassword(); + if ($password !== null) { + $archive = rar_open($archive, $password); + } else { + $archive = rar_open($archive); + } + + if (!$archive) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("Error opening the RAR Archive"); + } + + $target = $this->getTarget(); + if (!is_dir($target)) { + $target = dirname($target); + } + + $filelist = rar_list($archive); + if (!$filelist) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("Error reading the RAR Archive"); + } + + foreach($filelist as $file) { + $file->extract($target); + } + + rar_close($archive); + return true; + } + + /** + * Returns the adapter name + * + * @return string + */ + public function toString() + { + return 'Rar'; + } +} diff --git a/lib/zend/Zend/Filter/Compress/Tar.php b/lib/zend/Zend/Filter/Compress/Tar.php new file mode 100644 index 00000000000..d2ce0d89a9b --- /dev/null +++ b/lib/zend/Zend/Filter/Compress/Tar.php @@ -0,0 +1,245 @@ + Archive to use + * 'target' => Target to write the files to + * ) + * + * @var array + */ + protected $_options = array( + 'archive' => null, + 'target' => '.', + 'mode' => null, + ); + + /** + * Class constructor + * + * @param array $options (Optional) Options to set + */ + public function __construct($options = null) + { + if (!class_exists('Archive_Tar')) { + require_once 'Zend/Loader.php'; + try { + Zend_Loader::loadClass('Archive_Tar'); + } catch (Zend_Exception $e) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('This filter needs PEARs Archive_Tar', 0, $e); + } + } + + parent::__construct($options); + } + + /** + * Returns the set archive + * + * @return string + */ + public function getArchive() + { + return $this->_options['archive']; + } + + /** + * Sets the archive to use for de-/compression + * + * @param string $archive Archive to use + * @return Zend_Filter_Compress_Tar + */ + public function setArchive($archive) + { + $archive = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $archive); + $this->_options['archive'] = (string) $archive; + + return $this; + } + + /** + * Returns the set targetpath + * + * @return string + */ + public function getTarget() + { + return $this->_options['target']; + } + + /** + * Sets the targetpath to use + * + * @param string $target + * @return Zend_Filter_Compress_Tar + */ + public function setTarget($target) + { + if (!file_exists(dirname($target))) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("The directory '$target' does not exist"); + } + + $target = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $target); + $this->_options['target'] = (string) $target; + return $this; + } + + /** + * Returns the set compression mode + */ + public function getMode() + { + return $this->_options['mode']; + } + + /** + * Compression mode to use + * Eighter Gz or Bz2 + * + * @param string $mode + */ + public function setMode($mode) + { + $mode = ucfirst(strtolower($mode)); + if (($mode != 'Bz2') && ($mode != 'Gz')) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("The mode '$mode' is unknown"); + } + + if (($mode == 'Bz2') && (!extension_loaded('bz2'))) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('This mode needs the bz2 extension'); + } + + if (($mode == 'Gz') && (!extension_loaded('zlib'))) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('This mode needs the zlib extension'); + } + } + + /** + * Compresses the given content + * + * @param string $content + * @return string + */ + public function compress($content) + { + $archive = new Archive_Tar($this->getArchive(), $this->getMode()); + if (!file_exists($content)) { + $file = $this->getTarget(); + if (is_dir($file)) { + $file .= DIRECTORY_SEPARATOR . "tar.tmp"; + } + + $result = file_put_contents($file, $content); + if ($result === false) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('Error creating the temporary file'); + } + + $content = $file; + } + + if (is_dir($content)) { + // collect all file infos + foreach (new RecursiveIteratorIterator( + new RecursiveDirectoryIterator($content, RecursiveDirectoryIterator::KEY_AS_PATHNAME), + RecursiveIteratorIterator::SELF_FIRST + ) as $directory => $info + ) { + if ($info->isFile()) { + $file[] = $directory; + } + } + + $content = $file; + } + + $result = $archive->create($content); + if ($result === false) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('Error creating the Tar archive'); + } + + return $this->getArchive(); + } + + /** + * Decompresses the given content + * + * @param string $content + * @return boolean + */ + public function decompress($content) + { + $archive = $this->getArchive(); + if (file_exists($content)) { + $archive = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, realpath($content)); + } elseif (empty($archive) || !file_exists($archive)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('Tar Archive not found'); + } + + $archive = new Archive_Tar($archive, $this->getMode()); + $target = $this->getTarget(); + if (!is_dir($target)) { + $target = dirname($target); + } + + $result = $archive->extract($target); + if ($result === false) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('Error while extracting the Tar archive'); + } + + return true; + } + + /** + * Returns the adapter name + * + * @return string + */ + public function toString() + { + return 'Tar'; + } +} diff --git a/lib/zend/Zend/Filter/Compress/Zip.php b/lib/zend/Zend/Filter/Compress/Zip.php new file mode 100644 index 00000000000..9921fe9648a --- /dev/null +++ b/lib/zend/Zend/Filter/Compress/Zip.php @@ -0,0 +1,355 @@ + Archive to use + * 'password' => Password to use + * 'target' => Target to write the files to + * ) + * + * @var array + */ + protected $_options = array( + 'archive' => null, + 'target' => null, + ); + + /** + * Class constructor + * + * @param string|array $options (Optional) Options to set + */ + public function __construct($options = null) + { + if (!extension_loaded('zip')) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('This filter needs the zip extension'); + } + parent::__construct($options); + } + + /** + * Returns the set archive + * + * @return string + */ + public function getArchive() + { + return $this->_options['archive']; + } + + /** + * Sets the archive to use for de-/compression + * + * @param string $archive Archive to use + * @return Zend_Filter_Compress_Rar + */ + public function setArchive($archive) + { + $archive = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $archive); + $this->_options['archive'] = (string) $archive; + + return $this; + } + + /** + * Returns the set targetpath + * + * @return string + */ + public function getTarget() + { + return $this->_options['target']; + } + + /** + * Sets the target to use + * + * @param string $target + * @return Zend_Filter_Compress_Rar + */ + public function setTarget($target) + { + if (!file_exists(dirname($target))) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("The directory '$target' does not exist"); + } + + $target = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $target); + $this->_options['target'] = (string) $target; + return $this; + } + + /** + * Compresses the given content + * + * @param string $content + * @return string Compressed archive + */ + public function compress($content) + { + $zip = new ZipArchive(); + $res = $zip->open($this->getArchive(), ZipArchive::CREATE | ZipArchive::OVERWRITE); + + if ($res !== true) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception($this->_errorString($res)); + } + + if (file_exists($content)) { + $content = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, realpath($content)); + $basename = substr($content, strrpos($content, DIRECTORY_SEPARATOR) + 1); + if (is_dir($content)) { + $index = strrpos($content, DIRECTORY_SEPARATOR) + 1; + $content .= DIRECTORY_SEPARATOR; + $stack = array($content); + while (!empty($stack)) { + $current = array_pop($stack); + $files = array(); + + $dir = dir($current); + while (false !== ($node = $dir->read())) { + if (($node == '.') || ($node == '..')) { + continue; + } + + if (is_dir($current . $node)) { + array_push($stack, $current . $node . DIRECTORY_SEPARATOR); + } + + if (is_file($current . $node)) { + $files[] = $node; + } + } + + $local = substr($current, $index); + $zip->addEmptyDir(substr($local, 0, -1)); + + foreach ($files as $file) { + $zip->addFile($current . $file, $local . $file); + if ($res !== true) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception($this->_errorString($res)); + } + } + } + } else { + $res = $zip->addFile($content, $basename); + if ($res !== true) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception($this->_errorString($res)); + } + } + } else { + $file = $this->getTarget(); + if (!is_dir($file)) { + $file = basename($file); + } else { + $file = "zip.tmp"; + } + + $res = $zip->addFromString($file, $content); + if ($res !== true) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception($this->_errorString($res)); + } + } + + $zip->close(); + return $this->_options['archive']; + } + + /** + * Decompresses the given content + * + * @param string $content + * @return string + */ + public function decompress($content) + { + $archive = $this->getArchive(); + if (file_exists($content)) { + $archive = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, realpath($content)); + } elseif (empty($archive) || !file_exists($archive)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('ZIP Archive not found'); + } + + $zip = new ZipArchive(); + $res = $zip->open($archive); + + $target = $this->getTarget(); + + if (!empty($target) && !is_dir($target)) { + $target = dirname($target); + } + + if (!empty($target)) { + $target = rtrim($target, '/\\') . DIRECTORY_SEPARATOR; + } + + if (empty($target) || !is_dir($target)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('No target for ZIP decompression set'); + } + + if ($res !== true) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception($this->_errorString($res)); + } + + if (version_compare(PHP_VERSION, '5.2.8', '<')) { + for ($i = 0; $i < $zip->numFiles; $i++) { + $statIndex = $zip->statIndex($i); + $currName = $statIndex['name']; + if (($currName{0} == '/') || + (substr($currName, 0, 2) == '..') || + (substr($currName, 0, 4) == './..') + ) + { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('Upward directory traversal was detected inside ' . $archive + . ' please use PHP 5.2.8 or greater to take advantage of path resolution features of ' + . 'the zip extension in this decompress() method.' + ); + } + } + } + + $res = @$zip->extractTo($target); + if ($res !== true) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception($this->_errorString($res)); + } + + $zip->close(); + return $target; + } + + /** + * Returns the proper string based on the given error constant + * + * @param string $error + */ + protected function _errorString($error) + { + switch($error) { + case ZipArchive::ER_MULTIDISK : + return 'Multidisk ZIP Archives not supported'; + + case ZipArchive::ER_RENAME : + return 'Failed to rename the temporary file for ZIP'; + + case ZipArchive::ER_CLOSE : + return 'Failed to close the ZIP Archive'; + + case ZipArchive::ER_SEEK : + return 'Failure while seeking the ZIP Archive'; + + case ZipArchive::ER_READ : + return 'Failure while reading the ZIP Archive'; + + case ZipArchive::ER_WRITE : + return 'Failure while writing the ZIP Archive'; + + case ZipArchive::ER_CRC : + return 'CRC failure within the ZIP Archive'; + + case ZipArchive::ER_ZIPCLOSED : + return 'ZIP Archive already closed'; + + case ZipArchive::ER_NOENT : + return 'No such file within the ZIP Archive'; + + case ZipArchive::ER_EXISTS : + return 'ZIP Archive already exists'; + + case ZipArchive::ER_OPEN : + return 'Can not open ZIP Archive'; + + case ZipArchive::ER_TMPOPEN : + return 'Failure creating temporary ZIP Archive'; + + case ZipArchive::ER_ZLIB : + return 'ZLib Problem'; + + case ZipArchive::ER_MEMORY : + return 'Memory allocation problem while working on a ZIP Archive'; + + case ZipArchive::ER_CHANGED : + return 'ZIP Entry has been changed'; + + case ZipArchive::ER_COMPNOTSUPP : + return 'Compression method not supported within ZLib'; + + case ZipArchive::ER_EOF : + return 'Premature EOF within ZIP Archive'; + + case ZipArchive::ER_INVAL : + return 'Invalid argument for ZLIB'; + + case ZipArchive::ER_NOZIP : + return 'Given file is no zip archive'; + + case ZipArchive::ER_INTERNAL : + return 'Internal error while working on a ZIP Archive'; + + case ZipArchive::ER_INCONS : + return 'Inconsistent ZIP archive'; + + case ZipArchive::ER_REMOVE : + return 'Can not remove ZIP Archive'; + + case ZipArchive::ER_DELETED : + return 'ZIP Entry has been deleted'; + + default : + return 'Unknown error within ZIP Archive'; + } + } + + /** + * Returns the adapter name + * + * @return string + */ + public function toString() + { + return 'Zip'; + } +} diff --git a/lib/zend/Zend/Service/DeveloperGarden/Request/SendSms/SendFlashSMS.php b/lib/zend/Zend/Filter/Decompress.php similarity index 54% rename from lib/zend/Zend/Service/DeveloperGarden/Request/SendSms/SendFlashSMS.php rename to lib/zend/Zend/Filter/Decompress.php index 0471d5f4c9b..02e9a8e5d4f 100644 --- a/lib/zend/Zend/Service/DeveloperGarden/Request/SendSms/SendFlashSMS.php +++ b/lib/zend/Zend/Filter/Decompress.php @@ -13,34 +13,37 @@ * to license@zend.com so we can send you a copy immediately. * * @category Zend - * @package Zend_Service - * @subpackage DeveloperGarden - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @package Zend_Filter + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ /** - * @see Zend_Service_DeveloperGarden_Request_SendSms_SendSmsAbstract + * @see Zend_Filter_Compress */ -require_once 'Zend/Service/DeveloperGarden/Request/SendSms/SendSmsAbstract.php'; +require_once 'Zend/Filter/Compress.php'; /** + * Decompresses a given string + * * @category Zend - * @package Zend_Service - * @subpackage DeveloperGarden - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @author Marco Kaiser + * @package Zend_Filter + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class Zend_Service_DeveloperGarden_Request_SendSms_SendFlashSMS - extends Zend_Service_DeveloperGarden_Request_SendSms_SendSmsAbstract +class Zend_Filter_Decompress extends Zend_Filter_Compress { /** - * this is the sms type - * 2 = FlashSMS + * Defined by Zend_Filter_Interface * - * @var integer + * Decompresses the content $value with the defined settings + * + * @param string $value Content to decompress + * @return string The decompressed content */ - protected $_smsType = 2; + public function filter($value) + { + return $this->getAdapter()->decompress($value); + } } diff --git a/lib/zend/Zend/Service/DeveloperGarden/Request/SendSms/SendSMS.php b/lib/zend/Zend/Filter/Decrypt.php similarity index 54% rename from lib/zend/Zend/Service/DeveloperGarden/Request/SendSms/SendSMS.php rename to lib/zend/Zend/Filter/Decrypt.php index 2ff7d145a75..844d95b86f7 100644 --- a/lib/zend/Zend/Service/DeveloperGarden/Request/SendSms/SendSMS.php +++ b/lib/zend/Zend/Filter/Decrypt.php @@ -13,34 +13,37 @@ * to license@zend.com so we can send you a copy immediately. * * @category Zend - * @package Zend_Service - * @subpackage DeveloperGarden - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @package Zend_Filter + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ /** - * @see Zend_Service_DeveloperGarden_Request_SendSms_SendSmsAbstract + * @see Zend_Filter_Encrypt */ -require_once 'Zend/Service/DeveloperGarden/Request/SendSms/SendSmsAbstract.php'; +require_once 'Zend/Filter/Encrypt.php'; /** + * Decrypts a given string + * * @category Zend - * @package Zend_Service - * @subpackage DeveloperGarden - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @author Marco Kaiser + * @package Zend_Filter + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class Zend_Service_DeveloperGarden_Request_SendSms_SendSMS - extends Zend_Service_DeveloperGarden_Request_SendSms_SendSmsAbstract +class Zend_Filter_Decrypt extends Zend_Filter_Encrypt { /** - * this is the sms type - * 1 = normal SMS + * Defined by Zend_Filter_Interface * - * @var integer + * Decrypts the content $value with the defined settings + * + * @param string $value Content to decrypt + * @return string The decrypted content */ - protected $_smsType = 1; + public function filter($value) + { + return $this->_adapter->decrypt($value); + } } diff --git a/lib/zend/Zend/Filter/Digits.php b/lib/zend/Zend/Filter/Digits.php new file mode 100644 index 00000000000..01c3ed5a733 --- /dev/null +++ b/lib/zend/Zend/Filter/Digits.php @@ -0,0 +1,82 @@ +toArray(); + } + + $this->setAdapter($options); + } + + /** + * Returns the name of the set adapter + * + * @return string + */ + public function getAdapter() + { + return $this->_adapter->toString(); + } + + /** + * Sets new encryption options + * + * @param string|array $options (Optional) Encryption options + * @return Zend_Filter_Encrypt + */ + public function setAdapter($options = null) + { + if (is_string($options)) { + $adapter = $options; + } else if (isset($options['adapter'])) { + $adapter = $options['adapter']; + unset($options['adapter']); + } else { + $adapter = 'Mcrypt'; + } + + if (!is_array($options)) { + $options = array(); + } + + if (Zend_Loader::isReadable('Zend/Filter/Encrypt/' . ucfirst($adapter). '.php')) { + $adapter = 'Zend_Filter_Encrypt_' . ucfirst($adapter); + } + + if (!class_exists($adapter)) { + Zend_Loader::loadClass($adapter); + } + + $this->_adapter = new $adapter($options); + if (!$this->_adapter instanceof Zend_Filter_Encrypt_Interface) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("Encoding adapter '" . $adapter . "' does not implement Zend_Filter_Encrypt_Interface"); + } + + return $this; + } + + /** + * Calls adapter methods + * + * @param string $method Method to call + * @param string|array $options Options for this method + */ + public function __call($method, $options) + { + $part = substr($method, 0, 3); + if ((($part != 'get') and ($part != 'set')) or !method_exists($this->_adapter, $method)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("Unknown method '{$method}'"); + } + + return call_user_func_array(array($this->_adapter, $method), $options); + } + + /** + * Defined by Zend_Filter_Interface + * + * Encrypts the content $value with the defined settings + * + * @param string $value Content to encrypt + * @return string The encrypted content + */ + public function filter($value) + { + return $this->_adapter->encrypt($value); + } +} diff --git a/lib/zend/Zend/Filter/Encrypt/Interface.php b/lib/zend/Zend/Filter/Encrypt/Interface.php new file mode 100644 index 00000000000..1510e7ff90f --- /dev/null +++ b/lib/zend/Zend/Filter/Encrypt/Interface.php @@ -0,0 +1,47 @@ + encryption key string + * 'algorithm' => algorithm to use + * 'algorithm_directory' => directory where to find the algorithm + * 'mode' => encryption mode to use + * 'modedirectory' => directory where to find the mode + * ) + */ + protected $_encryption = array( + 'key' => 'ZendFramework', + 'algorithm' => 'blowfish', + 'algorithm_directory' => '', + 'mode' => 'cbc', + 'mode_directory' => '', + 'vector' => null, + 'salt' => false + ); + + /** + * Internal compression + * + * @var array + */ + protected $_compression; + + protected static $_srandCalled = false; + + /** + * Class constructor + * + * @param string|array|Zend_Config $options Cryption Options + */ + public function __construct($options) + { + if (!extension_loaded('mcrypt')) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('This filter needs the mcrypt extension'); + } + + if ($options instanceof Zend_Config) { + $options = $options->toArray(); + } elseif (is_string($options)) { + $options = array('key' => $options); + } elseif (!is_array($options)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('Invalid options argument provided to filter'); + } + + if (array_key_exists('compression', $options)) { + $this->setCompression($options['compression']); + unset($options['compress']); + } + + $this->setEncryption($options); + } + + /** + * Returns the set encryption options + * + * @return array + */ + public function getEncryption() + { + return $this->_encryption; + } + + /** + * Sets new encryption options + * + * @param string|array $options Encryption options + * @return Zend_Filter_File_Encryption + */ + public function setEncryption($options) + { + if (is_string($options)) { + $options = array('key' => $options); + } + + if (!is_array($options)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('Invalid options argument provided to filter'); + } + + $options = $options + $this->getEncryption(); + $algorithms = mcrypt_list_algorithms($options['algorithm_directory']); + if (!in_array($options['algorithm'], $algorithms)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("The algorithm '{$options['algorithm']}' is not supported"); + } + + $modes = mcrypt_list_modes($options['mode_directory']); + if (!in_array($options['mode'], $modes)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("The mode '{$options['mode']}' is not supported"); + } + + if (!mcrypt_module_self_test($options['algorithm'], $options['algorithm_directory'])) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('The given algorithm can not be used due an internal mcrypt problem'); + } + + if (!isset($options['vector'])) { + $options['vector'] = null; + } + + $this->_encryption = $options; + $this->setVector($options['vector']); + + return $this; + } + + /** + * Returns the set vector + * + * @return string + */ + public function getVector() + { + return $this->_encryption['vector']; + } + + /** + * Sets the initialization vector + * + * @param string $vector (Optional) Vector to set + * @return Zend_Filter_Encrypt_Mcrypt + */ + public function setVector($vector = null) + { + $cipher = $this->_openCipher(); + $size = mcrypt_enc_get_iv_size($cipher); + if (empty($vector)) { + $this->_srand(); + if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' && version_compare(PHP_VERSION, '5.3.0', '<')) { + $method = MCRYPT_RAND; + } else { + if (file_exists('/dev/urandom') || (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN')) { + $method = MCRYPT_DEV_URANDOM; + } elseif (file_exists('/dev/random')) { + $method = MCRYPT_DEV_RANDOM; + } else { + $method = MCRYPT_RAND; + } + } + $vector = mcrypt_create_iv($size, $method); + } else if (strlen($vector) != $size) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('The given vector has a wrong size for the set algorithm'); + } + + $this->_encryption['vector'] = $vector; + $this->_closeCipher($cipher); + + return $this; + } + + /** + * Returns the compression + * + * @return array + */ + public function getCompression() + { + return $this->_compression; + } + + /** + * Sets a internal compression for values to encrypt + * + * @param string|array $compression + * @return Zend_Filter_Encrypt_Mcrypt + */ + public function setCompression($compression) + { + if (is_string($this->_compression)) { + $compression = array('adapter' => $compression); + } + + $this->_compression = $compression; + return $this; + } + + /** + * Defined by Zend_Filter_Interface + * + * Encrypts $value with the defined settings + * + * @param string $value The content to encrypt + * @return string The encrypted content + */ + public function encrypt($value) + { + // compress prior to encryption + if (!empty($this->_compression)) { + require_once 'Zend/Filter/Compress.php'; + $compress = new Zend_Filter_Compress($this->_compression); + $value = $compress->filter($value); + } + + $cipher = $this->_openCipher(); + $this->_initCipher($cipher); + $encrypted = mcrypt_generic($cipher, $value); + mcrypt_generic_deinit($cipher); + $this->_closeCipher($cipher); + + return $encrypted; + } + + /** + * Defined by Zend_Filter_Interface + * + * Decrypts $value with the defined settings + * + * @param string $value Content to decrypt + * @return string The decrypted content + */ + public function decrypt($value) + { + $cipher = $this->_openCipher(); + $this->_initCipher($cipher); + $decrypted = mdecrypt_generic($cipher, $value); + mcrypt_generic_deinit($cipher); + $this->_closeCipher($cipher); + + // decompress after decryption + if (!empty($this->_compression)) { + require_once 'Zend/Filter/Decompress.php'; + $decompress = new Zend_Filter_Decompress($this->_compression); + $decrypted = $decompress->filter($decrypted); + } + + return $decrypted; + } + + /** + * Returns the adapter name + * + * @return string + */ + public function toString() + { + return 'Mcrypt'; + } + + /** + * Open a cipher + * + * @throws Zend_Filter_Exception When the cipher can not be opened + * @return resource Returns the opened cipher + */ + protected function _openCipher() + { + $cipher = mcrypt_module_open( + $this->_encryption['algorithm'], + $this->_encryption['algorithm_directory'], + $this->_encryption['mode'], + $this->_encryption['mode_directory']); + + if ($cipher === false) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('Mcrypt can not be opened with your settings'); + } + + return $cipher; + } + + /** + * Close a cipher + * + * @param resource $cipher Cipher to close + * @return Zend_Filter_Encrypt_Mcrypt + */ + protected function _closeCipher($cipher) + { + mcrypt_module_close($cipher); + + return $this; + } + + /** + * Initialises the cipher with the set key + * + * @param resource $cipher + * @throws + * @return resource + */ + protected function _initCipher($cipher) + { + $key = $this->_encryption['key']; + + $keysizes = mcrypt_enc_get_supported_key_sizes($cipher); + if (empty($keysizes) || ($this->_encryption['salt'] == true)) { + $this->_srand(); + $keysize = mcrypt_enc_get_key_size($cipher); + $key = substr(md5($key), 0, $keysize); + } else if (!in_array(strlen($key), $keysizes)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('The given key has a wrong size for the set algorithm'); + } + + $result = mcrypt_generic_init($cipher, $key, $this->_encryption['vector']); + if ($result < 0) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('Mcrypt could not be initialize with the given setting'); + } + + return $this; + } + + /** + * _srand() interception + * + * @see ZF-8742 + */ + protected function _srand() + { + if (version_compare(PHP_VERSION, '5.3.0', '>=')) { + return; + } + + if (!self::$_srandCalled) { + srand((double) microtime() * 1000000); + self::$_srandCalled = true; + } + } +} diff --git a/lib/zend/Zend/Filter/Encrypt/Openssl.php b/lib/zend/Zend/Filter/Encrypt/Openssl.php new file mode 100644 index 00000000000..7d1f70bd0ae --- /dev/null +++ b/lib/zend/Zend/Filter/Encrypt/Openssl.php @@ -0,0 +1,492 @@ + public keys + * 'private' => private keys + * 'envelope' => resulting envelope keys + * ) + */ + protected $_keys = array( + 'public' => array(), + 'private' => array(), + 'envelope' => array() + ); + + /** + * Internal passphrase + * + * @var string + */ + protected $_passphrase; + + /** + * Internal compression + * + * @var array + */ + protected $_compression; + + /** + * Internal create package + * + * @var boolean + */ + protected $_package = false; + + /** + * Class constructor + * Available options + * 'public' => public key + * 'private' => private key + * 'envelope' => envelope key + * 'passphrase' => passphrase + * 'compression' => compress value with this compression adapter + * 'package' => pack envelope keys into encrypted string, simplifies decryption + * + * @param string|array $options Options for this adapter + */ + public function __construct($options = array()) + { + if (!extension_loaded('openssl')) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('This filter needs the openssl extension'); + } + + if ($options instanceof Zend_Config) { + $options = $options->toArray(); + } + + if (!is_array($options)) { + $options = array('public' => $options); + } + + if (array_key_exists('passphrase', $options)) { + $this->setPassphrase($options['passphrase']); + unset($options['passphrase']); + } + + if (array_key_exists('compression', $options)) { + $this->setCompression($options['compression']); + unset($options['compress']); + } + + if (array_key_exists('package', $options)) { + $this->setPackage($options['package']); + unset($options['package']); + } + + $this->_setKeys($options); + } + + /** + * Sets the encryption keys + * + * @param string|array $keys Key with type association + * @return Zend_Filter_Encrypt_Openssl + */ + protected function _setKeys($keys) + { + if (!is_array($keys)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('Invalid options argument provided to filter'); + } + + foreach ($keys as $type => $key) { + if (ctype_print($key) && is_file(realpath($key)) && is_readable($key)) { + $file = fopen($key, 'r'); + $cert = fread($file, 8192); + fclose($file); + } else { + $cert = $key; + $key = count($this->_keys[$type]); + } + + switch ($type) { + case 'public': + $test = openssl_pkey_get_public($cert); + if ($test === false) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("Public key '{$cert}' not valid"); + } + + openssl_free_key($test); + $this->_keys['public'][$key] = $cert; + break; + case 'private': + $test = openssl_pkey_get_private($cert, $this->_passphrase); + if ($test === false) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("Private key '{$cert}' not valid"); + } + + openssl_free_key($test); + $this->_keys['private'][$key] = $cert; + break; + case 'envelope': + $this->_keys['envelope'][$key] = $cert; + break; + default: + break; + } + } + + return $this; + } + + /** + * Returns all public keys + * + * @return array + */ + public function getPublicKey() + { + $key = $this->_keys['public']; + return $key; + } + + /** + * Sets public keys + * + * @param string|array $key Public keys + * @return Zend_Filter_Encrypt_Openssl + */ + public function setPublicKey($key) + { + if (is_array($key)) { + foreach($key as $type => $option) { + if ($type !== 'public') { + $key['public'] = $option; + unset($key[$type]); + } + } + } else { + $key = array('public' => $key); + } + + return $this->_setKeys($key); + } + + /** + * Returns all private keys + * + * @return array + */ + public function getPrivateKey() + { + $key = $this->_keys['private']; + return $key; + } + + /** + * Sets private keys + * + * @param string $key Private key + * @param string $passphrase + * @return Zend_Filter_Encrypt_Openssl + */ + public function setPrivateKey($key, $passphrase = null) + { + if (is_array($key)) { + foreach($key as $type => $option) { + if ($type !== 'private') { + $key['private'] = $option; + unset($key[$type]); + } + } + } else { + $key = array('private' => $key); + } + + if ($passphrase !== null) { + $this->setPassphrase($passphrase); + } + + return $this->_setKeys($key); + } + + /** + * Returns all envelope keys + * + * @return array + */ + public function getEnvelopeKey() + { + $key = $this->_keys['envelope']; + return $key; + } + + /** + * Sets envelope keys + * + * @param string|array $options Envelope keys + * @return Zend_Filter_Encrypt_Openssl + */ + public function setEnvelopeKey($key) + { + if (is_array($key)) { + foreach($key as $type => $option) { + if ($type !== 'envelope') { + $key['envelope'] = $option; + unset($key[$type]); + } + } + } else { + $key = array('envelope' => $key); + } + + return $this->_setKeys($key); + } + + /** + * Returns the passphrase + * + * @return string + */ + public function getPassphrase() + { + return $this->_passphrase; + } + + /** + * Sets a new passphrase + * + * @param string $passphrase + * @return Zend_Filter_Encrypt_Openssl + */ + public function setPassphrase($passphrase) + { + $this->_passphrase = $passphrase; + return $this; + } + + /** + * Returns the compression + * + * @return array + */ + public function getCompression() + { + return $this->_compression; + } + + /** + * Sets a internal compression for values to encrypt + * + * @param string|array $compression + * @return Zend_Filter_Encrypt_Openssl + */ + public function setCompression($compression) + { + if (is_string($this->_compression)) { + $compression = array('adapter' => $compression); + } + + $this->_compression = $compression; + return $this; + } + + /** + * Returns if header should be packaged + * + * @return boolean + */ + public function getPackage() + { + return $this->_package; + } + + /** + * Sets if the envelope keys should be included in the encrypted value + * + * @param boolean $package + * @return Zend_Filter_Encrypt_Openssl + */ + public function setPackage($package) + { + $this->_package = (boolean) $package; + return $this; + } + + /** + * Encrypts $value with the defined settings + * Note that you also need the "encrypted" keys to be able to decrypt + * + * @param string $value Content to encrypt + * @return string The encrypted content + * @throws Zend_Filter_Exception + */ + public function encrypt($value) + { + $encrypted = array(); + $encryptedkeys = array(); + + if (count($this->_keys['public']) == 0) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('Openssl can not encrypt without public keys'); + } + + $keys = array(); + $fingerprints = array(); + $count = -1; + foreach($this->_keys['public'] as $key => $cert) { + $keys[$key] = openssl_pkey_get_public($cert); + if ($this->_package) { + $details = openssl_pkey_get_details($keys[$key]); + if ($details === false) { + $details = array('key' => 'ZendFramework'); + } + + ++$count; + $fingerprints[$count] = md5($details['key']); + } + } + + // compress prior to encryption + if (!empty($this->_compression)) { + require_once 'Zend/Filter/Compress.php'; + $compress = new Zend_Filter_Compress($this->_compression); + $value = $compress->filter($value); + } + + $crypt = openssl_seal($value, $encrypted, $encryptedkeys, $keys); + foreach ($keys as $key) { + openssl_free_key($key); + } + + if ($crypt === false) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('Openssl was not able to encrypt your content with the given options'); + } + + $this->_keys['envelope'] = $encryptedkeys; + + // Pack data and envelope keys into single string + if ($this->_package) { + $header = pack('n', count($this->_keys['envelope'])); + foreach($this->_keys['envelope'] as $key => $envKey) { + $header .= pack('H32n', $fingerprints[$key], strlen($envKey)) . $envKey; + } + + $encrypted = $header . $encrypted; + } + + return $encrypted; + } + + /** + * Defined by Zend_Filter_Interface + * + * Decrypts $value with the defined settings + * + * @param string $value Content to decrypt + * @return string The decrypted content + * @throws Zend_Filter_Exception + */ + public function decrypt($value) + { + $decrypted = ""; + $envelope = current($this->getEnvelopeKey()); + + if (count($this->_keys['private']) !== 1) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('Please give a private key for decryption with Openssl'); + } + + if (!$this->_package && empty($envelope)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('Please give a envelope key for decryption with Openssl'); + } + + foreach($this->_keys['private'] as $key => $cert) { + $keys = openssl_pkey_get_private($cert, $this->getPassphrase()); + } + + if ($this->_package) { + $details = openssl_pkey_get_details($keys); + if ($details !== false) { + $fingerprint = md5($details['key']); + } else { + $fingerprint = md5("ZendFramework"); + } + + $count = unpack('ncount', $value); + $count = $count['count']; + $length = 2; + for($i = $count; $i > 0; --$i) { + $header = unpack('H32print/nsize', substr($value, $length, 18)); + $length += 18; + if ($header['print'] == $fingerprint) { + $envelope = substr($value, $length, $header['size']); + } + + $length += $header['size']; + } + + // remainder of string is the value to decrypt + $value = substr($value, $length); + } + + $crypt = openssl_open($value, $decrypted, $envelope, $keys); + openssl_free_key($keys); + + if ($crypt === false) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('Openssl was not able to decrypt you content with the given options'); + } + + // decompress after decryption + if (!empty($this->_compression)) { + require_once 'Zend/Filter/Decompress.php'; + $decompress = new Zend_Filter_Decompress($this->_compression); + $decrypted = $decompress->filter($decrypted); + } + + return $decrypted; + } + + /** + * Returns the adapter name + * + * @return string + */ + public function toString() + { + return 'Openssl'; + } +} diff --git a/lib/zend/Zend/Filter/Exception.php b/lib/zend/Zend/Filter/Exception.php new file mode 100644 index 00000000000..5763b2456ec --- /dev/null +++ b/lib/zend/Zend/Filter/Exception.php @@ -0,0 +1,37 @@ +_filename; + } + + /** + * Sets the new filename where the content will be stored + * + * @param string $filename (Optional) New filename to set + * @return Zend_Filter_File_Encryt + */ + public function setFilename($filename = null) + { + $this->_filename = $filename; + return $this; + } + + /** + * Defined by Zend_Filter_Interface + * + * Decrypts the file $value with the defined settings + * + * @param string $value Full path of file to change + * @return string The filename which has been set, or false when there were errors + */ + public function filter($value) + { + if (!file_exists($value)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("File '$value' not found"); + } + + if (!isset($this->_filename)) { + $this->_filename = $value; + } + + if (file_exists($this->_filename) and !is_writable($this->_filename)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("File '{$this->_filename}' is not writable"); + } + + $content = file_get_contents($value); + if (!$content) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("Problem while reading file '$value'"); + } + + $decrypted = parent::filter($content); + $result = file_put_contents($this->_filename, $decrypted); + + if (!$result) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("Problem while writing file '{$this->_filename}'"); + } + + return $this->_filename; + } +} diff --git a/lib/zend/Zend/Filter/File/Encrypt.php b/lib/zend/Zend/Filter/File/Encrypt.php new file mode 100644 index 00000000000..23c71b4b0aa --- /dev/null +++ b/lib/zend/Zend/Filter/File/Encrypt.php @@ -0,0 +1,106 @@ +_filename; + } + + /** + * Sets the new filename where the content will be stored + * + * @param string $filename (Optional) New filename to set + * @return Zend_Filter_File_Encryt + */ + public function setFilename($filename = null) + { + $this->_filename = $filename; + return $this; + } + + /** + * Defined by Zend_Filter_Interface + * + * Encrypts the file $value with the defined settings + * + * @param string $value Full path of file to change + * @return string The filename which has been set, or false when there were errors + */ + public function filter($value) + { + if (!file_exists($value)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("File '$value' not found"); + } + + if (!isset($this->_filename)) { + $this->_filename = $value; + } + + if (file_exists($this->_filename) and !is_writable($this->_filename)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("File '{$this->_filename}' is not writable"); + } + + $content = file_get_contents($value); + if (!$content) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("Problem while reading file '$value'"); + } + + $encrypted = parent::filter($content); + $result = file_put_contents($this->_filename, $encrypted); + + if (!$result) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("Problem while writing file '{$this->_filename}'"); + } + + return $this->_filename; + } +} diff --git a/lib/zend/Zend/Filter/File/LowerCase.php b/lib/zend/Zend/Filter/File/LowerCase.php new file mode 100644 index 00000000000..dd34321dea7 --- /dev/null +++ b/lib/zend/Zend/Filter/File/LowerCase.php @@ -0,0 +1,84 @@ +setEncoding($options); + } + } + + /** + * Defined by Zend_Filter_Interface + * + * Does a lowercase on the content of the given file + * + * @param string $value Full path of file to change + * @return string The given $value + * @throws Zend_Filter_Exception + */ + public function filter($value) + { + if (!file_exists($value)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("File '$value' not found"); + } + + if (!is_writable($value)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("File '$value' is not writable"); + } + + $content = file_get_contents($value); + if (!$content) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("Problem while reading file '$value'"); + } + + $content = parent::filter($content); + $result = file_put_contents($value, $content); + + if (!$result) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("Problem while writing file '$value'"); + } + + return $value; + } +} diff --git a/lib/zend/Zend/Filter/File/Rename.php b/lib/zend/Zend/Filter/File/Rename.php new file mode 100644 index 00000000000..b70acbe301f --- /dev/null +++ b/lib/zend/Zend/Filter/File/Rename.php @@ -0,0 +1,309 @@ + Source filename or directory which will be renamed + * 'target' => Target filename or directory, the new name of the sourcefile + * 'overwrite' => Shall existing files be overwritten ? + * + * @param string|array $options Target file or directory to be renamed + * @param string $target Source filename or directory (deprecated) + * @param bool $overwrite Should existing files be overwritten (deprecated) + * @return void + */ + public function __construct($options) + { + if ($options instanceof Zend_Config) { + $options = $options->toArray(); + } elseif (is_string($options)) { + $options = array('target' => $options); + } elseif (!is_array($options)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('Invalid options argument provided to filter'); + } + + if (1 < func_num_args()) { + $argv = func_get_args(); + array_shift($argv); + $source = array_shift($argv); + $overwrite = false; + if (!empty($argv)) { + $overwrite = array_shift($argv); + } + $options['source'] = $source; + $options['overwrite'] = $overwrite; + } + + $this->setFile($options); + } + + /** + * Returns the files to rename and their new name and location + * + * @return array + */ + public function getFile() + { + return $this->_files; + } + + /** + * Sets a new file or directory as target, deleting existing ones + * + * Array accepts the following keys: + * 'source' => Source filename or directory which will be renamed + * 'target' => Target filename or directory, the new name of the sourcefile + * 'overwrite' => Shall existing files be overwritten ? + * + * @param string|array $options Old file or directory to be rewritten + * @return Zend_Filter_File_Rename + */ + public function setFile($options) + { + $this->_files = array(); + $this->addFile($options); + + return $this; + } + + /** + * Adds a new file or directory as target to the existing ones + * + * Array accepts the following keys: + * 'source' => Source filename or directory which will be renamed + * 'target' => Target filename or directory, the new name of the sourcefile + * 'overwrite' => Shall existing files be overwritten ? + * + * @param string|array $options Old file or directory to be rewritten + * @return Zend_Filter_File_Rename + */ + public function addFile($options) + { + if (is_string($options)) { + $options = array('target' => $options); + } elseif (!is_array($options)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception ('Invalid options to rename filter provided'); + } + + $this->_convertOptions($options); + + return $this; + } + + /** + * Returns only the new filename without moving it + * But existing files will be erased when the overwrite option is true + * + * @param string $value Full path of file to change + * @param boolean $source Return internal informations + * @return string The new filename which has been set + */ + public function getNewName($value, $source = false) + { + $file = $this->_getFileName($value); + + if (!is_array($file) || !array_key_exists('source', $file) || !array_key_exists('target', $file)) { + return $value; + } + + if ($file['source'] == $file['target']) { + return $value; + } + + if (!file_exists($file['source'])) { + return $value; + } + + if (($file['overwrite'] == true) && (file_exists($file['target']))) { + unlink($file['target']); + } + + if (file_exists($file['target'])) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception(sprintf("File '%s' could not be renamed. It already exists.", $value)); + } + + if ($source) { + return $file; + } + + return $file['target']; + } + + /** + * Defined by Zend_Filter_Interface + * + * Renames the file $value to the new name set before + * Returns the file $value, removing all but digit characters + * + * @param string $value Full path of file to change + * @throws Zend_Filter_Exception + * @return string The new filename which has been set, or false when there were errors + */ + public function filter($value) + { + $file = $this->getNewName($value, true); + if (is_string($file)) { + return $file; + } + + $result = rename($file['source'], $file['target']); + + if ($result === true) { + return $file['target']; + } + + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception(sprintf("File '%s' could not be renamed. An error occured while processing the file.", $value)); + } + + /** + * Internal method for creating the file array + * Supports single and nested arrays + * + * @param array $options + * @return array + */ + protected function _convertOptions($options) { + $files = array(); + foreach ($options as $key => $value) { + if (is_array($value)) { + $this->_convertOptions($value); + continue; + } + + switch ($key) { + case "source": + $files['source'] = (string) $value; + break; + + case 'target' : + $files['target'] = (string) $value; + break; + + case 'overwrite' : + $files['overwrite'] = (boolean) $value; + break; + + default: + break; + } + } + + if (empty($files)) { + return $this; + } + + if (empty($files['source'])) { + $files['source'] = '*'; + } + + if (empty($files['target'])) { + $files['target'] = '*'; + } + + if (empty($files['overwrite'])) { + $files['overwrite'] = false; + } + + $found = false; + foreach ($this->_files as $key => $value) { + if ($value['source'] == $files['source']) { + $this->_files[$key] = $files; + $found = true; + } + } + + if (!$found) { + $count = count($this->_files); + $this->_files[$count] = $files; + } + + return $this; + } + + /** + * Internal method to resolve the requested source + * and return all other related parameters + * + * @param string $file Filename to get the informations for + * @return array + */ + protected function _getFileName($file) + { + $rename = array(); + foreach ($this->_files as $value) { + if ($value['source'] == '*') { + if (!isset($rename['source'])) { + $rename = $value; + $rename['source'] = $file; + } + } + + if ($value['source'] == $file) { + $rename = $value; + } + } + + if (!isset($rename['source'])) { + return $file; + } + + if (!isset($rename['target']) or ($rename['target'] == '*')) { + $rename['target'] = $rename['source']; + } + + if (is_dir($rename['target'])) { + $name = basename($rename['source']); + $last = $rename['target'][strlen($rename['target']) - 1]; + if (($last != '/') and ($last != '\\')) { + $rename['target'] .= DIRECTORY_SEPARATOR; + } + + $rename['target'] .= $name; + } + + return $rename; + } +} diff --git a/lib/zend/Zend/Filter/File/UpperCase.php b/lib/zend/Zend/Filter/File/UpperCase.php new file mode 100644 index 00000000000..e65453e0fdb --- /dev/null +++ b/lib/zend/Zend/Filter/File/UpperCase.php @@ -0,0 +1,84 @@ +setEncoding($options); + } + } + + /** + * Defined by Zend_Filter_Interface + * + * Does a lowercase on the content of the given file + * + * @param string $value Full path of file to change + * @return string The given $value + * @throws Zend_Filter_Exception + */ + public function filter($value) + { + if (!file_exists($value)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("File '$value' not found"); + } + + if (!is_writable($value)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("File '$value' is not writable"); + } + + $content = file_get_contents($value); + if (!$content) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("Problem while reading file '$value'"); + } + + $content = parent::filter($content); + $result = file_put_contents($value, $content); + + if (!$result) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("Problem while writing file '$value'"); + } + + return $value; + } +} diff --git a/lib/zend/Zend/Filter/HtmlEntities.php b/lib/zend/Zend/Filter/HtmlEntities.php new file mode 100644 index 00000000000..0c1dfecb956 --- /dev/null +++ b/lib/zend/Zend/Filter/HtmlEntities.php @@ -0,0 +1,216 @@ +toArray(); + } else if (!is_array($options)) { + $options = func_get_args(); + $temp['quotestyle'] = array_shift($options); + if (!empty($options)) { + $temp['charset'] = array_shift($options); + } + + $options = $temp; + } + + if (!isset($options['quotestyle'])) { + $options['quotestyle'] = ENT_COMPAT; + } + + if (!isset($options['encoding'])) { + $options['encoding'] = 'UTF-8'; + } + if (isset($options['charset'])) { + $options['encoding'] = $options['charset']; + } + + if (!isset($options['doublequote'])) { + $options['doublequote'] = true; + } + + $this->setQuoteStyle($options['quotestyle']); + $this->setEncoding($options['encoding']); + $this->setDoubleQuote($options['doublequote']); + } + + /** + * Returns the quoteStyle option + * + * @return integer + */ + public function getQuoteStyle() + { + return $this->_quoteStyle; + } + + /** + * Sets the quoteStyle option + * + * @param integer $quoteStyle + * @return Zend_Filter_HtmlEntities Provides a fluent interface + */ + public function setQuoteStyle($quoteStyle) + { + $this->_quoteStyle = $quoteStyle; + return $this; + } + + + /** + * Get encoding + * + * @return string + */ + public function getEncoding() + { + return $this->_encoding; + } + + /** + * Set encoding + * + * @param string $value + * @return Zend_Filter_HtmlEntities + */ + public function setEncoding($value) + { + $this->_encoding = (string) $value; + return $this; + } + + /** + * Returns the charSet option + * + * Proxies to {@link getEncoding()} + * + * @return string + */ + public function getCharSet() + { + return $this->getEncoding(); + } + + /** + * Sets the charSet option + * + * Proxies to {@link setEncoding()} + * + * @param string $charSet + * @return Zend_Filter_HtmlEntities Provides a fluent interface + */ + public function setCharSet($charSet) + { + return $this->setEncoding($charSet); + } + + /** + * Returns the doubleQuote option + * + * @return boolean + */ + public function getDoubleQuote() + { + return $this->_doubleQuote; + } + + /** + * Sets the doubleQuote option + * + * @param boolean $doubleQuote + * @return Zend_Filter_HtmlEntities Provides a fluent interface + */ + public function setDoubleQuote($doubleQuote) + { + $this->_doubleQuote = (boolean) $doubleQuote; + return $this; + } + + /** + * Defined by Zend_Filter_Interface + * + * Returns the string $value, converting characters to their corresponding HTML entity + * equivalents where they exist + * + * @param string $value + * @return string + */ + public function filter($value) + { + $filtered = htmlentities((string) $value, $this->getQuoteStyle(), $this->getEncoding(), $this->getDoubleQuote()); + if (strlen((string) $value) && !strlen($filtered)) { + if (!function_exists('iconv')) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('Encoding mismatch has resulted in htmlentities errors'); + } + $enc = $this->getEncoding(); + $value = iconv('', $enc . '//IGNORE', (string) $value); + $filtered = htmlentities($value, $this->getQuoteStyle(), $enc, $this->getDoubleQuote()); + if (!strlen($filtered)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('Encoding mismatch has resulted in htmlentities errors'); + } + } + return $filtered; + } +} diff --git a/lib/zend/Zend/Filter/Inflector.php b/lib/zend/Zend/Filter/Inflector.php new file mode 100644 index 00000000000..00eea7d64b2 --- /dev/null +++ b/lib/zend/Zend/Filter/Inflector.php @@ -0,0 +1,527 @@ +toArray(); + } else if (!is_array($options)) { + $options = func_get_args(); + $temp = array(); + + if (!empty($options)) { + $temp['target'] = array_shift($options); + } + + if (!empty($options)) { + $temp['rules'] = array_shift($options); + } + + if (!empty($options)) { + $temp['throwTargetExceptionsOn'] = array_shift($options); + } + + if (!empty($options)) { + $temp['targetReplacementIdentifier'] = array_shift($options); + } + + $options = $temp; + } + + $this->setOptions($options); + } + + /** + * Retreive PluginLoader + * + * @return Zend_Loader_PluginLoader_Interface + */ + public function getPluginLoader() + { + if (!$this->_pluginLoader instanceof Zend_Loader_PluginLoader_Interface) { + $this->_pluginLoader = new Zend_Loader_PluginLoader(array('Zend_Filter_' => 'Zend/Filter/'), __CLASS__); + } + + return $this->_pluginLoader; + } + + /** + * Set PluginLoader + * + * @param Zend_Loader_PluginLoader_Interface $pluginLoader + * @return Zend_Filter_Inflector + */ + public function setPluginLoader(Zend_Loader_PluginLoader_Interface $pluginLoader) + { + $this->_pluginLoader = $pluginLoader; + return $this; + } + + /** + * Use Zend_Config object to set object state + * + * @deprecated Use setOptions() instead + * @param Zend_Config $config + * @return Zend_Filter_Inflector + */ + public function setConfig(Zend_Config $config) + { + return $this->setOptions($config); + } + + /** + * Set options + * + * @param array $options + * @return Zend_Filter_Inflector + */ + public function setOptions($options) { + if ($options instanceof Zend_Config) { + $options = $options->toArray(); + } + + // Set Präfix Path + if (array_key_exists('filterPrefixPath', $options)) { + if (!is_scalar($options['filterPrefixPath'])) { + foreach ($options['filterPrefixPath'] as $prefix => $path) { + $this->addFilterPrefixPath($prefix, $path); + } + } + } + + if (array_key_exists('throwTargetExceptionsOn', $options)) { + $this->setThrowTargetExceptionsOn($options['throwTargetExceptionsOn']); + } + + if (array_key_exists('targetReplacementIdentifier', $options)) { + $this->setTargetReplacementIdentifier($options['targetReplacementIdentifier']); + } + + if (array_key_exists('target', $options)) { + $this->setTarget($options['target']); + } + + if (array_key_exists('rules', $options)) { + $this->addRules($options['rules']); + } + + return $this; + } + + /** + * Convienence method to add prefix and path to PluginLoader + * + * @param string $prefix + * @param string $path + * @return Zend_Filter_Inflector + */ + public function addFilterPrefixPath($prefix, $path) + { + $this->getPluginLoader()->addPrefixPath($prefix, $path); + return $this; + } + + /** + * Set Whether or not the inflector should throw an exception when a replacement + * identifier is still found within an inflected target. + * + * @param bool $throwTargetExceptions + * @return Zend_Filter_Inflector + */ + public function setThrowTargetExceptionsOn($throwTargetExceptionsOn) + { + $this->_throwTargetExceptionsOn = ($throwTargetExceptionsOn == true) ? true : false; + return $this; + } + + /** + * Will exceptions be thrown? + * + * @return bool + */ + public function isThrowTargetExceptionsOn() + { + return $this->_throwTargetExceptionsOn; + } + + /** + * Set the Target Replacement Identifier, by default ':' + * + * @param string $targetReplacementIdentifier + * @return Zend_Filter_Inflector + */ + public function setTargetReplacementIdentifier($targetReplacementIdentifier) + { + if ($targetReplacementIdentifier) { + $this->_targetReplacementIdentifier = (string) $targetReplacementIdentifier; + } + + return $this; + } + + /** + * Get Target Replacement Identifier + * + * @return string + */ + public function getTargetReplacementIdentifier() + { + return $this->_targetReplacementIdentifier; + } + + /** + * Set a Target + * ex: 'scripts/:controller/:action.:suffix' + * + * @param string + * @return Zend_Filter_Inflector + */ + public function setTarget($target) + { + $this->_target = (string) $target; + return $this; + } + + /** + * Retrieve target + * + * @return string + */ + public function getTarget() + { + return $this->_target; + } + + /** + * Set Target Reference + * + * @param reference $target + * @return Zend_Filter_Inflector + */ + public function setTargetReference(&$target) + { + $this->_target =& $target; + return $this; + } + + /** + * SetRules() is the same as calling addRules() with the exception that it + * clears the rules before adding them. + * + * @param array $rules + * @return Zend_Filter_Inflector + */ + public function setRules(Array $rules) + { + $this->clearRules(); + $this->addRules($rules); + return $this; + } + + /** + * AddRules(): multi-call to setting filter rules. + * + * If prefixed with a ":" (colon), a filter rule will be added. If not + * prefixed, a static replacement will be added. + * + * ex: + * array( + * ':controller' => array('CamelCaseToUnderscore','StringToLower'), + * ':action' => array('CamelCaseToUnderscore','StringToLower'), + * 'suffix' => 'phtml' + * ); + * + * @param array + * @return Zend_Filter_Inflector + */ + public function addRules(Array $rules) + { + $keys = array_keys($rules); + foreach ($keys as $spec) { + if ($spec[0] == ':') { + $this->addFilterRule($spec, $rules[$spec]); + } else { + $this->setStaticRule($spec, $rules[$spec]); + } + } + + return $this; + } + + /** + * Get rules + * + * By default, returns all rules. If a $spec is provided, will return those + * rules if found, false otherwise. + * + * @param string $spec + * @return array|false + */ + public function getRules($spec = null) + { + if (null !== $spec) { + $spec = $this->_normalizeSpec($spec); + if (isset($this->_rules[$spec])) { + return $this->_rules[$spec]; + } + return false; + } + + return $this->_rules; + } + + /** + * getRule() returns a rule set by setFilterRule(), a numeric index must be provided + * + * @param string $spec + * @param int $index + * @return Zend_Filter_Interface|false + */ + public function getRule($spec, $index) + { + $spec = $this->_normalizeSpec($spec); + if (isset($this->_rules[$spec]) && is_array($this->_rules[$spec])) { + if (isset($this->_rules[$spec][$index])) { + return $this->_rules[$spec][$index]; + } + } + return false; + } + + /** + * ClearRules() clears the rules currently in the inflector + * + * @return Zend_Filter_Inflector + */ + public function clearRules() + { + $this->_rules = array(); + return $this; + } + + /** + * Set a filtering rule for a spec. $ruleSet can be a string, Filter object + * or an array of strings or filter objects. + * + * @param string $spec + * @param array|string|Zend_Filter_Interface $ruleSet + * @return Zend_Filter_Inflector + */ + public function setFilterRule($spec, $ruleSet) + { + $spec = $this->_normalizeSpec($spec); + $this->_rules[$spec] = array(); + return $this->addFilterRule($spec, $ruleSet); + } + + /** + * Add a filter rule for a spec + * + * @param mixed $spec + * @param mixed $ruleSet + * @return void + */ + public function addFilterRule($spec, $ruleSet) + { + $spec = $this->_normalizeSpec($spec); + if (!isset($this->_rules[$spec])) { + $this->_rules[$spec] = array(); + } + + if (!is_array($ruleSet)) { + $ruleSet = array($ruleSet); + } + + if (is_string($this->_rules[$spec])) { + $temp = $this->_rules[$spec]; + $this->_rules[$spec] = array(); + $this->_rules[$spec][] = $temp; + } + + foreach ($ruleSet as $rule) { + $this->_rules[$spec][] = $this->_getRule($rule); + } + + return $this; + } + + /** + * Set a static rule for a spec. This is a single string value + * + * @param string $name + * @param string $value + * @return Zend_Filter_Inflector + */ + public function setStaticRule($name, $value) + { + $name = $this->_normalizeSpec($name); + $this->_rules[$name] = (string) $value; + return $this; + } + + /** + * Set Static Rule Reference. + * + * This allows a consuming class to pass a property or variable + * in to be referenced when its time to build the output string from the + * target. + * + * @param string $name + * @param mixed $reference + * @return Zend_Filter_Inflector + */ + public function setStaticRuleReference($name, &$reference) + { + $name = $this->_normalizeSpec($name); + $this->_rules[$name] =& $reference; + return $this; + } + + /** + * Inflect + * + * @param string|array $source + * @return string + */ + public function filter($source) + { + // clean source + foreach ( (array) $source as $sourceName => $sourceValue) { + $source[ltrim($sourceName, ':')] = $sourceValue; + } + + $pregQuotedTargetReplacementIdentifier = preg_quote($this->_targetReplacementIdentifier, '#'); + $processedParts = array(); + + foreach ($this->_rules as $ruleName => $ruleValue) { + if (isset($source[$ruleName])) { + if (is_string($ruleValue)) { + // overriding the set rule + $processedParts['#'.$pregQuotedTargetReplacementIdentifier.$ruleName.'#'] = str_replace('\\', '\\\\', $source[$ruleName]); + } elseif (is_array($ruleValue)) { + $processedPart = $source[$ruleName]; + foreach ($ruleValue as $ruleFilter) { + $processedPart = $ruleFilter->filter($processedPart); + } + $processedParts['#'.$pregQuotedTargetReplacementIdentifier.$ruleName.'#'] = str_replace('\\', '\\\\', $processedPart); + } + } elseif (is_string($ruleValue)) { + $processedParts['#'.$pregQuotedTargetReplacementIdentifier.$ruleName.'#'] = str_replace('\\', '\\\\', $ruleValue); + } + } + + // all of the values of processedParts would have been str_replace('\\', '\\\\', ..)'d to disable preg_replace backreferences + $inflectedTarget = preg_replace(array_keys($processedParts), array_values($processedParts), $this->_target); + + if ($this->_throwTargetExceptionsOn && (preg_match('#(?='.$pregQuotedTargetReplacementIdentifier.'[A-Za-z]{1})#', $inflectedTarget) == true)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('A replacement identifier ' . $this->_targetReplacementIdentifier . ' was found inside the inflected target, perhaps a rule was not satisfied with a target source? Unsatisfied inflected target: ' . $inflectedTarget); + } + + return $inflectedTarget; + } + + /** + * Normalize spec string + * + * @param string $spec + * @return string + */ + protected function _normalizeSpec($spec) + { + return ltrim((string) $spec, ':&'); + } + + /** + * Resolve named filters and convert them to filter objects. + * + * @param string $rule + * @return Zend_Filter_Interface + */ + protected function _getRule($rule) + { + if ($rule instanceof Zend_Filter_Interface) { + return $rule; + } + + $rule = (string) $rule; + + $className = $this->getPluginLoader()->load($rule); + $ruleObject = new $className(); + if (!$ruleObject instanceof Zend_Filter_Interface) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('No class named ' . $rule . ' implementing Zend_Filter_Interface could be found'); + } + + return $ruleObject; + } +} diff --git a/lib/zend/Zend/Filter/Input.php b/lib/zend/Zend/Filter/Input.php new file mode 100644 index 00000000000..c3229fa6fb4 --- /dev/null +++ b/lib/zend/Zend/Filter/Input.php @@ -0,0 +1,1209 @@ + false, + self::BREAK_CHAIN => false, + self::ESCAPE_FILTER => 'HtmlEntities', + self::MISSING_MESSAGE => "Field '%field%' is required by rule '%rule%', but the field is missing", + self::NOT_EMPTY_MESSAGE => "You must give a non-empty value for field '%field%'", + self::PRESENCE => self::PRESENCE_OPTIONAL + ); + + /** + * @var boolean Set to False initially, this is set to True after the + * input data have been processed. Reset to False in setData() method. + */ + protected $_processed = false; + + /** + * Translation object + * @var Zend_Translate + */ + protected $_translator; + + /** + * Is translation disabled? + * @var Boolean + */ + protected $_translatorDisabled = false; + + /** + * @param array $filterRules + * @param array $validatorRules + * @param array $data OPTIONAL + * @param array $options OPTIONAL + */ + public function __construct($filterRules, $validatorRules, array $data = null, array $options = null) + { + if ($options) { + $this->setOptions($options); + } + + $this->_filterRules = (array) $filterRules; + $this->_validatorRules = (array) $validatorRules; + + if ($data) { + $this->setData($data); + } + } + + /** + * @param mixed $namespaces + * @return Zend_Filter_Input + * @deprecated since 1.5.0RC1 - use addFilterPrefixPath() or addValidatorPrefixPath instead. + */ + public function addNamespace($namespaces) + { + if (!is_array($namespaces)) { + $namespaces = array($namespaces); + } + + foreach ($namespaces as $namespace) { + $prefix = $namespace; + $path = str_replace('_', DIRECTORY_SEPARATOR, $prefix); + $this->addFilterPrefixPath($prefix, $path); + $this->addValidatorPrefixPath($prefix, $path); + } + + return $this; + } + + /** + * Add prefix path for all elements + * + * @param string $prefix + * @param string $path + * @return Zend_Filter_Input + */ + public function addFilterPrefixPath($prefix, $path) + { + $this->getPluginLoader(self::FILTER)->addPrefixPath($prefix, $path); + + return $this; + } + + /** + * Add prefix path for all elements + * + * @param string $prefix + * @param string $path + * @return Zend_Filter_Input + */ + public function addValidatorPrefixPath($prefix, $path) + { + $this->getPluginLoader(self::VALIDATE)->addPrefixPath($prefix, $path); + + return $this; + } + + /** + * Set plugin loaders for use with decorators and elements + * + * @param Zend_Loader_PluginLoader_Interface $loader + * @param string $type 'filter' or 'validate' + * @return Zend_Filter_Input + * @throws Zend_Filter_Exception on invalid type + */ + public function setPluginLoader(Zend_Loader_PluginLoader_Interface $loader, $type) + { + $type = strtolower($type); + switch ($type) { + case self::FILTER: + case self::VALIDATE: + $this->_loaders[$type] = $loader; + return $this; + default: + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception(sprintf('Invalid type "%s" provided to setPluginLoader()', $type)); + } + + return $this; + } + + /** + * Retrieve plugin loader for given type + * + * $type may be one of: + * - filter + * - validator + * + * If a plugin loader does not exist for the given type, defaults are + * created. + * + * @param string $type 'filter' or 'validate' + * @return Zend_Loader_PluginLoader_Interface + * @throws Zend_Filter_Exception on invalid type + */ + public function getPluginLoader($type) + { + $type = strtolower($type); + if (!isset($this->_loaders[$type])) { + switch ($type) { + case self::FILTER: + $prefixSegment = 'Zend_Filter_'; + $pathSegment = 'Zend/Filter/'; + break; + case self::VALIDATE: + $prefixSegment = 'Zend_Validate_'; + $pathSegment = 'Zend/Validate/'; + break; + default: + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception(sprintf('Invalid type "%s" provided to getPluginLoader()', $type)); + } + + require_once 'Zend/Loader/PluginLoader.php'; + $this->_loaders[$type] = new Zend_Loader_PluginLoader( + array($prefixSegment => $pathSegment) + ); + } + + return $this->_loaders[$type]; + } + + /** + * @return array + */ + public function getMessages() + { + $this->_process(); + return array_merge($this->_invalidMessages, $this->_missingFields); + } + + /** + * @return array + */ + public function getErrors() + { + $this->_process(); + return $this->_invalidErrors; + } + + /** + * @return array + */ + public function getInvalid() + { + $this->_process(); + return $this->_invalidMessages; + } + + /** + * @return array + */ + public function getMissing() + { + $this->_process(); + return $this->_missingFields; + } + + /** + * @return array + */ + public function getUnknown() + { + $this->_process(); + return $this->_unknownFields; + } + + /** + * @param string $fieldName OPTIONAL + * @return mixed + */ + public function getEscaped($fieldName = null) + { + $this->_process(); + $this->_getDefaultEscapeFilter(); + + if ($fieldName === null) { + return $this->_escapeRecursive($this->_validFields); + } + if (array_key_exists($fieldName, $this->_validFields)) { + return $this->_escapeRecursive($this->_validFields[$fieldName]); + } + return null; + } + + /** + * @param mixed $value + * @return mixed + */ + protected function _escapeRecursive($data) + { + if($data === null) { + return $data; + } + + if (!is_array($data)) { + return $this->_getDefaultEscapeFilter()->filter($data); + } + foreach ($data as &$element) { + $element = $this->_escapeRecursive($element); + } + return $data; + } + + /** + * @param string $fieldName OPTIONAL + * @return mixed + */ + public function getUnescaped($fieldName = null) + { + $this->_process(); + if ($fieldName === null) { + return $this->_validFields; + } + if (array_key_exists($fieldName, $this->_validFields)) { + return $this->_validFields[$fieldName]; + } + return null; + } + + /** + * @param string $fieldName + * @return mixed + */ + public function __get($fieldName) + { + return $this->getEscaped($fieldName); + } + + /** + * @return boolean + */ + public function hasInvalid() + { + $this->_process(); + return !(empty($this->_invalidMessages)); + } + + /** + * @return boolean + */ + public function hasMissing() + { + $this->_process(); + return !(empty($this->_missingFields)); + } + + /** + * @return boolean + */ + public function hasUnknown() + { + $this->_process(); + return !(empty($this->_unknownFields)); + } + + /** + * @return boolean + */ + public function hasValid() + { + $this->_process(); + return !(empty($this->_validFields)); + } + + /** + * @param string $fieldName + * @return boolean + */ + public function isValid($fieldName = null) + { + $this->_process(); + if ($fieldName === null) { + return !($this->hasMissing() || $this->hasInvalid()); + } + return array_key_exists($fieldName, $this->_validFields); + } + + /** + * @param string $fieldName + * @return boolean + */ + public function __isset($fieldName) + { + $this->_process(); + return isset($this->_validFields[$fieldName]); + } + + /** + * @return Zend_Filter_Input + * @throws Zend_Filter_Exception + */ + public function process() + { + $this->_process(); + if ($this->hasInvalid()) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("Input has invalid fields"); + } + if ($this->hasMissing()) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("Input has missing fields"); + } + + return $this; + } + + /** + * @param array $data + * @return Zend_Filter_Input + */ + public function setData(array $data) + { + $this->_data = $data; + + /** + * Reset to initial state + */ + $this->_validFields = array(); + $this->_invalidMessages = array(); + $this->_invalidErrors = array(); + $this->_missingFields = array(); + $this->_unknownFields = array(); + + $this->_processed = false; + + return $this; + } + + /** + * @param mixed $escapeFilter + * @return Zend_Filter_Interface + */ + public function setDefaultEscapeFilter($escapeFilter) + { + if (is_string($escapeFilter) || is_array($escapeFilter)) { + $escapeFilter = $this->_getFilter($escapeFilter); + } + if (!$escapeFilter instanceof Zend_Filter_Interface) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('Escape filter specified does not implement Zend_Filter_Interface'); + } + $this->_defaultEscapeFilter = $escapeFilter; + return $escapeFilter; + } + + /** + * @param array $options + * @return Zend_Filter_Input + * @throws Zend_Filter_Exception if an unknown option is given + */ + public function setOptions(array $options) + { + foreach ($options as $option => $value) { + switch ($option) { + case self::ESCAPE_FILTER: + $this->setDefaultEscapeFilter($value); + break; + case self::INPUT_NAMESPACE: + $this->addNamespace($value); + break; + case self::VALIDATOR_NAMESPACE: + if(is_string($value)) { + $value = array($value); + } + + foreach($value AS $prefix) { + $this->addValidatorPrefixPath( + $prefix, + str_replace('_', DIRECTORY_SEPARATOR, $prefix) + ); + } + break; + case self::FILTER_NAMESPACE: + if(is_string($value)) { + $value = array($value); + } + + foreach($value AS $prefix) { + $this->addFilterPrefixPath( + $prefix, + str_replace('_', DIRECTORY_SEPARATOR, $prefix) + ); + } + break; + case self::ALLOW_EMPTY: + case self::BREAK_CHAIN: + case self::MISSING_MESSAGE: + case self::NOT_EMPTY_MESSAGE: + case self::PRESENCE: + $this->_defaults[$option] = $value; + break; + default: + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("Unknown option '$option'"); + break; + } + } + + return $this; + } + + /** + * Set translation object + * + * @param Zend_Translate|Zend_Translate_Adapter|null $translator + * @return Zend_Filter_Input + */ + public function setTranslator($translator = null) + { + if ((null === $translator) || ($translator instanceof Zend_Translate_Adapter)) { + $this->_translator = $translator; + } elseif ($translator instanceof Zend_Translate) { + $this->_translator = $translator->getAdapter(); + } else { + require_once 'Zend/Validate/Exception.php'; + throw new Zend_Validate_Exception('Invalid translator specified'); + } + + return $this; + } + + /** + * Return translation object + * + * @return Zend_Translate_Adapter|null + */ + public function getTranslator() + { + if ($this->translatorIsDisabled()) { + return null; + } + + if ($this->_translator === null) { + require_once 'Zend/Registry.php'; + if (Zend_Registry::isRegistered('Zend_Translate')) { + $translator = Zend_Registry::get('Zend_Translate'); + if ($translator instanceof Zend_Translate_Adapter) { + return $translator; + } elseif ($translator instanceof Zend_Translate) { + return $translator->getAdapter(); + } + } + } + + return $this->_translator; + } + + /** + * Indicate whether or not translation should be disabled + * + * @param bool $flag + * @return Zend_Filter_Input + */ + public function setDisableTranslator($flag) + { + $this->_translatorDisabled = (bool) $flag; + return $this; + } + + /** + * Is translation disabled? + * + * @return bool + */ + public function translatorIsDisabled() + { + return $this->_translatorDisabled; + } + + /* + * Protected methods + */ + + /** + * @return void + */ + protected function _filter() + { + foreach ($this->_filterRules as $ruleName => &$filterRule) { + /** + * Make sure we have an array representing this filter chain. + * Don't typecast to (array) because it might be a Zend_Filter object + */ + if (!is_array($filterRule)) { + $filterRule = array($filterRule); + } + + /** + * Filters are indexed by integer, metacommands are indexed by string. + * Pick out the filters. + */ + $filterList = array(); + foreach ($filterRule as $key => $value) { + if (is_int($key)) { + $filterList[] = $value; + } + } + + /** + * Use defaults for filter metacommands. + */ + $filterRule[self::RULE] = $ruleName; + if (!isset($filterRule[self::FIELDS])) { + $filterRule[self::FIELDS] = $ruleName; + } + + /** + * Load all the filter classes and add them to the chain. + */ + if (!isset($filterRule[self::FILTER_CHAIN])) { + $filterRule[self::FILTER_CHAIN] = new Zend_Filter(); + foreach ($filterList as $filter) { + if (is_string($filter) || is_array($filter)) { + $filter = $this->_getFilter($filter); + } + $filterRule[self::FILTER_CHAIN]->addFilter($filter); + } + } + + /** + * If the ruleName is the special wildcard rule, + * then apply the filter chain to all input data. + * Else just process the field named by the rule. + */ + if ($ruleName == self::RULE_WILDCARD) { + foreach (array_keys($this->_data) as $field) { + $this->_filterRule(array_merge($filterRule, array(self::FIELDS => $field))); + } + } else { + $this->_filterRule($filterRule); + } + } + } + + /** + * @param array $filterRule + * @return void + */ + protected function _filterRule(array $filterRule) + { + $field = $filterRule[self::FIELDS]; + if (!array_key_exists($field, $this->_data)) { + return; + } + if (is_array($this->_data[$field])) { + foreach ($this->_data[$field] as $key => $value) { + $this->_data[$field][$key] = $filterRule[self::FILTER_CHAIN]->filter($value); + } + } else { + $this->_data[$field] = + $filterRule[self::FILTER_CHAIN]->filter($this->_data[$field]); + } + } + + /** + * @return Zend_Filter_Interface + */ + protected function _getDefaultEscapeFilter() + { + if ($this->_defaultEscapeFilter !== null) { + return $this->_defaultEscapeFilter; + } + return $this->setDefaultEscapeFilter($this->_defaults[self::ESCAPE_FILTER]); + } + + /** + * @param string $rule + * @param string $field + * @return string + */ + protected function _getMissingMessage($rule, $field) + { + $message = $this->_defaults[self::MISSING_MESSAGE]; + + if (null !== ($translator = $this->getTranslator())) { + if ($translator->isTranslated(self::MISSING_MESSAGE)) { + $message = $translator->translate(self::MISSING_MESSAGE); + } else { + $message = $translator->translate($message); + } + } + + $message = str_replace('%rule%', $rule, $message); + $message = str_replace('%field%', $field, $message); + return $message; + } + + /** + * @return string + */ + protected function _getNotEmptyMessage($rule, $field) + { + $message = $this->_defaults[self::NOT_EMPTY_MESSAGE]; + + if (null !== ($translator = $this->getTranslator())) { + if ($translator->isTranslated(self::NOT_EMPTY_MESSAGE)) { + $message = $translator->translate(self::NOT_EMPTY_MESSAGE); + } else { + $message = $translator->translate($message); + } + } + + $message = str_replace('%rule%', $rule, $message); + $message = str_replace('%field%', $field, $message); + return $message; + } + + /** + * @return void + */ + protected function _process() + { + if ($this->_processed === false) { + $this->_filter(); + $this->_validate(); + $this->_processed = true; + } + } + + /** + * @return void + */ + protected function _validate() + { + /** + * Special case: if there are no validators, treat all fields as valid. + */ + if (!$this->_validatorRules) { + $this->_validFields = $this->_data; + $this->_data = array(); + return; + } + + // remember the default not empty message in case we want to temporarily change it + $preserveDefaultNotEmptyMessage = $this->_defaults[self::NOT_EMPTY_MESSAGE]; + + foreach ($this->_validatorRules as $ruleName => &$validatorRule) { + /** + * Make sure we have an array representing this validator chain. + * Don't typecast to (array) because it might be a Zend_Validate object + */ + if (!is_array($validatorRule)) { + $validatorRule = array($validatorRule); + } + + /** + * Validators are indexed by integer, metacommands are indexed by string. + * Pick out the validators. + */ + $validatorList = array(); + foreach ($validatorRule as $key => $value) { + if (is_int($key)) { + $validatorList[$key] = $value; + } + } + + /** + * Use defaults for validation metacommands. + */ + $validatorRule[self::RULE] = $ruleName; + if (!isset($validatorRule[self::FIELDS])) { + $validatorRule[self::FIELDS] = $ruleName; + } + if (!isset($validatorRule[self::BREAK_CHAIN])) { + $validatorRule[self::BREAK_CHAIN] = $this->_defaults[self::BREAK_CHAIN]; + } + if (!isset($validatorRule[self::PRESENCE])) { + $validatorRule[self::PRESENCE] = $this->_defaults[self::PRESENCE]; + } + if (!isset($validatorRule[self::ALLOW_EMPTY])) { + $foundNotEmptyValidator = false; + + foreach ($validatorRule as $rule) { + if ($rule === 'NotEmpty') { + $foundNotEmptyValidator = true; + // field may not be empty, we are ready + break 1; + } + + if (is_array($rule)) { + $keys = array_keys($rule); + $classKey = array_shift($keys); + if (isset($rule[$classKey])) { + $ruleClass = $rule[$classKey]; + if ($ruleClass === 'NotEmpty') { + $foundNotEmptyValidator = true; + // field may not be empty, we are ready + break 1; + } + } + } + + // we must check if it is an object before using instanceof + if (!is_object($rule)) { + // it cannot be a NotEmpty validator, skip this one + continue; + } + + if($rule instanceof Zend_Validate_NotEmpty) { + $foundNotEmptyValidator = true; + // field may not be empty, we are ready + break 1; + } + } + + if (!$foundNotEmptyValidator) { + $validatorRule[self::ALLOW_EMPTY] = $this->_defaults[self::ALLOW_EMPTY]; + } else { + $validatorRule[self::ALLOW_EMPTY] = false; + } + } + + if (!isset($validatorRule[self::MESSAGES])) { + $validatorRule[self::MESSAGES] = array(); + } else if (!is_array($validatorRule[self::MESSAGES])) { + $validatorRule[self::MESSAGES] = array($validatorRule[self::MESSAGES]); + } else if (array_intersect_key($validatorList, $validatorRule[self::MESSAGES])) { + // this seems pointless... it just re-adds what it already has... + // I can disable all this and not a single unit test fails... + // There are now corresponding numeric keys in the validation rule messages array + // Treat it as a named messages list for all rule validators + $unifiedMessages = $validatorRule[self::MESSAGES]; + $validatorRule[self::MESSAGES] = array(); + + foreach ($validatorList as $key => $validator) { + if (array_key_exists($key, $unifiedMessages)) { + $validatorRule[self::MESSAGES][$key] = $unifiedMessages[$key]; + } + } + } + + /** + * Load all the validator classes and add them to the chain. + */ + if (!isset($validatorRule[self::VALIDATOR_CHAIN])) { + $validatorRule[self::VALIDATOR_CHAIN] = new Zend_Validate(); + + foreach ($validatorList as $key => $validator) { + if (is_string($validator) || is_array($validator)) { + $validator = $this->_getValidator($validator); + } + + if (isset($validatorRule[self::MESSAGES][$key])) { + $value = $validatorRule[self::MESSAGES][$key]; + if (is_array($value)) { + $validator->setMessages($value); + } else { + $validator->setMessage($value); + } + + if ($validator instanceof Zend_Validate_NotEmpty) { + /** we are changing the defaults here, this is alright if all subsequent validators are also a not empty + * validator, but it goes wrong if one of them is not AND is required!!! + * that is why we restore the default value at the end of this loop + */ + if (is_array($value)) { + $temp = $value; // keep the original value + $this->_defaults[self::NOT_EMPTY_MESSAGE] = array_pop($temp); + unset($temp); + } else { + $this->_defaults[self::NOT_EMPTY_MESSAGE] = $value; + } + } + } + + $validatorRule[self::VALIDATOR_CHAIN]->addValidator($validator, $validatorRule[self::BREAK_CHAIN]); + } + $validatorRule[self::VALIDATOR_CHAIN_COUNT] = count($validatorList); + } + + /** + * If the ruleName is the special wildcard rule, + * then apply the validator chain to all input data. + * Else just process the field named by the rule. + */ + if ($ruleName == self::RULE_WILDCARD) { + foreach (array_keys($this->_data) as $field) { + $this->_validateRule(array_merge($validatorRule, array(self::FIELDS => $field))); + } + } else { + $this->_validateRule($validatorRule); + } + + // reset the default not empty message + $this->_defaults[self::NOT_EMPTY_MESSAGE] = $preserveDefaultNotEmptyMessage; + } + + + + /** + * Unset fields in $_data that have been added to other arrays. + * We have to wait until all rules have been processed because + * a given field may be referenced by multiple rules. + */ + foreach (array_merge(array_keys($this->_missingFields), array_keys($this->_invalidMessages)) as $rule) { + foreach ((array) $this->_validatorRules[$rule][self::FIELDS] as $field) { + unset($this->_data[$field]); + } + } + foreach ($this->_validFields as $field => $value) { + unset($this->_data[$field]); + } + + /** + * Anything left over in $_data is an unknown field. + */ + $this->_unknownFields = $this->_data; + } + + /** + * @param array $validatorRule + * @return void + */ + protected function _validateRule(array $validatorRule) + { + /** + * Get one or more data values from input, and check for missing fields. + * Apply defaults if fields are missing. + */ + $data = array(); + foreach ((array) $validatorRule[self::FIELDS] as $key => $field) { + if (array_key_exists($field, $this->_data)) { + $data[$field] = $this->_data[$field]; + } else if (isset($validatorRule[self::DEFAULT_VALUE])) { + /** @todo according to this code default value can't be an array. It has to be reviewed */ + if (!is_array($validatorRule[self::DEFAULT_VALUE])) { + // Default value is a scalar + $data[$field] = $validatorRule[self::DEFAULT_VALUE]; + } else { + // Default value is an array. Search for corresponding key + if (isset($validatorRule[self::DEFAULT_VALUE][$key])) { + $data[$field] = $validatorRule[self::DEFAULT_VALUE][$key]; + } else if ($validatorRule[self::PRESENCE] == self::PRESENCE_REQUIRED) { + // Default value array is provided, but it doesn't have an entry for current field + // and presence is required + $this->_missingFields[$validatorRule[self::RULE]][] = + $this->_getMissingMessage($validatorRule[self::RULE], $field); + } + } + } else if ($validatorRule[self::PRESENCE] == self::PRESENCE_REQUIRED) { + $this->_missingFields[$validatorRule[self::RULE]][] = + $this->_getMissingMessage($validatorRule[self::RULE], $field); + } + } + + /** + * If any required fields are missing, break the loop. + */ + if (isset($this->_missingFields[$validatorRule[self::RULE]]) && count($this->_missingFields[$validatorRule[self::RULE]]) > 0) { + return; + } + + /** + * Evaluate the inputs against the validator chain. + */ + if (count((array) $validatorRule[self::FIELDS]) > 1) { + if (!$validatorRule[self::ALLOW_EMPTY]) { + $emptyFieldsFound = false; + $errorsList = array(); + $messages = array(); + + foreach ($data as $fieldKey => $field) { + // if there is no Zend_Validate_NotEmpty instance in the rules, we will use the default + if (!($notEmptyValidator = $this->_getNotEmptyValidatorInstance($validatorRule))) { + $notEmptyValidator = $this->_getValidator('NotEmpty'); + $notEmptyValidator->setMessage($this->_getNotEmptyMessage($validatorRule[self::RULE], $fieldKey)); + } + + if (!$notEmptyValidator->isValid($field)) { + foreach ($notEmptyValidator->getMessages() as $messageKey => $message) { + if (!isset($messages[$messageKey])) { + $messages[$messageKey] = $message; + } else { + $messages[] = $message; + } + } + $errorsList[] = $notEmptyValidator->getErrors(); + $emptyFieldsFound = true; + } + } + + if ($emptyFieldsFound) { + $this->_invalidMessages[$validatorRule[self::RULE]] = $messages; + $this->_invalidErrors[$validatorRule[self::RULE]] = array_unique(call_user_func_array('array_merge', $errorsList)); + return; + } + } + + if (!$validatorRule[self::VALIDATOR_CHAIN]->isValid($data)) { + $this->_invalidMessages[$validatorRule[self::RULE]] = $validatorRule[self::VALIDATOR_CHAIN]->getMessages(); + $this->_invalidErrors[$validatorRule[self::RULE]] = $validatorRule[self::VALIDATOR_CHAIN]->getErrors(); + return; + } + } else if (count($data) > 0) { + // $data is actually a one element array + $fieldNames = array_keys($data); + $fieldName = reset($fieldNames); + $field = reset($data); + + $failed = false; + if (!is_array($field)) { + $field = array($field); + } + + // if there is no Zend_Validate_NotEmpty instance in the rules, we will use the default + if (!($notEmptyValidator = $this->_getNotEmptyValidatorInstance($validatorRule))) { + $notEmptyValidator = $this->_getValidator('NotEmpty'); + $notEmptyValidator->setMessage($this->_getNotEmptyMessage($validatorRule[self::RULE], $fieldName)); + } + + if ($validatorRule[self::ALLOW_EMPTY]) { + $validatorChain = $validatorRule[self::VALIDATOR_CHAIN]; + } else { + $validatorChain = new Zend_Validate(); + $validatorChain->addValidator($notEmptyValidator, true /* Always break on failure */); + $validatorChain->addValidator($validatorRule[self::VALIDATOR_CHAIN]); + } + + foreach ($field as $key => $value) { + if ($validatorRule[self::ALLOW_EMPTY] && !$notEmptyValidator->isValid($value)) { + // Field is empty AND it's allowed. Do nothing. + continue; + } + + if (!$validatorChain->isValid($value)) { + if (isset($this->_invalidMessages[$validatorRule[self::RULE]])) { + $collectedMessages = $this->_invalidMessages[$validatorRule[self::RULE]]; + } else { + $collectedMessages = array(); + } + + foreach ($validatorChain->getMessages() as $messageKey => $message) { + if (!isset($collectedMessages[$messageKey])) { + $collectedMessages[$messageKey] = $message; + } else { + $collectedMessages[] = $message; + } + } + + $this->_invalidMessages[$validatorRule[self::RULE]] = $collectedMessages; + if (isset($this->_invalidErrors[$validatorRule[self::RULE]])) { + $this->_invalidErrors[$validatorRule[self::RULE]] = array_merge($this->_invalidErrors[$validatorRule[self::RULE]], + $validatorChain->getErrors()); + } else { + $this->_invalidErrors[$validatorRule[self::RULE]] = $validatorChain->getErrors(); + } + unset($this->_validFields[$fieldName]); + $failed = true; + if ($validatorRule[self::BREAK_CHAIN]) { + return; + } + } + } + if ($failed) { + return; + } + } + + /** + * If we got this far, the inputs for this rule pass validation. + */ + foreach ((array) $validatorRule[self::FIELDS] as $field) { + if (array_key_exists($field, $data)) { + $this->_validFields[$field] = $data[$field]; + } + } + } + + /** + * Check a validatorRule for the presence of a NotEmpty validator instance. + * The purpose is to preserve things like a custom message, that may have been + * set on the validator outside Zend_Filter_Input. + * @param array $validatorRule + * @return mixed false if none is found, Zend_Validate_NotEmpty instance if found + */ + protected function _getNotEmptyValidatorInstance($validatorRule) { + foreach ($validatorRule as $rule => $value) { + if (is_object($value) and $value instanceof Zend_Validate_NotEmpty) { + return $value; + } + } + + return false; + } + + /** + * @param mixed $classBaseName + * @return Zend_Filter_Interface + */ + protected function _getFilter($classBaseName) + { + return $this->_getFilterOrValidator(self::FILTER, $classBaseName); + } + + /** + * @param mixed $classBaseName + * @return Zend_Validate_Interface + */ + protected function _getValidator($classBaseName) + { + return $this->_getFilterOrValidator(self::VALIDATE, $classBaseName); + } + + /** + * @param string $type + * @param mixed $classBaseName + * @return Zend_Filter_Interface|Zend_Validate_Interface + * @throws Zend_Filter_Exception + */ + protected function _getFilterOrValidator($type, $classBaseName) + { + $args = array(); + + if (is_array($classBaseName)) { + $args = $classBaseName; + $classBaseName = array_shift($args); + } + + $interfaceName = 'Zend_' . ucfirst($type) . '_Interface'; + $className = $this->getPluginLoader($type)->load(ucfirst($classBaseName)); + + $class = new ReflectionClass($className); + + if (!$class->implementsInterface($interfaceName)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("Class '$className' based on basename '$classBaseName' must implement the '$interfaceName' interface"); + } + + if ($class->hasMethod('__construct')) { + $object = $class->newInstanceArgs($args); + } else { + $object = $class->newInstance(); + } + + return $object; + } + +} diff --git a/lib/zend/Zend/Service/DeveloperGarden/Request/SmsValidation/GetValidatedNumbers.php b/lib/zend/Zend/Filter/Int.php similarity index 57% rename from lib/zend/Zend/Service/DeveloperGarden/Request/SmsValidation/GetValidatedNumbers.php rename to lib/zend/Zend/Filter/Int.php index b7fff44f88e..ee20702559e 100644 --- a/lib/zend/Zend/Service/DeveloperGarden/Request/SmsValidation/GetValidatedNumbers.php +++ b/lib/zend/Zend/Filter/Int.php @@ -1,4 +1,5 @@ null, + 'date_format' => null, + 'precision' => null + ); + + /** + * Class constructor + * + * @param string|Zend_Locale $locale (Optional) Locale to set + */ + public function __construct($options = null) + { + if ($options instanceof Zend_Config) { + $options = $options->toArray(); + } + + if (null !== $options) { + $this->setOptions($options); + } + } + + /** + * Returns the set options + * + * @return array + */ + public function getOptions() + { + return $this->_options; + } + + /** + * Sets options to use + * + * @param array $options (Optional) Options to use + * @return Zend_Filter_LocalizedToNormalized + */ + public function setOptions(array $options = null) + { + $this->_options = $options + $this->_options; + return $this; + } + + /** + * Defined by Zend_Filter_Interface + * + * Normalizes the given input + * + * @param string $value Value to normalized + * @return string|array The normalized value + */ + public function filter($value) + { + if (Zend_Locale_Format::isNumber($value, $this->_options)) { + return Zend_Locale_Format::getNumber($value, $this->_options); + } else if (($this->_options['date_format'] === null) && (strpos($value, ':') !== false)) { + // Special case, no date format specified, detect time input + return Zend_Locale_Format::getTime($value, $this->_options); + } else if (Zend_Locale_Format::checkDateFormat($value, $this->_options)) { + // Detect date or time input + return Zend_Locale_Format::getDate($value, $this->_options); + } + + return $value; + } +} diff --git a/lib/zend/Zend/Filter/NormalizedToLocalized.php b/lib/zend/Zend/Filter/NormalizedToLocalized.php new file mode 100644 index 00000000000..60dbb9e0657 --- /dev/null +++ b/lib/zend/Zend/Filter/NormalizedToLocalized.php @@ -0,0 +1,111 @@ + null, + 'date_format' => null, + 'precision' => null + ); + + /** + * Class constructor + * + * @param string|Zend_Locale $locale (Optional) Locale to set + */ + public function __construct($options = null) + { + if ($options instanceof Zend_Config) { + $options = $options->toArray(); + } + + if (null !== $options) { + $this->setOptions($options); + } + } + + /** + * Returns the set options + * + * @return array + */ + public function getOptions() + { + return $this->_options; + } + + /** + * Sets options to use + * + * @param array $options (Optional) Options to use + * @return Zend_Filter_LocalizedToNormalized + */ + public function setOptions(array $options = null) + { + $this->_options = $options + $this->_options; + return $this; + } + + /** + * Defined by Zend_Filter_Interface + * + * Normalizes the given input + * + * @param string $value Value to normalized + * @return string|array The normalized value + */ + public function filter($value) + { + if (is_array($value)) { + require_once 'Zend/Date.php'; + $date = new Zend_Date($value, $this->_options['locale']); + return $date->toString($this->_options['date_format']); + } else if ($this->_options['precision'] === 0) { + return Zend_Locale_Format::toInteger($value, $this->_options); + } else if ($this->_options['precision'] === null) { + return Zend_Locale_Format::toFloat($value, $this->_options); + } + + return Zend_Locale_Format::toNumber($value, $this->_options); + } +} diff --git a/lib/zend/Zend/Filter/Null.php b/lib/zend/Zend/Filter/Null.php new file mode 100644 index 00000000000..c7988004160 --- /dev/null +++ b/lib/zend/Zend/Filter/Null.php @@ -0,0 +1,183 @@ + 'boolean', + self::INTEGER => 'integer', + self::EMPTY_ARRAY => 'array', + self::STRING => 'string', + self::ZERO => 'zero', + self::ALL => 'all' + ); + + /** + * Internal type to detect + * + * @var integer + */ + protected $_type = self::ALL; + + /** + * Constructor + * + * @param string|array|Zend_Config $options OPTIONAL + */ + public function __construct($options = null) + { + if ($options instanceof Zend_Config) { + $options = $options->toArray(); + } else if (!is_array($options)) { + $options = func_get_args(); + $temp = array(); + if (!empty($options)) { + $temp = array_shift($options); + } + $options = $temp; + } else if (is_array($options) && array_key_exists('type', $options)) { + $options = $options['type']; + } + + if (!empty($options)) { + $this->setType($options); + } + } + + /** + * Returns the set null types + * + * @return array + */ + public function getType() + { + return $this->_type; + } + + /** + * Set the null types + * + * @param integer|array $type + * @throws Zend_Filter_Exception + * @return Zend_Filter_Null + */ + public function setType($type = null) + { + if (is_array($type)) { + $detected = 0; + foreach($type as $value) { + if (is_int($value)) { + $detected += $value; + } else if (in_array($value, $this->_constants)) { + $detected += array_search($value, $this->_constants); + } + } + + $type = $detected; + } else if (is_string($type)) { + if (in_array($type, $this->_constants)) { + $type = array_search($type, $this->_constants); + } + } + + if (!is_int($type) || ($type < 0) || ($type > self::ALL)) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('Unknown type'); + } + + $this->_type = $type; + return $this; + } + + /** + * Defined by Zend_Filter_Interface + * + * Returns null representation of $value, if value is empty and matches + * types that should be considered null. + * + * @param string $value + * @return string + */ + public function filter($value) + { + $type = $this->getType(); + + // STRING ZERO ('0') + if ($type >= self::ZERO) { + $type -= self::ZERO; + if (is_string($value) && ($value == '0')) { + return null; + } + } + + // STRING ('') + if ($type >= self::STRING) { + $type -= self::STRING; + if (is_string($value) && ($value == '')) { + return null; + } + } + + // EMPTY_ARRAY (array()) + if ($type >= self::EMPTY_ARRAY) { + $type -= self::EMPTY_ARRAY; + if (is_array($value) && ($value == array())) { + return null; + } + } + + // INTEGER (0) + if ($type >= self::INTEGER) { + $type -= self::INTEGER; + if (is_int($value) && ($value == 0)) { + return null; + } + } + + // BOOLEAN (false) + if ($type >= self::BOOLEAN) { + $type -= self::BOOLEAN; + if (is_bool($value) && ($value == false)) { + return null; + } + } + + return $value; + } +} diff --git a/lib/zend/Zend/Filter/PregReplace.php b/lib/zend/Zend/Filter/PregReplace.php new file mode 100644 index 00000000000..7100c3717d8 --- /dev/null +++ b/lib/zend/Zend/Filter/PregReplace.php @@ -0,0 +1,174 @@ + matching pattern + * 'replace' => replace with this + * + * @param string|array $options + * @return void + */ + public function __construct($options = null) + { + if ($options instanceof Zend_Config) { + $options = $options->toArray(); + } else if (!is_array($options)) { + $options = func_get_args(); + $temp = array(); + if (!empty($options)) { + $temp['match'] = array_shift($options); + } + + if (!empty($options)) { + $temp['replace'] = array_shift($options); + } + + $options = $temp; + } + + if (array_key_exists('match', $options)) { + $this->setMatchPattern($options['match']); + } + + if (array_key_exists('replace', $options)) { + $this->setReplacement($options['replace']); + } + } + + /** + * Set the match pattern for the regex being called within filter() + * + * @param mixed $match - same as the first argument of preg_replace + * @return Zend_Filter_PregReplace + */ + public function setMatchPattern($match) + { + $this->_matchPattern = $match; + return $this; + } + + /** + * Get currently set match pattern + * + * @return string + */ + public function getMatchPattern() + { + return $this->_matchPattern; + } + + /** + * Set the Replacement pattern/string for the preg_replace called in filter + * + * @param mixed $replacement - same as the second argument of preg_replace + * @return Zend_Filter_PregReplace + */ + public function setReplacement($replacement) + { + $this->_replacement = $replacement; + return $this; + } + + /** + * Get currently set replacement value + * + * @return string + */ + public function getReplacement() + { + return $this->_replacement; + } + + /** + * Perform regexp replacement as filter + * + * @param string $value + * @return string + */ + public function filter($value) + { + if ($this->_matchPattern == null) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception(get_class($this) . ' does not have a valid MatchPattern set.'); + } + + return preg_replace($this->_matchPattern, $this->_replacement, $value); + } + +} diff --git a/lib/zend/Zend/Filter/RealPath.php b/lib/zend/Zend/Filter/RealPath.php new file mode 100644 index 00000000000..00881de5f52 --- /dev/null +++ b/lib/zend/Zend/Filter/RealPath.php @@ -0,0 +1,134 @@ +setExists($options); + } + + /** + * Returns true if the filtered path must exist + * + * @return boolean + */ + public function getExists() + { + return $this->_exists; + } + + /** + * Sets if the path has to exist + * TRUE when the path must exist + * FALSE when not existing paths can be given + * + * @param boolean|Zend_Config $exists Path must exist + * @return Zend_Filter_RealPath + */ + public function setExists($exists) + { + if ($exists instanceof Zend_Config) { + $exists = $exists->toArray(); + } + + if (is_array($exists)) { + if (isset($exists['exists'])) { + $exists = (boolean) $exists['exists']; + } + } + + $this->_exists = (boolean) $exists; + return $this; + } + + /** + * Defined by Zend_Filter_Interface + * + * Returns realpath($value) + * + * @param string $value + * @return string + */ + public function filter($value) + { + $path = (string) $value; + if ($this->_exists) { + return realpath($path); + } + + $realpath = @realpath($path); + if ($realpath) { + return $realpath; + } + + $drive = ''; + if (substr(PHP_OS, 0, 3) == 'WIN') { + $path = preg_replace('/[\\\\\/]/', DIRECTORY_SEPARATOR, $path); + if (preg_match('/([a-zA-Z]\:)(.*)/', $path, $matches)) { + list($fullMatch, $drive, $path) = $matches; + } else { + $cwd = getcwd(); + $drive = substr($cwd, 0, 2); + if (substr($path, 0, 1) != DIRECTORY_SEPARATOR) { + $path = substr($cwd, 3) . DIRECTORY_SEPARATOR . $path; + } + } + } elseif (substr($path, 0, 1) != DIRECTORY_SEPARATOR) { + $path = getcwd() . DIRECTORY_SEPARATOR . $path; + } + + $stack = array(); + $parts = explode(DIRECTORY_SEPARATOR, $path); + foreach ($parts as $dir) { + if (strlen($dir) && $dir !== '.') { + if ($dir == '..') { + array_pop($stack); + } else { + array_push($stack, $dir); + } + } + } + + return $drive . DIRECTORY_SEPARATOR . implode(DIRECTORY_SEPARATOR, $stack); + } +} diff --git a/lib/zend/Zend/Filter/StringToLower.php b/lib/zend/Zend/Filter/StringToLower.php new file mode 100644 index 00000000000..b208cfe77a1 --- /dev/null +++ b/lib/zend/Zend/Filter/StringToLower.php @@ -0,0 +1,121 @@ +toArray(); + } else if (!is_array($options)) { + $options = func_get_args(); + $temp = array(); + if (!empty($options)) { + $temp['encoding'] = array_shift($options); + } + $options = $temp; + } + + if (!array_key_exists('encoding', $options) && function_exists('mb_internal_encoding')) { + $options['encoding'] = mb_internal_encoding(); + } + + if (array_key_exists('encoding', $options)) { + $this->setEncoding($options['encoding']); + } + } + + /** + * Returns the set encoding + * + * @return string + */ + public function getEncoding() + { + return $this->_encoding; + } + + /** + * Set the input encoding for the given string + * + * @param string $encoding + * @return Zend_Filter_StringToLower Provides a fluent interface + * @throws Zend_Filter_Exception + */ + public function setEncoding($encoding = null) + { + if ($encoding !== null) { + if (!function_exists('mb_strtolower')) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('mbstring is required for this feature'); + } + + $encoding = (string) $encoding; + if (!in_array(strtolower($encoding), array_map('strtolower', mb_list_encodings()))) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("The given encoding '$encoding' is not supported by mbstring"); + } + } + + $this->_encoding = $encoding; + return $this; + } + + /** + * Defined by Zend_Filter_Interface + * + * Returns the string $value, converting characters to lowercase as necessary + * + * @param string $value + * @return string + */ + public function filter($value) + { + if ($this->_encoding !== null) { + return mb_strtolower((string) $value, $this->_encoding); + } + + return strtolower((string) $value); + } +} diff --git a/lib/zend/Zend/Filter/StringToUpper.php b/lib/zend/Zend/Filter/StringToUpper.php new file mode 100644 index 00000000000..8fe362055f2 --- /dev/null +++ b/lib/zend/Zend/Filter/StringToUpper.php @@ -0,0 +1,121 @@ +toArray(); + } else if (!is_array($options)) { + $options = func_get_args(); + $temp = array(); + if (!empty($options)) { + $temp['encoding'] = array_shift($options); + } + $options = $temp; + } + + if (!array_key_exists('encoding', $options) && function_exists('mb_internal_encoding')) { + $options['encoding'] = mb_internal_encoding(); + } + + if (array_key_exists('encoding', $options)) { + $this->setEncoding($options['encoding']); + } + } + + /** + * Returns the set encoding + * + * @return string + */ + public function getEncoding() + { + return $this->_encoding; + } + + /** + * Set the input encoding for the given string + * + * @param string $encoding + * @return Zend_Filter_StringToUpper Provides a fluent interface + * @throws Zend_Filter_Exception + */ + public function setEncoding($encoding = null) + { + if ($encoding !== null) { + if (!function_exists('mb_strtoupper')) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception('mbstring is required for this feature'); + } + + $encoding = (string) $encoding; + if (!in_array(strtolower($encoding), array_map('strtolower', mb_list_encodings()))) { + require_once 'Zend/Filter/Exception.php'; + throw new Zend_Filter_Exception("The given encoding '$encoding' is not supported by mbstring"); + } + } + + $this->_encoding = $encoding; + return $this; + } + + /** + * Defined by Zend_Filter_Interface + * + * Returns the string $value, converting characters to uppercase as necessary + * + * @param string $value + * @return string + */ + public function filter($value) + { + if ($this->_encoding) { + return mb_strtoupper((string) $value, $this->_encoding); + } + + return strtoupper((string) $value); + } +} diff --git a/lib/zend/Zend/Filter/StringTrim.php b/lib/zend/Zend/Filter/StringTrim.php new file mode 100644 index 00000000000..4f86d89e2c0 --- /dev/null +++ b/lib/zend/Zend/Filter/StringTrim.php @@ -0,0 +1,124 @@ +toArray(); + } else if (!is_array($options)) { + $options = func_get_args(); + $temp['charlist'] = array_shift($options); + $options = $temp; + } + + if (array_key_exists('charlist', $options)) { + $this->setCharList($options['charlist']); + } + } + + /** + * Returns the charList option + * + * @return string|null + */ + public function getCharList() + { + return $this->_charList; + } + + /** + * Sets the charList option + * + * @param string|null $charList + * @return Zend_Filter_StringTrim Provides a fluent interface + */ + public function setCharList($charList) + { + $this->_charList = $charList; + return $this; + } + + /** + * Defined by Zend_Filter_Interface + * + * Returns the string $value with characters stripped from the beginning and end + * + * @param string $value + * @return string + */ + public function filter($value) + { + if (null === $this->_charList) { + return $this->_unicodeTrim((string) $value); + } else { + return $this->_unicodeTrim((string) $value, $this->_charList); + } + } + + /** + * Unicode aware trim method + * Fixes a PHP problem + * + * @param string $value + * @param string $charlist + * @return string + */ + protected function _unicodeTrim($value, $charlist = '\\\\s') + { + $chars = preg_replace( + array( '/[\^\-\]\\\]/S', '/\\\{4}/S', '/\//'), + array( '\\\\\\0', '\\', '\/' ), + $charlist + ); + + $pattern = '^[' . $chars . ']*|[' . $chars . ']*$'; + return preg_replace("/$pattern/sSD", '', $value); + } +} diff --git a/lib/zend/Zend/Filter/StripNewlines.php b/lib/zend/Zend/Filter/StripNewlines.php new file mode 100644 index 00000000000..667c6aae240 --- /dev/null +++ b/lib/zend/Zend/Filter/StripNewlines.php @@ -0,0 +1,48 @@ + Tags which are allowed + * 'allowAttribs' => Attributes which are allowed + * 'allowComments' => Are comments allowed ? + * + * @param string|array|Zend_Config $options + * @return void + */ + public function __construct($options = null) + { + if ($options instanceof Zend_Config) { + $options = $options->toArray(); + } else if ((!is_array($options)) || (is_array($options) && !array_key_exists('allowTags', $options) && + !array_key_exists('allowAttribs', $options) && !array_key_exists('allowComments', $options))) { + $options = func_get_args(); + $temp['allowTags'] = array_shift($options); + if (!empty($options)) { + $temp['allowAttribs'] = array_shift($options); + } + + if (!empty($options)) { + $temp['allowComments'] = array_shift($options); + } + + $options = $temp; + } + + if (array_key_exists('allowTags', $options)) { + $this->setTagsAllowed($options['allowTags']); + } + + if (array_key_exists('allowAttribs', $options)) { + $this->setAttributesAllowed($options['allowAttribs']); + } + + if (array_key_exists('allowComments', $options)) { + $this->setCommentsAllowed($options['allowComments']); + } + } + + /** + * Returns the commentsAllowed option + * + * This setting is now deprecated and ignored internally. + * + * @deprecated + * @return bool + */ + public function getCommentsAllowed() + { + return $this->commentsAllowed; + } + + /** + * Sets the commentsAllowed option + * + * This setting is now deprecated and ignored internally. + * + * @deprecated + * @param boolean $commentsAllowed + * @return Zend_Filter_StripTags Provides a fluent interface + */ + public function setCommentsAllowed($commentsAllowed) + { + $this->commentsAllowed = (boolean) $commentsAllowed; + return $this; + } + + /** + * Returns the tagsAllowed option + * + * @return array + */ + public function getTagsAllowed() + { + return $this->_tagsAllowed; + } + + /** + * Sets the tagsAllowed option + * + * @param array|string $tagsAllowed + * @return Zend_Filter_StripTags Provides a fluent interface + */ + public function setTagsAllowed($tagsAllowed) + { + if (!is_array($tagsAllowed)) { + $tagsAllowed = array($tagsAllowed); + } + + foreach ($tagsAllowed as $index => $element) { + // If the tag was provided without attributes + if (is_int($index) && is_string($element)) { + // Canonicalize the tag name + $tagName = strtolower($element); + // Store the tag as allowed with no attributes + $this->_tagsAllowed[$tagName] = array(); + } + // Otherwise, if a tag was provided with attributes + else if (is_string($index) && (is_array($element) || is_string($element))) { + // Canonicalize the tag name + $tagName = strtolower($index); + // Canonicalize the attributes + if (is_string($element)) { + $element = array($element); + } + // Store the tag as allowed with the provided attributes + $this->_tagsAllowed[$tagName] = array(); + foreach ($element as $attribute) { + if (is_string($attribute)) { + // Canonicalize the attribute name + $attributeName = strtolower($attribute); + $this->_tagsAllowed[$tagName][$attributeName] = null; + } + } + } + } + + return $this; + } + + /** + * Returns the attributesAllowed option + * + * @return array + */ + public function getAttributesAllowed() + { + return $this->_attributesAllowed; + } + + /** + * Sets the attributesAllowed option + * + * @param array|string $attributesAllowed + * @return Zend_Filter_StripTags Provides a fluent interface + */ + public function setAttributesAllowed($attributesAllowed) + { + if (!is_array($attributesAllowed)) { + $attributesAllowed = array($attributesAllowed); + } + + // Store each attribute as allowed + foreach ($attributesAllowed as $attribute) { + if (is_string($attribute)) { + // Canonicalize the attribute name + $attributeName = strtolower($attribute); + $this->_attributesAllowed[$attributeName] = null; + } + } + + return $this; + } + + /** + * Defined by Zend_Filter_Interface + * + * @todo improve docblock descriptions + * + * @param string $value + * @return string + */ + public function filter($value) + { + $value = (string) $value; + + // Strip HTML comments first + while (strpos($value, ' - diff --git a/lib/zend/Zend/Service/DeveloperGarden/Wsdl/SmsValidationUserService.wsdl b/lib/zend/Zend/Service/DeveloperGarden/Wsdl/SmsValidationUserService.wsdl deleted file mode 100644 index 18c2c7cda7d..00000000000 --- a/lib/zend/Zend/Service/DeveloperGarden/Wsdl/SmsValidationUserService.wsdl +++ /dev/null @@ -1,169 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/zend/Zend/Service/DeveloperGarden/Wsdl/TokenService.wsdl b/lib/zend/Zend/Service/DeveloperGarden/Wsdl/TokenService.wsdl deleted file mode 100644 index 04d03ee45e8..00000000000 --- a/lib/zend/Zend/Service/DeveloperGarden/Wsdl/TokenService.wsdl +++ /dev/null @@ -1,353 +0,0 @@ - - - - - - - - - - - - - - - - Telekom specific format id, e.g. there will be multiple - different token formats derived from SAML 2.0 Assertions - - - - - - - - - - - Telekom specific encoding id - there can be different - encoding formats for the same token format, e.g. SAML - Assertions can be encoded as plain XML or in - base64-encoding - - - - - - - - - - - - - - format of the token carried by the response, - determines syntax and processing rules for token - - - - - - - - encoding of the token carried by the response, - determines syntax and processing rules for token - - - - - - - - contains the string representation of the - security token - no further token format identifier - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - valid SAM Session Id - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/zend/Zend/Service/DeveloperGarden/Wsdl/VoiceButlerService.wsdl b/lib/zend/Zend/Service/DeveloperGarden/Wsdl/VoiceButlerService.wsdl deleted file mode 100644 index c17a50ffd8a..00000000000 --- a/lib/zend/Zend/Service/DeveloperGarden/Wsdl/VoiceButlerService.wsdl +++ /dev/null @@ -1,164 +0,0 @@ - - VoiceButlerService - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/zend/Zend/Service/DeveloperGarden/Wsdl/VoiceButlerService.xsd b/lib/zend/Zend/Service/DeveloperGarden/Wsdl/VoiceButlerService.xsd deleted file mode 100644 index ef724672dd9..00000000000 --- a/lib/zend/Zend/Service/DeveloperGarden/Wsdl/VoiceButlerService.xsd +++ /dev/null @@ -1,264 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/zend/Zend/Service/DeveloperGarden/Wsdl/ccsPort.wsdl b/lib/zend/Zend/Service/DeveloperGarden/Wsdl/ccsPort.wsdl deleted file mode 100644 index 07d9ed9424a..00000000000 --- a/lib/zend/Zend/Service/DeveloperGarden/Wsdl/ccsPort.wsdl +++ /dev/null @@ -1,463 +0,0 @@ - - - -CCS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/zend/Zend/Service/DeveloperGarden/Wsdl/ccsPort.xsd b/lib/zend/Zend/Service/DeveloperGarden/Wsdl/ccsPort.xsd deleted file mode 100644 index d9c30670da0..00000000000 --- a/lib/zend/Zend/Service/DeveloperGarden/Wsdl/ccsPort.xsd +++ /dev/null @@ -1,736 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/zend/Zend/Service/DeveloperGarden/Wsdl/localsearch.wsdl b/lib/zend/Zend/Service/DeveloperGarden/Wsdl/localsearch.wsdl deleted file mode 100644 index 5258bfc7b5a..00000000000 --- a/lib/zend/Zend/Service/DeveloperGarden/Wsdl/localsearch.wsdl +++ /dev/null @@ -1,83 +0,0 @@ - - - -Local Search - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/zend/Zend/Service/DeveloperGarden/Wsdl/localsearch.xsd b/lib/zend/Zend/Service/DeveloperGarden/Wsdl/localsearch.xsd deleted file mode 100644 index 51684be499c..00000000000 --- a/lib/zend/Zend/Service/DeveloperGarden/Wsdl/localsearch.xsd +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/zend/Zend/Service/Ebay/Abstract.php b/lib/zend/Zend/Service/Ebay/Abstract.php new file mode 100644 index 00000000000..640475b33a8 --- /dev/null +++ b/lib/zend/Zend/Service/Ebay/Abstract.php @@ -0,0 +1,309 @@ +setOption($options); + } + + /** + * @param string|Zend_Config|array $name + * @param mixed $value + * @return Zend_Service_Ebay_Abstract Provides a fluent interface + */ + public function setOption($name, $value = null) + { + if ($name instanceof Zend_Config) { + $name = $name->toArray(); + } + if (is_array($name)) { + $this->_options = $name + $this->_options; + } else { + $this->_options[$name] = $value; + } + return $this; + } + + /** + * @param string $name + * @return mixed + */ + public function getOption($name = null) + { + if (null === $name) { + return $this->_options; + } + if ($this->hasOption($name)) { + return $this->_options[$name]; + } + return null; + } + + /** + * @param string $name + * @return boolean + */ + public function hasOption($name) + { + return array_key_exists($name, $this->_options); + } + + /** + * @param mixed $client + * @return Zend_Service_Ebay_Abstract Provides a fluent interface + */ + abstract public function setClient($client); + + /** + * @return mixed + */ + abstract public function getClient(); + + /** + * @param Zend_Config|array $options + * @throws Zend_Service_Ebay_Finding_Exception When $options is not an array neither a Zend_Config object + * @return array + */ + public static function optionsToArray($options) + { + if (null === $options) { + $options = array(); + } else if ($options instanceof Zend_Config) { + $options = $options->toArray(); + } + + if (!is_array($options)) { + /** + * @see Zend_Service_Ebay_Exception + */ + require_once 'Zend/Service/Ebay/Exception.php'; + throw new Zend_Service_Ebay_Exception('Invalid options provided.'); + } + + return $options; + } + + /** + * Implements Name-value Syntax translator. + * + * Example: + * + * array( + * 'paginationInput' => array( + * 'entriesPerPage' => 5, + * 'pageNumber' => 2 + * ), + * 'itemFilter' => array( + * array( + * 'name' => 'MaxPrice', + * 'value' => 25, + * 'paramName' => 'Currency', + * 'paramValue' => 'USD' + * ), + * array( + * 'name' => 'FreeShippingOnly', + * 'value' => true + * ), + * array( + * 'name' => 'ListingType', + * 'value' => array( + * 'AuctionWithBIN', + * 'FixedPrice', + * 'StoreInventory' + * ) + * ) + * ), + * 'productId' => array( + * '' => 123, + * 'type' => 'UPC' + * ) + * ) + * + * this above is translated to + * + * array( + * 'paginationInput.entriesPerPage' => '5', + * 'paginationInput.pageNumber' => '2', + * 'itemFilter(0).name' => 'MaxPrice', + * 'itemFilter(0).value' => '25', + * 'itemFilter(0).paramName' => 'Currency', + * 'itemFilter(0).paramValue' => 'USD', + * 'itemFilter(1).name' => 'FreeShippingOnly', + * 'itemFilter(1).value' => '1', + * 'itemFilter(2).name' => 'ListingType', + * 'itemFilter(2).value(0)' => 'AuctionWithBIN', + * 'itemFilter(2).value(1)' => 'FixedPrice', + * 'itemFilter(2).value(2)' => 'StoreInventory', + * 'productId' => '123', + * 'productId.@type' => 'UPC' + * ) + * + * @param Zend_Config|array $options + * @link http://developer.ebay.com/DevZone/finding/Concepts/MakingACall.html#nvsyntax + * @return array A simple array of strings + */ + protected function _optionsToNameValueSyntax($options) + { + $options = self::optionsToArray($options); + ksort($options); + $new = array(); + $runAgain = false; + foreach ($options as $name => $value) { + if (is_array($value)) { + // parse an array value, check if it is associative + $keyRaw = array_keys($value); + $keyNumber = range(0, count($value) - 1); + $isAssoc = count(array_diff($keyRaw, $keyNumber)) > 0; + // check for tag representation, like + // empty key refers to text value + // when there is a root tag, attributes receive flags + $hasAttribute = array_key_exists('', $value); + foreach ($value as $subName => $subValue) { + // generate new key name + if ($isAssoc) { + // named keys + $newName = $name; + if ($subName !== '') { + // when $subName is empty means that current value + // is the main value for the main key + $glue = $hasAttribute ? '.@' : '.'; + $newName .= $glue . $subName; + } + } else { + // numeric keys + $newName = $name . '(' . $subName . ')'; + } + // save value + if (is_array($subValue)) { + // it is necessary run this again, value is an array + $runAgain = true; + } else { + // parse basic type + $subValue = self::toEbayValue($subValue); + } + $new[$newName] = $subValue; + } + } else { + // parse basic type + $new[$name] = self::toEbayValue($value); + } + } + if ($runAgain) { + // this happens if any $subValue found is an array + $new = $this->_optionsToNameValueSyntax($new); + } + return $new; + } + + /** + * Translate native PHP values format to ebay format for request. + * + * Boolean is translated to "0" or "1", date object generates ISO 8601, + * everything else is translated to string. + * + * @param mixed $value + * @return string + */ + public static function toEbayValue($value) + { + if (is_bool($value)) { + $value = $value ? '1' : '0'; + } else if ($value instanceof Zend_Date) { + $value = $value->getIso(); + } else if ($value instanceof DateTime) { + $value = $value->format(DateTime::ISO8601); + } else { + $value = (string) $value; + } + return $value; + } + + /** + * Translate an ebay value format to native PHP type. + * + * @param string $value + * @param string $type + * @see http://developer.ebay.com/DevZone/finding/CallRef/types/simpleTypes.html + * @throws Zend_Service_Ebay_Finding_Exception When $type is not valid + * @return mixed + */ + public static function toPhpValue($value, $type) + { + switch ($type) { + // cast for: boolean + case 'boolean': + $value = (string) $value == 'true'; + break; + + // cast for: Amount, decimal, double, float, MeasureType + case 'float': + $value = floatval((string) $value); + break; + + // cast for: int, long + // integer type generates a string value, because 32 bit systems + // have an integer range of -2147483648 to 2147483647 + case 'integer': + // break intentionally omitted + + // cast for: anyURI, base64Binary, dateTime, duration, string, token + case 'string': + $value = (string) $value; + break; + + default: + /** + * @see Zend_Service_Ebay_Exception + */ + require_once 'Zend/Service/Ebay/Exception.php'; + throw new Zend_Service_Ebay_Exception("Invalid type '{$type}'."); + } + return $value; + } +} diff --git a/lib/zend/Zend/Service/Technorati/Exception.php b/lib/zend/Zend/Service/Ebay/Exception.php similarity index 71% rename from lib/zend/Zend/Service/Technorati/Exception.php rename to lib/zend/Zend/Service/Ebay/Exception.php index 88a34cd4db7..58577da8a5c 100644 --- a/lib/zend/Zend/Service/Technorati/Exception.php +++ b/lib/zend/Zend/Service/Ebay/Exception.php @@ -14,26 +14,24 @@ * * @category Zend * @package Zend_Service - * @subpackage Technorati - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @subpackage Ebay + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id$ + * @version $Id: Exception.php 20166 2010-01-09 19:00:17Z bkarwin $ */ - /** * @see Zend_Service_Exception */ require_once 'Zend/Service/Exception.php'; - /** * @category Zend * @package Zend_Service - * @subpackage Technorati - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @subpackage Ebay + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License + * @uses Zend_Service_Exception */ -class Zend_Service_Technorati_Exception extends Zend_Service_Exception -{ -} +class Zend_Service_Ebay_Exception extends Zend_Service_Exception +{} diff --git a/lib/zend/Zend/Service/Ebay/Finding.php b/lib/zend/Zend/Service/Ebay/Finding.php new file mode 100644 index 00000000000..a5fd4ae64f5 --- /dev/null +++ b/lib/zend/Zend/Service/Ebay/Finding.php @@ -0,0 +1,424 @@ + 'http://www.ebay.com/marketplace/search/v1/services', + self::XMLNS_MS => 'http://www.ebay.com/marketplace/services' + ); + + /** + * + * @var array + */ + protected $_options = array( + self::OPTION_GLOBAL_ID => 'EBAY-US' + ); + + /** + * @return array + */ + public static function getXmlNamespaces() + { + return self::$_xmlNamespaces; + } + + /** + * @param Zend_Config|array|string $options Application Id or array of options + * @throws Zend_Service_Ebay_Finding_Exception When application id is missing + * @return void + */ + public function __construct($options) + { + // prepare options + if (is_string($options)) { + // application id was given + $options = array(self::OPTION_APP_ID => $options); + } else { + // check application id + $options = parent::optionsToArray($options); + if (!array_key_exists(self::OPTION_APP_ID, $options)) { + /** + * @see Zend_Service_Ebay_Finding_Exception + */ + require_once 'Zend/Service/Ebay/Finding/Exception.php'; + throw new Zend_Service_Ebay_Finding_Exception( + 'Application Id is missing.'); + } + } + + // load options + parent::setOption($options); + } + + /** + * @param Zend_Rest_Client $client + * @return Zend_Service_Ebay_Finding Provides a fluent interface + */ + public function setClient($client) + { + if (!$client instanceof Zend_Rest_Client) { + /** + * @see Zend_Service_Ebay_Finding_Exception + */ + require_once 'Zend/Service/Ebay/Finding/Exception.php'; + throw new Zend_Service_Ebay_Finding_Exception( + 'Client object must extend Zend_Rest_Client.'); + } + $this->_client = $client; + + return $this; + } + + /** + * @return Zend_Rest_Client + */ + public function getClient() + { + if (!$this->_client instanceof Zend_Rest_Client) { + /** + * @see Zend_Rest_Client + */ + require_once 'Zend/Rest/Client.php'; + $this->_client = new Zend_Rest_Client(); + } + return $this->_client; + } + + /** + * Finds items by a keyword query and/or category and allows searching + * within item descriptions. + * + * @param string $keywords + * @param boolean $descriptionSearch + * @param integer $categoryId + * @param Zend_Config|array $options + * @link http://developer.ebay.com/DevZone/finding/CallRef/findItemsAdvanced.html + * @return Zend_Service_Ebay_Finding_Response_Items + */ + public function findItemsAdvanced($keywords, $descriptionSearch = true, $categoryId = null, $options = null) + { + // prepare options + $options = parent::optionsToArray($options); + $options['keywords'] = $keywords; + $options['descriptionSearch'] = $descriptionSearch; + if (!empty($categoryId)) { + $options['categoryId'] = $categoryId; + } + + // do request + return $this->_findItems($options, 'findItemsAdvanced'); + } + + /** + * Finds items in a specific category. Results can be filtered and sorted. + * + * @param integer $categoryId + * @param Zend_Config|array $options + * @link http://developer.ebay.com/DevZone/finding/CallRef/findItemsByCategory.html + * @return Zend_Service_Ebay_Finding_Response_Items + */ + public function findItemsByCategory($categoryId, $options = null) + { + // prepare options + $options = parent::optionsToArray($options); + $options['categoryId'] = $categoryId; + + // do request + return $this->_findItems($options, 'findItemsByCategory'); + } + + /** + * Finds items on eBay based upon a keyword query and returns details for + * matching items. + * + * @param string $keywords + * @param Zend_Config|array $options + * @link http://developer.ebay.com/DevZone/finding/CallRef/findItemsByKeywords.html + * @return Zend_Service_Ebay_Finding_Response_Items + */ + public function findItemsByKeywords($keywords, $options = null) + { + // prepare options + $options = parent::optionsToArray($options); + $options['keywords'] = $keywords; + + // do request + return $this->_findItems($options, 'findItemsByKeywords'); + } + + /** + * Finds items based upon a product ID, such as an ISBN, UPC, EAN, or ePID. + * + * @param integer $productId + * @param string $productIdType Default value is ReferenceID + * @param Zend_Config|array $options + * @link http://developer.ebay.com/DevZone/finding/CallRef/findItemsByProduct.html + * @return Zend_Service_Ebay_Finding_Response_Items + */ + public function findItemsByProduct($productId, $productIdType = null, $options = null) + { + if (null == $productIdType) { + $productIdType = 'ReferenceID'; + } + + // prepare options + $options = parent::optionsToArray($options); + $options['productId'] = array('' => $productId, + 'type' => $productIdType); + + // do request + return $this->_findItems($options, 'findItemsByProduct'); + } + + /** + * Finds items in eBay stores. Can search a specific store or can search all + * stores with a keyword query. + * + * @param string $storeName + * @param Zend_Config|array $options + * @link http://developer.ebay.com/DevZone/finding/CallRef/findItemsIneBayStores.html + * @return Zend_Service_Ebay_Finding_Response_Items + */ + public function findItemsInEbayStores($storeName, $options = null) + { + // prepare options + $options = parent::optionsToArray($options); + $options['storeName'] = $storeName; + + // do request + return $this->_findItems($options, 'findItemsIneBayStores'); + } + + /** + * @param array $options + * @param string $operation + * @return Zend_Service_Ebay_Finding_Response_Items + */ + protected function _findItems(array $options, $operation) + { + // set default output selector value + if (!array_key_exists('outputSelector', $options)) { + $options['outputSelector'] = array('AspectHistogram', + 'CategoryHistogram', + 'SellerInfo', + 'StoreInfo'); + } + + // do request + $dom = $this->_request($operation, $options); + + /** + * @see Zend_Service_Ebay_Finding_Response_Items + */ + require_once 'Zend/Service/Ebay/Finding/Response/Items.php'; + $response = new Zend_Service_Ebay_Finding_Response_Items($dom->firstChild); + return $response->setOperation($operation) + ->setOption($options); + } + + /** + * Gets category and/or aspect metadata for the specified category. + * + * @param integer $categoryId + * @param Zend_Config|array $options + * @link http://developer.ebay.com/DevZone/finding/CallRef/getHistograms.html + * @return Zend_Service_Ebay_Finding_Response_Histograms + */ + public function getHistograms($categoryId, $options = null) + { + // prepare options + $options = parent::optionsToArray($options); + $options['categoryId'] = $categoryId; + + // do request + $operation = 'getHistograms'; + $dom = $this->_request($operation, $options); + + /** + * @see Zend_Service_Ebay_Finding_Response_Histograms + */ + require_once 'Zend/Service/Ebay/Finding/Response/Histograms.php'; + $response = new Zend_Service_Ebay_Finding_Response_Histograms($dom->firstChild); + return $response->setOperation($operation) + ->setOption($options); + } + + /** + * Checks specified keywords and returns correctly spelled keywords for best + * search results. + * + * @param string $keywords + * @param Zend_Config|array $options + * @link http://developer.ebay.com/DevZone/finding/CallRef/getSearchKeywordsRecommendation.html + * @return Zend_Service_Ebay_Finding_Response_Keywords + */ + public function getSearchKeywordsRecommendation($keywords, $options = null) + { + // prepare options + $options = parent::optionsToArray($options); + $options['keywords'] = $keywords; + + // do request + $operation = 'getSearchKeywordsRecommendation'; + $dom = $this->_request($operation, $options); + + /** + * @see Zend_Service_Ebay_Finding_Response_Keywords + */ + require_once 'Zend/Service/Ebay/Finding/Response/Keywords.php'; + $response = new Zend_Service_Ebay_Finding_Response_Keywords($dom->firstChild); + return $response->setOperation($operation) + ->setOption($options); + } + + /** + * @param string $operation + * @param array $options + * @link http://developer.ebay.com/DevZone/finding/Concepts/MakingACall.html#StandardURLParameters + * @return DOMDocument + */ + protected function _request($operation, array $options = null) + { + // generate default options + // constructor load global-id and application-id values + $default = array('OPERATION-NAME' => $operation, + 'SERVICE-NAME' => self::SERVICE_NAME, + 'SERVICE-VERSION' => self::SERVICE_VERSION, + 'GLOBAL-ID' => $this->getOption(self::OPTION_GLOBAL_ID), + 'SECURITY-APPNAME' => $this->getOption(self::OPTION_APP_ID), + 'RESPONSE-DATA-FORMAT' => self::RESPONSE_DATA_FORMAT, + 'REST-PAYLOAD' => ''); + + // prepare options to ebay syntax + $options = $default + $this->_optionsToNameValueSyntax($options); + + // do request + $client = $this->getClient(); + $client->getHttpClient()->resetParameters(); + $response = $client->setUri(self::ENDPOINT_URI) + ->restGet(self::ENDPOINT_PATH, $options); + + return $this->_parseResponse($response); + } + + /** + * Search for error from request. + * + * If any error is found a DOMDocument is returned, this object contains a + * DOMXPath object as "ebayFindingXPath" attribute. + * + * @param Zend_Http_Response $response + * @link http://developer.ebay.com/DevZone/finding/CallRef/types/ErrorSeverity.html + * @see Zend_Service_Ebay_Finding_Abstract::_initXPath() + * @throws Zend_Service_Ebay_Finding_Exception When any error occurrs during request + * @return DOMDocument + */ + protected function _parseResponse(Zend_Http_Response $response) + { + // error message + $message = ''; + + // first trying, loading XML + $dom = new DOMDocument(); + if (!$dom = @Zend_Xml_Security::scan($response->getBody(), $dom)) { + $message = 'It was not possible to load XML returned.'; + } + + // second trying, check request status + if ($response->isError()) { + $message = $response->getMessage() + . ' (HTTP status code #' . $response->getStatus() . ')'; + } + + // third trying, search for error message into XML response + // only first error that contains severiry=Error is read + $xpath = new DOMXPath($dom); + foreach (self::$_xmlNamespaces as $alias => $uri) { + $xpath->registerNamespace($alias, $uri); + } + $ns = self::XMLNS_FINDING; + $nsMs = self::XMLNS_MS; + $expression = "//$nsMs:errorMessage[1]/$ns:error/$ns:severity[.='Error']"; + $severityNode = $xpath->query($expression)->item(0); + if ($severityNode) { + $errorNode = $severityNode->parentNode; + // ebay message + $messageNode = $xpath->query("//$ns:message[1]", $errorNode)->item(0); + if ($messageNode) { + $message = 'eBay error: ' . $messageNode->nodeValue; + } else { + $message = 'eBay error: unknown'; + } + // ebay error id + $errorIdNode = $xpath->query("//$ns:errorId[1]", $errorNode)->item(0); + if ($errorIdNode) { + $message .= ' (#' . $errorIdNode->nodeValue . ')'; + } + } + + // throw exception when an error was detected + if (strlen($message) > 0) { + /** + * @see Zend_Service_Ebay_Finding_Exception + */ + require_once 'Zend/Service/Ebay/Finding/Exception.php'; + throw new Zend_Service_Ebay_Finding_Exception($message); + } + + // add xpath to dom document + // it allows service_ebay_finding classes use this + $dom->ebayFindingXPath = $xpath; + + return $dom; + } +} diff --git a/lib/zend/Zend/Service/Ebay/Finding/Abstract.php b/lib/zend/Zend/Service/Ebay/Finding/Abstract.php new file mode 100644 index 00000000000..be025a817b8 --- /dev/null +++ b/lib/zend/Zend/Service/Ebay/Finding/Abstract.php @@ -0,0 +1,169 @@ +_dom = $dom; + $this->_initXPath(); + $this->_init(); + } + + /** + * @param string $tag + * @param string $attribute + * @return mixed + */ + public function attributes($tag, $attribute = null) + { + if (null === $attribute) { + // all attributes + if (array_key_exists($tag, $this->_attributes)) { + return $this->_attributes[$tag]; + } + return array(); + } + + // a specific attribute + if (isset($this->_attributes[$tag][$attribute])) { + return $this->_attributes[$tag][$attribute]; + } + return null; + } + + /** + * Initialize object. + * + * Post construct logic, classes must read their members here. Called from + * {@link __construct()} as final step of object initialization. + * + * @return void + */ + protected function _init() + { + } + + /** + * Load DOMXPath for current DOM object. + * + * @see Zend_Service_Ebay_Finding::_parseResponse() + * @return void + */ + protected function _initXPath() + { + $document = $this->_dom->ownerDocument; + if (!isset($document->ebayFindingXPath)) { + $xpath = new DOMXPath($document); + foreach (Zend_Service_Ebay_Finding::getXmlNamespaces() as $alias => $uri) { + $xpath->registerNamespace($alias, $uri); + } + $document->ebayFindingXPath = $xpath; + } + $this->_xPath = $document->ebayFindingXPath; + } + + /** + * @return DOMElement + */ + public function getDom() + { + return $this->_dom; + } + + /** + * @return DOMXPath + */ + public function getXPath() + { + return $this->_xPath; + } + + /** + * @param string $path + * @param string $type + * @param string $array When true means it expects more than one node occurence + * @return mixed + */ + protected function _query($path, $type, $array = false) + { + // find values + $values = array(); + $nodes = $this->_xPath->query($path, $this->_dom); + foreach ($nodes as $node) { + $value = (string) $node->nodeValue; + $values[] = Zend_Service_Ebay_Abstract::toPhpValue($value, $type); + if (!$array) { + break; + } + } + + // array + if ($array) { + return $values; + } + + // single value + if (count($values)) { + return reset($values); + } + + // no nodes fount + return null; + } +} diff --git a/lib/zend/Zend/Service/Ebay/Finding/Aspect.php b/lib/zend/Zend/Service/Ebay/Finding/Aspect.php new file mode 100644 index 00000000000..df1b66bc0f0 --- /dev/null +++ b/lib/zend/Zend/Service/Ebay/Finding/Aspect.php @@ -0,0 +1,68 @@ +_attributes['valueHistogram'] = array( + 'valueName' => $this->_query(".//$ns:valueHistogram/@valueName", 'string', true) + ); + + $nodes = $this->_xPath->query(".//$ns:valueHistogram", $this->_dom); + if ($nodes->length > 0) { + /** + * @see Zend_Service_Ebay_Finding_Aspect_Histogram_Value_Set + */ + require_once 'Zend/Service/Ebay/Finding/Aspect/Histogram/Value/Set.php'; + $this->valueHistogram = new Zend_Service_Ebay_Finding_Aspect_Histogram_Value_Set($nodes); + } + } +} diff --git a/lib/zend/Zend/Service/Ebay/Finding/Aspect/Histogram/Container.php b/lib/zend/Zend/Service/Ebay/Finding/Aspect/Histogram/Container.php new file mode 100644 index 00000000000..862e53430ef --- /dev/null +++ b/lib/zend/Zend/Service/Ebay/Finding/Aspect/Histogram/Container.php @@ -0,0 +1,106 @@ +domainDisplayName = $this->_query(".//$ns:domainDisplayName[1]", 'string'); + $this->domainName = $this->_query(".//$ns:domainName[1]", 'string'); + + $this->_attributes['aspect'] = array( + 'name' => $this->_query(".//$ns:aspect/@name", 'string', true) + ); + + $nodes = $this->_xPath->query(".//$ns:aspect", $this->_dom); + if ($nodes->length > 0) { + /** + * @see Zend_Service_Ebay_Finding_Aspect_Set + */ + require_once 'Zend/Service/Ebay/Finding/Aspect/Set.php'; + $this->aspect = new Zend_Service_Ebay_Finding_Aspect_Set($nodes); + } + } +} diff --git a/lib/zend/Zend/Service/DeveloperGarden/Response/ConferenceCall/AddConferenceTemplateParticipantResponseType.php b/lib/zend/Zend/Service/Ebay/Finding/Aspect/Histogram/Value.php similarity index 50% rename from lib/zend/Zend/Service/DeveloperGarden/Response/ConferenceCall/AddConferenceTemplateParticipantResponseType.php rename to lib/zend/Zend/Service/Ebay/Finding/Aspect/Histogram/Value.php index 5593ca9e630..8ca1ce35a08 100644 --- a/lib/zend/Zend/Service/DeveloperGarden/Response/ConferenceCall/AddConferenceTemplateParticipantResponseType.php +++ b/lib/zend/Zend/Service/Ebay/Finding/Aspect/Histogram/Value.php @@ -14,42 +14,43 @@ * * @category Zend * @package Zend_Service - * @subpackage DeveloperGarden - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @subpackage Ebay + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id$ + * @version $Id: Value.php 22791 2010-08-04 16:11:47Z renanbr $ */ /** - * @see Zend_Service_DeveloperGarden_Response_ConferenceCall_ConferenceCallAbstract + * @see Zend_Service_Ebay_Finding_Abstract */ -require_once 'Zend/Service/DeveloperGarden/Response/BaseType.php'; +require_once 'Zend/Service/Ebay/Finding/Abstract.php'; /** * @category Zend * @package Zend_Service - * @subpackage DeveloperGarden - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @author Marco Kaiser + * @subpackage Ebay + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License + * @uses Zend_Service_Ebay_Finding_Abstract */ -class Zend_Service_DeveloperGarden_Response_ConferenceCall_AddConferenceTemplateParticipantResponseType - extends Zend_Service_DeveloperGarden_Response_BaseType +class Zend_Service_Ebay_Finding_Aspect_Histogram_Value extends Zend_Service_Ebay_Finding_Abstract { /** - * the participant Id + * Number of items that share the characteristic the respective aspect + * value. * - * @var string + * @var integer */ - public $participantId = null; + public $count; /** - * return the participant id - * - * @return string + * @return void */ - public function getParticipantId() + protected function _init() { - return $this->participantId; + parent::_init(); + $ns = Zend_Service_Ebay_Finding::XMLNS_FINDING; + + $this->count = $this->_query(".//$ns:count[1]", 'integer'); } } diff --git a/lib/zend/Zend/Service/Ebay/Finding/Aspect/Histogram/Value/Set.php b/lib/zend/Zend/Service/Ebay/Finding/Aspect/Histogram/Value/Set.php new file mode 100644 index 00000000000..7b236267cd6 --- /dev/null +++ b/lib/zend/Zend/Service/Ebay/Finding/Aspect/Histogram/Value/Set.php @@ -0,0 +1,57 @@ +_nodes->item($this->_key); + if (!$node) { + return null; + } + + /** + * @see Zend_Service_Ebay_Finding_Aspect_Histogram_Value + */ + require_once 'Zend/Service/Ebay/Finding/Aspect/Histogram/Value.php'; + return new Zend_Service_Ebay_Finding_Aspect_Histogram_Value($node); + } +} diff --git a/lib/zend/Zend/Service/Ebay/Finding/Aspect/Set.php b/lib/zend/Zend/Service/Ebay/Finding/Aspect/Set.php new file mode 100644 index 00000000000..1ba41bf70a1 --- /dev/null +++ b/lib/zend/Zend/Service/Ebay/Finding/Aspect/Set.php @@ -0,0 +1,57 @@ +_nodes->item($this->_key); + if (!$node) { + return null; + } + + /** + * @see Zend_Service_Ebay_Finding_Aspect + */ + require_once 'Zend/Service/Ebay/Finding/Aspect.php'; + return new Zend_Service_Ebay_Finding_Aspect($node); + } +} diff --git a/lib/zend/Zend/Service/Ebay/Finding/Category.php b/lib/zend/Zend/Service/Ebay/Finding/Category.php new file mode 100644 index 00000000000..f16e35a8c13 --- /dev/null +++ b/lib/zend/Zend/Service/Ebay/Finding/Category.php @@ -0,0 +1,73 @@ +categoryId = $this->_query(".//$ns:categoryId[1]", 'string'); + $this->categoryName = $this->_query(".//$ns:categoryName[1]", 'string'); + } + + /** + * @param Zend_Service_Ebay_Finding $proxy + * @param Zend_Config|array $options + * @return Zend_Service_Ebay_Finding_Response_Items + */ + public function findItems(Zend_Service_Ebay_Finding $proxy, $options = null) + { + return $proxy->findItemsByCategory($this->categoryId, $options); + } +} diff --git a/lib/zend/Zend/Service/Ebay/Finding/Category/Histogram.php b/lib/zend/Zend/Service/Ebay/Finding/Category/Histogram.php new file mode 100644 index 00000000000..f126242bf46 --- /dev/null +++ b/lib/zend/Zend/Service/Ebay/Finding/Category/Histogram.php @@ -0,0 +1,77 @@ +count = $this->_query(".//$ns:count[1]", 'integer'); + + $nodes = $this->_xPath->query(".//$ns:childCategoryHistogram", $this->_dom); + if ($nodes->length > 0) { + /** + * @see Zend_Service_Ebay_Finding_Category_Histogram_Set + */ + require_once 'Zend/Service/Ebay/Finding/Category/Histogram/Set.php'; + $this->childCategoryHistogram = new Zend_Service_Ebay_Finding_Category_Histogram_Set($nodes); + } + } +} diff --git a/lib/zend/Zend/Service/Ebay/Finding/Category/Histogram/Container.php b/lib/zend/Zend/Service/Ebay/Finding/Category/Histogram/Container.php new file mode 100644 index 00000000000..41a26bb1104 --- /dev/null +++ b/lib/zend/Zend/Service/Ebay/Finding/Category/Histogram/Container.php @@ -0,0 +1,66 @@ +_xPath->query(".//$ns:categoryHistogram", $this->_dom); + if ($nodes->length > 0) { + /** + * @see Zend_Service_Ebay_Finding_Category_Histogram_Set + */ + require_once 'Zend/Service/Ebay/Finding/Category/Histogram/Set.php'; + $this->categoryHistogram = new Zend_Service_Ebay_Finding_Category_Histogram_Set($nodes); + } + } +} diff --git a/lib/zend/Zend/Service/Ebay/Finding/Category/Histogram/Set.php b/lib/zend/Zend/Service/Ebay/Finding/Category/Histogram/Set.php new file mode 100644 index 00000000000..1415bc3b91d --- /dev/null +++ b/lib/zend/Zend/Service/Ebay/Finding/Category/Histogram/Set.php @@ -0,0 +1,57 @@ +_nodes->item($this->_key); + if (!$node) { + return null; + } + + /** + * @see Zend_Service_Ebay_Finding_Category_Histogram + */ + require_once 'Zend/Service/Ebay/Finding/Category/Histogram.php'; + return new Zend_Service_Ebay_Finding_Category_Histogram($node); + } +} diff --git a/lib/zend/Zend/Service/Ebay/Finding/Error/Data.php b/lib/zend/Zend/Service/Ebay/Finding/Error/Data.php new file mode 100644 index 00000000000..977d86afadb --- /dev/null +++ b/lib/zend/Zend/Service/Ebay/Finding/Error/Data.php @@ -0,0 +1,158 @@ +category = $this->_query(".//$ns:category[1]", 'string'); + $this->domain = $this->_query(".//$ns:domain[1]", 'string'); + $this->errorId = $this->_query(".//$ns:errorId[1]", 'integer'); + $this->exceptionId = $this->_query(".//$ns:exceptionId[1]", 'string'); + $this->message = $this->_query(".//$ns:message[1]", 'string'); + $this->parameter = $this->_query(".//$ns:parameter", 'string', true); + $this->severity = $this->_query(".//$ns:severity[1]", 'string'); + $this->subdomain = $this->_query(".//$ns:subdomain[1]", 'string'); + + $this->_attributes['parameter'] = array( + 'name' => $this->_query(".//$ns:parameter/@name", 'string', true) + ); + } +} diff --git a/lib/zend/Zend/Service/Ebay/Finding/Error/Data/Set.php b/lib/zend/Zend/Service/Ebay/Finding/Error/Data/Set.php new file mode 100644 index 00000000000..5bafbf31585 --- /dev/null +++ b/lib/zend/Zend/Service/Ebay/Finding/Error/Data/Set.php @@ -0,0 +1,57 @@ +_nodes->item($this->_key); + if (!$node) { + return null; + } + + /** + * @see Zend_Service_Ebay_Finding_Error_Data + */ + require_once 'Zend/Service/Ebay/Finding/Error/Data.php'; + return new Zend_Service_Ebay_Finding_Error_Data($node); + } +} diff --git a/lib/zend/Zend/Service/Ebay/Finding/Error/Message.php b/lib/zend/Zend/Service/Ebay/Finding/Error/Message.php new file mode 100644 index 00000000000..24128ec7418 --- /dev/null +++ b/lib/zend/Zend/Service/Ebay/Finding/Error/Message.php @@ -0,0 +1,60 @@ +_xPath->query(".//$ns:error", $this->_dom); + if ($nodes->length > 0) { + /** + * @see Zend_Service_Ebay_Finding_Error_Data_Set + */ + require_once 'Zend/Service/Ebay/Finding/Error/Data/Set.php'; + $this->error = new Zend_Service_Ebay_Finding_Error_Data_Set($nodes); + } + } +} diff --git a/lib/zend/Zend/Service/DeveloperGarden/LocalSearch/Exception.php b/lib/zend/Zend/Service/Ebay/Finding/Exception.php similarity index 63% rename from lib/zend/Zend/Service/DeveloperGarden/LocalSearch/Exception.php rename to lib/zend/Zend/Service/Ebay/Finding/Exception.php index 6c667406dbf..403a9d38b96 100644 --- a/lib/zend/Zend/Service/DeveloperGarden/LocalSearch/Exception.php +++ b/lib/zend/Zend/Service/Ebay/Finding/Exception.php @@ -14,25 +14,24 @@ * * @category Zend * @package Zend_Service - * @subpackage DeveloperGarden - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @subpackage Ebay + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id$ + * @version $Id: Exception.php 20166 2010-01-09 19:00:17Z bkarwin $ */ /** - * Zend_Service_Exception + * @see Zend_Service_Exception */ -require_once 'Zend/Service/DeveloperGarden/Exception.php'; +require_once 'Zend/Service/Ebay/Exception.php'; /** * @category Zend * @package Zend_Service - * @subpackage DeveloperGarden - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @author Marco Kaiser + * @subpackage Ebay + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License + * @uses Zend_Service_Ebay_Exception */ -class Zend_Service_DeveloperGarden_LocalSearch_Exception extends Zend_Service_DeveloperGarden_Exception -{ -} +class Zend_Service_Ebay_Finding_Exception extends Zend_Service_Ebay_Exception +{} diff --git a/lib/zend/Zend/Service/Ebay/Finding/ListingInfo.php b/lib/zend/Zend/Service/Ebay/Finding/ListingInfo.php new file mode 100644 index 00000000000..c99dfff651c --- /dev/null +++ b/lib/zend/Zend/Service/Ebay/Finding/ListingInfo.php @@ -0,0 +1,211 @@ +bestOfferEnabled = $this->_query(".//$ns:bestOfferEnabled[1]", 'boolean'); + $this->buyItNowAvailable = $this->_query(".//$ns:buyItNowAvailable[1]", 'boolean'); + $this->buyItNowPrice = $this->_query(".//$ns:buyItNowPrice[1]", 'float'); + $this->convertedBuyItNowPrice = $this->_query(".//$ns:convertedBuyItNowPrice[1]", 'float'); + $this->endTime = $this->_query(".//$ns:endTime[1]", 'string'); + $this->gift = $this->_query(".//$ns:gift[1]", 'boolean'); + $this->listingType = $this->_query(".//$ns:listingType[1]", 'string'); + $this->startTime = $this->_query(".//$ns:startTime[1]", 'string'); + + $this->_attributes['buyItNowPrice'] = array( + 'currencyId' => $this->_query(".//$ns:buyItNowPrice[1]/@currencyId[1]", 'string') + ); + + $this->_attributes['convertedBuyItNowPrice'] = array( + 'currencyId' => $this->_query(".//$ns:convertedBuyItNowPrice[1]/@currencyId[1]", 'string') + ); + } +} diff --git a/lib/zend/Zend/Service/Ebay/Finding/PaginationOutput.php b/lib/zend/Zend/Service/Ebay/Finding/PaginationOutput.php new file mode 100644 index 00000000000..325474f04ef --- /dev/null +++ b/lib/zend/Zend/Service/Ebay/Finding/PaginationOutput.php @@ -0,0 +1,115 @@ +entriesPerPage = $this->_query(".//$ns:entriesPerPage[1]", 'integer'); + $this->pageNumber = $this->_query(".//$ns:pageNumber[1]", 'integer'); + $this->totalEntries = $this->_query(".//$ns:totalEntries[1]", 'integer'); + $this->totalPages = $this->_query(".//$ns:totalPages[1]", 'integer'); + } +} diff --git a/lib/zend/Zend/Service/Ebay/Finding/Response/Abstract.php b/lib/zend/Zend/Service/Ebay/Finding/Response/Abstract.php new file mode 100644 index 00000000000..bd7cb7c4896 --- /dev/null +++ b/lib/zend/Zend/Service/Ebay/Finding/Response/Abstract.php @@ -0,0 +1,185 @@ +ack = $this->_query(".//$ns:ack[1]", 'string'); + $this->timestamp = $this->_query(".//$ns:timestamp[1]", 'string'); + $this->version = $this->_query(".//$ns:version[1]", 'string'); + + $node = $this->_xPath->query(".//$ns:errorMessage[1]", $this->_dom)->item(0); + if ($node) { + /** + * @see Zend_Service_Ebay_Finding_Error_Message + */ + require_once 'Zend/Service/Ebay/Finding/Error/Message.php'; + $this->errorMessage = new Zend_Service_Ebay_Finding_Error_Message($node); + } + } + + /** + * @param string $operation + * @return Zend_Service_Ebay_Finding_Response_Abstract Provides a fluent interface + */ + public function setOperation($operation) + { + $this->_operation = (string) $operation; + return $this; + } + + /** + * @return string + */ + public function getOperation() + { + return $this->_operation; + } + + /** + * @param string|Zend_Config|array $name + * @param mixed $value + * @return Zend_Service_Ebay_Finding_Response_Abstract Provides a fluent interface + */ + public function setOption($name, $value = null) + { + if ($name instanceof Zend_Config) { + $name = $name->toArray(); + } + if (is_array($name)) { + $this->_options = $name; + } else { + $this->_options[$name] = $value; + } + return $this; + } + + /** + * @param string $name + * @return mixed + */ + public function getOption($name = null) + { + if (null === $name) { + return $this->_options; + } + if (array_key_exists($name, $this->_options)) { + return $this->_options[$name]; + } + return null; + } +} diff --git a/lib/zend/Zend/Service/Ebay/Finding/Response/Histograms.php b/lib/zend/Zend/Service/Ebay/Finding/Response/Histograms.php new file mode 100644 index 00000000000..1e87b598916 --- /dev/null +++ b/lib/zend/Zend/Service/Ebay/Finding/Response/Histograms.php @@ -0,0 +1,86 @@ +_xPath->query(".//$ns:aspectHistogramContainer[1]", $this->_dom)->item(0); + if ($node) { + /** + * @see Zend_Service_Ebay_Finding_Aspect_Histogram_Container + */ + require_once 'Zend/Service/Ebay/Finding/Aspect/Histogram/Container.php'; + $this->aspectHistogramContainer = new Zend_Service_Ebay_Finding_Aspect_Histogram_Container($node); + } + + $node = $this->_xPath->query(".//$ns:categoryHistogramContainer[1]", $this->_dom)->item(0); + if ($node) { + /** + * @see Zend_Service_Ebay_Finding_Category_Histogram_Container + */ + require_once 'Zend/Service/Ebay/Finding/Category/Histogram/Container.php'; + $this->categoryHistogramContainer = new Zend_Service_Ebay_Finding_Category_Histogram_Container($node); + } + } +} diff --git a/lib/zend/Zend/Service/Ebay/Finding/Response/Items.php b/lib/zend/Zend/Service/Ebay/Finding/Response/Items.php new file mode 100644 index 00000000000..cb6108985b5 --- /dev/null +++ b/lib/zend/Zend/Service/Ebay/Finding/Response/Items.php @@ -0,0 +1,249 @@ +_attributes['searchResult'] = array( + 'count' => $this->_query(".//$ns:searchResult[1]/@count[1]", 'string') + ); + + $node = $this->_xPath->query(".//$ns:searchResult[1]", $this->_dom)->item(0); + if ($node) { + /** + * @see Zend_Service_Ebay_Finding_Search_Result + */ + require_once 'Zend/Service/Ebay/Finding/Search/Result.php'; + $this->searchResult = new Zend_Service_Ebay_Finding_Search_Result($node); + } + + $node = $this->_xPath->query(".//$ns:paginationOutput[1]", $this->_dom)->item(0); + if ($node) { + /** + * @see Zend_Service_Ebay_Finding_PaginationOutput + */ + require_once 'Zend/Service/Ebay/Finding/PaginationOutput.php'; + $this->paginationOutput = new Zend_Service_Ebay_Finding_PaginationOutput($node); + } + } + + /** + * @param Zend_Service_Ebay_Finding $proxy + * @param integer $number + * @throws Zend_Service_Ebay_Finding_Exception When $number is invalid + * @return Zend_Service_Ebay_Finding_Response_Items + */ + public function page(Zend_Service_Ebay_Finding $proxy, $number) + { + // check page number + if ($number < 1 || $number > $this->paginationOutput->totalPages) { + /** + * @see Zend_Service_Ebay_Finding_Exception + */ + require_once 'Zend/Service/Ebay/Finding/Exception.php'; + throw new Zend_Service_Ebay_Finding_Exception( + "Page number '{$number}' is out of range."); + } + + // prepare arguments + $arguments = array(); + switch ($this->_operation) { + case 'findItemsAdvanced': + $arguments[] = $this->getOption('keywords'); + $arguments[] = $this->getOption('descriptionSearch'); + $arguments[] = $this->getOption('categoryId'); + break; + + case 'findItemsByCategory': + $arguments[] = $this->getOption('categoryId'); + break; + + case 'findItemsByKeywords': + $arguments[] = $this->getOption('keywords'); + break; + + case 'findItemsByProduct': + $productId = $this->getOption('productId'); + if (!is_array($productId)) { + $productId = array('' => $productId); + } + $arguments[] = array_key_exists('', $productId) + ? $productId[''] + : null; + $arguments[] = array_key_exists('type', $productId) + ? $productId['type'] + : null; + break; + + case 'findItemsIneBayStores': + $arguments[] = $this->getOption('storeName'); + break; + + default: + /** + * @see Zend_Service_Ebay_Finding_Exception + */ + require_once 'Zend/Service/Ebay/Finding/Exception.php'; + throw new Zend_Service_Ebay_Finding_Exception( + "Invalid operation '{$this->_operation}'."); + } + + // prepare options + // remove every pagination entry from current option list + $options = $this->_options; + foreach (array_keys($options) as $optionName) { + if (substr($optionName, 0, 15) == 'paginationInput') { + unset($options[$optionName]); + } + } + + // set new pagination values + // see more at http://developer.ebay.com/DevZone/finding/CallRef/types/PaginationInput.html + $entriesPerPage = $this->paginationOutput->entriesPerPage; + $options['paginationInput'] = array('entriesPerPage' => $entriesPerPage, + 'pageNumber' => $number); + + // add current options as last argument + ksort($options); + $arguments[] = $options; + + // verify cache + $id = serialize($arguments); + if (!array_key_exists($id, self::$_pageCache)) { + if ($number == $this->paginationOutput->pageNumber) { + // add itself to cache + $new = $this; + } else { + // request new page + $callback = array($proxy, $this->_operation); + $new = call_user_func_array($callback, $arguments); + } + self::$_pageCache[$id] = $new; + } + + return self::$_pageCache[$id]; + } + + /** + * @param Zend_Service_Ebay_Finding $proxy + * @return Zend_Service_Ebay_Finding_Response_Items + */ + public function pageFirst(Zend_Service_Ebay_Finding $proxy) + { + return $this->page($proxy, 1); + } + + /** + * @param Zend_Service_Ebay_Finding $proxy + * @param integer $max + * @return Zend_Service_Ebay_Finding_Response_Items + */ + public function pageLast(Zend_Service_Ebay_Finding $proxy, $max = self::PAGE_MAX_DEFAULT) + { + $last = $this->paginationOutput->totalPages; + if ($max > 0 && $last > $max) { + $last = $max; + } + return $this->page($proxy, $last); + } + + /** + * @param Zend_Service_Ebay_Finding $proxy + * @param integer $max + * @return Zend_Service_Ebay_Finding_Response_Items + */ + public function pageNext(Zend_Service_Ebay_Finding $proxy, $max = self::PAGE_MAX_DEFAULT) + { + $next = $this->paginationOutput->pageNumber + 1; + $last = $this->paginationOutput->totalPages; + if (($max > 0 && $next > $max) || $next > $last) { + return null; + } + return $this->page($proxy, $next); + } + + /** + * @param Zend_Service_Ebay_Finding $proxy + * @return Zend_Service_Ebay_Finding_Response_Items + */ + public function pagePrevious(Zend_Service_Ebay_Finding $proxy) + { + $previous = $this->paginationOutput->pageNumber - 1; + if ($previous < 1) { + return null; + } + return $this->page($proxy, $previous); + } +} diff --git a/lib/zend/Zend/Service/Ebay/Finding/Response/Keywords.php b/lib/zend/Zend/Service/Ebay/Finding/Response/Keywords.php new file mode 100644 index 00000000000..7e992a50212 --- /dev/null +++ b/lib/zend/Zend/Service/Ebay/Finding/Response/Keywords.php @@ -0,0 +1,78 @@ +keywords = $this->_query(".//$ns:keywords[1]", 'string'); + } + + /** + * @param Zend_Service_Ebay_Finding $proxy + * @param Zend_Config|array $options + * @return Zend_Service_Ebay_Finding_Response_Items + */ + public function findItems(Zend_Service_Ebay_Finding $proxy, $options = null) + { + // prepare options + $options = Zend_Service_Ebay_Abstract::optionsToArray($options); + $options = $options + $this->_options; + + // find items + return $proxy->findItemsByKeywords($this->keywords, $options); + } +} diff --git a/lib/zend/Zend/Service/Ebay/Finding/Search/Item.php b/lib/zend/Zend/Service/Ebay/Finding/Search/Item.php new file mode 100644 index 00000000000..55c62e2c8a6 --- /dev/null +++ b/lib/zend/Zend/Service/Ebay/Finding/Search/Item.php @@ -0,0 +1,394 @@ +autoPay = $this->_query(".//$ns:autoPay[1]", 'boolean'); + $this->charityId = $this->_query(".//$ns:charityId[1]", 'integer'); + $this->country = $this->_query(".//$ns:country[1]", 'string'); + $this->distance = $this->_query(".//$ns:distance[1]", 'float'); + $this->galleryPlusPictureURL = $this->_query(".//$ns:galleryPlusPictureURL", 'string', true); + $this->galleryURL = $this->_query(".//$ns:galleryURL[1]", 'string'); + $this->globalId = $this->_query(".//$ns:globalId[1]", 'string'); + $this->itemId = $this->_query(".//$ns:itemId[1]", 'string'); + $this->location = $this->_query(".//$ns:location[1]", 'string'); + $this->paymentMethod = $this->_query(".//$ns:paymentMethod", 'string', true); + $this->postalCode = $this->_query(".//$ns:postalCode[1]", 'string'); + $this->productId = $this->_query(".//$ns:productId[1]", 'string'); + $this->subtitle = $this->_query(".//$ns:subtitle[1]", 'string'); + $this->title = $this->_query(".//$ns:title[1]", 'string'); + $this->viewItemURL = $this->_query(".//$ns:viewItemURL[1]", 'string'); + + $this->_attributes['distance'] = array( + 'unit' => $this->_query(".//$ns:distance[1]/@unit[1]", 'string') + ); + $this->_attributes['productId'] = array( + 'type' => $this->_query(".//$ns:productId[1]/@type[1]", 'string') + ); + + $node = $this->_xPath->query(".//$ns:listingInfo[1]", $this->_dom)->item(0); + if ($node) { + /** + * @see Zend_Service_Ebay_Finding_ListingInfo + */ + require_once 'Zend/Service/Ebay/Finding/ListingInfo.php'; + $this->listingInfo = new Zend_Service_Ebay_Finding_ListingInfo($node); + } + + $node = $this->_xPath->query(".//$ns:primaryCategory[1]", $this->_dom)->item(0); + if ($node) { + /** + * @see Zend_Service_Ebay_Finding_Category + */ + require_once 'Zend/Service/Ebay/Finding/Category.php'; + $this->primaryCategory = new Zend_Service_Ebay_Finding_Category($node); + } + + $node = $this->_xPath->query(".//$ns:secondaryCategory[1]", $this->_dom)->item(0); + if ($node) { + /** + * @see Zend_Service_Ebay_Finding_Category + */ + require_once 'Zend/Service/Ebay/Finding/Category.php'; + $this->secondaryCategory = new Zend_Service_Ebay_Finding_Category($node); + } + + $node = $this->_xPath->query(".//$ns:sellerInfo[1]", $this->_dom)->item(0); + if ($node) { + /** + * @see Zend_Service_Ebay_Finding_SellerInfo + */ + require_once 'Zend/Service/Ebay/Finding/SellerInfo.php'; + $this->sellerInfo = new Zend_Service_Ebay_Finding_SellerInfo($node); + } + + $node = $this->_xPath->query(".//$ns:sellingStatus[1]", $this->_dom)->item(0); + if ($node) { + /** + * @see Zend_Service_Ebay_Finding_SellingStatus + */ + require_once 'Zend/Service/Ebay/Finding/SellingStatus.php'; + $this->sellingStatus = new Zend_Service_Ebay_Finding_SellingStatus($node); + } + + $node = $this->_xPath->query("./$ns:shippingInfo", $this->_dom)->item(0); + if ($node) { + /** + * @see Zend_Service_Ebay_Finding_ShippingInfo + */ + require_once 'Zend/Service/Ebay/Finding/ShippingInfo.php'; + $this->shippingInfo = new Zend_Service_Ebay_Finding_ShippingInfo($node); + } + + $node = $this->_xPath->query(".//$ns:storeInfo[1]", $this->_dom)->item(0); + if ($node) { + /** + * @see Zend_Service_Ebay_Finding_Storefront + */ + require_once 'Zend/Service/Ebay/Finding/Storefront.php'; + $this->storeInfo = new Zend_Service_Ebay_Finding_Storefront($node); + } + } + + /** + * @param Zend_Service_Ebay_Finding $proxy + * @param Zend_Config|array $options + * @return Zend_Service_Ebay_Finding_Response_Items + */ + public function findItemsByProduct(Zend_Service_Ebay_Finding $proxy, $options = null) + { + $type = $this->attributes('productId', 'type'); + return $proxy->findItemsByProduct($this->productId, $type, $options); + } +} diff --git a/lib/zend/Zend/Service/Ebay/Finding/Search/Item/Set.php b/lib/zend/Zend/Service/Ebay/Finding/Search/Item/Set.php new file mode 100644 index 00000000000..57a3727fe52 --- /dev/null +++ b/lib/zend/Zend/Service/Ebay/Finding/Search/Item/Set.php @@ -0,0 +1,57 @@ +_nodes->item($this->_key); + if (!$node) { + return null; + } + + /** + * @see Zend_Service_Ebay_Finding_Search_Item + */ + require_once 'Zend/Service/Ebay/Finding/Search/Item.php'; + return new Zend_Service_Ebay_Finding_Search_Item($node); + } +} diff --git a/lib/zend/Zend/Service/Ebay/Finding/Search/Result.php b/lib/zend/Zend/Service/Ebay/Finding/Search/Result.php new file mode 100644 index 00000000000..9509b99625a --- /dev/null +++ b/lib/zend/Zend/Service/Ebay/Finding/Search/Result.php @@ -0,0 +1,63 @@ +_xPath->query(".//$ns:item", $this->_dom); + if ($nodes) { + /** + * @see Zend_Service_Ebay_Finding_Search_Item_Set + */ + require_once 'Zend/Service/Ebay/Finding/Search/Item/Set.php'; + $this->item = new Zend_Service_Ebay_Finding_Search_Item_Set($nodes); + } + } +} diff --git a/lib/zend/Zend/Service/Ebay/Finding/SellerInfo.php b/lib/zend/Zend/Service/Ebay/Finding/SellerInfo.php new file mode 100644 index 00000000000..4e7081ebdd5 --- /dev/null +++ b/lib/zend/Zend/Service/Ebay/Finding/SellerInfo.php @@ -0,0 +1,144 @@ +feedbackRatingStar = $this->_query(".//$ns:feedbackRatingStar[1]", 'string'); + $this->feedbackScore = $this->_query(".//$ns:feedbackScore[1]", 'integer'); + $this->positiveFeedbackPercent = $this->_query(".//$ns:positiveFeedbackPercent[1]", 'float'); + $this->sellerUserName = $this->_query(".//$ns:sellerUserName[1]", 'string'); + $this->topRatedSeller = $this->_query(".//$ns:topRatedSeller[1]", 'boolean'); + } +} diff --git a/lib/zend/Zend/Service/Ebay/Finding/SellingStatus.php b/lib/zend/Zend/Service/Ebay/Finding/SellingStatus.php new file mode 100644 index 00000000000..a6a3295607b --- /dev/null +++ b/lib/zend/Zend/Service/Ebay/Finding/SellingStatus.php @@ -0,0 +1,130 @@ +bidCount = $this->_query(".//$ns:bidCount[1]", 'integer'); + $this->convertedCurrentPrice = $this->_query(".//$ns:convertedCurrentPrice[1]", 'float'); + $this->currentPrice = $this->_query(".//$ns:currentPrice[1]", 'float'); + $this->sellingState = $this->_query(".//$ns:sellingState[1]", 'string'); + $this->timeLeft = $this->_query(".//$ns:timeLeft[1]", 'string'); + + $this->_attributes['convertedCurrentPrice'] = array( + 'currencyId' => $this->_query(".//$ns:convertedCurrentPrice[1]/@currencyId[1]", 'string') + ); + + $this->_attributes['currentPrice'] = array( + 'currencyId' => $this->_query(".//$ns:currentPrice[1]/@currencyId[1]", 'string') + ); + } +} diff --git a/lib/zend/Zend/Service/Ebay/Finding/Set/Abstract.php b/lib/zend/Zend/Service/Ebay/Finding/Set/Abstract.php new file mode 100644 index 00000000000..08abf109f90 --- /dev/null +++ b/lib/zend/Zend/Service/Ebay/Finding/Set/Abstract.php @@ -0,0 +1,128 @@ +_nodes = $nodes; + $this->_init(); + } + + /** + * Initialize object. + * + * Called from {@link __construct()} as final step of object initialization. + * + * @return void + */ + protected function _init() + { + } + + /** + * Implement SeekableIterator::seek() + * + * @param integer $key + * @throws OutOfBoundsException When $key is not seekable + * @return void + */ + public function seek($key) + { + if ($key < 0 || $key >= $this->count()) { + $message = "Position '{$key}' is not seekable."; + throw new OutOfBoundsException($message); + } + $this->_key = $key; + } + + /** + * Implement Iterator::key() + * + * @return integer + */ + public function key() + { + return $this->_key; + } + + /** + * Implement Iterator::next() + * + * @return void + */ + public function next() + { + $this->_key++; + } + + /** + * Implement Iterator::rewind() + * + * @return void + */ + public function rewind() + { + $this->_key = 0; + } + + /** + * Implement Iterator::valid() + * + * @return boolean + */ + public function valid() + { + return $this->_key >= 0 && $this->_key < $this->count(); + } + + /** + * Implement Countable::current() + * + * @return integer + */ + public function count() + { + return $this->_nodes ? $this->_nodes->length : 0; + } +} diff --git a/lib/zend/Zend/Service/Ebay/Finding/ShippingInfo.php b/lib/zend/Zend/Service/Ebay/Finding/ShippingInfo.php new file mode 100644 index 00000000000..a31257a0353 --- /dev/null +++ b/lib/zend/Zend/Service/Ebay/Finding/ShippingInfo.php @@ -0,0 +1,126 @@ +shippingServiceCost = $this->_query(".//$ns:shippingServiceCost[1]", 'float'); + $this->shippingType = $this->_query(".//$ns:shippingType[1]", 'string'); + $this->shipToLocations = $this->_query(".//$ns:shipToLocations", 'string', true); + + $this->_attributes['shippingServiceCost'] = array( + 'currencyId' => $this->_query(".//$ns:shippingServiceCost[1]/@currencyId[1]", 'string') + ); + } +} diff --git a/lib/zend/Zend/Service/Ebay/Finding/Storefront.php b/lib/zend/Zend/Service/Ebay/Finding/Storefront.php new file mode 100644 index 00000000000..a32ffb9be83 --- /dev/null +++ b/lib/zend/Zend/Service/Ebay/Finding/Storefront.php @@ -0,0 +1,73 @@ +storeName = $this->_query(".//$ns:storeName[1]", 'string'); + $this->storeURL = $this->_query(".//$ns:storeURL[1]", 'string'); + } + + /** + * @param Zend_Service_Ebay_Finding $proxy + * @param Zend_Config|array $options + * @return Zend_Service_Ebay_Finding_Response_Items + */ + public function findItems(Zend_Service_Ebay_Finding $proxy, $options = null) + { + return $proxy->findItemsInEbayStores($this->storeName, $options); + } +} diff --git a/lib/zend/Zend/Service/Exception.php b/lib/zend/Zend/Service/Exception.php index 6421b7b78f0..15beef5cc1c 100644 --- a/lib/zend/Zend/Service/Exception.php +++ b/lib/zend/Zend/Service/Exception.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Service - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -29,7 +29,7 @@ require_once 'Zend/Exception.php'; /** * @category Zend * @package Zend_Service - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Service_Exception extends Zend_Exception diff --git a/lib/zend/Zend/Service/Flickr.php b/lib/zend/Zend/Service/Flickr.php index af185f0ad18..a748ed4820a 100644 --- a/lib/zend/Zend/Service/Flickr.php +++ b/lib/zend/Zend/Service/Flickr.php @@ -16,17 +16,19 @@ * @category Zend * @package Zend_Service * @subpackage Flickr - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ +/** @see Zend_Xml_Security */ +require_once 'Zend/Xml/Security.php'; /** * @category Zend * @package Zend_Service * @subpackage Flickr - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Service_Flickr @@ -34,7 +36,7 @@ class Zend_Service_Flickr /** * Base URI for the REST client */ - const URI_BASE = 'http://www.flickr.com'; + const URI_BASE = 'https://www.flickr.com'; /** * Your Flickr API key @@ -62,10 +64,6 @@ class Zend_Service_Flickr */ public function __construct($apiKey) { - iconv_set_encoding('output_encoding', 'UTF-8'); - iconv_set_encoding('input_encoding', 'UTF-8'); - iconv_set_encoding('internal_encoding', 'UTF-8'); - $this->apiKey = (string) $apiKey; } @@ -118,8 +116,7 @@ class Zend_Service_Flickr } $dom = new DOMDocument(); - $dom->loadXML($response->getBody()); - + $dom = Zend_Xml_Security::scan($response->getBody(), $dom); self::_checkErrors($dom); /** @@ -182,8 +179,7 @@ class Zend_Service_Flickr } $dom = new DOMDocument(); - $dom->loadXML($response->getBody()); - + $dom = Zend_Xml_Security::scan($response->getBody(), $dom); self::_checkErrors($dom); /** @@ -237,8 +233,7 @@ class Zend_Service_Flickr } $dom = new DOMDocument(); - $dom->loadXML($response->getBody()); - + $dom = Zend_Xml_Security::scan($response->getBody(), $dom); self::_checkErrors($dom); /** @@ -287,7 +282,7 @@ class Zend_Service_Flickr } $dom = new DOMDocument(); - $dom->loadXML($response->getBody()); + $dom = Zend_Xml_Security::scan($response->getBody(), $dom); self::_checkErrors($dom); $xpath = new DOMXPath($dom); return (string) $xpath->query('//user')->item(0)->getAttribute('id'); @@ -331,7 +326,7 @@ class Zend_Service_Flickr } $dom = new DOMDocument(); - $dom->loadXML($response->getBody()); + $dom = Zend_Xml_Security::scan($response->getBody(), $dom); self::_checkErrors($dom); $xpath = new DOMXPath($dom); return (string) $xpath->query('//user')->item(0)->getAttribute('id'); @@ -364,7 +359,7 @@ class Zend_Service_Flickr $response = $restClient->restGet('/services/rest/', $options); $dom = new DOMDocument(); - $dom->loadXML($response->getBody()); + $dom = Zend_Xml_Security::scan($response->getBody(), $dom); $xpath = new DOMXPath($dom); self::_checkErrors($dom); $retval = array(); diff --git a/lib/zend/Zend/Service/Flickr/Image.php b/lib/zend/Zend/Service/Flickr/Image.php index fcf3063f8fc..197f9533990 100644 --- a/lib/zend/Zend/Service/Flickr/Image.php +++ b/lib/zend/Zend/Service/Flickr/Image.php @@ -16,7 +16,7 @@ * @category Zend * @package Zend_Service * @subpackage Flickr - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -26,7 +26,7 @@ * @category Zend * @package Zend_Service * @subpackage Flickr - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Service_Flickr_Image diff --git a/lib/zend/Zend/Service/Flickr/Result.php b/lib/zend/Zend/Service/Flickr/Result.php index 8fcea0812d4..8fad69a28a0 100644 --- a/lib/zend/Zend/Service/Flickr/Result.php +++ b/lib/zend/Zend/Service/Flickr/Result.php @@ -16,7 +16,7 @@ * @category Zend * @package Zend_Service * @subpackage Flickr - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -26,7 +26,7 @@ * @category Zend * @package Zend_Service * @subpackage Flickr - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Service_Flickr_Result diff --git a/lib/zend/Zend/Service/Flickr/ResultSet.php b/lib/zend/Zend/Service/Flickr/ResultSet.php index 2368627552e..31dd41050c5 100644 --- a/lib/zend/Zend/Service/Flickr/ResultSet.php +++ b/lib/zend/Zend/Service/Flickr/ResultSet.php @@ -16,7 +16,7 @@ * @category Zend * @package Zend_Service * @subpackage Flickr - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -32,7 +32,7 @@ require_once 'Zend/Service/Flickr/Result.php'; * @category Zend * @package Zend_Service * @subpackage Flickr - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Service_Flickr_ResultSet implements SeekableIterator diff --git a/lib/zend/Zend/Service/LiveDocx.php b/lib/zend/Zend/Service/LiveDocx.php index 02521327e89..7df6ebc44a1 100644 --- a/lib/zend/Zend/Service/LiveDocx.php +++ b/lib/zend/Zend/Service/LiveDocx.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Service * @subpackage LiveDocx - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -24,7 +24,7 @@ * @category Zend * @package Zend_Service * @subpackage LiveDocx - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @since LiveDocx 1.0 */ @@ -34,7 +34,7 @@ class Zend_Service_LiveDocx * LiveDocx service version * @since LiveDocx 1.0 */ - const VERSION = '1.2'; + const VERSION = '2.0'; /** * SOAP client used to connect to LiveDocx service @@ -42,37 +42,37 @@ class Zend_Service_LiveDocx * @since LiveDocx 1.0 */ protected $_soapClient; - + /** * WSDL of LiveDocx web service * @var string * @since LiveDocx 1.0 */ protected $_wsdl; - + /** * Array of credentials (username and password) to log into backend server * @var array * @since LiveDocx 1.2 */ protected $_credentials; - + /** * Set to true, when session is logged into backend server * @var boolean * @since LiveDocx 1.2 */ protected $_loggedIn; - + /** * Constructor * * Optionally, pass an array of options (or Zend_Config object). - * - * If an option with the key 'soapClient' is provided, that value will be + * + * If an option with the key 'soapClient' is provided, that value will be * used to set the internal SOAP client used to connect to the LiveDocx * service. - * + * * Use 'soapClient' in the case that you have a dedicated or (locally * installed) licensed LiveDocx server. For example: * @@ -85,7 +85,7 @@ class Zend_Service_LiveDocx * ) * ); * {code} - * + * * Replace the URI of the WSDL in the constructor of Zend_Soap_Client with * that of your dedicated or licensed LiveDocx server. * @@ -100,54 +100,54 @@ class Zend_Service_LiveDocx * ) * ); * {code} - * + * * If you prefer to not pass the username and password through the * constructor, you can also call the following methods: - * + * * {code} * $phpLiveDocx = new Zend_Service_LiveDocx_MailMerge(); - * + * * $phpLiveDocx->setUsername('myUsername') * ->setPassword('myPassword'); * {/code} - * + * * Or, if you want to specify your own SoapClient: - * + * * {code} * $phpLiveDocx = new Zend_Service_LiveDocx_MailMerge(); - * + * * $phpLiveDocx->setUsername('myUsername') * ->setPassword('myPassword'); - * + * * $phpLiveDocx->setSoapClient( * new Zend_Soap_Client('https://api.example.com/path/mailmerge.asmx?WSDL') * ); - * {/code} + * {/code} * * @param array|Zend_Config $options * @return void * @throws Zend_Service_LiveDocx_Exception * @since LiveDocx 1.0 - */ + */ public function __construct($options = null) { $this->_credentials = array(); $this->_loggedIn = false; - + if ($options instanceof Zend_Config) { $options = $options->toArray(); } - + if (is_array($options)) { $this->setOptions($options); } } - + /** * Set options * One or more of username, password, soapClient - * - * @param $options + * + * @param array $options * @return Zend_Service_LiveDocx * @since LiveDocx 1.2 */ @@ -159,10 +159,10 @@ class Zend_Service_LiveDocx $this->$method($value); } } - + return $this; } - + /** * Clean up and log out of LiveDocx service * @@ -173,7 +173,7 @@ class Zend_Service_LiveDocx { return $this->logOut(); } - + /** * Init Soap client - connect to SOAP service * @@ -187,13 +187,13 @@ class Zend_Service_LiveDocx try { require_once 'Zend/Soap/Client.php'; $this->_soapClient = new Zend_Soap_Client(); - $this->_soapClient->setWsdl($endpoint); + $this->_soapClient->setWsdl($endpoint); } catch (Zend_Soap_Client_Exception $e) { require_once 'Zend/Service/LiveDocx/Exception.php'; throw new Zend_Service_LiveDocx_Exception('Cannot connect to LiveDocx service at ' . $endpoint, 0, $e); - } + } } - + /** * Get SOAP client * @@ -204,7 +204,7 @@ class Zend_Service_LiveDocx { return $this->_soapClient; } - + /** * Set SOAP client * @@ -237,18 +237,18 @@ class Zend_Service_LiveDocx 'Username has not been set. To set username specify the options array in the constructor or call setUsername($username) after instantiation' ); } - + if (null === $this->getPassword()) { require_once 'Zend/Service/LiveDocx/Exception.php'; throw new Zend_Service_LiveDocx_Exception( 'Password has not been set. To set password specify the options array in the constructor or call setPassword($password) after instantiation' ); } - + if (null === $this->getSoapClient()) { $this->_initSoapClient($this->_wsdl); - } - + } + try { $this->getSoapClient()->LogIn(array( 'username' => $this->getUsername(), @@ -260,9 +260,9 @@ class Zend_Service_LiveDocx throw new Zend_Service_LiveDocx_Exception( 'Cannot login into LiveDocx service - username and/or password are invalid', 0, $e ); - } + } } - + return $this->_loggedIn; } @@ -284,15 +284,15 @@ class Zend_Service_LiveDocx throw new Zend_Service_LiveDocx_Exception( 'Cannot log out of LiveDocx service', 0, $e ); - } + } } - + return $this->_loggedIn; } - + /** * Return true, if session is currently logged into the backend server - * + * * @return boolean * @since LiveDocx 1.2 */ @@ -300,10 +300,10 @@ class Zend_Service_LiveDocx { return $this->_loggedIn; } - + /** * Set username - * + * * @return Zend_Service_LiveDocx * @since LiveDocx 1.0 */ @@ -312,13 +312,13 @@ class Zend_Service_LiveDocx $this->_credentials['username'] = $username; return $this; } - + /** * Set password - * + * * @return Zend_Service_LiveDocx * @since LiveDocx 1.0 - */ + */ public function setPassword($password) { $this->_credentials['password'] = $password; @@ -327,19 +327,19 @@ class Zend_Service_LiveDocx /** * Set WSDL of LiveDocx web service - * + * * @return Zend_Service_LiveDocx * @since LiveDocx 1.0 - */ - public function setWsdl($wsdl) + */ + public function setWsdl($wsdl) { $this->_wsdl = $wsdl; return $this; } - + /** * Return current username - * + * * @return string|null * @since LiveDocx 1.0 */ @@ -348,35 +348,35 @@ class Zend_Service_LiveDocx if (isset($this->_credentials['username'])) { return $this->_credentials['username']; } - + return null; } - + /** * Return current password - * + * * @return string|null * @since LiveDocx 1.0 - */ + */ public function getPassword() { if (isset($this->_credentials['password'])) { return $this->_credentials['password']; } - - return null; + + return null; } - + /** * Return WSDL of LiveDocx web service - * + * * @return Zend_Service_LiveDocx * @since LiveDocx 1.0 - */ - public function getWsdl() + */ + public function getWsdl() { return $this->_wsdl; - } + } /** * Return the document format (extension) of a filename @@ -389,7 +389,7 @@ class Zend_Service_LiveDocx { return strtolower(substr(strrchr($filename, '.'), 1)); } - + /** * Return the current API version * @@ -400,7 +400,7 @@ class Zend_Service_LiveDocx { return self::VERSION; } - + /** * Compare the current API version with another version * @@ -412,4 +412,4 @@ class Zend_Service_LiveDocx { return version_compare($version, $this->getVersion()); } -} \ No newline at end of file +} diff --git a/lib/zend/Zend/Service/LiveDocx/Exception.php b/lib/zend/Zend/Service/LiveDocx/Exception.php index a410e56bc25..53610c4afce 100644 --- a/lib/zend/Zend/Service/LiveDocx/Exception.php +++ b/lib/zend/Zend/Service/LiveDocx/Exception.php @@ -16,7 +16,7 @@ * @category Zend * @package Zend_Service * @subpackage LiveDocx - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -30,10 +30,10 @@ require_once 'Zend/Service/Exception.php'; * @category Zend * @package Zend_Service * @subpackage LiveDocx - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @since LiveDocx 1.0 */ class Zend_Service_LiveDocx_Exception extends Zend_Service_Exception { -} \ No newline at end of file +} diff --git a/lib/zend/Zend/Service/LiveDocx/MailMerge.php b/lib/zend/Zend/Service/LiveDocx/MailMerge.php index 487730ef47c..0287e73f890 100644 --- a/lib/zend/Zend/Service/LiveDocx/MailMerge.php +++ b/lib/zend/Zend/Service/LiveDocx/MailMerge.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Service * @subpackage LiveDocx - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -30,17 +30,18 @@ require_once 'Zend/Service/LiveDocx.php'; * @category Zend * @package Zend_Service * @subpackage LiveDocx - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License - * @since LiveDocx 1.0 + * @since LiveDocx 1.0 */ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx { /** * URI of LiveDocx.MailMerge WSDL - * @since LiveDocx 1.0 + * @since LiveDocx 1.0 */ - const WSDL = 'https://api.livedocx.com/1.2/mailmerge.asmx?WSDL'; + //const WSDL = 'https://api.livedocx.com/1.2/mailmerge.asmx?WSDL'; + const WSDL = 'https://api.livedocx.com/2.0/mailmerge.asmx?WSDL'; /** * Field values @@ -70,7 +71,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx $this->_wsdl = self::WSDL; $this->_fieldValues = array(); $this->_blockFieldValues = array(); - + parent::__construct($options); } @@ -85,8 +86,14 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx */ public function setLocalTemplate($filename) { + if (!is_readable($filename)) { + throw new Zend_Service_LiveDocx_Exception( + 'Cannot read local template from disk.' + ); + } + $this->logIn(); - + try { $this->getSoapClient()->SetLocalTemplate(array( 'template' => base64_encode(file_get_contents($filename)), @@ -114,7 +121,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx public function setRemoteTemplate($filename) { $this->logIn(); - + try { $this->getSoapClient()->SetRemoteTemplate(array( 'filename' => $filename, @@ -140,7 +147,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx public function setFieldValues($values) { $this->logIn(); - + foreach ($values as $value) { if (is_array($value)) { $method = 'multiAssocArrayToArrayOfArrayOfString'; @@ -149,7 +156,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx } break; } - + try { $this->getSoapClient()->SetFieldValues(array( 'fieldValues' => self::$method($values), @@ -177,7 +184,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx public function setFieldValue($field, $value) { $this->_fieldValues[$field] = $value; - + return $this; } @@ -194,7 +201,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx public function setBlockFieldValues($blockName, $blockFieldValues) { $this->logIn(); - + try { $this->getSoapClient()->SetBlockFieldValues(array( 'blockName' => $blockName, @@ -243,9 +250,9 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx /** * Set a password to open to document - * + * * This method can only be used for PDF documents - * + * * @param string $password * @return Zend_Service_LiveDocx_MailMerge * @throws Zend_Service_LiveDocx_Exception @@ -254,7 +261,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx public function setDocumentPassword($password) { $this->logIn(); - + try { $this->getSoapClient()->SetDocumentPassword(array( 'password' => $password @@ -265,18 +272,18 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx 'Cannot set document password. This method can be used on PDF files only.', 0, $e ); } - - return $this; + + return $this; } - + /** * Set a master password for document and determine which security features * are accessible without using the master password. - * + * * As default, nothing is allowed. To allow a security setting, * explicatively set it using one of he DOCUMENT_ACCESS_PERMISSION_* class - * constants. - * + * constants. + * * {code} * $phpLiveDocx->setDocumentAccessPermissions( * array ( @@ -286,10 +293,10 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx * 'myDocumentAccessPassword' * ); * {code} - * + * * This method can only be used for PDF documents - * - * @param array $permissions + * + * @param array $permissions * @param string $password * @return Zend_Service_LiveDocx_MailMerge * @throws Zend_Service_LiveDocx_Exception @@ -298,7 +305,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx public function setDocumentAccessPermissions($permissions, $password) { $this->logIn(); - + try { $this->getSoapClient()->SetDocumentAccessPermissions(array( 'permissions' => $permissions, @@ -310,10 +317,10 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx 'Cannot set document access permissions', 0, $e ); } - - return $this; - } - + + return $this; + } + /** * Merge assigned data with template to generate document * @@ -324,7 +331,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx public function createDocument() { $this->logIn(); - + if (count($this->_fieldValues) > 0) { $this->setFieldValues($this->_fieldValues); } @@ -354,9 +361,9 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx public function retrieveDocument($format) { $this->logIn(); - + $format = strtolower($format); - + try { $result = $this->getSoapClient()->RetrieveDocument(array( 'format' => $format, @@ -383,7 +390,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx public function getMetafiles($fromPage, $toPage) { $this->logIn(); - + $ret = array(); $result = $this->getSoapClient()->GetMetafiles(array( 'fromPage' => (integer) $fromPage, @@ -415,7 +422,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx public function getAllMetafiles() { $this->logIn(); - + $ret = array(); $result = $this->getSoapClient()->GetAllMetafiles(); @@ -432,8 +439,8 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx } return $ret; - } - + } + /** * Return graphical bitmap data for specified page range of created document * Return array contains bitmap data (binary) - array key is page number @@ -444,13 +451,13 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx * @param string $format * @return array * @since LiveDocx 1.2 - */ + */ public function getBitmaps($fromPage, $toPage, $zoomFactor, $format) { $this->logIn(); - + $ret = array(); - + $result = $this->getSoapClient()->GetBitmaps(array( 'fromPage' => (integer) $fromPage, 'toPage' => (integer) $toPage, @@ -470,9 +477,9 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx } } - return $ret; + return $ret; } - + /** * Return graphical bitmap data for all pages of created document * Return array contains bitmap data (binary) - array key is page number @@ -481,11 +488,11 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx * @param string $format * @return array * @since LiveDocx 1.2 - */ + */ public function getAllBitmaps($zoomFactor, $format) { $this->logIn(); - + $ret = array(); $result = $this->getSoapClient()->GetAllBitmaps(array( 'zoomFactor' => (integer) $zoomFactor, @@ -504,8 +511,8 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx } } - return $ret; - } + return $ret; + } /** * Return all the fields in the template @@ -516,7 +523,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx public function getFieldNames() { $this->logIn(); - + $ret = array(); $result = $this->getSoapClient()->GetFieldNames(); @@ -541,7 +548,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx public function getBlockFieldNames($blockName) { $this->logIn(); - + $ret = array(); $result = $this->getSoapClient()->GetBlockFieldNames(array( 'blockName' => $blockName @@ -567,7 +574,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx public function getBlockNames() { $this->logIn(); - + $ret = array(); $result = $this->getSoapClient()->GetBlockNames(); @@ -593,7 +600,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx public function uploadTemplate($filename) { $this->logIn(); - + try { $this->getSoapClient()->UploadTemplate(array( 'template' => base64_encode(file_get_contents($filename)), @@ -618,7 +625,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx public function downloadTemplate($filename) { $this->logIn(); - + try { $result = $this->getSoapClient()->DownloadTemplate(array( 'filename' => basename($filename), @@ -644,7 +651,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx public function deleteTemplate($filename) { $this->logIn(); - + $this->getSoapClient()->DeleteTemplate(array( 'filename' => basename($filename), )); @@ -654,12 +661,12 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx * List all templates stored on LiveDocx service * * @return array - * @since LiveDocx 1.0 + * @since LiveDocx 1.0 */ public function listTemplates() { $this->logIn(); - + $ret = array(); $result = $this->getSoapClient()->ListTemplates(); @@ -680,7 +687,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx public function templateExists($filename) { $this->logIn(); - + $result = $this->getSoapClient()->TemplateExists(array( 'filename' => basename($filename), )); @@ -697,7 +704,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx public function shareDocument() { $this->logIn(); - + $ret = null; $result = $this->getSoapClient()->ShareDocument(); @@ -717,7 +724,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx public function listSharedDocuments() { $this->logIn(); - + $ret = array(); $result = $this->getSoapClient()->ListSharedDocuments(); @@ -740,7 +747,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx public function deleteSharedDocument($filename) { $this->logIn(); - + $this->getSoapClient()->DeleteSharedDocument(array( 'filename' => basename($filename), )); @@ -757,7 +764,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx public function downloadSharedDocument($filename) { $this->logIn(); - + try { $result = $this->getSoapClient()->DownloadSharedDocument(array( 'filename' => basename($filename), @@ -782,11 +789,11 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx public function sharedDocumentExists($filename) { $this->logIn(); - + $ret = false; $sharedDocuments = $this->listSharedDocuments(); foreach ($sharedDocuments as $shareDocument) { - if (isset($shareDocument['filename']) + if (isset($shareDocument['filename']) && (basename($filename) === $shareDocument['filename']) ) { $ret = true; @@ -806,7 +813,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx public function getTemplateFormats() { $this->logIn(); - + $ret = array(); $result = $this->getSoapClient()->GetTemplateFormats(); @@ -827,7 +834,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx public function getDocumentFormats() { $this->logIn(); - + $ret = array(); $result = $this->getSoapClient()->GetDocumentFormats(); @@ -838,28 +845,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx return $ret; } - - /* - * Return supported image formats (lowercase) - * - * @return array - * @since LiveDocx 1.2 - */ - public function getImageFormats() - { - $this->logIn(); - - $ret = array(); - $result = $this->getSoapClient()->GetImageFormats(); - if (isset($result->GetImageFormatsResult->string)) { - $ret = $result->GetImageFormatsResult->string; - $ret = array_map('strtolower', $ret); - } - - return $ret; - } - /** * Return the names of all fonts that are installed on backend server * @@ -869,7 +855,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx public function getFontNames() { $this->logIn(); - + $ret = array(); $result = $this->getSoapClient()->GetFontNames(); @@ -878,8 +864,8 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx } return $ret; - } - + } + /** * Return supported document access options * @@ -889,7 +875,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx public function getDocumentAccessOptions() { $this->logIn(); - + $ret = array(); $result = $this->getSoapClient()->GetDocumentAccessOptions(); @@ -898,19 +884,190 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx } return $ret; - } + } + + /** + * Return supported image formats from which can be imported (lowercase) + * + * @return array + * @since LiveDocx 2.0 + */ + public function getImageImportFormats() + { + $this->logIn(); + + $ret = array(); + $result = $this->getSoapClient()->GetImageImportFormats(); + + if (isset($result->GetImageImportFormatsResult->string)) { + $ret = $result->GetImageImportFormatsResult->string; + $ret = array_map('strtolower', $ret); + } + + return $ret; + } + + /** + * Return supported image formats to which can be exported (lowercase) + * + * @return array + * @since LiveDocx 2.0 + */ + public function getImageExportFormats() + { + $this->logIn(); + + $ret = array(); + $result = $this->getSoapClient()->GetImageExportFormats(); + + if (isset($result->GetImageExportFormatsResult->string)) { + $ret = $result->GetImageExportFormatsResult->string; + $ret = array_map('strtolower', $ret); + } + + return $ret; + } + + /* + * Return supported image formats (lowercase) + * + * @return array + * @since LiveDocx 1.2 + * @deprecated since LiveDocx 2.0 + */ + public function getImageFormats() + { + $replacement = 'getImageExportFormats'; + + /* + $errorMessage = sprintf( + "%s::%s is deprecated as of LiveDocx 2.0. " + . "It has been replaced by %s::%s() (drop in replacement)", + __CLASS__, __FUNCTION__, __CLASS__, $replacement); + + trigger_error($errorMessage, E_USER_NOTICE); + */ + + return $this->$replacement(); + } + + /** + * Upload an image file to LiveDocx service + * + * @param string $filename + * @return void + * @throws Zend_Service_LiveDocx_Exception + * @since LiveDocx 2.0 + */ + public function uploadImage($filename) + { + $this->logIn(); + + try { + $this->getSoapClient()->UploadImage(array( + 'image' => base64_encode(file_get_contents($filename)), + 'filename' => basename($filename), + )); + } catch (Exception $e) { + require_once 'Zend/Service/LiveDocx/Exception.php'; + throw new Zend_Service_LiveDocx_Exception( + 'Cannot upload image', 0, $e + ); + } + } + + /** + * Download an image file from LiveDocx service + * + * @param string $filename + * @return void + * @throws Zend_Service_LiveDocx_Exception + * @since LiveDocx 2.0 + */ + public function downloadImage($filename) + { + $this->logIn(); + + try { + $result = $this->getSoapClient()->DownloadImage(array( + 'filename' => basename($filename), + )); + } catch (Exception $e) { + require_once 'Zend/Service/LiveDocx/Exception.php'; + throw new Zend_Service_LiveDocx_Exception( + 'Cannot download image', 0, $e + ); + } + + return base64_decode($result->DownloadImageResult); + } + + /** + * List all images stored on LiveDocx service + * + * @return array + * @since LiveDocx 2.0 + */ + public function listImages() + { + $this->logIn(); + + $ret = array(); + $result = $this->getSoapClient()->ListImages(); + + if (isset($result->ListImagesResult)) { + $ret = $this->_backendListArrayToMultiAssocArray($result->ListImagesResult); + } + + return $ret; + } + + /** + * Delete an image file from LiveDocx service + * + * @param string $filename + * @return void + * @throws Zend_Service_LiveDocx_Exception + * @since LiveDocx 2.0 + */ + public function deleteImage($filename) + { + $this->logIn(); + + $this->getSoapClient()->DeleteImage(array( + 'filename' => basename($filename), + )); + } + + /** + * Check whether an image file is available on LiveDocx service + * + * @param string $filename + * @return boolean + * @since LiveDocx 2.0 + */ + public function imageExists($filename) + { + $this->logIn(); + + $result = $this->getSoapClient()->ImageExists(array( + 'filename' => basename($filename), + )); + + return (boolean) $result->ImageExistsResult; + } /** * Convert LiveDocx service return value from list methods to consistent PHP array * * @param array $list * @return array - * @since LiveDocx 1.0 + * @since LiveDocx 1.0 */ protected function _backendListArrayToMultiAssocArray($list) { $this->logIn(); - + $ret = array(); if (isset($list->ArrayOfString)) { foreach ($list->ArrayOfString as $a) { @@ -951,7 +1108,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx { $arrayKeys = array_keys($assoc); $arrayValues = array_values($assoc); - + return array($arrayKeys, $arrayValues); } @@ -975,4 +1132,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx return array_merge($arrayKeys, $arrayValues); } -} \ No newline at end of file + + // ------------------------------------------------------------------------- + +} diff --git a/lib/zend/Zend/Service/Nirvanix.php b/lib/zend/Zend/Service/Nirvanix.php deleted file mode 100644 index a63075d6999..00000000000 --- a/lib/zend/Zend/Service/Nirvanix.php +++ /dev/null @@ -1,107 +0,0 @@ - array(), - 'httpClient' => new Zend_Http_Client(), - 'host' => 'http://services.nirvanix.com'); - $this->_options = array_merge($defaultOptions, $options); - - // login and save sessionToken to default POST params - $resp = $this->getService('Authentication')->login($authParams); - $this->_options['defaults']['sessionToken'] = (string)$resp->SessionToken; - } - - /** - * Nirvanix divides its service into namespaces, with each namespace - * providing different functionality. This is a factory method that - * returns a preconfigured Zend_Service_Nirvanix_Namespace_Base proxy. - * - * @param string $namespace Name of the namespace - * @return Zend_Service_Nirvanix_Namespace_Base - */ - public function getService($namespace, $options = array()) - { - switch ($namespace) { - case 'IMFS': - $class = 'Zend_Service_Nirvanix_Namespace_Imfs'; - break; - default: - $class = 'Zend_Service_Nirvanix_Namespace_Base'; - } - - $options['namespace'] = ucfirst($namespace); - $options = array_merge($this->_options, $options); - - if (!class_exists($class)) { - require_once 'Zend/Loader.php'; - Zend_Loader::loadClass($class); - } - return new $class($options); - } - - /** - * Get the configured options. - * - * @return array - */ - public function getOptions() - { - return $this->_options; - } - -} diff --git a/lib/zend/Zend/Service/Nirvanix/Namespace/Base.php b/lib/zend/Zend/Service/Nirvanix/Namespace/Base.php deleted file mode 100644 index a7bc1d0f98f..00000000000 --- a/lib/zend/Zend/Service/Nirvanix/Namespace/Base.php +++ /dev/null @@ -1,172 +0,0 @@ -_host = $options['baseUrl']; - } - - if (isset($options['namespace'])) { - $this->_namespace = $options['namespace']; - } - - if (isset($options['defaults'])) { - $this->_defaults = $options['defaults']; - } - - if (! isset($options['httpClient'])) { - $options['httpClient'] = new Zend_Http_Client(); - } - $this->_httpClient = $options['httpClient']; - } - - /** - * When a method call is made against this proxy, convert it to - * an HTTP request to make against the Nirvanix REST service. - * - * $imfs->DeleteFiles(array('filePath' => 'foo')); - * - * Assuming this object was proxying the IMFS namespace, the - * method call above would call the DeleteFiles command. The - * POST parameters would be filePath, merged with the - * $this->_defaults (containing the sessionToken). - * - * @param string $methodName Name of the command to call - * on this namespace. - * @param array $args Only the first is used and it must be - * an array. It contains the POST params. - * - * @return Zend_Service_Nirvanix_Response - */ - public function __call($methodName, $args) - { - $uri = $this->_makeUri($methodName); - $this->_httpClient->setUri($uri); - - if (!isset($args[0]) || !is_array($args[0])) { - $args[0] = array(); - } - - $params = array_merge($this->_defaults, $args[0]); - $this->_httpClient->resetParameters(); - $this->_httpClient->setParameterPost($params); - - $httpResponse = $this->_httpClient->request(Zend_Http_Client::POST); - return $this->_wrapResponse($httpResponse); - } - - /** - * Return the HTTP client used for this namespace. This is useful - * for inspecting the last request or directly interacting with the - * HTTP client. - * - * @return Zend_Http_Client - */ - public function getHttpClient() - { - return $this->_httpClient; - } - - /** - * Make a complete URI from an RPC method name. All Nirvanix REST - * service URIs use the same format. - * - * @param string $methodName RPC method name - * @return string - */ - protected function _makeUri($methodName) - { - $methodName = ucfirst($methodName); - return "{$this->_host}/ws/{$this->_namespace}/{$methodName}.ashx"; - } - - /** - * All Nirvanix REST service calls return an XML payload. This method - * makes a Zend_Service_Nirvanix_Response from that XML payload. - * - * @param Zend_Http_Response $httpResponse Raw response from Nirvanix - * @return Zend_Service_Nirvanix_Response Wrapped response - */ - protected function _wrapResponse($httpResponse) - { - return new Zend_Service_Nirvanix_Response($httpResponse->getBody()); - } -} diff --git a/lib/zend/Zend/Service/Nirvanix/Namespace/Imfs.php b/lib/zend/Zend/Service/Nirvanix/Namespace/Imfs.php deleted file mode 100644 index 86907ad323f..00000000000 --- a/lib/zend/Zend/Service/Nirvanix/Namespace/Imfs.php +++ /dev/null @@ -1,105 +0,0 @@ - $filePath, - 'expiration' => $expiration); - $resp = $this->getOptimalUrls($params); - $url = (string)$resp->Download->DownloadURL; - - // download the file - $this->_httpClient->resetParameters(); - $this->_httpClient->setUri($url); - $resp = $this->_httpClient->request(Zend_Http_Client::GET); - - return $resp->getBody(); - } - - /** - * Convenience function to put the contents of a string into - * the Nirvanix IMFS. Analog to PHP's file_put_contents(). - * - * @param string $filePath Remote path and filename - * @param integer $data Data to store in the file - * @param string $mimeType Mime type of data - * @return Zend_Service_Nirvanix_Response - */ - public function putContents($filePath, $data, $mimeType = null) - { - // get storage node for upload - $params = array('sizeBytes' => strlen($data)); - $resp = $this->getStorageNode($params); - $host = (string)$resp->GetStorageNode->UploadHost; - $uploadToken = (string)$resp->GetStorageNode->UploadToken; - - // http upload data into remote file - $this->_httpClient->resetParameters(); - $this->_httpClient->setUri("http://{$host}/Upload.ashx"); - $this->_httpClient->setParameterPost('uploadToken', $uploadToken); - $this->_httpClient->setParameterPost('destFolderPath', str_replace('\\', '/',dirname($filePath))); - $this->_httpClient->setFileUpload(basename($filePath), 'uploadFile', $data, $mimeType); - $response = $this->_httpClient->request(Zend_Http_Client::POST); - - return new Zend_Service_Nirvanix_Response($response->getBody()); - } - - /** - * Convenience function to remove a file from the Nirvanix IMFS. - * Analog to PHP's unlink(). - * - * @param string $filePath Remove path and filename - * @return Zend_Service_Nirvanix_Response - */ - public function unlink($filePath) - { - $params = array('filePath' => $filePath); - return $this->deleteFiles($params); - } - -} diff --git a/lib/zend/Zend/Service/Nirvanix/Response.php b/lib/zend/Zend/Service/Nirvanix/Response.php deleted file mode 100644 index b1de6422f7a..00000000000 --- a/lib/zend/Zend/Service/Nirvanix/Response.php +++ /dev/null @@ -1,123 +0,0 @@ - contains an error. - * - * @category Zend - * @package Zend_Service - * @subpackage Nirvanix - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - */ -class Zend_Service_Nirvanix_Response -{ - /** - * SimpleXMLElement parsed from Nirvanix web service response. - * - * @var SimpleXMLElement - */ - protected $_sxml; - - /** - * Class constructor. Parse the XML response from a Nirvanix method - * call into a decorated SimpleXMLElement element. - * - * @param string $xml XML response string from Nirvanix - * @throws Zend_Service_Nirvanix_Exception - */ - public function __construct($xml) - { - $this->_sxml = @simplexml_load_string($xml); - - if (! $this->_sxml instanceof SimpleXMLElement) { - $this->_throwException("XML could not be parsed from response: $xml"); - } - - $name = $this->_sxml->getName(); - if ($name != 'Response') { - $this->_throwException("Expected XML element Response, got $name"); - } - - $code = (int)$this->_sxml->ResponseCode; - if ($code != 0) { - $msg = (string)$this->_sxml->ErrorMessage; - $this->_throwException($msg, $code); - } - } - - /** - * Return the SimpleXMLElement representing this response - * for direct access. - * - * @return SimpleXMLElement - */ - public function getSxml() - { - return $this->_sxml; - } - - /** - * Delegate undefined properties to the decorated SimpleXMLElement. - * - * @param string $offset Undefined property name - * @return mixed - */ - public function __get($offset) - { - return $this->_sxml->$offset; - } - - /** - * Delegate undefined methods to the decorated SimpleXMLElement. - * - * @param string $offset Underfined method name - * @param array $args Method arguments - * @return mixed - */ - public function __call($method, $args) - { - return call_user_func_array(array($this->_sxml, $method), $args); - } - - /** - * Throw an exception. This method exists to only contain the - * lazy-require() of the exception class. - * - * @param string $message Error message - * @param integer $code Error code - * @throws Zend_Service_Nirvanix_Exception - * @return void - */ - protected function _throwException($message, $code = null) - { - /** - * @see Zend_Service_Nirvanix_Exception - */ - require_once 'Zend/Service/Nirvanix/Exception.php'; - - throw new Zend_Service_Nirvanix_Exception($message, $code); - } - -} diff --git a/lib/zend/Zend/Service/Rackspace/Abstract.php b/lib/zend/Zend/Service/Rackspace/Abstract.php new file mode 100644 index 00000000000..afec6a4e5db --- /dev/null +++ b/lib/zend/Zend/Service/Rackspace/Abstract.php @@ -0,0 +1,392 @@ +setUser($user); + $this->setKey($key); + $this->setAuthUrl($authUrl); + } + /** + * Get User account + * + * @return string + */ + public function getUser() + { + return $this->user; + } + /** + * Get user key + * + * @return string + */ + public function getKey() + { + return $this->key; + } + /** + * Get authentication URL + * + * @return string + */ + public function getAuthUrl() + { + return $this->authUrl; + } + /** + * Get the storage URL + * + * @return string|boolean + */ + public function getStorageUrl() + { + if (empty($this->storageUrl)) { + if (!$this->authenticate()) { + return false; + } + } + return $this->storageUrl; + } + /** + * Get the CDN URL + * + * @return string|boolean + */ + public function getCdnUrl() + { + if (empty($this->cdnUrl)) { + if (!$this->authenticate()) { + return false; + } + } + return $this->cdnUrl; + } + /** + * Get the management server URL + * + * @return string|boolean + */ + public function getManagementUrl() + { + if (empty($this->managementUrl)) { + if (!$this->authenticate()) { + return false; + } + } + return $this->managementUrl; + } + /** + * Set the user account + * + * @param string $user + * @return void + */ + public function setUser($user) + { + if (!empty($user)) { + $this->user = $user; + } + } + /** + * Set the authentication key + * + * @param string $key + * @return void + */ + public function setKey($key) + { + if (!empty($key)) { + $this->key = $key; + } + } + /** + * Set the Authentication URL + * + * @param string $url + * @return void + */ + public function setAuthUrl($url) + { + if (!empty($url) && in_array($url, array(self::US_AUTH_URL, self::UK_AUTH_URL))) { + $this->authUrl = $url; + } else { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception("The authentication URL is not valid"); + } + } + + /** + * Sets whether to use ServiceNet + * + * ServiceNet is Rackspace's internal network. Bandwidth on ServiceNet is + * not charged. + * + * @param boolean $useServiceNet + */ + public function setServiceNet($useServiceNet = true) + { + $this->useServiceNet = $useServiceNet; + return $this; + } + + /** + * Get whether we're using ServiceNet + * + * @return boolean + */ + public function getServiceNet() + { + return $this->useServiceNet; + } + + /** + * Get the authentication token + * + * @return string + */ + public function getToken() + { + if (empty($this->token)) { + if (!$this->authenticate()) { + return false; + } + } + return $this->token; + } + /** + * Get the error msg of the last HTTP call + * + * @return string + */ + public function getErrorMsg() + { + return $this->errorMsg; + } + /** + * Get the error code of the last HTTP call + * + * @return strig + */ + public function getErrorCode() + { + return $this->errorCode; + } + /** + * get the HttpClient instance + * + * @return Zend_Http_Client + */ + public function getHttpClient() + { + if (empty($this->httpClient)) { + $this->httpClient = new Zend_Http_Client(); + } + return $this->httpClient; + } + /** + * Return true is the last call was successful + * + * @return boolean + */ + public function isSuccessful() + { + return ($this->errorMsg==''); + } + /** + * HTTP call + * + * @param string $url + * @param string $method + * @param array $headers + * @param array $get + * @param string $body + * @return Zend_Http_Response + */ + protected function httpCall($url,$method,$headers=array(),$data=array(),$body=null) + { + $client = $this->getHttpClient(); + $client->resetParameters(true); + if ($method == 'PUT' && empty($body)) { + // if left at NULL a PUT request will always have + // Content-Type: x-url-form-encoded, which breaks copyObject() + $client->setEncType(''); + } + if (empty($headers[self::AUTHUSER_HEADER])) { + $headers[self::AUTHTOKEN]= $this->getToken(); + } + $client->setMethod($method); + if (empty($data['format'])) { + $data['format']= self::API_FORMAT; + } + $client->setParameterGet($data); + if (!empty($body)) { + $client->setRawData($body); + if (!isset($headers['Content-Type'])) { + $headers['Content-Type']= 'application/json'; + } + } + $client->setHeaders($headers); + $client->setUri($url); + $this->errorMsg=''; + $this->errorCode=''; + return $client->request(); + } + /** + * Authentication + * + * @return boolean + */ + public function authenticate() + { + if (empty($this->user)) { + /** + * @see Zend_Service_Rackspace_Exception + */ + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception("User has not been set"); + } + + $headers = array ( + self::AUTHUSER_HEADER => $this->user, + self::AUTHKEY_HEADER => $this->key + ); + $result = $this->httpCall($this->authUrl.'/'.self::VERSION,'GET', $headers); + if ($result->getStatus()==204) { + $this->token = $result->getHeader(self::AUTHTOKEN); + $this->cdnUrl = $result->getHeader(self::CDNM_URL); + $this->managementUrl = $result->getHeader(self::MANAGEMENT_URL); + $storageUrl = $result->getHeader(self::STORAGE_URL); + if ($this->useServiceNet) { + $storageUrl = preg_replace('|(.*)://([^/]*)(.*)|', '$1://snet-$2$3', $storageUrl); + } + $this->storageUrl = $storageUrl; + return true; + } + $this->errorMsg = $result->getBody(); + $this->errorCode = $result->getStatus(); + return false; + } +} diff --git a/lib/zend/Zend/Service/Nirvanix/Exception.php b/lib/zend/Zend/Service/Rackspace/Exception.php similarity index 78% rename from lib/zend/Zend/Service/Nirvanix/Exception.php rename to lib/zend/Zend/Service/Rackspace/Exception.php index d81d4d13ba4..3074fff06af 100644 --- a/lib/zend/Zend/Service/Nirvanix/Exception.php +++ b/lib/zend/Zend/Service/Rackspace/Exception.php @@ -14,8 +14,8 @@ * * @category Zend * @package Zend_Service - * @subpackage Nirvanix - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @subpackage Rackspace + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -28,9 +28,9 @@ require_once 'Zend/Service/Exception.php'; /** * @category Zend * @package Zend_Service - * @subpackage Nirvanix - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @subpackage Rackspace + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class Zend_Service_Nirvanix_Exception extends Zend_Service_Exception +class Zend_Service_Rackspace_Exception extends Zend_Service_Exception {} diff --git a/lib/zend/Zend/Service/Rackspace/Files.php b/lib/zend/Zend/Service/Rackspace/Files.php new file mode 100644 index 00000000000..fd4bc6036a9 --- /dev/null +++ b/lib/zend/Zend/Service/Rackspace/Files.php @@ -0,0 +1,727 @@ +getInfoAccount(); + return $data['tot_containers']; + } + /** + * Return the size in bytes of all the containers + * + * @return int + */ + public function getSizeContainers() + { + $data= $this->getInfoAccount(); + return $data['size_containers']; + } + /** + * Return the count of objects contained in all the containers + * + * @return int + */ + public function getCountObjects() + { + $data= $this->getInfoAccount(); + return $data['tot_objects']; + } + /** + * Get all the containers + * + * @param array $options + * @return Zend_Service_Rackspace_Files_ContainerList|bool + */ + public function getContainers($options=array()) + { + $result= $this->httpCall($this->getStorageUrl(),'GET',null,$options); + if ($result->isSuccessful()) { + return new Zend_Service_Rackspace_Files_ContainerList($this,json_decode($result->getBody(),true)); + } + return false; + } + /** + * Get all the CDN containers + * + * @param array $options + * @return array|bool + */ + public function getCdnContainers($options=array()) + { + $options['enabled_only']= true; + $result= $this->httpCall($this->getCdnUrl(),'GET',null,$options); + if ($result->isSuccessful()) { + return new Zend_Service_Rackspace_Files_ContainerList($this,json_decode($result->getBody(),true)); + } + return false; + } + /** + * Get the metadata information of the accounts: + * - total count containers + * - size in bytes of all the containers + * - total objects in all the containers + * + * @return array|bool + */ + public function getInfoAccount() + { + $result= $this->httpCall($this->getStorageUrl(),'HEAD'); + if ($result->isSuccessful()) { + $output= array( + 'tot_containers' => $result->getHeader(self::ACCOUNT_CONTAINER_COUNT), + 'size_containers' => $result->getHeader(self::ACCOUNT_BYTES_USED), + 'tot_objects' => $result->getHeader(self::ACCOUNT_OBJ_COUNT) + ); + return $output; + } + return false; + } + + /** + * Get all the objects of a container + * + * Returns a maximum of 10,000 object names. + * + * @param string $container + * @param array $options + * @return bool|Zend_Service_Rackspace_Files_ObjectList + * @throws Zend_Service_Rackspace_Exception + */ + public function getObjects($container,$options=array()) + { + if (empty($container)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_CONTAINER); + } + $result= $this->httpCall($this->getStorageUrl().'/'.rawurlencode($container),'GET',null,$options); + if ($result->isSuccessful()) { + return new Zend_Service_Rackspace_Files_ObjectList($this,json_decode($result->getBody(),true),$container); + } + return false; + } + + /** + * Create a container + * + * @param string $container + * @param array $metadata + * @return bool|Zend_Service_Rackspace_Files_Container + * @throws Zend_Service_Rackspace_Exception + */ + public function createContainer($container,$metadata=array()) + { + if (empty($container)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_CONTAINER); + } + $headers=array(); + if (!empty($metadata)) { + foreach ($metadata as $key => $value) { + $headers[self::METADATA_CONTAINER_HEADER.rawurlencode(strtolower($key))]= rawurlencode($value); + } + } + $result= $this->httpCall($this->getStorageUrl().'/'.rawurlencode($container),'PUT',$headers); + $status= $result->getStatus(); + switch ($status) { + case '201': // break intentionally omitted + $data= array( + 'name' => $container + ); + return new Zend_Service_Rackspace_Files_Container($this,$data); + case '202': + $this->errorMsg= self::ERROR_CONTAINER_EXIST; + break; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } + + /** + * Delete a container (only if it's empty) + * + * @param string $container + * @return bool + * @throws Zend_Service_Rackspace_Exception + */ + public function deleteContainer($container) + { + if (empty($container)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_CONTAINER); + } + $result= $this->httpCall($this->getStorageUrl().'/'.rawurlencode($container),'DELETE'); + $status= $result->getStatus(); + switch ($status) { + case '204': // break intentionally omitted + return true; + case '409': + $this->errorMsg= self::ERROR_CONTAINER_NOT_EMPTY; + break; + case '404': + $this->errorMsg= self::ERROR_CONTAINER_NOT_FOUND; + break; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } + + /** + * Get the metadata of a container + * + * @param string $container + * @return array|bool + * @throws Zend_Service_Rackspace_Exception + */ + public function getMetadataContainer($container) + { + if (empty($container)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_CONTAINER); + } + $result= $this->httpCall($this->getStorageUrl().'/'.rawurlencode($container),'HEAD'); + $status= $result->getStatus(); + switch ($status) { + case '204': // break intentionally omitted + $headers= $result->getHeaders(); + $count= strlen(self::METADATA_CONTAINER_HEADER); + // Zend_Http_Response alters header name in array key, so match our header to what will be in the headers array + $headerName = ucwords(strtolower(self::METADATA_CONTAINER_HEADER)); + $metadata= array(); + foreach ($headers as $type => $value) { + if (strpos($type,$headerName)!==false) { + $metadata[strtolower(substr($type, $count))]= $value; + } + } + $data= array ( + 'name' => $container, + 'count' => $result->getHeader(self::CONTAINER_OBJ_COUNT), + 'bytes' => $result->getHeader(self::CONTAINER_BYTES_USE), + 'metadata' => $metadata + ); + return $data; + case '404': + $this->errorMsg= self::ERROR_CONTAINER_NOT_FOUND; + break; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } + /** + * Get a container + * + * @param string $container + * @return Zend_Service_Rackspace_Files_Container|bool + */ + public function getContainer($container) { + $result= $this->getMetadataContainer($container); + if (!empty($result)) { + return new Zend_Service_Rackspace_Files_Container($this,$result); + } + return false; + } + + /** + * Get an object in a container + * + * @param string $container + * @param string $object + * @param array $headers + * @return bool|Zend_Service_Rackspace_Files_Object + * @throws Zend_Service_Rackspace_Exception + */ + public function getObject($container,$object,$headers=array()) + { + if (empty($container)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_CONTAINER); + } + if (empty($object)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_OBJECT); + } + $result= $this->httpCall($this->getStorageUrl().'/'.rawurlencode($container).'/'.rawurlencode($object),'GET',$headers); + $status= $result->getStatus(); + switch ($status) { + case '200': // break intentionally omitted + $data= array( + 'name' => $object, + 'container' => $container, + 'hash' => $result->getHeader(self::HEADER_HASH), + 'bytes' => $result->getHeader(self::HEADER_CONTENT_LENGTH), + 'last_modified' => $result->getHeader(self::HEADER_LAST_MODIFIED), + 'content_type' => $result->getHeader(self::HEADER_CONTENT_TYPE), + 'content' => $result->getBody() + ); + return new Zend_Service_Rackspace_Files_Object($this,$data); + case '404': + $this->errorMsg= self::ERROR_OBJECT_NOT_FOUND; + break; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } + + /** + * Store a file in a container + * + * @param string $container + * @param string $object + * @param string $content + * @param array $metadata + * @param string $content_type + * @return bool + * @throws Zend_Service_Rackspace_Exception + */ + public function storeObject($container,$object,$content,$metadata=array(),$content_type=null) { + if (empty($container)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_CONTAINER); + } + if (empty($object)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_OBJECT); + } + if (empty($content)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_CONTENT); + } + if (!empty($content_type)) { + $headers[self::HEADER_CONTENT_TYPE]= $content_type; + } + if (!empty($metadata) && is_array($metadata)) { + foreach ($metadata as $key => $value) { + $headers[self::METADATA_OBJECT_HEADER.$key]= $value; + } + } + $headers[self::HEADER_HASH]= md5($content); + $headers[self::HEADER_CONTENT_LENGTH]= strlen($content); + $result= $this->httpCall($this->getStorageUrl().'/'.rawurlencode($container).'/'.rawurlencode($object),'PUT',$headers,null,$content); + $status= $result->getStatus(); + switch ($status) { + case '201': // break intentionally omitted + return true; + case '412': + $this->errorMsg= self::ERROR_OBJECT_MISSING_PARAM; + break; + case '422': + $this->errorMsg= self::ERROR_OBJECT_CHECKSUM; + break; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } + + /** + * Delete an object in a container + * + * @param string $container + * @param string $object + * @return bool + * @throws Zend_Service_Rackspace_Exception + */ + public function deleteObject($container,$object) { + if (empty($container)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_CONTAINER); + } + if (empty($object)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_OBJECT); + } + $result= $this->httpCall($this->getStorageUrl().'/'.rawurlencode($container).'/'.rawurlencode($object),'DELETE'); + $status= $result->getStatus(); + switch ($status) { + case '204': // break intentionally omitted + return true; + case '404': + $this->errorMsg= self::ERROR_OBJECT_NOT_FOUND; + break; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } + + /** + * Copy an object from a container to another + * + * @param string $container_source + * @param string $obj_source + * @param string $container_dest + * @param string $obj_dest + * @param array $metadata + * @param string $content_type + * @return bool + * @throws Zend_Service_Rackspace_Exception + */ + public function copyObject($container_source,$obj_source,$container_dest,$obj_dest,$metadata=array(),$content_type=null) { + if (empty($container_source)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_SOURCE_CONTAINER); + } + if (empty($obj_source)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_SOURCE_OBJECT); + } + if (empty($container_dest)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_DEST_CONTAINER); + } + if (empty($obj_dest)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_DEST_OBJECT); + } + $headers= array( + self::HEADER_COPY_FROM => '/'.rawurlencode($container_source).'/'.rawurlencode($obj_source), + self::HEADER_CONTENT_LENGTH => 0 + ); + if (!empty($content_type)) { + $headers[self::HEADER_CONTENT_TYPE]= $content_type; + } + if (!empty($metadata) && is_array($metadata)) { + foreach ($metadata as $key => $value) { + $headers[self::METADATA_OBJECT_HEADER.$key]= $value; + } + } + $result= $this->httpCall($this->getStorageUrl().'/'.rawurlencode($container_dest).'/'.rawurlencode($obj_dest),'PUT',$headers); + $status= $result->getStatus(); + switch ($status) { + case '201': // break intentionally omitted + return true; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } + + /** + * Get the metadata of an object + * + * @param string $container + * @param string $object + * @return array|bool + * @throws Zend_Service_Rackspace_Exception + */ + public function getMetadataObject($container,$object) { + if (empty($container)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_CONTAINER); + } + if (empty($object)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_OBJECT); + } + $result= $this->httpCall($this->getStorageUrl().'/'.rawurlencode($container).'/'.rawurlencode($object),'HEAD'); + $status= $result->getStatus(); + switch ($status) { + case '200': // break intentionally omitted + $headers= $result->getHeaders(); + $count= strlen(self::METADATA_OBJECT_HEADER); + // Zend_Http_Response alters header name in array key, so match our header to what will be in the headers array + $headerName = ucwords(strtolower(self::METADATA_OBJECT_HEADER)); + $metadata= array(); + foreach ($headers as $type => $value) { + if (strpos($type,$headerName)!==false) { + $metadata[strtolower(substr($type, $count))]= $value; + } + } + $data= array ( + 'name' => $object, + 'container' => $container, + 'hash' => $result->getHeader(self::HEADER_HASH), + 'bytes' => $result->getHeader(self::HEADER_CONTENT_LENGTH), + 'content_type' => $result->getHeader(self::HEADER_CONTENT_TYPE), + 'last_modified' => $result->getHeader(self::HEADER_LAST_MODIFIED), + 'metadata' => $metadata + ); + return $data; + case '404': + $this->errorMsg= self::ERROR_OBJECT_NOT_FOUND; + break; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } + + /** + * Set the metadata of a object in a container + * The old metadata values are replaced with the new one + * + * @param string $container + * @param string $object + * @param array $metadata + * @return bool + * @throws Zend_Service_Rackspace_Exception + */ + public function setMetadataObject($container,$object,$metadata) + { + if (empty($container)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_CONTAINER); + } + if (empty($object)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_OBJECT); + } + if (empty($metadata) || !is_array($metadata)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_OBJECT); + } + $headers=array(); + foreach ($metadata as $key => $value) { + $headers[self::METADATA_OBJECT_HEADER.$key]= $value; + } + $result= $this->httpCall($this->getStorageUrl().'/'.rawurlencode($container).'/'.rawurlencode($object),'POST',$headers); + $status= $result->getStatus(); + switch ($status) { + case '202': // break intentionally omitted + return true; + case '404': + $this->errorMsg= self::ERROR_OBJECT_NOT_FOUND; + break; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } + + /** + * Enable the CDN for a container + * + * @param string $container + * @param int $ttl + * @return array|bool + * @throws Zend_Service_Rackspace_Exception + */ + public function enableCdnContainer ($container,$ttl=self::CDN_TTL_MIN) { + if (empty($container)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_CONTAINER); + } + $headers=array(); + if (is_numeric($ttl) && ($ttl>=self::CDN_TTL_MIN) && ($ttl<=self::CDN_TTL_MAX)) { + $headers[self::CDN_TTL]= $ttl; + } else { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_CDN_TTL_OUT_OF_RANGE); + } + $result= $this->httpCall($this->getCdnUrl().'/'.rawurlencode($container),'PUT',$headers); + $status= $result->getStatus(); + switch ($status) { + case '201': + case '202': // break intentionally omitted + $data= array ( + 'cdn_uri' => $result->getHeader(self::CDN_URI), + 'cdn_uri_ssl' => $result->getHeader(self::CDN_SSL_URI) + ); + return $data; + case '404': + $this->errorMsg= self::ERROR_CONTAINER_NOT_FOUND; + break; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } + + /** + * Update the attribute of a CDN container + * + * @param string $container + * @param int $ttl + * @param bool $cdn_enabled + * @param bool $log + * @return bool + * @throws Zend_Service_Rackspace_Exception + */ + public function updateCdnContainer($container,$ttl=null,$cdn_enabled=null,$log=null) + { + if (empty($container)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_CONTAINER); + } + if (empty($ttl) && (!isset($cdn_enabled)) && (!isset($log))) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_UPDATE_CDN); + } + $headers=array(); + if (isset($ttl)) { + if (is_numeric($ttl) && ($ttl>=self::CDN_TTL_MIN) && ($ttl<=self::CDN_TTL_MAX)) { + $headers[self::CDN_TTL]= $ttl; + } else { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_CDN_TTL_OUT_OF_RANGE); + } + } + if (isset($cdn_enabled)) { + if ($cdn_enabled===true) { + $headers[self::CDN_ENABLED]= 'true'; + } else { + $headers[self::CDN_ENABLED]= 'false'; + } + } + if (isset($log)) { + if ($log===true) { + $headers[self::CDN_LOG_RETENTION]= 'true'; + } else { + $headers[self::CDN_LOG_RETENTION]= 'false'; + } + } + $result= $this->httpCall($this->getCdnUrl().'/'.rawurlencode($container),'POST',$headers); + $status= $result->getStatus(); + switch ($status) { + case '200': + case '202': // break intentionally omitted + return true; + case '404': + $this->errorMsg= self::ERROR_CONTAINER_NOT_FOUND; + break; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } + + /** + * Get the information of a Cdn container + * + * @param string $container + * @return array|bool + * @throws Zend_Service_Rackspace_Exception + */ + public function getInfoCdnContainer($container) { + if (empty($container)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_CONTAINER); + } + $result= $this->httpCall($this->getCdnUrl().'/'.rawurlencode($container),'HEAD'); + $status= $result->getStatus(); + switch ($status) { + case '204': // break intentionally omitted + $data= array ( + 'ttl' => $result->getHeader(self::CDN_TTL), + 'cdn_uri' => $result->getHeader(self::CDN_URI), + 'cdn_uri_ssl' => $result->getHeader(self::CDN_SSL_URI) + ); + $data['cdn_enabled']= (strtolower($result->getHeader(self::CDN_ENABLED))!=='false'); + $data['log_retention']= (strtolower($result->getHeader(self::CDN_LOG_RETENTION))!=='false'); + return $data; + case '404': + $this->errorMsg= self::ERROR_CONTAINER_NOT_FOUND; + break; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } +} diff --git a/lib/zend/Zend/Service/Rackspace/Files/Container.php b/lib/zend/Zend/Service/Rackspace/Files/Container.php new file mode 100644 index 00000000000..da6b7046237 --- /dev/null +++ b/lib/zend/Zend/Service/Rackspace/Files/Container.php @@ -0,0 +1,405 @@ +service = $service; + $this->name = $data['name']; + } + + /** + * Get the name of the container + * + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * Get the size in bytes of the container + * + * @return integer|bool + */ + public function getSize() + { + $data = $this->getInfo(); + if (isset($data['bytes'])) { + return $data['bytes']; + } + + return false; + } + + /** + * Get the total count of objects in the container + * + * @return integer|bool + */ + public function getObjectCount() + { + $data = $this->getInfo(); + if (isset($data['count'])) { + return $data['count']; + } + + return false; + } + + /** + * Return true if the container is CDN enabled + * + * @return bool + */ + public function isCdnEnabled() + { + $data = $this->getCdnInfo(); + if (isset($data['cdn_enabled'])) { + return $data['cdn_enabled']; + } + + return false; + } + + /** + * Get the TTL of the CDN + * + * @return integer|bool + */ + public function getCdnTtl() + { + $data = $this->getCdnInfo(); + if (isset($data['ttl'])) { + return $data['ttl']; + } + + return false; + } + + /** + * Return true if the log retention is enabled for the CDN + * + * @return bool + */ + public function isCdnLogEnabled() + { + $data = $this->getCdnInfo(); + if (isset($data['log_retention'])) { + return $data['log_retention']; + } + + return false; + } + + /** + * Get the CDN URI + * + * @return string|bool + */ + public function getCdnUri() + { + $data = $this->getCdnInfo(); + if (isset($data['cdn_uri'])) { + return $data['cdn_uri']; + } + + return false; + } + + /** + * Get the CDN URI SSL + * + * @return string|bool + */ + public function getCdnUriSsl() + { + $data = $this->getCdnInfo(); + if (isset($data['cdn_uri_ssl'])) { + return $data['cdn_uri_ssl']; + } + + return false; + } + + /** + * Get the metadata of the container + * + * If $key is empty return the array of metadata + * + * @param string $key + * + * @return array|string|bool + */ + public function getMetadata($key = null) + { + $result = $this->service->getMetadataContainer($this->getName()); + if (!empty($result) && is_array($result)) { + if (empty($key)) { + return $result['metadata']; + } else { + if (isset ($result['metadata'][$key])) { + return $result['metadata'][$key]; + } + } + } + + return false; + } + + /** + * Get the information of the container (total of objects, total size) + * + * @return array|bool + */ + public function getInfo() + { + $result = $this->service->getMetadataContainer($this->getName()); + if (!empty($result) && is_array($result)) { + return $result; + } + + return false; + } + + /** + * Get all the object of the container + * + * @return Zend_Service_Rackspace_Files_ObjectList + */ + public function getObjects() + { + return $this->service->getObjects($this->getName()); + } + + /** + * Get an object of the container + * + * @param string $name + * @param array $headers + * + * @return Zend_Service_Rackspace_Files_Object|bool + */ + public function getObject($name, $headers = array()) + { + return $this->service->getObject($this->getName(), $name, $headers); + } + + /** + * Add an object in the container + * + * @param string $name + * @param string $file the content of the object + * @param array $metadata + * + * @return bool + */ + public function addObject($name, $file, $metadata = array()) + { + return $this->service->storeObject( + $this->getName(), $name, $file, $metadata + ); + } + + /** + * Delete an object in the container + * + * @param string $obj + * + * @return bool + */ + public function deleteObject($obj) + { + return $this->service->deleteObject($this->getName(), $obj); + } + + /** + * Copy an object to another container + * + * @param string $obj_source + * @param string $container_dest + * @param string $obj_dest + * @param array $metadata + * @param string $content_type + * + * @return bool + */ + public function copyObject( + $obj_source, $container_dest, $obj_dest, $metadata = array(), + $content_type = null + ) + { + return $this->service->copyObject( + $this->getName(), + $obj_source, + $container_dest, + $obj_dest, + $metadata, + $content_type + ); + } + + /** + * Get the metadata of an object in the container + * + * @param string $object + * + * @return array + */ + public function getMetadataObject($object) + { + return $this->service->getMetadataObject($this->getName(), $object); + } + + /** + * Set the metadata of an object in the container + * + * @param string $object + * @param array $metadata + * + * @return bool + */ + public function setMetadataObject($object, $metadata = array()) + { + return $this->service->setMetadataObject( + $this->getName(), $object, $metadata + ); + } + + /** + * Enable the CDN for the container + * + * @param integer $ttl + * + * @return array|bool + */ + public function enableCdn($ttl = Zend_Service_Rackspace_Files::CDN_TTL_MIN) + { + return $this->service->enableCdnContainer($this->getName(), $ttl); + } + + /** + * Disable the CDN for the container + * + * @return bool + */ + public function disableCdn() + { + $result = + $this->service->updateCdnContainer($this->getName(), null, false); + + return ($result !== false); + } + + /** + * Change the TTL for the CDN container + * + * @param integer $ttl + * + * @return bool + */ + public function changeTtlCdn($ttl) + { + $result = $this->service->updateCdnContainer($this->getName(), $ttl); + + return ($result !== false); + } + + /** + * Enable the log retention for the CDN + * + * @return bool + */ + public function enableLogCdn() + { + $result = $this->service->updateCdnContainer( + $this->getName(), null, null, true + ); + + return ($result !== false); + } + + /** + * Disable the log retention for the CDN + * + * @return bool + */ + public function disableLogCdn() + { + $result = $this->service->updateCdnContainer( + $this->getName(), null, null, false + ); + + return ($result !== false); + } + + /** + * Get the CDN information + * + * @return array|bool + */ + public function getCdnInfo() + { + return $this->service->getInfoCdnContainer($this->getName()); + } +} diff --git a/lib/zend/Zend/Service/Rackspace/Files/ContainerList.php b/lib/zend/Zend/Service/Rackspace/Files/ContainerList.php new file mode 100644 index 00000000000..f0650232fb8 --- /dev/null +++ b/lib/zend/Zend/Service/Rackspace/Files/ContainerList.php @@ -0,0 +1,221 @@ +service= $service; + $this->_constructFromArray($list); + } + /** + * Transforms the Array to array of container + * + * @param array $list + * @return void + */ + private function _constructFromArray(array $list) + { + foreach ($list as $container) { + $this->_addObject(new Zend_Service_Rackspace_Files_Container($this->service,$container)); + } + } + /** + * Add an object + * + * @param Zend_Service_Rackspace_Files_Container $obj + * @return Zend_Service_Rackspace_Files_ContainerList + */ + protected function _addObject (Zend_Service_Rackspace_Files_Container $obj) + { + $this->objects[] = $obj; + return $this; + } + /** + * Return number of servers + * + * Implement Countable::count() + * + * @return int + */ + public function count() + { + return count($this->objects); + } + /** + * Return the current element + * + * Implement Iterator::current() + * + * @return Zend_Service_Rackspace_Files_Container + */ + public function current() + { + return $this->objects[$this->iteratorKey]; + } + /** + * Return the key of the current element + * + * Implement Iterator::key() + * + * @return int + */ + public function key() + { + return $this->iteratorKey; + } + /** + * Move forward to next element + * + * Implement Iterator::next() + * + * @return void + */ + public function next() + { + $this->iteratorKey += 1; + } + /** + * Rewind the Iterator to the first element + * + * Implement Iterator::rewind() + * + * @return void + */ + public function rewind() + { + $this->iteratorKey = 0; + } + /** + * Check if there is a current element after calls to rewind() or next() + * + * Implement Iterator::valid() + * + * @return bool + */ + public function valid() + { + $numItems = $this->count(); + if ($numItems > 0 && $this->iteratorKey < $numItems) { + return true; + } else { + return false; + } + } + /** + * Whether the offset exists + * + * Implement ArrayAccess::offsetExists() + * + * @param int $offset + * @return bool + */ + public function offsetExists($offset) + { + return ($offset < $this->count()); + } + /** + * Return value at given offset + * + * Implement ArrayAccess::offsetGet() + * + * @param int $offset + * @throws Zend_Service_Rackspace_Files_Exception + * @return Zend_Service_Rackspace_Files_Container + */ + public function offsetGet($offset) + { + if ($this->offsetExists($offset)) { + return $this->objects[$offset]; + } else { + require_once 'Zend/Service/Rackspace/Files/Exception.php'; + throw new Zend_Service_Rackspace_Files_Exception('Illegal index'); + } + } + + /** + * Throws exception because all values are read-only + * + * Implement ArrayAccess::offsetSet() + * + * @param int $offset + * @param string $value + * @throws Zend_Service_Rackspace_Files_Exception + */ + public function offsetSet($offset, $value) + { + require_once 'Zend/Service/Rackspace/Files/Exception.php'; + throw new Zend_Service_Rackspace_Files_Exception('You are trying to set read-only property'); + } + + /** + * Throws exception because all values are read-only + * + * Implement ArrayAccess::offsetUnset() + * + * @param int $offset + * @throws Zend_Service_Rackspace_Files_Exception + */ + public function offsetUnset($offset) + { + require_once 'Zend/Service/Rackspace/Files/Exception.php'; + throw new Zend_Service_Rackspace_Files_Exception('You are trying to unset read-only property'); + } +} diff --git a/lib/zend/Zend/Service/DeveloperGarden/Exception.php b/lib/zend/Zend/Service/Rackspace/Files/Exception.php similarity index 63% rename from lib/zend/Zend/Service/DeveloperGarden/Exception.php rename to lib/zend/Zend/Service/Rackspace/Files/Exception.php index 63a8a09e4fa..bd1c7ae72a7 100644 --- a/lib/zend/Zend/Service/DeveloperGarden/Exception.php +++ b/lib/zend/Zend/Service/Rackspace/Files/Exception.php @@ -13,26 +13,24 @@ * to license@zend.com so we can send you a copy immediately. * * @category Zend - * @package Zend_Service - * @subpackage DeveloperGarden - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @package Zend_Service_Rackspace + * @subpackage Files + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ /** - * Zend_Service_Exception + * @see Zend_Service_Rackspace_Exception */ -require_once 'Zend/Service/Exception.php'; +require_once 'Zend/Service/Rackspace/Exception.php'; /** * @category Zend - * @package Zend_Service - * @subpackage DeveloperGarden - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @author Marco Kaiser + * @package Zend_Service_Rackspace + * @subpackage Files + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class Zend_Service_DeveloperGarden_Exception extends Zend_Service_Exception -{ -} +class Zend_Service_Rackspace_Files_Exception extends Zend_Service_Rackspace_Exception +{} diff --git a/lib/zend/Zend/Service/Rackspace/Files/Object.php b/lib/zend/Zend/Service/Rackspace/Files/Object.php new file mode 100644 index 00000000000..4b2714ba279 --- /dev/null +++ b/lib/zend/Zend/Service/Rackspace/Files/Object.php @@ -0,0 +1,312 @@ +name = $data['name']; + $this->hash = $data['hash']; + $this->size = $data['bytes']; + $this->contentType = $data['content_type']; + $this->lastModified = $data['last_modified']; + + if (!empty($data['content'])) { + $this->content = $data['content']; + } + } elseif (array_key_exists('subdir', $data)) { + $this->name = $data['subdir']; + } else { + require_once 'Zend/Service/Rackspace/Files/Exception.php'; + throw new Zend_Service_Rackspace_Files_Exception( + 'You must pass the name of the object in the array (name)' + ); + } + + $this->container = $data['container']; + $this->service = $service; + } + + /** + * Get name + * + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * Get the name of the container + * + * @return string + */ + public function getContainer() + { + return $this->container; + } + + /** + * Get the MD5 of the object's content + * + * @return string|boolean + */ + public function getHash() + { + return $this->hash; + } + + /** + * Get the size (in bytes) of the object's content + * + * @return integer|boolean + */ + public function getSize() + { + return $this->size; + } + + /** + * Get the content type of the object's content + * + * @return string + */ + public function getContentType() + { + return $this->contentType; + } + + /** + * Get the data of the last modified of the object + * + * @return string + */ + public function getLastModified() + { + return $this->lastModified; + } + + /** + * Get the content of the object + * + * @return string + */ + public function getContent() + { + return $this->content; + } + + /** + * Get the metadata of the object + * If you don't pass the $key it returns the entire array of metadata value + * + * @param string $key + * @return string|array|boolean + */ + public function getMetadata($key=null) + { + $result= $this->service->getMetadataObject($this->container,$this->name); + if (!empty($result)) { + if (empty($key)) { + return $result['metadata']; + } + if (isset($result['metadata'][$key])) { + return $result['metadata'][$key]; + } + } + return false; + } + + /** + * Set the metadata value + * The old metadata values are replaced with the new one + * + * @param array $metadata + * @return boolean + */ + public function setMetadata($metadata) + { + return $this->service->setMetadataObject($this->container,$this->name,$metadata); + } + + /** + * Copy the object to another container + * You can add metadata information to the destination object, change the + * content_type and the name of the object + * + * @param string $container_dest + * @param string $name_dest + * @param array $metadata + * @param string $content_type + * @return boolean + */ + public function copyTo($container_dest,$name_dest,$metadata=array(),$content_type=null) + { + return $this->service->copyObject($this->container,$this->name,$container_dest,$name_dest,$metadata,$content_type); + } + + /** + * Get the CDN URL of the object + * + * @return string + */ + public function getCdnUrl() + { + $result= $this->service->getInfoCdnContainer($this->container); + if ($result!==false) { + if ($result['cdn_enabled']) { + return $result['cdn_uri'].'/'.$this->name; + } + } + return false; + } + + /** + * Get the CDN SSL URL of the object + * + * @return string + */ + public function getCdnUrlSsl() + { + $result= $this->service->getInfoCdnContainer($this->container); + if ($result!==false) { + if ($result['cdn_enabled']) { + return $result['cdn_uri_ssl'].'/'.$this->name; + } + } + return false; + } +} diff --git a/lib/zend/Zend/Service/Rackspace/Files/ObjectList.php b/lib/zend/Zend/Service/Rackspace/Files/ObjectList.php new file mode 100644 index 00000000000..99abcb1c453 --- /dev/null +++ b/lib/zend/Zend/Service/Rackspace/Files/ObjectList.php @@ -0,0 +1,237 @@ +service= $service; + $this->container= $container; + $this->_constructFromArray($list); + } + /** + * Transforms the Array to array of container + * + * @param array $list + * @return void + */ + private function _constructFromArray(array $list) + { + foreach ($list as $obj) { + $obj['container']= $this->container; + $this->_addObject(new Zend_Service_Rackspace_Files_Object($this->service,$obj)); + } + } + /** + * Add an object + * + * @param Zend_Service_Rackspace_Files_Object $obj + * @return Zend_Service_Rackspace_Files_ObjectList + */ + protected function _addObject (Zend_Service_Rackspace_Files_Object $obj) + { + $this->objects[] = $obj; + return $this; + } + /** + * Return number of servers + * + * Implement Countable::count() + * + * @return int + */ + public function count() + { + return count($this->objects); + } + /** + * Return the current element + * + * Implement Iterator::current() + * + * @return Zend_Service_Rackspace_Files_Object + */ + public function current() + { + return $this->objects[$this->iteratorKey]; + } + /** + * Return the key of the current element + * + * Implement Iterator::key() + * + * @return int + */ + public function key() + { + return $this->iteratorKey; + } + /** + * Move forward to next element + * + * Implement Iterator::next() + * + * @return void + */ + public function next() + { + $this->iteratorKey += 1; + } + /** + * Rewind the Iterator to the first element + * + * Implement Iterator::rewind() + * + * @return void + */ + public function rewind() + { + $this->iteratorKey = 0; + } + /** + * Check if there is a current element after calls to rewind() or next() + * + * Implement Iterator::valid() + * + * @return bool + */ + public function valid() + { + $numItems = $this->count(); + if ($numItems > 0 && $this->iteratorKey < $numItems) { + return true; + } else { + return false; + } + } + /** + * Whether the offset exists + * + * Implement ArrayAccess::offsetExists() + * + * @param int $offset + * @return bool + */ + public function offsetExists($offset) + { + return ($offset < $this->count()); + } + /** + * Return value at given offset + * + * Implement ArrayAccess::offsetGet() + * + * @param int $offset + * @throws Zend_Service_Rackspace_Files_Exception + * @return Zend_Service_Rackspace_Files_Object + */ + public function offsetGet($offset) + { + if ($this->offsetExists($offset)) { + return $this->objects[$offset]; + } else { + require_once 'Zend/Service/Rackspace/Files/Exception.php'; + throw new Zend_Service_Rackspace_Files_Exception('Illegal index'); + } + } + + /** + * Throws exception because all values are read-only + * + * Implement ArrayAccess::offsetSet() + * + * @param int $offset + * @param string $value + * @throws Zend_Service_Rackspace_Files_Exception + */ + public function offsetSet($offset, $value) + { + require_once 'Zend/Service/Rackspace/Files/Exception.php'; + throw new Zend_Service_Rackspace_Files_Exception('You are trying to set read-only property'); + } + + /** + * Throws exception because all values are read-only + * + * Implement ArrayAccess::offsetUnset() + * + * @param int $offset + * @throws Zend_Service_Rackspace_Files_Exception + */ + public function offsetUnset($offset) + { + require_once 'Zend/Service/Rackspace/Files/Exception.php'; + throw new Zend_Service_Rackspace_Files_Exception('You are trying to unset read-only property'); + } +} diff --git a/lib/zend/Zend/Service/Rackspace/Servers.php b/lib/zend/Zend/Service/Rackspace/Servers.php new file mode 100644 index 00000000000..f76b7dde0e0 --- /dev/null +++ b/lib/zend/Zend/Service/Rackspace/Servers.php @@ -0,0 +1,1281 @@ +httpCall($this->getManagementUrl().$url,'GET'); + $status= $result->getStatus(); + switch ($status) { + case '200' : + case '203' : // break intentionally omitted + $servers= json_decode($result->getBody(),true); + return new Zend_Service_Rackspace_Servers_ServerList($this,$servers['servers']); + case '503' : + $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE; + break; + case '401' : + $this->errorMsg= self::ERROR_UNAUTHORIZED; + break; + case '413' : + $this->errorMsg= self::ERROR_OVERLIMIT; + break; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } + /** + * Get the specified server + * + * @param string $id + * @return Zend_Service_Rackspace_Servers_Server + */ + public function getServer($id) + { + if (empty($id)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_ID); + } + $result= $this->httpCall($this->getManagementUrl().'/servers/'.rawurlencode($id),'GET'); + $status= $result->getStatus(); + switch ($status) { + case '200' : + case '203' : // break intentionally omitted + $server = json_decode($result->getBody(),true); + return new Zend_Service_Rackspace_Servers_Server($this,$server['server']); + case '503' : + $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE; + break; + case '401' : + $this->errorMsg= self::ERROR_UNAUTHORIZED; + break; + case '404' : + $this->errorMsg= self::ERROR_ITEM_NOT_FOUND; + break; + case '413' : + $this->errorMsg= self::ERROR_OVERLIMIT; + break; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } + /** + * Create a new server + * + * The required parameters are specified in $data (name, imageId, falvorId) + * The $files is an associative array with 'serverPath' => 'localPath' + * + * @param array $data + * @param array $metadata + * @param array $files + * @return Zend_Service_Rackspace_Servers_Server|boolean + */ + public function createServer(array $data, $metadata=array(),$files=array()) + { + if (empty($data) || !is_array($data) || !is_array($metadata) || !is_array($files)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_ARRAY); + } + if (!isset($data['name'])) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME); + } + if (!isset($data['flavorId'])) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_FLAVORID); + } + if (!isset($data['imageId'])) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_IMAGEID); + } + if (count($files)>self::LIMIT_NUM_FILE) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception('You can attach '.self::LIMIT_NUM_FILE.' files maximum'); + } + if (!empty($metadata)) { + $data['metadata']= $metadata; + } + $data['flavorId']= (integer) $data['flavorId']; + $data['imageId']= (integer) $data['imageId']; + if (!empty($files)) { + foreach ($files as $serverPath => $filePath) { + if (!file_exists($filePath)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception( + sprintf("The file %s doesn't exist",$filePath)); + } + $content= file_get_contents($filePath); + if (strlen($content) > self::LIMIT_FILE_SIZE) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception( + sprintf("The size of the file %s is greater than the max size of %d bytes", + $filePath,self::LIMIT_FILE_SIZE)); + } + $data['personality'][] = array ( + 'path' => $serverPath, + 'contents' => base64_encode(file_get_contents($filePath)) + ); + } + } + $result = $this->httpCall($this->getManagementUrl().'/servers','POST', + null,null,json_encode(array ('server' => $data))); + $status = $result->getStatus(); + switch ($status) { + case '200' : + case '202' : // break intentionally omitted + $server = json_decode($result->getBody(),true); + return new Zend_Service_Rackspace_Servers_Server($this,$server['server']); + case '503' : + $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE; + break; + case '401' : + $this->errorMsg= self::ERROR_UNAUTHORIZED; + break; + case '404' : + $this->errorMsg= self::ERROR_ITEM_NOT_FOUND; + break; + case '413' : + $this->errorMsg= self::ERROR_OVERLIMIT; + break; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } + /** + * Change the name or the admin password for a server + * + * @param string $id + * @param string $name + * @param string $password + * @return boolean + */ + protected function updateServer($id,$name=null,$password=null) + { + if (empty($id)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception('You must specify the ID of the server'); + } + if (empty($name) && empty($password)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception("You must specify the new name or password of server"); + } + $data= array(); + if (!empty($name)) { + $data['name']= $name; + } + if (!empty($password)) { + $data['adminPass']= $password; + } + $result = $this->httpCall($this->getManagementUrl().'/servers/'.rawurlencode($id),'PUT', + null,null,json_encode(array('server' => $data))); + $status = $result->getStatus(); + switch ($status) { + case '204' : // break intentionally omitted + return true; + case '503' : + $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE; + break; + case '401' : + $this->errorMsg= self::ERROR_UNAUTHORIZED; + break; + case '404' : + $this->errorMsg= self::ERROR_ITEM_NOT_FOUND; + break; + case '409' : + $this->errorMsg= self::ERROR_IN_PROGRESS; + break; + case '413' : + $this->errorMsg= self::ERROR_OVERLIMIT; + break; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } + /** + * Change the server's name + * + * @param string $id + * @param string $name + * @return boolean + */ + public function changeServerName($id,$name) + { + if (empty($id)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception('You must specify the ID of the server'); + } + if (empty($name)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception("You must specify the new name of the server"); + } + return $this->updateServer($id, $name); + } + /** + * Change the admin password of the server + * + * @param string $id + * @param string $password + * @return boolean + */ + public function changeServerPassword($id,$password) + { + if (empty($id)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception('You must specify the ID of the server'); + } + if (empty($password)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception("You must specify the new password of the server"); + } + return $this->updateServer($id, null,$password); + } + /** + * Delete a server + * + * @param string $id + * @return boolean + */ + public function deleteServer($id) + { + if (empty($id)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception('You must specify the ID of the server'); + } + $result = $this->httpCall($this->getManagementUrl().'/servers/'.rawurlencode($id),'DELETE'); + $status = $result->getStatus(); + switch ($status) { + case '202' : // break intentionally omitted + return true; + case '503' : + $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE; + break; + case '401' : + $this->errorMsg= self::ERROR_UNAUTHORIZED; + break; + case '404' : + $this->errorMsg= self::ERROR_ITEM_NOT_FOUND; + break; + case '409' : + $this->errorMsg= self::ERROR_IN_PROGRESS; + break; + case '413' : + $this->errorMsg= self::ERROR_OVERLIMIT; + break; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } + /** + * Get the server's IPs (public and private) + * + * @param string $id + * @return array|boolean + */ + public function getServerIp($id) + { + $result= $this->getServer($id); + if ($result===false) { + return false; + } + $result= $result->toArray(); + return $result['addresses']; + } + /** + * Get the Public IPs of a server + * + * @param string $id + * @return array|boolean + */ + public function getServerPublicIp($id) + { + $addresses= $this->getServerIp($id); + if ($addresses===false) { + return false; + } + return $addresses['public']; + } + /** + * Get the Private IPs of a server + * + * @param string $id + * @return array|boolean + */ + public function getServerPrivateIp($id) + { + $addresses= $this->getServerIp($id); + if ($addresses===false) { + return false; + } + return $addresses['private']; + } + /** + * Share an ip address for a server (id) + * + * @param string $id server + * @param string $ip + * @param string $groupId + * @return boolean + */ + public function shareIpAddress($id,$ip,$groupId,$configure=true) + { + if (empty($id)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception('You didn\'t specified the ID of the server'); + } + if (empty($ip)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception('You didn\'t specified the IP address to share'); + } + $validator = new Zend_Validate_Ip(); + if (!$validator->isValid($ip)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception("The parameter $ip specified is not a valid IP address"); + } + if (empty($groupId)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception('You didn\'t specified the group id to use'); + } + $data= array ( + 'sharedIpGroupId' => (integer) $groupId, + 'configureServer' => $configure + ); + $result = $this->httpCall($this->getManagementUrl().'/servers/'.rawurlencode($id).'/ips/public/'.rawurlencode($ip),'PUT', + null,null,json_encode(array('shareIp' => $data))); + $status = $result->getStatus(); + switch ($status) { + case '202' : // break intentionally omitted + return true; + case '503' : + $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE; + break; + case '401' : + $this->errorMsg= self::ERROR_UNAUTHORIZED; + break; + case '404' : + $this->errorMsg= self::ERROR_ITEM_NOT_FOUND; + break; + case '413' : + $this->errorMsg= self::ERROR_OVERLIMIT; + break; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } + /** + * Unshare IP address for a server ($id) + * + * @param string $id + * @param string $ip + * @return boolean + */ + public function unshareIpAddress($id,$ip) + { + if (empty($id)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception('You didn\'t specified the ID of the server'); + } + if (empty($ip)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception('You didn\'t specified the IP address to share'); + } + $validator = new Zend_Validate_Ip(); + if (!$validator->isValid($ip)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception("The parameter $ip specified is not a valid IP address"); + } + $result = $this->httpCall($this->getManagementUrl().'/servers/'.rawurlencode($id).'/ips/public/'.rawurlencode($ip), + 'DELETE'); + $status = $result->getStatus(); + switch ($status) { + case '202' : // break intentionally omitted + return true; + case '503' : + $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE; + break; + case '401' : + $this->errorMsg= self::ERROR_UNAUTHORIZED; + break; + case '404' : + $this->errorMsg= self::ERROR_ITEM_NOT_FOUND; + break; + case '413' : + $this->errorMsg= self::ERROR_OVERLIMIT; + break; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } + /** + * Reboot a server + * + * $hard true is the equivalent of power cycling the server + * $hard false is a graceful shutdown + * + * @param string $id + * @param boolean $hard + * @return boolean + */ + public function rebootServer($id,$hard=false) + { + if (empty($id)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception('You didn\'t specified the ID of the server'); + } + if (!$hard) { + $type= 'SOFT'; + } else { + $type= 'HARD'; + } + $data= array ( + 'reboot' => array ( + 'type' => $type + ) + ); + $result = $this->httpCall($this->getManagementUrl().'/servers/'.rawurlencode($id).'/action', + 'POST', null, null, json_encode($data)); + $status = $result->getStatus(); + switch ($status) { + case '200' : + case '202' : // break intentionally omitted + return true; + case '503' : + $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE; + break; + case '401' : + $this->errorMsg= self::ERROR_UNAUTHORIZED; + break; + case '404' : + $this->errorMsg= self::ERROR_ITEM_NOT_FOUND; + break; + case '409' : + $this->errorMsg= self::ERROR_BUILD_IN_PROGRESS; + break; + case '413' : + $this->errorMsg= self::ERROR_OVERLIMIT; + break; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } + /** + * Rebuild a server + * + * The rebuild function removes all data on the server and replaces it with the specified image, + * serverId and IP addresses will remain the same. + * + * @param string $id + * @param string $imageId + * @return boolean + */ + public function rebuildServer($id,$imageId) + { + if (empty($id)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception('You didn\'t specified the ID of the server'); + } + if (empty($imageId)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception('You didn\'t specified the new imageId of the server'); + } + $data= array ( + 'rebuild' => array ( + 'imageId' => (integer) $imageId + ) + ); + $result = $this->httpCall($this->getManagementUrl().'/servers/'.rawurlencode($id).'/action', + 'POST', null, null, json_encode($data)); + $status = $result->getStatus(); + switch ($status) { + case '202' : // break intentionally omitted + return true; + case '503' : + $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE; + break; + case '401' : + $this->errorMsg= self::ERROR_UNAUTHORIZED; + break; + case '404' : + $this->errorMsg= self::ERROR_ITEM_NOT_FOUND; + break; + case '409' : + $this->errorMsg= self::ERROR_BUILD_IN_PROGRESS; + break; + case '413' : + $this->errorMsg= self::ERROR_OVERLIMIT; + break; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } + /** + * Resize a server + * + * The resize function converts an existing server to a different flavor, in essence, scaling the + * server up or down. The original server is saved for a period of time to allow rollback if there + * is a problem. All resizes should be tested and explicitly confirmed, at which time the original + * server is removed. All resizes are automatically confirmed after 24 hours if they are not + * explicitly confirmed or reverted. + * + * @param string $id + * @param string $flavorId + * @return boolean + */ + public function resizeServer($id,$flavorId) + { + if (empty($id)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception('You didn\'t specified the ID of the server'); + } + if (empty($flavorId)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception('You didn\'t specified the new flavorId of the server'); + } + $data= array ( + 'resize' => array ( + 'flavorId' => (integer) $flavorId + ) + ); + $result = $this->httpCall($this->getManagementUrl().'/servers/'.rawurlencode($id).'/action', + 'POST', null, null, json_encode($data)); + $status = $result->getStatus(); + switch ($status) { + case '202' : // break intentionally omitted + return true; + case '503' : + $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE; + break; + case '401' : + $this->errorMsg= self::ERROR_UNAUTHORIZED; + break; + case '403' : + $this->errorMsg= self::ERROR_RESIZE_NOT_ALLOWED; + break; + case '404' : + $this->errorMsg= self::ERROR_ITEM_NOT_FOUND; + break; + case '409' : + $this->errorMsg= self::ERROR_BUILD_IN_PROGRESS; + break; + case '413' : + $this->errorMsg= self::ERROR_OVERLIMIT; + break; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } + /** + * Confirm resize of a server + * + * During a resize operation, the original server is saved for a period of time to allow roll + * back if there is a problem. Once the newly resized server is tested and has been confirmed + * to be functioning properly, use this operation to confirm the resize. After confirmation, + * the original server is removed and cannot be rolled back to. All resizes are automatically + * confirmed after 24 hours if they are not explicitly confirmed or reverted. + * + * @param string $id + * @return boolean + */ + public function confirmResizeServer($id) + { + if (empty($id)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception('You didn\'t specified the ID of the server'); + } + $data= array ( + 'confirmResize' => null + ); + $result = $this->httpCall($this->getManagementUrl().'/servers/'.rawurlencode($id).'/action', + 'POST', null, null, json_encode($data)); + $status = $result->getStatus(); + switch ($status) { + case '204' : // break intentionally omitted + return true; + case '503' : + $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE; + break; + case '401' : + $this->errorMsg= self::ERROR_UNAUTHORIZED; + break; + case '403' : + $this->errorMsg= self::ERROR_RESIZE_NOT_ALLOWED; + break; + case '404' : + $this->errorMsg= self::ERROR_ITEM_NOT_FOUND; + break; + case '409' : + $this->errorMsg= self::ERROR_BUILD_IN_PROGRESS; + break; + case '413' : + $this->errorMsg= self::ERROR_OVERLIMIT; + break; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } + /** + * Revert resize of a server + * + * During a resize operation, the original server is saved for a period of time to allow for roll + * back if there is a problem. If you determine there is a problem with a newly resized server, + * use this operation to revert the resize and roll back to the original server. All resizes are + * automatically confirmed after 24 hours if they have not already been confirmed explicitly or + * reverted. + * + * @param string $id + * @return boolean + */ + public function revertResizeServer($id) + { + if (empty($id)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception('You didn\'t specified the ID of the server'); + } + $data= array ( + 'revertResize' => null + ); + $result = $this->httpCall($this->getManagementUrl().'/servers/'.rawurlencode($id).'/action', + 'POST', null, null, json_encode($data)); + $status = $result->getStatus(); + switch ($status) { + case '202' : // break intentionally omitted + return true; + case '503' : + $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE; + break; + case '401' : + $this->errorMsg= self::ERROR_UNAUTHORIZED; + break; + case '403' : + $this->errorMsg= self::ERROR_RESIZE_NOT_ALLOWED; + break; + case '404' : + $this->errorMsg= self::ERROR_ITEM_NOT_FOUND; + break; + case '409' : + $this->errorMsg= self::ERROR_BUILD_IN_PROGRESS; + break; + case '413' : + $this->errorMsg= self::ERROR_OVERLIMIT; + break; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } + /** + * Get the list of the flavors + * + * If $details is true returns detail info + * + * @param boolean $details + * @return array|boolean + */ + public function listFlavors($details=false) + { + $url= '/flavors'; + if ($details) { + $url.= '/detail'; + } + $result= $this->httpCall($this->getManagementUrl().$url,'GET'); + $status= $result->getStatus(); + switch ($status) { + case '200' : + case '203' : // break intentionally omitted + $flavors= json_decode($result->getBody(),true); + return $flavors['flavors']; + case '503' : + $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE; + break; + case '401' : + $this->errorMsg= self::ERROR_UNAUTHORIZED; + break; + case '413' : + $this->errorMsg= self::ERROR_OVERLIMIT; + break; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } + /** + * Get the detail of a flavor + * + * @param string $flavorId + * @return array|boolean + */ + public function getFlavor($flavorId) + { + if (empty($flavorId)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception('You didn\'t specified the new flavorId of the server'); + } + $result= $this->httpCall($this->getManagementUrl().'/flavors/'.rawurlencode($flavorId),'GET'); + $status= $result->getStatus(); + switch ($status) { + case '200' : + case '203' : // break intentionally omitted + $flavor= json_decode($result->getBody(),true); + return $flavor['flavor']; + case '503' : + $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE; + break; + case '401' : + $this->errorMsg= self::ERROR_UNAUTHORIZED; + break; + case '413' : + $this->errorMsg= self::ERROR_OVERLIMIT; + break; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } + /** + * Get the list of the images + * + * @param boolean $details + * @return Zend_Service_Rackspace_Servers_ImageList|boolean + */ + public function listImages($details=false) + { + $url= '/images'; + if ($details) { + $url.= '/detail'; + } + $result= $this->httpCall($this->getManagementUrl().$url,'GET'); + $status= $result->getStatus(); + switch ($status) { + case '200' : + case '203' : // break intentionally omitted + $images= json_decode($result->getBody(),true); + return new Zend_Service_Rackspace_Servers_ImageList($this,$images['images']); + case '503' : + $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE; + break; + case '401' : + $this->errorMsg= self::ERROR_UNAUTHORIZED; + break; + case '413' : + $this->errorMsg= self::ERROR_OVERLIMIT; + break; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } + /** + * Get detail about an image + * + * @param string $id + * @return Zend_Service_Rackspace_Servers_Image|boolean + */ + public function getImage($id) + { + $result= $this->httpCall($this->getManagementUrl().'/images/'.rawurlencode($id),'GET'); + $status= $result->getStatus(); + switch ($status) { + case '200' : + case '203' : // break intentionally omitted + $image= json_decode($result->getBody(),true); + return new Zend_Service_Rackspace_Servers_Image($this,$image['image']); + case '503' : + $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE; + break; + case '401' : + $this->errorMsg= self::ERROR_UNAUTHORIZED; + break; + case '404' : + $this->errorMsg= self::ERROR_ITEM_NOT_FOUND; + break; + case '413' : + $this->errorMsg= self::ERROR_OVERLIMIT; + break; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } + /** + * Create an image for a serverId + * + * @param string $serverId + * @param string $name + * @return Zend_Service_Rackspace_Servers_Image + */ + public function createImage($serverId,$name) + { + if (empty($serverId)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_SERVERID); + } + if (empty($name)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME); + } + $data = array( + 'image' => array ( + 'serverId' => (integer) $serverId, + 'name' => $name + ) + ); + $result = $this->httpCall($this->getManagementUrl().'/images', 'POST', + null, null, json_encode($data)); + $status = $result->getStatus(); + switch ($status) { + case '202' : // break intentionally omitted + $image= json_decode($result->getBody(),true); + return new Zend_Service_Rackspace_Servers_Image($this,$image['image']); + case '503' : + $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE; + break; + case '401' : + $this->errorMsg= self::ERROR_UNAUTHORIZED; + break; + case '403' : + $this->errorMsg= self::ERROR_RESIZE_NOT_ALLOWED; + break; + case '404' : + $this->errorMsg= self::ERROR_ITEM_NOT_FOUND; + break; + case '409' : + $this->errorMsg= self::ERROR_BUILD_IN_PROGRESS; + break; + case '413' : + $this->errorMsg= self::ERROR_OVERLIMIT; + break; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } + /** + * Delete an image + * + * @param string $id + * @return boolean + */ + public function deleteImage($id) + { + if (empty($id)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_ID); + } + $result = $this->httpCall($this->getManagementUrl().'/images/'.rawurlencode($id),'DELETE'); + $status = $result->getStatus(); + switch ($status) { + case '204' : // break intentionally omitted + return true; + case '503' : + $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE; + break; + case '401' : + $this->errorMsg= self::ERROR_UNAUTHORIZED; + break; + case '404' : + $this->errorMsg= self::ERROR_ITEM_NOT_FOUND; + break; + case '413' : + $this->errorMsg= self::ERROR_OVERLIMIT; + break; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } + /** + * Get the backup schedule of a server + * + * @param string $id server's Id + * @return array|boolean + */ + public function getBackupSchedule($id) + { + if (empty($id)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_ID); + } + $result= $this->httpCall($this->getManagementUrl().'/servers/'.rawurlencode($id).'/backup_schedule', + 'GET'); + $status= $result->getStatus(); + switch ($status) { + case '200' : + case '203' : // break intentionally omitted + $backup = json_decode($result->getBody(),true); + return $backup['backupSchedule']; + case '503' : + $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE; + break; + case '401' : + $this->errorMsg= self::ERROR_UNAUTHORIZED; + break; + case '404' : + $this->errorMsg= self::ERROR_ITEM_NOT_FOUND; + break; + case '413' : + $this->errorMsg= self::ERROR_OVERLIMIT; + break; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } + /** + * Change the backup schedule of a server + * + * @param string $id server's Id + * @param string $weekly + * @param string $daily + * @return boolean + */ + public function changeBackupSchedule($id,$weekly,$daily) + { + if (empty($id)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_ID); + } + if (empty($weekly)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_WEEKLY); + } + if (empty($daily)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_DAILY); + } + $data = array ( + 'backupSchedule' => array ( + 'enabled' => true, + 'weekly' => $weekly, + 'daily' => $daily + ) + ); + $result= $this->httpCall($this->getManagementUrl().'/servers/'.rawurlencode($id).'/backup_schedule', + 'POST',null,null,json_encode($data)); + $status= $result->getStatus(); + switch ($status) { + case '204' : // break intentionally omitted + return true; + case '503' : + $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE; + break; + case '401' : + $this->errorMsg= self::ERROR_UNAUTHORIZED; + break; + case '404' : + $this->errorMsg= self::ERROR_ITEM_NOT_FOUND; + break; + case '409' : + $this->errorMsg= self::ERROR_BUILD_IN_PROGRESS; + break; + case '413' : + $this->errorMsg= self::ERROR_OVERLIMIT; + break; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } + /** + * Disable the backup schedule for a server + * + * @param string $id server's Id + * @return boolean + */ + public function disableBackupSchedule($id) + { + if (empty($id)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_ID); + } + $result = $this->httpCall($this->getManagementUrl().'/servers/'.rawurlencode($id).'/backup_schedule', + 'DELETE'); + $status = $result->getStatus(); + switch ($status) { + case '204' : // break intentionally omitted + return true; + case '503' : + $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE; + break; + case '401' : + $this->errorMsg= self::ERROR_UNAUTHORIZED; + break; + case '404' : + $this->errorMsg= self::ERROR_ITEM_NOT_FOUND; + break; + case '409' : + $this->errorMsg= self::ERROR_BUILD_IN_PROGRESS; + break; + case '413' : + $this->errorMsg= self::ERROR_OVERLIMIT; + break; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } + /** + * Get the list of shared IP groups + * + * @param boolean $details + * @return Zend_Service_Rackspace_Servers_SharedIpGroupList|boolean + */ + public function listSharedIpGroups($details=false) + { + $url= '/shared_ip_groups'; + if ($details) { + $url.= '/detail'; + } + $result= $this->httpCall($this->getManagementUrl().$url,'GET'); + $status= $result->getStatus(); + switch ($status) { + case '200' : + case '203' : // break intentionally omitted + $groups= json_decode($result->getBody(),true); + return new Zend_Service_Rackspace_Servers_SharedIpGroupList($this,$groups['sharedIpGroups']); + case '503' : + $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE; + break; + case '401' : + $this->errorMsg= self::ERROR_UNAUTHORIZED; + break; + case '413' : + $this->errorMsg= self::ERROR_OVERLIMIT; + break; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } + /** + * Get the shared IP group + * + * @param integer $id + * @return Zend_Service_Rackspace_Servers_SharedIpGroup|boolean + */ + public function getSharedIpGroup($id) + { + if (empty($id)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_ID); + } + $result= $this->httpCall($this->getManagementUrl().'/shared_ip_groups/'.rawurlencode($id),'GET'); + $status= $result->getStatus(); + switch ($status) { + case '200' : + case '203' : // break intentionally omitted + $group= json_decode($result->getBody(),true); + return new Zend_Service_Rackspace_Servers_SharedIpGroup($this,$group['sharedIpGroup']); + case '503' : + $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE; + break; + case '401' : + $this->errorMsg= self::ERROR_UNAUTHORIZED; + break; + case '404' : + $this->errorMsg= self::ERROR_ITEM_NOT_FOUND; + break; + case '413' : + $this->errorMsg= self::ERROR_OVERLIMIT; + break; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } + /** + * Create a shared Ip group + * + * @param string $name + * @param string $serverId + * @return array|boolean + */ + public function createSharedIpGroup($name,$serverId) + { + if (empty($name)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME); + } + if (empty($serverId)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_ID); + } + $data = array ( + 'sharedIpGroup' => array ( + 'name' => $name, + 'server' => (integer) $serverId + ) + ); + $result= $this->httpCall($this->getManagementUrl().'/shared_ip_groups', + 'POST',null,null,json_encode($data)); + $status= $result->getStatus(); + switch ($status) { + case '201' : // break intentionally omitted + $group = json_decode($result->getBody(),true); + return new Zend_Service_Rackspace_Servers_SharedIpGroup($this,$group['sharedIpGroup']); + case '503' : + $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE; + break; + case '401' : + $this->errorMsg= self::ERROR_UNAUTHORIZED; + break; + case '413' : + $this->errorMsg= self::ERROR_OVERLIMIT; + break; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } + /** + * Delete a Shared Ip Group + * + * @param integer $id + * @return boolean + */ + public function deleteSharedIpGroup($id) + { + if (empty($id)) { + require_once 'Zend/Service/Rackspace/Exception.php'; + throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_ID); + } + $result= $this->httpCall($this->getManagementUrl().'/shared_ip_groups/'.rawurlencode($id),'DELETE'); + $status= $result->getStatus(); + switch ($status) { + case '204' : // break intentionally omitted + return true; + case '503' : + $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE; + break; + case '401' : + $this->errorMsg= self::ERROR_UNAUTHORIZED; + break; + case '404' : + $this->errorMsg= self::ERROR_ITEM_NOT_FOUND; + break; + case '413' : + $this->errorMsg= self::ERROR_OVERLIMIT; + break; + default: + $this->errorMsg= $result->getBody(); + break; + } + $this->errorCode= $status; + return false; + } +} diff --git a/lib/zend/Zend/Service/Rackspace/Servers/Exception.php b/lib/zend/Zend/Service/Rackspace/Servers/Exception.php new file mode 100644 index 00000000000..70de0889e5c --- /dev/null +++ b/lib/zend/Zend/Service/Rackspace/Servers/Exception.php @@ -0,0 +1,36 @@ +service= $service; + $this->name = $data['name']; + $this->id = $data['id']; + if (isset($data['serverId'])) { + $this->serverId= $data['serverId']; + } + if (isset($data['updated'])) { + $this->updated= $data['updated']; + } + if (isset($data['created'])) { + $this->created= $data['created']; + } + if (isset($data['status'])) { + $this->status= $data['status']; + } + if (isset($data['progress'])) { + $this->progress= $data['progress']; + } + } + /** + * Get the name of the image + * + * @return string + */ + public function getName() + { + return $this->name; + } + /** + * Get the image's id + * + * @return string + */ + public function getId() + { + return $this->id; + } + /** + * Get the server's id of the image + * + * @return string + */ + public function getServerId() + { + return $this->serverId; + } + /** + * Get the updated data + * + * @return string + */ + public function getUpdated() + { + return $this->updated; + } + /** + * Get the created data + * + * @return string + */ + public function getCreated() + { + return $this->created; + } + /** + * Get the image's status + * + * @return string|boolean + */ + public function getStatus() + { + $data= $this->service->getImage($this->id); + if ($data!==false) { + $data= $data->toArray(); + $this->status= $data['status']; + return $this->status; + } + return false; + } + /** + * Get the progress's status + * + * @return integer|boolean + */ + public function getProgress() + { + $data= $this->service->getImage($this->id); + if ($data!==false) { + $data= $data->toArray(); + $this->progress= $data['progress']; + return $this->progress; + } + return false; + } + /** + * To Array + * + * @return array + */ + public function toArray() + { + return array ( + 'name' => $this->name, + 'id' => $this->id, + 'serverId' => $this->serverId, + 'updated' => $this->updated, + 'created' => $this->created, + 'status' => $this->status, + 'progress' => $this->progress + ); + } +} diff --git a/lib/zend/Zend/Service/Rackspace/Servers/ImageList.php b/lib/zend/Zend/Service/Rackspace/Servers/ImageList.php new file mode 100644 index 00000000000..2d7848567b1 --- /dev/null +++ b/lib/zend/Zend/Service/Rackspace/Servers/ImageList.php @@ -0,0 +1,234 @@ +service= $service; + $this->constructFromArray($list); + } + /** + * Transforms the array to array of Server + * + * @param array $list + * @return void + */ + private function constructFromArray(array $list) + { + foreach ($list as $image) { + $this->addImage(new Zend_Service_Rackspace_Servers_Image($this->service,$image)); + } + } + /** + * Add an image + * + * @param Zend_Service_Rackspace_Servers_Image $image + * @return Zend_Service_Rackspace_Servers_ImageList + */ + protected function addImage (Zend_Service_Rackspace_Servers_Image $image) + { + $this->images[] = $image; + return $this; + } + /** + * To Array + * + * @return array + */ + public function toArray() + { + $array= array(); + foreach ($this->images as $image) { + $array[]= $image->toArray(); + } + return $array; + } + /** + * Return number of images + * + * Implement Countable::count() + * + * @return int + */ + public function count() + { + return count($this->images); + } + /** + * Return the current element + * + * Implement Iterator::current() + * + * @return Zend_Service_Rackspace_Servers_Image + */ + public function current() + { + return $this->images[$this->iteratorKey]; + } + /** + * Return the key of the current element + * + * Implement Iterator::key() + * + * @return int + */ + public function key() + { + return $this->iteratorKey; + } + /** + * Move forward to next element + * + * Implement Iterator::next() + * + * @return void + */ + public function next() + { + $this->iteratorKey += 1; + } + /** + * Rewind the Iterator to the first element + * + * Implement Iterator::rewind() + * + * @return void + */ + public function rewind() + { + $this->iteratorKey = 0; + } + /** + * Check if there is a current element after calls to rewind() or next() + * + * Implement Iterator::valid() + * + * @return bool + */ + public function valid() + { + $numItems = $this->count(); + if ($numItems > 0 && $this->iteratorKey < $numItems) { + return true; + } else { + return false; + } + } + /** + * Whether the offset exists + * + * Implement ArrayAccess::offsetExists() + * + * @param int $offset + * @return bool + */ + public function offsetExists($offset) + { + return ($offset < $this->count()); + } + /** + * Return value at given offset + * + * Implement ArrayAccess::offsetGet() + * + * @param int $offset + * @throws Zend_Service_Rackspace_Servers_Exception + * @return Zend_Service_Rackspace_Servers_Image + */ + public function offsetGet($offset) + { + if ($this->offsetExists($offset)) { + return $this->images[$offset]; + } else { + require_once 'Zend/Service/Rackspace/Servers/Exception.php'; + throw new Zend_Service_Rackspace_Servers_Exception('Illegal index'); + } + } + + /** + * Throws exception because all values are read-only + * + * Implement ArrayAccess::offsetSet() + * + * @param int $offset + * @param string $value + * @throws Zend_Service_Rackspace_Servers_Exception + */ + public function offsetSet($offset, $value) + { + require_once 'Zend/Service/Rackspace/Servers/Exception.php'; + throw new Zend_Service_Rackspace_Servers_Exception('You are trying to set read-only property'); + } + + /** + * Throws exception because all values are read-only + * + * Implement ArrayAccess::offsetUnset() + * + * @param int $offset + * @throws Zend_Service_Rackspace_Servers_Exception + */ + public function offsetUnset($offset) + { + require_once 'Zend/Service/Rackspace/Servers/Exception.php'; + throw new Zend_Service_Rackspace_Servers_Exception('You are trying to unset read-only property'); + } +} diff --git a/lib/zend/Zend/Service/Rackspace/Servers/Server.php b/lib/zend/Zend/Service/Rackspace/Servers/Server.php new file mode 100644 index 00000000000..5249a9732e4 --- /dev/null +++ b/lib/zend/Zend/Service/Rackspace/Servers/Server.php @@ -0,0 +1,325 @@ +service = $service; + $this->name = $data['name']; + $this->id = $data['id']; + if (isset($data['imageId'])) { + $this->imageId= $data['imageId']; + } + if (isset($data['flavorId'])) { + $this->flavorId= $data['flavorId']; + } + if (isset($data['hostId'])) { + $this->hostId= $data['hostId']; + } + if (isset($data['status'])) { + $this->status= $data['status']; + } + if (isset($data['progress'])) { + $this->progress= $data['progress']; + } + if (isset($data['adminPass'])) { + $this->adminPass= $data['adminPass']; + } + if (isset($data['addresses']) && is_array($data['addresses'])) { + $this->addresses= $data['addresses']; + } + if (isset($data['metadata']) && is_array($data['metadata'])) { + $this->metadata= $data['metadata']; + } + } + /** + * Get the name of the server + * + * @return string + */ + public function getName() + { + return $this->name; + } + /** + * Get the server's id + * + * @return string + */ + public function getId() + { + return $this->id; + } + /** + * Get the server's image Id + * + * @return string + */ + public function getImageId() + { + return $this->imageId; + } + /** + * Get the server's flavor Id + * + * @return string + */ + public function getFlavorId() + { + return $this->flavorId; + } + /** + * Get the server's host Id + * + * @return string + */ + public function getHostId() + { + return $this->hostId; + } + /** + * Ge the server's admin password + * + * @return string + */ + public function getAdminPass() + { + return $this->adminPass; + } + /** + * Get the server's status + * + * @return string|boolean + */ + public function getStatus() + { + $data= $this->service->getServer($this->id); + if ($data!==false) { + $data= $data->toArray(); + $this->status= $data['status']; + return $this->status; + } + return false; + } + /** + * Get the progress's status + * + * @return integer|boolean + */ + public function getProgress() + { + $data= $this->service->getServer($this->id); + if ($data!==false) { + $data= $data->toArray(); + $this->progress= $data['progress']; + return $this->progress; + } + return false; + } + /** + * Get the private IPs + * + * @return array|boolean + */ + public function getPrivateIp() + { + if (isset($this->addresses['private'])) { + return $this->addresses['private']; + } + return false; + } + /** + * Get the public IPs + * + * @return array|boolean + */ + public function getPublicIp() + { + if (isset($this->addresses['public'])) { + return $this->addresses['public']; + } + return false; + } + /** + * Get the metadata of the container + * + * If $key is empty return the array of metadata + * + * @param string $key + * @return array|string + */ + public function getMetadata($key=null) + { + if (!empty($key) && isset($this->metadata[$key])) { + return $this->metadata[$key]; + } + return $this->metadata; + } + /** + * Change the name of the server + * + * @param string $name + * @return boolean + */ + public function changeName($name) + { + $result= $this->service->changeServerName($this->id, $name); + if ($result!==false) { + $this->name= $name; + return true; + } + return false; + } + /** + * Change the admin password of the server + * + * @param string $password + * @return boolean + */ + public function changePassword($password) + { + $result= $this->service->changeServerPassword($this->id, $password); + if ($result!==false) { + $this->adminPass= $password; + return true; + } + return false; + } + /** + * Reboot the server + * + * @return boolean + */ + public function reboot($hard=false) + { + return $this->service->rebootServer($this->id,$hard); + } + /** + * To Array + * + * @return array + */ + public function toArray() + { + return array ( + 'name' => $this->name, + 'id' => $this->id, + 'imageId' => $this->imageId, + 'flavorId' => $this->flavorId, + 'hostId' => $this->hostId, + 'status' => $this->status, + 'progress' => $this->progress, + 'adminPass' => $this->adminPass, + 'addresses' => $this->addresses, + 'metadata' => $this->metadata + ); + } +} diff --git a/lib/zend/Zend/Service/Rackspace/Servers/ServerList.php b/lib/zend/Zend/Service/Rackspace/Servers/ServerList.php new file mode 100644 index 00000000000..9dda8684ec1 --- /dev/null +++ b/lib/zend/Zend/Service/Rackspace/Servers/ServerList.php @@ -0,0 +1,235 @@ +service= $service; + $this->constructFromArray($list); + } + /** + * Transforms the array to array of Server + * + * @param array $list + * @return void + */ + private function constructFromArray(array $list) + { + foreach ($list as $server) { + $this->addServer(new Zend_Service_Rackspace_Servers_Server($this->service,$server)); + } + } + /** + * Add a server + * + * @param Zend_Service_Rackspace_Servers_Server $server + * @return Zend_Service_Rackspace_Servers_ServerList + */ + protected function addServer (Zend_Service_Rackspace_Servers_Server $server) + { + $this->servers[] = $server; + return $this; + } + /** + * To Array + * + * @return array + */ + public function toArray() + { + $array= array(); + foreach ($this->servers as $server) { + $array[]= $server->toArray(); + } + return $array; + } + /** + * Return number of servers + * + * Implement Countable::count() + * + * @return int + */ + public function count() + { + return count($this->servers); + } + /** + * Return the current element + * + * Implement Iterator::current() + * + * @return Zend_Service_Rackspace_Servers_Server + */ + public function current() + { + return $this->servers[$this->iteratorKey]; + } + /** + * Return the key of the current element + * + * Implement Iterator::key() + * + * @return int + */ + public function key() + { + return $this->iteratorKey; + } + /** + * Move forward to next element + * + * Implement Iterator::next() + * + * @return void + */ + public function next() + { + $this->iteratorKey += 1; + } + /** + * Rewind the Iterator to the first element + * + * Implement Iterator::rewind() + * + * @return void + */ + public function rewind() + { + $this->iteratorKey = 0; + } + /** + * Check if there is a current element after calls to rewind() or next() + * + * Implement Iterator::valid() + * + * @return bool + */ + public function valid() + { + $numItems = $this->count(); + if ($numItems > 0 && $this->iteratorKey < $numItems) { + return true; + } else { + return false; + } + } + /** + * Whether the offset exists + * + * Implement ArrayAccess::offsetExists() + * + * @param int $offset + * @return bool + */ + public function offsetExists($offset) + { + return ($offset < $this->count()); + } + /** + * Return value at given offset + * + * Implement ArrayAccess::offsetGet() + * + * @param int $offset + * @throws Zend_Service_Rackspace_Servers_Exception + * @return Zend_Service_Rackspace_Servers_Server + */ + public function offsetGet($offset) + { + if ($this->offsetExists($offset)) { + return $this->servers[$offset]; + } else { + require_once 'Zend/Service/Rackspace/Servers/Exception.php'; + throw new Zend_Service_Rackspace_Servers_Exception('Illegal index'); + } + } + + /** + * Throws exception because all values are read-only + * + * Implement ArrayAccess::offsetSet() + * + * @param int $offset + * @param string $value + * @throws Zend_Service_Rackspace_Servers_Exception + */ + public function offsetSet($offset, $value) + { + require_once 'Zend/Service/Rackspace/Servers/Exception.php'; + throw new Zend_Service_Rackspace_Servers_Exception('You are trying to set read-only property'); + } + + /** + * Throws exception because all values are read-only + * + * Implement ArrayAccess::offsetUnset() + * + * @param int $offset + * @throws Zend_Service_Rackspace_Servers_Exception + */ + public function offsetUnset($offset) + { + require_once 'Zend/Service/Rackspace/Servers/Exception.php'; + throw new Zend_Service_Rackspace_Servers_Exception('You are trying to unset read-only property'); + } +} diff --git a/lib/zend/Zend/Service/Rackspace/Servers/SharedIpGroup.php b/lib/zend/Zend/Service/Rackspace/Servers/SharedIpGroup.php new file mode 100644 index 00000000000..6367db299d2 --- /dev/null +++ b/lib/zend/Zend/Service/Rackspace/Servers/SharedIpGroup.php @@ -0,0 +1,165 @@ +service= $service; + $this->name = $data['name']; + $this->id = $data['id']; + if (isset($data['servers'])) { + $this->serversId= $data['servers']; + } + } + /** + * Get the name of the shared IP group + * + * @return string + */ + public function getName() + { + return $this->name; + } + /** + * Get the id of the shared IP group + * + * @return string + */ + public function getId() + { + return $this->id; + } + /** + * Get the server's array of the shared IP group + * + * @return string + */ + public function getServersId() + { + if (empty($this->serversId)) { + $info= $this->service->getSharedIpGroup($this->id); + if (($info!==false)) { + $info= $info->toArray(); + if (isset($info['servers'])) { + $this->serversId= $info['servers']; + } + } + } + return $this->serversId; + } + /** + * Get the server + * + * @param integer $id + * @return Zend_Service_Rackspace_Servers_Server|boolean + */ + public function getServer($id) + { + if (empty($this->serversId)) { + $this->getServersId(); + } + if (in_array($id,$this->serversId)) { + return $this->service->getServer($id); + } + return false; + } + /** + * Create a server in the shared Ip Group + * + * @param array $data + * @param array $metadata + * @param array $files + * @return Zend_Service_Rackspace_Servers_Server|boolean + */ + public function createServer(array $data, $metadata=array(),$files=array()) + { + $data['sharedIpGroupId']= (integer) $this->id; + return $this->service->createServer($data,$metadata,$files); + } + /** + * To Array + * + * @return array + */ + public function toArray() + { + return array ( + 'name' => $this->name, + 'id' => $this->id, + 'servers' => $this->serversId + ); + } +} diff --git a/lib/zend/Zend/Service/Rackspace/Servers/SharedIpGroupList.php b/lib/zend/Zend/Service/Rackspace/Servers/SharedIpGroupList.php new file mode 100644 index 00000000000..476f58a6a53 --- /dev/null +++ b/lib/zend/Zend/Service/Rackspace/Servers/SharedIpGroupList.php @@ -0,0 +1,234 @@ +service= $service; + $this->constructFromArray($list); + } + /** + * Transforms the array to array of Shared Ip Group + * + * @param array $list + * @return void + */ + private function constructFromArray(array $list) + { + foreach ($list as $share) { + $this->addSharedIpGroup(new Zend_Service_Rackspace_Servers_SharedIpGroup($this->service,$share)); + } + } + /** + * Add a shared Ip group + * + * @param Zend_Service_Rackspace_Servers_SharedIpGroup $shared + * @return Zend_Service_Rackspace_Servers_SharedIpGroupList + */ + protected function addSharedIpGroup (Zend_Service_Rackspace_Servers_SharedIpGroup $share) + { + $this->shared[] = $share; + return $this; + } + /** + * To Array + * + * @return array + */ + public function toArray() + { + $array= array(); + foreach ($this->shared as $share) { + $array[]= $share->toArray(); + } + return $array; + } + /** + * Return number of shared Ip Groups + * + * Implement Countable::count() + * + * @return int + */ + public function count() + { + return count($this->shared); + } + /** + * Return the current element + * + * Implement Iterator::current() + * + * @return Zend_Service_Rackspace_Servers_SharedIpGroup + */ + public function current() + { + return $this->shared[$this->iteratorKey]; + } + /** + * Return the key of the current element + * + * Implement Iterator::key() + * + * @return int + */ + public function key() + { + return $this->iteratorKey; + } + /** + * Move forward to next element + * + * Implement Iterator::next() + * + * @return void + */ + public function next() + { + $this->iteratorKey += 1; + } + /** + * Rewind the Iterator to the first element + * + * Implement Iterator::rewind() + * + * @return void + */ + public function rewind() + { + $this->iteratorKey = 0; + } + /** + * Check if there is a current element after calls to rewind() or next() + * + * Implement Iterator::valid() + * + * @return boolean + */ + public function valid() + { + $numItems = $this->count(); + if ($numItems > 0 && $this->iteratorKey < $numItems) { + return true; + } else { + return false; + } + } + /** + * Whether the offset exists + * + * Implement ArrayAccess::offsetExists() + * + * @param int $offset + * @return boolean + */ + public function offsetExists($offset) + { + return ($offset < $this->count()); + } + /** + * Return value at given offset + * + * Implement ArrayAccess::offsetGet() + * + * @param int $offset + * @throws Zend_Service_Rackspace_Servers_Exception + * @return Zend_Service_Rackspace_Servers_SharedIpGroup + */ + public function offsetGet($offset) + { + if ($this->offsetExists($offset)) { + return $this->shared[$offset]; + } else { + require_once 'Zend/Service/Rackspace/Servers/Exception.php'; + throw new Zend_Service_Rackspace_Servers_Exception('Illegal index'); + } + } + + /** + * Throws exception because all values are read-only + * + * Implement ArrayAccess::offsetSet() + * + * @param int $offset + * @param string $value + * @throws Zend_Service_Rackspace_Servers_Exception + */ + public function offsetSet($offset, $value) + { + require_once 'Zend/Service/Rackspace/Servers/Exception.php'; + throw new Zend_Service_Rackspace_Servers_Exception('You are trying to set read-only property'); + } + + /** + * Throws exception because all values are read-only + * + * Implement ArrayAccess::offsetUnset() + * + * @param int $offset + * @throws Zend_Service_Rackspace_Servers_Exception + */ + public function offsetUnset($offset) + { + require_once 'Zend/Service/Rackspace/Servers/Exception.php'; + throw new Zend_Service_Rackspace_Servers_Exception('You are trying to unset read-only property'); + } +} diff --git a/lib/zend/Zend/Service/ReCaptcha.php b/lib/zend/Zend/Service/ReCaptcha.php index 2421d9dc898..4993d201eac 100644 --- a/lib/zend/Zend/Service/ReCaptcha.php +++ b/lib/zend/Zend/Service/ReCaptcha.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Service * @subpackage ReCaptcha - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -34,7 +34,7 @@ require_once 'Zend/Service/ReCaptcha/Response.php'; * @category Zend * @package Zend_Service * @subpackage ReCaptcha - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -45,21 +45,21 @@ class Zend_Service_ReCaptcha extends Zend_Service_Abstract * * @var string */ - const API_SERVER = 'http://api.recaptcha.net'; + const API_SERVER = 'http://www.google.com/recaptcha/api'; /** * URI to the secure API * * @var string */ - const API_SECURE_SERVER = 'https://api-secure.recaptcha.net'; + const API_SECURE_SERVER = 'https://www.google.com/recaptcha/api'; /** * URI to the verify server * * @var string */ - const VERIFY_SERVER = 'http://api-verify.recaptcha.net/verify'; + const VERIFY_SERVER = 'http://www.google.com/recaptcha/api/verify'; /** * Public key used when displaying the captcha @@ -103,8 +103,9 @@ class Zend_Service_ReCaptcha extends Zend_Service_Abstract * @var array */ protected $_options = array( - 'theme' => 'red', - 'lang' => 'en', + 'theme' => 'red', + 'lang' => 'en', + 'custom_translations' => array(), ); /** @@ -373,10 +374,11 @@ class Zend_Service_ReCaptcha extends Zend_Service_Abstract * * This method uses the public key to fetch a recaptcha form. * + * @param null|string $name Base name for recaptcha form elements * @return string * @throws Zend_Service_ReCaptcha_Exception */ - public function getHtml() + public function getHtml($name = null) { if ($this->_publicKey === null) { /** @see Zend_Service_ReCaptcha_Exception */ @@ -415,6 +417,12 @@ class Zend_Service_ReCaptcha extends Zend_Service_Abstract SCRIPT; } + $challengeField = 'recaptcha_challenge_field'; + $responseField = 'recaptcha_response_field'; + if (!empty($name)) { + $challengeField = $name . '[' . $challengeField . ']'; + $responseField = $name . '[' . $responseField . ']'; + } $return = $reCaptchaOptions; $return .= << {$htmlBreak} - - HTML; @@ -460,21 +468,9 @@ HTML; throw new Zend_Service_ReCaptcha_Exception('Missing ip address'); } - if (empty($challengeField)) { - /** @see Zend_Service_ReCaptcha_Exception */ - require_once 'Zend/Service/ReCaptcha/Exception.php'; - throw new Zend_Service_ReCaptcha_Exception('Missing challenge field'); - } - - if (empty($responseField)) { - /** @see Zend_Service_ReCaptcha_Exception */ - require_once 'Zend/Service/ReCaptcha/Exception.php'; - - throw new Zend_Service_ReCaptcha_Exception('Missing response field'); - } - /* Fetch an instance of the http client */ $httpClient = self::getHttpClient(); + $httpClient->resetParameters(true); $postParams = array('privatekey' => $this->_privateKey, 'remoteip' => $this->_ip, diff --git a/lib/zend/Zend/Service/ReCaptcha/Exception.php b/lib/zend/Zend/Service/ReCaptcha/Exception.php index 4edf24e3a5e..b84d47eb13a 100644 --- a/lib/zend/Zend/Service/ReCaptcha/Exception.php +++ b/lib/zend/Zend/Service/ReCaptcha/Exception.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Service * @subpackage ReCaptcha - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -28,9 +28,9 @@ require_once 'Zend/Service/Exception.php'; * @category Zend * @package Zend_Service * @subpackage ReCaptcha - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ class Zend_Service_ReCaptcha_Exception extends Zend_Service_Exception -{} \ No newline at end of file +{} diff --git a/lib/zend/Zend/Service/ReCaptcha/MailHide.php b/lib/zend/Zend/Service/ReCaptcha/MailHide.php index 0528af5395a..6bbe6614f1d 100644 --- a/lib/zend/Zend/Service/ReCaptcha/MailHide.php +++ b/lib/zend/Zend/Service/ReCaptcha/MailHide.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Service * @subpackage ReCaptcha - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -28,7 +28,7 @@ require_once 'Zend/Service/ReCaptcha.php'; * @category Zend * @package Zend_Service * @subpackage ReCaptcha - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -312,18 +312,18 @@ class Zend_Service_ReCaptcha_MailHide extends Zend_Service_ReCaptcha $enc = $this->getOption('encoding'); /* Genrate the HTML used to represent the email address */ - $html = htmlentities($this->getEmailLocalPart(), ENT_COMPAT, $enc) - . '' . $this->_options['linkHiddenText'] . '@' + . $this->_options['popupWidth'] + . ',height=' + . $this->_options['popupHeight'] + . '\'); return false;" title="' + . $this->_options['linkTitle'] + . '">' . $this->_options['linkHiddenText'] . '@' . htmlentities($this->getEmailDomainPart(), ENT_COMPAT, $enc); return $html; diff --git a/lib/zend/Zend/Service/ReCaptcha/MailHide/Exception.php b/lib/zend/Zend/Service/ReCaptcha/MailHide/Exception.php index 105e8823927..7710e7fd0c3 100644 --- a/lib/zend/Zend/Service/ReCaptcha/MailHide/Exception.php +++ b/lib/zend/Zend/Service/ReCaptcha/MailHide/Exception.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Service * @subpackage ReCaptcha - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -28,9 +28,9 @@ require_once 'Zend/Service/ReCaptcha/Exception.php'; * @category Zend * @package Zend_Service * @subpackage ReCaptcha - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ class Zend_Service_ReCaptcha_MailHide_Exception extends Zend_Service_ReCaptcha_Exception -{} \ No newline at end of file +{} diff --git a/lib/zend/Zend/Service/ReCaptcha/Response.php b/lib/zend/Zend/Service/ReCaptcha/Response.php index d9fad2caba6..d20318f1d4a 100644 --- a/lib/zend/Zend/Service/ReCaptcha/Response.php +++ b/lib/zend/Zend/Service/ReCaptcha/Response.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Service * @subpackage ReCaptcha - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -25,7 +25,7 @@ * @category Zend * @package Zend_Service * @subpackage ReCaptcha - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -142,13 +142,18 @@ class Zend_Service_ReCaptcha_Response { $body = $response->getBody(); - $parts = explode("\n", $body, 2); + // Default status and error code + $status = 'false'; + $errorCode = ''; - if (count($parts) !== 2) { - $status = 'false'; - $errorCode = ''; - } else { - list($status, $errorCode) = $parts; + $parts = explode("\n", $body); + + if ($parts[0] === 'true') { + $status = 'true'; + } + + if (!empty($parts[1])) { + $errorCode = $parts[1]; } $this->setStatus($status); @@ -156,4 +161,4 @@ class Zend_Service_ReCaptcha_Response return $this; } -} \ No newline at end of file +} diff --git a/lib/zend/Zend/Service/Simpy.php b/lib/zend/Zend/Service/Simpy.php deleted file mode 100644 index 26a9be6501a..00000000000 --- a/lib/zend/Zend/Service/Simpy.php +++ /dev/null @@ -1,433 +0,0 @@ -_http = new Zend_Http_Client; - $this->_http->setAuth($username, $password); - } - - /** - * Returns the HTTP client currently in use by this class for REST API - * calls, intended mainly for testing. - * - * @return Zend_Http_Client - */ - public function getHttpClient() - { - return $this->_http; - } - - /** - * Sends a request to the REST API service and does initial processing - * on the response. - * - * @param string $op Name of the operation for the request - * @param array $query Query data for the request (optional) - * @throws Zend_Service_Exception - * @return DOMDocument Parsed XML response - */ - protected function _makeRequest($op, $query = null) - { - if ($query != null) { - $query = array_diff($query, array_filter($query, 'is_null')); - $query = '?' . http_build_query($query); - } - - $this->_http->setUri($this->_baseUri . $op . '.do' . $query); - $response = $this->_http->request('GET'); - - if ($response->isSuccessful()) { - $doc = new DOMDocument(); - $doc->loadXML($response->getBody()); - $xpath = new DOMXPath($doc); - $list = $xpath->query('/status/code'); - - if ($list->length > 0) { - $code = $list->item(0)->nodeValue; - - if ($code != 0) { - $list = $xpath->query('/status/message'); - $message = $list->item(0)->nodeValue; - /** - * @see Zend_Service_Exception - */ - require_once 'Zend/Service/Exception.php'; - throw new Zend_Service_Exception($message, $code); - } - } - - return $doc; - } - - /** - * @see Zend_Service_Exception - */ - require_once 'Zend/Service/Exception.php'; - throw new Zend_Service_Exception($response->getMessage(), $response->getStatus()); - } - - /** - * Returns a list of all tags and their counts, ordered by count in - * decreasing order - * - * @param int $limit Limits the number of tags returned (optional) - * @link http://www.simpy.com/doc/api/rest/GetTags - * @throws Zend_Service_Exception - * @return Zend_Service_Simpy_TagSet - */ - public function getTags($limit = null) - { - $query = array( - 'limit' => $limit - ); - - $doc = $this->_makeRequest('GetTags', $query); - - /** - * @see Zend_Service_Simpy_TagSet - */ - require_once 'Zend/Service/Simpy/TagSet.php'; - return new Zend_Service_Simpy_TagSet($doc); - } - - /** - * Removes a tag. - * - * @param string $tag Tag to be removed - * @link http://www.simpy.com/doc/api/rest/RemoveTag - * @return Zend_Service_Simpy Provides a fluent interface - */ - public function removeTag($tag) - { - $query = array( - 'tag' => $tag - ); - - $this->_makeRequest('RemoveTag', $query); - - return $this; - } - - /** - * Renames a tag. - * - * @param string $fromTag Tag to be renamed - * @param string $toTag New tag name - * @link http://www.simpy.com/doc/api/rest/RenameTag - * @return Zend_Service_Simpy Provides a fluent interface - */ - public function renameTag($fromTag, $toTag) - { - $query = array( - 'fromTag' => $fromTag, - 'toTag' => $toTag - ); - - $this->_makeRequest('RenameTag', $query); - - return $this; - } - - /** - * Merges two tags into a new tag. - * - * @param string $fromTag1 First tag to merge. - * @param string $fromTag2 Second tag to merge. - * @param string $toTag Tag to merge the two tags into. - * @link http://www.simpy.com/doc/api/rest/MergeTags - * @return Zend_Service_Simpy Provides a fluent interface - */ - public function mergeTags($fromTag1, $fromTag2, $toTag) - { - $query = array( - 'fromTag1' => $fromTag1, - 'fromTag2' => $fromTag2, - 'toTag' => $toTag - ); - - $this->_makeRequest('MergeTags', $query); - - return $this; - } - - /** - * Splits a single tag into two separate tags. - * - * @param string $tag Tag to split - * @param string $toTag1 First tag to split into - * @param string $toTag2 Second tag to split into - * @link http://www.simpy.com/doc/api/rest/SplitTag - * @return Zend_Service_Simpy Provides a fluent interface - */ - public function splitTag($tag, $toTag1, $toTag2) - { - $query = array( - 'tag' => $tag, - 'toTag1' => $toTag1, - 'toTag2' => $toTag2 - ); - - $this->_makeRequest('SplitTag', $query); - - return $this; - } - - /** - * Performs a query on existing links and returns the results or returns all - * links if no particular query is specified (which should be used sparingly - * to prevent overloading Simpy servers) - * - * @param Zend_Service_Simpy_LinkQuery $q Query object to use (optional) - * @return Zend_Service_Simpy_LinkSet - */ - public function getLinks(Zend_Service_Simpy_LinkQuery $q = null) - { - if ($q != null) { - $query = array( - 'q' => $q->getQueryString(), - 'limit' => $q->getLimit(), - 'date' => $q->getDate(), - 'afterDate' => $q->getAfterDate(), - 'beforeDate' => $q->getBeforeDate() - ); - - $doc = $this->_makeRequest('GetLinks', $query); - } else { - $doc = $this->_makeRequest('GetLinks'); - } - - /** - * @see Zend_Service_Simpy_LinkSet - */ - require_once 'Zend/Service/Simpy/LinkSet.php'; - return new Zend_Service_Simpy_LinkSet($doc); - } - - /** - * Saves a given link. - * - * @param string $title Title of the page to save - * @param string $href URL of the page to save - * @param int $accessType ACCESSTYPE_PUBLIC or ACCESSTYPE_PRIVATE - * @param mixed $tags String containing a comma-separated list of - * tags or array of strings containing tags - * (optional) - * @param string $urlNickname Alternative custom title (optional) - * @param string $note Free text note (optional) - * @link Zend_Service_Simpy::ACCESSTYPE_PUBLIC - * @link Zend_Service_Simpy::ACCESSTYPE_PRIVATE - * @link http://www.simpy.com/doc/api/rest/SaveLink - * @return Zend_Service_Simpy Provides a fluent interface - */ - public function saveLink($title, $href, $accessType, $tags = null, $urlNickname = null, $note = null) - { - if (is_array($tags)) { - $tags = implode(',', $tags); - } - - $query = array( - 'title' => $title, - 'href' => $href, - 'accessType' => $accessType, - 'tags' => $tags, - 'urlNickname' => $urlNickname, - 'note' => $note - ); - - $this->_makeRequest('SaveLink', $query); - - return $this; - } - - /** - * Deletes a given link. - * - * @param string $href URL of the bookmark to delete - * @link http://www.simpy.com/doc/api/rest/DeleteLink - * @return Zend_Service_Simpy Provides a fluent interface - */ - public function deleteLink($href) - { - $query = array( - 'href' => $href - ); - - $this->_makeRequest('DeleteLink', $query); - - return $this; - } - - /** - * Return a list of watchlists and their meta-data, including the number - * of new links added to each watchlist since last login. - * - * @link http://www.simpy.com/doc/api/rest/GetWatchlists - * @return Zend_Service_Simpy_WatchlistSet - */ - public function getWatchlists() - { - $doc = $this->_makeRequest('GetWatchlists'); - - /** - * @see Zend_Service_Simpy_WatchlistSet - */ - require_once 'Zend/Service/Simpy/WatchlistSet.php'; - return new Zend_Service_Simpy_WatchlistSet($doc); - } - - /** - * Returns the meta-data for a given watchlist. - * - * @param int $watchlistId ID of the watchlist to retrieve - * @link http://www.simpy.com/doc/api/rest/GetWatchlist - * @return Zend_Service_Simpy_Watchlist - */ - public function getWatchlist($watchlistId) - { - $query = array( - 'watchlistId' => $watchlistId - ); - - $doc = $this->_makeRequest('GetWatchlist', $query); - - /** - * @see Zend_Service_Simpy_Watchlist - */ - require_once 'Zend/Service/Simpy/Watchlist.php'; - return new Zend_Service_Simpy_Watchlist($doc->documentElement); - } - - /** - * Returns all notes in reverse chronological order by add date or by - * rank. - * - * @param string $q Query string formatted using Simpy search syntax - * and search fields (optional) - * @param int $limit Limits the number notes returned (optional) - * @link http://www.simpy.com/doc/api/rest/GetNotes - * @link http://www.simpy.com/simpy/FAQ.do#searchSyntax - * @link http://www.simpy.com/simpy/FAQ.do#searchFieldsLinks - * @return Zend_Service_Simpy_NoteSet - */ - public function getNotes($q = null, $limit = null) - { - $query = array( - 'q' => $q, - 'limit' => $limit - ); - - $doc = $this->_makeRequest('GetNotes', $query); - - /** - * @see Zend_Service_Simpy_NoteSet - */ - require_once 'Zend/Service/Simpy/NoteSet.php'; - return new Zend_Service_Simpy_NoteSet($doc); - } - - /** - * Saves a note. - * - * @param string $title Title of the note - * @param mixed $tags String containing a comma-separated list of - * tags or array of strings containing tags - * (optional) - * @param string $description Free-text note (optional) - * @param int $noteId Unique identifier for an existing note to - * update (optional) - * @link http://www.simpy.com/doc/api/rest/SaveNote - * @return Zend_Service_Simpy Provides a fluent interface - */ - public function saveNote($title, $tags = null, $description = null, $noteId = null) - { - if (is_array($tags)) { - $tags = implode(',', $tags); - } - - $query = array( - 'title' => $title, - 'tags' => $tags, - 'description' => $description, - 'noteId' => $noteId - ); - - $this->_makeRequest('SaveNote', $query); - - return $this; - } - - /** - * Deletes a given note. - * - * @param int $noteId ID of the note to delete - * @link http://www.simpy.com/doc/api/rest/DeleteNote - * @return Zend_Service_Simpy Provides a fluent interface - */ - public function deleteNote($noteId) - { - $query = array( - 'noteId' => $noteId - ); - - $this->_makeRequest('DeleteNote', $query); - - return $this; - } -} diff --git a/lib/zend/Zend/Service/Simpy/Link.php b/lib/zend/Zend/Service/Simpy/Link.php deleted file mode 100644 index 0a7c5381eb9..00000000000 --- a/lib/zend/Zend/Service/Simpy/Link.php +++ /dev/null @@ -1,215 +0,0 @@ - node from a parsed response from - * a GetLinks operation - * @return void - */ - public function __construct($node) - { - $this->_accessType = $node->attributes->getNamedItem('accessType')->nodeValue; - - $doc = new DOMDocument(); - $doc->appendChild($doc->importNode($node, true)); - $xpath = new DOMXPath($doc); - - $this->_url = $xpath->evaluate('/link/url')->item(0)->nodeValue; - $this->_modDate = $xpath->evaluate('/link/modDate')->item(0)->nodeValue; - $this->_addDate = $xpath->evaluate('/link/addDate')->item(0)->nodeValue; - $this->_title = $xpath->evaluate('/link/title')->item(0)->nodeValue; - $this->_nickname = $xpath->evaluate('/link/nickname')->item(0)->nodeValue; - $this->_note = $xpath->evaluate('/link/note')->item(0)->nodeValue; - - $list = $xpath->query('/link/tags/tag'); - $this->_tags = array(); - - for ($x = 0; $x < $list->length; $x++) { - $this->_tags[$x] = $list->item($x)->nodeValue; - } - } - - /** - * Returns the access type assigned to the link - * - * @see ACCESSTYPE_PRIVATE - * @see ACCESSTYPE_PUBLIC - * @return string - */ - public function getAccessType() - { - return $this->_accessType; - } - - /** - * Returns the URL of the link - * - * @return string - */ - public function getUrl() - { - return $this->_url; - } - - /** - * Returns the date of the last modification made to the link - * - * @return string - */ - public function getModDate() - { - return $this->_modDate; - } - - /** - * Returns the date the link was added - * - * @return string - */ - public function getAddDate() - { - return $this->_addDate; - } - - /** - * Returns the title assigned to the link - * - * @return string - */ - public function getTitle() - { - return $this->_title; - } - - /** - * Returns the nickname assigned to the link - * - * @return string - */ - public function getNickname() - { - return $this->_nickname; - } - - /** - * Returns the tags assigned to the link - * - * @return array - */ - public function getTags() - { - return $this->_tags; - } - - /** - * Returns the note assigned to the link - * - * @return string - */ - public function getNote() - { - return $this->_note; - } -} diff --git a/lib/zend/Zend/Service/Simpy/LinkQuery.php b/lib/zend/Zend/Service/Simpy/LinkQuery.php deleted file mode 100644 index 68502f2a06e..00000000000 --- a/lib/zend/Zend/Service/Simpy/LinkQuery.php +++ /dev/null @@ -1,200 +0,0 @@ -_query = $query; - - return $this; - } - - /** - * Returns the query string set for this query - * - * @return string - */ - public function getQueryString() - { - return $this->_query; - } - - /** - * Sets the maximum number of search results to return - * - * @param int $limit - * @return Zend_Service_Simpy_LinkQuery Provides a fluent interface - */ - public function setLimit($limit) - { - $this->_limit = intval($limit); - - if ($this->_limit == 0) { - $this->_limit = null; - } - - return $this; - } - - /** - * Returns the maximum number of search results to return - * - * @return int - */ - public function getLimit() - { - return $this->_limit; - } - - /** - * Sets the date on which search results must have been added, which will - * override any existing values set using setAfterDate() and setBeforeDate() - * - * @param string $date - * @see setAfterDate() - * @see setBeforeDate() - * @return Zend_Service_Simpy_LinkQuery Provides a fluent interface - */ - public function setDate($date) - { - $this->_date = $date; - $this->_afterDate = null; - $this->_beforeDate = null; - - return $this; - } - - /** - * Returns the date on which search results must have been added - * - * @return string - */ - public function getDate() - { - return $this->_date; - } - - /** - * Sets the date after which search results must have been added, which will - * override any existing values set using setDate() - * - * @param string $date - * @see setDate() - * @return Zend_Service_Simpy_LinkQuery Provides a fluent interface - */ - public function setAfterDate($date) - { - $this->_afterDate = $date; - $this->_date = null; - - return $this; - } - - /** - * Returns the date after which search results must have been added - * - * @return string - */ - public function getAfterDate() - { - return $this->_afterDate; - } - - /** - * Sets the date before which search results must have been added, which - * will override any existing values set using setDate() - * - * @param string $date - * @see setDate() - * @return Zend_Service_Simpy_LinkQuery Provides a fluent interface - */ - public function setBeforeDate($date) - { - $this->_beforeDate = $date; - $this->_date = null; - - return $this; - } - - /** - * Returns the date before which search results must have been added - * - * @return string - */ - public function getBeforeDate() - { - return $this->_beforeDate; - } -} diff --git a/lib/zend/Zend/Service/Simpy/LinkSet.php b/lib/zend/Zend/Service/Simpy/LinkSet.php deleted file mode 100644 index 8fa5ad89c3a..00000000000 --- a/lib/zend/Zend/Service/Simpy/LinkSet.php +++ /dev/null @@ -1,83 +0,0 @@ -query('//links/link'); - $this->_links = array(); - - for ($x = 0; $x < $list->length; $x++) { - $this->_links[$x] = new Zend_Service_Simpy_Link($list->item($x)); - } - } - - /** - * Returns an iterator for the link set - * - * @return ArrayIterator - */ - public function getIterator() - { - return new ArrayIterator($this->_links); - } - - /** - * Returns the number of links in the set - * - * @return int - */ - public function getLength() - { - return count($this->_links); - } -} diff --git a/lib/zend/Zend/Service/Simpy/Note.php b/lib/zend/Zend/Service/Simpy/Note.php deleted file mode 100644 index 75d65d9ab64..00000000000 --- a/lib/zend/Zend/Service/Simpy/Note.php +++ /dev/null @@ -1,215 +0,0 @@ - node from a parsed response from - * a GetLinks operation - * @return void - */ - public function __construct($node) - { - $this->_accessType = $node->attributes->getNamedItem('accessType')->nodeValue; - - $doc = new DOMDocument(); - $doc->appendChild($doc->importNode($node, true)); - $xpath = new DOMXPath($doc); - - $this->_uri = $xpath->evaluate('/note/uri')->item(0)->nodeValue; - $this->_id = substr($this->_uri, strrpos($this->_uri, '=') + 1); - $this->_modDate = trim($xpath->evaluate('/note/modDate')->item(0)->nodeValue); - $this->_addDate = trim($xpath->evaluate('/note/addDate')->item(0)->nodeValue); - $this->_title = $xpath->evaluate('/note/title')->item(0)->nodeValue; - $this->_description = $xpath->evaluate('/note/description')->item(0)->nodeValue; - - $list = $xpath->query('/note/tags/tag'); - $this->_tags = array(); - - for ($x = 0; $x < $list->length; $x++) { - $this->_tags[$x] = $list->item($x)->nodeValue; - } - } - - /** - * Returns the access type assigned to the note - * - * @see ACCESSTYPE_PRIVATE - * @see ACCESSTYPE_PUBLIC - * @return string - */ - public function getAccessType() - { - return $this->_accessType; - } - - /** - * Returns the ID of the note - * - * @return int - */ - public function getId() - { - return $this->_id; - } - - /** - * Returns the URI of the note - * - * @return string - */ - public function getUri() - { - return $this->_uri; - } - - /** - * Returns the date of the last modification made to the note - * - * @return string - */ - public function getModDate() - { - return $this->_modDate; - } - - /** - * Returns the date the note was added - * - * @return string - */ - public function getAddDate() - { - return $this->_addDate; - } - - /** - * Returns the title assigned to the note - * - * @return string - */ - public function getTitle() - { - return $this->_title; - } - - /** - * Returns the tags assigned to the note - * - * @return array - */ - public function getTags() - { - return $this->_tags; - } - - /** - * Returns the description assigned to the note - * - * @return string - */ - public function getDescription() - { - return $this->_description; - } -} diff --git a/lib/zend/Zend/Service/Simpy/NoteSet.php b/lib/zend/Zend/Service/Simpy/NoteSet.php deleted file mode 100644 index 38fa6fd99b5..00000000000 --- a/lib/zend/Zend/Service/Simpy/NoteSet.php +++ /dev/null @@ -1,83 +0,0 @@ -query('//notes/note'); - $this->_notes = array(); - - for ($x = 0; $x < $list->length; $x++) { - $this->_notes[$x] = new Zend_Service_Simpy_Note($list->item($x)); - } - } - - /** - * Returns an iterator for the note set - * - * @return ArrayIterator - */ - public function getIterator() - { - return new ArrayIterator($this->_notes); - } - - /** - * Returns the number of notes in the set - * - * @return int - */ - public function getLength() - { - return count($this->_notes); - } -} diff --git a/lib/zend/Zend/Service/Simpy/Tag.php b/lib/zend/Zend/Service/Simpy/Tag.php deleted file mode 100644 index 694c4ad7054..00000000000 --- a/lib/zend/Zend/Service/Simpy/Tag.php +++ /dev/null @@ -1,81 +0,0 @@ - node from a parsed response from - * a GetTags operation - * @return void - */ - public function __construct($node) - { - $map =& $node->attributes; - $this->_tag = $map->getNamedItem('name')->nodeValue; - $this->_count = $map->getNamedItem('count')->nodeValue; - } - - /** - * Returns the name of the tag - * - * @return string - */ - public function getTag() - { - return $this->_tag; - } - - /** - * Returns the number of links with the tag - * - * @return int - */ - public function getCount() - { - return $this->_count; - } -} diff --git a/lib/zend/Zend/Service/Simpy/TagSet.php b/lib/zend/Zend/Service/Simpy/TagSet.php deleted file mode 100644 index 904922cde76..00000000000 --- a/lib/zend/Zend/Service/Simpy/TagSet.php +++ /dev/null @@ -1,83 +0,0 @@ -query('//tags/tag'); - $this->_tags = array(); - - for ($x = 0; $x < $list->length; $x++) { - $this->_tags[$x] = new Zend_Service_Simpy_Tag($list->item($x)); - } - } - - /** - * Returns an iterator for the tag set - * - * @return ArrayIterator - */ - public function getIterator() - { - return new ArrayIterator($this->_tags); - } - - /** - * Returns the number of tags in the set - * - * @return int - */ - public function getLength() - { - return count($this->_tags); - } -} diff --git a/lib/zend/Zend/Service/Simpy/Watchlist.php b/lib/zend/Zend/Service/Simpy/Watchlist.php deleted file mode 100644 index 2eb531c4a0a..00000000000 --- a/lib/zend/Zend/Service/Simpy/Watchlist.php +++ /dev/null @@ -1,191 +0,0 @@ - node from a parsed - * response from a GetWatchlists or GetWatchlist - * operation - * @return void - */ - public function __construct($node) - { - $map =& $node->attributes; - - $this->_id = $map->getNamedItem('id')->nodeValue; - $this->_name = $map->getNamedItem('name')->nodeValue; - $this->_description = $map->getNamedItem('description')->nodeValue; - $this->_addDate = $map->getNamedItem('addDate')->nodeValue; - $this->_newLinks = $map->getNamedItem('newLinks')->nodeValue; - - $this->_users = array(); - $this->_filters = new Zend_Service_Simpy_WatchlistFilterSet(); - - $childNode = $node->firstChild; - while ($childNode !== null) { - if ($childNode->nodeName == 'user') { - $this->_users[] = $childNode->attributes->getNamedItem('username')->nodeValue; - } elseif ($childNode->nodeName == 'filter') { - $filter = new Zend_Service_Simpy_WatchlistFilter($childNode); - $this->_filters->add($filter); - } - $childNode = $childNode->nextSibling; - } - } - - /** - * Returns the identifier for the watchlist - * - * @return int - */ - public function getId() - { - return $this->_id; - } - - /** - * Returns the name of the watchlist - * - * @return string - */ - public function getName() - { - return $this->_name; - } - - /** - * Returns the description of the watchlist - * - * @return string - */ - public function getDescription() - { - return $this->_description; - } - - /** - * Returns a timestamp for when the watchlist was added - * - * @return string - */ - public function getAddDate() - { - return $this->_addDate; - } - - /** - * Returns the number of new links in the watchlist - * - * @return int - */ - public function getNewLinks() - { - return $this->_newLinks; - } - - /** - * Returns a list of usernames for users included in the watchlist - * - * @return array - */ - public function getUsers() - { - return $this->_users; - } - - /** - * Returns a list of filters included in the watchlist - * - * @return Zend_Service_Simpy_WatchlistFilterSet - */ - public function getFilters() - { - return $this->_filters; - } -} diff --git a/lib/zend/Zend/Service/Simpy/WatchlistFilter.php b/lib/zend/Zend/Service/Simpy/WatchlistFilter.php deleted file mode 100644 index 210fddc317e..00000000000 --- a/lib/zend/Zend/Service/Simpy/WatchlistFilter.php +++ /dev/null @@ -1,81 +0,0 @@ - node from a parsed response from - * a GetWatchlists or GetWatchlist operation - * @return void - */ - public function __construct($node) - { - $map =& $node->attributes; - $this->_name = $map->getNamedItem('name')->nodeValue; - $this->_query = $map->getNamedItem('query')->nodeValue; - } - - /** - * Returns the name of the filter - * - * @return string - */ - public function getName() - { - return $this->_name; - } - - /** - * Returns the query for the filter - * - * @return string - */ - public function getQuery() - { - return $this->_query; - } -} diff --git a/lib/zend/Zend/Service/Simpy/WatchlistFilterSet.php b/lib/zend/Zend/Service/Simpy/WatchlistFilterSet.php deleted file mode 100644 index 3e1a2f7d7a2..00000000000 --- a/lib/zend/Zend/Service/Simpy/WatchlistFilterSet.php +++ /dev/null @@ -1,77 +0,0 @@ -_filters[] = $filter; - } - - /** - * Returns an iterator for the watchlist filter set - * - * @return ArrayIterator - */ - public function getIterator() - { - return new ArrayIterator($this->_filters); - } - - /** - * Returns the number of filters in the set - * - * @return int - */ - public function getLength() - { - return count($this->_filters); - } -} diff --git a/lib/zend/Zend/Service/Simpy/WatchlistSet.php b/lib/zend/Zend/Service/Simpy/WatchlistSet.php deleted file mode 100644 index 93a5e4a3b97..00000000000 --- a/lib/zend/Zend/Service/Simpy/WatchlistSet.php +++ /dev/null @@ -1,82 +0,0 @@ -query('//watchlists/watchlist'); - - for ($x = 0; $x < $list->length; $x++) { - $this->_watchlists[$x] = new Zend_Service_Simpy_Watchlist($list->item($x)); - } - } - - /** - * Returns an iterator for the watchlist set - * - * @return ArrayIterator - */ - public function getIterator() - { - return new ArrayIterator($this->_watchlists); - } - - /** - * Returns the number of watchlists in the set - * - * @return int - */ - public function getLength() - { - return count($this->_watchlists); - } -} diff --git a/lib/zend/Zend/Service/SlideShare.php b/lib/zend/Zend/Service/SlideShare.php index 7fcdc2510f8..33577af8a23 100644 --- a/lib/zend/Zend/Service/SlideShare.php +++ b/lib/zend/Zend/Service/SlideShare.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Service * @subpackage SlideShare - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -35,6 +35,9 @@ require_once 'Zend/Cache.php'; */ require_once 'Zend/Service/SlideShare/SlideShow.php'; +/** Zend_Xml_Security */ +require_once 'Zend/Xml/Security.php'; + /** * The Zend_Service_SlideShare component is used to interface with the * slideshare.net web server to retrieve slide shows hosted on the web site for @@ -44,12 +47,11 @@ require_once 'Zend/Service/SlideShare/SlideShow.php'; * @package Zend_Service * @subpackage SlideShare * @throws Zend_Service_SlideShare_Exception - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Service_SlideShare { - /** * Web service result code mapping */ @@ -71,17 +73,17 @@ class Zend_Service_SlideShare /** * Slide share Web service communication URIs */ - const SERVICE_UPLOAD_URI = 'http://www.slideshare.net/api/1/upload_slideshow'; - const SERVICE_GET_SHOW_URI = 'http://www.slideshare.net/api/1/get_slideshow'; - const SERVICE_GET_SHOW_BY_USER_URI = 'http://www.slideshare.net/api/1/get_slideshow_by_user'; - const SERVICE_GET_SHOW_BY_TAG_URI = 'http://www.slideshare.net/api/1/get_slideshow_by_tag'; - const SERVICE_GET_SHOW_BY_GROUP_URI = 'http://www.slideshare.net/api/1/get_slideshows_from_group'; + const SERVICE_UPLOAD_URI = 'https://www.slideshare.net/api/2/upload_slideshow'; + const SERVICE_GET_SHOW_URI = 'https://www.slideshare.net/api/2/get_slideshow'; + const SERVICE_GET_SHOW_BY_USER_URI = 'https://www.slideshare.net/api/2/get_slideshows_by_user'; + const SERVICE_GET_SHOW_BY_TAG_URI = 'https://www.slideshare.net/api/2/get_slideshows_by_tag'; + const SERVICE_GET_SHOW_BY_GROUP_URI = 'https://www.slideshare.net/api/2/get_slideshows_by_group'; /** * The MIME type of Slideshow files * */ - const POWERPOINT_MIME_TYPE = "application/vnd.ms-powerpoint"; + const POWERPOINT_MIME_TYPE = "application/vnd.ms-powerpoint"; /** * The API key to use in requests @@ -126,8 +128,8 @@ class Zend_Service_SlideShare protected $_cacheobject; /** - * Sets the Zend_Http_Client object to use in requests. If not provided a default will - * be used. + * Sets the Zend_Http_Client object to use in requests. If not provided a + * default will be used. * * @param Zend_Http_Client $client The HTTP client instance to use * @return Zend_Service_SlideShare @@ -139,23 +141,28 @@ class Zend_Service_SlideShare } /** - * Returns the instance of the Zend_Http_Client which will be used. Creates an instance - * of Zend_Http_Client if no previous client was set. + * Returns the instance of the Zend_Http_Client which will be used. Creates + * an instance of Zend_Http_Client if no previous client was set. * * @return Zend_Http_Client The HTTP client which will be used */ public function getHttpClient() { - if(!($this->_httpclient instanceof Zend_Http_Client)) { + if (!($this->_httpclient instanceof Zend_Http_Client)) { $client = new Zend_Http_Client(); - $client->setConfig(array('maxredirects' => 2, - 'timeout' => 5)); + $client->setConfig( + array( + 'maxredirects' => 2, + 'timeout' => 5 + ) + ); $this->setHttpClient($client); } $this->_httpclient->resetParameters(); + return $this->_httpclient; } @@ -172,19 +179,25 @@ class Zend_Service_SlideShare } /** - * Gets the Zend_Cache object which will be used to cache API queries. If no cache object - * was previously set the the default will be used (Filesystem caching in /tmp with a life - * time of 43200 seconds) + * Gets the Zend_Cache object which will be used to cache API queries. If no + * cache object was previously set the the default will be used (Filesystem + * caching in /tmp with a life time of 43200 seconds) * * @return Zend_Cache_Core The object used in caching */ public function getCacheObject() { - if(!($this->_cacheobject instanceof Zend_Cache_Core)) { - $cache = Zend_Cache::factory('Core', 'File', array('lifetime' => 43200, - 'automatic_serialization' => true), - array('cache_dir' => '/tmp')); + if (!($this->_cacheobject instanceof Zend_Cache_Core)) { + $cache = Zend_Cache::factory( + 'Core', + 'File', + array( + 'lifetime' => 43200, + 'automatic_serialization' => true + ), + array('cache_dir' => '/tmp') + ); $this->setCacheObject($cache); } @@ -283,17 +296,19 @@ class Zend_Service_SlideShare /** * The Constructor * - * @param string $apikey The API key + * @param string $apikey The API key * @param string $sharedSecret The shared secret - * @param string $username The username - * @param string $password The password + * @param string $username The username + * @param string $password The password */ - public function __construct($apikey, $sharedSecret, $username = null, $password = null) + public function __construct( + $apikey, $sharedSecret, $username = null, $password = null + ) { $this->setApiKey($apikey) - ->setSharedSecret($sharedSecret) - ->setUserName($username) - ->setPassword($password); + ->setSharedSecret($sharedSecret) + ->setUserName($username) + ->setPassword($password); $this->_httpclient = new Zend_Http_Client(); } @@ -301,41 +316,53 @@ class Zend_Service_SlideShare /** * Uploads the specified Slide show the the server * - * @param Zend_Service_SlideShare_SlideShow $ss The slide show object representing the slide show to upload - * @param boolean $make_src_public Determines if the the slide show's source file is public or not upon upload - * @return Zend_Service_SlideShare_SlideShow The passed Slide show object, with the new assigned ID provided + * @param Zend_Service_SlideShare_SlideShow $ss The slide show + * object representing the + * slide show to upload + * @param boolean $makeSrcPublic Determines if the slide + * show's source file is public + * or not upon upload + * @return Zend_Service_SlideShare_SlideShow The passed Slide show object, + * with the new assigned ID + * provided + * @throws Zend_Service_SlideShare_Exception */ - public function uploadSlideShow(Zend_Service_SlideShare_SlideShow $ss, $make_src_public = true) + public function uploadSlideShow( + Zend_Service_SlideShare_SlideShow $ss, $makeSrcPublic = true + ) { - $timestamp = time(); - $params = array('api_key' => $this->getApiKey(), - 'ts' => $timestamp, - 'hash' => sha1($this->getSharedSecret().$timestamp), - 'username' => $this->getUserName(), - 'password' => $this->getPassword(), - 'slideshow_title' => $ss->getTitle()); + $params = array( + 'api_key' => $this->getApiKey(), + 'ts' => $timestamp, + 'hash' => sha1($this->getSharedSecret() . $timestamp), + 'username' => $this->getUserName(), + 'password' => $this->getPassword(), + 'slideshow_title' => $ss->getTitle() + ); $description = $ss->getDescription(); - $tags = $ss->getTags(); + $tags = $ss->getTags(); $filename = $ss->getFilename(); - if(!file_exists($filename) || !is_readable($filename)) { + if (!file_exists($filename) || !is_readable($filename)) { require_once 'Zend/Service/SlideShare/Exception.php'; - throw new Zend_Service_SlideShare_Exception("Specified Slideshow for upload not found or unreadable"); + throw new Zend_Service_SlideShare_Exception( + 'Specified Slideshow for upload not found or unreadable' + ); } - if(!empty($description)) { + if (!empty($description)) { $params['slideshow_description'] = $description; } else { $params['slideshow_description'] = ""; } - if(!empty($tags)) { + if (!empty($tags)) { $tmp = array(); - foreach($tags as $tag) { + foreach ($tags as $tag) { $tmp[] = "\"$tag\""; } $params['slideshow_tags'] = implode(' ', $tmp); @@ -343,7 +370,6 @@ class Zend_Service_SlideShare $params['slideshow_tags'] = ""; } - $client = $this->getHttpClient(); $client->setUri(self::SERVICE_UPLOAD_URI); $client->setParameterPost($params); @@ -352,23 +378,30 @@ class Zend_Service_SlideShare require_once 'Zend/Http/Client/Exception.php'; try { $response = $client->request('POST'); - } catch(Zend_Http_Client_Exception $e) { + } catch (Zend_Http_Client_Exception $e) { require_once 'Zend/Service/SlideShare/Exception.php'; - throw new Zend_Service_SlideShare_Exception("Service Request Failed: {$e->getMessage()}", 0, $e); + throw new Zend_Service_SlideShare_Exception( + "Service Request Failed: {$e->getMessage()}", 0, $e + ); } - $sxe = simplexml_load_string($response->getBody()); + $sxe = Zend_Xml_Security::scan($response->getBody()); - if($sxe->getName() == "SlideShareServiceError") { + if ($sxe->getName() == "SlideShareServiceError") { $message = (string)$sxe->Message[0]; - list($code, $error_str) = explode(':', $message); + list($code, $errorStr) = explode(':', $message); require_once 'Zend/Service/SlideShare/Exception.php'; - throw new Zend_Service_SlideShare_Exception(trim($error_str), $code); + throw new Zend_Service_SlideShare_Exception( + trim($errorStr), + $code + ); } - if(!$sxe->getName() == "SlideShowUploaded") { + if (!$sxe->getName() == "SlideShowUploaded") { require_once 'Zend/Service/SlideShare/Exception.php'; - throw new Zend_Service_SlideShare_Exception("Unknown XML Respons Received"); + throw new Zend_Service_SlideShare_Exception( + 'Unknown XML Respons Received' + ); } $ss->setId((int)(string)$sxe->SlideShowID); @@ -379,23 +412,25 @@ class Zend_Service_SlideShare /** * Retrieves a slide show's information based on slide show ID * - * @param int $ss_id The slide show ID + * @param int $ssId The slide show ID * @return Zend_Service_SlideShare_SlideShow the Slideshow object + * @throws Zend_Service_SlideShare_Exception */ - public function getSlideShow($ss_id) + public function getSlideShow($ssId) { $timestamp = time(); - $params = array('api_key' => $this->getApiKey(), - 'ts' => $timestamp, - 'hash' => sha1($this->getSharedSecret().$timestamp), - 'slideshow_id' => $ss_id); + $params = array( + 'api_key' => $this->getApiKey(), + 'ts' => $timestamp, + 'hash' => sha1($this->getSharedSecret() . $timestamp), + 'slideshow_id' => $ssId + ); - $cache = $this->getCacheObject(); + $cache = $this->getCacheObject(); + $cacheKey = md5("__zendslideshare_cache_$ssId"); - $cache_key = md5("__zendslideshare_cache_$ss_id"); - - if(!$retval = $cache->load($cache_key)) { + if (!$retval = $cache->load($cacheKey)) { $client = $this->getHttpClient(); $client->setUri(self::SERVICE_GET_SHOW_URI); @@ -404,28 +439,34 @@ class Zend_Service_SlideShare require_once 'Zend/Http/Client/Exception.php'; try { $response = $client->request('POST'); - } catch(Zend_Http_Client_Exception $e) { + } catch (Zend_Http_Client_Exception $e) { require_once 'Zend/Service/SlideShare/Exception.php'; - throw new Zend_Service_SlideShare_Exception("Service Request Failed: {$e->getMessage()}", 0, $e); + throw new Zend_Service_SlideShare_Exception( + "Service Request Failed: {$e->getMessage()}", 0, $e + ); } - $sxe = simplexml_load_string($response->getBody()); + $sxe = Zend_Xml_Security::scan($response->getBody()); - if($sxe->getName() == "SlideShareServiceError") { + if ($sxe->getName() == "SlideShareServiceError") { $message = (string)$sxe->Message[0]; - list($code, $error_str) = explode(':', $message); + list($code, $errorStr) = explode(':', $message); require_once 'Zend/Service/SlideShare/Exception.php'; - throw new Zend_Service_SlideShare_Exception(trim($error_str), $code); + throw new Zend_Service_SlideShare_Exception( + trim($errorStr), + $code + ); } - if(!$sxe->getName() == 'Slideshows') { + if (!($sxe->getName() == 'Slideshow')) { require_once 'Zend/Service/SlideShare/Exception.php'; - throw new Zend_Service_SlideShare_Exception('Unknown XML Repsonse Received'); + throw new Zend_Service_SlideShare_Exception( + 'Unknown XML Repsonse Received' + ); } + $retval = $this->_slideShowNodeToObject(clone $sxe); - $retval = $this->_slideShowNodeToObject(clone $sxe->Slideshow[0]); - - $cache->save($retval, $cache_key); + $cache->save($retval, $cacheKey); } return $retval; @@ -439,9 +480,13 @@ class Zend_Service_SlideShare * @param int $limit The maximum number of slide shows to retrieve * @return array An array of Zend_Service_SlideShare_SlideShow objects */ - public function getSlideShowsByUsername($username, $offset = null, $limit = null) + public function getSlideShowsByUsername( + $username, $offset = null, $limit = null + ) { - return $this->_getSlideShowsByType('username_for', $username, $offset, $limit); + return $this->_getSlideShowsByType( + 'username_for', $username, $offset, $limit + ); } /** @@ -455,9 +500,9 @@ class Zend_Service_SlideShare public function getSlideShowsByTag($tag, $offset = null, $limit = null) { - if(is_array($tag)) { + if (is_array($tag)) { $tmp = array(); - foreach($tag as $t) { + foreach ($tag as $t) { $tmp[] = "\"$t\""; } @@ -484,56 +529,60 @@ class Zend_Service_SlideShare * Retrieves Zend_Service_SlideShare_SlideShow object arrays based on the type of * list desired * - * @param string $key The type of slide show object to retrieve - * @param string $value The specific search query for the slide show type to look up - * @param int $offset The offset of the list to start retrieving from - * @param int $limit The maximum number of slide shows to retrieve + * @param string $key The type of slide show object to retrieve + * @param string $value The specific search query for the slide show type to look up + * @param int $offset The offset of the list to start retrieving from + * @param int $limit The maximum number of slide shows to retrieve * @return array An array of Zend_Service_SlideShare_SlideShow objects + * @throws Zend_Service_SlideShare_Exception */ - protected function _getSlideShowsByType($key, $value, $offset = null, $limit = null) + protected function _getSlideShowsByType( + $key, $value, $offset = null, $limit = null + ) { - $key = strtolower($key); - switch($key) { + switch ($key) { case 'username_for': $responseTag = 'User'; - $queryUri = self::SERVICE_GET_SHOW_BY_USER_URI; + $queryUri = self::SERVICE_GET_SHOW_BY_USER_URI; break; case 'group_name': $responseTag = 'Group'; - $queryUri = self::SERVICE_GET_SHOW_BY_GROUP_URI; + $queryUri = self::SERVICE_GET_SHOW_BY_GROUP_URI; break; case 'tag': $responseTag = 'Tag'; - $queryUri = self::SERVICE_GET_SHOW_BY_TAG_URI; + $queryUri = self::SERVICE_GET_SHOW_BY_TAG_URI; break; default: require_once 'Zend/Service/SlideShare/Exception.php'; - throw new Zend_Service_SlideShare_Exception("Invalid SlideShare Query"); + throw new Zend_Service_SlideShare_Exception( + 'Invalid SlideShare Query' + ); } $timestamp = time(); - $params = array('api_key' => $this->getApiKey(), - 'ts' => $timestamp, - 'hash' => sha1($this->getSharedSecret().$timestamp), - $key => $value); + $params = array( + 'api_key' => $this->getApiKey(), + 'ts' => $timestamp, + 'hash' => sha1($this->getSharedSecret() . $timestamp), + $key => $value + ); - if($offset !== null) { + if ($offset !== null) { $params['offset'] = (int)$offset; } - if($limit !== null) { + if ($limit !== null) { $params['limit'] = (int)$limit; } - $cache = $this->getCacheObject(); - - $cache_key = md5($key.$value.$offset.$limit); - - if(!$retval = $cache->load($cache_key)) { + $cache = $this->getCacheObject(); + $cacheKey = md5($key . $value . $offset . $limit); + if (!$retval = $cache->load($cacheKey)) { $client = $this->getHttpClient(); $client->setUri($queryUri); @@ -542,34 +591,40 @@ class Zend_Service_SlideShare require_once 'Zend/Http/Client/Exception.php'; try { $response = $client->request('POST'); - } catch(Zend_Http_Client_Exception $e) { + } catch (Zend_Http_Client_Exception $e) { require_once 'Zend/Service/SlideShare/Exception.php'; - throw new Zend_Service_SlideShare_Exception("Service Request Failed: {$e->getMessage()}", 0, $e); + throw new Zend_Service_SlideShare_Exception( + "Service Request Failed: {$e->getMessage()}", 0, $e + ); } - $sxe = simplexml_load_string($response->getBody()); + $sxe = Zend_Xml_Security::scan($response->getBody()); - if($sxe->getName() == "SlideShareServiceError") { + if ($sxe->getName() == "SlideShareServiceError") { $message = (string)$sxe->Message[0]; - list($code, $error_str) = explode(':', $message); + list($code, $errorStr) = explode(':', $message); require_once 'Zend/Service/SlideShare/Exception.php'; - throw new Zend_Service_SlideShare_Exception(trim($error_str), $code); + throw new Zend_Service_SlideShare_Exception( + trim($errorStr), $code + ); } - if(!$sxe->getName() == $responseTag) { + if (!$sxe->getName() == $responseTag) { require_once 'Zend/Service/SlideShare/Exception.php'; - throw new Zend_Service_SlideShare_Exception('Unknown or Invalid XML Repsonse Received'); + throw new Zend_Service_SlideShare_Exception( + 'Unknown or Invalid XML Repsonse Received' + ); } $retval = array(); - foreach($sxe->children() as $node) { - if($node->getName() == 'Slideshow') { + foreach ($sxe->children() as $node) { + if ($node->getName() == 'Slideshow') { $retval[] = $this->_slideShowNodeToObject($node); } } - $cache->save($retval, $cache_key); + $cache->save($retval, $cacheKey); } return $retval; @@ -579,41 +634,43 @@ class Zend_Service_SlideShare * Converts a SimpleXMLElement object representing a response from the service * into a Zend_Service_SlideShare_SlideShow object * + * @see http://www.slideshare.net/developers/documentation#get_slideshow + * * @param SimpleXMLElement $node The input XML from the slideshare.net service * @return Zend_Service_SlideShare_SlideShow The resulting object + * @throws Zend_Service_SlideShare_Exception */ protected function _slideShowNodeToObject(SimpleXMLElement $node) { - if($node->getName() == 'Slideshow') { - + if ($node->getName() == 'Slideshow') { $ss = new Zend_Service_SlideShare_SlideShow(); $ss->setId((string)$node->ID); $ss->setDescription((string)$node->Description); - $ss->setEmbedCode((string)$node->EmbedCode); + $ss->setEmbedCode((string)$node->Embed); $ss->setNumViews((string)$node->Views); - $ss->setPermaLink((string)$node->Permalink); + $ss->setUrl((string)$node->URL); $ss->setStatus((string)$node->Status); $ss->setStatusDescription((string)$node->StatusDescription); - foreach(explode(",", (string)$node->Tags) as $tag) { - - if(!in_array($tag, $ss->getTags())) { + foreach (explode(",", (string)$node->Tags) as $tag) { + if (!in_array($tag, $ss->getTags())) { $ss->addTag($tag); } } - $ss->setThumbnailUrl((string)$node->Thumbnail); + $ss->setThumbnailUrl((string)$node->ThumbnailURL); $ss->setTitle((string)$node->Title); $ss->setLocation((string)$node->Location); $ss->setTranscript((string)$node->Transcript); return $ss; - } require_once 'Zend/Service/SlideShare/Exception.php'; - throw new Zend_Service_SlideShare_Exception("Was not provided the expected XML Node for processing"); + throw new Zend_Service_SlideShare_Exception( + 'Was not provided the expected XML Node for processing' + ); } } diff --git a/lib/zend/Zend/Service/SlideShare/Exception.php b/lib/zend/Zend/Service/SlideShare/Exception.php index a8939d30c80..577d6366014 100644 --- a/lib/zend/Zend/Service/SlideShare/Exception.php +++ b/lib/zend/Zend/Service/SlideShare/Exception.php @@ -16,7 +16,7 @@ * @category Zend * @package Zend_Service * @subpackage SlideShare - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -30,9 +30,9 @@ require_once 'Zend/Service/Exception.php'; * @category Zend * @package Zend_Service * @subpackage SlideShare - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Service_SlideShare_Exception extends Zend_Service_Exception { -} \ No newline at end of file +} diff --git a/lib/zend/Zend/Service/SlideShare/SlideShow.php b/lib/zend/Zend/Service/SlideShare/SlideShow.php index 7699e0238ea..782ef496e52 100644 --- a/lib/zend/Zend/Service/SlideShare/SlideShow.php +++ b/lib/zend/Zend/Service/SlideShare/SlideShow.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Service * @subpackage SlideShare - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -28,12 +28,11 @@ * @category Zend * @package Zend_Service * @subpackage SlideShare - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Service_SlideShare_SlideShow { - /** * Status constant mapping for web service * @@ -86,11 +85,11 @@ class Zend_Service_SlideShare_SlideShow protected $_statusDescription; /** - * The Permanent link for the slide show + * The URL for the slide show * - * @var string the Permalink for the slide show + * @var string the URL for the slide show */ - protected $_permalink; + protected $_url; /** * The number of views this slide show has received @@ -328,7 +327,7 @@ class Zend_Service_SlideShare_SlideShow /** * Sets the description for the Slide show * - * @param strign $desc The description of the slide show + * @param string $desc The description of the slide show * @return Zend_Service_SlideShare_SlideShow */ public function setDescription($desc) @@ -394,23 +393,51 @@ class Zend_Service_SlideShare_SlideShow /** * Sets the permanent link of the slide show * + * @see Zend_Service_SlideShare_SlideShow::setUrl() + * * @param string $url The permanent URL for the slide show * @return Zend_Service_SlideShare_SlideShow + * @deprecated Since 1.12.10, use setUrl() */ public function setPermaLink($url) { - $this->_permalink = (string)$url; + $this->setUrl($url); return $this; } /** * Gets the permanent link of the slide show * + * @see Zend_Service_SlideShare_SlideShow::getUrl() + * * @return string the permanent URL for the slide show + * @deprecated Since 1.12.10, use getUrl() */ public function getPermaLink() { - return $this->_permalink; + return $this->getUrl(); + } + + /** + * Sets the URL of the slide show + * + * @param string $url The URL for the slide show + * @return self + */ + public function setUrl($url) + { + $this->_url = (string)$url; + return $this; + } + + /** + * Gets the URL of the slide show + * + * @return string The URL for the slide show + */ + public function getUrl() + { + return $this->_url; } /** @@ -434,4 +461,4 @@ class Zend_Service_SlideShare_SlideShow { return $this->_numViews; } -} \ No newline at end of file +} diff --git a/lib/zend/Zend/Service/WindowsAzure/Exception.php b/lib/zend/Zend/Service/SqlAzure/Exception.php similarity index 78% rename from lib/zend/Zend/Service/WindowsAzure/Exception.php rename to lib/zend/Zend/Service/SqlAzure/Exception.php index 73f69523e42..800baafcef8 100644 --- a/lib/zend/Zend/Service/WindowsAzure/Exception.php +++ b/lib/zend/Zend/Service/SqlAzure/Exception.php @@ -16,7 +16,7 @@ * @package Zend_Service_WindowsAzure * @subpackage Exception * @version $Id$ - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -27,9 +27,9 @@ require_once 'Zend/Service/Exception.php'; /** * @category Zend - * @package Zend_Service_WindowsAzure - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @package Zend_Service_SqlAzure + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class Zend_Service_WindowsAzure_Exception extends Zend_Service_Exception +class Zend_Service_SqlAzure_Exception extends Zend_Service_Exception {} diff --git a/lib/zend/Zend/Service/SqlAzure/Management/Client.php b/lib/zend/Zend/Service/SqlAzure/Management/Client.php new file mode 100644 index 00000000000..5aec418b887 --- /dev/null +++ b/lib/zend/Zend/Service/SqlAzure/Management/Client.php @@ -0,0 +1,612 @@ +_subscriptionId = $subscriptionId; + $this->_certificatePath = $certificatePath; + $this->_certificatePassphrase = $certificatePassphrase; + + $this->_retryPolicy = $retryPolicy; + if (is_null($this->_retryPolicy)) { + $this->_retryPolicy = Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract::noRetry(); + } + + // Setup default Zend_Http_Client channel + $options = array( + 'adapter' => 'Zend_Http_Client_Adapter_Socket', + 'ssltransport' => 'ssl', + 'sslcert' => $this->_certificatePath, + 'sslpassphrase' => $this->_certificatePassphrase, + 'sslusecontext' => true, + ); + if (function_exists('curl_init')) { + // Set cURL options if cURL is used afterwards + $options['curloptions'] = array( + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_TIMEOUT => 120, + ); + } + $this->_httpClientChannel = new Zend_Http_Client(null, $options); + } + + /** + * Set the HTTP client channel to use + * + * @param Zend_Http_Client_Adapter_Interface|string $adapterInstance Adapter instance or adapter class name. + */ + public function setHttpClientChannel($adapterInstance = 'Zend_Http_Client_Adapter_Socket') + { + $this->_httpClientChannel->setAdapter($adapterInstance); + } + + /** + * Retrieve HTTP client channel + * + * @return Zend_Http_Client_Adapter_Interface + */ + public function getHttpClientChannel() + { + return $this->_httpClientChannel; + } + + /** + * Returns the Windows Azure subscription ID + * + * @return string + */ + public function getSubscriptionId() + { + return $this->_subscriptionId; + } + + /** + * Returns the last request ID. + * + * @return string + */ + public function getLastRequestId() + { + return $this->_lastRequestId; + } + + /** + * Get base URL for creating requests + * + * @return string + */ + public function getBaseUrl() + { + return self::URL_MANAGEMENT . '/' . $this->_subscriptionId; + } + + /** + * Perform request using Zend_Http_Client channel + * + * @param string $path Path + * @param string $queryString Query string + * @param string $httpVerb HTTP verb the request will use + * @param array $headers x-ms headers to add + * @param mixed $rawData Optional RAW HTTP data to be sent over the wire + * @return Zend_Http_Response + */ + protected function _performRequest( + $path = '/', + $queryString = '', + $httpVerb = Zend_Http_Client::GET, + $headers = array(), + $rawData = null + ) { + // Clean path + if (strpos($path, '/') !== 0) { + $path = '/' . $path; + } + + // Clean headers + if (is_null($headers)) { + $headers = array(); + } + + // Ensure cUrl will also work correctly: + // - disable Content-Type if required + // - disable Expect: 100 Continue + if (!isset($headers["Content-Type"])) { + $headers["Content-Type"] = ''; + } + //$headers["Expect"] = ''; + + // Add version header + $headers['x-ms-version'] = $this->_apiVersion; + + // URL encoding + $path = self::urlencode($path); + $queryString = self::urlencode($queryString); + + // Generate URL and sign request + $requestUrl = $this->getBaseUrl() . $path . $queryString; + $requestHeaders = $headers; + + // Prepare request + $this->_httpClientChannel->resetParameters(true); + $this->_httpClientChannel->setUri($requestUrl); + $this->_httpClientChannel->setHeaders($requestHeaders); + $this->_httpClientChannel->setRawData($rawData); + + // Execute request + $response = $this->_retryPolicy->execute( + array($this->_httpClientChannel, 'request'), + array($httpVerb) + ); + + // Store request id + $this->_lastRequestId = $response->getHeader('x-ms-request-id'); + + return $response; + } + + /** + * Parse result from Zend_Http_Response + * + * @param Zend_Http_Response $response Response from HTTP call + * @return object + * @throws Zend_Service_WindowsAzure_Exception + */ + protected function _parseResponse(Zend_Http_Response $response = null) + { + if (is_null($response)) { + require_once 'Zend/Service/SqlAzure/Exception.php'; + throw new Zend_Service_SqlAzure_Exception('Response should not be null.'); + } + + $xml = @Zend_Xml_Security::scan($response->getBody()); + + if ($xml !== false) { + // Fetch all namespaces + $namespaces = array_merge($xml->getNamespaces(true), $xml->getDocNamespaces(true)); + + // Register all namespace prefixes + foreach ($namespaces as $prefix => $ns) { + if ($prefix != '') { + $xml->registerXPathNamespace($prefix, $ns); + } + } + } + + return $xml; + } + + /** + * URL encode function + * + * @param string $value Value to encode + * @return string Encoded value + */ + public static function urlencode($value) + { + return str_replace(' ', '%20', $value); + } + + /** + * Builds a query string from an array of elements + * + * @param array Array of elements + * @return string Assembled query string + */ + public static function createQueryStringFromArray($queryString) + { + return count($queryString) > 0 ? '?' . implode('&', $queryString) : ''; + } + + /** + * Get error message from Zend_Http_Response + * + * @param Zend_Http_Response $response Repsonse + * @param string $alternativeError Alternative error message + * @return string + */ + protected function _getErrorMessage(Zend_Http_Response $response, $alternativeError = 'Unknown error.') + { + $response = $this->_parseResponse($response); + if ($response && $response->Message) { + return (string)$response->Message; + } else { + return $alternativeError; + } + } + + /** + * The Create Server operation adds a new SQL Azure server to a subscription. + * + * @param string $administratorLogin Administrator login. + * @param string $administratorPassword Administrator password. + * @param string $location Location of the server. + * @return Zend_Service_SqlAzure_Management_ServerInstance Server information. + * @throws Zend_Service_SqlAzure_Management_Exception + */ + public function createServer($administratorLogin, $administratorPassword, $location) + { + if ($administratorLogin == '' || is_null($administratorLogin)) { + require_once 'Zend/Service/SqlAzure/Management/Exception.php'; + throw new Zend_Service_SqlAzure_Management_Exception('Administrator login should be specified.'); + } + if ($administratorPassword == '' || is_null($administratorPassword)) { + require_once 'Zend/Service/SqlAzure/Management/Exception.php'; + throw new Zend_Service_SqlAzure_Management_Exception('Administrator password should be specified.'); + } + if (is_null($location) && is_null($affinityGroup)) { + require_once 'Zend/Service/SqlAzure/Management/Exception.php'; + throw new Zend_Service_SqlAzure_Management_Exception('Please specify a location for the server.'); + } + + $response = $this->_performRequest(self::OP_SERVERS, '', + Zend_Http_Client::POST, + array('Content-Type' => 'application/xml; charset=utf-8'), + '' . $administratorLogin . '' . $administratorPassword . '' . $location . ''); + + if ($response->isSuccessful()) { + $xml = $this->_parseResponse($response); + + return new Zend_Service_SqlAzure_Management_ServerInstance( + (string)$xml, + $administratorLogin, + $location + ); + } else { + require_once 'Zend/Service/SqlAzure/Management/Exception.php'; + throw new Zend_Service_SqlAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); + } + } + + /** + * The Get Servers operation enumerates SQL Azure servers that are provisioned for a subscription. + * + * @return array An array of Zend_Service_SqlAzure_Management_ServerInstance. + * @throws Zend_Service_SqlAzure_Management_Exception + */ + public function listServers() + { + $response = $this->_performRequest(self::OP_SERVERS); + + if ($response->isSuccessful()) { + $xml = $this->_parseResponse($response); + $xmlServices = null; + + if (!$xml->Server) { + return array(); + } + if (count($xml->Server) > 1) { + $xmlServices = $xml->Server; + } else { + $xmlServices = array($xml->Server); + } + + $services = array(); + if (!is_null($xmlServices)) { + + for ($i = 0; $i < count($xmlServices); $i++) { + $services[] = new Zend_Service_SqlAzure_Management_ServerInstance( + (string)$xmlServices[$i]->Name, + (string)$xmlServices[$i]->AdministratorLogin, + (string)$xmlServices[$i]->Location + ); + } + } + return $services; + } else { + require_once 'Zend/Service/SqlAzure/Management/Exception.php'; + throw new Zend_Service_SqlAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); + } + } + + /** + * The Drop Server operation drops a SQL Azure server from a subscription. + * + * @param string $serverName Server to drop. + * @throws Zend_Service_SqlAzure_Management_Exception + */ + public function dropServer($serverName) + { + if ($serverName == '' || is_null($serverName)) { + require_once 'Zend/Service/SqlAzure/Management/Exception.php'; + throw new Zend_Service_SqlAzure_Management_Exception('Server name should be specified.'); + } + + $response = $this->_performRequest(self::OP_SERVERS . '/' . $serverName, '', Zend_Http_Client::DELETE); + + if (!$response->isSuccessful()) { + require_once 'Zend/Service/SqlAzure/Management/Exception.php'; + throw new Zend_Service_SqlAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); + } + } + + /** + * The Set Server Administrator Password operation sets the administrative password of a SQL Azure server for a subscription. + * + * @param string $serverName Server to set password for. + * @param string $administratorPassword Administrator password. + * @throws Zend_Service_SqlAzure_Management_Exception + */ + public function setAdministratorPassword($serverName, $administratorPassword) + { + if ($serverName == '' || is_null($serverName)) { + require_once 'Zend/Service/SqlAzure/Management/Exception.php'; + throw new Zend_Service_SqlAzure_Management_Exception('Server name should be specified.'); + } + if ($administratorPassword == '' || is_null($administratorPassword)) { + require_once 'Zend/Service/SqlAzure/Management/Exception.php'; + throw new Zend_Service_SqlAzure_Management_Exception('Administrator password should be specified.'); + } + + $response = $this->_performRequest(self::OP_SERVERS . '/' . $serverName, '?op=ResetPassword', + Zend_Http_Client::POST, + array('Content-Type' => 'application/xml; charset=utf-8'), + '' . $administratorPassword . ''); + + if (!$response->isSuccessful()) { + require_once 'Zend/Service/SqlAzure/Management/Exception.php'; + throw new Zend_Service_SqlAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); + } + } + + /** + * The Set Server Firewall Rule operation updates an existing firewall rule or adds a new firewall rule for a SQL Azure server that belongs to a subscription. + * + * @param string $serverName Server name. + * @param string $ruleName Firewall rule name. + * @param string $startIpAddress Start IP address. + * @param string $endIpAddress End IP address. + * @return Zend_Service_SqlAzure_Management_FirewallRuleInstance + * @throws Zend_Service_SqlAzure_Management_Exception + */ + public function createFirewallRule($serverName, $ruleName, $startIpAddress, $endIpAddress) + { + if ($serverName == '' || is_null($serverName)) { + require_once 'Zend/Service/SqlAzure/Management/Exception.php'; + throw new Zend_Service_SqlAzure_Management_Exception('Server name should be specified.'); + } + if ($ruleName == '' || is_null($ruleName)) { + require_once 'Zend/Service/SqlAzure/Management/Exception.php'; + throw new Zend_Service_SqlAzure_Management_Exception('Rule name should be specified.'); + } + if ($startIpAddress == '' || is_null($startIpAddress) || !filter_var($startIpAddress, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { + require_once 'Zend/Service/SqlAzure/Management/Exception.php'; + throw new Zend_Service_SqlAzure_Management_Exception('Start IP address should be specified.'); + } + if ($endIpAddress == '' || is_null($endIpAddress) || !filter_var($endIpAddress, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { + require_once 'Zend/Service/SqlAzure/Management/Exception.php'; + throw new Zend_Service_SqlAzure_Management_Exception('End IP address should be specified.'); + } + + $response = $this->_performRequest(self::OP_SERVERS . '/' . $serverName . '/' . self::OP_FIREWALLRULES . '/' . $ruleName, '', + Zend_Http_Client::PUT, + array('Content-Type' => 'application/xml; charset=utf-8'), + '' . $startIpAddress . '' . $endIpAddress . ''); + + if ($response->isSuccessful()) { + + return new Zend_Service_SqlAzure_Management_FirewallRuleInstance( + $ruleName, + $startIpAddress, + $endIpAddress + ); + } else { + require_once 'Zend/Service/SqlAzure/Management/Exception.php'; + throw new Zend_Service_SqlAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); + } + } + + /** + * The Get Server Firewall Rules operation retrieves a list of all the firewall rules for a SQL Azure server that belongs to a subscription. + * + * @param string $serverName Server name. + * @return Array of Zend_Service_SqlAzure_Management_FirewallRuleInstance. + * @throws Zend_Service_SqlAzure_Management_Exception + */ + public function listFirewallRules($serverName) + { + if ($serverName == '' || is_null($serverName)) { + require_once 'Zend/Service/SqlAzure/Management/Exception.php'; + throw new Zend_Service_SqlAzure_Management_Exception('Server name should be specified.'); + } + + $response = $this->_performRequest(self::OP_SERVERS . '/' . $serverName . '/' . self::OP_FIREWALLRULES); + + if ($response->isSuccessful()) { + $xml = $this->_parseResponse($response); + $xmlServices = null; + + if (!$xml->FirewallRule) { + return array(); + } + if (count($xml->FirewallRule) > 1) { + $xmlServices = $xml->FirewallRule; + } else { + $xmlServices = array($xml->FirewallRule); + } + + $services = array(); + if (!is_null($xmlServices)) { + + for ($i = 0; $i < count($xmlServices); $i++) { + $services[] = new Zend_Service_SqlAzure_Management_FirewallRuleInstance( + (string)$xmlServices[$i]->Name, + (string)$xmlServices[$i]->StartIpAddress, + (string)$xmlServices[$i]->EndIpAddress + ); + } + } + return $services; + } else { + require_once 'Zend/Service/SqlAzure/Management/Exception.php'; + throw new Zend_Service_SqlAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); + } + } + + /** + * The Delete Server Firewall Rule operation deletes a firewall rule from a SQL Azure server that belongs to a subscription. + * + * @param string $serverName Server name. + * @param string $ruleName Rule name. + * @throws Zend_Service_SqlAzure_Management_Exception + */ + public function deleteFirewallRule($serverName, $ruleName) + { + if ($serverName == '' || is_null($serverName)) { + require_once 'Zend/Service/SqlAzure/Management/Exception.php'; + throw new Zend_Service_SqlAzure_Management_Exception('Server name should be specified.'); + } + if ($ruleName == '' || is_null($ruleName)) { + require_once 'Zend/Service/SqlAzure/Management/Exception.php'; + throw new Zend_Service_SqlAzure_Management_Exception('Rule name should be specified.'); + } + + $response = $this->_performRequest(self::OP_SERVERS . '/' . $serverName . '/' . self::OP_FIREWALLRULES . '/' . $ruleName, '', + Zend_Http_Client::DELETE); + + if (!$response->isSuccessful()) { + require_once 'Zend/Service/SqlAzure/Management/Exception.php'; + throw new Zend_Service_SqlAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); + } + } + + /** + * Creates a firewall rule for Microsoft Services. This is required if access to SQL Azure is required from other services like Windows Azure. + * + * @param string $serverName Server name. + * @param boolean $allowAccess Allow access from other Microsoft Services? + * @throws Zend_Service_SqlAzure_Management_Exception + */ + public function createFirewallRuleForMicrosoftServices($serverName, $allowAccess) + { + if ($allowAccess) { + $this->createFirewallRule($serverName, 'MicrosoftServices', '0.0.0.0', '0.0.0.0'); + } else { + $this->deleteFirewallRule($serverName, 'MicrosoftServices'); + } + } + +} diff --git a/lib/zend/Zend/Service/SqlAzure/Management/Exception.php b/lib/zend/Zend/Service/SqlAzure/Management/Exception.php new file mode 100644 index 00000000000..88e2f8fefe1 --- /dev/null +++ b/lib/zend/Zend/Service/SqlAzure/Management/Exception.php @@ -0,0 +1,35 @@ +_data = array( + 'name' => $name, + 'startipaddress' => $startIpAddress, + 'endipaddress' => $endIpAddress + ); + } +} diff --git a/lib/zend/Zend/Service/SqlAzure/Management/ServerInstance.php b/lib/zend/Zend/Service/SqlAzure/Management/ServerInstance.php new file mode 100644 index 00000000000..d10611e5467 --- /dev/null +++ b/lib/zend/Zend/Service/SqlAzure/Management/ServerInstance.php @@ -0,0 +1,59 @@ +_data = array( + 'name' => $name, + 'dnsname' => $name . '.database.windows.net', + 'administratorlogin' => $administratorLogin, + 'location' => $location + ); + } +} diff --git a/lib/zend/Zend/Service/WindowsAzure/Storage/QueueInstance.php b/lib/zend/Zend/Service/SqlAzure/Management/ServiceEntityAbstract.php similarity index 57% rename from lib/zend/Zend/Service/WindowsAzure/Storage/QueueInstance.php rename to lib/zend/Zend/Service/SqlAzure/Management/ServiceEntityAbstract.php index c6f03f7ee9f..5cc53711a47 100644 --- a/lib/zend/Zend/Service/WindowsAzure/Storage/QueueInstance.php +++ b/lib/zend/Zend/Service/SqlAzure/Management/ServiceEntityAbstract.php @@ -14,30 +14,21 @@ * * @category Zend * @package Zend_Service_WindowsAzure - * @subpackage Storage - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @subpackage Management + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ -/** - * @see Zend_Service_WindowsAzure_Exception - */ -require_once 'Zend/Service/WindowsAzure/Exception.php'; - /** * @category Zend - * @package Zend_Service_WindowsAzure - * @subpackage Storage - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @package Zend_Service_SqlAzure + * @subpackage Management + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License - * - * @property string $Name Name of the queue - * @property array $Metadata Key/value pairs of meta data - * @property integer $ApproximateMessageCount The approximate number of messages in the queue */ -class Zend_Service_WindowsAzure_Storage_QueueInstance +abstract class Zend_Service_SqlAzure_Management_ServiceEntityAbstract { /** * Data @@ -46,21 +37,6 @@ class Zend_Service_WindowsAzure_Storage_QueueInstance */ protected $_data = null; - /** - * Constructor - * - * @param string $name Name - * @param array $metadata Key/value pairs of meta data - */ - public function __construct($name, $metadata = array()) - { - $this->_data = array( - 'name' => $name, - 'metadata' => $metadata, - 'approximatemessagecount' => 0 - ); - } - /** * Magic overload for setting properties * @@ -72,8 +48,8 @@ class Zend_Service_WindowsAzure_Storage_QueueInstance $this->_data[strtolower($name)] = $value; return; } - - throw new Exception("Unknown property: " . $name); + require_once 'Zend/Service/SqlAzure/Management/Exception.php'; + throw new Zend_Service_SqlAzure_Management_Exception("Unknown property: " . $name); } /** @@ -85,7 +61,7 @@ class Zend_Service_WindowsAzure_Storage_QueueInstance if (array_key_exists(strtolower($name), $this->_data)) { return $this->_data[strtolower($name)]; } - - throw new Exception("Unknown property: " . $name); + require_once 'Zend/Service/SqlAzure/Management/Exception.php'; + throw new Zend_Service_SqlAzure_Management_Exception("Unknown property: " . $name); } } diff --git a/lib/zend/Zend/Service/StrikeIron.php b/lib/zend/Zend/Service/StrikeIron.php index 2501a56ae4f..5ab03fcda3b 100644 --- a/lib/zend/Zend/Service/StrikeIron.php +++ b/lib/zend/Zend/Service/StrikeIron.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Service * @subpackage StrikeIron - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -29,7 +29,7 @@ * @category Zend * @package Zend_Service * @subpackage StrikeIron - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Service_StrikeIron diff --git a/lib/zend/Zend/Service/StrikeIron/Base.php b/lib/zend/Zend/Service/StrikeIron/Base.php index 9b55b519638..a2d35ef218b 100644 --- a/lib/zend/Zend/Service/StrikeIron/Base.php +++ b/lib/zend/Zend/Service/StrikeIron/Base.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Service * @subpackage StrikeIron - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -31,7 +31,7 @@ require_once 'Zend/Service/StrikeIron/Decorator.php'; * @category Zend * @package Zend_Service * @subpackage StrikeIron - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Service_StrikeIron_Base @@ -193,10 +193,10 @@ class Zend_Service_StrikeIron_Base * on what was originally called. * * @see __call() - * @param $result Raw result returned from SOAPClient_>__soapCall() - * @param $method Method name that was passed to SOAPClient->__soapCall() - * @param $params Method parameters that were passed to SOAPClient->__soapCall() - * @return mixed Transformed result + * @param object $result Raw result returned from SOAPClient_>__soapCall() + * @param string $method Method name that was passed to SOAPClient->__soapCall() + * @param array $params Method parameters that were passed to SOAPClient->__soapCall() + * @return mixed Transformed result */ protected function _transformResult($result, $method, $params) { diff --git a/lib/zend/Zend/Service/StrikeIron/Decorator.php b/lib/zend/Zend/Service/StrikeIron/Decorator.php index 280204147c6..023fd8c7f68 100644 --- a/lib/zend/Zend/Service/StrikeIron/Decorator.php +++ b/lib/zend/Zend/Service/StrikeIron/Decorator.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Service * @subpackage StrikeIron - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ * @category Zend * @package Zend_Service * @subpackage StrikeIron - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Service_StrikeIron_Decorator diff --git a/lib/zend/Zend/Service/StrikeIron/Exception.php b/lib/zend/Zend/Service/StrikeIron/Exception.php index f9172aed9c0..5506309743c 100644 --- a/lib/zend/Zend/Service/StrikeIron/Exception.php +++ b/lib/zend/Zend/Service/StrikeIron/Exception.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Service * @subpackage StrikeIron - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -29,7 +29,7 @@ require_once 'Zend/Service/Exception.php'; * @category Zend * @package Zend_Service * @subpackage StrikeIron - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Service_StrikeIron_Exception extends Zend_Service_Exception diff --git a/lib/zend/Zend/Service/StrikeIron/SalesUseTaxBasic.php b/lib/zend/Zend/Service/StrikeIron/SalesUseTaxBasic.php index b70d46f86dc..5dae1ce60d3 100644 --- a/lib/zend/Zend/Service/StrikeIron/SalesUseTaxBasic.php +++ b/lib/zend/Zend/Service/StrikeIron/SalesUseTaxBasic.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Service * @subpackage StrikeIron - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Service/StrikeIron/Base.php'; * @category Zend * @package Zend_Service * @subpackage StrikeIron - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Service_StrikeIron_SalesUseTaxBasic extends Zend_Service_StrikeIron_Base diff --git a/lib/zend/Zend/Service/StrikeIron/USAddressVerification.php b/lib/zend/Zend/Service/StrikeIron/USAddressVerification.php index 93ba95cbece..86cb22f5667 100644 --- a/lib/zend/Zend/Service/StrikeIron/USAddressVerification.php +++ b/lib/zend/Zend/Service/StrikeIron/USAddressVerification.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Service * @subpackage StrikeIron - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Service/StrikeIron/Base.php'; * @category Zend * @package Zend_Service * @subpackage StrikeIron - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Service_StrikeIron_USAddressVerification extends Zend_Service_StrikeIron_Base diff --git a/lib/zend/Zend/Service/StrikeIron/ZipCodeInfo.php b/lib/zend/Zend/Service/StrikeIron/ZipCodeInfo.php index 8e917924fb7..1a60ee298f9 100644 --- a/lib/zend/Zend/Service/StrikeIron/ZipCodeInfo.php +++ b/lib/zend/Zend/Service/StrikeIron/ZipCodeInfo.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Service * @subpackage StrikeIron - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Service/StrikeIron/Base.php'; * @category Zend * @package Zend_Service * @subpackage StrikeIron - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Service_StrikeIron_ZipCodeInfo extends Zend_Service_StrikeIron_Base diff --git a/lib/zend/Zend/Service/Technorati.php b/lib/zend/Zend/Service/Technorati.php deleted file mode 100644 index 3658f43e068..00000000000 --- a/lib/zend/Zend/Service/Technorati.php +++ /dev/null @@ -1,1028 +0,0 @@ -_apiKey = $apiKey; - } - - - /** - * Cosmos query lets you see what blogs are linking to a given URL. - * - * On the Technorati site, you can enter a URL in the searchbox and - * it will return a list of blogs linking to it. - * The API version allows more features and gives you a way - * to use the cosmos on your own site. - * - * Query options include: - * - * 'type' => (link|weblog) - * optional - A value of link returns the freshest links referencing your target URL. - * A value of weblog returns the last set of unique weblogs referencing your target URL. - * 'limit' => (int) - * optional - adjust the size of your result from the default value of 20 - * to between 1 and 100 results. - * 'start' => (int) - * optional - adjust the range of your result set. - * Set this number to larger than zero and you will receive - * the portion of Technorati's total result set ranging from start to start+limit. - * The default start value is 1. - * 'current' => (true|false) - * optional - the default setting of true - * Technorati returns links that are currently on a weblog's homepage. - * Set this parameter to false if you would like to receive all links - * to the given URL regardless of their current placement on the source blog. - * Internally the value is converted in (yes|no). - * 'claim' => (true|false) - * optional - the default setting of FALSE returns no user information - * about each weblog included in the result set when available. - * Set this parameter to FALSE to include Technorati member data - * in the result set when a weblog in your result set - * has been successfully claimed by a member of Technorati. - * Internally the value is converted in (int). - * 'highlight' => (true|false) - * optional - the default setting of TRUE - * highlights the citation of the given URL within the weblog excerpt. - * Set this parameter to FALSE to apply no special markup to the blog excerpt. - * Internally the value is converted in (int). - * - * @param string $url the URL you are searching for. Prefixes http:// and www. are optional. - * @param array $options additional parameters to refine your query - * @return Zend_Service_Technorati_CosmosResultSet - * @throws Zend_Service_Technorati_Exception - * @link http://technorati.com/developers/api/cosmos.html Technorati API: Cosmos Query reference - */ - public function cosmos($url, $options = null) - { - static $defaultOptions = array( 'type' => 'link', - 'start' => 1, - 'limit' => 20, - 'current' => 'yes', - 'format' => 'xml', - 'claim' => 0, - 'highlight' => 1, - ); - - $options['url'] = $url; - - $options = $this->_prepareOptions($options, $defaultOptions); - $this->_validateCosmos($options); - $response = $this->_makeRequest(self::API_PATH_COSMOS, $options); - $dom = $this->_convertResponseAndCheckContent($response); - - /** - * @see Zend_Service_Technorati_CosmosResultSet - */ - require_once 'Zend/Service/Technorati/CosmosResultSet.php'; - return new Zend_Service_Technorati_CosmosResultSet($dom, $options); - } - - /** - * Search lets you see what blogs contain a given search string. - * - * Query options include: - * - * 'language' => (string) - * optional - a ISO 639-1 two character language code - * to retrieve results specific to that language. - * This feature is currently beta and may not work for all languages. - * 'authority' => (n|a1|a4|a7) - * optional - filter results to those from blogs with at least - * the Technorati Authority specified. - * Technorati calculates a blog's authority by how many people link to it. - * Filtering by authority is a good way to refine your search results. - * There are four settings: - * - n => Any authority: All results. - * - a1 => A little authority: Results from blogs with at least one link. - * - a4 => Some authority: Results from blogs with a handful of links. - * - a7 => A lot of authority: Results from blogs with hundreds of links. - * 'limit' => (int) - * optional - adjust the size of your result from the default value of 20 - * to between 1 and 100 results. - * 'start' => (int) - * optional - adjust the range of your result set. - * Set this number to larger than zero and you will receive - * the portion of Technorati's total result set ranging from start to start+limit. - * The default start value is 1. - * 'claim' => (true|false) - * optional - the default setting of FALSE returns no user information - * about each weblog included in the result set when available. - * Set this parameter to FALSE to include Technorati member data - * in the result set when a weblog in your result set - * has been successfully claimed by a member of Technorati. - * Internally the value is converted in (int). - * - * @param string $query the words you are searching for. - * @param array $options additional parameters to refine your query - * @return Zend_Service_Technorati_SearchResultSet - * @throws Zend_Service_Technorati_Exception - * @link http://technorati.com/developers/api/search.html Technorati API: Search Query reference - */ - public function search($query, $options = null) - { - static $defaultOptions = array( 'start' => 1, - 'limit' => 20, - 'format' => 'xml', - 'claim' => 0); - - $options['query'] = $query; - - $options = $this->_prepareOptions($options, $defaultOptions); - $this->_validateSearch($options); - $response = $this->_makeRequest(self::API_PATH_SEARCH, $options); - $dom = $this->_convertResponseAndCheckContent($response); - - /** - * @see Zend_Service_Technorati_SearchResultSet - */ - require_once 'Zend/Service/Technorati/SearchResultSet.php'; - return new Zend_Service_Technorati_SearchResultSet($dom, $options); - } - - /** - * Tag lets you see what posts are associated with a given tag. - * - * Query options include: - * - * 'limit' => (int) - * optional - adjust the size of your result from the default value of 20 - * to between 1 and 100 results. - * 'start' => (int) - * optional - adjust the range of your result set. - * Set this number to larger than zero and you will receive - * the portion of Technorati's total result set ranging from start to start+limit. - * The default start value is 1. - * 'excerptsize' => (int) - * optional - number of word characters to include in the post excerpts. - * By default 100 word characters are returned. - * 'topexcerptsize' => (int) - * optional - number of word characters to include in the first post excerpt. - * By default 150 word characters are returned. - * - * @param string $tag the tag term you are searching posts for. - * @param array $options additional parameters to refine your query - * @return Zend_Service_Technorati_TagResultSet - * @throws Zend_Service_Technorati_Exception - * @link http://technorati.com/developers/api/tag.html Technorati API: Tag Query reference - */ - public function tag($tag, $options = null) - { - static $defaultOptions = array( 'start' => 1, - 'limit' => 20, - 'format' => 'xml', - 'excerptsize' => 100, - 'topexcerptsize' => 150); - - $options['tag'] = $tag; - - $options = $this->_prepareOptions($options, $defaultOptions); - $this->_validateTag($options); - $response = $this->_makeRequest(self::API_PATH_TAG, $options); - $dom = $this->_convertResponseAndCheckContent($response); - - /** - * @see Zend_Service_Technorati_TagResultSet - */ - require_once 'Zend/Service/Technorati/TagResultSet.php'; - return new Zend_Service_Technorati_TagResultSet($dom, $options); - } - - /** - * TopTags provides daily counts of posts containing the queried keyword. - * - * Query options include: - * - * 'days' => (int) - * optional - Used to specify the number of days in the past - * to request daily count data for. - * Can be any integer between 1 and 180, default is 180 - * - * @param string $q the keyword query - * @param array $options additional parameters to refine your query - * @return Zend_Service_Technorati_DailyCountsResultSet - * @throws Zend_Service_Technorati_Exception - * @link http://technorati.com/developers/api/dailycounts.html Technorati API: DailyCounts Query reference - */ - public function dailyCounts($query, $options = null) - { - static $defaultOptions = array( 'days' => 180, - 'format' => 'xml' - ); - - $options['q'] = $query; - - $options = $this->_prepareOptions($options, $defaultOptions); - $this->_validateDailyCounts($options); - $response = $this->_makeRequest(self::API_PATH_DAILYCOUNTS, $options); - $dom = $this->_convertResponseAndCheckContent($response); - - /** - * @see Zend_Service_Technorati_DailyCountsResultSet - */ - require_once 'Zend/Service/Technorati/DailyCountsResultSet.php'; - return new Zend_Service_Technorati_DailyCountsResultSet($dom); - } - - /** - * TopTags provides information on top tags indexed by Technorati. - * - * Query options include: - * - * 'limit' => (int) - * optional - adjust the size of your result from the default value of 20 - * to between 1 and 100 results. - * 'start' => (int) - * optional - adjust the range of your result set. - * Set this number to larger than zero and you will receive - * the portion of Technorati's total result set ranging from start to start+limit. - * The default start value is 1. - * - * @param array $options additional parameters to refine your query - * @return Zend_Service_Technorati_TagsResultSet - * @throws Zend_Service_Technorati_Exception - * @link http://technorati.com/developers/api/toptags.html Technorati API: TopTags Query reference - */ - public function topTags($options = null) - { - static $defaultOptions = array( 'start' => 1, - 'limit' => 20, - 'format' => 'xml' - ); - - $options = $this->_prepareOptions($options, $defaultOptions); - $this->_validateTopTags($options); - $response = $this->_makeRequest(self::API_PATH_TOPTAGS, $options); - $dom = $this->_convertResponseAndCheckContent($response); - - /** - * @see Zend_Service_Technorati_TagsResultSet - */ - require_once 'Zend/Service/Technorati/TagsResultSet.php'; - return new Zend_Service_Technorati_TagsResultSet($dom); - } - - /** - * BlogInfo provides information on what blog, if any, is associated with a given URL. - * - * @param string $url the URL you are searching for. Prefixes http:// and www. are optional. - * The URL must be recognized by Technorati as a blog. - * @param array $options additional parameters to refine your query - * @return Zend_Service_Technorati_BlogInfoResult - * @throws Zend_Service_Technorati_Exception - * @link http://technorati.com/developers/api/bloginfo.html Technorati API: BlogInfo Query reference - */ - public function blogInfo($url, $options = null) - { - static $defaultOptions = array( 'format' => 'xml' - ); - - $options['url'] = $url; - - $options = $this->_prepareOptions($options, $defaultOptions); - $this->_validateBlogInfo($options); - $response = $this->_makeRequest(self::API_PATH_BLOGINFO, $options); - $dom = $this->_convertResponseAndCheckContent($response); - - /** - * @see Zend_Service_Technorati_BlogInfoResult - */ - require_once 'Zend/Service/Technorati/BlogInfoResult.php'; - return new Zend_Service_Technorati_BlogInfoResult($dom); - } - - /** - * BlogPostTags provides information on the top tags used by a specific blog. - * - * Query options include: - * - * 'limit' => (int) - * optional - adjust the size of your result from the default value of 20 - * to between 1 and 100 results. - * 'start' => (int) - * optional - adjust the range of your result set. - * Set this number to larger than zero and you will receive - * the portion of Technorati's total result set ranging from start to start+limit. - * The default start value is 1. - * Note. This property is not documented. - * - * @param string $url the URL you are searching for. Prefixes http:// and www. are optional. - * The URL must be recognized by Technorati as a blog. - * @param array $options additional parameters to refine your query - * @return Zend_Service_Technorati_TagsResultSet - * @throws Zend_Service_Technorati_Exception - * @link http://technorati.com/developers/api/blogposttags.html Technorati API: BlogPostTags Query reference - */ - public function blogPostTags($url, $options = null) - { - static $defaultOptions = array( 'start' => 1, - 'limit' => 20, - 'format' => 'xml' - ); - - $options['url'] = $url; - - $options = $this->_prepareOptions($options, $defaultOptions); - $this->_validateBlogPostTags($options); - $response = $this->_makeRequest(self::API_PATH_BLOGPOSTTAGS, $options); - $dom = $this->_convertResponseAndCheckContent($response); - - /** - * @see Zend_Service_Technorati_TagsResultSet - */ - require_once 'Zend/Service/Technorati/TagsResultSet.php'; - return new Zend_Service_Technorati_TagsResultSet($dom); - } - - /** - * GetInfo query tells you things that Technorati knows about a member. - * - * The returned info is broken up into two sections: - * The first part describes some information that the user wants - * to allow people to know about him- or herself. - * The second part of the document is a listing of the weblogs - * that the user has successfully claimed and the information - * that Technorati knows about these weblogs. - * - * @param string $username the Technorati user name you are searching for - * @param array $options additional parameters to refine your query - * @return Zend_Service_Technorati_GetInfoResult - * @throws Zend_Service_Technorati_Exception - * @link http://technorati.com/developers/api/getinfo.html Technorati API: GetInfo reference - */ - public function getInfo($username, $options = null) - { - static $defaultOptions = array('format' => 'xml'); - - $options['username'] = $username; - - $options = $this->_prepareOptions($options, $defaultOptions); - $this->_validateGetInfo($options); - $response = $this->_makeRequest(self::API_PATH_GETINFO, $options); - $dom = $this->_convertResponseAndCheckContent($response); - - /** - * @see Zend_Service_Technorati_GetInfoResult - */ - require_once 'Zend/Service/Technorati/GetInfoResult.php'; - return new Zend_Service_Technorati_GetInfoResult($dom); - } - - /** - * KeyInfo query provides information on daily usage of an API key. - * Key Info Queries do not count against a key's daily query limit. - * - * A day is defined as 00:00-23:59 Pacific time. - * - * @return Zend_Service_Technorati_KeyInfoResult - * @throws Zend_Service_Technorati_Exception - * @link http://developers.technorati.com/wiki/KeyInfo Technorati API: Key Info reference - */ - public function keyInfo() - { - static $defaultOptions = array(); - - $options = $this->_prepareOptions(array(), $defaultOptions); - // you don't need to validate this request - // because key is the only mandatory element - // and it's already set in #_prepareOptions - $response = $this->_makeRequest(self::API_PATH_KEYINFO, $options); - $dom = $this->_convertResponseAndCheckContent($response); - - /** - * @see Zend_Service_Technorati_KeyInfoResult - */ - require_once 'Zend/Service/Technorati/KeyInfoResult.php'; - return new Zend_Service_Technorati_KeyInfoResult($dom, $this->_apiKey); - } - - - /** - * Returns Technorati API key. - * - * @return string Technorati API key - */ - public function getApiKey() - { - return $this->_apiKey; - } - - /** - * Returns a reference to the REST client object in use. - * - * If the reference hasn't being inizialized yet, - * then a new Zend_Rest_Client instance is created. - * - * @return Zend_Rest_Client - */ - public function getRestClient() - { - if ($this->_restClient === null) { - /** - * @see Zend_Rest_Client - */ - require_once 'Zend/Rest/Client.php'; - $this->_restClient = new Zend_Rest_Client(self::API_URI_BASE); - } - - return $this->_restClient; - } - - /** - * Sets Technorati API key. - * - * Be aware that this function doesn't validate the key. - * The key is validated as soon as the first API request is sent. - * If the key is invalid, the API request method will throw - * a Zend_Service_Technorati_Exception exception with Invalid Key message. - * - * @param string $key Technorati API Key - * @return void - * @link http://technorati.com/developers/apikey.html How to get your Technorati API Key - */ - public function setApiKey($key) - { - $this->_apiKey = $key; - return $this; - } - - - /** - * Validates Cosmos query options. - * - * @param array $options - * @return void - * @throws Zend_Service_Technorati_Exception - * @access protected - */ - protected function _validateCosmos(array $options) - { - static $validOptions = array('key', 'url', - 'type', 'limit', 'start', 'current', 'claim', 'highlight', 'format'); - - // Validate keys in the $options array - $this->_compareOptions($options, $validOptions); - // Validate url (required) - $this->_validateOptionUrl($options); - // Validate limit (optional) - $this->_validateOptionLimit($options); - // Validate start (optional) - $this->_validateOptionStart($options); - // Validate format (optional) - $this->_validateOptionFormat($options); - // Validate type (optional) - $this->_validateInArrayOption('type', $options, array('link', 'weblog')); - // Validate claim (optional) - $this->_validateOptionClaim($options); - // Validate highlight (optional) - $this->_validateIntegerOption('highlight', $options); - // Validate current (optional) - if (isset($options['current'])) { - $tmp = (int) $options['current']; - $options['current'] = $tmp ? 'yes' : 'no'; - } - - } - - /** - * Validates Search query options. - * - * @param array $options - * @return void - * @throws Zend_Service_Technorati_Exception - * @access protected - */ - protected function _validateSearch(array $options) - { - static $validOptions = array('key', 'query', - 'language', 'authority', 'limit', 'start', 'claim', 'format'); - - // Validate keys in the $options array - $this->_compareOptions($options, $validOptions); - // Validate query (required) - $this->_validateMandatoryOption('query', $options); - // Validate authority (optional) - $this->_validateInArrayOption('authority', $options, array('n', 'a1', 'a4', 'a7')); - // Validate limit (optional) - $this->_validateOptionLimit($options); - // Validate start (optional) - $this->_validateOptionStart($options); - // Validate claim (optional) - $this->_validateOptionClaim($options); - // Validate format (optional) - $this->_validateOptionFormat($options); - } - - /** - * Validates Tag query options. - * - * @param array $options - * @return void - * @throws Zend_Service_Technorati_Exception - * @access protected - */ - protected function _validateTag(array $options) - { - static $validOptions = array('key', 'tag', - 'limit', 'start', 'excerptsize', 'topexcerptsize', 'format'); - - // Validate keys in the $options array - $this->_compareOptions($options, $validOptions); - // Validate query (required) - $this->_validateMandatoryOption('tag', $options); - // Validate limit (optional) - $this->_validateOptionLimit($options); - // Validate start (optional) - $this->_validateOptionStart($options); - // Validate excerptsize (optional) - $this->_validateIntegerOption('excerptsize', $options); - // Validate excerptsize (optional) - $this->_validateIntegerOption('topexcerptsize', $options); - // Validate format (optional) - $this->_validateOptionFormat($options); - } - - - /** - * Validates DailyCounts query options. - * - * @param array $options - * @return void - * @throws Zend_Service_Technorati_Exception - * @access protected - */ - protected function _validateDailyCounts(array $options) - { - static $validOptions = array('key', 'q', - 'days', 'format'); - - // Validate keys in the $options array - $this->_compareOptions($options, $validOptions); - // Validate q (required) - $this->_validateMandatoryOption('q', $options); - // Validate format (optional) - $this->_validateOptionFormat($options); - // Validate days (optional) - if (isset($options['days'])) { - $options['days'] = (int) $options['days']; - if ($options['days'] < self::PARAM_DAYS_MIN_VALUE || - $options['days'] > self::PARAM_DAYS_MAX_VALUE) { - /** - * @see Zend_Service_Technorati_Exception - */ - require_once 'Zend/Service/Technorati/Exception.php'; - throw new Zend_Service_Technorati_Exception( - "Invalid value '" . $options['days'] . "' for 'days' option"); - } - } - } - - /** - * Validates GetInfo query options. - * - * @param array $options - * @return void - * @throws Zend_Service_Technorati_Exception - * @access protected - */ - protected function _validateGetInfo(array $options) - { - static $validOptions = array('key', 'username', - 'format'); - - // Validate keys in the $options array - $this->_compareOptions($options, $validOptions); - // Validate username (required) - $this->_validateMandatoryOption('username', $options); - // Validate format (optional) - $this->_validateOptionFormat($options); - } - - /** - * Validates TopTags query options. - * - * @param array $options - * @return void - * @throws Zend_Service_Technorati_Exception - * @access protected - */ - protected function _validateTopTags(array $options) - { - static $validOptions = array('key', - 'limit', 'start', 'format'); - - // Validate keys in the $options array - $this->_compareOptions($options, $validOptions); - // Validate limit (optional) - $this->_validateOptionLimit($options); - // Validate start (optional) - $this->_validateOptionStart($options); - // Validate format (optional) - $this->_validateOptionFormat($options); - } - - /** - * Validates BlogInfo query options. - * - * @param array $options - * @return void - * @throws Zend_Service_Technorati_Exception - * @access protected - */ - protected function _validateBlogInfo(array $options) - { - static $validOptions = array('key', 'url', - 'format'); - - // Validate keys in the $options array - $this->_compareOptions($options, $validOptions); - // Validate url (required) - $this->_validateOptionUrl($options); - // Validate format (optional) - $this->_validateOptionFormat($options); - } - - /** - * Validates TopTags query options. - * - * @param array $options - * @return void - * @throws Zend_Service_Technorati_Exception - * @access protected - */ - protected function _validateBlogPostTags(array $options) - { - static $validOptions = array('key', 'url', - 'limit', 'start', 'format'); - - // Validate keys in the $options array - $this->_compareOptions($options, $validOptions); - // Validate url (required) - $this->_validateOptionUrl($options); - // Validate limit (optional) - $this->_validateOptionLimit($options); - // Validate start (optional) - $this->_validateOptionStart($options); - // Validate format (optional) - $this->_validateOptionFormat($options); - } - - /** - * Checks whether an option is in a given array. - * - * @param string $name option name - * @param array $options - * @param array $array array of valid options - * @return void - * @throws Zend_Service_Technorati_Exception - * @access protected - */ - protected function _validateInArrayOption($name, $options, array $array) - { - if (isset($options[$name]) && !in_array($options[$name], $array)) { - /** - * @see Zend_Service_Technorati_Exception - */ - require_once 'Zend/Service/Technorati/Exception.php'; - throw new Zend_Service_Technorati_Exception( - "Invalid value '{$options[$name]}' for '$name' option"); - } - } - - /** - * Checks whether mandatory $name option exists and it's valid. - * - * @param array $options - * @return void - * @throws Zend_Service_Technorati_Exception - * @access protected - */ - protected function _validateMandatoryOption($name, $options) - { - if (!isset($options[$name]) || !trim($options[$name])) { - /** - * @see Zend_Service_Technorati_Exception - */ - require_once 'Zend/Service/Technorati/Exception.php'; - throw new Zend_Service_Technorati_Exception( - "Empty value for '$name' option"); - } - } - - /** - * Checks whether $name option is a valid integer and casts it. - * - * @param array $options - * @return void - * @access protected - */ - protected function _validateIntegerOption($name, $options) - { - if (isset($options[$name])) { - $options[$name] = (int) $options[$name]; - } - } - - /** - * Makes and HTTP GET request to given $path with $options. - * HTTP Response is first validated, then returned. - * - * @param string $path - * @param array $options - * @return Zend_Http_Response - * @throws Zend_Service_Technorati_Exception on failure - * @access protected - */ - protected function _makeRequest($path, $options = array()) - { - $restClient = $this->getRestClient(); - $restClient->getHttpClient()->resetParameters(); - $response = $restClient->restGet($path, $options); - self::_checkResponse($response); - return $response; - } - - /** - * Checks whether 'claim' option value is valid. - * - * @param array $options - * @return void - * @access protected - */ - protected function _validateOptionClaim(array $options) - { - $this->_validateIntegerOption('claim', $options); - } - - /** - * Checks whether 'format' option value is valid. - * Be aware that Zend_Service_Technorati supports only XML as format value. - * - * @param array $options - * @return void - * @throws Zend_Service_Technorati_Exception if 'format' value != XML - * @access protected - */ - protected function _validateOptionFormat(array $options) - { - if (isset($options['format']) && $options['format'] != 'xml') { - /** - * @see Zend_Service_Technorati_Exception - */ - require_once 'Zend/Service/Technorati/Exception.php'; - throw new Zend_Service_Technorati_Exception( - "Invalid value '" . $options['format'] . "' for 'format' option. " . - "Zend_Service_Technorati supports only 'xml'"); - } - } - - /** - * Checks whether 'limit' option value is valid. - * Value must be an integer greater than PARAM_LIMIT_MIN_VALUE - * and lower than PARAM_LIMIT_MAX_VALUE. - * - * @param array $options - * @return void - * @throws Zend_Service_Technorati_Exception if 'limit' value is invalid - * @access protected - */ - protected function _validateOptionLimit(array $options) - { - if (!isset($options['limit'])) return; - - $options['limit'] = (int) $options['limit']; - if ($options['limit'] < self::PARAM_LIMIT_MIN_VALUE || - $options['limit'] > self::PARAM_LIMIT_MAX_VALUE) { - /** - * @see Zend_Service_Technorati_Exception - */ - require_once 'Zend/Service/Technorati/Exception.php'; - throw new Zend_Service_Technorati_Exception( - "Invalid value '" . $options['limit'] . "' for 'limit' option"); - } - } - - /** - * Checks whether 'start' option value is valid. - * Value must be an integer greater than 0. - * - * @param array $options - * @return void - * @throws Zend_Service_Technorati_Exception if 'start' value is invalid - * @access protected - */ - protected function _validateOptionStart(array $options) - { - if (!isset($options['start'])) return; - - $options['start'] = (int) $options['start']; - if ($options['start'] < self::PARAM_START_MIN_VALUE) { - /** - * @see Zend_Service_Technorati_Exception - */ - require_once 'Zend/Service/Technorati/Exception.php'; - throw new Zend_Service_Technorati_Exception( - "Invalid value '" . $options['start'] . "' for 'start' option"); - } - } - - /** - * Checks whether 'url' option value exists and is valid. - * 'url' must be a valid HTTP(s) URL. - * - * @param array $options - * @return void - * @throws Zend_Service_Technorati_Exception if 'url' value is invalid - * @access protected - * @todo support for Zend_Uri_Http - */ - protected function _validateOptionUrl(array $options) - { - $this->_validateMandatoryOption('url', $options); - } - - /** - * Checks XML response content for errors. - * - * @param DomDocument $dom the XML response as a DOM document - * @return void - * @throws Zend_Service_Technorati_Exception - * @link http://technorati.com/developers/api/error.html Technorati API: Error response - * @access protected - */ - protected static function _checkErrors(DomDocument $dom) - { - $xpath = new DOMXPath($dom); - - $result = $xpath->query("/tapi/document/result/error"); - if ($result->length >= 1) { - $error = $result->item(0)->nodeValue; - /** - * @see Zend_Service_Technorati_Exception - */ - require_once 'Zend/Service/Technorati/Exception.php'; - throw new Zend_Service_Technorati_Exception($error); - } - } - - /** - * Converts $response body to a DOM object and checks it. - * - * @param Zend_Http_Response $response - * @return DOMDocument - * @throws Zend_Service_Technorati_Exception if response content contains an error message - * @access protected - */ - protected function _convertResponseAndCheckContent(Zend_Http_Response $response) - { - $dom = new DOMDocument(); - $dom->loadXML($response->getBody()); - self::_checkErrors($dom); - return $dom; - } - - /** - * Checks ReST response for errors. - * - * @param Zend_Http_Response $response the ReST response - * @return void - * @throws Zend_Service_Technorati_Exception - * @access protected - */ - protected static function _checkResponse(Zend_Http_Response $response) - { - if ($response->isError()) { - /** - * @see Zend_Service_Technorati_Exception - */ - require_once 'Zend/Service/Technorati/Exception.php'; - throw new Zend_Service_Technorati_Exception(sprintf( - 'Invalid response status code (HTTP/%s %s %s)', - $response->getVersion(), $response->getStatus(), $response->getMessage())); - } - } - - /** - * Checks whether user given options are valid. - * - * @param array $options user options - * @param array $validOptions valid options - * @return void - * @throws Zend_Service_Technorati_Exception - * @access protected - */ - protected function _compareOptions(array $options, array $validOptions) - { - $difference = array_diff(array_keys($options), $validOptions); - if ($difference) { - /** - * @see Zend_Service_Technorati_Exception - */ - require_once 'Zend/Service/Technorati/Exception.php'; - throw new Zend_Service_Technorati_Exception( - "The following parameters are invalid: '" . - implode("', '", $difference) . "'"); - } - } - - /** - * Prepares options for the request - * - * @param array $options user options - * @param array $defaultOptions default options - * @return array Merged array of user and default/required options. - * @access protected - */ - protected function _prepareOptions($options, array $defaultOptions) - { - $options = (array) $options; // force cast to convert null to array() - $options['key'] = $this->_apiKey; - $options = array_merge($defaultOptions, $options); - return $options; - } -} diff --git a/lib/zend/Zend/Service/Technorati/Author.php b/lib/zend/Zend/Service/Technorati/Author.php deleted file mode 100644 index 7cffc24244c..00000000000 --- a/lib/zend/Zend/Service/Technorati/Author.php +++ /dev/null @@ -1,242 +0,0 @@ -ownerDocument); - - $result = $xpath->query('./firstname/text()', $dom); - if ($result->length == 1) $this->setFirstName($result->item(0)->data); - - $result = $xpath->query('./lastname/text()', $dom); - if ($result->length == 1) $this->setLastName($result->item(0)->data); - - $result = $xpath->query('./username/text()', $dom); - if ($result->length == 1) $this->setUsername($result->item(0)->data); - - $result = $xpath->query('./description/text()', $dom); - if ($result->length == 1) $this->setDescription($result->item(0)->data); - - $result = $xpath->query('./bio/text()', $dom); - if ($result->length == 1) $this->setBio($result->item(0)->data); - - $result = $xpath->query('./thumbnailpicture/text()', $dom); - if ($result->length == 1) $this->setThumbnailPicture($result->item(0)->data); - } - - - /** - * Returns Author first name. - * - * @return string Author first name - */ - public function getFirstName() { - return $this->_firstName; - } - - /** - * Returns Author last name. - * - * @return string Author last name - */ - public function getLastName() { - return $this->_lastName; - } - - /** - * Returns Technorati account username. - * - * @return string Technorati account username - */ - public function getUsername() { - return $this->_username; - } - - /** - * Returns Technorati account description. - * - * @return string Technorati account description - */ - public function getDescription() { - return $this->_description; - } - - /** - * Returns Technorati account biography. - * - * @return string Technorati account biography - */ - public function getBio() { - return $this->_bio; - } - - /** - * Returns Technorati account thumbnail picture. - * - * @return null|Zend_Uri_Http Technorati account thumbnail picture - */ - public function getThumbnailPicture() { - return $this->_thumbnailPicture; - } - - - /** - * Sets author first name. - * - * @param string $input first Name input value - * @return Zend_Service_Technorati_Author $this instance - */ - public function setFirstName($input) { - $this->_firstName = (string) $input; - return $this; - } - - /** - * Sets author last name. - * - * @param string $input last Name input value - * @return Zend_Service_Technorati_Author $this instance - */ - public function setLastName($input) { - $this->_lastName = (string) $input; - return $this; - } - - /** - * Sets Technorati account username. - * - * @param string $input username input value - * @return Zend_Service_Technorati_Author $this instance - */ - public function setUsername($input) { - $this->_username = (string) $input; - return $this; - } - - /** - * Sets Technorati account biography. - * - * @param string $input biography input value - * @return Zend_Service_Technorati_Author $this instance - */ - public function setBio($input) { - $this->_bio = (string) $input; - return $this; - } - - /** - * Sets Technorati account description. - * - * @param string $input description input value - * @return Zend_Service_Technorati_Author $this instance - */ - public function setDescription($input) { - $this->_description = (string) $input; - return $this; - } - - /** - * Sets Technorati account thumbnail picture. - * - * @param string|Zend_Uri_Http $input thumbnail picture URI - * @return Zend_Service_Technorati_Author $this instance - * @throws Zend_Service_Technorati_Exception if $input is an invalid URI - * (via Zend_Service_Technorati_Utils::normalizeUriHttp) - */ - public function setThumbnailPicture($input) { - $this->_thumbnailPicture = Zend_Service_Technorati_Utils::normalizeUriHttp($input); - return $this; - } - -} diff --git a/lib/zend/Zend/Service/Technorati/BlogInfoResult.php b/lib/zend/Zend/Service/Technorati/BlogInfoResult.php deleted file mode 100644 index a288693d6d3..00000000000 --- a/lib/zend/Zend/Service/Technorati/BlogInfoResult.php +++ /dev/null @@ -1,161 +0,0 @@ -query('//result/weblog'); - if ($result->length == 1) { - $this->_weblog = new Zend_Service_Technorati_Weblog($result->item(0)); - } else { - // follow the same behavior of blogPostTags - // and raise an Exception if the URL is not a valid weblog - /** - * @see Zend_Service_Technorati_Exception - */ - require_once 'Zend/Service/Technorati/Exception.php'; - throw new Zend_Service_Technorati_Exception( - "Your URL is not a recognized Technorati weblog"); - } - - $result = $xpath->query('//result/url/text()'); - if ($result->length == 1) { - try { - // fetched URL often doens't include schema - // and this issue causes the following line to fail - $this->_url = Zend_Service_Technorati_Utils::normalizeUriHttp($result->item(0)->data); - } catch(Zend_Service_Technorati_Exception $e) { - if ($this->getWeblog() instanceof Zend_Service_Technorati_Weblog) { - $this->_url = $this->getWeblog()->getUrl(); - } - } - } - - $result = $xpath->query('//result/inboundblogs/text()'); - if ($result->length == 1) $this->_inboundBlogs = (int) $result->item(0)->data; - - $result = $xpath->query('//result/inboundlinks/text()'); - if ($result->length == 1) $this->_inboundLinks = (int) $result->item(0)->data; - - } - - - /** - * Returns the weblog URL. - * - * @return Zend_Uri_Http - */ - public function getUrl() { - return $this->_url; - } - - /** - * Returns the weblog. - * - * @return Zend_Service_Technorati_Weblog - */ - public function getWeblog() { - return $this->_weblog; - } - - /** - * Returns number of unique blogs linking this blog. - * - * @return integer the number of inbound blogs - */ - public function getInboundBlogs() - { - return (int) $this->_inboundBlogs; - } - - /** - * Returns number of incoming links to this blog. - * - * @return integer the number of inbound links - */ - public function getInboundLinks() - { - return (int) $this->_inboundLinks; - } - -} diff --git a/lib/zend/Zend/Service/Technorati/CosmosResult.php b/lib/zend/Zend/Service/Technorati/CosmosResult.php deleted file mode 100644 index 8a930a5dbda..00000000000 --- a/lib/zend/Zend/Service/Technorati/CosmosResult.php +++ /dev/null @@ -1,152 +0,0 @@ -_fields = array( '_nearestPermalink' => 'nearestpermalink', - '_excerpt' => 'excerpt', - '_linkCreated' => 'linkcreated', - '_linkUrl' => 'linkurl'); - parent::__construct($dom); - - // weblog object field - $this->_parseWeblog(); - - // filter fields - $this->_nearestPermalink = Zend_Service_Technorati_Utils::normalizeUriHttp($this->_nearestPermalink); - $this->_linkUrl = Zend_Service_Technorati_Utils::normalizeUriHttp($this->_linkUrl); - $this->_linkCreated = Zend_Service_Technorati_Utils::normalizeDate($this->_linkCreated); - } - - /** - * Returns the weblog object that links queried URL. - * - * @return Zend_Service_Technorati_Weblog - */ - public function getWeblog() { - return $this->_weblog; - } - - /** - * Returns the nearest permalink tracked for queried URL. - * - * @return Zend_Uri_Http - */ - public function getNearestPermalink() { - return $this->_nearestPermalink; - } - - /** - * Returns the excerpt of the blog/page linking queried URL. - * - * @return string - */ - public function getExcerpt() { - return $this->_excerpt; - } - - /** - * Returns the datetime the link was created. - * - * @return Zend_Date - */ - public function getLinkCreated() { - return $this->_linkCreated; - } - - /** - * If queried URL is a valid blog, - * returns the URL of the specific link target page. - * - * @return Zend_Uri_Http - */ - public function getLinkUrl() { - return $this->_linkUrl; - } - -} diff --git a/lib/zend/Zend/Service/Technorati/CosmosResultSet.php b/lib/zend/Zend/Service/Technorati/CosmosResultSet.php deleted file mode 100644 index 03d7363762e..00000000000 --- a/lib/zend/Zend/Service/Technorati/CosmosResultSet.php +++ /dev/null @@ -1,176 +0,0 @@ -_xpath->query('/tapi/document/result/inboundlinks/text()'); - if ($result->length == 1) $this->_inboundLinks = (int) $result->item(0)->data; - - $result = $this->_xpath->query('/tapi/document/result/inboundblogs/text()'); - if ($result->length == 1) $this->_inboundBlogs = (int) $result->item(0)->data; - - $result = $this->_xpath->query('/tapi/document/result/weblog'); - if ($result->length == 1) { - /** - * @see Zend_Service_Technorati_Weblog - */ - require_once 'Zend/Service/Technorati/Weblog.php'; - $this->_weblog = new Zend_Service_Technorati_Weblog($result->item(0)); - } - - $result = $this->_xpath->query('/tapi/document/result/url/text()'); - if ($result->length == 1) { - try { - // fetched URL often doens't include schema - // and this issue causes the following line to fail - $this->_url = Zend_Service_Technorati_Utils::normalizeUriHttp($result->item(0)->data); - } catch(Zend_Service_Technorati_Exception $e) { - if ($this->getWeblog() instanceof Zend_Service_Technorati_Weblog) { - $this->_url = $this->getWeblog()->getUrl(); - } - } - } - - $this->_totalResultsReturned = (int) $this->_xpath->evaluate("count(/tapi/document/item)"); - - // total number of results depends on query type - // for now check only getInboundLinks() and getInboundBlogs() value - if ((int) $this->getInboundLinks() > 0) { - $this->_totalResultsAvailable = $this->getInboundLinks(); - } elseif ((int) $this->getInboundBlogs() > 0) { - $this->_totalResultsAvailable = $this->getInboundBlogs(); - } else { - $this->_totalResultsAvailable = 0; - } - } - - - /** - * Returns the weblog URL. - * - * @return Zend_Uri_Http - */ - public function getUrl() { - return $this->_url; - } - - /** - * Returns the weblog. - * - * @return Zend_Service_Technorati_Weblog - */ - public function getWeblog() { - return $this->_weblog; - } - - /** - * Returns number of unique blogs linking this blog. - * - * @return integer the number of inbound blogs - */ - public function getInboundBlogs() - { - return $this->_inboundBlogs; - } - - /** - * Returns number of incoming links to this blog. - * - * @return integer the number of inbound links - */ - public function getInboundLinks() - { - return $this->_inboundLinks; - } - - /** - * Implements Zend_Service_Technorati_ResultSet::current(). - * - * @return Zend_Service_Technorati_CosmosResult current result - */ - public function current() - { - /** - * @see Zend_Service_Technorati_CosmosResult - */ - require_once 'Zend/Service/Technorati/CosmosResult.php'; - return new Zend_Service_Technorati_CosmosResult($this->_results->item($this->_currentIndex)); - } -} diff --git a/lib/zend/Zend/Service/Technorati/DailyCountsResult.php b/lib/zend/Zend/Service/Technorati/DailyCountsResult.php deleted file mode 100644 index c1e6a804deb..00000000000 --- a/lib/zend/Zend/Service/Technorati/DailyCountsResult.php +++ /dev/null @@ -1,93 +0,0 @@ -_fields = array( '_date' => 'date', - '_count' => 'count'); - parent::__construct($dom); - - // filter fields - $this->_date = new Zend_Date(strtotime($this->_date)); - $this->_count = (int) $this->_count; - } - - /** - * Returns the date of count. - * - * @return Zend_Date - */ - public function getDate() { - return $this->_date; - } - - /** - * Returns the number of posts containing query on given date. - * - * @return int - */ - public function getCount() { - return $this->_count; - } -} diff --git a/lib/zend/Zend/Service/Technorati/DailyCountsResultSet.php b/lib/zend/Zend/Service/Technorati/DailyCountsResultSet.php deleted file mode 100644 index e28c63361ca..00000000000 --- a/lib/zend/Zend/Service/Technorati/DailyCountsResultSet.php +++ /dev/null @@ -1,125 +0,0 @@ -_xpath->query('/tapi/document/result/days/text()'); - if ($result->length == 1) $this->_days = (int) $result->item(0)->data; - - $result = $this->_xpath->query('/tapi/document/result/searchurl/text()'); - if ($result->length == 1) { - $this->_searchUrl = Zend_Service_Technorati_Utils::normalizeUriHttp($result->item(0)->data); - } - - $this->_totalResultsReturned = (int) $this->_xpath->evaluate("count(/tapi/document/items/item)"); - $this->_totalResultsAvailable = (int) $this->getDays(); - } - - - /** - * Returns the search URL for given query. - * - * @return Zend_Uri_Http - */ - public function getSearchUrl() { - return $this->_searchUrl; - } - - /** - * Returns the number of days for which counts provided. - * - * @return int - */ - public function getDays() { - return $this->_days; - } - - /** - * Implements Zend_Service_Technorati_ResultSet::current(). - * - * @return Zend_Service_Technorati_DailyCountsResult current result - */ - public function current() - { - /** - * @see Zend_Service_Technorati_DailyCountsResult - */ - require_once 'Zend/Service/Technorati/DailyCountsResult.php'; - return new Zend_Service_Technorati_DailyCountsResult($this->_results->item($this->_currentIndex)); - } -} diff --git a/lib/zend/Zend/Service/Technorati/GetInfoResult.php b/lib/zend/Zend/Service/Technorati/GetInfoResult.php deleted file mode 100644 index 1cfdd9bf644..00000000000 --- a/lib/zend/Zend/Service/Technorati/GetInfoResult.php +++ /dev/null @@ -1,103 +0,0 @@ -query('//result'); - if ($result->length == 1) { - $this->_author = new Zend_Service_Technorati_Author($result->item(0)); - } - - /** - * @see Zend_Service_Technorati_Weblog - */ - require_once 'Zend/Service/Technorati/Weblog.php'; - - $result = $xpath->query('//item/weblog'); - if ($result->length >= 1) { - foreach ($result as $weblog) { - $this->_weblogs[] = new Zend_Service_Technorati_Weblog($weblog); - } - } - } - - - /** - * Returns the author associated with queried username. - * - * @return Zend_Service_Technorati_Author - */ - public function getAuthor() { - return $this->_author; - } - - /** - * Returns the collection of weblogs authored by queried username. - * - * @return array of Zend_Service_Technorati_Weblog - */ - public function getWeblogs() { - return $this->_weblogs; - } - -} diff --git a/lib/zend/Zend/Service/Technorati/KeyInfoResult.php b/lib/zend/Zend/Service/Technorati/KeyInfoResult.php deleted file mode 100644 index e98666913db..00000000000 --- a/lib/zend/Zend/Service/Technorati/KeyInfoResult.php +++ /dev/null @@ -1,118 +0,0 @@ -_dom = $dom; - // $this->_xpath = new DOMXPath($dom); - $xpath = new DOMXPath($dom); - - $this->_apiQueries = (int) $xpath->query('/tapi/document/result/apiqueries/text()')->item(0)->data; - $this->_maxQueries = (int) $xpath->query('/tapi/document/result/maxqueries/text()')->item(0)->data; - $this->setApiKey($apiKey); - } - - - /** - * Returns API Key string. - * - * @return string API Key string - */ - public function getApiKey() { - return $this->_apiKey; - } - - /** - * Returns the number of queries sent today. - * - * @return int number of queries sent today - */ - public function getApiQueries() { - return $this->_apiQueries; - } - - /** - * Returns Key's daily query limit. - * - * @return int maximum number of available queries per day - */ - public function getMaxQueries() { - return $this->_maxQueries; - } - - - /** - * Sets API Key string. - * - * @param string $apiKey the API Key - * @return Zend_Service_Technorati_KeyInfoResult $this instance - */ - public function setApiKey($apiKey) { - $this->_apiKey = $apiKey; - return $this; - } -} diff --git a/lib/zend/Zend/Service/Technorati/Result.php b/lib/zend/Zend/Service/Technorati/Result.php deleted file mode 100644 index 518e06f69a5..00000000000 --- a/lib/zend/Zend/Service/Technorati/Result.php +++ /dev/null @@ -1,121 +0,0 @@ - 'xmlfieldtag' - * - * @var array - * @access protected - */ - protected $_fields; - - /** - * The ReST fragment for this result object - * - * @var DomElement - * @access protected - */ - protected $_dom; - - /** - * Object for $this->_dom - * - * @var DOMXpath - * @access protected - */ - protected $_xpath; - - - /** - * Constructs a new object from DOM Element. - * Properties are automatically fetched from XML - * according to array of $_fields to be read. - * - * @param DomElement $result the ReST fragment for this object - */ - public function __construct(DomElement $dom) - { - $this->_xpath = new DOMXPath($dom->ownerDocument); - $this->_dom = $dom; - - // default fields for all search results - $fields = array(); - - // merge with child's object fields - $this->_fields = array_merge($this->_fields, $fields); - - // add results to appropriate fields - foreach($this->_fields as $phpName => $xmlName) { - $query = "./$xmlName/text()"; - $node = $this->_xpath->query($query, $this->_dom); - if ($node->length == 1) { - $this->{$phpName} = (string) $node->item(0)->data; - } - } - } - - /** - * Parses weblog node and sets weblog object. - * - * @return void - */ - protected function _parseWeblog() - { - // weblog object field - $result = $this->_xpath->query('./weblog', $this->_dom); - if ($result->length == 1) { - /** - * @see Zend_Service_Technorati_Weblog - */ - require_once 'Zend/Service/Technorati/Weblog.php'; - $this->_weblog = new Zend_Service_Technorati_Weblog($result->item(0)); - } else { - $this->_weblog = null; - } - } - - /** - * Returns the document fragment for this object as XML string. - * - * @return string the document fragment for this object - * converted into XML format - */ - public function getXml() - { - return $this->_dom->ownerDocument->saveXML($this->_dom); - } -} diff --git a/lib/zend/Zend/Service/Technorati/ResultSet.php b/lib/zend/Zend/Service/Technorati/ResultSet.php deleted file mode 100644 index 43008210f0b..00000000000 --- a/lib/zend/Zend/Service/Technorati/ResultSet.php +++ /dev/null @@ -1,289 +0,0 @@ -_dom - * - * @var DOMXpath - * @access protected - */ - protected $_xpath; - - /** - * XML string representation for $this->_dom - * - * @var string - * @access protected - */ - protected $_xml; - - /** - * Current Item - * - * @var int - * @access protected - */ - protected $_currentIndex = 0; - - - /** - * Parses the search response and retrieves the results for iteration. - * - * @param DomDocument $dom the ReST fragment for this object - * @param array $options query options as associative array - */ - public function __construct(DomDocument $dom, $options = array()) - { - $this->_init($dom, $options); - - // Technorati loves to make developer's life really hard - // I must read query options in order to normalize a single way - // to display start and limit. - // The value is printed out in XML using many different tag names, - // too hard to get it from XML - - // Additionally, the following tags should be always available - // according to API documentation but... this is not the truth! - // - querytime - // - limit - // - start (sometimes rankingstart) - - // query tag is only available for some requests, the same for url. - // For now ignore them. - - //$start = isset($options['start']) ? $options['start'] : 1; - //$limit = isset($options['limit']) ? $options['limit'] : 20; - //$this->_firstResultPosition = $start; - } - - /** - * Initializes this object from a DomDocument response. - * - * Because __construct and __wakeup shares some common executions, - * it's useful to group them in a single initialization method. - * This method is called once each time a new instance is created - * or a serialized object is unserialized. - * - * @param DomDocument $dom the ReST fragment for this object - * @param array $options query options as associative array - * * @return void - */ - protected function _init(DomDocument $dom, $options = array()) - { - $this->_dom = $dom; - $this->_xpath = new DOMXPath($dom); - - $this->_results = $this->_xpath->query("//item"); - } - - /** - * Number of results returned. - * - * @return int total number of results returned - */ - public function totalResults() - { - return (int) $this->_totalResultsReturned; - } - - - /** - * Number of available results. - * - * @return int total number of available results - */ - public function totalResultsAvailable() - { - return (int) $this->_totalResultsAvailable; - } - - /** - * Implements SeekableIterator::current(). - * - * @return void - * @throws Zend_Service_Exception - * @abstract - */ - // abstract public function current(); - - /** - * Implements SeekableIterator::key(). - * - * @return int - */ - public function key() - { - return $this->_currentIndex; - } - - /** - * Implements SeekableIterator::next(). - * - * @return void - */ - public function next() - { - $this->_currentIndex += 1; - } - - /** - * Implements SeekableIterator::rewind(). - * - * @return bool - */ - public function rewind() - { - $this->_currentIndex = 0; - return true; - } - - /** - * Implement SeekableIterator::seek(). - * - * @param int $index - * @return void - * @throws OutOfBoundsException - */ - public function seek($index) - { - $indexInt = (int) $index; - if ($indexInt >= 0 && $indexInt < $this->_results->length) { - $this->_currentIndex = $indexInt; - } else { - throw new OutOfBoundsException("Illegal index '$index'"); - } - } - - /** - * Implement SeekableIterator::valid(). - * - * @return boolean - */ - public function valid() - { - return null !== $this->_results && $this->_currentIndex < $this->_results->length; - } - - /** - * Returns the response document as XML string. - * - * @return string the response document converted into XML format - */ - public function getXml() - { - return $this->_dom->saveXML(); - } - - /** - * Overwrites standard __sleep method to make this object serializable. - * - * DomDocument and DOMXpath objects cannot be serialized. - * This method converts them back to an XML string. - * - * @return void - */ - public function __sleep() { - $this->_xml = $this->getXml(); - $vars = array_keys(get_object_vars($this)); - return array_diff($vars, array('_dom', '_xpath')); - } - - /** - * Overwrites standard __wakeup method to make this object unserializable. - * - * Restores object status before serialization. - * Converts XML string into a DomDocument object and creates a valid - * DOMXpath instance for given DocDocument. - * - * @return void - */ - public function __wakeup() { - $dom = new DOMDocument(); - $dom->loadXml($this->_xml); - $this->_init($dom); - $this->_xml = null; // reset XML content - } -} diff --git a/lib/zend/Zend/Service/Technorati/SearchResult.php b/lib/zend/Zend/Service/Technorati/SearchResult.php deleted file mode 100644 index 76828439f4f..00000000000 --- a/lib/zend/Zend/Service/Technorati/SearchResult.php +++ /dev/null @@ -1,150 +0,0 @@ -_fields = array( '_permalink' => 'permalink', - '_excerpt' => 'excerpt', - '_created' => 'created', - '_title' => 'title'); - parent::__construct($dom); - - // weblog object field - $this->_parseWeblog(); - - // filter fields - $this->_permalink = Zend_Service_Technorati_Utils::normalizeUriHttp($this->_permalink); - $this->_created = Zend_Service_Technorati_Utils::normalizeDate($this->_created); - } - - /** - * Returns the weblog object that links queried URL. - * - * @return Zend_Service_Technorati_Weblog - */ - public function getWeblog() { - return $this->_weblog; - } - - /** - * Returns the title of the entry. - * - * @return string - */ - public function getTitle() { - return $this->_title; - } - - /** - * Returns the blurb from entry with search term highlighted. - * - * @return string - */ - public function getExcerpt() { - return $this->_excerpt; - } - - /** - * Returns the datetime the entry was created. - * - * @return Zend_Date - */ - public function getCreated() { - return $this->_created; - } - - /** - * Returns the permalink of the blog entry. - * - * @return Zend_Uri_Http - */ - public function getPermalink() { - return $this->_permalink; - } - -} diff --git a/lib/zend/Zend/Service/Technorati/SearchResultSet.php b/lib/zend/Zend/Service/Technorati/SearchResultSet.php deleted file mode 100644 index c6718ee0727..00000000000 --- a/lib/zend/Zend/Service/Technorati/SearchResultSet.php +++ /dev/null @@ -1,79 +0,0 @@ -_xpath->query('/tapi/document/result/querycount/text()'); - if ($result->length == 1) $this->_queryCount = (int) $result->item(0)->data; - - $this->_totalResultsReturned = (int) $this->_xpath->evaluate("count(/tapi/document/item)"); - $this->_totalResultsAvailable = (int) $this->_queryCount; - } - - /** - * Implements Zend_Service_Technorati_ResultSet::current(). - * - * @return Zend_Service_Technorati_SearchResult current result - */ - public function current() - { - /** - * @see Zend_Service_Technorati_SearchResult - */ - require_once 'Zend/Service/Technorati/SearchResult.php'; - return new Zend_Service_Technorati_SearchResult($this->_results->item($this->_currentIndex)); - } -} diff --git a/lib/zend/Zend/Service/Technorati/TagResult.php b/lib/zend/Zend/Service/Technorati/TagResult.php deleted file mode 100644 index e371b9abc7a..00000000000 --- a/lib/zend/Zend/Service/Technorati/TagResult.php +++ /dev/null @@ -1,171 +0,0 @@ -_fields = array( '_permalink' => 'permalink', - '_excerpt' => 'excerpt', - '_created' => 'created', - '_updated' => 'postupdate', - '_title' => 'title'); - parent::__construct($dom); - - // weblog object field - $this->_parseWeblog(); - - // filter fields - $this->_permalink = Zend_Service_Technorati_Utils::normalizeUriHttp($this->_permalink); - $this->_created = Zend_Service_Technorati_Utils::normalizeDate($this->_created); - $this->_updated = Zend_Service_Technorati_Utils::normalizeDate($this->_updated); - } - - /** - * Returns the weblog object that links queried URL. - * - * @return Zend_Service_Technorati_Weblog - */ - public function getWeblog() { - return $this->_weblog; - } - - /** - * Returns the title of the entry. - * - * @return string - */ - public function getTitle() { - return $this->_title; - } - - /** - * Returns the blurb from entry with search term highlighted. - * - * @return string - */ - public function getExcerpt() { - return $this->_excerpt; - } - - /** - * Returns the datetime the entry was created. - * - * @return Zend_Date - */ - public function getCreated() { - return $this->_created; - } - - /** - * Returns the datetime the entry was updated. - * - * @return Zend_Date - */ - public function getUpdated() { - return $this->_updated; - } - - /** - * Returns the permalink of the blog entry. - * - * @return Zend_Uri_Http - */ - public function getPermalink() { - return $this->_permalink; - } - -} diff --git a/lib/zend/Zend/Service/Technorati/TagResultSet.php b/lib/zend/Zend/Service/Technorati/TagResultSet.php deleted file mode 100644 index 62068bba62d..00000000000 --- a/lib/zend/Zend/Service/Technorati/TagResultSet.php +++ /dev/null @@ -1,110 +0,0 @@ -_xpath->query('/tapi/document/result/postsmatched/text()'); - if ($result->length == 1) $this->_postsMatched = (int) $result->item(0)->data; - - $result = $this->_xpath->query('/tapi/document/result/blogsmatched/text()'); - if ($result->length == 1) $this->_blogsMatched = (int) $result->item(0)->data; - - $this->_totalResultsReturned = (int) $this->_xpath->evaluate("count(/tapi/document/item)"); - /** @todo Validate the following assertion */ - $this->_totalResultsAvailable = (int) $this->getPostsMatched(); - } - - - /** - * Returns the number of posts that match the tag. - * - * @return int - */ - public function getPostsMatched() { - return $this->_postsMatched; - } - - /** - * Returns the number of blogs that match the tag. - * - * @return int - */ - public function getBlogsMatched() { - return $this->_blogsMatched; - } - - /** - * Implements Zend_Service_Technorati_ResultSet::current(). - * - * @return Zend_Service_Technorati_TagResult current result - */ - public function current() - { - /** - * @see Zend_Service_Technorati_TagResult - */ - require_once 'Zend/Service/Technorati/TagResult.php'; - return new Zend_Service_Technorati_TagResult($this->_results->item($this->_currentIndex)); - } -} diff --git a/lib/zend/Zend/Service/Technorati/TagsResult.php b/lib/zend/Zend/Service/Technorati/TagsResult.php deleted file mode 100644 index b97980154be..00000000000 --- a/lib/zend/Zend/Service/Technorati/TagsResult.php +++ /dev/null @@ -1,93 +0,0 @@ -_fields = array( '_tag' => 'tag', - '_posts' => 'posts'); - parent::__construct($dom); - - // filter fields - $this->_tag = (string) $this->_tag; - $this->_posts = (int) $this->_posts; - } - - /** - * Returns the tag name. - * - * @return string - */ - public function getTag() { - return $this->_tag; - } - - /** - * Returns the number of posts. - * - * @return int - */ - public function getPosts() { - return $this->_posts; - } -} diff --git a/lib/zend/Zend/Service/Technorati/TagsResultSet.php b/lib/zend/Zend/Service/Technorati/TagsResultSet.php deleted file mode 100644 index c804ecd21e6..00000000000 --- a/lib/zend/Zend/Service/Technorati/TagsResultSet.php +++ /dev/null @@ -1,67 +0,0 @@ -_totalResultsReturned = (int) $this->_xpath->evaluate("count(/tapi/document/item)"); - $this->_totalResultsAvailable = (int) $this->_totalResultsReturned; - } - - /** - * Implements Zend_Service_Technorati_ResultSet::current(). - * - * @return Zend_Service_Technorati_TagsResult current result - */ - public function current() - { - /** - * @see Zend_Service_Technorati_TagsResult - */ - require_once 'Zend/Service/Technorati/TagsResult.php'; - return new Zend_Service_Technorati_TagsResult($this->_results->item($this->_currentIndex)); - } -} diff --git a/lib/zend/Zend/Service/Technorati/Utils.php b/lib/zend/Zend/Service/Technorati/Utils.php deleted file mode 100644 index 36448d75749..00000000000 --- a/lib/zend/Zend/Service/Technorati/Utils.php +++ /dev/null @@ -1,136 +0,0 @@ -getMessage(), 0, $e); - } - } - - // allow inly Zend_Uri_Http objects or child classes - if (!($uri instanceof Zend_Uri_Http)) { - /** - * @see Zend_Service_Technorati_Exception - */ - require_once 'Zend/Service/Technorati/Exception.php'; - throw new Zend_Service_Technorati_Exception( - "Invalid URL $uri, only HTTP(S) protocols can be used"); - } - - return $uri; - } - /** - * Parses, validates and returns a valid Zend_Date object - * from given $input. - * - * $input can be either a string, an integer or a Zend_Date object. - * If $input is string or int, it will be provided to Zend_Date as it is. - * If $input is a Zend_Date object, the object instance will be returned. - * - * @param mixed|Zend_Date $input - * @return null|Zend_Date - * @throws Zend_Service_Technorati_Exception - * @static - */ - public static function normalizeDate($input) - { - /** - * @see Zend_Date - */ - require_once 'Zend/Date.php'; - /** - * @see Zend_Locale - */ - require_once 'Zend/Locale.php'; - - // allow null as value and return valid Zend_Date objects - if (($input === null) || ($input instanceof Zend_Date)) { - return $input; - } - - // due to a BC break as of ZF 1.5 it's not safe to use Zend_Date::isDate() here - // see ZF-2524, ZF-2334 - if (@strtotime($input) !== FALSE) { - return new Zend_Date($input); - } else { - /** - * @see Zend_Service_Technorati_Exception - */ - require_once 'Zend/Service/Technorati/Exception.php'; - throw new Zend_Service_Technorati_Exception("'$input' is not a valid Date/Time"); - } - } - - /** - * @todo public static function xpathQueryAndSet() {} - */ - - /** - * @todo public static function xpathQueryAndSetIf() {} - */ - - /** - * @todo public static function xpathQueryAndSetUnless() {} - */ -} diff --git a/lib/zend/Zend/Service/Technorati/Weblog.php b/lib/zend/Zend/Service/Technorati/Weblog.php deleted file mode 100644 index c7044d84ac6..00000000000 --- a/lib/zend/Zend/Service/Technorati/Weblog.php +++ /dev/null @@ -1,486 +0,0 @@ -ownerDocument); - - $result = $xpath->query('./name/text()', $dom); - if ($result->length == 1) $this->setName($result->item(0)->data); - - $result = $xpath->query('./url/text()', $dom); - if ($result->length == 1) $this->setUrl($result->item(0)->data); - - $result = $xpath->query('./inboundblogs/text()', $dom); - if ($result->length == 1) $this->setInboundBlogs($result->item(0)->data); - - $result = $xpath->query('./inboundlinks/text()', $dom); - if ($result->length == 1) $this->setInboundLinks($result->item(0)->data); - - $result = $xpath->query('./lastupdate/text()', $dom); - if ($result->length == 1) $this->setLastUpdate($result->item(0)->data); - - /* The following elements need more attention */ - - $result = $xpath->query('./rssurl/text()', $dom); - if ($result->length == 1) $this->setRssUrl($result->item(0)->data); - - $result = $xpath->query('./atomurl/text()', $dom); - if ($result->length == 1) $this->setAtomUrl($result->item(0)->data); - - $result = $xpath->query('./author', $dom); - if ($result->length >= 1) { - foreach ($result as $author) { - $this->_authors[] = new Zend_Service_Technorati_Author($author); - } - } - - /** - * The following are optional elements - * - * I can't find any official documentation about the following properties - * however they are included in response DTD and/or test responses. - */ - - $result = $xpath->query('./rank/text()', $dom); - if ($result->length == 1) $this->setRank($result->item(0)->data); - - $result = $xpath->query('./lat/text()', $dom); - if ($result->length == 1) $this->setLat($result->item(0)->data); - - $result = $xpath->query('./lon/text()', $dom); - if ($result->length == 1) $this->setLon($result->item(0)->data); - - $result = $xpath->query('./hasphoto/text()', $dom); - if ($result->length == 1) $this->setHasPhoto($result->item(0)->data); - } - - - /** - * Returns weblog name. - * - * @return string Weblog name - */ - public function getName() - { - return $this->_name; - } - - /** - * Returns weblog URL. - * - * @return null|Zend_Uri_Http object representing weblog base URL - */ - public function getUrl() - { - return $this->_url; - } - - /** - * Returns number of unique blogs linking this blog. - * - * @return integer the number of inbound blogs - */ - public function getInboundBlogs() - { - return $this->_inboundBlogs; - } - - /** - * Returns number of incoming links to this blog. - * - * @return integer the number of inbound links - */ - public function getInboundLinks() - { - return $this->_inboundLinks; - } - - /** - * Returns weblog Rss URL. - * - * @return null|Zend_Uri_Http object representing the URL - * of the RSS feed for given blog - */ - public function getRssUrl() - { - return $this->_rssUrl; - } - - /** - * Returns weblog Atom URL. - * - * @return null|Zend_Uri_Http object representing the URL - * of the Atom feed for given blog - */ - public function getAtomUrl() - { - return $this->_atomUrl; - } - - /** - * Returns UNIX timestamp of the last weblog update. - * - * @return integer UNIX timestamp of the last weblog update - */ - public function getLastUpdate() - { - return $this->_lastUpdate; - } - - /** - * Returns weblog rank value. - * - * Note. This property is not documented. - * - * @return integer weblog rank value - */ - public function getRank() - { - return $this->_rank; - } - - /** - * Returns weblog latitude coordinate. - * - * Note. This property is not documented. - * - * @return float weblog latitude coordinate - */ - public function getLat() { - return $this->_lat; - } - - /** - * Returns weblog longitude coordinate. - * - * Note. This property is not documented. - * - * @return float weblog longitude coordinate - */ - public function getLon() - { - return $this->_lon; - } - - /** - * Returns whether the author who claimed this weblog has a photo. - * - * Note. This property is not documented. - * - * @return bool TRUE if the author who claimed this weblog has a photo, - * FALSE otherwise. - */ - public function hasPhoto() - { - return (bool) $this->_hasPhoto; - } - - /** - * Returns the array of weblog authors. - * - * @return array of Zend_Service_Technorati_Author authors - */ - public function getAuthors() - { - return (array) $this->_authors; - } - - - /** - * Sets weblog name. - * - * @param string $name - * @return Zend_Service_Technorati_Weblog $this instance - */ - public function setName($name) - { - $this->_name = (string) $name; - return $this; - } - - /** - * Sets weblog URL. - * - * @param string|Zend_Uri_Http $url - * @return void - * @throws Zend_Service_Technorati_Exception if $input is an invalid URI - * (via Zend_Service_Technorati_Utils::normalizeUriHttp) - */ - public function setUrl($url) - { - $this->_url = Zend_Service_Technorati_Utils::normalizeUriHttp($url); - return $this; - } - - /** - * Sets number of inbound blogs. - * - * @param integer $number - * @return Zend_Service_Technorati_Weblog $this instance - */ - public function setInboundBlogs($number) - { - $this->_inboundBlogs = (int) $number; - return $this; - } - - /** - * Sets number of Iinbound links. - * - * @param integer $number - * @return Zend_Service_Technorati_Weblog $this instance - */ - public function setInboundLinks($number) - { - $this->_inboundLinks = (int) $number; - return $this; - } - - /** - * Sets weblog Rss URL. - * - * @param string|Zend_Uri_Http $url - * @return Zend_Service_Technorati_Weblog $this instance - * @throws Zend_Service_Technorati_Exception if $input is an invalid URI - * (via Zend_Service_Technorati_Utils::normalizeUriHttp) - */ - public function setRssUrl($url) - { - $this->_rssUrl = Zend_Service_Technorati_Utils::normalizeUriHttp($url); - return $this; - } - - /** - * Sets weblog Atom URL. - * - * @param string|Zend_Uri_Http $url - * @return Zend_Service_Technorati_Weblog $this instance - * @throws Zend_Service_Technorati_Exception if $input is an invalid URI - * (via Zend_Service_Technorati_Utils::normalizeUriHttp) - */ - public function setAtomUrl($url) - { - $this->_atomUrl = Zend_Service_Technorati_Utils::normalizeUriHttp($url); - return $this; - } - - /** - * Sets weblog Last Update timestamp. - * - * $datetime can be any value supported by - * Zend_Service_Technorati_Utils::normalizeDate(). - * - * @param mixed $datetime A string representing the last update date time - * in a valid date time format - * @return Zend_Service_Technorati_Weblog $this instance - * @throws Zend_Service_Technorati_Exception - */ - public function setLastUpdate($datetime) - { - $this->_lastUpdate = Zend_Service_Technorati_Utils::normalizeDate($datetime); - return $this; - } - - /** - * Sets weblog Rank. - * - * @param integer $rank - * @return Zend_Service_Technorati_Weblog $this instance - */ - public function setRank($rank) - { - $this->_rank = (int) $rank; - return $this; - } - - /** - * Sets weblog latitude coordinate. - * - * @param float $coordinate - * @return Zend_Service_Technorati_Weblog $this instance - */ - public function setLat($coordinate) - { - $this->_lat = (float) $coordinate; - return $this; - } - - /** - * Sets weblog longitude coordinate. - * - * @param float $coordinate - * @return Zend_Service_Technorati_Weblog $this instance - */ - public function setLon($coordinate) - { - $this->_lon = (float) $coordinate; - return $this; - } - - /** - * Sets hasPhoto property. - * - * @param bool $hasPhoto - * @return Zend_Service_Technorati_Weblog $this instance - */ - public function setHasPhoto($hasPhoto) - { - $this->_hasPhoto = (bool) $hasPhoto; - return $this; - } - -} diff --git a/lib/zend/Zend/Service/Twitter.php b/lib/zend/Zend/Service/Twitter.php old mode 100644 new mode 100755 index d75bb8be958..836d3b8cadb --- a/lib/zend/Zend/Service/Twitter.php +++ b/lib/zend/Zend/Service/Twitter.php @@ -15,35 +15,54 @@ * @category Zend * @package Zend_Service * @subpackage Twitter - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ /** - * @see Zend_Rest_Client + * @see Zend_Http_Client */ -require_once 'Zend/Rest/Client.php'; +require_once 'Zend/Http/Client.php'; /** - * @see Zend_Rest_Client_Result + * @see Zend_Http_CookieJar */ -require_once 'Zend/Rest/Client/Result.php'; +require_once 'Zend/Http/CookieJar.php'; /** * @see Zend_Oauth_Consumer */ require_once 'Zend/Oauth/Consumer.php'; +/** + * @see Zend_Oauth_Token_Access + */ +require_once 'Zend/Oauth/Token/Access.php'; + +/** + * @see Zend_Service_Twitter_Response + */ +require_once 'Zend/Service/Twitter/Response.php'; + /** * @category Zend * @package Zend_Service * @subpackage Twitter - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class Zend_Service_Twitter extends Zend_Rest_Client +class Zend_Service_Twitter { + /** + * Base URI for all API calls + */ + const API_BASE_URI = 'https://api.twitter.com/1.1/'; + + /** + * OAuth Endpoint + */ + const OAUTH_BASE_URI = 'https://api.twitter.com/oauth'; /** * 246 is the current limit for a status message, 140 characters are displayed @@ -54,181 +73,165 @@ class Zend_Service_Twitter extends Zend_Rest_Client * This should be reviewed in the future... */ const STATUS_MAX_CHARACTERS = 246; - + /** - * OAuth Endpoint + * @var array */ - const OAUTH_BASE_URI = 'http://twitter.com/oauth'; - - /** - * @var Zend_Http_CookieJar - */ - protected $_cookieJar; - + protected $cookieJar; + /** * Date format for 'since' strings * * @var string */ - protected $_dateFormat = 'D, d M Y H:i:s T'; - + protected $dateFormat = 'D, d M Y H:i:s T'; + /** - * Username - * - * @var string + * @var Zend_Http_Client */ - protected $_username; - + protected $httpClient = null; + /** * Current method type (for method proxying) * * @var string */ - protected $_methodType; - + protected $methodType; + /** - * Zend_Oauth Consumer + * Oauth Consumer * * @var Zend_Oauth_Consumer */ - protected $_oauthConsumer = null; - + protected $oauthConsumer = null; + /** * Types of API methods * * @var array */ - protected $_methodTypes = array( - 'status', - 'user', - 'directMessage', - 'friendship', + protected $methodTypes = array( 'account', - 'favorite', - 'block' + 'application', + 'blocks', + 'directmessages', + 'favorites', + 'friendships', + 'search', + 'statuses', + 'users', ); - + /** * Options passed to constructor * * @var array */ - protected $_options = array(); + protected $options = array(); /** - * Local HTTP Client cloned from statically set client + * Username * - * @var Zend_Http_Client + * @var string */ - protected $_localHttpClient = null; + protected $username; /** * Constructor * - * @param array $options Optional options array - * @return void + * @param null|array|Zend_Config $options + * @param null|Zend_Oauth_Consumer $consumer + * @param null|Zend_Http_Client $httpClient */ - public function __construct(array $options = null, Zend_Oauth_Consumer $consumer = null) + public function __construct($options = null, Zend_Oauth_Consumer $consumer = null, Zend_Http_Client $httpClient = null) { - $this->setUri('http://api.twitter.com'); - if (!is_array($options)) $options = array(); - $options['siteUrl'] = self::OAUTH_BASE_URI; if ($options instanceof Zend_Config) { $options = $options->toArray(); } - $this->_options = $options; + if (!is_array($options)) { + $options = array(); + } + + $this->options = $options; + if (isset($options['username'])) { $this->setUsername($options['username']); } - if (isset($options['accessToken']) - && $options['accessToken'] instanceof Zend_Oauth_Token_Access) { - $this->setLocalHttpClient($options['accessToken']->getHttpClient($options)); + + $accessToken = false; + if (isset($options['accessToken'])) { + $accessToken = $options['accessToken']; + } elseif (isset($options['access_token'])) { + $accessToken = $options['access_token']; + } + + $oauthOptions = array(); + if (isset($options['oauthOptions'])) { + $oauthOptions = $options['oauthOptions']; + } elseif (isset($options['oauth_options'])) { + $oauthOptions = $options['oauth_options']; + } + $oauthOptions['siteUrl'] = self::OAUTH_BASE_URI; + + $httpClientOptions = array(); + if (isset($options['httpClientOptions'])) { + $httpClientOptions = $options['httpClientOptions']; + } elseif (isset($options['http_client_options'])) { + $httpClientOptions = $options['http_client_options']; + } + + // If we have an OAuth access token, use the HTTP client it provides + if ($accessToken && is_array($accessToken) + && (isset($accessToken['token']) && isset($accessToken['secret'])) + ) { + $token = new Zend_Oauth_Token_Access(); + $token->setToken($accessToken['token']); + $token->setTokenSecret($accessToken['secret']); + $accessToken = $token; + } + if ($accessToken && $accessToken instanceof Zend_Oauth_Token_Access) { + $oauthOptions['token'] = $accessToken; + $this->setHttpClient($accessToken->getHttpClient($oauthOptions, self::OAUTH_BASE_URI, $httpClientOptions)); + return; + } + + // See if we were passed an http client + if (isset($options['httpClient']) && null === $httpClient) { + $httpClient = $options['httpClient']; + } elseif (isset($options['http_client']) && null === $httpClient) { + $httpClient = $options['http_client']; + } + if ($httpClient instanceof Zend_Http_Client) { + $this->httpClient = $httpClient; } else { - $this->setLocalHttpClient(clone self::getHttpClient()); - if (is_null($consumer)) { - $this->_oauthConsumer = new Zend_Oauth_Consumer($options); - } else { - $this->_oauthConsumer = $consumer; - } + $this->setHttpClient(new Zend_Http_Client(null, $httpClientOptions)); } - } - /** - * Set local HTTP client as distinct from the static HTTP client - * as inherited from Zend_Rest_Client. - * - * @param Zend_Http_Client $client - * @return self - */ - public function setLocalHttpClient(Zend_Http_Client $client) - { - $this->_localHttpClient = $client; - $this->_localHttpClient->setHeaders('Accept-Charset', 'ISO-8859-1,utf-8'); - return $this; - } - - /** - * Get the local HTTP client as distinct from the static HTTP client - * inherited from Zend_Rest_Client - * - * @return Zend_Http_Client - */ - public function getLocalHttpClient() - { - return $this->_localHttpClient; - } - - /** - * Checks for an authorised state - * - * @return bool - */ - public function isAuthorised() - { - if ($this->getLocalHttpClient() instanceof Zend_Oauth_Client) { - return true; + // Set the OAuth consumer + if ($consumer === null) { + $consumer = new Zend_Oauth_Consumer($oauthOptions); } - return false; - } - - /** - * Retrieve username - * - * @return string - */ - public function getUsername() - { - return $this->_username; - } - - /** - * Set username - * - * @param string $value - * @return Zend_Service_Twitter - */ - public function setUsername($value) - { - $this->_username = $value; - return $this; + $this->oauthConsumer = $consumer; } /** * Proxy service methods * * @param string $type - * @return Zend_Service_Twitter - * @throws Zend_Service_Twitter_Exception If method not in method types list + * @return Twitter + * @throws Exception\DomainException If method not in method types list */ public function __get($type) { - if (!in_array($type, $this->_methodTypes)) { - include_once 'Zend/Service/Twitter/Exception.php'; + $type = strtolower($type); + $type = str_replace('_', '', $type); + if (!in_array($type, $this->methodTypes)) { + require_once 'Zend/Service/Twitter/Exception.php'; throw new Zend_Service_Twitter_Exception( 'Invalid method type "' . $type . '"' ); } - $this->_methodType = $type; + $this->methodType = $type; return $this; } @@ -238,26 +241,28 @@ class Zend_Service_Twitter extends Zend_Rest_Client * @param string $method * @param array $params * @return mixed - * @throws Zend_Service_Twitter_Exception if unable to find method + * @throws Exception\BadMethodCallException if unable to find method */ public function __call($method, $params) { - if (method_exists($this->_oauthConsumer, $method)) { - $return = call_user_func_array(array($this->_oauthConsumer, $method), $params); + if (method_exists($this->oauthConsumer, $method)) { + $return = call_user_func_array(array($this->oauthConsumer, $method), $params); if ($return instanceof Zend_Oauth_Token_Access) { - $this->setLocalHttpClient($return->getHttpClient($this->_options)); + $this->setHttpClient($return->getHttpClient($this->options)); } return $return; } - if (empty($this->_methodType)) { - include_once 'Zend/Service/Twitter/Exception.php'; + if (empty($this->methodType)) { + require_once 'Zend/Service/Twitter/Exception.php'; throw new Zend_Service_Twitter_Exception( 'Invalid method "' . $method . '"' ); } - $test = $this->_methodType . ucfirst($method); + + $test = str_replace('_', '', strtolower($method)); + $test = $this->methodType . $test; if (!method_exists($this, $test)) { - include_once 'Zend/Service/Twitter/Exception.php'; + require_once 'Zend/Service/Twitter/Exception.php'; throw new Zend_Service_Twitter_Exception( 'Invalid method "' . $test . '"' ); @@ -267,414 +272,158 @@ class Zend_Service_Twitter extends Zend_Rest_Client } /** - * Initialize HTTP authentication + * Set HTTP client * - * @return void + * @param Zend_Http_Client $client + * @return self */ - protected function _init() + public function setHttpClient(Zend_Http_Client $client) { - if (!$this->isAuthorised() && $this->getUsername() !== null) { - require_once 'Zend/Service/Twitter/Exception.php'; - throw new Zend_Service_Twitter_Exception( - 'Twitter session is unauthorised. You need to initialize ' - . 'Zend_Service_Twitter with an OAuth Access Token or use ' - . 'its OAuth functionality to obtain an Access Token before ' - . 'attempting any API actions that require authorisation' - ); - } - $client = $this->_localHttpClient; - $client->resetParameters(); - if (null == $this->_cookieJar) { - $client->setCookieJar(); - $this->_cookieJar = $client->getCookieJar(); - } else { - $client->setCookieJar($this->_cookieJar); - } + $this->httpClient = $client; + $this->httpClient->setHeaders(array('Accept-Charset' => 'ISO-8859-1,utf-8')); + return $this; } /** - * Set date header + * Get the HTTP client * - * @param int|string $value - * @deprecated Not supported by Twitter since April 08, 2009 - * @return void + * Lazy loads one if none present + * + * @return Zend_Http_Client */ - protected function _setDate($value) + public function getHttpClient() { - if (is_int($value)) { - $date = date($this->_dateFormat, $value); - } else { - $date = date($this->_dateFormat, strtotime($value)); + if (null === $this->httpClient) { + $this->setHttpClient(new Zend_Http_Client()); } - $this->_localHttpClient->setHeaders('If-Modified-Since', $date); + return $this->httpClient; } /** - * Public Timeline status + * Retrieve username + * + * @return string + */ + public function getUsername() + { + return $this->username; + } + + /** + * Set username + * + * @param string $value + * @return self + */ + public function setUsername($value) + { + $this->username = $value; + return $this; + } + + /** + * Checks for an authorised state + * + * @return bool + */ + public function isAuthorised() + { + if ($this->getHttpClient() instanceof Zend_Oauth_Client) { + return true; + } + return false; + } + + /** + * Verify Account Credentials * * @throws Zend_Http_Client_Exception if HTTP request fails or times out - * @return Zend_Rest_Client_Result + * @throws Exception\DomainException if unable to decode JSON payload + * @return Zend_Service_Twitter_Response */ - public function statusPublicTimeline() + public function accountVerifyCredentials() { - $this->_init(); - $path = '/1/statuses/public_timeline.xml'; - $response = $this->_get($path); - return new Zend_Rest_Client_Result($response->getBody()); + $this->init(); + $response = $this->get('account/verify_credentials'); + return new Zend_Service_Twitter_Response($response); } /** - * Friend Timeline Status + * Returns the number of api requests you have left per hour. * - * $params may include one or more of the following keys - * - id: ID of a friend whose timeline you wish to receive - * - count: how many statuses to return - * - since_id: return results only after the specific tweet - * - page: return page X of results - * - * @param array $params + * @todo Have a separate payload object to represent rate limits * @throws Zend_Http_Client_Exception if HTTP request fails or times out - * @return void + * @throws Exception\DomainException if unable to decode JSON payload + * @return Zend_Service_Twitter_Response */ - public function statusFriendsTimeline(array $params = array()) + public function applicationRateLimitStatus() { - $this->_init(); - $path = '/1/statuses/friends_timeline'; - $_params = array(); - foreach ($params as $key => $value) { - switch (strtolower($key)) { - case 'count': - $count = (int) $value; - if (0 >= $count) { - $count = 1; - } elseif (200 < $count) { - $count = 200; - } - $_params['count'] = (int) $count; - break; - case 'since_id': - $_params['since_id'] = $this->_validInteger($value); - break; - case 'page': - $_params['page'] = (int) $value; - break; - default: - break; - } - } - $path .= '.xml'; - $response = $this->_get($path, $_params); - return new Zend_Rest_Client_Result($response->getBody()); + $this->init(); + $response = $this->get('application/rate_limit_status'); + return new Zend_Service_Twitter_Response($response); } /** - * User Timeline status + * Blocks the user specified in the ID parameter as the authenticating user. + * Destroys a friendship to the blocked user if it exists. * - * $params may include one or more of the following keys - * - id: ID of a friend whose timeline you wish to receive - * - since_id: return results only after the tweet id specified - * - page: return page X of results - * - count: how many statuses to return - * - max_id: returns only statuses with an ID less than or equal to the specified ID - * - user_id: specfies the ID of the user for whom to return the user_timeline - * - screen_name: specfies the screen name of the user for whom to return the user_timeline - * - * @throws Zend_Http_Client_Exception if HTTP request fails or times out - * @return Zend_Rest_Client_Result + * @param integer|string $id The ID or screen name of a user to block. + * @throws Exception\DomainException if unable to decode JSON payload + * @return Zend_Service_Twitter_Response */ - public function statusUserTimeline(array $params = array()) + public function blocksCreate($id) { - $this->_init(); - $path = '/1/statuses/user_timeline'; - $_params = array(); - foreach ($params as $key => $value) { - switch (strtolower($key)) { - case 'id': - $path .= '/' . $value; - break; - case 'page': - $_params['page'] = (int) $value; - break; - case 'count': - $count = (int) $value; - if (0 >= $count) { - $count = 1; - } elseif (200 < $count) { - $count = 200; - } - $_params['count'] = $count; - break; - case 'user_id': - $_params['user_id'] = $this->_validInteger($value); - break; - case 'screen_name': - $_params['screen_name'] = $this->_validateScreenName($value); - break; - case 'since_id': - $_params['since_id'] = $this->_validInteger($value); - break; - case 'max_id': - $_params['max_id'] = $this->_validInteger($value); - break; - default: - break; - } - } - $path .= '.xml'; - $response = $this->_get($path, $_params); - return new Zend_Rest_Client_Result($response->getBody()); + $this->init(); + $path = 'blocks/create'; + $params = $this->createUserParameter($id, array()); + $response = $this->post($path, $params); + return new Zend_Service_Twitter_Response($response); } /** - * Show a single status + * Un-blocks the user specified in the ID parameter for the authenticating user * - * @param int $id Id of status to show - * @throws Zend_Http_Client_Exception if HTTP request fails or times out - * @return Zend_Rest_Client_Result + * @param integer|string $id The ID or screen_name of the user to un-block. + * @throws Exception\DomainException if unable to decode JSON payload + * @return Zend_Service_Twitter_Response */ - public function statusShow($id) + public function blocksDestroy($id) { - $this->_init(); - $path = '/1/statuses/show/' . $this->_validInteger($id) . '.xml'; - $response = $this->_get($path); - return new Zend_Rest_Client_Result($response->getBody()); + $this->init(); + $path = 'blocks/destroy'; + $params = $this->createUserParameter($id, array()); + $response = $this->post($path, $params); + return new Zend_Service_Twitter_Response($response); } /** - * Update user's current status + * Returns an array of user ids that the authenticating user is blocking * - * @param string $status - * @param int $in_reply_to_status_id - * @return Zend_Rest_Client_Result - * @throws Zend_Http_Client_Exception if HTTP request fails or times out - * @throws Zend_Service_Twitter_Exception if message is too short or too long + * @param integer $cursor Optional. Specifies the cursor position at which to begin listing ids; defaults to first "page" of results. + * @throws Exception\DomainException if unable to decode JSON payload + * @return Zend_Service_Twitter_Response */ - public function statusUpdate($status, $inReplyToStatusId = null) + public function blocksIds($cursor = -1) { - $this->_init(); - $path = '/1/statuses/update.xml'; - $len = iconv_strlen(htmlspecialchars($status, ENT_QUOTES, 'UTF-8'), 'UTF-8'); - if ($len > self::STATUS_MAX_CHARACTERS) { - include_once 'Zend/Service/Twitter/Exception.php'; - throw new Zend_Service_Twitter_Exception( - 'Status must be no more than ' - . self::STATUS_MAX_CHARACTERS - . ' characters in length' - ); - } elseif (0 == $len) { - include_once 'Zend/Service/Twitter/Exception.php'; - throw new Zend_Service_Twitter_Exception( - 'Status must contain at least one character' - ); - } - $data = array('status' => $status); - if (is_numeric($inReplyToStatusId) && !empty($inReplyToStatusId)) { - $data['in_reply_to_status_id'] = $inReplyToStatusId; - } - $response = $this->_post($path, $data); - return new Zend_Rest_Client_Result($response->getBody()); + $this->init(); + $path = 'blocks/ids'; + $response = $this->get($path, array('cursor' => $cursor)); + return new Zend_Service_Twitter_Response($response); } /** - * Get status replies + * Returns an array of user objects that the authenticating user is blocking * - * $params may include one or more of the following keys - * - since_id: return results only after the specified tweet id - * - page: return page X of results - * - * @throws Zend_Http_Client_Exception if HTTP request fails or times out - * @return Zend_Rest_Client_Result + * @param integer $cursor Optional. Specifies the cursor position at which to begin listing ids; defaults to first "page" of results. + * @throws Exception\DomainException if unable to decode JSON payload + * @return Zend_Service_Twitter_Response */ - public function statusReplies(array $params = array()) + public function blocksList($cursor = -1) { - $this->_init(); - $path = '/1/statuses/mentions.xml'; - $_params = array(); - foreach ($params as $key => $value) { - switch (strtolower($key)) { - case 'since_id': - $_params['since_id'] = $this->_validInteger($value); - break; - case 'page': - $_params['page'] = (int) $value; - break; - default: - break; - } - } - $response = $this->_get($path, $_params); - return new Zend_Rest_Client_Result($response->getBody()); - } - - /** - * Destroy a status message - * - * @param int $id ID of status to destroy - * @throws Zend_Http_Client_Exception if HTTP request fails or times out - * @return Zend_Rest_Client_Result - */ - public function statusDestroy($id) - { - $this->_init(); - $path = '/1/statuses/destroy/' . $this->_validInteger($id) . '.xml'; - $response = $this->_post($path); - return new Zend_Rest_Client_Result($response->getBody()); - } - - /** - * User friends - * - * @param int|string $id Id or username of user for whom to fetch friends - * @throws Zend_Http_Client_Exception if HTTP request fails or times out - * @return Zend_Rest_Client_Result - */ - public function userFriends(array $params = array()) - { - $this->_init(); - $path = '/1/statuses/friends'; - $_params = array(); - - foreach ($params as $key => $value) { - switch (strtolower($key)) { - case 'id': - $path .= '/' . $value; - break; - case 'page': - $_params['page'] = (int) $value; - break; - default: - break; - } - } - $path .= '.xml'; - - $response = $this->_get($path, $_params); - return new Zend_Rest_Client_Result($response->getBody()); - } - - /** - * User Followers - * - * @param bool $lite If true, prevents inline inclusion of current status for followers; defaults to false - * @throws Zend_Http_Client_Exception if HTTP request fails or times out - * @return Zend_Rest_Client_Result - */ - public function userFollowers($lite = false) - { - $this->_init(); - $path = '/1/statuses/followers.xml'; - if ($lite) { - $this->lite = 'true'; - } - $response = $this->_get($path); - return new Zend_Rest_Client_Result($response->getBody()); - } - - /** - * Show extended information on a user - * - * @param int|string $id User ID or name - * @throws Zend_Http_Client_Exception if HTTP request fails or times out - * @return Zend_Rest_Client_Result - */ - public function userShow($id) - { - $this->_init(); - $path = '/1/users/show.xml'; - $response = $this->_get($path, array('id'=>$id)); - return new Zend_Rest_Client_Result($response->getBody()); - } - - /** - * Retrieve direct messages for the current user - * - * $params may include one or more of the following keys - * - since_id: return statuses only greater than the one specified - * - page: return page X of results - * - * @param array $params - * @throws Zend_Http_Client_Exception if HTTP request fails or times out - * @return Zend_Rest_Client_Result - */ - public function directMessageMessages(array $params = array()) - { - $this->_init(); - $path = '/1/direct_messages.xml'; - $_params = array(); - foreach ($params as $key => $value) { - switch (strtolower($key)) { - case 'since_id': - $_params['since_id'] = $this->_validInteger($value); - break; - case 'page': - $_params['page'] = (int) $value; - break; - default: - break; - } - } - $response = $this->_get($path, $_params); - return new Zend_Rest_Client_Result($response->getBody()); - } - - /** - * Retrieve list of direct messages sent by current user - * - * $params may include one or more of the following keys - * - since_id: return statuses only greater than the one specified - * - page: return page X of results - * - * @param array $params - * @throws Zend_Http_Client_Exception if HTTP request fails or times out - * @return Zend_Rest_Client_Result - */ - public function directMessageSent(array $params = array()) - { - $this->_init(); - $path = '/1/direct_messages/sent.xml'; - $_params = array(); - foreach ($params as $key => $value) { - switch (strtolower($key)) { - case 'since_id': - $_params['since_id'] = $this->_validInteger($value); - break; - case 'page': - $_params['page'] = (int) $value; - break; - default: - break; - } - } - $response = $this->_get($path, $_params); - return new Zend_Rest_Client_Result($response->getBody()); - } - - /** - * Send a direct message to a user - * - * @param int|string $user User to whom to send message - * @param string $text Message to send to user - * @return Zend_Rest_Client_Result - * @throws Zend_Service_Twitter_Exception if message is too short or too long - * @throws Zend_Http_Client_Exception if HTTP request fails or times out - */ - public function directMessageNew($user, $text) - { - $this->_init(); - $path = '/1/direct_messages/new.xml'; - $len = iconv_strlen($text, 'UTF-8'); - if (0 == $len) { - throw new Zend_Service_Twitter_Exception( - 'Direct message must contain at least one character' - ); - } elseif (140 < $len) { - throw new Zend_Service_Twitter_Exception( - 'Direct message must contain no more than 140 characters' - ); - } - $data = array('user' => $user, 'text' => $text); - $response = $this->_post($path, $data); - return new Zend_Rest_Client_Result($response->getBody()); + $this->init(); + $path = 'blocks/list'; + $response = $this->get($path, array('cursor' => $cursor)); + return new Zend_Service_Twitter_Response($response); } /** @@ -682,132 +431,141 @@ class Zend_Service_Twitter extends Zend_Rest_Client * * @param int $id ID of message to destroy * @throws Zend_Http_Client_Exception if HTTP request fails or times out - * @return Zend_Rest_Client_Result + * @throws Exception\DomainException if unable to decode JSON payload + * @return Zend_Service_Twitter_Response */ - public function directMessageDestroy($id) + public function directMessagesDestroy($id) { - $this->_init(); - $path = '/1/direct_messages/destroy/' . $this->_validInteger($id) . '.xml'; - $response = $this->_post($path); - return new Zend_Rest_Client_Result($response->getBody()); + $this->init(); + $path = 'direct_messages/destroy'; + $params = array('id' => $this->validInteger($id)); + $response = $this->post($path, $params); + return new Zend_Service_Twitter_Response($response); } /** - * Create friendship + * Retrieve direct messages for the current user * - * @param int|string $id User ID or name of new friend + * $options may include one or more of the following keys + * - count: return page X of results + * - since_id: return statuses only greater than the one specified + * - max_id: return statuses with an ID less than (older than) or equal to that specified + * - include_entities: setting to false will disable embedded entities + * - skip_status:setting to true, "t", or 1 will omit the status in returned users + * + * @param array $options * @throws Zend_Http_Client_Exception if HTTP request fails or times out - * @return Zend_Rest_Client_Result + * @throws Exception\DomainException if unable to decode JSON payload + * @return Zend_Service_Twitter_Response */ - public function friendshipCreate($id) + public function directMessagesMessages(array $options = array()) { - $this->_init(); - $path = '/1/friendships/create/' . $id . '.xml'; - $response = $this->_post($path); - return new Zend_Rest_Client_Result($response->getBody()); - } - - /** - * Destroy friendship - * - * @param int|string $id User ID or name of friend to remove - * @throws Zend_Http_Client_Exception if HTTP request fails or times out - * @return Zend_Rest_Client_Result - */ - public function friendshipDestroy($id) - { - $this->_init(); - $path = '/1/friendships/destroy/' . $id . '.xml'; - $response = $this->_post($path); - return new Zend_Rest_Client_Result($response->getBody()); - } - - /** - * Friendship exists - * - * @param int|string $id User ID or name of friend to see if they are your friend - * @throws Zend_Http_Client_Exception if HTTP request fails or times out - * @return Zend_Rest_Client_result - */ - public function friendshipExists($id) - { - $this->_init(); - $path = '/1/friendships/exists.xml'; - $data = array('user_a' => $this->getUsername(), 'user_b' => $id); - $response = $this->_get($path, $data); - return new Zend_Rest_Client_Result($response->getBody()); - } - - /** - * Verify Account Credentials - * @throws Zend_Http_Client_Exception if HTTP request fails or times out - * - * @return Zend_Rest_Client_Result - */ - public function accountVerifyCredentials() - { - $this->_init(); - $response = $this->_get('/1/account/verify_credentials.xml'); - return new Zend_Rest_Client_Result($response->getBody()); - } - - /** - * End current session - * - * @throws Zend_Http_Client_Exception if HTTP request fails or times out - * @return true - */ - public function accountEndSession() - { - $this->_init(); - $this->_get('/1/account/end_session'); - return true; - } - - /** - * Returns the number of api requests you have left per hour. - * - * @throws Zend_Http_Client_Exception if HTTP request fails or times out - * @return Zend_Rest_Client_Result - */ - public function accountRateLimitStatus() - { - $this->_init(); - $response = $this->_get('/1/account/rate_limit_status.xml'); - return new Zend_Rest_Client_Result($response->getBody()); - } - - /** - * Fetch favorites - * - * $params may contain one or more of the following: - * - 'id': Id of a user for whom to fetch favorites - * - 'page': Retrieve a different page of resuls - * - * @param array $params - * @throws Zend_Http_Client_Exception if HTTP request fails or times out - * @return Zend_Rest_Client_Result - */ - public function favoriteFavorites(array $params = array()) - { - $this->_init(); - $path = '/1/favorites'; - $_params = array(); - foreach ($params as $key => $value) { + $this->init(); + $path = 'direct_messages'; + $params = array(); + foreach ($options as $key => $value) { switch (strtolower($key)) { - case 'id': - $path .= '/' . $this->_validInteger($value); + case 'count': + $params['count'] = (int) $value; break; - case 'page': - $_params['page'] = (int) $value; + case 'since_id': + $params['since_id'] = $this->validInteger($value); + break; + case 'max_id': + $params['max_id'] = $this->validInteger($value); + break; + case 'include_entities': + $params['include_entities'] = (bool) $value; + break; + case 'skip_status': + $params['skip_status'] = (bool) $value; break; default: break; } } - $path .= '.xml'; - $response = $this->_get($path, $_params); - return new Zend_Rest_Client_Result($response->getBody()); + $response = $this->get($path, $params); + return new Zend_Service_Twitter_Response($response); + } + + /** + * Send a direct message to a user + * + * @param int|string $user User to whom to send message + * @param string $text Message to send to user + * @throws Exception\InvalidArgumentException if message is empty + * @throws Exception\OutOfRangeException if message is too long + * @throws Zend_Http_Client_Exception if HTTP request fails or times out + * @throws Exception\DomainException if unable to decode JSON payload + * @return Zend_Service_Twitter_Response + */ + public function directMessagesNew($user, $text) + { + $this->init(); + $path = 'direct_messages/new'; + + $len = iconv_strlen($text, 'UTF-8'); + if (0 == $len) { + require_once 'Zend/Service/Twitter/Exception.php'; + throw new Zend_Service_Twitter_Exception( + 'Direct message must contain at least one character' + ); + } elseif (140 < $len) { + require_once 'Zend/Service/Twitter/Exception.php'; + throw new Zend_Service_Twitter_Exception( + 'Direct message must contain no more than 140 characters' + ); + } + + $params = $this->createUserParameter($user, array()); + $params['text'] = $text; + $response = $this->post($path, $params); + return new Zend_Service_Twitter_Response($response); + } + + /** + * Retrieve list of direct messages sent by current user + * + * $options may include one or more of the following keys + * - count: return page X of results + * - page: return starting at page + * - since_id: return statuses only greater than the one specified + * - max_id: return statuses with an ID less than (older than) or equal to that specified + * - include_entities: setting to false will disable embedded entities + * + * @param array $options + * @throws Zend_Http_Client_Exception if HTTP request fails or times out + * @throws Exception\DomainException if unable to decode JSON payload + * @return Zend_Service_Twitter_Response + */ + public function directMessagesSent(array $options = array()) + { + $this->init(); + $path = 'direct_messages/sent'; + $params = array(); + foreach ($options as $key => $value) { + switch (strtolower($key)) { + case 'count': + $params['count'] = (int) $value; + break; + case 'page': + $params['page'] = (int) $value; + break; + case 'since_id': + $params['since_id'] = $this->validInteger($value); + break; + case 'max_id': + $params['max_id'] = $this->validInteger($value); + break; + case 'include_entities': + $params['include_entities'] = (bool) $value; + break; + default: + break; + } + } + $response = $this->get($path, $params); + return new Zend_Service_Twitter_Response($response); } /** @@ -815,14 +573,16 @@ class Zend_Service_Twitter extends Zend_Rest_Client * * @param int $id Status ID you want to mark as a favorite * @throws Zend_Http_Client_Exception if HTTP request fails or times out - * @return Zend_Rest_Client_Result + * @throws Exception\DomainException if unable to decode JSON payload + * @return Zend_Service_Twitter_Response */ - public function favoriteCreate($id) + public function favoritesCreate($id) { - $this->_init(); - $path = '/1/favorites/create/' . $this->_validInteger($id) . '.xml'; - $response = $this->_post($path); - return new Zend_Rest_Client_Result($response->getBody()); + $this->init(); + $path = 'favorites/create'; + $params = array('id' => $this->validInteger($id)); + $response = $this->post($path, $params); + return new Zend_Service_Twitter_Response($response); } /** @@ -830,96 +590,602 @@ class Zend_Service_Twitter extends Zend_Rest_Client * * @param int $id Status ID you want to de-list as a favorite * @throws Zend_Http_Client_Exception if HTTP request fails or times out - * @return Zend_Rest_Client_Result + * @throws Exception\DomainException if unable to decode JSON payload + * @return Zend_Service_Twitter_Response */ - public function favoriteDestroy($id) + public function favoritesDestroy($id) { - $this->_init(); - $path = '/1/favorites/destroy/' . $this->_validInteger($id) . '.xml'; - $response = $this->_post($path); - return new Zend_Rest_Client_Result($response->getBody()); + $this->init(); + $path = 'favorites/destroy'; + $params = array('id' => $this->validInteger($id)); + $response = $this->post($path, $params); + return new Zend_Service_Twitter_Response($response); } /** - * Blocks the user specified in the ID parameter as the authenticating user. - * Destroys a friendship to the blocked user if it exists. + * Fetch favorites * - * @param integer|string $id The ID or screen name of a user to block. - * @return Zend_Rest_Client_Result + * $options may contain one or more of the following: + * - user_id: Id of a user for whom to fetch favorites + * - screen_name: Screen name of a user for whom to fetch favorites + * - count: number of tweets to attempt to retrieve, up to 200 + * - since_id: return results only after the specified tweet id + * - max_id: return results with an ID less than (older than) or equal to the specified ID + * - include_entities: when set to false, entities member will be omitted + * + * @param array $params + * @throws Zend_Http_Client_Exception if HTTP request fails or times out + * @throws Exception\DomainException if unable to decode JSON payload + * @return Zend_Service_Twitter_Response */ - public function blockCreate($id) + public function favoritesList(array $options = array()) { - $this->_init(); - $path = '/1/blocks/create/' . $id . '.xml'; - $response = $this->_post($path); - return new Zend_Rest_Client_Result($response->getBody()); + $this->init(); + $path = 'favorites/list'; + $params = array(); + foreach ($options as $key => $value) { + switch (strtolower($key)) { + case 'user_id': + $params['user_id'] = $this->validInteger($value); + break; + case 'screen_name': + $params['screen_name'] = $value; + break; + case 'count': + $params['count'] = (int) $value; + break; + case 'since_id': + $params['since_id'] = $this->validInteger($value); + break; + case 'max_id': + $params['max_id'] = $this->validInteger($value); + break; + case 'include_entities': + $params['include_entities'] = (bool) $value; + break; + default: + break; + } + } + $response = $this->get($path, $params); + return new Zend_Service_Twitter_Response($response); } /** - * Un-blocks the user specified in the ID parameter for the authenticating user + * Create friendship * - * @param integer|string $id The ID or screen_name of the user to un-block. - * @return Zend_Rest_Client_Result + * @param int|string $id User ID or name of new friend + * @param array $params Additional parameters to pass + * @throws Zend_Http_Client_Exception if HTTP request fails or times out + * @throws Exception\DomainException if unable to decode JSON payload + * @return Zend_Service_Twitter_Response */ - public function blockDestroy($id) + public function friendshipsCreate($id, array $params = array()) { - $this->_init(); - $path = '/1/blocks/destroy/' . $id . '.xml'; - $response = $this->_post($path); - return new Zend_Rest_Client_Result($response->getBody()); + $this->init(); + $path = 'friendships/create'; + $params = $this->createUserParameter($id, $params); + $allowed = array( + 'user_id' => null, + 'screen_name' => null, + 'follow' => null, + ); + $params = array_intersect_key($params, $allowed); + $response = $this->post($path, $params); + return new Zend_Service_Twitter_Response($response); } /** - * Returns if the authenticating user is blocking a target user. + * Destroy friendship * - * @param string|integer $id The ID or screen_name of the potentially blocked user. - * @param boolean $returnResult Instead of returning a boolean return the rest response from twitter - * @return Boolean|Zend_Rest_Client_Result + * @param int|string $id User ID or name of friend to remove + * @throws Zend_Http_Client_Exception if HTTP request fails or times out + * @throws Exception\DomainException if unable to decode JSON payload + * @return Zend_Service_Twitter_Response */ - public function blockExists($id, $returnResult = false) + public function friendshipsDestroy($id) { - $this->_init(); - $path = '/1/blocks/exists/' . $id . '.xml'; - $response = $this->_get($path); + $this->init(); + $path = 'friendships/destroy'; + $params = $this->createUserParameter($id, array()); + $response = $this->post($path, $params); + return new Zend_Service_Twitter_Response($response); + } - $cr = new Zend_Rest_Client_Result($response->getBody()); + /** + * Search tweets + * + * $options may include any of the following: + * - geocode: a string of the form "latitude, longitude, radius" + * - lang: restrict tweets to the two-letter language code + * - locale: query is in the given two-letter language code + * - result_type: what type of results to receive: mixed, recent, or popular + * - count: number of tweets to return per page; up to 100 + * - until: return tweets generated before the given date + * - since_id: return resutls with an ID greater than (more recent than) the given ID + * - max_id: return results with an ID less than (older than) the given ID + * - include_entities: whether or not to include embedded entities + * + * @param string $query + * @param array $options + * @throws Zend_Http_Client_Exception if HTTP request fails or times out + * @throws Exception\DomainException if unable to decode JSON payload + * @return Zend_Service_Twitter_Response + */ + public function searchTweets($query, array $options = array()) + { + $this->init(); + $path = 'search/tweets'; - if ($returnResult === true) - return $cr; - - if (!empty($cr->request)) { - return false; + $len = iconv_strlen($query, 'UTF-8'); + if (0 == $len) { + require_once 'Zend/Service/Twitter/Exception.php'; + throw new Zend_Service_Twitter_Exception( + 'Query must contain at least one character' + ); } - return true; + $params = array('q' => $query); + foreach ($options as $key => $value) { + switch (strtolower($key)) { + case 'geocode': + if (!substr_count($value, ',') !== 2) { + require_once 'Zend/Service/Twitter/Exception.php'; + throw new Zend_Service_Twitter_Exception( + '"geocode" must be of the format "latitude,longitude,radius"' + ); + } + list($latitude, $longitude, $radius) = explode(',', $value); + $radius = trim($radius); + if (!preg_match('/^\d+(mi|km)$/', $radius)) { + require_once 'Zend/Service/Twitter/Exception.php'; + throw new Zend_Service_Twitter_Exception( + 'Radius segment of "geocode" must be of the format "[unit](mi|km)"' + ); + } + $latitude = (float) $latitude; + $longitude = (float) $longitude; + $params['geocode'] = $latitude . ',' . $longitude . ',' . $radius; + break; + case 'lang': + if (strlen($value) > 2) { + require_once 'Zend/Service/Twitter/Exception.php'; + throw new Zend_Service_Twitter_Exception( + 'Query language must be a 2 character string' + ); + } + $params['lang'] = strtolower($value); + break; + case 'locale': + if (strlen($value) > 2) { + require_once 'Zend/Service/Twitter/Exception.php'; + throw new Zend_Service_Twitter_Exception( + 'Query locale must be a 2 character string' + ); + } + $params['locale'] = strtolower($value); + break; + case 'result_type': + $value = strtolower($value); + if (!in_array($value, array('mixed', 'recent', 'popular'))) { + require_once 'Zend/Service/Twitter/Exception.php'; + throw new Zend_Service_Twitter_Exception( + 'result_type must be one of "mixed", "recent", or "popular"' + ); + } + $params['result_type'] = $value; + break; + case 'count': + $value = (int) $value; + if (1 > $value || 100 < $value) { + require_once 'Zend/Service/Twitter/Exception.php'; + throw new Zend_Service_Twitter_Exception( + 'count must be between 1 and 100' + ); + } + $params['count'] = $value; + break; + case 'until': + if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $value)) { + require_once 'Zend/Service/Twitter/Exception.php'; + throw new Zend_Service_Twitter_Exception( + '"until" must be a date in the format YYYY-MM-DD' + ); + } + $params['until'] = $value; + break; + case 'since_id': + $params['since_id'] = $this->validInteger($value); + break; + case 'max_id': + $params['max_id'] = $this->validInteger($value); + break; + case 'include_entities': + $params['include_entities'] = (bool) $value; + break; + default: + break; + } + } + $response = $this->get($path, $params); + return new Zend_Service_Twitter_Response($response); } /** - * Returns an array of user objects that the authenticating user is blocking + * Destroy a status message * - * @param integer $page Optional. Specifies the page number of the results beginning at 1. A single page contains 20 ids. - * @param boolean $returnUserIds Optional. Returns only the userid's instead of the whole user object - * @return Zend_Rest_Client_Result + * @param int $id ID of status to destroy + * @throws Zend_Http_Client_Exception if HTTP request fails or times out + * @throws Exception\DomainException if unable to decode JSON payload + * @return Zend_Service_Twitter_Response */ - public function blockBlocking($page = 1, $returnUserIds = false) + public function statusesDestroy($id) { - $this->_init(); - $path = '/1/blocks/blocking'; - if ($returnUserIds === true) { - $path .= '/ids'; + $this->init(); + $path = 'statuses/destroy/' . $this->validInteger($id); + $response = $this->post($path); + return new Zend_Service_Twitter_Response($response); + } + + /** + * Friend Timeline Status + * + * $options may include one or more of the following keys + * - count: number of tweets to attempt to retrieve, up to 200 + * - since_id: return results only after the specified tweet id + * - max_id: return results with an ID less than (older than) or equal to the specified ID + * - trim_user: when set to true, "t", or 1, user object in tweets will include only author's ID. + * - contributor_details: when set to true, includes screen_name of each contributor + * - include_entities: when set to false, entities member will be omitted + * - exclude_replies: when set to true, will strip replies appearing in the timeline + * + * @param array $params + * @throws Zend_Http_Client_Exception if HTTP request fails or times out + * @throws Exception\DomainException if unable to decode JSON payload + * @return Zend_Service_Twitter_Response + */ + public function statusesHomeTimeline(array $options = array()) + { + $this->init(); + $path = 'statuses/home_timeline'; + $params = array(); + foreach ($options as $key => $value) { + switch (strtolower($key)) { + case 'count': + $params['count'] = (int) $value; + break; + case 'since_id': + $params['since_id'] = $this->validInteger($value); + break; + case 'max_id': + $params['max_id'] = $this->validInteger($value); + break; + case 'trim_user': + if (in_array($value, array(true, 'true', 't', 1, '1'))) { + $value = true; + } else { + $value = false; + } + $params['trim_user'] = $value; + break; + case 'contributor_details:': + $params['contributor_details:'] = (bool) $value; + break; + case 'include_entities': + $params['include_entities'] = (bool) $value; + break; + case 'exclude_replies': + $params['exclude_replies'] = (bool) $value; + break; + default: + break; + } + } + $response = $this->get($path, $params); + return new Zend_Service_Twitter_Response($response); + } + + /** + * Get status replies + * + * $options may include one or more of the following keys + * - count: number of tweets to attempt to retrieve, up to 200 + * - since_id: return results only after the specified tweet id + * - max_id: return results with an ID less than (older than) or equal to the specified ID + * - trim_user: when set to true, "t", or 1, user object in tweets will include only author's ID. + * - contributor_details: when set to true, includes screen_name of each contributor + * - include_entities: when set to false, entities member will be omitted + * + * @param array $options + * @throws Zend_Http_Client_Exception if HTTP request fails or times out + * @throws Exception\DomainException if unable to decode JSON payload + * @return Zend_Service_Twitter_Response + */ + public function statusesMentionsTimeline(array $options = array()) + { + $this->init(); + $path = 'statuses/mentions_timeline'; + $params = array(); + foreach ($options as $key => $value) { + switch (strtolower($key)) { + case 'count': + $params['count'] = (int) $value; + break; + case 'since_id': + $params['since_id'] = $this->validInteger($value); + break; + case 'max_id': + $params['max_id'] = $this->validInteger($value); + break; + case 'trim_user': + if (in_array($value, array(true, 'true', 't', 1, '1'))) { + $value = true; + } else { + $value = false; + } + $params['trim_user'] = $value; + break; + case 'contributor_details:': + $params['contributor_details:'] = (bool) $value; + break; + case 'include_entities': + $params['include_entities'] = (bool) $value; + break; + default: + break; + } + } + $response = $this->get($path, $params); + return new Zend_Service_Twitter_Response($response); + } + + /** + * Public Timeline status + * + * @throws Zend_Http_Client_Exception if HTTP request fails or times out + * @throws Exception\DomainException if unable to decode JSON payload + * @return Zend_Service_Twitter_Response + */ + public function statusesSample() + { + $this->init(); + $path = 'statuses/sample'; + $response = $this->get($path); + return new Zend_Service_Twitter_Response($response); + } + + /** + * Show a single status + * + * @param int $id Id of status to show + * @throws Zend_Http_Client_Exception if HTTP request fails or times out + * @throws Exception\DomainException if unable to decode JSON payload + * @return Zend_Service_Twitter_Response + */ + public function statusesShow($id) + { + $this->init(); + $path = 'statuses/show/' . $this->validInteger($id); + $response = $this->get($path); + return new Zend_Service_Twitter_Response($response); + } + + /** + * Update user's current status + * + * @todo Support additional parameters supported by statuses/update endpoint + * @param string $status + * @param null|int $inReplyToStatusId + * @throws Zend_Http_Client_Exception if HTTP request fails or times out + * @throws Exception\OutOfRangeException if message is too long + * @throws Exception\InvalidArgumentException if message is empty + * @throws Exception\DomainException if unable to decode JSON payload + * @return Zend_Service_Twitter_Response + */ + public function statusesUpdate($status, $inReplyToStatusId = null) + { + $this->init(); + $path = 'statuses/update'; + $len = iconv_strlen(htmlspecialchars($status, ENT_QUOTES, 'UTF-8'), 'UTF-8'); + if ($len > self::STATUS_MAX_CHARACTERS) { + require_once 'Zend/Service/Twitter/Exception.php'; + throw new Zend_Service_Twitter_Exception( + 'Status must be no more than ' + . self::STATUS_MAX_CHARACTERS + . ' characters in length' + ); + } elseif (0 == $len) { + require_once 'Zend/Service/Twitter/Exception.php'; + throw new Zend_Service_Twitter_Exception( + 'Status must contain at least one character' + ); + } + + $params = array('status' => $status); + $inReplyToStatusId = $this->validInteger($inReplyToStatusId); + if ($inReplyToStatusId) { + $params['in_reply_to_status_id'] = $inReplyToStatusId; + } + $response = $this->post($path, $params); + return new Zend_Service_Twitter_Response($response); + } + + /** + * User Timeline status + * + * $options may include one or more of the following keys + * - user_id: Id of a user for whom to fetch favorites + * - screen_name: Screen name of a user for whom to fetch favorites + * - count: number of tweets to attempt to retrieve, up to 200 + * - since_id: return results only after the specified tweet id + * - max_id: return results with an ID less than (older than) or equal to the specified ID + * - trim_user: when set to true, "t", or 1, user object in tweets will include only author's ID. + * - exclude_replies: when set to true, will strip replies appearing in the timeline + * - contributor_details: when set to true, includes screen_name of each contributor + * - include_rts: when set to false, will strip native retweets + * + * @throws Zend_Http_Client_Exception if HTTP request fails or times out + * @throws Exception\DomainException if unable to decode JSON payload + * @return Zend_Service_Twitter_Response + */ + public function statusesUserTimeline(array $options = array()) + { + $this->init(); + $path = 'statuses/user_timeline'; + $params = array(); + foreach ($options as $key => $value) { + switch (strtolower($key)) { + case 'user_id': + $params['user_id'] = $this->validInteger($value); + break; + case 'screen_name': + $params['screen_name'] = $this->validateScreenName($value); + break; + case 'count': + $params['count'] = (int) $value; + break; + case 'since_id': + $params['since_id'] = $this->validInteger($value); + break; + case 'max_id': + $params['max_id'] = $this->validInteger($value); + break; + case 'trim_user': + if (in_array($value, array(true, 'true', 't', 1, '1'))) { + $value = true; + } else { + $value = false; + } + $params['trim_user'] = $value; + break; + case 'contributor_details:': + $params['contributor_details:'] = (bool) $value; + break; + case 'exclude_replies': + $params['exclude_replies'] = (bool) $value; + break; + case 'include_rts': + $params['include_rts'] = (bool) $value; + break; + default: + break; + } + } + $response = $this->get($path, $params); + return new Zend_Service_Twitter_Response($response); + } + + /** + * Search users + * + * $options may include any of the following: + * - page: the page of results to retrieve + * - count: the number of users to retrieve per page; max is 20 + * - include_entities: if set to boolean true, include embedded entities + * + * @param string $query + * @param array $options + * @throws Zend_Http_Client_Exception if HTTP request fails or times out + * @throws Exception\DomainException if unable to decode JSON payload + * @return Zend_Service_Twitter_Response + */ + public function usersSearch($query, array $options = array()) + { + $this->init(); + $path = 'users/search'; + + $len = iconv_strlen($query, 'UTF-8'); + if (0 == $len) { + require_once 'Zend/Service/Twitter/Exception.php'; + throw new Zend_Service_Twitter_Exception( + 'Query must contain at least one character' + ); + } + + $params = array('q' => $query); + foreach ($options as $key => $value) { + switch (strtolower($key)) { + case 'count': + $value = (int) $value; + if (1 > $value || 20 < $value) { + require_once 'Zend/Service/Twitter/Exception.php'; + throw new Zend_Service_Twitter_Exception( + 'count must be between 1 and 20' + ); + } + $params['count'] = $value; + break; + case 'page': + $params['page'] = (int) $value; + break; + case 'include_entities': + $params['include_entities'] = (bool) $value; + break; + default: + break; + } + } + $response = $this->get($path, $params); + return new Zend_Service_Twitter_Response($response); + } + + + /** + * Show extended information on a user + * + * @param int|string $id User ID or name + * @throws Zend_Http_Client_Exception if HTTP request fails or times out + * @throws Exception\DomainException if unable to decode JSON payload + * @return Zend_Service_Twitter_Response + */ + public function usersShow($id) + { + $this->init(); + $path = 'users/show'; + $params = $this->createUserParameter($id, array()); + $response = $this->get($path, $params); + return new Zend_Service_Twitter_Response($response); + } + + /** + * Initialize HTTP authentication + * + * @return void + * @throws Exception\DomainException if unauthorised + */ + protected function init() + { + if (!$this->isAuthorised() && $this->getUsername() !== null) { + require_once 'Zend/Service/Twitter/Exception.php'; + throw new Zend_Service_Twitter_Exception( + 'Twitter session is unauthorised. You need to initialize ' + . __CLASS__ . ' with an OAuth Access Token or use ' + . 'its OAuth functionality to obtain an Access Token before ' + . 'attempting any API actions that require authorisation' + ); + } + $client = $this->getHttpClient(); + $client->resetParameters(); + if (null === $this->cookieJar) { + $cookieJar = $client->getCookieJar(); + if (null === $cookieJar) { + $cookieJar = new Zend_Http_CookieJar(); + } + $this->cookieJar = $cookieJar; + $this->cookieJar->reset(); + } else { + $client->setCookieJar($this->cookieJar); } - $path .= '.xml'; - $response = $this->_get($path, array('page' => $page)); - return new Zend_Rest_Client_Result($response->getBody()); } /** * Protected function to validate that the integer is valid or return a 0 - * @param $int + * + * @param $int * @throws Zend_Http_Client_Exception if HTTP request fails or times out * @return integer */ - protected function _validInteger($int) + protected function validInteger($int) { if (preg_match("/(\d+)/", $int)) { return $int; @@ -931,10 +1197,10 @@ class Zend_Service_Twitter extends Zend_Rest_Client * Validate a screen name using Twitter rules * * @param string $name - * @throws Zend_Service_Twitter_Exception * @return string + * @throws Exception\InvalidArgumentException */ - protected function _validateScreenName($name) + protected function validateScreenName($name) { if (!preg_match('/^[a-zA-Z0-9_]{0,20}$/', $name)) { require_once 'Zend/Service/Twitter/Exception.php'; @@ -947,36 +1213,21 @@ class Zend_Service_Twitter extends Zend_Rest_Client } /** - * Call a remote REST web service URI and return the Zend_Http_Response object + * Call a remote REST web service URI * - * @param string $path The path to append to the URI - * @throws Zend_Rest_Client_Exception + * @param string $path The path to append to the URI + * @param Zend_Http_Client $client + * @throws Zend_Http_Client_Exception * @return void */ - protected function _prepare($path) + protected function prepare($path, Zend_Http_Client $client) { - // Get the URI object and configure it - if (!$this->_uri instanceof Zend_Uri_Http) { - require_once 'Zend/Rest/Client/Exception.php'; - throw new Zend_Rest_Client_Exception( - 'URI object must be set before performing call' - ); - } - - $uri = $this->_uri->getUri(); - - if ($path[0] != '/' && $uri[strlen($uri) - 1] != '/') { - $path = '/' . $path; - } - - $this->_uri->setPath($path); + $client->setUri(self::API_BASE_URI . $path . '.json'); /** - * Get the HTTP client and configure it for the endpoint URI. - * Do this each time because the Zend_Http_Client instance is shared - * among all Zend_Service_Abstract subclasses. + * Do this each time to ensure oauth calls do not inject new params */ - $this->_localHttpClient->resetParameters()->setUri((string) $this->_uri); + $client->resetParameters(); } /** @@ -987,11 +1238,13 @@ class Zend_Service_Twitter extends Zend_Rest_Client * @throws Zend_Http_Client_Exception * @return Zend_Http_Response */ - protected function _get($path, array $query = null) + protected function get($path, array $query = array()) { - $this->_prepare($path); - $this->_localHttpClient->setParameterGet($query); - return $this->_localHttpClient->request(Zend_Http_Client::GET); + $client = $this->getHttpClient(); + $this->prepare($path, $client); + $client->setParameterGet($query); + $response = $client->request(Zend_Http_Client::GET); + return $response; } /** @@ -1002,10 +1255,12 @@ class Zend_Service_Twitter extends Zend_Rest_Client * @throws Zend_Http_Client_Exception * @return Zend_Http_Response */ - protected function _post($path, $data = null) + protected function post($path, $data = null) { - $this->_prepare($path); - return $this->_performPost(Zend_Http_Client::POST, $data); + $client = $this->getHttpClient(); + $this->prepare($path, $client); + $response = $this->performPost(Zend_Http_Client::POST, $data, $client); + return $response; } /** @@ -1019,9 +1274,8 @@ class Zend_Service_Twitter extends Zend_Rest_Client * @param mixed $data * @return Zend_Http_Response */ - protected function _performPost($method, $data = null) + protected function performPost($method, $data, Zend_Http_Client $client) { - $client = $this->_localHttpClient; if (is_string($data)) { $client->setRawData($data); } elseif (is_array($data) || is_object($data)) { @@ -1030,4 +1284,24 @@ class Zend_Service_Twitter extends Zend_Rest_Client return $client->request($method); } + /** + * Create a parameter representing the user + * + * Determines if $id is an integer, and, if so, sets the "user_id" parameter. + * If not, assumes the $id is the "screen_name". + * + * @param int|string $id + * @param array $params + * @return array + */ + protected function createUserParameter($id, array $params) + { + if ($this->validInteger($id)) { + $params['user_id'] = $id; + return $params; + } + + $params['screen_name'] = $this->validateScreenName($id); + return $params; + } } diff --git a/lib/zend/Zend/Service/Twitter/Exception.php b/lib/zend/Zend/Service/Twitter/Exception.php old mode 100644 new mode 100755 index 06fc25ef2df..742f14418f9 --- a/lib/zend/Zend/Service/Twitter/Exception.php +++ b/lib/zend/Zend/Service/Twitter/Exception.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Service * @subpackage Twitter - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -29,7 +29,7 @@ require_once 'Zend/Service/Exception.php'; * @category Zend * @package Zend_Service * @subpackage Twitter - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Service_Twitter_Exception extends Zend_Service_Exception diff --git a/lib/zend/Zend/Service/Twitter/Response.php b/lib/zend/Zend/Service/Twitter/Response.php new file mode 100644 index 00000000000..23f994dab5e --- /dev/null +++ b/lib/zend/Zend/Service/Twitter/Response.php @@ -0,0 +1,179 @@ +httpResponse = $httpResponse; + $this->rawBody = $httpResponse->getBody(); + try { + $jsonBody = Zend_Json::decode($this->rawBody, Zend_Json::TYPE_OBJECT); + $this->jsonBody = $jsonBody; + } catch (Zend_Json_Exception $e) { + require_once 'Zend/Service/Twitter/Exception.php'; + throw new Zend_Service_Twitter_Exception(sprintf( + 'Unable to decode response from twitter: %s', + $e->getMessage() + ), 0, $e); + } + } + + /** + * Property overloading to JSON elements + * + * If a named property exists within the JSON response returned, + * proxies to it. Otherwise, returns null. + * + * @param string $name + * @return mixed + */ + public function __get($name) + { + if (null === $this->jsonBody) { + return null; + } + if (!isset($this->jsonBody->{$name})) { + return null; + } + return $this->jsonBody->{$name}; + } + + /** + * Was the request successful? + * + * @return bool + */ + public function isSuccess() + { + return $this->httpResponse->isSuccessful(); + } + + /** + * Did an error occur in the request? + * + * @return bool + */ + public function isError() + { + return !$this->httpResponse->isSuccessful(); + } + + /** + * Retrieve the errors. + * + * Twitter _should_ return a standard error object, which contains an + * "errors" property pointing to an array of errors. This method will + * return that array if present, and raise an exception if not detected. + * + * If the response was successful, an empty array is returned. + * + * @return array + * @throws Exception\DomainException if unable to detect structure of error response + */ + public function getErrors() + { + if (!$this->isError()) { + return array(); + } + if (null === $this->jsonBody + || !isset($this->jsonBody->errors) + ) { + require_once 'Zend/Service/Twitter/Exception.php'; + throw new Zend_Service_Twitter_Exception( + 'Either no JSON response received, or JSON error response is malformed; cannot return errors' + ); + } + return $this->jsonBody->errors; + } + + /** + * Retrieve the raw response body + * + * @return string + */ + public function getRawResponse() + { + return $this->rawBody; + } + + /** + * Retun the decoded response body + * + * @return array|stdClass + */ + public function toValue() + { + return $this->jsonBody; + } +} diff --git a/lib/zend/Zend/Service/Twitter/Search.php b/lib/zend/Zend/Service/Twitter/Search.php deleted file mode 100644 index f20961e94a2..00000000000 --- a/lib/zend/Zend/Service/Twitter/Search.php +++ /dev/null @@ -1,167 +0,0 @@ -setResponseType($responseType); - $this->setUri("http://search.twitter.com"); - - $this->setHeaders('Accept-Charset', 'ISO-8859-1,utf-8'); - } - - /** - * set responseType - * - * @param string $responseType - * @throws Zend_Service_Twitter_Exception - * @return Zend_Service_Twitter_Search - */ - public function setResponseType($responseType = 'json') - { - if(!in_array($responseType, $this->_responseTypes, TRUE)) { - require_once 'Zend/Service/Twitter/Exception.php'; - throw new Zend_Service_Twitter_Exception('Invalid Response Type'); - } - $this->_responseType = $responseType; - return $this; - } - - /** - * Retrieve responseType - * - * @return string - */ - public function getResponseType() - { - return $this->_responseType; - } - - /** - * Get the current twitter trends. Currnetly only supports json as the return. - * - * @throws Zend_Http_Client_Exception - * @return array - */ - public function trends() - { - $response = $this->restGet('/trends.json'); - - return Zend_Json::decode($response->getBody()); - } - - /** - * Performs a Twitter search query. - * - * @throws Zend_Http_Client_Exception - */ - public function search($query, array $params = array()) - { - - $_query = array(); - - $_query['q'] = $query; - - foreach($params as $key=>$param) { - switch($key) { - case 'geocode': - case 'lang': - case 'since_id': - $_query[$key] = $param; - break; - case 'rpp': - $_query[$key] = (intval($param) > 100) ? 100 : intval($param); - break; - case 'page': - $_query[$key] = intval($param); - break; - case 'show_user': - $_query[$key] = 'true'; - } - } - - $response = $this->restGet('/search.' . $this->_responseType, $_query); - - switch($this->_responseType) { - case 'json': - return Zend_Json::decode($response->getBody()); - break; - case 'atom': - return Zend_Feed::importString($response->getBody()); - break; - } - - return ; - } -} diff --git a/lib/zend/Zend/Service/WindowsAzure/Credentials/CredentialsAbstract.php b/lib/zend/Zend/Service/WindowsAzure/Credentials/CredentialsAbstract.php deleted file mode 100644 index 1af258269bf..00000000000 --- a/lib/zend/Zend/Service/WindowsAzure/Credentials/CredentialsAbstract.php +++ /dev/null @@ -1,197 +0,0 @@ -_accountName = $accountName; - $this->_accountKey = base64_decode($accountKey); - $this->_usePathStyleUri = $usePathStyleUri; - } - - /** - * Set account name for Windows Azure - * - * @param string $value - * @return Zend_Service_WindowsAzure_Credentials_CredentialsAbstract - */ - public function setAccountName($value = Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_ACCOUNT) - { - $this->_accountName = $value; - return $this; - } - - /** - * Set account key for Windows Azure - * - * @param string $value - * @return Zend_Service_WindowsAzure_Credentials_CredentialsAbstract - */ - public function setAccountkey($value = Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_KEY) - { - $this->_accountKey = base64_decode($value); - return $this; - } - - /** - * Set use path-style URI's - * - * @param boolean $value - * @return Zend_Service_WindowsAzure_Credentials_CredentialsAbstract - */ - public function setUsePathStyleUri($value = false) - { - $this->_usePathStyleUri = $value; - return $this; - } - - /** - * Sign request URL with credentials - * - * @param string $requestUrl Request URL - * @param string $resourceType Resource type - * @param string $requiredPermission Required permission - * @return string Signed request URL - */ - abstract public function signRequestUrl( - $requestUrl = '', - $resourceType = Zend_Service_WindowsAzure_Storage::RESOURCE_UNKNOWN, - $requiredPermission = Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ - ); - - /** - * Sign request headers with credentials - * - * @param string $httpVerb HTTP verb the request will use - * @param string $path Path for the request - * @param string $queryString Query string for the request - * @param array $headers x-ms headers to add - * @param boolean $forTableStorage Is the request for table storage? - * @param string $resourceType Resource type - * @param string $requiredPermission Required permission - * @return array Array of headers - */ - abstract public function signRequestHeaders( - $httpVerb = Zend_Http_Client::GET, - $path = '/', - $queryString = '', - $headers = null, - $forTableStorage = false, - $resourceType = Zend_Service_WindowsAzure_Storage::RESOURCE_UNKNOWN, - $requiredPermission = Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ - ); - - - /** - * Prepare query string for signing - * - * @param string $value Original query string - * @return string Query string for signing - */ - protected function _prepareQueryStringForSigning($value) - { - // Check for 'comp=' - if (strpos($value, 'comp=') === false) { - // If not found, no query string needed - return ''; - } else { - // If found, make sure it is the only parameter being used - if (strlen($value) > 0 && strpos($value, '?') === 0) { - $value = substr($value, 1); - } - - // Split parts - $queryParts = explode('&', $value); - foreach ($queryParts as $queryPart) { - if (strpos($queryPart, 'comp=') !== false) { - return '?' . $queryPart; - } - } - - // Should never happen... - return ''; - } - } -} diff --git a/lib/zend/Zend/Service/WindowsAzure/Credentials/SharedAccessSignature.php b/lib/zend/Zend/Service/WindowsAzure/Credentials/SharedAccessSignature.php deleted file mode 100644 index f3134a96693..00000000000 --- a/lib/zend/Zend/Service/WindowsAzure/Credentials/SharedAccessSignature.php +++ /dev/null @@ -1,305 +0,0 @@ -_permissionSet = $permissionSet; - } - - /** - * Get permission set - * - * @return array - */ - public function getPermissionSet() - { - return $this->_permissionSet; - } - - /** - * Set permisison set - * - * Warning: fine-grained permissions should be added prior to coarse-grained permissions. - * For example: first add blob permissions, end with container-wide permissions. - * - * Warning: the signed access signature URL must match the account name of the - * Zend_Service_WindowsAzure_Credentials_Zend_Service_WindowsAzure_Credentials_SharedAccessSignature instance - * - * @param array $value Permission set - * @return void - */ - public function setPermissionSet($value = array()) - { - foreach ($value as $url) { - if (strpos($url, $this->_accountName) === false) { - throw new Zend_Service_WindowsAzure_Exception('The permission set can only contain URLs for the account name specified in the Zend_Service_WindowsAzure_Credentials_SharedAccessSignature instance.'); - } - } - $this->_permissionSet = $value; - } - - /** - * Create signature - * - * @param string $path Path for the request - * @param string $resource Signed resource - container (c) - blob (b) - * @param string $permissions Signed permissions - read (r), write (w), delete (d) and list (l) - * @param string $start The time at which the Shared Access Signature becomes valid. - * @param string $expiry The time at which the Shared Access Signature becomes invalid. - * @param string $identifier Signed identifier - * @return string - */ - public function createSignature( - $path = '/', - $resource = 'b', - $permissions = 'r', - $start = '', - $expiry = '', - $identifier = '' - ) { - // Determine path - if ($this->_usePathStyleUri) { - $path = substr($path, strpos($path, '/')); - } - - // Add trailing slash to $path - if (substr($path, 0, 1) !== '/') { - $path = '/' . $path; - } - - // Build canonicalized resource string - $canonicalizedResource = '/' . $this->_accountName; - /*if ($this->_usePathStyleUri) { - $canonicalizedResource .= '/' . $this->_accountName; - }*/ - $canonicalizedResource .= $path; - - // Create string to sign - $stringToSign = array(); - $stringToSign[] = $permissions; - $stringToSign[] = $start; - $stringToSign[] = $expiry; - $stringToSign[] = $canonicalizedResource; - $stringToSign[] = $identifier; - - $stringToSign = implode("\n", $stringToSign); - $signature = base64_encode(hash_hmac('sha256', $stringToSign, $this->_accountKey, true)); - - return $signature; - } - - /** - * Create signed query string - * - * @param string $path Path for the request - * @param string $queryString Query string for the request - * @param string $resource Signed resource - container (c) - blob (b) - * @param string $permissions Signed permissions - read (r), write (w), delete (d) and list (l) - * @param string $start The time at which the Shared Access Signature becomes valid. - * @param string $expiry The time at which the Shared Access Signature becomes invalid. - * @param string $identifier Signed identifier - * @return string - */ - public function createSignedQueryString( - $path = '/', - $queryString = '', - $resource = 'b', - $permissions = 'r', - $start = '', - $expiry = '', - $identifier = '' - ) { - // Parts - $parts = array(); - if ($start !== '') { - $parts[] = 'st=' . urlencode($start); - } - $parts[] = 'se=' . urlencode($expiry); - $parts[] = 'sr=' . $resource; - $parts[] = 'sp=' . $permissions; - if ($identifier !== '') { - $parts[] = 'si=' . urlencode($identifier); - } - $parts[] = 'sig=' . urlencode($this->createSignature($path, $resource, $permissions, $start, $expiry, $identifier)); - - // Assemble parts and query string - if ($queryString != '') { - $queryString .= '&'; - } - $queryString .= implode('&', $parts); - - return $queryString; - } - - /** - * Permission matches request? - * - * @param string $permissionUrl Permission URL - * @param string $requestUrl Request URL - * @param string $resourceType Resource type - * @param string $requiredPermission Required permission - * @return string Signed request URL - */ - public function permissionMatchesRequest( - $permissionUrl = '', - $requestUrl = '', - $resourceType = Zend_Service_WindowsAzure_Storage::RESOURCE_UNKNOWN, - $requiredPermission = Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ - ) { - // Build requirements - $requiredResourceType = $resourceType; - if ($requiredResourceType == Zend_Service_WindowsAzure_Storage::RESOURCE_BLOB) { - $requiredResourceType .= Zend_Service_WindowsAzure_Storage::RESOURCE_CONTAINER; - } - - // Parse permission url - $parsedPermissionUrl = parse_url($permissionUrl); - - // Parse permission properties - $permissionParts = explode('&', $parsedPermissionUrl['query']); - - // Parse request url - $parsedRequestUrl = parse_url($requestUrl); - - // Check if permission matches request - $matches = true; - foreach ($permissionParts as $part) { - list($property, $value) = explode('=', $part, 2); - - if ($property == 'sr') { - $matches = $matches && (strpbrk($value, $requiredResourceType) !== false); - } - - if ($property == 'sp') { - $matches = $matches && (strpbrk($value, $requiredPermission) !== false); - } - } - - // Ok, but... does the resource match? - $matches = $matches && (strpos($parsedRequestUrl['path'], $parsedPermissionUrl['path']) !== false); - - // Return - return $matches; - } - - /** - * Sign request URL with credentials - * - * @param string $requestUrl Request URL - * @param string $resourceType Resource type - * @param string $requiredPermission Required permission - * @return string Signed request URL - */ - public function signRequestUrl( - $requestUrl = '', - $resourceType = Zend_Service_WindowsAzure_Storage::RESOURCE_UNKNOWN, - $requiredPermission = Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ - ) { - // Look for a matching permission - foreach ($this->getPermissionSet() as $permittedUrl) { - if ($this->permissionMatchesRequest($permittedUrl, $requestUrl, $resourceType, $requiredPermission)) { - // This matches, append signature data - $parsedPermittedUrl = parse_url($permittedUrl); - - if (strpos($requestUrl, '?') === false) { - $requestUrl .= '?'; - } else { - $requestUrl .= '&'; - } - - $requestUrl .= $parsedPermittedUrl['query']; - - // Return url - return $requestUrl; - } - } - - // Return url, will be unsigned... - return $requestUrl; - } - - /** - * Sign request with credentials - * - * @param string $httpVerb HTTP verb the request will use - * @param string $path Path for the request - * @param string $queryString Query string for the request - * @param array $headers x-ms headers to add - * @param boolean $forTableStorage Is the request for table storage? - * @param string $resourceType Resource type - * @param string $requiredPermission Required permission - * @return array Array of headers - */ - public function signRequestHeaders( - $httpVerb = Zend_Http_Client::GET, - $path = '/', - $queryString = '', - $headers = null, - $forTableStorage = false, - $resourceType = Zend_Service_WindowsAzure_Storage::RESOURCE_UNKNOWN, - $requiredPermission = Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ - ) { - return $headers; - } -} diff --git a/lib/zend/Zend/Service/WindowsAzure/Credentials/SharedKey.php b/lib/zend/Zend/Service/WindowsAzure/Credentials/SharedKey.php deleted file mode 100644 index df9836d36f1..00000000000 --- a/lib/zend/Zend/Service/WindowsAzure/Credentials/SharedKey.php +++ /dev/null @@ -1,154 +0,0 @@ -_usePathStyleUri) { - $path = substr($path, strpos($path, '/')); - } - - // Determine query - $queryString = $this->_prepareQueryStringForSigning($queryString); - - // Canonicalized headers - $canonicalizedHeaders = array(); - - // Request date - $requestDate = ''; - if (isset($headers[Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PREFIX_STORAGE_HEADER . 'date'])) { - $requestDate = $headers[Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PREFIX_STORAGE_HEADER . 'date']; - } else { - $requestDate = gmdate('D, d M Y H:i:s', time()) . ' GMT'; // RFC 1123 - $canonicalizedHeaders[] = Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PREFIX_STORAGE_HEADER . 'date:' . $requestDate; - } - - // Build canonicalized headers - if (!is_null($headers)) { - foreach ($headers as $header => $value) { - if (is_bool($value)) { - $value = $value === true ? 'True' : 'False'; - } - - $headers[$header] = $value; - if (substr($header, 0, strlen(Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PREFIX_STORAGE_HEADER)) == Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PREFIX_STORAGE_HEADER) { - $canonicalizedHeaders[] = strtolower($header) . ':' . $value; - } - } - } - sort($canonicalizedHeaders); - - // Build canonicalized resource string - $canonicalizedResource = '/' . $this->_accountName; - if ($this->_usePathStyleUri) { - $canonicalizedResource .= '/' . $this->_accountName; - } - $canonicalizedResource .= $path; - if ($queryString !== '') { - $canonicalizedResource .= $queryString; - } - - // Create string to sign - $stringToSign = array(); - $stringToSign[] = strtoupper($httpVerb); // VERB - $stringToSign[] = ""; // Content-MD5 - $stringToSign[] = ""; // Content-Type - $stringToSign[] = ""; - // Date already in $canonicalizedHeaders - // $stringToSign[] = self::PREFIX_STORAGE_HEADER . 'date:' . $requestDate; // Date - - if (!$forTableStorage && count($canonicalizedHeaders) > 0) { - $stringToSign[] = implode("\n", $canonicalizedHeaders); // Canonicalized headers - } - - $stringToSign[] = $canonicalizedResource; // Canonicalized resource - $stringToSign = implode("\n", $stringToSign); - $signString = base64_encode(hash_hmac('sha256', $stringToSign, $this->_accountKey, true)); - - // Sign request - $headers[Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PREFIX_STORAGE_HEADER . 'date'] = $requestDate; - $headers['Authorization'] = 'SharedKey ' . $this->_accountName . ':' . $signString; - - // Return headers - return $headers; - } -} diff --git a/lib/zend/Zend/Service/WindowsAzure/Credentials/SharedKeyLite.php b/lib/zend/Zend/Service/WindowsAzure/Credentials/SharedKeyLite.php deleted file mode 100644 index c880ad35673..00000000000 --- a/lib/zend/Zend/Service/WindowsAzure/Credentials/SharedKeyLite.php +++ /dev/null @@ -1,123 +0,0 @@ -_usePathStyleUri) { - $path = substr($path, strpos($path, '/')); - } - - // Determine query - $queryString = $this->_prepareQueryStringForSigning($queryString); - - // Build canonicalized resource string - $canonicalizedResource = '/' . $this->_accountName; - if ($this->_usePathStyleUri) { - $canonicalizedResource .= '/' . $this->_accountName; - } - $canonicalizedResource .= $path; - if ($queryString !== '') { - $canonicalizedResource .= $queryString; - } - - // Request date - $requestDate = ''; - if (isset($headers[Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PREFIX_STORAGE_HEADER . 'date'])) { - $requestDate = $headers[Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PREFIX_STORAGE_HEADER . 'date']; - } else { - $requestDate = gmdate('D, d M Y H:i:s', time()) . ' GMT'; // RFC 1123 - } - - // Create string to sign - $stringToSign = array(); - $stringToSign[] = $requestDate; // Date - $stringToSign[] = $canonicalizedResource; // Canonicalized resource - $stringToSign = implode("\n", $stringToSign); - $signString = base64_encode(hash_hmac('sha256', $stringToSign, $this->_accountKey, true)); - - // Sign request - $headers[Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PREFIX_STORAGE_HEADER . 'date'] = $requestDate; - $headers['Authorization'] = 'SharedKeyLite ' . $this->_accountName . ':' . $signString; - - // Return headers - return $headers; - } -} diff --git a/lib/zend/Zend/Service/WindowsAzure/RetryPolicy/Exception.php b/lib/zend/Zend/Service/WindowsAzure/RetryPolicy/Exception.php deleted file mode 100644 index 1d42a7926ce..00000000000 --- a/lib/zend/Zend/Service/WindowsAzure/RetryPolicy/Exception.php +++ /dev/null @@ -1,36 +0,0 @@ -_retryCount = $count; - $this->_retryInterval = $intervalBetweenRetries; - } - - /** - * Execute function under retry policy - * - * @param string|array $function Function to execute - * @param array $parameters Parameters for function call - * @return mixed - */ - public function execute($function, $parameters = array()) - { - $returnValue = null; - - for ($retriesLeft = $this->_retryCount; $retriesLeft >= 0; --$retriesLeft) { - try { - $returnValue = call_user_func_array($function, $parameters); - return $returnValue; - } catch (Exception $ex) { - if ($retriesLeft == 1) { - throw new Zend_Service_WindowsAzure_RetryPolicy_Exception("Exceeded retry count of " . $this->_retryCount . ". " . $ex->getMessage()); - } - - usleep($this->_retryInterval * 1000); - } - } - } -} \ No newline at end of file diff --git a/lib/zend/Zend/Service/WindowsAzure/RetryPolicy/RetryPolicyAbstract.php b/lib/zend/Zend/Service/WindowsAzure/RetryPolicy/RetryPolicyAbstract.php deleted file mode 100644 index e3a48764be4..00000000000 --- a/lib/zend/Zend/Service/WindowsAzure/RetryPolicy/RetryPolicyAbstract.php +++ /dev/null @@ -1,77 +0,0 @@ -_tableStorage = $tableStorage; - $this->_sessionTable = $sessionTable; - $this->_sessionTablePartition = $sessionTablePartition; - } - - /** - * Registers the current session handler as PHP's session handler - * - * @return boolean - */ - public function register() - { - return session_set_save_handler(array($this, 'open'), - array($this, 'close'), - array($this, 'read'), - array($this, 'write'), - array($this, 'destroy'), - array($this, 'gc') - ); - } - - /** - * Open the session store - * - * @return bool - */ - public function open() - { - // Make sure table exists - $tableExists = $this->_tableStorage->tableExists($this->_sessionTable); - if (!$tableExists) { - $this->_tableStorage->createTable($this->_sessionTable); - } - - // Ok! - return true; - } - - /** - * Close the session store - * - * @return bool - */ - public function close() - { - return true; - } - - /** - * Read a specific session - * - * @param int $id Session Id - * @return string - */ - public function read($id) - { - try - { - $sessionRecord = $this->_tableStorage->retrieveEntityById( - $this->_sessionTable, - $this->_sessionTablePartition, - $id - ); - return base64_decode($sessionRecord->serializedData); - } - catch (Zend_Service_WindowsAzure_Exception $ex) - { - return ''; - } - } - - /** - * Write a specific session - * - * @param int $id Session Id - * @param string $serializedData Serialized PHP object - */ - public function write($id, $serializedData) - { - $sessionRecord = new Zend_Service_WindowsAzure_Storage_DynamicTableEntity($this->_sessionTablePartition, $id); - $sessionRecord->sessionExpires = time(); - $sessionRecord->serializedData = base64_encode($serializedData); - - $sessionRecord->setAzurePropertyType('sessionExpires', 'Edm.Int32'); - - try - { - $this->_tableStorage->updateEntity($this->_sessionTable, $sessionRecord); - } - catch (Zend_Service_WindowsAzure_Exception $unknownRecord) - { - $this->_tableStorage->insertEntity($this->_sessionTable, $sessionRecord); - } - } - - /** - * Destroy a specific session - * - * @param int $id Session Id - * @return boolean - */ - public function destroy($id) - { - try - { - $sessionRecord = $this->_tableStorage->retrieveEntityById( - $this->_sessionTable, - $this->_sessionTablePartition, - $id - ); - $this->_tableStorage->deleteEntity($this->_sessionTable, $sessionRecord); - - return true; - } - catch (Zend_Service_WindowsAzure_Exception $ex) - { - return false; - } - } - - /** - * Garbage collector - * - * @param int $lifeTime Session maximal lifetime - * @see session.gc_divisor 100 - * @see session.gc_maxlifetime 1440 - * @see session.gc_probability 1 - * @usage Execution rate 1/100 (session.gc_probability/session.gc_divisor) - * @return boolean - */ - public function gc($lifeTime) - { - try - { - $result = $this->_tableStorage->retrieveEntities($this->_sessionTable, 'PartitionKey eq \'' . $this->_sessionTablePartition . '\' and sessionExpires lt ' . (time() - $lifeTime)); - foreach ($result as $sessionRecord) - { - $this->_tableStorage->deleteEntity($this->_sessionTable, $sessionRecord); - } - return true; - } - catch (Zend_Service_WindowsAzure_exception $ex) - { - return false; - } - } -} diff --git a/lib/zend/Zend/Service/WindowsAzure/Storage.php b/lib/zend/Zend/Service/WindowsAzure/Storage.php deleted file mode 100644 index a2448c2d91c..00000000000 --- a/lib/zend/Zend/Service/WindowsAzure/Storage.php +++ /dev/null @@ -1,507 +0,0 @@ -_host = $host; - $this->_accountName = $accountName; - $this->_accountKey = $accountKey; - $this->_usePathStyleUri = $usePathStyleUri; - - // Using local storage? - if (!$this->_usePathStyleUri - && ($this->_host == self::URL_DEV_BLOB - || $this->_host == self::URL_DEV_QUEUE - || $this->_host == self::URL_DEV_TABLE) - ) { - // Local storage - $this->_usePathStyleUri = true; - } - - if (is_null($this->_credentials)) { - $this->_credentials = new Zend_Service_WindowsAzure_Credentials_SharedKey( - $this->_accountName, $this->_accountKey, $this->_usePathStyleUri); - } - - $this->_retryPolicy = $retryPolicy; - if (is_null($this->_retryPolicy)) { - $this->_retryPolicy = Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract::noRetry(); - } - - // Setup default Zend_Http_Client channel - $options = array( - 'adapter' => 'Zend_Http_Client_Adapter_Proxy' - ); - if (function_exists('curl_init')) { - // Set cURL options if cURL is used afterwards - $options['curloptions'] = array( - CURLOPT_FOLLOWLOCATION => true, - CURLOPT_TIMEOUT => 120, - ); - } - $this->_httpClientChannel = new Zend_Http_Client(null, $options); - } - - /** - * Set the HTTP client channel to use - * - * @param Zend_Http_Client_Adapter_Interface|string $adapterInstance Adapter instance or adapter class name. - */ - public function setHttpClientChannel($adapterInstance = 'Zend_Http_Client_Adapter_Proxy') - { - $this->_httpClientChannel->setAdapter($adapterInstance); - } - - /** - * Set retry policy to use when making requests - * - * @param Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy Retry policy to use when making requests - */ - public function setRetryPolicy(Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy = null) - { - $this->_retryPolicy = $retryPolicy; - if (is_null($this->_retryPolicy)) { - $this->_retryPolicy = Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract::noRetry(); - } - } - - /** - * Set proxy - * - * @param boolean $useProxy Use proxy? - * @param string $proxyUrl Proxy URL - * @param int $proxyPort Proxy port - * @param string $proxyCredentials Proxy credentials - */ - public function setProxy($useProxy = false, $proxyUrl = '', $proxyPort = 80, $proxyCredentials = '') - { - $this->_useProxy = $useProxy; - $this->_proxyUrl = $proxyUrl; - $this->_proxyPort = $proxyPort; - $this->_proxyCredentials = $proxyCredentials; - - if ($this->_useProxy) { - $credentials = explode(':', $this->_proxyCredentials); - if(!isset($credentials[1])) { - $credentials[1] = ''; - } - $this->_httpClientChannel->setConfig(array( - 'proxy_host' => $this->_proxyUrl, - 'proxy_port' => $this->_proxyPort, - 'proxy_user' => $credentials[0], - 'proxy_pass' => $credentials[1], - )); - } else { - $this->_httpClientChannel->setConfig(array( - 'proxy_host' => '', - 'proxy_port' => 8080, - 'proxy_user' => '', - 'proxy_pass' => '', - )); - } - } - - /** - * Returns the Windows Azure account name - * - * @return string - */ - public function getAccountName() - { - return $this->_accountName; - } - - /** - * Get base URL for creating requests - * - * @return string - */ - public function getBaseUrl() - { - if ($this->_usePathStyleUri) { - return 'http://' . $this->_host . '/' . $this->_accountName; - } else { - return 'http://' . $this->_accountName . '.' . $this->_host; - } - } - - /** - * Set Zend_Service_WindowsAzure_Credentials_CredentialsAbstract instance - * - * @param Zend_Service_WindowsAzure_Credentials_CredentialsAbstract $credentials Zend_Service_WindowsAzure_Credentials_CredentialsAbstract instance to use for request signing. - */ - public function setCredentials(Zend_Service_WindowsAzure_Credentials_CredentialsAbstract $credentials) - { - $this->_credentials = $credentials; - $this->_credentials->setAccountName($this->_accountName); - $this->_credentials->setAccountkey($this->_accountKey); - $this->_credentials->setUsePathStyleUri($this->_usePathStyleUri); - } - - /** - * Get Zend_Service_WindowsAzure_Credentials_CredentialsAbstract instance - * - * @return Zend_Service_WindowsAzure_Credentials_CredentialsAbstract - */ - public function getCredentials() - { - return $this->_credentials; - } - - /** - * Perform request using Zend_Http_Client channel - * - * @param string $path Path - * @param string $queryString Query string - * @param string $httpVerb HTTP verb the request will use - * @param array $headers x-ms headers to add - * @param boolean $forTableStorage Is the request for table storage? - * @param mixed $rawData Optional RAW HTTP data to be sent over the wire - * @param string $resourceType Resource type - * @param string $requiredPermission Required permission - * @return Zend_Http_Response - */ - protected function _performRequest( - $path = '/', - $queryString = '', - $httpVerb = Zend_Http_Client::GET, - $headers = array(), - $forTableStorage = false, - $rawData = null, - $resourceType = Zend_Service_WindowsAzure_Storage::RESOURCE_UNKNOWN, - $requiredPermission = Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ - ) { - // Clean path - if (strpos($path, '/') !== 0) { - $path = '/' . $path; - } - - // Clean headers - if (is_null($headers)) { - $headers = array(); - } - - // Ensure cUrl will also work correctly: - // - disable Content-Type if required - // - disable Expect: 100 Continue - if (!isset($headers["Content-Type"])) { - $headers["Content-Type"] = ''; - } - $headers["Expect"]= ''; - - // Add version header - $headers['x-ms-version'] = $this->_apiVersion; - - // URL encoding - $path = self::urlencode($path); - $queryString = self::urlencode($queryString); - - // Generate URL and sign request - $requestUrl = $this->_credentials - ->signRequestUrl($this->getBaseUrl() . $path . $queryString, $resourceType, $requiredPermission); - $requestHeaders = $this->_credentials - ->signRequestHeaders($httpVerb, $path, $queryString, $headers, $forTableStorage, $resourceType, $requiredPermission); - - // Prepare request - $this->_httpClientChannel->resetParameters(true); - $this->_httpClientChannel->setUri($requestUrl); - $this->_httpClientChannel->setHeaders($requestHeaders); - $this->_httpClientChannel->setRawData($rawData); - - // Execute request - $response = $this->_retryPolicy->execute( - array($this->_httpClientChannel, 'request'), - array($httpVerb) - ); - - return $response; - } - - /** - * Parse result from Zend_Http_Response - * - * @param Zend_Http_Response $response Response from HTTP call - * @return object - * @throws Zend_Service_WindowsAzure_Exception - */ - protected function _parseResponse(Zend_Http_Response $response = null) - { - if (is_null($response)) { - throw new Zend_Service_WindowsAzure_Exception('Response should not be null.'); - } - - $xml = @simplexml_load_string($response->getBody()); - - if ($xml !== false) { - // Fetch all namespaces - $namespaces = array_merge($xml->getNamespaces(true), $xml->getDocNamespaces(true)); - - // Register all namespace prefixes - foreach ($namespaces as $prefix => $ns) { - if ($prefix != '') { - $xml->registerXPathNamespace($prefix, $ns); - } - } - } - - return $xml; - } - - /** - * Generate metadata headers - * - * @param array $metadata - * @return HTTP headers containing metadata - */ - protected function _generateMetadataHeaders($metadata = array()) - { - // Validate - if (!is_array($metadata)) { - return array(); - } - - // Return headers - $headers = array(); - foreach ($metadata as $key => $value) { - if (strpos($value, "\r") !== false || strpos($value, "\n") !== false) { - throw new Zend_Service_WindowsAzure_Exception('Metadata cannot contain newline characters.'); - } - $headers["x-ms-meta-" . strtolower($key)] = $value; - } - return $headers; - } - - /** - * Parse metadata errors - * - * @param array $headers HTTP headers containing metadata - * @return array - */ - protected function _parseMetadataHeaders($headers = array()) - { - // Validate - if (!is_array($headers)) { - return array(); - } - - // Return metadata - $metadata = array(); - foreach ($headers as $key => $value) { - if (substr(strtolower($key), 0, 10) == "x-ms-meta-") { - $metadata[str_replace("x-ms-meta-", '', strtolower($key))] = $value; - } - } - return $metadata; - } - - /** - * Generate ISO 8601 compliant date string in UTC time zone - * - * @param int $timestamp - * @return string - */ - public function isoDate($timestamp = null) - { - $tz = @date_default_timezone_get(); - @date_default_timezone_set('UTC'); - - if (is_null($timestamp)) { - $timestamp = time(); - } - - $returnValue = str_replace('+00:00', '.0000000Z', @date('c', $timestamp)); - @date_default_timezone_set($tz); - return $returnValue; - } - - /** - * URL encode function - * - * @param string $value Value to encode - * @return string Encoded value - */ - public static function urlencode($value) - { - return str_replace(' ', '%20', $value); - } -} diff --git a/lib/zend/Zend/Service/WindowsAzure/Storage/Batch.php b/lib/zend/Zend/Service/WindowsAzure/Storage/Batch.php deleted file mode 100644 index 369c5c29692..00000000000 --- a/lib/zend/Zend/Service/WindowsAzure/Storage/Batch.php +++ /dev/null @@ -1,248 +0,0 @@ -_storageClient = $storageClient; - $this->_baseUrl = $baseUrl; - $this->_beginBatch(); - } - - /** - * Get base URL for creating requests - * - * @return string - */ - public function getBaseUrl() - { - return $this->_baseUrl; - } - - /** - * Starts a new batch operation set - * - * @throws Zend_Service_WindowsAzure_Exception - */ - protected function _beginBatch() - { - $this->_storageClient->setCurrentBatch($this); - } - - /** - * Cleanup current batch - */ - protected function _clean() - { - unset($this->_operations); - $this->_storageClient->setCurrentBatch(null); - $this->_storageClient = null; - unset($this); - } - - /** - * Enlist operation in current batch - * - * @param string $path Path - * @param string $queryString Query string - * @param string $httpVerb HTTP verb the request will use - * @param array $headers x-ms headers to add - * @param boolean $forTableStorage Is the request for table storage? - * @param mixed $rawData Optional RAW HTTP data to be sent over the wire - * @throws Zend_Service_WindowsAzure_Exception - */ - public function enlistOperation($path = '/', $queryString = '', $httpVerb = Zend_Http_Client::GET, $headers = array(), $forTableStorage = false, $rawData = null) - { - // Set _forTableStorage - if ($forTableStorage) { - $this->_forTableStorage = true; - } - - // Set _isSingleSelect - if ($httpVerb == Zend_Http_Client::GET) { - if (count($this->_operations) > 0) { - throw new Zend_Service_WindowsAzure_Exception("Select operations can only be performed in an empty batch transaction."); - } - $this->_isSingleSelect = true; - } - - // Clean path - if (strpos($path, '/') !== 0) { - $path = '/' . $path; - } - - // Clean headers - if (is_null($headers)) { - $headers = array(); - } - - // URL encoding - $path = Zend_Service_WindowsAzure_Storage::urlencode($path); - $queryString = Zend_Service_WindowsAzure_Storage::urlencode($queryString); - - // Generate URL - $requestUrl = $this->getBaseUrl() . $path . $queryString; - - // Generate $rawData - if (is_null($rawData)) { - $rawData = ''; - } - - // Add headers - if ($httpVerb != Zend_Http_Client::GET) { - $headers['Content-ID'] = count($this->_operations) + 1; - if ($httpVerb != Zend_Http_Client::DELETE) { - $headers['Content-Type'] = 'application/atom+xml;type=entry'; - } - $headers['Content-Length'] = strlen($rawData); - } - - // Generate $operation - $operation = ''; - $operation .= $httpVerb . ' ' . $requestUrl . ' HTTP/1.1' . "\n"; - foreach ($headers as $key => $value) - { - $operation .= $key . ': ' . $value . "\n"; - } - $operation .= "\n"; - - // Add data - $operation .= $rawData; - - // Store operation - $this->_operations[] = $operation; - } - - /** - * Commit current batch - * - * @return Zend_Http_Response - * @throws Zend_Service_WindowsAzure_Exception - */ - public function commit() - { - // Perform batch - $response = $this->_storageClient->performBatch($this->_operations, $this->_forTableStorage, $this->_isSingleSelect); - - // Dispose - $this->_clean(); - - // Parse response - $errors = null; - preg_match_all('/(.*)<\/message>/', $response->getBody(), $errors); - - // Error? - if (count($errors[2]) > 0) { - throw new Zend_Service_WindowsAzure_Exception('An error has occured while committing a batch: ' . $errors[2][0]); - } - - // Return - return $response; - } - - /** - * Rollback current batch - */ - public function rollback() - { - // Dispose - $this->_clean(); - } - - /** - * Get operation count - * - * @return integer - */ - public function getOperationCount() - { - return count($this->_operations); - } - - /** - * Is single select? - * - * @return boolean - */ - public function isSingleSelect() - { - return $this->_isSingleSelect; - } -} diff --git a/lib/zend/Zend/Service/WindowsAzure/Storage/BatchStorageAbstract.php b/lib/zend/Zend/Service/WindowsAzure/Storage/BatchStorageAbstract.php deleted file mode 100644 index 3a1f7c0117b..00000000000 --- a/lib/zend/Zend/Service/WindowsAzure/Storage/BatchStorageAbstract.php +++ /dev/null @@ -1,193 +0,0 @@ -isInBatch()) { - throw new Zend_Service_WindowsAzure_Exception('Only one batch can be active at a time.'); - } - $this->_currentBatch = $batch; - } - - /** - * Get current batch - * - * @return Zend_Service_WindowsAzure_Storage_Batch - */ - public function getCurrentBatch() - { - return $this->_currentBatch; - } - - /** - * Is there a current batch? - * - * @return boolean - */ - public function isInBatch() - { - return !is_null($this->_currentBatch); - } - - /** - * Starts a new batch operation set - * - * @return Zend_Service_WindowsAzure_Storage_Batch - * @throws Zend_Service_WindowsAzure_Exception - */ - public function startBatch() - { - return new Zend_Service_WindowsAzure_Storage_Batch($this, $this->getBaseUrl()); - } - - /** - * Perform batch using Zend_Http_Client channel, combining all batch operations into one request - * - * @param array $operations Operations in batch - * @param boolean $forTableStorage Is the request for table storage? - * @param boolean $isSingleSelect Is the request a single select statement? - * @param string $resourceType Resource type - * @param string $requiredPermission Required permission - * @return Zend_Http_Response - */ - public function performBatch($operations = array(), $forTableStorage = false, $isSingleSelect = false, $resourceType = Zend_Service_WindowsAzure_Storage::RESOURCE_UNKNOWN, $requiredPermission = Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ) - { - // Generate boundaries - $batchBoundary = 'batch_' . md5(time() . microtime()); - $changesetBoundary = 'changeset_' . md5(time() . microtime()); - - // Set headers - $headers = array(); - - // Add version header - $headers['x-ms-version'] = $this->_apiVersion; - - // Add content-type header - $headers['Content-Type'] = 'multipart/mixed; boundary=' . $batchBoundary; - - // Set path and query string - $path = '/$batch'; - $queryString = ''; - - // Set verb - $httpVerb = Zend_Http_Client::POST; - - // Generate raw data - $rawData = ''; - - // Single select? - if ($isSingleSelect) { - $operation = $operations[0]; - $rawData .= '--' . $batchBoundary . "\n"; - $rawData .= 'Content-Type: application/http' . "\n"; - $rawData .= 'Content-Transfer-Encoding: binary' . "\n\n"; - $rawData .= $operation; - $rawData .= '--' . $batchBoundary . '--'; - } else { - $rawData .= '--' . $batchBoundary . "\n"; - $rawData .= 'Content-Type: multipart/mixed; boundary=' . $changesetBoundary . "\n\n"; - - // Add operations - foreach ($operations as $operation) - { - $rawData .= '--' . $changesetBoundary . "\n"; - $rawData .= 'Content-Type: application/http' . "\n"; - $rawData .= 'Content-Transfer-Encoding: binary' . "\n\n"; - $rawData .= $operation; - } - $rawData .= '--' . $changesetBoundary . '--' . "\n"; - - $rawData .= '--' . $batchBoundary . '--'; - } - - // Generate URL and sign request - $requestUrl = $this->_credentials->signRequestUrl($this->getBaseUrl() . $path . $queryString, $resourceType, $requiredPermission); - $requestHeaders = $this->_credentials->signRequestHeaders($httpVerb, $path, $queryString, $headers, $forTableStorage, $resourceType, $requiredPermission); - - // Prepare request - $this->_httpClientChannel->resetParameters(true); - $this->_httpClientChannel->setUri($requestUrl); - $this->_httpClientChannel->setHeaders($requestHeaders); - $this->_httpClientChannel->setRawData($rawData); - - // Execute request - $response = $this->_retryPolicy->execute( - array($this->_httpClientChannel, 'request'), - array($httpVerb) - ); - - return $response; - } -} diff --git a/lib/zend/Zend/Service/WindowsAzure/Storage/Blob.php b/lib/zend/Zend/Service/WindowsAzure/Storage/Blob.php deleted file mode 100644 index 67d0fe511d9..00000000000 --- a/lib/zend/Zend/Service/WindowsAzure/Storage/Blob.php +++ /dev/null @@ -1,1401 +0,0 @@ -_apiVersion = '2009-07-17'; - - // SharedAccessSignature credentials - $this->_sharedAccessSignatureCredentials = new Zend_Service_WindowsAzure_Credentials_SharedAccessSignature($accountName, $accountKey, $usePathStyleUri); - } - - /** - * Check if a blob exists - * - * @param string $containerName Container name - * @param string $blobName Blob name - * @return boolean - */ - public function blobExists($containerName = '', $blobName = '') - { - if ($containerName === '') { - throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); - } - if (!self::isValidContainerName($containerName)) { - throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.'); - } - if ($blobName === '') { - throw new Zend_Service_WindowsAzure_Exception('Blob name is not specified.'); - } - - // List blobs - $blobs = $this->listBlobs($containerName, $blobName, '', 1); - foreach ($blobs as $blob) { - if ($blob->Name == $blobName) { - return true; - } - } - - return false; - } - - /** - * Check if a container exists - * - * @param string $containerName Container name - * @return boolean - */ - public function containerExists($containerName = '') - { - if ($containerName === '') { - throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); - } - if (!self::isValidContainerName($containerName)) { - throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.'); - } - - // List containers - $containers = $this->listContainers($containerName, 1); - foreach ($containers as $container) { - if ($container->Name == $containerName) { - return true; - } - } - - return false; - } - - /** - * Create container - * - * @param string $containerName Container name - * @param array $metadata Key/value pairs of meta data - * @return object Container properties - * @throws Zend_Service_WindowsAzure_Exception - */ - public function createContainer($containerName = '', $metadata = array()) - { - if ($containerName === '') { - throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); - } - if (!self::isValidContainerName($containerName)) { - throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.'); - } - if (!is_array($metadata)) { - throw new Zend_Service_WindowsAzure_Exception('Meta data should be an array of key and value pairs.'); - } - - // Create metadata headers - $headers = array(); - $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata)); - - // Perform request - $response = $this->_performRequest($containerName, '?restype=container', Zend_Http_Client::PUT, $headers, false, null, Zend_Service_WindowsAzure_Storage::RESOURCE_CONTAINER, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE); - if ($response->isSuccessful()) { - return new Zend_Service_WindowsAzure_Storage_BlobContainer( - $containerName, - $response->getHeader('Etag'), - $response->getHeader('Last-modified'), - $metadata - ); - } else { - throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); - } - } - - /** - * Get container ACL - * - * @param string $containerName Container name - * @param bool $signedIdentifiers Display only public/private or display signed identifiers? - * @return bool Acl, to be compared with Zend_Service_WindowsAzure_Storage_Blob::ACL_* - * @throws Zend_Service_WindowsAzure_Exception - */ - public function getContainerAcl($containerName = '', $signedIdentifiers = false) - { - if ($containerName === '') { - throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); - } - if (!self::isValidContainerName($containerName)) { - throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.'); - } - - // Perform request - $response = $this->_performRequest($containerName, '?restype=container&comp=acl', Zend_Http_Client::GET, array(), false, null, Zend_Service_WindowsAzure_Storage::RESOURCE_CONTAINER, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ); - if ($response->isSuccessful()) { - if ($signedIdentifiers == false) { - // Only public/private - return $response->getHeader('x-ms-prop-publicaccess') == 'True'; - } else { - // Parse result - $result = $this->_parseResponse($response); - if (!$result) { - return array(); - } - - $entries = null; - if ($result->SignedIdentifier) { - if (count($result->SignedIdentifier) > 1) { - $entries = $result->SignedIdentifier; - } else { - $entries = array($result->SignedIdentifier); - } - } - - // Return value - $returnValue = array(); - foreach ($entries as $entry) { - $returnValue[] = new Zend_Service_WindowsAzure_Storage_SignedIdentifier( - $entry->Id, - $entry->AccessPolicy ? $entry->AccessPolicy->Start ? $entry->AccessPolicy->Start : '' : '', - $entry->AccessPolicy ? $entry->AccessPolicy->Expiry ? $entry->AccessPolicy->Expiry : '' : '', - $entry->AccessPolicy ? $entry->AccessPolicy->Permission ? $entry->AccessPolicy->Permission : '' : '' - ); - } - - // Return - return $returnValue; - } - } else { - throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); - } - } - - /** - * Set container ACL - * - * @param string $containerName Container name - * @param bool $acl Zend_Service_WindowsAzure_Storage_Blob::ACL_* - * @param array $signedIdentifiers Signed identifiers - * @throws Zend_Service_WindowsAzure_Exception - */ - public function setContainerAcl($containerName = '', $acl = self::ACL_PRIVATE, $signedIdentifiers = array()) - { - if ($containerName === '') { - throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); - } - if (!self::isValidContainerName($containerName)) { - throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.'); - } - - // Policies - $policies = null; - if (is_array($signedIdentifiers) && count($signedIdentifiers) > 0) { - $policies = ''; - $policies .= '' . "\r\n"; - $policies .= '' . "\r\n"; - foreach ($signedIdentifiers as $signedIdentifier) { - $policies .= ' ' . "\r\n"; - $policies .= ' ' . $signedIdentifier->Id . '' . "\r\n"; - $policies .= ' ' . "\r\n"; - if ($signedIdentifier->Start != '') - $policies .= ' ' . $signedIdentifier->Start . '' . "\r\n"; - if ($signedIdentifier->Expiry != '') - $policies .= ' ' . $signedIdentifier->Expiry . '' . "\r\n"; - if ($signedIdentifier->Permissions != '') - $policies .= ' ' . $signedIdentifier->Permissions . '' . "\r\n"; - $policies .= ' ' . "\r\n"; - $policies .= ' ' . "\r\n"; - } - $policies .= '' . "\r\n"; - } - - // Perform request - $response = $this->_performRequest($containerName, '?restype=container&comp=acl', Zend_Http_Client::PUT, array('x-ms-prop-publicaccess' => $acl), false, $policies, Zend_Service_WindowsAzure_Storage::RESOURCE_CONTAINER, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE); - if (!$response->isSuccessful()) { - throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); - } - } - - /** - * Get container - * - * @param string $containerName Container name - * @return Zend_Service_WindowsAzure_Storage_BlobContainer - * @throws Zend_Service_WindowsAzure_Exception - */ - public function getContainer($containerName = '') - { - if ($containerName === '') { - throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); - } - if (!self::isValidContainerName($containerName)) { - throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.'); - } - - // Perform request - $response = $this->_performRequest($containerName, '?restype=container', Zend_Http_Client::GET, array(), false, null, Zend_Service_WindowsAzure_Storage::RESOURCE_CONTAINER, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ); - if ($response->isSuccessful()) { - // Parse metadata - $metadata = $this->_parseMetadataHeaders($response->getHeaders()); - - // Return container - return new Zend_Service_WindowsAzure_Storage_BlobContainer( - $containerName, - $response->getHeader('Etag'), - $response->getHeader('Last-modified'), - $metadata - ); - } else { - throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); - } - } - - /** - * Get container metadata - * - * @param string $containerName Container name - * @return array Key/value pairs of meta data - * @throws Zend_Service_WindowsAzure_Exception - */ - public function getContainerMetadata($containerName = '') - { - if ($containerName === '') { - throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); - } - if (!self::isValidContainerName($containerName)) { - throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.'); - } - - return $this->getContainer($containerName)->Metadata; - } - - /** - * Set container metadata - * - * Calling the Set Container Metadata operation overwrites all existing metadata that is associated with the container. It's not possible to modify an individual name/value pair. - * - * @param string $containerName Container name - * @param array $metadata Key/value pairs of meta data - * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. - * @throws Zend_Service_WindowsAzure_Exception - */ - public function setContainerMetadata($containerName = '', $metadata = array(), $additionalHeaders = array()) - { - if ($containerName === '') { - throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); - } - if (!self::isValidContainerName($containerName)) { - throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.'); - } - if (!is_array($metadata)) { - throw new Zend_Service_WindowsAzure_Exception('Meta data should be an array of key and value pairs.'); - } - if (count($metadata) == 0) { - return; - } - - // Create metadata headers - $headers = array(); - $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata)); - - // Additional headers? - foreach ($additionalHeaders as $key => $value) { - $headers[$key] = $value; - } - - // Perform request - $response = $this->_performRequest($containerName, '?restype=container&comp=metadata', Zend_Http_Client::PUT, $headers, false, null, Zend_Service_WindowsAzure_Storage::RESOURCE_CONTAINER, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE); - if (!$response->isSuccessful()) { - throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); - } - } - - /** - * Delete container - * - * @param string $containerName Container name - * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. - * @throws Zend_Service_WindowsAzure_Exception - */ - public function deleteContainer($containerName = '', $additionalHeaders = array()) - { - if ($containerName === '') { - throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); - } - if (!self::isValidContainerName($containerName)) { - throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.'); - } - - // Additional headers? - $headers = array(); - foreach ($additionalHeaders as $key => $value) { - $headers[$key] = $value; - } - - // Perform request - $response = $this->_performRequest($containerName, '?restype=container', Zend_Http_Client::DELETE, $headers, false, null, Zend_Service_WindowsAzure_Storage::RESOURCE_CONTAINER, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE); - if (!$response->isSuccessful()) { - throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); - } - } - - /** - * List containers - * - * @param string $prefix Optional. Filters the results to return only containers whose name begins with the specified prefix. - * @param int $maxResults Optional. Specifies the maximum number of containers to return per call to Azure storage. This does NOT affect list size returned by this function. (maximum: 5000) - * @param string $marker Optional string value that identifies the portion of the list to be returned with the next list operation. - * @param int $currentResultCount Current result count (internal use) - * @return array - * @throws Zend_Service_WindowsAzure_Exception - */ - public function listContainers($prefix = null, $maxResults = null, $marker = null, $currentResultCount = 0) - { - // Build query string - $queryString = '?comp=list'; - if (!is_null($prefix)) { - $queryString .= '&prefix=' . $prefix; - } - if (!is_null($maxResults)) { - $queryString .= '&maxresults=' . $maxResults; - } - if (!is_null($marker)) { - $queryString .= '&marker=' . $marker; - } - - // Perform request - $response = $this->_performRequest('', $queryString, Zend_Http_Client::GET, array(), false, null, Zend_Service_WindowsAzure_Storage::RESOURCE_CONTAINER, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_LIST); - if ($response->isSuccessful()) { - $xmlContainers = $this->_parseResponse($response)->Containers->Container; - $xmlMarker = (string)$this->_parseResponse($response)->NextMarker; - - $containers = array(); - if (!is_null($xmlContainers)) { - for ($i = 0; $i < count($xmlContainers); $i++) { - $containers[] = new Zend_Service_WindowsAzure_Storage_BlobContainer( - (string)$xmlContainers[$i]->Name, - (string)$xmlContainers[$i]->Etag, - (string)$xmlContainers[$i]->LastModified - ); - } - } - $currentResultCount = $currentResultCount + count($containers); - if (!is_null($maxResults) && $currentResultCount < $maxResults) { - if (!is_null($xmlMarker) && $xmlMarker != '') { - $containers = array_merge($containers, $this->listContainers($prefix, $maxResults, $xmlMarker, $currentResultCount)); - } - } - if (!is_null($maxResults) && count($containers) > $maxResults) { - $containers = array_slice($containers, 0, $maxResults); - } - - return $containers; - } else { - throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); - } - } - - /** - * Put blob - * - * @param string $containerName Container name - * @param string $blobName Blob name - * @param string $localFileName Local file name to be uploaded - * @param array $metadata Key/value pairs of meta data - * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. - * @return object Partial blob properties - * @throws Zend_Service_WindowsAzure_Exception - */ - public function putBlob($containerName = '', $blobName = '', $localFileName = '', $metadata = array(), $additionalHeaders = array()) - { - if ($containerName === '') { - throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); - } - if (!self::isValidContainerName($containerName)) { - throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.'); - } - if ($blobName === '') { - throw new Zend_Service_WindowsAzure_Exception('Blob name is not specified.'); - } - if ($localFileName === '') { - throw new Zend_Service_WindowsAzure_Exception('Local file name is not specified.'); - } - if (!file_exists($localFileName)) { - throw new Zend_Service_WindowsAzure_Exception('Local file not found.'); - } - if ($containerName === '$root' && strpos($blobName, '/') !== false) { - throw new Zend_Service_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).'); - } - - // Check file size - if (filesize($localFileName) >= self::MAX_BLOB_SIZE) { - return $this->putLargeBlob($containerName, $blobName, $localFileName, $metadata); - } - - // Create metadata headers - $headers = array(); - $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata)); - - // Additional headers? - foreach ($additionalHeaders as $key => $value) { - $headers[$key] = $value; - } - - // File contents - $fileContents = file_get_contents($localFileName); - - // Resource name - $resourceName = self::createResourceName($containerName , $blobName); - - // Perform request - $response = $this->_performRequest($resourceName, '', Zend_Http_Client::PUT, $headers, false, $fileContents, Zend_Service_WindowsAzure_Storage::RESOURCE_BLOB, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE); - if ($response->isSuccessful()) { - return new Zend_Service_WindowsAzure_Storage_BlobInstance( - $containerName, - $blobName, - $response->getHeader('Etag'), - $response->getHeader('Last-modified'), - $this->getBaseUrl() . '/' . $containerName . '/' . $blobName, - strlen($fileContents), - '', - '', - '', - false, - $metadata - ); - } else { - throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); - } - } - - /** - * Put large blob (> 64 MB) - * - * @param string $containerName Container name - * @param string $blobName Blob name - * @param string $localFileName Local file name to be uploaded - * @param array $metadata Key/value pairs of meta data - * @return object Partial blob properties - * @throws Zend_Service_WindowsAzure_Exception - */ - public function putLargeBlob($containerName = '', $blobName = '', $localFileName = '', $metadata = array()) - { - if ($containerName === '') { - throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); - } - if (!self::isValidContainerName($containerName)) { - throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.'); - } - if ($blobName === '') { - throw new Zend_Service_WindowsAzure_Exception('Blob name is not specified.'); - } - if ($localFileName === '') { - throw new Zend_Service_WindowsAzure_Exception('Local file name is not specified.'); - } - if (!file_exists($localFileName)) { - throw new Zend_Service_WindowsAzure_Exception('Local file not found.'); - } - if ($containerName === '$root' && strpos($blobName, '/') !== false) { - throw new Zend_Service_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).'); - } - - // Check file size - if (filesize($localFileName) < self::MAX_BLOB_SIZE) { - return $this->putBlob($containerName, $blobName, $localFileName, $metadata); - } - - // Determine number of parts - $numberOfParts = ceil( filesize($localFileName) / self::MAX_BLOB_TRANSFER_SIZE ); - - // Generate block id's - $blockIdentifiers = array(); - for ($i = 0; $i < $numberOfParts; $i++) { - $blockIdentifiers[] = $this->_generateBlockId($i); - } - - // Open file - $fp = fopen($localFileName, 'r'); - if ($fp === false) { - throw new Zend_Service_WindowsAzure_Exception('Could not open local file.'); - } - - // Upload parts - for ($i = 0; $i < $numberOfParts; $i++) { - // Seek position in file - fseek($fp, $i * self::MAX_BLOB_TRANSFER_SIZE); - - // Read contents - $fileContents = fread($fp, self::MAX_BLOB_TRANSFER_SIZE); - - // Put block - $this->putBlock($containerName, $blobName, $blockIdentifiers[$i], $fileContents); - - // Dispose file contents - $fileContents = null; - unset($fileContents); - } - - // Close file - fclose($fp); - - // Put block list - $this->putBlockList($containerName, $blobName, $blockIdentifiers, $metadata); - - // Return information of the blob - return $this->getBlobInstance($containerName, $blobName); - } - - /** - * Put large blob block - * - * @param string $containerName Container name - * @param string $blobName Blob name - * @param string $identifier Block ID - * @param array $contents Contents of the block - * @throws Zend_Service_WindowsAzure_Exception - */ - public function putBlock($containerName = '', $blobName = '', $identifier = '', $contents = '') - { - if ($containerName === '') { - throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); - } - if (!self::isValidContainerName($containerName)) { - throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.'); - } - if ($identifier === '') { - throw new Zend_Service_WindowsAzure_Exception('Block identifier is not specified.'); - } - if (strlen($contents) > self::MAX_BLOB_TRANSFER_SIZE) { - throw new Zend_Service_WindowsAzure_Exception('Block size is too big.'); - } - if ($containerName === '$root' && strpos($blobName, '/') !== false) { - throw new Zend_Service_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).'); - } - - // Resource name - $resourceName = self::createResourceName($containerName , $blobName); - - // Upload - $response = $this->_performRequest($resourceName, '?comp=block&blockid=' . base64_encode($identifier), Zend_Http_Client::PUT, null, false, $contents, Zend_Service_WindowsAzure_Storage::RESOURCE_BLOB, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE); - if (!$response->isSuccessful()) { - throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); - } - } - - /** - * Put block list - * - * @param string $containerName Container name - * @param string $blobName Blob name - * @param array $blockList Array of block identifiers - * @param array $metadata Key/value pairs of meta data - * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. - * @throws Zend_Service_WindowsAzure_Exception - */ - public function putBlockList($containerName = '', $blobName = '', $blockList = array(), $metadata = array(), $additionalHeaders = array()) - { - if ($containerName === '') { - throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); - } - if (!self::isValidContainerName($containerName)) { - throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.'); - } - if ($blobName === '') { - throw new Zend_Service_WindowsAzure_Exception('Blob name is not specified.'); - } - if (count($blockList) == 0) { - throw new Zend_Service_WindowsAzure_Exception('Block list does not contain any elements.'); - } - if ($containerName === '$root' && strpos($blobName, '/') !== false) { - throw new Zend_Service_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).'); - } - - // Generate block list - $blocks = ''; - foreach ($blockList as $block) { - $blocks .= ' ' . base64_encode($block) . '' . "\n"; - } - - // Generate block list request - $fileContents = utf8_encode(implode("\n", array( - '', - '', - $blocks, - '' - ))); - - // Create metadata headers - $headers = array(); - $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata)); - - // Additional headers? - foreach ($additionalHeaders as $key => $value) { - $headers[$key] = $value; - } - - // Resource name - $resourceName = self::createResourceName($containerName , $blobName); - - // Perform request - $response = $this->_performRequest($resourceName, '?comp=blocklist', Zend_Http_Client::PUT, $headers, false, $fileContents, Zend_Service_WindowsAzure_Storage::RESOURCE_BLOB, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE); - if (!$response->isSuccessful()) { - throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); - } - } - - /** - * Get block list - * - * @param string $containerName Container name - * @param string $blobName Blob name - * @param integer $type Type of block list to retrieve. 0 = all, 1 = committed, 2 = uncommitted - * @return array - * @throws Zend_Service_WindowsAzure_Exception - */ - public function getBlockList($containerName = '', $blobName = '', $type = 0) - { - if ($containerName === '') { - throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); - } - if (!self::isValidContainerName($containerName)) { - throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.'); - } - if ($blobName === '') { - throw new Zend_Service_WindowsAzure_Exception('Blob name is not specified.'); - } - if ($type < 0 || $type > 2) { - throw new Zend_Service_WindowsAzure_Exception('Invalid type of block list to retrieve.'); - } - - // Set $blockListType - $blockListType = 'all'; - if ($type == 1) { - $blockListType = 'committed'; - } - if ($type == 2) { - $blockListType = 'uncommitted'; - } - - // Resource name - $resourceName = self::createResourceName($containerName , $blobName); - - // Perform request - $response = $this->_performRequest($resourceName, '?comp=blocklist&blocklisttype=' . $blockListType, Zend_Http_Client::GET, array(), false, null, Zend_Service_WindowsAzure_Storage::RESOURCE_BLOB, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ); - if ($response->isSuccessful()) { - // Parse response - $blockList = $this->_parseResponse($response); - - // Create return value - $returnValue = array(); - if ($blockList->CommittedBlocks) { - foreach ($blockList->CommittedBlocks->Block as $block) { - $returnValue['CommittedBlocks'][] = (object)array( - 'Name' => (string)$block->Name, - 'Size' => (string)$block->Size - ); - } - } - if ($blockList->UncommittedBlocks) { - foreach ($blockList->UncommittedBlocks->Block as $block) { - $returnValue['UncommittedBlocks'][] = (object)array( - 'Name' => (string)$block->Name, - 'Size' => (string)$block->Size - ); - } - } - - return $returnValue; - } else { - throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); - } - } - - /** - * Copy blob - * - * @param string $sourceContainerName Source container name - * @param string $sourceBlobName Source blob name - * @param string $destinationContainerName Destination container name - * @param string $destinationBlobName Destination blob name - * @param array $metadata Key/value pairs of meta data - * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd894037.aspx for more information. - * @return object Partial blob properties - * @throws Zend_Service_WindowsAzure_Exception - */ - public function copyBlob($sourceContainerName = '', $sourceBlobName = '', $destinationContainerName = '', $destinationBlobName = '', $metadata = array(), $additionalHeaders = array()) - { - if ($sourceContainerName === '') { - throw new Zend_Service_WindowsAzure_Exception('Source container name is not specified.'); - } - if (!self::isValidContainerName($sourceContainerName)) { - throw new Zend_Service_WindowsAzure_Exception('Source container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.'); - } - if ($sourceBlobName === '') { - throw new Zend_Service_WindowsAzure_Exception('Source blob name is not specified.'); - } - if ($destinationContainerName === '') { - throw new Zend_Service_WindowsAzure_Exception('Destination container name is not specified.'); - } - if (!self::isValidContainerName($destinationContainerName)) { - throw new Zend_Service_WindowsAzure_Exception('Destination container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.'); - } - if ($destinationBlobName === '') { - throw new Zend_Service_WindowsAzure_Exception('Destination blob name is not specified.'); - } - if ($sourceContainerName === '$root' && strpos($sourceBlobName, '/') !== false) { - throw new Zend_Service_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).'); - } - if ($destinationContainerName === '$root' && strpos($destinationBlobName, '/') !== false) { - throw new Zend_Service_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).'); - } - - // Create metadata headers - $headers = array(); - $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata)); - - // Additional headers? - foreach ($additionalHeaders as $key => $value) { - $headers[$key] = $value; - } - - // Resource names - $sourceResourceName = self::createResourceName($sourceContainerName, $sourceBlobName); - $destinationResourceName = self::createResourceName($destinationContainerName, $destinationBlobName); - - // Set source blob - $headers["x-ms-copy-source"] = '/' . $this->_accountName . '/' . $sourceResourceName; - - // Perform request - $response = $this->_performRequest($destinationResourceName, '', Zend_Http_Client::PUT, $headers, false, null, Zend_Service_WindowsAzure_Storage::RESOURCE_BLOB, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE); - if ($response->isSuccessful()) { - return new Zend_Service_WindowsAzure_Storage_BlobInstance( - $destinationContainerName, - $destinationBlobName, - $response->getHeader('Etag'), - $response->getHeader('Last-modified'), - $this->getBaseUrl() . '/' . $destinationContainerName . '/' . $destinationBlobName, - 0, - '', - '', - '', - false, - $metadata - ); - } else { - throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); - } - } - - /** - * Get blob - * - * @param string $containerName Container name - * @param string $blobName Blob name - * @param string $localFileName Local file name to store downloaded blob - * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. - * @throws Zend_Service_WindowsAzure_Exception - */ - public function getBlob($containerName = '', $blobName = '', $localFileName = '', $additionalHeaders = array()) - { - if ($containerName === '') { - throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); - } - if (!self::isValidContainerName($containerName)) { - throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.'); - } - if ($blobName === '') { - throw new Zend_Service_WindowsAzure_Exception('Blob name is not specified.'); - } - if ($localFileName === '') { - throw new Zend_Service_WindowsAzure_Exception('Local file name is not specified.'); - } - - // Additional headers? - $headers = array(); - foreach ($additionalHeaders as $key => $value) { - $headers[$key] = $value; - } - - // Resource name - $resourceName = self::createResourceName($containerName , $blobName); - - // Perform request - $response = $this->_performRequest($resourceName, '', Zend_Http_Client::GET, $headers, false, null, Zend_Service_WindowsAzure_Storage::RESOURCE_BLOB, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ); - if ($response->isSuccessful()) { - file_put_contents($localFileName, $response->getBody()); - } else { - throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); - } - } - - /** - * Get container - * - * @param string $containerName Container name - * @param string $blobName Blob name - * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. - * @return Zend_Service_WindowsAzure_Storage_BlobInstance - * @throws Zend_Service_WindowsAzure_Exception - */ - public function getBlobInstance($containerName = '', $blobName = '', $additionalHeaders = array()) - { - if ($containerName === '') { - throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); - } - if (!self::isValidContainerName($containerName)) { - throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.'); - } - if ($blobName === '') { - throw new Zend_Service_WindowsAzure_Exception('Blob name is not specified.'); - } - if ($containerName === '$root' && strpos($blobName, '/') !== false) { - throw new Zend_Service_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).'); - } - - // Additional headers? - $headers = array(); - foreach ($additionalHeaders as $key => $value) { - $headers[$key] = $value; - } - - // Resource name - $resourceName = self::createResourceName($containerName , $blobName); - - // Perform request - $response = $this->_performRequest($resourceName, '', Zend_Http_Client::HEAD, $headers, false, null, Zend_Service_WindowsAzure_Storage::RESOURCE_BLOB, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ); - if ($response->isSuccessful()) { - // Parse metadata - $metadata = $this->_parseMetadataHeaders($response->getHeaders()); - - // Return blob - return new Zend_Service_WindowsAzure_Storage_BlobInstance( - $containerName, - $blobName, - $response->getHeader('Etag'), - $response->getHeader('Last-modified'), - $this->getBaseUrl() . '/' . $containerName . '/' . $blobName, - $response->getHeader('Content-Length'), - $response->getHeader('Content-Type'), - $response->getHeader('Content-Encoding'), - $response->getHeader('Content-Language'), - false, - $metadata - ); - } else { - throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); - } - } - - /** - * Get blob metadata - * - * @param string $containerName Container name - * @param string $blobName Blob name - * @return array Key/value pairs of meta data - * @throws Zend_Service_WindowsAzure_Exception - */ - public function getBlobMetadata($containerName = '', $blobName = '') - { - if ($containerName === '') { - throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); - } - if (!self::isValidContainerName($containerName)) { - throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.'); - } - if ($blobName === '') { - throw new Zend_Service_WindowsAzure_Exception('Blob name is not specified.'); - } - if ($containerName === '$root' && strpos($blobName, '/') !== false) { - throw new Zend_Service_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).'); - } - - return $this->getBlobInstance($containerName, $blobName)->Metadata; - } - - /** - * Set blob metadata - * - * Calling the Set Blob Metadata operation overwrites all existing metadata that is associated with the blob. It's not possible to modify an individual name/value pair. - * - * @param string $containerName Container name - * @param string $blobName Blob name - * @param array $metadata Key/value pairs of meta data - * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. - * @throws Zend_Service_WindowsAzure_Exception - */ - public function setBlobMetadata($containerName = '', $blobName = '', $metadata = array(), $additionalHeaders = array()) - { - if ($containerName === '') { - throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); - } - if (!self::isValidContainerName($containerName)) { - throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.'); - } - if ($blobName === '') { - throw new Zend_Service_WindowsAzure_Exception('Blob name is not specified.'); - } - if ($containerName === '$root' && strpos($blobName, '/') !== false) { - throw new Zend_Service_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).'); - } - if (count($metadata) == 0) { - return; - } - - // Create metadata headers - $headers = array(); - $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata)); - - // Additional headers? - foreach ($additionalHeaders as $key => $value) { - $headers[$key] = $value; - } - - // Perform request - $response = $this->_performRequest($containerName . '/' . $blobName, '?comp=metadata', Zend_Http_Client::PUT, $headers, false, null, Zend_Service_WindowsAzure_Storage::RESOURCE_BLOB, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE); - if (!$response->isSuccessful()) { - throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); - } - } - - /** - * Delete blob - * - * @param string $containerName Container name - * @param string $blobName Blob name - * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. - * @throws Zend_Service_WindowsAzure_Exception - */ - public function deleteBlob($containerName = '', $blobName = '', $additionalHeaders = array()) - { - if ($containerName === '') { - throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); - } - if (!self::isValidContainerName($containerName)) { - throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.'); - } - if ($blobName === '') { - throw new Zend_Service_WindowsAzure_Exception('Blob name is not specified.'); - } - if ($containerName === '$root' && strpos($blobName, '/') !== false) { - throw new Zend_Service_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).'); - } - - // Additional headers? - $headers = array(); - foreach ($additionalHeaders as $key => $value) { - $headers[$key] = $value; - } - - // Resource name - $resourceName = self::createResourceName($containerName , $blobName); - - // Perform request - $response = $this->_performRequest($resourceName, '', Zend_Http_Client::DELETE, $headers, false, null, Zend_Service_WindowsAzure_Storage::RESOURCE_BLOB, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE); - if (!$response->isSuccessful()) { - throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); - } - } - - /** - * List blobs - * - * @param string $containerName Container name - * @param string $prefix Optional. Filters the results to return only blobs whose name begins with the specified prefix. - * @param string $delimiter Optional. Delimiter, i.e. '/', for specifying folder hierarchy - * @param int $maxResults Optional. Specifies the maximum number of blobs to return per call to Azure storage. This does NOT affect list size returned by this function. (maximum: 5000) - * @param string $marker Optional string value that identifies the portion of the list to be returned with the next list operation. - * @param int $currentResultCount Current result count (internal use) - * @return array - * @throws Zend_Service_WindowsAzure_Exception - */ - public function listBlobs($containerName = '', $prefix = '', $delimiter = '', $maxResults = null, $marker = null, $currentResultCount = 0) - { - if ($containerName === '') { - throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); - } - if (!self::isValidContainerName($containerName)) { - throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.'); - } - - // Build query string - $queryString = '?restype=container&comp=list'; - if (!is_null($prefix)) { - $queryString .= '&prefix=' . $prefix; - } - if ($delimiter !== '') { - $queryString .= '&delimiter=' . $delimiter; - } - if (!is_null($maxResults)) { - $queryString .= '&maxresults=' . $maxResults; - } - if (!is_null($marker)) { - $queryString .= '&marker=' . $marker; - } - - // Perform request - $response = $this->_performRequest($containerName, $queryString, Zend_Http_Client::GET, array(), false, null, Zend_Service_WindowsAzure_Storage::RESOURCE_BLOB, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_LIST); - if ($response->isSuccessful()) { - // Return value - $blobs = array(); - - // Blobs - $xmlBlobs = $this->_parseResponse($response)->Blobs->Blob; - if (!is_null($xmlBlobs)) { - for ($i = 0; $i < count($xmlBlobs); $i++) { - $blobs[] = new Zend_Service_WindowsAzure_Storage_BlobInstance( - $containerName, - (string)$xmlBlobs[$i]->Name, - (string)$xmlBlobs[$i]->Etag, - (string)$xmlBlobs[$i]->LastModified, - (string)$xmlBlobs[$i]->Url, - (string)$xmlBlobs[$i]->Size, - (string)$xmlBlobs[$i]->ContentType, - (string)$xmlBlobs[$i]->ContentEncoding, - (string)$xmlBlobs[$i]->ContentLanguage, - false - ); - } - } - - // Blob prefixes (folders) - $xmlBlobs = $this->_parseResponse($response)->Blobs->BlobPrefix; - - if (!is_null($xmlBlobs)) { - for ($i = 0; $i < count($xmlBlobs); $i++) { - $blobs[] = new Zend_Service_WindowsAzure_Storage_BlobInstance( - $containerName, - (string)$xmlBlobs[$i]->Name, - '', - '', - '', - 0, - '', - '', - '', - true - ); - } - } - - // More blobs? - $xmlMarker = (string)$this->_parseResponse($response)->NextMarker; - $currentResultCount = $currentResultCount + count($blobs); - if (!is_null($maxResults) && $currentResultCount < $maxResults) { - if (!is_null($xmlMarker) && $xmlMarker != '') { - $blobs = array_merge($blobs, $this->listBlobs($containerName, $prefix, $delimiter, $maxResults, $marker, $currentResultCount)); - } - } - if (!is_null($maxResults) && count($blobs) > $maxResults) { - $blobs = array_slice($blobs, 0, $maxResults); - } - - return $blobs; - } else { - throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); - } - } - - /** - * Generate shared access URL - * - * @param string $containerName Container name - * @param string $blobName Blob name - * @param string $resource Signed resource - container (c) - blob (b) - * @param string $permissions Signed permissions - read (r), write (w), delete (d) and list (l) - * @param string $start The time at which the Shared Access Signature becomes valid. - * @param string $expiry The time at which the Shared Access Signature becomes invalid. - * @param string $identifier Signed identifier - * @return string - */ - public function generateSharedAccessUrl($containerName = '', $blobName = '', $resource = 'b', $permissions = 'r', $start = '', $expiry = '', $identifier = '') - { - if ($containerName === '') { - throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); - } - if (!self::isValidContainerName($containerName)) { - throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.'); - } - - // Resource name - $resourceName = self::createResourceName($containerName , $blobName); - - // Generate URL - return $this->getBaseUrl() . '/' . $resourceName . '?' . - $this->_sharedAccessSignatureCredentials->createSignedQueryString( - $resourceName, - '', - $resource, - $permissions, - $start, - $expiry, - $identifier); - } - - /** - * Register this object as stream wrapper client - * - * @param string $name Protocol name - * @return Zend_Service_WindowsAzure_Storage_Blob - */ - public function registerAsClient($name) - { - self::$_wrapperClients[$name] = $this; - return $this; - } - - /** - * Unregister this object as stream wrapper client - * - * @param string $name Protocol name - * @return Zend_Service_WindowsAzure_Storage_Blob - */ - public function unregisterAsClient($name) - { - unset(self::$_wrapperClients[$name]); - return $this; - } - - /** - * Get wrapper client for stream type - * - * @param string $name Protocol name - * @return Zend_Service_WindowsAzure_Storage_Blob - */ - public static function getWrapperClient($name) - { - return self::$_wrapperClients[$name]; - } - - /** - * Register this object as stream wrapper - * - * @param string $name Protocol name - */ - public function registerStreamWrapper($name = 'azure') - { - /** - * @see Zend_Service_WindowsAzure_Storage_Blob_Stream - */ - require_once 'Zend/Service/WindowsAzure/Storage/Blob/Stream.php'; - - stream_register_wrapper($name, 'Zend_Service_WindowsAzure_Storage_Blob_Stream'); - $this->registerAsClient($name); - } - - /** - * Unregister this object as stream wrapper - * - * @param string $name Protocol name - * @return Zend_Service_WindowsAzure_Storage_Blob - */ - public function unregisterStreamWrapper($name = 'azure') - { - stream_wrapper_unregister($name); - $this->unregisterAsClient($name); - } - - /** - * Create resource name - * - * @param string $containerName Container name - * @param string $blobName Blob name - * @return string - */ - public static function createResourceName($containerName = '', $blobName = '') - { - // Resource name - $resourceName = $containerName . '/' . $blobName; - if ($containerName === '' || $containerName === '$root') { - $resourceName = $blobName; - } - if ($blobName === '') { - $resourceName = $containerName; - } - - return $resourceName; - } - - /** - * Is valid container name? - * - * @param string $containerName Container name - * @return boolean - */ - public static function isValidContainerName($containerName = '') - { - if ($containerName == '$root') { - return true; - } - - if (preg_match("/^[a-z0-9][a-z0-9-]*$/", $containerName) === 0) { - return false; - } - - if (strpos($containerName, '--') !== false) { - return false; - } - - if (strtolower($containerName) != $containerName) { - return false; - } - - if (strlen($containerName) < 3 || strlen($containerName) > 63) { - return false; - } - - if (substr($containerName, -1) == '-') { - return false; - } - - return true; - } - - /** - * Get error message from Zend_Http_Response - * - * @param Zend_Http_Response $response Repsonse - * @param string $alternativeError Alternative error message - * @return string - */ - protected function _getErrorMessage(Zend_Http_Response $response, $alternativeError = 'Unknown error.') - { - $response = $this->_parseResponse($response); - if ($response && $response->Message) { - return (string)$response->Message; - } else { - return $alternativeError; - } - } - - /** - * Generate block id - * - * @param int $part Block number - * @return string Windows Azure Blob Storage block number - */ - protected function _generateBlockId($part = 0) - { - $returnValue = $part; - while (strlen($returnValue) < 64) { - $returnValue = '0' . $returnValue; - } - - return $returnValue; - } -} diff --git a/lib/zend/Zend/Service/WindowsAzure/Storage/Blob/Stream.php b/lib/zend/Zend/Service/WindowsAzure/Storage/Blob/Stream.php deleted file mode 100644 index 4171828585b..00000000000 --- a/lib/zend/Zend/Service/WindowsAzure/Storage/Blob/Stream.php +++ /dev/null @@ -1,565 +0,0 @@ -_storageClient)) { - $url = explode(':', $path); - if (!$url) { - throw new Zend_Service_WindowsAzure_Exception('Could not parse path "' . $path . '".'); - } - - $this->_storageClient = Zend_Service_WindowsAzure_Storage_Blob::getWrapperClient($url[0]); - if (!$this->_storageClient) { - throw new Zend_Service_WindowsAzure_Exception('No storage client registered for stream type "' . $url[0] . '://".'); - } - } - - return $this->_storageClient; - } - - /** - * Extract container name - * - * @param string $path - * @return string - */ - protected function _getContainerName($path) - { - $url = parse_url($path); - if ($url['host']) { - return $url['host']; - } - - return ''; - } - - /** - * Extract file name - * - * @param string $path - * @return string - */ - protected function _getFileName($path) - { - $url = parse_url($path); - if ($url['host']) { - $fileName = isset($url['path']) ? $url['path'] : $url['host']; - if (strpos($fileName, '/') === 0) { - $fileName = substr($fileName, 1); - } - return $fileName; - } - - return ''; - } - - /** - * Open the stream - * - * @param string $path - * @param string $mode - * @param integer $options - * @param string $opened_path - * @return boolean - */ - public function stream_open($path, $mode, $options, $opened_path) - { - $this->_fileName = $path; - $this->_temporaryFileName = tempnam(sys_get_temp_dir(), 'azure'); - - // Check the file can be opened - $fh = @fopen($this->_temporaryFileName, $mode); - if ($fh === false) { - return false; - } - fclose($fh); - - // Write mode? - if (strpbrk($mode, 'wax+')) { - $this->_writeMode = true; - } else { - $this->_writeMode = false; - } - - // If read/append, fetch the file - if (!$this->_writeMode || strpbrk($mode, 'ra+')) { - $this->_getStorageClient($this->_fileName)->getBlob( - $this->_getContainerName($this->_fileName), - $this->_getFileName($this->_fileName), - $this->_temporaryFileName - ); - } - - // Open temporary file handle - $this->_temporaryFileHandle = fopen($this->_temporaryFileName, $mode); - - // Ok! - return true; - } - - /** - * Close the stream - * - * @return void - */ - public function stream_close() - { - @fclose($this->_temporaryFileHandle); - - // Upload the file? - if ($this->_writeMode) { - // Make sure the container exists - $containerExists = $this->_getStorageClient($this->_fileName)->containerExists( - $this->_getContainerName($this->_fileName) - ); - if (!$containerExists) { - $this->_getStorageClient($this->_fileName)->createContainer( - $this->_getContainerName($this->_fileName) - ); - } - - // Upload the file - try { - $this->_getStorageClient($this->_fileName)->putBlob( - $this->_getContainerName($this->_fileName), - $this->_getFileName($this->_fileName), - $this->_temporaryFileName - ); - } catch (Zend_Service_WindowsAzure_Exception $ex) { - @unlink($this->_temporaryFileName); - unset($this->_storageClient); - - throw $ex; - } - } - - @unlink($this->_temporaryFileName); - unset($this->_storageClient); - } - - /** - * Read from the stream - * - * @param integer $count - * @return string - */ - public function stream_read($count) - { - if (!$this->_temporaryFileHandle) { - return false; - } - - return fread($this->_temporaryFileHandle, $count); - } - - /** - * Write to the stream - * - * @param string $data - * @return integer - */ - public function stream_write($data) - { - if (!$this->_temporaryFileHandle) { - return 0; - } - - $len = strlen($data); - fwrite($this->_temporaryFileHandle, $data, $len); - return $len; - } - - /** - * End of the stream? - * - * @return boolean - */ - public function stream_eof() - { - if (!$this->_temporaryFileHandle) { - return true; - } - - return feof($this->_temporaryFileHandle); - } - - /** - * What is the current read/write position of the stream? - * - * @return integer - */ - public function stream_tell() - { - return ftell($this->_temporaryFileHandle); - } - - /** - * Update the read/write position of the stream - * - * @param integer $offset - * @param integer $whence - * @return boolean - */ - public function stream_seek($offset, $whence) - { - if (!$this->_temporaryFileHandle) { - return false; - } - - return (fseek($this->_temporaryFileHandle, $offset, $whence) === 0); - } - - /** - * Flush current cached stream data to storage - * - * @return boolean - */ - public function stream_flush() - { - $result = fflush($this->_temporaryFileHandle); - - // Upload the file? - if ($this->_writeMode) { - // Make sure the container exists - $containerExists = $this->_getStorageClient($this->_fileName)->containerExists( - $this->_getContainerName($this->_fileName) - ); - if (!$containerExists) { - $this->_getStorageClient($this->_fileName)->createContainer( - $this->_getContainerName($this->_fileName) - ); - } - - // Upload the file - try { - $this->_getStorageClient($this->_fileName)->putBlob( - $this->_getContainerName($this->_fileName), - $this->_getFileName($this->_fileName), - $this->_temporaryFileName - ); - } catch (Zend_Service_WindowsAzure_Exception $ex) { - @unlink($this->_temporaryFileName); - unset($this->_storageClient); - - throw $ex; - } - } - - return $result; - } - - /** - * Returns data array of stream variables - * - * @return array - */ - public function stream_stat() - { - if (!$this->_temporaryFileHandle) { - return false; - } - - $stat = array(); - $stat['dev'] = 0; - $stat['ino'] = 0; - $stat['mode'] = 0; - $stat['nlink'] = 0; - $stat['uid'] = 0; - $stat['gid'] = 0; - $stat['rdev'] = 0; - $stat['size'] = 0; - $stat['atime'] = 0; - $stat['mtime'] = 0; - $stat['ctime'] = 0; - $stat['blksize'] = 0; - $stat['blocks'] = 0; - - $info = null; - try { - $info = $this->_getStorageClient($this->_fileName)->getBlobInstance( - $this->_getContainerName($this->_fileName), - $this->_getFileName($this->_fileName) - ); - } catch (Zend_Service_WindowsAzure_Exception $ex) { - // Unexisting file... - } - if (!is_null($info)) { - $stat['size'] = $info->Size; - $stat['atime'] = time(); - } - - return $stat; - } - - /** - * Attempt to delete the item - * - * @param string $path - * @return boolean - */ - public function unlink($path) - { - $this->_getStorageClient($path)->deleteBlob( - $this->_getContainerName($path), - $this->_getFileName($path) - ); - } - - /** - * Attempt to rename the item - * - * @param string $path_from - * @param string $path_to - * @return boolean False - */ - public function rename($path_from, $path_to) - { - if ($this->_getContainerName($path_from) != $this->_getContainerName($path_to)) { - throw new Zend_Service_WindowsAzure_Exception('Container name can not be changed.'); - } - - if ($this->_getFileName($path_from) == $this->_getContainerName($path_to)) { - return true; - } - - $this->_getStorageClient($path_from)->copyBlob( - $this->_getContainerName($path_from), - $this->_getFileName($path_from), - $this->_getContainerName($path_to), - $this->_getFileName($path_to) - ); - $this->_getStorageClient($path_from)->deleteBlob( - $this->_getContainerName($path_from), - $this->_getFileName($path_from) - ); - return true; - } - - /** - * Return array of URL variables - * - * @param string $path - * @param integer $flags - * @return array - */ - public function url_stat($path, $flags) - { - $stat = array(); - $stat['dev'] = 0; - $stat['ino'] = 0; - $stat['mode'] = 0; - $stat['nlink'] = 0; - $stat['uid'] = 0; - $stat['gid'] = 0; - $stat['rdev'] = 0; - $stat['size'] = 0; - $stat['atime'] = 0; - $stat['mtime'] = 0; - $stat['ctime'] = 0; - $stat['blksize'] = 0; - $stat['blocks'] = 0; - - $info = null; - try { - $info = $this->_getStorageClient($path)->getBlobInstance( - $this->_getContainerName($path), - $this->_getFileName($path) - ); - } catch (Zend_Service_WindowsAzure_Exception $ex) { - // Unexisting file... - } - if (!is_null($info)) { - $stat['size'] = $info->Size; - $stat['atime'] = time(); - } - - return $stat; - } - - /** - * Create a new directory - * - * @param string $path - * @param integer $mode - * @param integer $options - * @return boolean - */ - public function mkdir($path, $mode, $options) - { - if ($this->_getContainerName($path) == $this->_getFileName($path)) { - // Create container - try { - $this->_getStorageClient($path)->createContainer( - $this->_getContainerName($path) - ); - } catch (Zend_Service_WindowsAzure_Exception $ex) { - return false; - } - } else { - throw new Zend_Service_WindowsAzure_Exception('mkdir() with multiple levels is not supported on Windows Azure Blob Storage.'); - } - } - - /** - * Remove a directory - * - * @param string $path - * @param integer $options - * @return boolean - */ - public function rmdir($path, $options) - { - if ($this->_getContainerName($path) == $this->_getFileName($path)) { - // Delete container - try { - $this->_getStorageClient($path)->deleteContainer( - $this->_getContainerName($path) - ); - } catch (Zend_Service_WindowsAzure_Exception $ex) { - return false; - } - } else { - throw new Zend_Service_WindowsAzure_Exception('rmdir() with multiple levels is not supported on Windows Azure Blob Storage.'); - } - } - - /** - * Attempt to open a directory - * - * @param string $path - * @param integer $options - * @return boolean - */ - public function dir_opendir($path, $options) - { - $this->_blobs = $this->_getStorageClient($path)->listBlobs( - $this->_getContainerName($path) - ); - return is_array($this->_blobs); - } - - /** - * Return the next filename in the directory - * - * @return string - */ - public function dir_readdir() - { - $object = current($this->_blobs); - if ($object !== false) { - next($this->_blobs); - return $object->Name; - } - return false; - } - - /** - * Reset the directory pointer - * - * @return boolean True - */ - public function dir_rewinddir() - { - reset($this->_blobs); - return true; - } - - /** - * Close a directory - * - * @return boolean True - */ - public function dir_closedir() - { - $this->_blobs = null; - return true; - } -} diff --git a/lib/zend/Zend/Service/WindowsAzure/Storage/BlobContainer.php b/lib/zend/Zend/Service/WindowsAzure/Storage/BlobContainer.php deleted file mode 100644 index 1066f43a3cf..00000000000 --- a/lib/zend/Zend/Service/WindowsAzure/Storage/BlobContainer.php +++ /dev/null @@ -1,95 +0,0 @@ -_data = array( - 'name' => $name, - 'etag' => $etag, - 'lastmodified' => $lastModified, - 'metadata' => $metadata - ); - } - - /** - * Magic overload for setting properties - * - * @param string $name Name of the property - * @param string $value Value to set - */ - public function __set($name, $value) { - if (array_key_exists(strtolower($name), $this->_data)) { - $this->_data[strtolower($name)] = $value; - return; - } - - throw new Exception("Unknown property: " . $name); - } - - /** - * Magic overload for getting properties - * - * @param string $name Name of the property - */ - public function __get($name) { - if (array_key_exists(strtolower($name), $this->_data)) { - return $this->_data[strtolower($name)]; - } - - throw new Exception("Unknown property: " . $name); - } -} diff --git a/lib/zend/Zend/Service/WindowsAzure/Storage/BlobInstance.php b/lib/zend/Zend/Service/WindowsAzure/Storage/BlobInstance.php deleted file mode 100644 index d8185ccb2f8..00000000000 --- a/lib/zend/Zend/Service/WindowsAzure/Storage/BlobInstance.php +++ /dev/null @@ -1,116 +0,0 @@ -_data = array( - 'container' => $containerName, - 'name' => $name, - 'etag' => $etag, - 'lastmodified' => $lastModified, - 'url' => $url, - 'size' => $size, - 'contenttype' => $contentType, - 'contentencoding' => $contentEncoding, - 'contentlanguage' => $contentLanguage, - 'isprefix' => $isPrefix, - 'metadata' => $metadata - ); - } - - /** - * Magic overload for setting properties - * - * @param string $name Name of the property - * @param string $value Value to set - */ - public function __set($name, $value) { - if (array_key_exists(strtolower($name), $this->_data)) { - $this->_data[strtolower($name)] = $value; - return; - } - - throw new Exception("Unknown property: " . $name); - } - - /** - * Magic overload for getting properties - * - * @param string $name Name of the property - */ - public function __get($name) { - if (array_key_exists(strtolower($name), $this->_data)) { - return $this->_data[strtolower($name)]; - } - - throw new Exception("Unknown property: " . $name); - } -} diff --git a/lib/zend/Zend/Service/WindowsAzure/Storage/DynamicTableEntity.php b/lib/zend/Zend/Service/WindowsAzure/Storage/DynamicTableEntity.php deleted file mode 100644 index 03a18509d40..00000000000 --- a/lib/zend/Zend/Service/WindowsAzure/Storage/DynamicTableEntity.php +++ /dev/null @@ -1,200 +0,0 @@ -setAzureProperty($name, $value, null); - } - - /** - * Magic overload for getting properties - * - * @param string $name Name of the property - */ - public function __get($name) { - return $this->getAzureProperty($name); - } - - /** - * Set an Azure property - * - * @param string $name Property name - * @param mixed $value Property value - * @param string $type Property type (Edm.xxxx) - * @return Zend_Service_WindowsAzure_Storage_DynamicTableEntity - */ - public function setAzureProperty($name, $value = '', $type = null) - { - if (strtolower($name) == 'partitionkey') { - $this->setPartitionKey($value); - } else if (strtolower($name) == 'rowkey') { - $this->setRowKey($value); - } else if (strtolower($name) == 'etag') { - $this->setEtag($value); - } else { - if (!array_key_exists(strtolower($name), $this->_dynamicProperties)) { - // Determine type? - if (is_null($type)) { - $type = 'Edm.String'; - if (is_int($value)) { - $type = 'Edm.Int32'; - } else if (is_float($value)) { - $type = 'Edm.Double'; - } else if (is_bool($value)) { - $type = 'Edm.Boolean'; - } - } - - // Set dynamic property - $this->_dynamicProperties[strtolower($name)] = (object)array( - 'Name' => $name, - 'Type' => $type, - 'Value' => $value, - ); - } - - $this->_dynamicProperties[strtolower($name)]->Value = $value; - } - return $this; - } - - /** - * Set an Azure property type - * - * @param string $name Property name - * @param string $type Property type (Edm.xxxx) - * @return Zend_Service_WindowsAzure_Storage_DynamicTableEntity - */ - public function setAzurePropertyType($name, $type = 'Edm.String') - { - if (!array_key_exists(strtolower($name), $this->_dynamicProperties)) { - $this->setAzureProperty($name, '', $type); - } else { - $this->_dynamicProperties[strtolower($name)]->Type = $type; - } - return $this; - } - - /** - * Get an Azure property - * - * @param string $name Property name - * @param mixed $value Property value - * @param string $type Property type (Edm.xxxx) - * @return Zend_Service_WindowsAzure_Storage_DynamicTableEntity - */ - public function getAzureProperty($name) - { - if (strtolower($name) == 'partitionkey') { - return $this->getPartitionKey(); - } - if (strtolower($name) == 'rowkey') { - return $this->getRowKey(); - } - if (strtolower($name) == 'etag') { - return $this->getEtag(); - } - - if (!array_key_exists(strtolower($name), $this->_dynamicProperties)) { - $this->setAzureProperty($name); - } - - return $this->_dynamicProperties[strtolower($name)]->Value; - } - - /** - * Get an Azure property type - * - * @param string $name Property name - * @return string Property type (Edm.xxxx) - */ - public function getAzurePropertyType($name) - { - if (!array_key_exists(strtolower($name), $this->_dynamicProperties)) { - $this->setAzureProperty($name, '', $type); - } - - return $this->_dynamicProperties[strtolower($name)]->Type; - } - - /** - * Get Azure values - * - * @return array - */ - public function getAzureValues() - { - return array_merge(array_values($this->_dynamicProperties), parent::getAzureValues()); - } - - /** - * Set Azure values - * - * @param array $values - * @param boolean $throwOnError Throw Zend_Service_WindowsAzure_Exception when a property is not specified in $values? - * @throws Zend_Service_WindowsAzure_Exception - */ - public function setAzureValues($values = array(), $throwOnError = false) - { - // Set parent values - parent::setAzureValues($values, false); - - // Set current values - foreach ($values as $key => $value) - { - $this->$key = $value; - } - } -} diff --git a/lib/zend/Zend/Service/WindowsAzure/Storage/Queue.php b/lib/zend/Zend/Service/WindowsAzure/Storage/Queue.php deleted file mode 100644 index 0a7b48fb8fd..00000000000 --- a/lib/zend/Zend/Service/WindowsAzure/Storage/Queue.php +++ /dev/null @@ -1,547 +0,0 @@ -_apiVersion = '2009-04-14'; - } - - /** - * Check if a queue exists - * - * @param string $queueName Queue name - * @return boolean - */ - public function queueExists($queueName = '') - { - if ($queueName === '') { - throw new Zend_Service_WindowsAzure_Exception('Queue name is not specified.'); - } - if (!self::isValidQueueName($queueName)) { - throw new Zend_Service_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.'); - } - - // List queues - $queues = $this->listQueues($queueName, 1); - foreach ($queues as $queue) { - if ($queue->Name == $queueName) { - return true; - } - } - - return false; - } - - /** - * Create queue - * - * @param string $queueName Queue name - * @param array $metadata Key/value pairs of meta data - * @return object Queue properties - * @throws Zend_Service_WindowsAzure_Exception - */ - public function createQueue($queueName = '', $metadata = array()) - { - if ($queueName === '') { - throw new Zend_Service_WindowsAzure_Exception('Queue name is not specified.'); - } - if (!self::isValidQueueName($queueName)) { - throw new Zend_Service_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.'); - } - - // Create metadata headers - $headers = array(); - $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata)); - - // Perform request - $response = $this->_performRequest($queueName, '', Zend_Http_Client::PUT, $headers); - if ($response->isSuccessful()) { - return new Zend_Service_WindowsAzure_Storage_QueueInstance( - $queueName, - $metadata - ); - } else { - throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); - } - } - - /** - * Get queue - * - * @param string $queueName Queue name - * @return Zend_Service_WindowsAzure_Storage_QueueInstance - * @throws Zend_Service_WindowsAzure_Exception - */ - public function getQueue($queueName = '') - { - if ($queueName === '') { - throw new Zend_Service_WindowsAzure_Exception('Queue name is not specified.'); - } - if (!self::isValidQueueName($queueName)) { - throw new Zend_Service_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.'); - } - - // Perform request - $response = $this->_performRequest($queueName, '?comp=metadata', Zend_Http_Client::GET); - if ($response->isSuccessful()) { - // Parse metadata - $metadata = $this->_parseMetadataHeaders($response->getHeaders()); - - // Return queue - $queue = new Zend_Service_WindowsAzure_Storage_QueueInstance( - $queueName, - $metadata - ); - $queue->ApproximateMessageCount = intval($response->getHeader('x-ms-approximate-message-count')); - return $queue; - } else { - throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); - } - } - - /** - * Get queue metadata - * - * @param string $queueName Queue name - * @return array Key/value pairs of meta data - * @throws Zend_Service_WindowsAzure_Exception - */ - public function getQueueMetadata($queueName = '') - { - if ($queueName === '') { - throw new Zend_Service_WindowsAzure_Exception('Queue name is not specified.'); - } - if (!self::isValidQueueName($queueName)) { - throw new Zend_Service_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.'); - } - - return $this->getQueue($queueName)->Metadata; - } - - /** - * Set queue metadata - * - * Calling the Set Queue Metadata operation overwrites all existing metadata that is associated with the queue. It's not possible to modify an individual name/value pair. - * - * @param string $queueName Queue name - * @param array $metadata Key/value pairs of meta data - * @throws Zend_Service_WindowsAzure_Exception - */ - public function setQueueMetadata($queueName = '', $metadata = array()) - { - if ($queueName === '') { - throw new Zend_Service_WindowsAzure_Exception('Queue name is not specified.'); - } - if (!self::isValidQueueName($queueName)) { - throw new Zend_Service_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.'); - } - if (count($metadata) == 0) { - return; - } - - // Create metadata headers - $headers = array(); - $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata)); - - // Perform request - $response = $this->_performRequest($queueName, '?comp=metadata', Zend_Http_Client::PUT, $headers); - - if (!$response->isSuccessful()) { - throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); - } - } - - /** - * Delete queue - * - * @param string $queueName Queue name - * @throws Zend_Service_WindowsAzure_Exception - */ - public function deleteQueue($queueName = '') - { - if ($queueName === '') { - throw new Zend_Service_WindowsAzure_Exception('Queue name is not specified.'); - } - if (!self::isValidQueueName($queueName)) { - throw new Zend_Service_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.'); - } - - // Perform request - $response = $this->_performRequest($queueName, '', Zend_Http_Client::DELETE); - if (!$response->isSuccessful()) { - throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); - } - } - - /** - * List queues - * - * @param string $prefix Optional. Filters the results to return only queues whose name begins with the specified prefix. - * @param int $maxResults Optional. Specifies the maximum number of queues to return per call to Azure storage. This does NOT affect list size returned by this function. (maximum: 5000) - * @param string $marker Optional string value that identifies the portion of the list to be returned with the next list operation. - * @param int $currentResultCount Current result count (internal use) - * @return array - * @throws Zend_Service_WindowsAzure_Exception - */ - public function listQueues($prefix = null, $maxResults = null, $marker = null, $currentResultCount = 0) - { - // Build query string - $queryString = '?comp=list'; - if (!is_null($prefix)) { - $queryString .= '&prefix=' . $prefix; - } - if (!is_null($maxResults)) { - $queryString .= '&maxresults=' . $maxResults; - } - if (!is_null($marker)) { - $queryString .= '&marker=' . $marker; - } - - // Perform request - $response = $this->_performRequest('', $queryString, Zend_Http_Client::GET); - if ($response->isSuccessful()) { - $xmlQueues = $this->_parseResponse($response)->Queues->Queue; - $xmlMarker = (string)$this->_parseResponse($response)->NextMarker; - - $queues = array(); - if (!is_null($xmlQueues)) { - for ($i = 0; $i < count($xmlQueues); $i++) { - $queues[] = new Zend_Service_WindowsAzure_Storage_QueueInstance( - (string)$xmlQueues[$i]->QueueName - ); - } - } - $currentResultCount = $currentResultCount + count($queues); - if (!is_null($maxResults) && $currentResultCount < $maxResults) { - if (!is_null($xmlMarker) && $xmlMarker != '') { - $queues = array_merge($queues, $this->listQueues($prefix, $maxResults, $xmlMarker, $currentResultCount)); - } - } - if (!is_null($maxResults) && count($queues) > $maxResults) { - $queues = array_slice($queues, 0, $maxResults); - } - - return $queues; - } else { - throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); - } - } - - /** - * Put message into queue - * - * @param string $queueName Queue name - * @param string $message Message - * @param int $ttl Message Time-To-Live (in seconds). Defaults to 7 days if the parameter is omitted. - * @throws Zend_Service_WindowsAzure_Exception - */ - public function putMessage($queueName = '', $message = '', $ttl = null) - { - if ($queueName === '') { - throw new Zend_Service_WindowsAzure_Exception('Queue name is not specified.'); - } - if (!self::isValidQueueName($queueName)) { - throw new Zend_Service_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.'); - } - if (strlen($message) > self::MAX_MESSAGE_SIZE) { - throw new Zend_Service_WindowsAzure_Exception('Message is too big. Message content should be < 8KB.'); - } - if ($message == '') { - throw new Zend_Service_WindowsAzure_Exception('Message is not specified.'); - } - if (!is_null($ttl) && ($ttl <= 0 || $ttl > self::MAX_MESSAGE_SIZE)) { - throw new Zend_Service_WindowsAzure_Exception('Message TTL is invalid. Maximal TTL is 7 days (' . self::MAX_MESSAGE_SIZE . ' seconds) and should be greater than zero.'); - } - - // Build query string - $queryString = ''; - if (!is_null($ttl)) { - $queryString .= '?messagettl=' . $ttl; - } - - // Build body - $rawData = ''; - $rawData .= ''; - $rawData .= ' ' . base64_encode($message) . ''; - $rawData .= ''; - - // Perform request - $response = $this->_performRequest($queueName . '/messages', $queryString, Zend_Http_Client::POST, array(), false, $rawData); - - if (!$response->isSuccessful()) { - throw new Zend_Service_WindowsAzure_Exception('Error putting message into queue.'); - } - } - - /** - * Get queue messages - * - * @param string $queueName Queue name - * @param string $numOfMessages Optional. A nonzero integer value that specifies the number of messages to retrieve from the queue, up to a maximum of 32. By default, a single message is retrieved from the queue with this operation. - * @param int $visibilityTimeout Optional. An integer value that specifies the message's visibility timeout in seconds. The maximum value is 2 hours. The default message visibility timeout is 30 seconds. - * @param string $peek Peek only? - * @return array - * @throws Zend_Service_WindowsAzure_Exception - */ - public function getMessages($queueName = '', $numOfMessages = 1, $visibilityTimeout = null, $peek = false) - { - if ($queueName === '') { - throw new Zend_Service_WindowsAzure_Exception('Queue name is not specified.'); - } - if (!self::isValidQueueName($queueName)) { - throw new Zend_Service_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.'); - } - if ($numOfMessages < 1 || $numOfMessages > 32 || intval($numOfMessages) != $numOfMessages) { - throw new Zend_Service_WindowsAzure_Exception('Invalid number of messages to retrieve.'); - } - if (!is_null($visibilityTimeout) && ($visibilityTimeout <= 0 || $visibilityTimeout > 7200)) { - throw new Zend_Service_WindowsAzure_Exception('Visibility timeout is invalid. Maximum value is 2 hours (7200 seconds) and should be greater than zero.'); - } - - // Build query string - $query = array(); - if ($peek) { - $query[] = 'peekonly=true'; - } - if ($numOfMessages > 1) { - $query[] = 'numofmessages=' . $numOfMessages; - } - if (!$peek && !is_null($visibilityTimeout)) { - $query[] = 'visibilitytimeout=' . $visibilityTimeout; - } - $queryString = '?' . implode('&', $query); - - // Perform request - $response = $this->_performRequest($queueName . '/messages', $queryString, Zend_Http_Client::GET); - if ($response->isSuccessful()) { - // Parse results - $result = $this->_parseResponse($response); - if (!$result) { - return array(); - } - - $xmlMessages = null; - if (count($result->QueueMessage) > 1) { - $xmlMessages = $result->QueueMessage; - } else { - $xmlMessages = array($result->QueueMessage); - } - - $messages = array(); - for ($i = 0; $i < count($xmlMessages); $i++) { - $messages[] = new Zend_Service_WindowsAzure_Storage_QueueMessage( - (string)$xmlMessages[$i]->MessageId, - (string)$xmlMessages[$i]->InsertionTime, - (string)$xmlMessages[$i]->ExpirationTime, - ($peek ? '' : (string)$xmlMessages[$i]->PopReceipt), - ($peek ? '' : (string)$xmlMessages[$i]->TimeNextVisible), - base64_decode((string)$xmlMessages[$i]->MessageText) - ); - } - - return $messages; - } else { - throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); - } - } - - /** - * Peek queue messages - * - * @param string $queueName Queue name - * @param string $numOfMessages Optional. A nonzero integer value that specifies the number of messages to retrieve from the queue, up to a maximum of 32. By default, a single message is retrieved from the queue with this operation. - * @return array - * @throws Zend_Service_WindowsAzure_Exception - */ - public function peekMessages($queueName = '', $numOfMessages = 1) - { - return $this->getMessages($queueName, $numOfMessages, null, true); - } - - /** - * Clear queue messages - * - * @param string $queueName Queue name - * @throws Zend_Service_WindowsAzure_Exception - */ - public function clearMessages($queueName = '') - { - if ($queueName === '') { - throw new Zend_Service_WindowsAzure_Exception('Queue name is not specified.'); - } - if (!self::isValidQueueName($queueName)) { - throw new Zend_Service_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.'); - } - - // Perform request - $response = $this->_performRequest($queueName . '/messages', '', Zend_Http_Client::DELETE); - if (!$response->isSuccessful()) { - throw new Zend_Service_WindowsAzure_Exception('Error clearing messages from queue.'); - } - } - - /** - * Delete queue message - * - * @param string $queueName Queue name - * @param Zend_Service_WindowsAzure_Storage_QueueMessage $message Message to delete from queue. A message retrieved using "peekMessages" can NOT be deleted! - * @throws Zend_Service_WindowsAzure_Exception - */ - public function deleteMessage($queueName = '', Zend_Service_WindowsAzure_Storage_QueueMessage $message) - { - if ($queueName === '') { - throw new Zend_Service_WindowsAzure_Exception('Queue name is not specified.'); - } - if (!self::isValidQueueName($queueName)) { - throw new Zend_Service_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.'); - } - if ($message->PopReceipt == '') { - throw new Zend_Service_WindowsAzure_Exception('A message retrieved using "peekMessages" can NOT be deleted! Use "getMessages" instead.'); - } - - // Perform request - $response = $this->_performRequest($queueName . '/messages/' . $message->MessageId, '?popreceipt=' . $message->PopReceipt, Zend_Http_Client::DELETE); - if (!$response->isSuccessful()) { - throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); - } - } - - /** - * Is valid queue name? - * - * @param string $queueName Queue name - * @return boolean - */ - public static function isValidQueueName($queueName = '') - { - if (preg_match("/^[a-z0-9][a-z0-9-]*$/", $queueName) === 0) { - return false; - } - - if (strpos($queueName, '--') !== false) { - return false; - } - - if (strtolower($queueName) != $queueName) { - return false; - } - - if (strlen($queueName) < 3 || strlen($queueName) > 63) { - return false; - } - - if (substr($queueName, -1) == '-') { - return false; - } - - return true; - } - - /** - * Get error message from Zend_Http_Response - * - * @param Zend_Http_Response $response Repsonse - * @param string $alternativeError Alternative error message - * @return string - */ - protected function _getErrorMessage(Zend_Http_Response $response, $alternativeError = 'Unknown error.') - { - $response = $this->_parseResponse($response); - if ($response && $response->Message) { - return (string)$response->Message; - } else { - return $alternativeError; - } - } -} diff --git a/lib/zend/Zend/Service/WindowsAzure/Storage/QueueMessage.php b/lib/zend/Zend/Service/WindowsAzure/Storage/QueueMessage.php deleted file mode 100644 index 2317489d52a..00000000000 --- a/lib/zend/Zend/Service/WindowsAzure/Storage/QueueMessage.php +++ /dev/null @@ -1,101 +0,0 @@ -_data = array( - 'messageid' => $messageId, - 'insertiontime' => $insertionTime, - 'expirationtime' => $expirationTime, - 'popreceipt' => $popReceipt, - 'timenextvisible' => $timeNextVisible, - 'messagetext' => $messageText - ); - } - - /** - * Magic overload for setting properties - * - * @param string $name Name of the property - * @param string $value Value to set - */ - public function __set($name, $value) { - if (array_key_exists(strtolower($name), $this->_data)) { - $this->_data[strtolower($name)] = $value; - return; - } - - throw new Exception("Unknown property: " . $name); - } - - /** - * Magic overload for getting properties - * - * @param string $name Name of the property - */ - public function __get($name) { - if (array_key_exists(strtolower($name), $this->_data)) { - return $this->_data[strtolower($name)]; - } - - throw new Exception("Unknown property: " . $name); - } -} diff --git a/lib/zend/Zend/Service/WindowsAzure/Storage/SignedIdentifier.php b/lib/zend/Zend/Service/WindowsAzure/Storage/SignedIdentifier.php deleted file mode 100644 index cd262fbd560..00000000000 --- a/lib/zend/Zend/Service/WindowsAzure/Storage/SignedIdentifier.php +++ /dev/null @@ -1,94 +0,0 @@ -_data = array( - 'id' => $id, - 'start' => $start, - 'expiry' => $expiry, - 'permissions' => $permissions - ); - } - - /** - * Magic overload for setting properties - * - * @param string $name Name of the property - * @param string $value Value to set - */ - public function __set($name, $value) { - if (array_key_exists(strtolower($name), $this->_data)) { - $this->_data[strtolower($name)] = $value; - return; - } - - throw new Exception("Unknown property: " . $name); - } - - /** - * Magic overload for getting properties - * - * @param string $name Name of the property - */ - public function __get($name) { - if (array_key_exists(strtolower($name), $this->_data)) { - return $this->_data[strtolower($name)]; - } - - throw new Exception("Unknown property: " . $name); - } -} diff --git a/lib/zend/Zend/Service/WindowsAzure/Storage/Table.php b/lib/zend/Zend/Service/WindowsAzure/Storage/Table.php deleted file mode 100644 index 0307f09bd9c..00000000000 --- a/lib/zend/Zend/Service/WindowsAzure/Storage/Table.php +++ /dev/null @@ -1,816 +0,0 @@ -_credentials = new Zend_Service_WindowsAzure_Credentials_SharedKeyLite($accountName, $accountKey, $this->_usePathStyleUri); - - // API version - $this->_apiVersion = '2009-04-14'; - } - - /** - * Check if a table exists - * - * @param string $tableName Table name - * @return boolean - */ - public function tableExists($tableName = '') - { - if ($tableName === '') { - throw new Zend_Service_WindowsAzure_Exception('Table name is not specified.'); - } - - // List tables - $tables = $this->listTables($tableName); - foreach ($tables as $table) { - if ($table->Name == $tableName) { - return true; - } - } - - return false; - } - - /** - * List tables - * - * @param string $nextTableName Next table name, used for listing tables when total amount of tables is > 1000. - * @return array - * @throws Zend_Service_WindowsAzure_Exception - */ - public function listTables($nextTableName = '') - { - // Build query string - $queryString = ''; - if ($nextTableName != '') { - $queryString = '?NextTableName=' . $nextTableName; - } - - // Perform request - $response = $this->_performRequest('Tables', $queryString, Zend_Http_Client::GET, null, true); - if ($response->isSuccessful()) { - // Parse result - $result = $this->_parseResponse($response); - - if (!$result || !$result->entry) { - return array(); - } - - $entries = null; - if (count($result->entry) > 1) { - $entries = $result->entry; - } else { - $entries = array($result->entry); - } - - // Create return value - $returnValue = array(); - foreach ($entries as $entry) { - $tableName = $entry->xpath('.//m:properties/d:TableName'); - $tableName = (string)$tableName[0]; - - $returnValue[] = new Zend_Service_WindowsAzure_Storage_TableInstance( - (string)$entry->id, - $tableName, - (string)$entry->link['href'], - (string)$entry->updated - ); - } - - // More tables? - if (!is_null($response->getHeader('x-ms-continuation-NextTableName'))) { - $returnValue = array_merge($returnValue, $this->listTables($response->getHeader('x-ms-continuation-NextTableName'))); - } - - return $returnValue; - } else { - throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); - } - } - - /** - * Create table - * - * @param string $tableName Table name - * @return Zend_Service_WindowsAzure_Storage_TableInstance - * @throws Zend_Service_WindowsAzure_Exception - */ - public function createTable($tableName = '') - { - if ($tableName === '') { - throw new Zend_Service_WindowsAzure_Exception('Table name is not specified.'); - } - - // Generate request body - $requestBody = ' - - - <updated>{tpl:Updated}</updated> - <author> - <name /> - </author> - <id /> - <content type="application/xml"> - <m:properties> - <d:TableName>{tpl:TableName}</d:TableName> - </m:properties> - </content> - </entry>'; - - $requestBody = $this->_fillTemplate($requestBody, array( - 'BaseUrl' => $this->getBaseUrl(), - 'TableName' => htmlspecialchars($tableName), - 'Updated' => $this->isoDate(), - 'AccountName' => $this->_accountName - )); - - // Add header information - $headers = array(); - $headers['Content-Type'] = 'application/atom+xml'; - $headers['DataServiceVersion'] = '1.0;NetFx'; - $headers['MaxDataServiceVersion'] = '1.0;NetFx'; - - // Perform request - $response = $this->_performRequest('Tables', '', Zend_Http_Client::POST, $headers, true, $requestBody); - if ($response->isSuccessful()) { - // Parse response - $entry = $this->_parseResponse($response); - - $tableName = $entry->xpath('.//m:properties/d:TableName'); - $tableName = (string)$tableName[0]; - - return new Zend_Service_WindowsAzure_Storage_TableInstance( - (string)$entry->id, - $tableName, - (string)$entry->link['href'], - (string)$entry->updated - ); - } else { - throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); - } - } - - /** - * Delete table - * - * @param string $tableName Table name - * @throws Zend_Service_WindowsAzure_Exception - */ - public function deleteTable($tableName = '') - { - if ($tableName === '') { - throw new Zend_Service_WindowsAzure_Exception('Table name is not specified.'); - } - - // Add header information - $headers = array(); - $headers['Content-Type'] = 'application/atom+xml'; - - // Perform request - $response = $this->_performRequest('Tables(\'' . $tableName . '\')', '', Zend_Http_Client::DELETE, $headers, true, null); - if (!$response->isSuccessful()) { - throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); - } - } - - /** - * Insert entity into table - * - * @param string $tableName Table name - * @param Zend_Service_WindowsAzure_Storage_TableEntity $entity Entity to insert - * @return Zend_Service_WindowsAzure_Storage_TableEntity - * @throws Zend_Service_WindowsAzure_Exception - */ - public function insertEntity($tableName = '', Zend_Service_WindowsAzure_Storage_TableEntity $entity = null) - { - if ($tableName === '') { - throw new Zend_Service_WindowsAzure_Exception('Table name is not specified.'); - } - if (is_null($entity)) { - throw new Zend_Service_WindowsAzure_Exception('Entity is not specified.'); - } - - // Generate request body - $requestBody = '<?xml version="1.0" encoding="utf-8" standalone="yes"?> - <entry xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom"> - <title /> - <updated>{tpl:Updated}</updated> - <author> - <name /> - </author> - <id /> - <content type="application/xml"> - <m:properties> - {tpl:Properties} - </m:properties> - </content> - </entry>'; - - $requestBody = $this->_fillTemplate($requestBody, array( - 'Updated' => $this->isoDate(), - 'Properties' => $this->_generateAzureRepresentation($entity) - )); - - // Add header information - $headers = array(); - $headers['Content-Type'] = 'application/atom+xml'; - - // Perform request - $response = null; - if ($this->isInBatch()) { - $this->getCurrentBatch()->enlistOperation($tableName, '', Zend_Http_Client::POST, $headers, true, $requestBody); - return null; - } else { - $response = $this->_performRequest($tableName, '', Zend_Http_Client::POST, $headers, true, $requestBody); - } - if ($response->isSuccessful()) { - // Parse result - $result = $this->_parseResponse($response); - - $timestamp = $result->xpath('//m:properties/d:Timestamp'); - $timestamp = (string)$timestamp[0]; - - $etag = $result->attributes('http://schemas.microsoft.com/ado/2007/08/dataservices/metadata'); - $etag = (string)$etag['etag']; - - // Update properties - $entity->setTimestamp($timestamp); - $entity->setEtag($etag); - - return $entity; - } else { - throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); - } - } - - /** - * Delete entity from table - * - * @param string $tableName Table name - * @param Zend_Service_WindowsAzure_Storage_TableEntity $entity Entity to delete - * @param boolean $verifyEtag Verify etag of the entity (used for concurrency) - * @throws Zend_Service_WindowsAzure_Exception - */ - public function deleteEntity($tableName = '', Zend_Service_WindowsAzure_Storage_TableEntity $entity = null, $verifyEtag = false) - { - if ($tableName === '') { - throw new Zend_Service_WindowsAzure_Exception('Table name is not specified.'); - } - if (is_null($entity)) { - throw new Zend_Service_WindowsAzure_Exception('Entity is not specified.'); - } - - // Add header information - $headers = array(); - if (!$this->isInBatch()) { - // http://social.msdn.microsoft.com/Forums/en-US/windowsazure/thread/9e255447-4dc7-458a-99d3-bdc04bdc5474/ - $headers['Content-Type'] = 'application/atom+xml'; - } - $headers['Content-Length'] = 0; - if (!$verifyEtag) { - $headers['If-Match'] = '*'; - } else { - $headers['If-Match'] = $entity->getEtag(); - } - - // Perform request - $response = null; - if ($this->isInBatch()) { - $this->getCurrentBatch()->enlistOperation($tableName . '(PartitionKey=\'' . $entity->getPartitionKey() . '\', RowKey=\'' . $entity->getRowKey() . '\')', '', Zend_Http_Client::DELETE, $headers, true, null); - return null; - } else { - $response = $this->_performRequest($tableName . '(PartitionKey=\'' . $entity->getPartitionKey() . '\', RowKey=\'' . $entity->getRowKey() . '\')', '', Zend_Http_Client::DELETE, $headers, true, null); - } - if (!$response->isSuccessful()) { - throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); - } - } - - /** - * Retrieve entity from table, by id - * - * @param string $tableName Table name - * @param string $partitionKey Partition key - * @param string $rowKey Row key - * @param string $entityClass Entity class name* - * @return Zend_Service_WindowsAzure_Storage_TableEntity - * @throws Zend_Service_WindowsAzure_Exception - */ - public function retrieveEntityById($tableName = '', $partitionKey = '', $rowKey = '', $entityClass = 'Zend_Service_WindowsAzure_Storage_DynamicTableEntity') - { - if ($tableName === '') { - throw new Zend_Service_WindowsAzure_Exception('Table name is not specified.'); - } - if ($partitionKey === '') { - throw new Zend_Service_WindowsAzure_Exception('Partition key is not specified.'); - } - if ($rowKey === '') { - throw new Zend_Service_WindowsAzure_Exception('Row key is not specified.'); - } - if ($entityClass === '') { - throw new Zend_Service_WindowsAzure_Exception('Entity class is not specified.'); - } - - - // Check for combined size of partition key and row key - // http://msdn.microsoft.com/en-us/library/dd179421.aspx - if (strlen($partitionKey . $rowKey) >= 256) { - // Start a batch if possible - if ($this->isInBatch()) { - throw new Zend_Service_WindowsAzure_Exception('Entity cannot be retrieved. A transaction is required to retrieve the entity, but another transaction is already active.'); - } - - $this->startBatch(); - } - - // Fetch entities from Azure - $result = $this->retrieveEntities( - $this->select() - ->from($tableName) - ->wherePartitionKey($partitionKey) - ->whereRowKey($rowKey), - '', - $entityClass - ); - - // Return - if (count($result) == 1) { - return $result[0]; - } - - return null; - } - - /** - * Create a new Zend_Service_WindowsAzure_Storage_TableEntityQuery - * - * @return Zend_Service_WindowsAzure_Storage_TableEntityQuery - */ - public function select() - { - return new Zend_Service_WindowsAzure_Storage_TableEntityQuery(); - } - - /** - * Retrieve entities from table - * - * @param string $tableName|Zend_Service_WindowsAzure_Storage_TableEntityQuery Table name -or- Zend_Service_WindowsAzure_Storage_TableEntityQuery instance - * @param string $filter Filter condition (not applied when $tableName is a Zend_Service_WindowsAzure_Storage_TableEntityQuery instance) - * @param string $entityClass Entity class name - * @param string $nextPartitionKey Next partition key, used for listing entities when total amount of entities is > 1000. - * @param string $nextRowKey Next row key, used for listing entities when total amount of entities is > 1000. - * @return array Array of Zend_Service_WindowsAzure_Storage_TableEntity - * @throws Zend_Service_WindowsAzure_Exception - */ - public function retrieveEntities($tableName = '', $filter = '', $entityClass = 'Zend_Service_WindowsAzure_Storage_DynamicTableEntity', $nextPartitionKey = null, $nextRowKey = null) - { - if ($tableName === '') { - throw new Zend_Service_WindowsAzure_Exception('Table name is not specified.'); - } - if ($entityClass === '') { - throw new Zend_Service_WindowsAzure_Exception('Entity class is not specified.'); - } - - // Convenience... - if (class_exists($filter)) { - $entityClass = $filter; - $filter = ''; - } - - // Query string - $queryString = ''; - - // Determine query - if (is_string($tableName)) { - // Option 1: $tableName is a string - - // Append parentheses - $tableName .= '()'; - - // Build query - $query = array(); - - // Filter? - if ($filter !== '') { - $query[] = '$filter=' . rawurlencode($filter); - } - - // Build queryString - if (count($query) > 0) { - $queryString = '?' . implode('&', $query); - } - } else if (get_class($tableName) == 'Zend_Service_WindowsAzure_Storage_TableEntityQuery') { - // Option 2: $tableName is a Zend_Service_WindowsAzure_Storage_TableEntityQuery instance - - // Build queryString - $queryString = $tableName->assembleQueryString(true); - - // Change $tableName - $tableName = $tableName->assembleFrom(true); - } else { - throw new Zend_Service_WindowsAzure_Exception('Invalid argument: $tableName'); - } - - // Add continuation querystring parameters? - if (!is_null($nextPartitionKey) && !is_null($nextRowKey)) { - if ($queryString !== '') { - $queryString .= '&'; - } - - $queryString .= '&NextPartitionKey=' . rawurlencode($nextPartitionKey) . '&NextRowKey=' . rawurlencode($nextRowKey); - } - - // Perform request - $response = null; - if ($this->isInBatch() && $this->getCurrentBatch()->getOperationCount() == 0) { - $this->getCurrentBatch()->enlistOperation($tableName, $queryString, Zend_Http_Client::GET, array(), true, null); - $response = $this->getCurrentBatch()->commit(); - - // Get inner response (multipart) - $innerResponse = $response->getBody(); - $innerResponse = substr($innerResponse, strpos($innerResponse, 'HTTP/1.1 200 OK')); - $innerResponse = substr($innerResponse, 0, strpos($innerResponse, '--batchresponse')); - $response = Zend_Http_Response::fromString($innerResponse); - } else { - $response = $this->_performRequest($tableName, $queryString, Zend_Http_Client::GET, array(), true, null); - } - - if ($response->isSuccessful()) { - // Parse result - $result = $this->_parseResponse($response); - if (!$result) { - return array(); - } - - $entries = null; - if ($result->entry) { - if (count($result->entry) > 1) { - $entries = $result->entry; - } else { - $entries = array($result->entry); - } - } else { - // This one is tricky... If we have properties defined, we have an entity. - $properties = $result->xpath('//m:properties'); - if ($properties) { - $entries = array($result); - } else { - return array(); - } - } - - // Create return value - $returnValue = array(); - foreach ($entries as $entry) { - // Parse properties - $properties = $entry->xpath('.//m:properties'); - $properties = $properties[0]->children('http://schemas.microsoft.com/ado/2007/08/dataservices'); - - // Create entity - $entity = new $entityClass('', ''); - $entity->setAzureValues((array)$properties, true); - - // If we have a Zend_Service_WindowsAzure_Storage_DynamicTableEntity, make sure all property types are OK - if ($entity instanceof Zend_Service_WindowsAzure_Storage_DynamicTableEntity) { - foreach ($properties as $key => $value) { - $attributes = $value->attributes('http://schemas.microsoft.com/ado/2007/08/dataservices/metadata'); - $type = (string)$attributes['type']; - if ($type !== '') { - $entity->setAzurePropertyType($key, $type); - } - } - } - - // Update etag - $etag = $entry->attributes('http://schemas.microsoft.com/ado/2007/08/dataservices/metadata'); - $etag = (string)$etag['etag']; - $entity->setEtag($etag); - - // Add to result - $returnValue[] = $entity; - } - - // More entities? - if (!is_null($response->getHeader('x-ms-continuation-NextPartitionKey')) && !is_null($response->getHeader('x-ms-continuation-NextRowKey'))) { - if (strpos($queryString, '$top') === false) { - $returnValue = array_merge($returnValue, $this->retrieveEntities($tableName, $filter, $entityClass, $response->getHeader('x-ms-continuation-NextPartitionKey'), $response->getHeader('x-ms-continuation-NextRowKey'))); - } - } - - // Return - return $returnValue; - } else { - throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); - } - } - - /** - * Update entity by replacing it - * - * @param string $tableName Table name - * @param Zend_Service_WindowsAzure_Storage_TableEntity $entity Entity to update - * @param boolean $verifyEtag Verify etag of the entity (used for concurrency) - * @throws Zend_Service_WindowsAzure_Exception - */ - public function updateEntity($tableName = '', Zend_Service_WindowsAzure_Storage_TableEntity $entity = null, $verifyEtag = false) - { - return $this->_changeEntity(Zend_Http_Client::PUT, $tableName, $entity, $verifyEtag); - } - - /** - * Update entity by adding or updating properties - * - * @param string $tableName Table name - * @param Zend_Service_WindowsAzure_Storage_TableEntity $entity Entity to update - * @param boolean $verifyEtag Verify etag of the entity (used for concurrency) - * @param array $properties Properties to merge. All properties will be used when omitted. - * @throws Zend_Service_WindowsAzure_Exception - */ - public function mergeEntity($tableName = '', Zend_Service_WindowsAzure_Storage_TableEntity $entity = null, $verifyEtag = false, $properties = array()) - { - $mergeEntity = null; - if (is_array($properties) && count($properties) > 0) { - // Build a new object - $mergeEntity = new Zend_Service_WindowsAzure_Storage_DynamicTableEntity($entity->getPartitionKey(), $entity->getRowKey()); - - // Keep only values mentioned in $properties - $azureValues = $entity->getAzureValues(); - foreach ($azureValues as $key => $value) { - if (in_array($value->Name, $properties)) { - $mergeEntity->setAzureProperty($value->Name, $value->Value, $value->Type); - } - } - } else { - $mergeEntity = $entity; - } - - return $this->_changeEntity(Zend_Http_Client::MERGE, $tableName, $mergeEntity, $verifyEtag); - } - - /** - * Get error message from Zend_Http_Response - * - * @param Zend_Http_Response $response Repsonse - * @param string $alternativeError Alternative error message - * @return string - */ - protected function _getErrorMessage(Zend_Http_Response $response, $alternativeError = 'Unknown error.') - { - $response = $this->_parseResponse($response); - if ($response && $response->message) { - return (string)$response->message; - } else { - return $alternativeError; - } - } - - /** - * Update entity / merge entity - * - * @param string $httpVerb HTTP verb to use (PUT = update, MERGE = merge) - * @param string $tableName Table name - * @param Zend_Service_WindowsAzure_Storage_TableEntity $entity Entity to update - * @param boolean $verifyEtag Verify etag of the entity (used for concurrency) - * @throws Zend_Service_WindowsAzure_Exception - */ - protected function _changeEntity($httpVerb = Zend_Http_Client::PUT, $tableName = '', Zend_Service_WindowsAzure_Storage_TableEntity $entity = null, $verifyEtag = false) - { - if ($tableName === '') { - throw new Zend_Service_WindowsAzure_Exception('Table name is not specified.'); - } - if (is_null($entity)) { - throw new Zend_Service_WindowsAzure_Exception('Entity is not specified.'); - } - - // Add header information - $headers = array(); - $headers['Content-Type'] = 'application/atom+xml'; - $headers['Content-Length'] = 0; - if (!$verifyEtag) { - $headers['If-Match'] = '*'; - } else { - $headers['If-Match'] = $entity->getEtag(); - } - - // Generate request body - $requestBody = '<?xml version="1.0" encoding="utf-8" standalone="yes"?> - <entry xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom"> - <title /> - <updated>{tpl:Updated}</updated> - <author> - <name /> - </author> - <id /> - <content type="application/xml"> - <m:properties> - {tpl:Properties} - </m:properties> - </content> - </entry>'; - - $requestBody = $this->_fillTemplate($requestBody, array( - 'Updated' => $this->isoDate(), - 'Properties' => $this->_generateAzureRepresentation($entity) - )); - - // Add header information - $headers = array(); - $headers['Content-Type'] = 'application/atom+xml'; - if (!$verifyEtag) { - $headers['If-Match'] = '*'; - } else { - $headers['If-Match'] = $entity->getEtag(); - } - - // Perform request - $response = null; - if ($this->isInBatch()) { - $this->getCurrentBatch()->enlistOperation($tableName . '(PartitionKey=\'' . $entity->getPartitionKey() . '\', RowKey=\'' . $entity->getRowKey() . '\')', '', $httpVerb, $headers, true, $requestBody); - return null; - } else { - $response = $this->_performRequest($tableName . '(PartitionKey=\'' . $entity->getPartitionKey() . '\', RowKey=\'' . $entity->getRowKey() . '\')', '', $httpVerb, $headers, true, $requestBody); - } - if ($response->isSuccessful()) { - // Update properties - $entity->setEtag($response->getHeader('Etag')); - $entity->setTimestamp($response->getHeader('Last-modified')); - - return $entity; - } else { - throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); - } - } - - /** - * Generate RFC 1123 compliant date string - * - * @return string - */ - protected function _rfcDate() - { - return gmdate('D, d M Y H:i:s', time()) . ' GMT'; // RFC 1123 - } - - /** - * Fill text template with variables from key/value array - * - * @param string $templateText Template text - * @param array $variables Array containing key/value pairs - * @return string - */ - protected function _fillTemplate($templateText, $variables = array()) - { - foreach ($variables as $key => $value) { - $templateText = str_replace('{tpl:' . $key . '}', $value, $templateText); - } - return $templateText; - } - - /** - * Generate Azure representation from entity (creates atompub markup from properties) - * - * @param Zend_Service_WindowsAzure_Storage_TableEntity $entity - * @return string - */ - protected function _generateAzureRepresentation(Zend_Service_WindowsAzure_Storage_TableEntity $entity = null) - { - // Generate Azure representation from entity - $azureRepresentation = array(); - $azureValues = $entity->getAzureValues(); - foreach ($azureValues as $azureValue) { - $value = array(); - $value[] = '<d:' . $azureValue->Name; - if ($azureValue->Type != '') { - $value[] = ' m:type="' . $azureValue->Type . '"'; - } - if (is_null($azureValue->Value)) { - $value[] = ' m:null="true"'; - } - $value[] = '>'; - - if (!is_null($azureValue->Value)) { - if (strtolower($azureValue->Type) == 'edm.boolean') { - $value[] = ($azureValue->Value == true ? '1' : '0'); - } else { - $value[] = htmlspecialchars($azureValue->Value); - } - } - - $value[] = '</d:' . $azureValue->Name . '>'; - $azureRepresentation[] = implode('', $value); - } - - return implode('', $azureRepresentation); - } -} diff --git a/lib/zend/Zend/Service/WindowsAzure/Storage/TableEntity.php b/lib/zend/Zend/Service/WindowsAzure/Storage/TableEntity.php deleted file mode 100644 index 0cd1a5297c3..00000000000 --- a/lib/zend/Zend/Service/WindowsAzure/Storage/TableEntity.php +++ /dev/null @@ -1,323 +0,0 @@ -<?php -/** - * Zend Framework - * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Service_WindowsAzure - * @subpackage Storage - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id$ - */ - -/** - * @see Zend_Service_WindowsAzure_Exception - */ -require_once 'Zend/Service/WindowsAzure/Exception.php'; - - -/** - * @category Zend - * @package Zend_Service_WindowsAzure - * @subpackage Storage - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - */ -class Zend_Service_WindowsAzure_Storage_TableEntity -{ - /** - * Partition key - * - * @var string - */ - protected $_partitionKey; - - /** - * Row key - * - * @var string - */ - protected $_rowKey; - - /** - * Timestamp - * - * @var string - */ - protected $_timestamp = '1900-01-01T00:00:00'; - - /** - * Etag - * - * @var string - */ - protected $_etag = ''; - - /** - * Constructor - * - * @param string $partitionKey Partition key - * @param string $rowKey Row key - */ - public function __construct($partitionKey = '', $rowKey = '') - { - $this->_partitionKey = $partitionKey; - $this->_rowKey = $rowKey; - } - - /** - * Get partition key - * - * @azure PartitionKey - * @return string - */ - public function getPartitionKey() - { - return $this->_partitionKey; - } - - /** - * Set partition key - * - * @azure PartitionKey - * @param string $value - */ - public function setPartitionKey($value) - { - $this->_partitionKey = $value; - } - - /** - * Get row key - * - * @azure RowKey - * @return string - */ - public function getRowKey() - { - return $this->_rowKey; - } - - /** - * Set row key - * - * @azure RowKey - * @param string $value - */ - public function setRowKey($value) - { - $this->_rowKey = $value; - } - - /** - * Get timestamp - * - * @azure Timestamp Edm.DateTime - * @return string - */ - public function getTimestamp() - { - return $this->_timestamp; - } - - /** - * Set timestamp - * - * @azure Timestamp Edm.DateTime - * @param string $value - */ - public function setTimestamp($value = '1900-01-01T00:00:00') - { - $this->_timestamp = $value; - } - - /** - * Get etag - * - * @return string - */ - public function getEtag() - { - return $this->_etag; - } - - /** - * Set etag - * - * @param string $value - */ - public function setEtag($value = '') - { - $this->_etag = $value; - } - - /** - * Get Azure values - * - * @return array - */ - public function getAzureValues() - { - // Get accessors - $accessors = self::getAzureAccessors(get_class($this)); - - // Loop accessors and retrieve values - $returnValue = array(); - foreach ($accessors as $accessor) { - if ($accessor->EntityType == 'ReflectionProperty') { - $property = $accessor->EntityAccessor; - $returnValue[] = (object)array( - 'Name' => $accessor->AzurePropertyName, - 'Type' => $accessor->AzurePropertyType, - 'Value' => $this->$property, - ); - } else if ($accessor->EntityType == 'ReflectionMethod' && substr(strtolower($accessor->EntityAccessor), 0, 3) == 'get') { - $method = $accessor->EntityAccessor; - $returnValue[] = (object)array( - 'Name' => $accessor->AzurePropertyName, - 'Type' => $accessor->AzurePropertyType, - 'Value' => $this->$method(), - ); - } - } - - // Return - return $returnValue; - } - - /** - * Set Azure values - * - * @param array $values - * @param boolean $throwOnError Throw Zend_Service_WindowsAzure_Exception when a property is not specified in $values? - * @throws Zend_Service_WindowsAzure_Exception - */ - public function setAzureValues($values = array(), $throwOnError = false) - { - // Get accessors - $accessors = self::getAzureAccessors(get_class($this)); - - // Loop accessors and set values - $returnValue = array(); - foreach ($accessors as $accessor) { - if (isset($values[$accessor->AzurePropertyName])) { - // Cast to correct type - if ($accessor->AzurePropertyType != '') { - switch (strtolower($accessor->AzurePropertyType)) { - case 'edm.int32': - case 'edm.int64': - $values[$accessor->AzurePropertyName] = intval($values[$accessor->AzurePropertyName]); break; - case 'edm.boolean': - if ($values[$accessor->AzurePropertyName] == 'true' || $values[$accessor->AzurePropertyName] == '1') - $values[$accessor->AzurePropertyName] = true; - else - $values[$accessor->AzurePropertyName] = false; - break; - case 'edm.double': - $values[$accessor->AzurePropertyName] = floatval($values[$accessor->AzurePropertyName]); break; - } - } - - // Assign value - if ($accessor->EntityType == 'ReflectionProperty') { - $property = $accessor->EntityAccessor; - $this->$property = $values[$accessor->AzurePropertyName]; - } else if ($accessor->EntityType == 'ReflectionMethod' && substr(strtolower($accessor->EntityAccessor), 0, 3) == 'set') { - $method = $accessor->EntityAccessor; - $this->$method($values[$accessor->AzurePropertyName]); - } - } else if ($throwOnError) { - throw new Zend_Service_WindowsAzure_Exception("Property '" . $accessor->AzurePropertyName . "' was not found in \$values array"); - } - } - - // Return - return $returnValue; - } - - /** - * Get Azure accessors from class - * - * @param string $className Class to get accessors for - * @return array - */ - public static function getAzureAccessors($className = '') - { - // List of accessors - $azureAccessors = array(); - - // Get all types - $type = new ReflectionClass($className); - - // Loop all properties - $properties = $type->getProperties(); - foreach ($properties as $property) { - $accessor = self::getAzureAccessor($property); - if (!is_null($accessor)) { - $azureAccessors[] = $accessor; - } - } - - // Loop all methods - $methods = $type->getMethods(); - foreach ($methods as $method) { - $accessor = self::getAzureAccessor($method); - if (!is_null($accessor)) { - $azureAccessors[] = $accessor; - } - } - - // Return - return $azureAccessors; - } - - /** - * Get Azure accessor from reflection member - * - * @param ReflectionProperty|ReflectionMethod $member - * @return object - */ - public static function getAzureAccessor($member) - { - // Get comment - $docComment = $member->getDocComment(); - - // Check for Azure comment - if (strpos($docComment, '@azure') === false) - { - return null; - } - - // Search for @azure contents - $azureComment = ''; - $commentLines = explode("\n", $docComment); - foreach ($commentLines as $commentLine) { - if (strpos($commentLine, '@azure') !== false) { - $azureComment = trim(substr($commentLine, strpos($commentLine, '@azure') + 6)); - while (strpos($azureComment, ' ') !== false) { - $azureComment = str_replace(' ', ' ', $azureComment); - } - break; - } - } - - // Fetch @azure properties - $azureProperties = explode(' ', $azureComment); - return (object)array( - 'EntityAccessor' => $member->getName(), - 'EntityType' => get_class($member), - 'AzurePropertyName' => $azureProperties[0], - 'AzurePropertyType' => isset($azureProperties[1]) ? $azureProperties[1] : '' - ); - } -} diff --git a/lib/zend/Zend/Service/WindowsAzure/Storage/TableEntityQuery.php b/lib/zend/Zend/Service/WindowsAzure/Storage/TableEntityQuery.php deleted file mode 100644 index 8da0b0ffb9b..00000000000 --- a/lib/zend/Zend/Service/WindowsAzure/Storage/TableEntityQuery.php +++ /dev/null @@ -1,326 +0,0 @@ -<?php -/** - * Zend Framework - * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Service_WindowsAzure - * @subpackage Storage - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id$ - */ - -/** - * @category Zend - * @package Zend_Service_WindowsAzure - * @subpackage Storage - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - */ -class Zend_Service_WindowsAzure_Storage_TableEntityQuery -{ - /** - * From - * - * @var string - */ - protected $_from = ''; - - /** - * Where - * - * @var array - */ - protected $_where = array(); - - /** - * Order by - * - * @var array - */ - protected $_orderBy = array(); - - /** - * Top - * - * @var int - */ - protected $_top = null; - - /** - * Partition key - * - * @var string - */ - protected $_partitionKey = null; - - /** - * Row key - * - * @var string - */ - protected $_rowKey = null; - - /** - * Select clause - * - * @return Zend_Service_WindowsAzure_Storage_TableEntityQuery - */ - public function select() - { - return $this; - } - - /** - * From clause - * - * @param string $name Table name to select entities from - * @return Zend_Service_WindowsAzure_Storage_TableEntityQuery - */ - public function from($name) - { - $this->_from = $name; - return $this; - } - - /** - * Specify partition key - * - * @param string $value Partition key to query for - * @return Zend_Service_WindowsAzure_Storage_TableEntityQuery - */ - public function wherePartitionKey($value = null) - { - $this->_partitionKey = $value; - return $this; - } - - /** - * Specify row key - * - * @param string $value Row key to query for - * @return Zend_Service_WindowsAzure_Storage_TableEntityQuery - */ - public function whereRowKey($value = null) - { - $this->_rowKey = $value; - return $this; - } - - /** - * Add where clause - * - * @param string $condition Condition, can contain question mark(s) (?) for parameter insertion. - * @param string|array $value Value(s) to insert in question mark (?) parameters. - * @param string $cond Condition for the clause (and/or/not) - * @return Zend_Service_WindowsAzure_Storage_TableEntityQuery - */ - public function where($condition, $value = null, $cond = '') - { - $condition = $this->_replaceOperators($condition); - - if (!is_null($value)) { - $condition = $this->_quoteInto($condition, $value); - } - - if (count($this->_where) == 0) { - $cond = ''; - } else if ($cond !== '') { - $cond = ' ' . strtolower(trim($cond)) . ' '; - } - - $this->_where[] = $cond . $condition; - return $this; - } - - /** - * Add where clause with AND condition - * - * @param string $condition Condition, can contain question mark(s) (?) for parameter insertion. - * @param string|array $value Value(s) to insert in question mark (?) parameters. - * @return Zend_Service_WindowsAzure_Storage_TableEntityQuery - */ - public function andWhere($condition, $value = null) - { - return $this->where($condition, $value, 'and'); - } - - /** - * Add where clause with OR condition - * - * @param string $condition Condition, can contain question mark(s) (?) for parameter insertion. - * @param string|array $value Value(s) to insert in question mark (?) parameters. - * @return Zend_Service_WindowsAzure_Storage_TableEntityQuery - */ - public function orWhere($condition, $value = null) - { - return $this->where($condition, $value, 'or'); - } - - /** - * OrderBy clause - * - * @param string $column Column to sort by - * @param string $direction Direction to sort (asc/desc) - * @return Zend_Service_WindowsAzure_Storage_TableEntityQuery - */ - public function orderBy($column, $direction = 'asc') - { - $this->_orderBy[] = $column . ' ' . $direction; - return $this; - } - - /** - * Top clause - * - * @param int $top Top to fetch - * @return Zend_Service_WindowsAzure_Storage_TableEntityQuery - */ - public function top($top = null) - { - $this->_top = (int)$top; - return $this; - } - - /** - * Assembles the query string - * - * @param boolean $urlEncode Apply URL encoding to the query string - * @return string - */ - public function assembleQueryString($urlEncode = false) - { - $query = array(); - if (count($this->_where) != 0) { - $filter = implode('', $this->_where); - $query[] = '$filter=' . ($urlEncode ? urlencode($filter) : $filter); - } - - if (count($this->_orderBy) != 0) { - $orderBy = implode(',', $this->_orderBy); - $query[] = '$orderby=' . ($urlEncode ? urlencode($orderBy) : $orderBy); - } - - if (!is_null($this->_top)) { - $query[] = '$top=' . $this->_top; - } - - if (count($query) != 0) { - return '?' . implode('&', $query); - } - - return ''; - } - - /** - * Assemble from - * - * @param boolean $includeParentheses Include parentheses? () - * @return string - */ - public function assembleFrom($includeParentheses = true) - { - $identifier = ''; - if ($includeParentheses) { - $identifier .= '('; - - if (!is_null($this->_partitionKey)) { - $identifier .= 'PartitionKey=\'' . $this->_partitionKey . '\''; - } - - if (!is_null($this->_partitionKey) && !is_null($this->_rowKey)) { - $identifier .= ', '; - } - - if (!is_null($this->_rowKey)) { - $identifier .= 'RowKey=\'' . $this->_rowKey . '\''; - } - - $identifier .= ')'; - } - return $this->_from . $identifier; - } - - /** - * Assemble full query - * - * @return string - */ - public function assembleQuery() - { - $assembledQuery = $this->assembleFrom(); - - $queryString = $this->assembleQueryString(); - if ($queryString !== '') { - $assembledQuery .= $queryString; - } - - return $assembledQuery; - } - - /** - * Quotes a variable into a condition - * - * @param string $text Condition, can contain question mark(s) (?) for parameter insertion. - * @param string|array $value Value(s) to insert in question mark (?) parameters. - * @return string - */ - protected function _quoteInto($text, $value = null) - { - if (!is_array($value)) { - $text = str_replace('?', '\'' . addslashes($value) . '\'', $text); - } else { - $i = 0; - while(strpos($text, '?') !== false) { - if (is_numeric($value[$i])) { - $text = substr_replace($text, $value[$i++], strpos($text, '?'), 1); - } else { - $text = substr_replace($text, '\'' . addslashes($value[$i++]) . '\'', strpos($text, '?'), 1); - } - } - } - return $text; - } - - /** - * Replace operators - * - * @param string $text - * @return string - */ - protected function _replaceOperators($text) - { - $text = str_replace('==', 'eq', $text); - $text = str_replace('>', 'gt', $text); - $text = str_replace('<', 'lt', $text); - $text = str_replace('>=', 'ge', $text); - $text = str_replace('<=', 'le', $text); - $text = str_replace('!=', 'ne', $text); - - $text = str_replace('&&', 'and', $text); - $text = str_replace('||', 'or', $text); - $text = str_replace('!', 'not', $text); - - return $text; - } - - /** - * __toString overload - * - * @return string - */ - public function __toString() - { - return $this->assembleQuery(); - } -} \ No newline at end of file diff --git a/lib/zend/Zend/Service/WindowsAzure/Storage/TableInstance.php b/lib/zend/Zend/Service/WindowsAzure/Storage/TableInstance.php deleted file mode 100644 index b0671eadb8b..00000000000 --- a/lib/zend/Zend/Service/WindowsAzure/Storage/TableInstance.php +++ /dev/null @@ -1,95 +0,0 @@ -<?php -/** - * Zend Framework - * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Service_WindowsAzure - * @subpackage Storage - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id$ - */ - -/** - * @see Zend_Service_WindowsAzure_Exception - */ -require_once 'Zend/Service/WindowsAzure/Exception.php'; - - -/** - * @category Zend - * @package Zend_Service_WindowsAzure - * @subpackage Storage - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * - * @property string $Id Id - * @property string $Name Name - * @property string $Href Href - * @property string $Updated Updated - */ -class Zend_Service_WindowsAzure_Storage_TableInstance -{ - /** - * Data - * - * @var array - */ - protected $_data = null; - - /** - * Constructor - * - * @param string $id Id - * @param string $name Name - * @param string $href Href - * @param string $updated Updated - */ - public function __construct($id, $name, $href, $updated) - { - $this->_data = array( - 'id' => $id, - 'name' => $name, - 'href' => $href, - 'updated' => $updated - ); - } - - /** - * Magic overload for setting properties - * - * @param string $name Name of the property - * @param string $value Value to set - */ - public function __set($name, $value) { - if (array_key_exists(strtolower($name), $this->_data)) { - $this->_data[strtolower($name)] = $value; - return; - } - - throw new Exception("Unknown property: " . $name); - } - - /** - * Magic overload for getting properties - * - * @param string $name Name of the property - */ - public function __get($name) { - if (array_key_exists(strtolower($name), $this->_data)) { - return $this->_data[strtolower($name)]; - } - - throw new Exception("Unknown property: " . $name); - } -} diff --git a/lib/zend/Zend/Service/Yahoo.php b/lib/zend/Zend/Service/Yahoo.php index 925232ccc4c..2503435e5aa 100644 --- a/lib/zend/Zend/Service/Yahoo.php +++ b/lib/zend/Zend/Service/Yahoo.php @@ -16,17 +16,19 @@ * @category Zend * @package Zend_Service * @subpackage Yahoo - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ +/** @see Zend_Xml_Security */ +require_once 'Zend/Xml/Security.php'; /** * @category Zend * @package Zend_Service * @subpackage Yahoo - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Service_Yahoo @@ -99,8 +101,7 @@ class Zend_Service_Yahoo } $dom = new DOMDocument(); - $dom->loadXML($response->getBody()); - + $dom = Zend_Xml_Security::scan($response->getBody(), $dom); self::_checkErrors($dom); /** @@ -155,8 +156,7 @@ class Zend_Service_Yahoo } $dom = new DOMDocument(); - $dom->loadXML($response->getBody()); - + $dom = Zend_Xml_Security::scan($response->getBody(), $dom); self::_checkErrors($dom); /** @@ -219,8 +219,7 @@ class Zend_Service_Yahoo } $dom = new DOMDocument(); - $dom->loadXML($response->getBody()); - + $dom = Zend_Xml_Security::scan($response->getBody(), $dom); self::_checkErrors($dom); /** @@ -273,8 +272,7 @@ class Zend_Service_Yahoo } $dom = new DOMDocument(); - $dom->loadXML($response->getBody()); - + $dom = Zend_Xml_Security::scan($response->getBody(), $dom); self::_checkErrors($dom); /** @@ -320,8 +318,7 @@ class Zend_Service_Yahoo } $dom = new DOMDocument(); - $dom->loadXML($response->getBody()); - + $dom = Zend_Xml_Security::scan($response->getBody(), $dom); self::_checkErrors($dom); /** @@ -374,8 +371,7 @@ class Zend_Service_Yahoo } $dom = new DOMDocument(); - $dom->loadXML($response->getBody()); - + $dom = Zend_Xml_Security::scan($response->getBody(), $dom); self::_checkErrors($dom); /** @@ -431,8 +427,7 @@ class Zend_Service_Yahoo } $dom = new DOMDocument(); - $dom->loadXML($response->getBody()); - + $dom = Zend_Xml_Security::scan($response->getBody(), $dom); self::_checkErrors($dom); /** diff --git a/lib/zend/Zend/Service/Yahoo/Image.php b/lib/zend/Zend/Service/Yahoo/Image.php index 30f3757a5db..defdddec45f 100644 --- a/lib/zend/Zend/Service/Yahoo/Image.php +++ b/lib/zend/Zend/Service/Yahoo/Image.php @@ -16,7 +16,7 @@ * @category Zend * @package Zend_Service * @subpackage Yahoo - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -26,7 +26,7 @@ * @category Zend * @package Zend_Service * @subpackage Yahoo - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Service_Yahoo_Image diff --git a/lib/zend/Zend/Service/Yahoo/ImageResult.php b/lib/zend/Zend/Service/Yahoo/ImageResult.php index 5c2909efeda..5f38b9a3eff 100644 --- a/lib/zend/Zend/Service/Yahoo/ImageResult.php +++ b/lib/zend/Zend/Service/Yahoo/ImageResult.php @@ -16,7 +16,7 @@ * @category Zend * @package Zend_Service * @subpackage Yahoo - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -32,7 +32,7 @@ require_once 'Zend/Service/Yahoo/Result.php'; * @category Zend * @package Zend_Service * @subpackage Yahoo - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Service_Yahoo_ImageResult extends Zend_Service_Yahoo_Result diff --git a/lib/zend/Zend/Service/Yahoo/ImageResultSet.php b/lib/zend/Zend/Service/Yahoo/ImageResultSet.php index 38d7f01f910..b8274683219 100644 --- a/lib/zend/Zend/Service/Yahoo/ImageResultSet.php +++ b/lib/zend/Zend/Service/Yahoo/ImageResultSet.php @@ -16,7 +16,7 @@ * @category Zend * @package Zend_Service * @subpackage Yahoo - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -38,7 +38,7 @@ require_once 'Zend/Service/Yahoo/ImageResult.php'; * @category Zend * @package Zend_Service * @subpackage Yahoo - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Service_Yahoo_ImageResultSet extends Zend_Service_Yahoo_ResultSet diff --git a/lib/zend/Zend/Service/Yahoo/InlinkDataResult.php b/lib/zend/Zend/Service/Yahoo/InlinkDataResult.php index 1ac6d1c24f6..f325aff8dcf 100644 --- a/lib/zend/Zend/Service/Yahoo/InlinkDataResult.php +++ b/lib/zend/Zend/Service/Yahoo/InlinkDataResult.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Service * @subpackage Yahoo - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -31,7 +31,7 @@ require_once 'Zend/Service/Yahoo/Result.php'; * @category Zend * @package Zend_Service * @subpackage Yahoo - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Service_Yahoo_InlinkDataResult extends Zend_Service_Yahoo_Result diff --git a/lib/zend/Zend/Service/Yahoo/InlinkDataResultSet.php b/lib/zend/Zend/Service/Yahoo/InlinkDataResultSet.php index d03bc7b91c8..3a8b815d103 100644 --- a/lib/zend/Zend/Service/Yahoo/InlinkDataResultSet.php +++ b/lib/zend/Zend/Service/Yahoo/InlinkDataResultSet.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Service * @subpackage Yahoo - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -37,7 +37,7 @@ require_once 'Zend/Service/Yahoo/InlinkDataResult.php'; * @category Zend * @package Zend_Service * @subpackage Yahoo - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Service_Yahoo_InlinkDataResultSet extends Zend_Service_Yahoo_ResultSet diff --git a/lib/zend/Zend/Service/Yahoo/LocalResult.php b/lib/zend/Zend/Service/Yahoo/LocalResult.php index bd7d9142632..9993e92835a 100644 --- a/lib/zend/Zend/Service/Yahoo/LocalResult.php +++ b/lib/zend/Zend/Service/Yahoo/LocalResult.php @@ -16,7 +16,7 @@ * @category Zend * @package Zend_Service * @subpackage Yahoo - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -32,7 +32,7 @@ require_once 'Zend/Service/Yahoo/Result.php'; * @category Zend * @package Zend_Service * @subpackage Yahoo - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Service_Yahoo_LocalResult extends Zend_Service_Yahoo_Result diff --git a/lib/zend/Zend/Service/Yahoo/LocalResultSet.php b/lib/zend/Zend/Service/Yahoo/LocalResultSet.php index 50ddf35bf84..d2228244e6d 100644 --- a/lib/zend/Zend/Service/Yahoo/LocalResultSet.php +++ b/lib/zend/Zend/Service/Yahoo/LocalResultSet.php @@ -16,7 +16,7 @@ * @category Zend * @package Zend_Service * @subpackage Yahoo - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -38,7 +38,7 @@ require_once 'Zend/Service/Yahoo/LocalResult.php'; * @category Zend * @package Zend_Service * @subpackage Yahoo - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Service_Yahoo_LocalResultSet extends Zend_Service_Yahoo_ResultSet diff --git a/lib/zend/Zend/Service/Yahoo/NewsResult.php b/lib/zend/Zend/Service/Yahoo/NewsResult.php index cb0e4327257..e71daef5789 100644 --- a/lib/zend/Zend/Service/Yahoo/NewsResult.php +++ b/lib/zend/Zend/Service/Yahoo/NewsResult.php @@ -16,7 +16,7 @@ * @category Zend * @package Zend_Service * @subpackage Yahoo - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -32,7 +32,7 @@ require_once 'Zend/Service/Yahoo/Result.php'; * @category Zend * @package Zend_Service * @subpackage Yahoo - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Service_Yahoo_NewsResult extends Zend_Service_Yahoo_Result diff --git a/lib/zend/Zend/Service/Yahoo/NewsResultSet.php b/lib/zend/Zend/Service/Yahoo/NewsResultSet.php index 695fad984aa..7f2c13120d1 100644 --- a/lib/zend/Zend/Service/Yahoo/NewsResultSet.php +++ b/lib/zend/Zend/Service/Yahoo/NewsResultSet.php @@ -16,7 +16,7 @@ * @category Zend * @package Zend_Service * @subpackage Yahoo - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -38,7 +38,7 @@ require_once 'Zend/Service/Yahoo/NewsResult.php'; * @category Zend * @package Zend_Service * @subpackage Yahoo - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Service_Yahoo_NewsResultSet extends Zend_Service_Yahoo_ResultSet diff --git a/lib/zend/Zend/Service/Yahoo/PageDataResult.php b/lib/zend/Zend/Service/Yahoo/PageDataResult.php index 34aa988223f..a4aa74da251 100644 --- a/lib/zend/Zend/Service/Yahoo/PageDataResult.php +++ b/lib/zend/Zend/Service/Yahoo/PageDataResult.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Service * @subpackage Yahoo - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -31,7 +31,7 @@ require_once 'Zend/Service/Yahoo/Result.php'; * @category Zend * @package Zend_Service * @subpackage Yahoo - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Service_Yahoo_PageDataResult extends Zend_Service_Yahoo_Result diff --git a/lib/zend/Zend/Service/Yahoo/PageDataResultSet.php b/lib/zend/Zend/Service/Yahoo/PageDataResultSet.php index f7e0c9d3a7a..60cd4a576f1 100644 --- a/lib/zend/Zend/Service/Yahoo/PageDataResultSet.php +++ b/lib/zend/Zend/Service/Yahoo/PageDataResultSet.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Service * @subpackage Yahoo - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -37,7 +37,7 @@ require_once 'Zend/Service/Yahoo/PageDataResult.php'; * @category Zend * @package Zend_Service * @subpackage Yahoo - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Service_Yahoo_PageDataResultSet extends Zend_Service_Yahoo_ResultSet diff --git a/lib/zend/Zend/Service/Yahoo/Result.php b/lib/zend/Zend/Service/Yahoo/Result.php index 23b5fa1bf11..fcd73d29d1a 100644 --- a/lib/zend/Zend/Service/Yahoo/Result.php +++ b/lib/zend/Zend/Service/Yahoo/Result.php @@ -16,7 +16,7 @@ * @category Zend * @package Zend_Service * @subpackage Yahoo - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -26,7 +26,7 @@ * @category Zend * @package Zend_Service * @subpackage Yahoo - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Service_Yahoo_Result diff --git a/lib/zend/Zend/Service/Yahoo/ResultSet.php b/lib/zend/Zend/Service/Yahoo/ResultSet.php index 57951d7179a..163cafb68b7 100644 --- a/lib/zend/Zend/Service/Yahoo/ResultSet.php +++ b/lib/zend/Zend/Service/Yahoo/ResultSet.php @@ -16,7 +16,7 @@ * @category Zend * @package Zend_Service * @subpackage Yahoo - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -26,7 +26,7 @@ * @category Zend * @package Zend_Service * @subpackage Yahoo - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Service_Yahoo_ResultSet implements SeekableIterator diff --git a/lib/zend/Zend/Service/Yahoo/VideoResult.php b/lib/zend/Zend/Service/Yahoo/VideoResult.php index c3f53578773..7aded46437e 100644 --- a/lib/zend/Zend/Service/Yahoo/VideoResult.php +++ b/lib/zend/Zend/Service/Yahoo/VideoResult.php @@ -16,7 +16,7 @@ * @category Zend * @package Zend_Service * @subpackage Yahoo - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -32,7 +32,7 @@ require_once 'Zend/Service/Yahoo/Result.php'; * @category Zend * @package Zend_Service * @subpackage Yahoo - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Service_Yahoo_VideoResult extends Zend_Service_Yahoo_Result diff --git a/lib/zend/Zend/Service/Yahoo/VideoResultSet.php b/lib/zend/Zend/Service/Yahoo/VideoResultSet.php index fe884cd7ee5..c26ff496e52 100644 --- a/lib/zend/Zend/Service/Yahoo/VideoResultSet.php +++ b/lib/zend/Zend/Service/Yahoo/VideoResultSet.php @@ -16,7 +16,7 @@ * @category Zend * @package Zend_Service * @subpackage Yahoo - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -38,7 +38,7 @@ require_once 'Zend/Service/Yahoo/VideoResult.php'; * @category Zend * @package Zend_Service * @subpackage Yahoo - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Service_Yahoo_VideoResultSet extends Zend_Service_Yahoo_ResultSet diff --git a/lib/zend/Zend/Service/Yahoo/WebResult.php b/lib/zend/Zend/Service/Yahoo/WebResult.php index ffffb99c263..7fa318473a6 100644 --- a/lib/zend/Zend/Service/Yahoo/WebResult.php +++ b/lib/zend/Zend/Service/Yahoo/WebResult.php @@ -16,7 +16,7 @@ * @category Zend * @package Zend_Service * @subpackage Yahoo - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -32,7 +32,7 @@ require_once 'Zend/Service/Yahoo/Result.php'; * @category Zend * @package Zend_Service * @subpackage Yahoo - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Service_Yahoo_WebResult extends Zend_Service_Yahoo_Result diff --git a/lib/zend/Zend/Service/Yahoo/WebResultSet.php b/lib/zend/Zend/Service/Yahoo/WebResultSet.php index e704a86fe1b..267f04b4bdb 100644 --- a/lib/zend/Zend/Service/Yahoo/WebResultSet.php +++ b/lib/zend/Zend/Service/Yahoo/WebResultSet.php @@ -16,7 +16,7 @@ * @category Zend * @package Zend_Service * @subpackage Yahoo - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -38,7 +38,7 @@ require_once 'Zend/Service/Yahoo/WebResult.php'; * @category Zend * @package Zend_Service * @subpackage Yahoo - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Service_Yahoo_WebResultSet extends Zend_Service_Yahoo_ResultSet diff --git a/lib/zend/Zend/Soap/AutoDiscover.php b/lib/zend/Zend/Soap/AutoDiscover.php index 1440e5ab667..f1df112ab74 100644 --- a/lib/zend/Zend/Soap/AutoDiscover.php +++ b/lib/zend/Zend/Soap/AutoDiscover.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Soap * @subpackage AutoDiscover - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -91,13 +91,21 @@ class Zend_Soap_AutoDiscover implements Zend_Server_Interface */ protected $_bindingStyle = array('style' => 'rpc', 'transport' => 'http://schemas.xmlsoap.org/soap/http'); + /** + * Name of the class to handle the WSDL creation. + * + * @var string + */ + protected $_wsdlClass = 'Zend_Soap_Wsdl'; + /** * Constructor * * @param boolean|string|Zend_Soap_Wsdl_Strategy_Interface $strategy * @param string|Zend_Uri $uri + * @param string $wsdlClass */ - public function __construct($strategy = true, $uri=null) + public function __construct($strategy = true, $uri=null, $wsdlClass=null) { $this->_reflection = new Zend_Server_Reflection(); $this->setComplexTypeStrategy($strategy); @@ -105,26 +113,30 @@ class Zend_Soap_AutoDiscover implements Zend_Server_Interface if($uri !== null) { $this->setUri($uri); } + + if($wsdlClass !== null) { + $this->setWsdlClass($wsdlClass); + } } /** * Set the location at which the WSDL file will be availabe. * * @see Zend_Soap_Exception - * @throws Zend_Soap_AutoDiscover_Exception * @param Zend_Uri|string $uri * @return Zend_Soap_AutoDiscover + * @throws Zend_Soap_AutoDiscover_Exception */ public function setUri($uri) { - if(!is_string($uri) && !($uri instanceof Zend_Uri)) { + if (!is_string($uri) && !($uri instanceof Zend_Uri)) { require_once "Zend/Soap/AutoDiscover/Exception.php"; throw new Zend_Soap_AutoDiscover_Exception("No uri given to Zend_Soap_AutoDiscover::setUri as string or Zend_Uri instance."); } $this->_uri = $uri; // change uri in WSDL file also if existant - if($this->_wsdl instanceof Zend_Soap_Wsdl) { + if ($this->_wsdl instanceof Zend_Soap_Wsdl) { $this->_wsdl->setUri($uri); } @@ -150,6 +162,36 @@ class Zend_Soap_AutoDiscover implements Zend_Server_Interface return $uri; } + /** + * Set the name of the WSDL handling class. + * + * @see Zend_Soap_Exception + * @see Zend_Soap_Exception + * @param string $wsdlClass + * @return Zend_Soap_AutoDiscover + * @throws Zend_Soap_AutoDiscover_Exception + */ + public function setWsdlClass($wsdlClass) + { + if (!is_string($wsdlClass) && !is_subclass_of($wsdlClass, 'Zend_Soap_Wsdl')) { + require_once "Zend/Soap/AutoDiscover/Exception.php"; + throw new Zend_Soap_AutoDiscover_Exception("No Zend_Soap_Wsdl subclass given to Zend_Soap_AutoDiscover::setWsdlClass as string."); + } + $this->_wsdlClass = $wsdlClass; + + return $this; + } + + /** + * Return the name of the WSDL handling class. + * + * @return string + */ + public function getWsdlClass() + { + return $this->_wsdlClass; + } + /** * Set options for all the binding operations soap:body elements. * @@ -159,6 +201,7 @@ class Zend_Soap_AutoDiscover implements Zend_Server_Interface * @see Zend_Soap_AutoDiscover_Exception * @param array $operationStyle * @return Zend_Soap_AutoDiscover + * @throws Zend_Soap_AutoDiscover_Exception */ public function setOperationBodyStyle(array $operationStyle=array()) { @@ -225,7 +268,9 @@ class Zend_Soap_AutoDiscover implements Zend_Server_Interface */ protected function getRequestUriWithoutParameters() { - if (isset($_SERVER['HTTP_X_REWRITE_URL'])) { // check this first so IIS will catch + if (isset($_SERVER['HTTP_X_ORIGINAL_URL'])) { // IIS with Microsoft Rewrite Module + $requestUri = $_SERVER['HTTP_X_ORIGINAL_URL']; + } elseif (isset($_SERVER['HTTP_X_REWRITE_URL'])) { // check this first so IIS will catch $requestUri = $_SERVER['HTTP_X_REWRITE_URL']; } elseif (isset($_SERVER['REQUEST_URI'])) { $requestUri = $_SERVER['REQUEST_URI']; @@ -263,12 +308,13 @@ class Zend_Soap_AutoDiscover implements Zend_Server_Interface * @param string $class Class Name * @param string $namespace Class Namspace - Not Used * @param array $argv Arguments to instantiate the class - Not Used + * @return Zend_Soap_AutoDiscover */ public function setClass($class, $namespace = '', $argv = null) { $uri = $this->getUri(); - $wsdl = new Zend_Soap_Wsdl($class, $uri, $this->_strategy); + $wsdl = new $this->_wsdlClass($class, $uri, $this->_strategy); // The wsdl:types element must precede all other elements (WS-I Basic Profile 1.1 R2023) $wsdl->addSchemaTypeSection(); @@ -282,6 +328,8 @@ class Zend_Soap_AutoDiscover implements Zend_Server_Interface $this->_addFunctionToWsdl($method, $wsdl, $port, $binding); } $this->_wsdl = $wsdl; + + return $this; } /** @@ -289,6 +337,7 @@ class Zend_Soap_AutoDiscover implements Zend_Server_Interface * * @param string $function Function Name * @param string $namespace Function namespace - Not Used + * @return Zend_Soap_AutoDiscover */ public function addFunction($function, $namespace = '') { @@ -324,15 +373,17 @@ class Zend_Soap_AutoDiscover implements Zend_Server_Interface $this->_addFunctionToWsdl($method, $wsdl, $port, $binding); } $this->_wsdl = $wsdl; + + return $this; } /** * Add a function to the WSDL document. * - * @param $function Zend_Server_Reflection_Function_Abstract function to add - * @param $wsdl Zend_Soap_Wsdl WSDL document - * @param $port object wsdl:portType - * @param $binding object wsdl:binding + * @param Zend_Server_Reflection_Function_Abstract $function function to add + * @param Zend_Soap_Wsdl $wsdl WSDL document + * @param object $port wsdl:portType + * @param object $binding wsdl:binding * @return void */ protected function _addFunctionToWsdl($function, $wsdl, $port, $binding) @@ -430,7 +481,11 @@ class Zend_Soap_AutoDiscover implements Zend_Server_Interface } // Add the binding operation - $operation = $wsdl->addBindingOperation($binding, $function->getName(), $this->_operationBodyStyle, $this->_operationBodyStyle); + if($isOneWayMessage == false) { + $operation = $wsdl->addBindingOperation($binding, $function->getName(), $this->_operationBodyStyle, $this->_operationBodyStyle); + } else { + $operation = $wsdl->addBindingOperation($binding, $function->getName(), $this->_operationBodyStyle); + } $wsdl->addSoapOperation($operation, $uri . '#' .$function->getName()); // Add the function name to the list @@ -442,6 +497,7 @@ class Zend_Soap_AutoDiscover implements Zend_Server_Interface * * @param string $fault * @param string|int $code + * @throws Zend_Soap_AutoDiscover_Exception */ public function fault($fault = null, $code = null) { @@ -466,6 +522,8 @@ class Zend_Soap_AutoDiscover implements Zend_Server_Interface * Proxy to WSDL dump function * * @param string $filename + * @return boolean + * @throws Zend_Soap_AutoDiscover_Exception */ public function dump($filename) { @@ -482,6 +540,9 @@ class Zend_Soap_AutoDiscover implements Zend_Server_Interface /** * Proxy to WSDL toXml() function + * + * @return string + * @throws Zend_Soap_AutoDiscover_Exception */ public function toXml() { @@ -510,6 +571,7 @@ class Zend_Soap_AutoDiscover implements Zend_Server_Interface * Load Functions * * @param unknown_type $definition + * @throws Zend_Soap_AutoDiscover_Exception */ public function loadFunctions($definition) { @@ -521,6 +583,7 @@ class Zend_Soap_AutoDiscover implements Zend_Server_Interface * Set Persistance * * @param int $mode + * @throws Zend_Soap_AutoDiscover_Exception */ public function setPersistence($mode) { diff --git a/lib/zend/Zend/Soap/AutoDiscover/Exception.php b/lib/zend/Zend/Soap/AutoDiscover/Exception.php index dd1b75a981d..278ff8e1b0e 100644 --- a/lib/zend/Zend/Soap/AutoDiscover/Exception.php +++ b/lib/zend/Zend/Soap/AutoDiscover/Exception.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Soap * @subpackage AutoDiscover - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ diff --git a/lib/zend/Zend/Soap/Client.php b/lib/zend/Zend/Soap/Client.php index 3fc620a385d..9a3b754c35b 100644 --- a/lib/zend/Zend/Soap/Client.php +++ b/lib/zend/Zend/Soap/Client.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Soap * @subpackage Client - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -41,7 +41,7 @@ require_once 'Zend/Soap/Client/Common.php'; * @category Zend * @package Zend_Soap * @subpackage Client - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Soap_Client @@ -89,6 +89,7 @@ class Zend_Soap_Client protected $_features = null; protected $_cache_wsdl = null; protected $_user_agent = null; + protected $_exceptions = null; /** * WSDL used to access server @@ -268,6 +269,9 @@ class Zend_Soap_Client case 'user_agent': $this->setUserAgent($value); break; + case 'exceptions': + $this->setExceptions($value); + break; // Not used now // case 'connection_timeout': @@ -315,13 +319,14 @@ class Zend_Soap_Client $options['cache_wsdl'] = $this->getWsdlCache(); $options['features'] = $this->getSoapFeatures(); $options['user_agent'] = $this->getUserAgent(); + $options['exceptions'] = $this->getExceptions(); foreach ($options as $key => $value) { /* * ugly hack as I don't know if checking for '=== null' * breaks some other option */ - if ($key == 'user_agent') { + if (in_array($key, array('user_agent', 'cache_wsdl', 'compression', 'exceptions'))) { if ($value === null) { unset($options[$key]); } @@ -767,15 +772,17 @@ class Zend_Soap_Client /** * Set compression options * - * @param int $compressionOptions + * @param int|null $compressionOptions * @return Zend_Soap_Client */ public function setCompressionOptions($compressionOptions) { - $this->_compression = $compressionOptions; - + if ($compressionOptions === null) { + $this->_compression = null; + } else { + $this->_compression = (int)$compressionOptions; + } $this->_soapClient = null; - return $this; } @@ -857,17 +864,23 @@ class Zend_Soap_Client /** * Set the SOAP Wsdl Caching Options * - * @param string|int|boolean $caching + * @param string|int|boolean|null $caching * @return Zend_Soap_Client */ - public function setWsdlCache($options) + public function setWsdlCache($caching) { - $this->_cache_wsdl = $options; + if ($caching === null) { + $this->_cache_wsdl = null; + } else { + $this->_cache_wsdl = (int)$caching; + } return $this; } /** * Get current SOAP Wsdl Caching option + * + * @return int */ public function getWsdlCache() { @@ -900,6 +913,39 @@ class Zend_Soap_Client return $this->_user_agent; } + /** + * Set the exceptions option + * + * The exceptions option is a boolean value defining whether soap errors + * throw exceptions. + * + * @see http://php.net/manual/soapclient.soapclient.php#refsect1-soapclient.soapclient-parameters + * + * @param bool $exceptions + * @return $this + */ + public function setExceptions($exceptions) + { + $this->_exceptions = (bool) $exceptions; + + return $this; + } + + /** + * Get the exceptions option + * + * The exceptions option is a boolean value defining whether soap errors + * throw exceptions. + * + * @see http://php.net/manual/soapclient.soapclient.php#refsect1-soapclient.soapclient-parameters + * + * @return bool|null + */ + public function getExceptions() + { + return $this->_exceptions; + } + /** * Retrieve request XML * diff --git a/lib/zend/Zend/Soap/Client/Common.php b/lib/zend/Zend/Soap/Client/Common.php index d3eb8e21155..7880115ce73 100644 --- a/lib/zend/Zend/Soap/Client/Common.php +++ b/lib/zend/Zend/Soap/Client/Common.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Soap * @subpackage Client - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ diff --git a/lib/zend/Zend/Soap/Client/DotNet.php b/lib/zend/Zend/Soap/Client/DotNet.php index 8a630f08bff..d031f4c368c 100644 --- a/lib/zend/Zend/Soap/Client/DotNet.php +++ b/lib/zend/Zend/Soap/Client/DotNet.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Soap * @subpackage Client - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ diff --git a/lib/zend/Zend/Soap/Client/Exception.php b/lib/zend/Zend/Soap/Client/Exception.php index fc278a2c44f..8f6d0c627bc 100644 --- a/lib/zend/Zend/Soap/Client/Exception.php +++ b/lib/zend/Zend/Soap/Client/Exception.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Soap * @subpackage Client - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -26,7 +26,7 @@ require_once 'Zend/Exception.php'; * @category Zend * @package Zend_Soap * @subpackage Client - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ diff --git a/lib/zend/Zend/Soap/Client/Local.php b/lib/zend/Zend/Soap/Client/Local.php index 09b43d3613b..18a11b28266 100644 --- a/lib/zend/Zend/Soap/Client/Local.php +++ b/lib/zend/Zend/Soap/Client/Local.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Soap * @subpackage Client - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -83,8 +83,14 @@ class Zend_Soap_Client_Local extends Zend_Soap_Client // Perform request as is ob_start(); $this->_server->handle($request); - $response = ob_get_contents(); - ob_end_clean(); + $response = ob_get_clean(); + + if ($response === null || $response === '') { + $serverResponse = $this->server->getResponse(); + if ($serverResponse !== null) { + $response = $serverResponse; + } + } return $response; } diff --git a/lib/zend/Zend/Soap/Server.php b/lib/zend/Zend/Soap/Server.php index 469192c38cf..d1421d3eccf 100644 --- a/lib/zend/Zend/Soap/Server.php +++ b/lib/zend/Zend/Soap/Server.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Soap * @subpackage Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -24,6 +24,12 @@ */ require_once 'Zend/Server/Interface.php'; +/** @see Zend_Xml_Security */ +require_once 'Zend/Xml/Security.php'; + +/** @see Zend_Xml_Exception */ +require_once 'Zend/Xml/Exception.php'; + /** * Zend_Soap_Server * @@ -31,7 +37,7 @@ require_once 'Zend/Server/Interface.php'; * @package Zend_Soap * @subpackage Server * @uses Zend_Server_Interface - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -86,7 +92,13 @@ class Zend_Soap_Server implements Zend_Server_Interface */ protected $_wsdlCache; - + /** + * WS-I compliant + * + * @var boolean + */ + protected $_wsiCompliant; + /** * Registered fault exceptions * @var array @@ -210,11 +222,16 @@ class Zend_Soap_Server implements Zend_Server_Interface $this->setWsdl($value); break; case 'featues': + trigger_error(__METHOD__ . ': the option "featues" is deprecated as of 1.10.x and will be removed with 2.0.0; use "features" instead', E_USER_NOTICE); + case 'features': $this->setSoapFeatures($value); break; case 'cache_wsdl': $this->setWsdlCache($value); break; + case 'wsi_compliant': + $this->setWsiCompliant($value); + break; default: break; } @@ -251,17 +268,42 @@ class Zend_Soap_Server implements Zend_Server_Interface $options['uri'] = $this->_uri; } - if(null !== $this->_features) { + if (null !== $this->_features) { $options['features'] = $this->_features; } - if(null !== $this->_wsdlCache) { + if (null !== $this->_wsdlCache) { $options['cache_wsdl'] = $this->_wsdlCache; } + if (null !== $this->_wsiCompliant) { + $options['wsi_compliant'] = $this->_wsiCompliant; + } + return $options; } - + /** + * Set WS-I compliant + * + * @param boolean $value + * @return Zend_Soap_Server + */ + public function setWsiCompliant($value) + { + if (is_bool($value)) { + $this->_wsiCompliant = $value; + } + return $this; + } + /** + * Gt WS-I compliant + * + * @return boolean + */ + public function getWsiCompliant() + { + return $this->_wsiCompliant; + } /** * Set encoding * @@ -593,7 +635,12 @@ class Zend_Soap_Server implements Zend_Server_Interface throw new Zend_Soap_Server_Exception('An object has already been registered with this soap server instance'); } - $this->_object = $object; + if ($this->_wsiCompliant) { + require_once 'Zend/Soap/Server/Proxy.php'; + $this->_object = new Zend_Soap_Server_Proxy($object); + } else { + $this->_object = $object; + } return $this; } @@ -689,9 +736,16 @@ class Zend_Soap_Server implements Zend_Server_Interface } $dom = new DOMDocument(); - if(strlen($xml) == 0 || !$dom->loadXML($xml)) { + try { + if(strlen($xml) == 0 || (!$dom = Zend_Xml_Security::scan($xml, $dom))) { + require_once 'Zend/Soap/Server/Exception.php'; + throw new Zend_Soap_Server_Exception('Invalid XML'); + } + } catch (Zend_Xml_Exception $e) { require_once 'Zend/Soap/Server/Exception.php'; - throw new Zend_Soap_Server_Exception('Invalid XML'); + throw new Zend_Soap_Server_Exception( + $e->getMessage() + ); } } $this->_request = $xml; @@ -766,6 +820,10 @@ class Zend_Soap_Server implements Zend_Server_Interface if (!empty($this->_class)) { $args = $this->_classArgs; array_unshift($args, $this->_class); + if ($this->_wsiCompliant) { + require_once 'Zend/Soap/Server/Proxy.php'; + array_unshift($args, 'Zend_Soap_Server_Proxy'); + } call_user_func_array(array($server, 'setClass'), $args); } @@ -818,19 +876,19 @@ class Zend_Soap_Server implements Zend_Server_Interface } catch (Zend_Soap_Server_Exception $e) { $setRequestException = $e; } - + $soap = $this->_getSoap(); + $fault = false; ob_start(); - if($setRequestException instanceof Exception) { - // Send SOAP fault message if we've catched exception - $soap->fault("Sender", $setRequestException->getMessage()); + if ($setRequestException instanceof Exception) { + // Create SOAP fault message if we've caught a request exception + $fault = $this->fault($setRequestException->getMessage(), 'Sender'); } else { try { - $soap->handle($request); + $soap->handle($this->_request); } catch (Exception $e) { $fault = $this->fault($e); - $soap->fault($fault->faultcode, $fault->faultstring); } } $this->_response = ob_get_clean(); @@ -839,6 +897,11 @@ class Zend_Soap_Server implements Zend_Server_Interface restore_error_handler(); ini_set('display_errors', $displayErrorsOriginalState); + // Send a fault, if we have one + if ($fault) { + $soap->fault($fault->faultcode, $fault->faultstring); + } + if (!$this->_returnResponse) { echo $this->_response; return; diff --git a/lib/zend/Zend/Soap/Server/Exception.php b/lib/zend/Zend/Soap/Server/Exception.php index de19a674272..1e8531896a9 100644 --- a/lib/zend/Zend/Soap/Server/Exception.php +++ b/lib/zend/Zend/Soap/Server/Exception.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Soap * @subpackage Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -28,7 +28,7 @@ require_once 'Zend/Exception.php'; * @category Zend * @package Zend_Soap * @subpackage Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ diff --git a/lib/zend/Zend/Soap/Server/Proxy.php b/lib/zend/Zend/Soap/Server/Proxy.php new file mode 100644 index 00000000000..93b6ab4e6a0 --- /dev/null +++ b/lib/zend/Zend/Soap/Server/Proxy.php @@ -0,0 +1,75 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_Soap + * @subpackage AutoDiscover + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @version $Id:$ + */ + +class Zend_Soap_Server_Proxy +{ + /** + * @var object + */ + protected $_classInstance; + /** + * @var string + */ + protected $_className; + /** + * Constructor + * + * @param object $service + */ + public function __construct($className, $classArgs = array()) + { + $class = new ReflectionClass($className); + $constructor = $class->getConstructor(); + if ($constructor === null) { + $this->_classInstance = $class->newInstance(); + } else { + $this->_classInstance = $class->newInstanceArgs($classArgs); + } + $this->_className = $className; + } + /** + * Proxy for the WS-I compliant call + * + * @param string $name + * @param string $arguments + * @return array + */ + public function __call($name, $arguments) + { + $result = call_user_func_array(array($this->_classInstance, $name), $this->_preProcessArguments($arguments)); + return array("{$name}Result"=>$result); + } + /** + * Pre process arguments + * + * @param mixed $arguments + * @return array + */ + protected function _preProcessArguments($arguments) + { + if (count($arguments) == 1 && is_object($arguments[0])) { + return get_object_vars($arguments[0]); + } else { + return $arguments; + } + } +} diff --git a/lib/zend/Zend/Soap/Wsdl.php b/lib/zend/Zend/Soap/Wsdl.php index 5c9ceb40cac..afc5f687ca5 100644 --- a/lib/zend/Zend/Soap/Wsdl.php +++ b/lib/zend/Zend/Soap/Wsdl.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Soap - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -29,6 +29,9 @@ require_once "Zend/Soap/Wsdl/Strategy/Interface.php"; */ require_once "Zend/Soap/Wsdl/Strategy/Abstract.php"; +/** @see Zend_Xml_Security */ +require_once "Zend/Xml/Security.php"; + /** * Zend_Soap_Wsdl * @@ -97,12 +100,11 @@ class Zend_Soap_Wsdl xmlns:soap-enc='http://schemas.xmlsoap.org/soap/encoding/' xmlns:wsdl='http://schemas.xmlsoap.org/wsdl/'></definitions>"; $this->_dom = new DOMDocument(); - if (!$this->_dom->loadXML($wsdl)) { + if (!$this->_dom = Zend_Xml_Security::scan($wsdl, $this->_dom)) { require_once 'Zend/Server/Exception.php'; throw new Zend_Server_Exception('Unable to create DomDocument'); - } else { - $this->_wsdl = $this->_dom->documentElement; - } + } + $this->_wsdl = $this->_dom->documentElement; $this->setComplexTypeStrategy($strategy); } @@ -126,7 +128,7 @@ class Zend_Soap_Wsdl $xml = $this->_dom->saveXML(); $xml = str_replace($oldUri, $uri, $xml); $this->_dom = new DOMDocument(); - $this->_dom->loadXML($xml); + $this->_dom = Zend_Xml_Security::scan($xml, $this->_dom); } return $this; @@ -317,11 +319,17 @@ class Zend_Soap_Wsdl if (is_array($fault)) { $node = $this->_dom->createElement('fault'); + /** + * Note. Do we really need name attribute to be also set at wsdl:fault node??? + * W3C standard doesn't mention it (http://www.w3.org/TR/wsdl#_soap:fault) + * But some real world WSDLs use it, so it may be required for compatibility reasons. + */ if (isset($fault['name'])) { $node->setAttribute('name', $fault['name']); } - $soap_node = $this->_dom->createElement('soap:body'); - foreach ($output as $name => $value) { + + $soap_node = $this->_dom->createElement('soap:fault'); + foreach ($fault as $name => $value) { $soap_node->setAttribute($name, $value); } $node->appendChild($soap_node); @@ -424,7 +432,7 @@ class Zend_Soap_Wsdl } $doc = $this->_dom->createElement('documentation'); - $doc_cdata = $this->_dom->createTextNode($documentation); + $doc_cdata = $this->_dom->createTextNode(str_replace(array("\r\n", "\r"), "\n", $documentation)); $doc->appendChild($doc_cdata); if($node->hasChildNodes()) { @@ -537,28 +545,24 @@ class Zend_Soap_Wsdl case 'string': case 'str': return 'xsd:string'; - break; + case 'long': + return 'xsd:long'; case 'int': case 'integer': return 'xsd:int'; - break; case 'float': - case 'double': return 'xsd:float'; - break; + case 'double': + return 'xsd:double'; case 'boolean': case 'bool': return 'xsd:boolean'; - break; case 'array': return 'soap-enc:Array'; - break; case 'object': return 'xsd:struct'; - break; case 'mixed': return 'xsd:anyType'; - break; case 'void': return ''; default: diff --git a/lib/zend/Zend/Soap/Wsdl/Exception.php b/lib/zend/Zend/Soap/Wsdl/Exception.php index fc6e43dbe9d..029ef73b54e 100644 --- a/lib/zend/Zend/Soap/Wsdl/Exception.php +++ b/lib/zend/Zend/Soap/Wsdl/Exception.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Soap * @subpackage Wsdl - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -31,7 +31,7 @@ require_once "Zend/Exception.php"; * @category Zend * @package Zend_Soap * @subpackage Wsdl - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class Zend_Soap_Wsdl_Exception extends Zend_Exception { } \ No newline at end of file +class Zend_Soap_Wsdl_Exception extends Zend_Exception { } diff --git a/lib/zend/Zend/Soap/Wsdl/Strategy/Abstract.php b/lib/zend/Zend/Soap/Wsdl/Strategy/Abstract.php index 220807e2e03..63abdba42b2 100644 --- a/lib/zend/Zend/Soap/Wsdl/Strategy/Abstract.php +++ b/lib/zend/Zend/Soap/Wsdl/Strategy/Abstract.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Soap * @subpackage Wsdl - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -31,7 +31,7 @@ require_once "Zend/Soap/Wsdl/Strategy/Interface.php"; * @category Zend * @package Zend_Soap * @subpackage Wsdl - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ abstract class Zend_Soap_Wsdl_Strategy_Abstract implements Zend_Soap_Wsdl_Strategy_Interface diff --git a/lib/zend/Zend/Soap/Wsdl/Strategy/AnyType.php b/lib/zend/Zend/Soap/Wsdl/Strategy/AnyType.php index 813c995545b..bb0e011794e 100644 --- a/lib/zend/Zend/Soap/Wsdl/Strategy/AnyType.php +++ b/lib/zend/Zend/Soap/Wsdl/Strategy/AnyType.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Soap * @subpackage Wsdl - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -31,7 +31,7 @@ require_once "Zend/Soap/Wsdl/Strategy/Interface.php"; * @category Zend * @package Zend_Soap * @subpackage Wsdl - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Soap_Wsdl_Strategy_AnyType implements Zend_Soap_Wsdl_Strategy_Interface @@ -56,4 +56,4 @@ class Zend_Soap_Wsdl_Strategy_AnyType implements Zend_Soap_Wsdl_Strategy_Interfa { return 'xsd:anyType'; } -} \ No newline at end of file +} diff --git a/lib/zend/Zend/Soap/Wsdl/Strategy/ArrayOfTypeComplex.php b/lib/zend/Zend/Soap/Wsdl/Strategy/ArrayOfTypeComplex.php index 1ea69b5da67..3e7d6acbb64 100644 --- a/lib/zend/Zend/Soap/Wsdl/Strategy/ArrayOfTypeComplex.php +++ b/lib/zend/Zend/Soap/Wsdl/Strategy/ArrayOfTypeComplex.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Soap * @subpackage Wsdl - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -31,7 +31,7 @@ require_once "Zend/Soap/Wsdl/Strategy/DefaultComplexType.php"; * @category Zend * @package Zend_Soap * @subpackage Wsdl - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Soap_Wsdl_Strategy_ArrayOfTypeComplex extends Zend_Soap_Wsdl_Strategy_DefaultComplexType @@ -46,9 +46,8 @@ class Zend_Soap_Wsdl_Strategy_ArrayOfTypeComplex extends Zend_Soap_Wsdl_Strategy */ public function addComplexType($type) { - if(in_array($type, $this->_inProcess)) { - require_once "Zend/Soap/Wsdl/Exception.php"; - throw new Zend_Soap_Wsdl_Exception("Infinite recursion, cannot nest '".$type."' into itself."); + if (in_array($type, $this->_inProcess)) { + return "tns:" . $type; } $this->_inProcess[$type] = $type; @@ -143,4 +142,4 @@ class Zend_Soap_Wsdl_Strategy_ArrayOfTypeComplex extends Zend_Soap_Wsdl_Strategy { return substr_count($type, "[]"); } -} \ No newline at end of file +} diff --git a/lib/zend/Zend/Soap/Wsdl/Strategy/ArrayOfTypeSequence.php b/lib/zend/Zend/Soap/Wsdl/Strategy/ArrayOfTypeSequence.php index bbbd4740e15..0c04221a335 100644 --- a/lib/zend/Zend/Soap/Wsdl/Strategy/ArrayOfTypeSequence.php +++ b/lib/zend/Zend/Soap/Wsdl/Strategy/ArrayOfTypeSequence.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Soap - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -30,7 +30,7 @@ require_once "Zend/Soap/Wsdl/Strategy/DefaultComplexType.php"; * @category Zend * @package Zend_Soap * @subpackage Wsdl - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Soap_Wsdl_Strategy_ArrayOfTypeSequence extends Zend_Soap_Wsdl_Strategy_DefaultComplexType diff --git a/lib/zend/Zend/Soap/Wsdl/Strategy/Composite.php b/lib/zend/Zend/Soap/Wsdl/Strategy/Composite.php index 39fd70a0cd6..eb531bfb054 100644 --- a/lib/zend/Zend/Soap/Wsdl/Strategy/Composite.php +++ b/lib/zend/Zend/Soap/Wsdl/Strategy/Composite.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Soap * @subpackage Wsdl - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -31,7 +31,7 @@ require_once "Zend/Soap/Wsdl/Strategy/Interface.php"; * @category Zend * @package Zend_Soap * @subpackage Wsdl - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Soap_Wsdl_Strategy_Composite implements Zend_Soap_Wsdl_Strategy_Interface @@ -185,4 +185,4 @@ class Zend_Soap_Wsdl_Strategy_Composite implements Zend_Soap_Wsdl_Strategy_Inter $strategy->setContext($this->_context); return $strategy->addComplexType($type); } -} \ No newline at end of file +} diff --git a/lib/zend/Zend/Soap/Wsdl/Strategy/DefaultComplexType.php b/lib/zend/Zend/Soap/Wsdl/Strategy/DefaultComplexType.php index ba7d1a16a1d..4bbf2a8f3b9 100644 --- a/lib/zend/Zend/Soap/Wsdl/Strategy/DefaultComplexType.php +++ b/lib/zend/Zend/Soap/Wsdl/Strategy/DefaultComplexType.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Soap * @subpackage Wsdl - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -31,7 +31,7 @@ require_once "Zend/Soap/Wsdl/Strategy/Abstract.php"; * @category Zend * @package Zend_Soap * @subpackage Wsdl - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Soap_Wsdl_Strategy_DefaultComplexType extends Zend_Soap_Wsdl_Strategy_Abstract @@ -55,6 +55,8 @@ class Zend_Soap_Wsdl_Strategy_DefaultComplexType extends Zend_Soap_Wsdl_Strategy $dom = $this->getContext()->toDomDocument(); $class = new ReflectionClass($type); + $defaultProperties = $class->getDefaultProperties(); + $complexType = $dom->createElement('xsd:complexType'); $complexType->setAttribute('name', $type); @@ -68,8 +70,14 @@ class Zend_Soap_Wsdl_Strategy_DefaultComplexType extends Zend_Soap_Wsdl_Strategy * node for describing other classes used as attribute types for current class */ $element = $dom->createElement('xsd:element'); - $element->setAttribute('name', $property->getName()); + $element->setAttribute('name', $propertyName = $property->getName()); $element->setAttribute('type', $this->getContext()->getType(trim($matches[1][0]))); + + // If the default value is null, then this property is nillable. + if ($defaultProperties[$propertyName] === null) { + $element->setAttribute('nillable', 'true'); + } + $all->appendChild($element); } } diff --git a/lib/zend/Zend/Soap/Wsdl/Strategy/Interface.php b/lib/zend/Zend/Soap/Wsdl/Strategy/Interface.php index 456bc6ea318..9a576055cad 100644 --- a/lib/zend/Zend/Soap/Wsdl/Strategy/Interface.php +++ b/lib/zend/Zend/Soap/Wsdl/Strategy/Interface.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Soap * @subpackage Wsdl - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -26,7 +26,7 @@ * @category Zend * @package Zend_Soap * @subpackage Wsdl - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ interface Zend_Soap_Wsdl_Strategy_Interface @@ -45,4 +45,4 @@ interface Zend_Soap_Wsdl_Strategy_Interface * @return string XSD type */ public function addComplexType($type); -} \ No newline at end of file +} diff --git a/lib/zend/Zend/Uri.php b/lib/zend/Zend/Uri.php index 9db6375073d..e1660d8bf17 100644 --- a/lib/zend/Zend/Uri.php +++ b/lib/zend/Zend/Uri.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Uri - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -24,7 +24,7 @@ * * @category Zend * @package Zend_Uri - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ abstract class Zend_Uri @@ -53,7 +53,12 @@ abstract class Zend_Uri */ public function __toString() { - return $this->getUri(); + try { + return $this->getUri(); + } catch (Exception $e) { + trigger_error($e->getMessage(), E_USER_WARNING); + return ''; + } } /** @@ -127,14 +132,12 @@ abstract class Zend_Uri } } - if (!class_exists($className)) { - require_once 'Zend/Loader.php'; - try { - Zend_Loader::loadClass($className); - } catch (Exception $e) { - require_once 'Zend/Uri/Exception.php'; - throw new Zend_Uri_Exception("\"$className\" not found"); - } + require_once 'Zend/Loader.php'; + try { + Zend_Loader::loadClass($className); + } catch (Exception $e) { + require_once 'Zend/Uri/Exception.php'; + throw new Zend_Uri_Exception("\"$className\" not found"); } $schemeHandler = new $className($scheme, $schemeSpecific); diff --git a/lib/zend/Zend/Uri/Exception.php b/lib/zend/Zend/Uri/Exception.php index 80b7e7d8b7b..f5a497edd0a 100644 --- a/lib/zend/Zend/Uri/Exception.php +++ b/lib/zend/Zend/Uri/Exception.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Uri - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -29,7 +29,7 @@ require_once 'Zend/Exception.php'; * * @category Zend * @package Zend_Uri - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Uri_Exception extends Zend_Exception diff --git a/lib/zend/Zend/Uri/Http.php b/lib/zend/Zend/Uri/Http.php index 9ac428569c0..b99f9f8169a 100644 --- a/lib/zend/Zend/Uri/Http.php +++ b/lib/zend/Zend/Uri/Http.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Uri - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -35,7 +35,7 @@ require_once 'Zend/Validate/Hostname.php'; * @category Zend * @package Zend_Uri * @uses Zend_Uri - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Uri_Http extends Zend_Uri @@ -217,24 +217,20 @@ class Zend_Uri_Http extends Zend_Uri // Additional decomposition to get username, password, host, and port $combo = isset($matches[3]) === true ? $matches[3] : ''; - $pattern = '~^(([^:@]*)(:([^@]*))?@)?([^:]+)(:(.*))?$~'; + $pattern = '~^(([^:@]*)(:([^@]*))?@)?((?(?=[[])[[][^]]+[]]|[^:]+))(:(.*))?$~'; $status = @preg_match($pattern, $combo, $matches); if ($status === false) { require_once 'Zend/Uri/Exception.php'; throw new Zend_Uri_Exception('Internal error: authority decomposition failed'); } - - // Failed decomposition; no further processing needed - if ($status === false) { - return; - } - + // Save remaining URI components $this->_username = isset($matches[2]) === true ? $matches[2] : ''; $this->_password = isset($matches[4]) === true ? $matches[4] : ''; - $this->_host = isset($matches[5]) === true ? $matches[5] : ''; + $this->_host = isset($matches[5]) === true + ? preg_replace('~^\[([^]]+)\]$~', '\1', $matches[5]) // Strip wrapper [] from IPv6 literal + : ''; $this->_port = isset($matches[7]) === true ? $matches[7] : ''; - } /** @@ -522,7 +518,7 @@ class Zend_Uri_Http extends Zend_Uri } /** - * Returns the path and filename portion of the URL, or FALSE if none. + * Returns the path and filename portion of the URL. * * @return string */ diff --git a/lib/zend/Zend/Validate.php b/lib/zend/Zend/Validate.php new file mode 100644 index 00000000000..956d3119dc4 --- /dev/null +++ b/lib/zend/Zend/Validate.php @@ -0,0 +1,290 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_Validate + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @version $Id$ + */ + +/** + * @see Zend_Validate_Interface + */ +require_once 'Zend/Validate/Interface.php'; + +/** + * @category Zend + * @package Zend_Validate + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_Validate implements Zend_Validate_Interface +{ + /** + * Validator chain + * + * @var array + */ + protected $_validators = array(); + + /** + * Array of validation failure messages + * + * @var array + */ + protected $_messages = array(); + + /** + * Default Namespaces + * + * @var array + */ + protected static $_defaultNamespaces = array(); + + /** + * Array of validation failure message codes + * + * @var array + * @deprecated Since 1.5.0 + */ + protected $_errors = array(); + + /** + * Adds a validator to the end of the chain + * + * If $breakChainOnFailure is true, then if the validator fails, the next validator in the chain, + * if one exists, will not be executed. + * + * @param Zend_Validate_Interface $validator + * @param boolean $breakChainOnFailure + * @return Zend_Validate Provides a fluent interface + */ + public function addValidator(Zend_Validate_Interface $validator, $breakChainOnFailure = false) + { + $this->_validators[] = array( + 'instance' => $validator, + 'breakChainOnFailure' => (boolean) $breakChainOnFailure + ); + return $this; + } + + /** + * Returns true if and only if $value passes all validations in the chain + * + * Validators are run in the order in which they were added to the chain (FIFO). + * + * @param mixed $value + * @return boolean + */ + public function isValid($value) + { + $this->_messages = array(); + $this->_errors = array(); + $result = true; + foreach ($this->_validators as $element) { + $validator = $element['instance']; + if ($validator->isValid($value)) { + continue; + } + $result = false; + $messages = $validator->getMessages(); + $this->_messages = array_merge($this->_messages, $messages); + $this->_errors = array_merge($this->_errors, array_keys($messages)); + if ($element['breakChainOnFailure']) { + break; + } + } + return $result; + } + + /** + * Defined by Zend_Validate_Interface + * + * Returns array of validation failure messages + * + * @return array + */ + public function getMessages() + { + return $this->_messages; + } + + /** + * Defined by Zend_Validate_Interface + * + * Returns array of validation failure message codes + * + * @return array + * @deprecated Since 1.5.0 + */ + public function getErrors() + { + return $this->_errors; + } + + /** + * Returns the set default namespaces + * + * @return array + */ + public static function getDefaultNamespaces() + { + return self::$_defaultNamespaces; + } + + /** + * Sets new default namespaces + * + * @param array|string $namespace + * @return null + */ + public static function setDefaultNamespaces($namespace) + { + if (!is_array($namespace)) { + $namespace = array((string) $namespace); + } + + self::$_defaultNamespaces = $namespace; + } + + /** + * Adds a new default namespace + * + * @param array|string $namespace + * @return null + */ + public static function addDefaultNamespaces($namespace) + { + if (!is_array($namespace)) { + $namespace = array((string) $namespace); + } + + self::$_defaultNamespaces = array_unique(array_merge(self::$_defaultNamespaces, $namespace)); + } + + /** + * Returns true when defaultNamespaces are set + * + * @return boolean + */ + public static function hasDefaultNamespaces() + { + return (!empty(self::$_defaultNamespaces)); + } + + /** + * @param mixed $value + * @param string $classBaseName + * @param array $args OPTIONAL + * @param mixed $namespaces OPTIONAL + * @return boolean + * @throws Zend_Validate_Exception + */ + public static function is($value, $classBaseName, array $args = array(), $namespaces = array()) + { + $namespaces = array_merge((array) $namespaces, self::$_defaultNamespaces, array('Zend_Validate')); + $className = ucfirst($classBaseName); + try { + if (!class_exists($className, false)) { + require_once 'Zend/Loader.php'; + foreach($namespaces as $namespace) { + $class = $namespace . '_' . $className; + $file = str_replace('_', DIRECTORY_SEPARATOR, $class) . '.php'; + if (Zend_Loader::isReadable($file)) { + Zend_Loader::loadClass($class); + $className = $class; + break; + } + } + } + + $class = new ReflectionClass($className); + if ($class->implementsInterface('Zend_Validate_Interface')) { + if ($class->hasMethod('__construct')) { + $keys = array_keys($args); + $numeric = false; + foreach($keys as $key) { + if (is_numeric($key)) { + $numeric = true; + break; + } + } + + if ($numeric) { + $object = $class->newInstanceArgs($args); + } else { + $object = $class->newInstance($args); + } + } else { + $object = $class->newInstance(); + } + + return $object->isValid($value); + } + } catch (Zend_Validate_Exception $ze) { + // if there is an exception while validating throw it + throw $ze; + } catch (Exception $e) { + // fallthrough and continue for missing validation classes + } + + require_once 'Zend/Validate/Exception.php'; + throw new Zend_Validate_Exception("Validate class not found from basename '$classBaseName'"); + } + + /** + * Returns the maximum allowed message length + * + * @return integer + */ + public static function getMessageLength() + { + require_once 'Zend/Validate/Abstract.php'; + return Zend_Validate_Abstract::getMessageLength(); + } + + /** + * Sets the maximum allowed message length + * + * @param integer $length + */ + public static function setMessageLength($length = -1) + { + require_once 'Zend/Validate/Abstract.php'; + Zend_Validate_Abstract::setMessageLength($length); + } + + /** + * Returns the default translation object + * + * @return Zend_Translate_Adapter|null + */ + public static function getDefaultTranslator($translator = null) + { + require_once 'Zend/Validate/Abstract.php'; + return Zend_Validate_Abstract::getDefaultTranslator(); + } + + /** + * Sets a default translation object for all validation objects + * + * @param Zend_Translate|Zend_Translate_Adapter|null $translator + */ + public static function setDefaultTranslator($translator = null) + { + require_once 'Zend/Validate/Abstract.php'; + Zend_Validate_Abstract::setDefaultTranslator($translator); + } +} diff --git a/lib/zend/Zend/Validate/Abstract.php b/lib/zend/Zend/Validate/Abstract.php index 7f978ee4f04..87998c576a2 100644 --- a/lib/zend/Zend/Validate/Abstract.php +++ b/lib/zend/Zend/Validate/Abstract.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Interface.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ abstract class Zend_Validate_Abstract implements Zend_Validate_Interface @@ -229,17 +229,23 @@ abstract class Zend_Validate_Abstract implements Zend_Validate_Interface } else { $value = $value->__toString(); } + } elseif (is_array($value)) { + $value = $this->_implodeRecursive($value); } else { - $value = (string)$value; + $value = implode((array) $value); } if ($this->getObscureValue()) { $value = str_repeat('*', strlen($value)); } - $message = str_replace('%value%', (string) $value, $message); + $message = str_replace('%value%', $value, $message); foreach ($this->_messageVariables as $ident => $property) { - $message = str_replace("%$ident%", (string) $this->$property, $message); + $message = str_replace( + "%$ident%", + implode(' ', (array) $this->$property), + $message + ); } $length = self::getMessageLength(); @@ -250,6 +256,26 @@ abstract class Zend_Validate_Abstract implements Zend_Validate_Interface return $message; } + /** + * Joins elements of a multidimensional array + * + * @param array $pieces + * @return string + */ + protected function _implodeRecursive(array $pieces) + { + $values = array(); + foreach ($pieces as $item) { + if (is_array($item)) { + $values[] = $this->_implodeRecursive($item); + } else { + $values[] = $item; + } + } + + return implode(', ', $values); + } + /** * @param string $messageKey * @param string $value OPTIONAL @@ -319,6 +345,7 @@ abstract class Zend_Validate_Abstract implements Zend_Validate_Interface * Set translation object * * @param Zend_Translate|Zend_Translate_Adapter|null $translator + * @throws Zend_Validate_Exception * @return Zend_Validate_Abstract */ public function setTranslator($translator = null) @@ -366,7 +393,7 @@ abstract class Zend_Validate_Abstract implements Zend_Validate_Interface * Set default translation object for all validate objects * * @param Zend_Translate|Zend_Translate_Adapter|null $translator - * @return void + * @throws Zend_Validate_Exception */ public static function setDefaultTranslator($translator = null) { diff --git a/lib/zend/Zend/Validate/Alnum.php b/lib/zend/Zend/Validate/Alnum.php index 1585e5f115f..5091830215d 100644 --- a/lib/zend/Zend/Validate/Alnum.php +++ b/lib/zend/Zend/Validate/Alnum.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Abstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Alnum extends Zend_Validate_Abstract @@ -57,7 +57,7 @@ class Zend_Validate_Alnum extends Zend_Validate_Abstract * @var array */ protected $_messageTemplates = array( - self::INVALID => "Invalid type given, value should be float, string, or integer", + self::INVALID => "Invalid type given. String, integer or float expected", self::NOT_ALNUM => "'%value%' contains characters which are non alphabetic and no digits", self::STRING_EMPTY => "'%value%' is an empty string", ); @@ -65,8 +65,7 @@ class Zend_Validate_Alnum extends Zend_Validate_Abstract /** * Sets default option values for this instance * - * @param boolean|Zend_Config $allowWhiteSpace - * @return void + * @param boolean|Zend_Config $allowWhiteSpace */ public function __construct($allowWhiteSpace = false) { diff --git a/lib/zend/Zend/Validate/Alpha.php b/lib/zend/Zend/Validate/Alpha.php index 894ed877443..c9ea9828f56 100644 --- a/lib/zend/Zend/Validate/Alpha.php +++ b/lib/zend/Zend/Validate/Alpha.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Abstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Alpha extends Zend_Validate_Abstract @@ -57,7 +57,7 @@ class Zend_Validate_Alpha extends Zend_Validate_Abstract * @var array */ protected $_messageTemplates = array( - self::INVALID => "Invalid type given, value should be a string", + self::INVALID => "Invalid type given. String expected", self::NOT_ALPHA => "'%value%' contains non alphabetic characters", self::STRING_EMPTY => "'%value%' is an empty string" ); @@ -65,8 +65,7 @@ class Zend_Validate_Alpha extends Zend_Validate_Abstract /** * Sets default option values for this instance * - * @param boolean|Zend_Config $allowWhiteSpace - * @return void + * @param boolean|Zend_Config $allowWhiteSpace */ public function __construct($allowWhiteSpace = false) { diff --git a/lib/zend/Zend/Validate/Barcode.php b/lib/zend/Zend/Validate/Barcode.php index 31b70f6ce63..4d48d516034 100644 --- a/lib/zend/Zend/Validate/Barcode.php +++ b/lib/zend/Zend/Validate/Barcode.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -32,7 +32,7 @@ require_once 'Zend/Loader.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Barcode extends Zend_Validate_Abstract @@ -46,7 +46,7 @@ class Zend_Validate_Barcode extends Zend_Validate_Abstract self::FAILED => "'%value%' failed checksum validation", self::INVALID_CHARS => "'%value%' contains invalid characters", self::INVALID_LENGTH => "'%value%' should have a length of %length% characters", - self::INVALID => "Invalid type given, value should be string", + self::INVALID => "Invalid type given. String expected", ); /** @@ -77,7 +77,6 @@ class Zend_Validate_Barcode extends Zend_Validate_Abstract * * @param string|Zend_Config| * Zend_Validate_Barcode_BarcodeAdapter $adapter Barcode adapter to use - * @return void * @throws Zend_Validate_Exception */ public function __construct($adapter) @@ -126,7 +125,7 @@ class Zend_Validate_Barcode extends Zend_Validate_Abstract * * @param string|Zend_Validate_Barcode $adapter Barcode adapter to use * @param array $options Options for this adapter - * @return void + * @return $this * @throws Zend_Validate_Exception */ public function setAdapter($adapter, $options = null) @@ -194,6 +193,17 @@ class Zend_Validate_Barcode extends Zend_Validate_Abstract $this->_length = $adapter->getLength(); $result = $adapter->checkLength($value); if (!$result) { + if (is_array($this->_length)) { + $temp = $this->_length; + $this->_length = ""; + foreach($temp as $length) { + $this->_length .= "/"; + $this->_length .= $length; + } + + $this->_length = substr($this->_length, 1); + } + $this->_error(self::INVALID_LENGTH); return false; } @@ -214,4 +224,4 @@ class Zend_Validate_Barcode extends Zend_Validate_Abstract return true; } -} \ No newline at end of file +} diff --git a/lib/zend/Zend/Validate/Barcode/AdapterAbstract.php b/lib/zend/Zend/Validate/Barcode/AdapterAbstract.php index 1514d94f317..05dc2b9faf1 100644 --- a/lib/zend/Zend/Validate/Barcode/AdapterAbstract.php +++ b/lib/zend/Zend/Validate/Barcode/AdapterAbstract.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Barcode/AdapterInterface.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ abstract class Zend_Validate_Barcode_AdapterAbstract diff --git a/lib/zend/Zend/Validate/Barcode/AdapterInterface.php b/lib/zend/Zend/Validate/Barcode/AdapterInterface.php index 424db32967e..8e96effbf46 100644 --- a/lib/zend/Zend/Validate/Barcode/AdapterInterface.php +++ b/lib/zend/Zend/Validate/Barcode/AdapterInterface.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -22,7 +22,7 @@ /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ interface Zend_Validate_Barcode_AdapterInterface @@ -62,7 +62,7 @@ interface Zend_Validate_Barcode_AdapterInterface * Sets the checksum validation * * @param boolean $check - * @return Zend_Validate_Barcode_Adapter Provides fluid interface + * @return Zend_Validate_Barcode_Adapter Provides a fluent interface */ public function setCheck($check); } diff --git a/lib/zend/Zend/Validate/Barcode/Code25.php b/lib/zend/Zend/Validate/Barcode/Code25.php index 79ec830a1d5..a42048787b0 100644 --- a/lib/zend/Zend/Validate/Barcode/Code25.php +++ b/lib/zend/Zend/Validate/Barcode/Code25.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Barcode/AdapterAbstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Barcode_Code25 extends Zend_Validate_Barcode_AdapterAbstract @@ -54,8 +54,6 @@ class Zend_Validate_Barcode_Code25 extends Zend_Validate_Barcode_AdapterAbstract * Constructor * * Sets check flag to false. - * - * @return void */ public function __construct() { diff --git a/lib/zend/Zend/Validate/Barcode/Code25interleaved.php b/lib/zend/Zend/Validate/Barcode/Code25interleaved.php index 1442cf1ab5b..479aa03203c 100644 --- a/lib/zend/Zend/Validate/Barcode/Code25interleaved.php +++ b/lib/zend/Zend/Validate/Barcode/Code25interleaved.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Barcode/AdapterAbstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Barcode_Code25interleaved extends Zend_Validate_Barcode_AdapterAbstract @@ -54,8 +54,6 @@ class Zend_Validate_Barcode_Code25interleaved extends Zend_Validate_Barcode_Adap * Constructor * * Sets check flag to false. - * - * @return void */ public function __construct() { diff --git a/lib/zend/Zend/Validate/Barcode/Code39.php b/lib/zend/Zend/Validate/Barcode/Code39.php index 7679a6609e5..37b2f13afde 100644 --- a/lib/zend/Zend/Validate/Barcode/Code39.php +++ b/lib/zend/Zend/Validate/Barcode/Code39.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Barcode/AdapterAbstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Barcode_Code39 extends Zend_Validate_Barcode_AdapterAbstract @@ -67,8 +67,6 @@ class Zend_Validate_Barcode_Code39 extends Zend_Validate_Barcode_AdapterAbstract * Constructor * * Sets check flag to false. - * - * @return void */ public function __construct() { diff --git a/lib/zend/Zend/Validate/Barcode/Code39ext.php b/lib/zend/Zend/Validate/Barcode/Code39ext.php index 221683cf7bc..cd99c363c3a 100644 --- a/lib/zend/Zend/Validate/Barcode/Code39ext.php +++ b/lib/zend/Zend/Validate/Barcode/Code39ext.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Barcode/AdapterAbstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Barcode_Code39ext extends Zend_Validate_Barcode_AdapterAbstract @@ -48,8 +48,6 @@ class Zend_Validate_Barcode_Code39ext extends Zend_Validate_Barcode_AdapterAbstr * Constructor * * Sets check flag to false. - * - * @return void */ public function __construct() { diff --git a/lib/zend/Zend/Validate/Barcode/Code93.php b/lib/zend/Zend/Validate/Barcode/Code93.php index c67a0fe8d69..e09ba17ec1f 100644 --- a/lib/zend/Zend/Validate/Barcode/Code93.php +++ b/lib/zend/Zend/Validate/Barcode/Code93.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Barcode/AdapterAbstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Barcode_Code93 extends Zend_Validate_Barcode_AdapterAbstract @@ -68,8 +68,6 @@ class Zend_Validate_Barcode_Code93 extends Zend_Validate_Barcode_AdapterAbstract * Constructor * * Sets check flag to false. - * - * @return void */ public function __construct() { diff --git a/lib/zend/Zend/Validate/Barcode/Code93ext.php b/lib/zend/Zend/Validate/Barcode/Code93ext.php index 1b7fd41df01..6879a893721 100644 --- a/lib/zend/Zend/Validate/Barcode/Code93ext.php +++ b/lib/zend/Zend/Validate/Barcode/Code93ext.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Barcode/AdapterAbstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Barcode_Code93ext extends Zend_Validate_Barcode_AdapterAbstract @@ -48,8 +48,6 @@ class Zend_Validate_Barcode_Code93ext extends Zend_Validate_Barcode_AdapterAbstr * Constructor * * Sets check flag to false. - * - * @return void */ public function __construct() { diff --git a/lib/zend/Zend/Validate/Barcode/Ean12.php b/lib/zend/Zend/Validate/Barcode/Ean12.php index 4d2560b456e..e185233f5cf 100644 --- a/lib/zend/Zend/Validate/Barcode/Ean12.php +++ b/lib/zend/Zend/Validate/Barcode/Ean12.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Barcode/AdapterAbstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Barcode_Ean12 extends Zend_Validate_Barcode_AdapterAbstract diff --git a/lib/zend/Zend/Validate/Barcode/Ean13.php b/lib/zend/Zend/Validate/Barcode/Ean13.php index b8e83dc79d6..8daf54237b1 100644 --- a/lib/zend/Zend/Validate/Barcode/Ean13.php +++ b/lib/zend/Zend/Validate/Barcode/Ean13.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Barcode/AdapterAbstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Barcode_Ean13 extends Zend_Validate_Barcode_AdapterAbstract diff --git a/lib/zend/Zend/Validate/Barcode/Ean14.php b/lib/zend/Zend/Validate/Barcode/Ean14.php index 4959fa33b25..12cf49bbc58 100644 --- a/lib/zend/Zend/Validate/Barcode/Ean14.php +++ b/lib/zend/Zend/Validate/Barcode/Ean14.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Barcode/AdapterAbstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Barcode_Ean14 extends Zend_Validate_Barcode_AdapterAbstract diff --git a/lib/zend/Zend/Validate/Barcode/Ean18.php b/lib/zend/Zend/Validate/Barcode/Ean18.php index d027e7f667b..0f3df06b50c 100644 --- a/lib/zend/Zend/Validate/Barcode/Ean18.php +++ b/lib/zend/Zend/Validate/Barcode/Ean18.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Barcode/AdapterAbstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Barcode_Ean18 extends Zend_Validate_Barcode_AdapterAbstract diff --git a/lib/zend/Zend/Validate/Barcode/Ean2.php b/lib/zend/Zend/Validate/Barcode/Ean2.php index ad77e77f405..e2cec4b119f 100644 --- a/lib/zend/Zend/Validate/Barcode/Ean2.php +++ b/lib/zend/Zend/Validate/Barcode/Ean2.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Barcode/AdapterAbstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Barcode_Ean2 extends Zend_Validate_Barcode_AdapterAbstract @@ -48,8 +48,6 @@ class Zend_Validate_Barcode_Ean2 extends Zend_Validate_Barcode_AdapterAbstract * Constructor * * Sets check flag to false. - * - * @return void */ public function __construct() { diff --git a/lib/zend/Zend/Validate/Barcode/Ean5.php b/lib/zend/Zend/Validate/Barcode/Ean5.php index 002b766692c..ff5b4bb2ae0 100644 --- a/lib/zend/Zend/Validate/Barcode/Ean5.php +++ b/lib/zend/Zend/Validate/Barcode/Ean5.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Barcode/AdapterAbstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Barcode_Ean5 extends Zend_Validate_Barcode_AdapterAbstract @@ -48,8 +48,6 @@ class Zend_Validate_Barcode_Ean5 extends Zend_Validate_Barcode_AdapterAbstract * Constructor * * Sets check flag to false. - * - * @return void */ public function __construct() { diff --git a/lib/zend/Zend/Validate/Barcode/Ean8.php b/lib/zend/Zend/Validate/Barcode/Ean8.php index 6cc986536ce..6b1caa973e0 100644 --- a/lib/zend/Zend/Validate/Barcode/Ean8.php +++ b/lib/zend/Zend/Validate/Barcode/Ean8.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Barcode/AdapterAbstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Barcode_Ean8 extends Zend_Validate_Barcode_AdapterAbstract diff --git a/lib/zend/Zend/Validate/Barcode/Gtin12.php b/lib/zend/Zend/Validate/Barcode/Gtin12.php index 08d98c62d10..65ff5b9a21d 100644 --- a/lib/zend/Zend/Validate/Barcode/Gtin12.php +++ b/lib/zend/Zend/Validate/Barcode/Gtin12.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Barcode/AdapterAbstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Barcode_Gtin12 extends Zend_Validate_Barcode_AdapterAbstract diff --git a/lib/zend/Zend/Validate/Barcode/Gtin13.php b/lib/zend/Zend/Validate/Barcode/Gtin13.php index eaf6dcaccbe..382dccd726f 100644 --- a/lib/zend/Zend/Validate/Barcode/Gtin13.php +++ b/lib/zend/Zend/Validate/Barcode/Gtin13.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Barcode/AdapterAbstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Barcode_Gtin13 extends Zend_Validate_Barcode_AdapterAbstract diff --git a/lib/zend/Zend/Validate/Barcode/Gtin14.php b/lib/zend/Zend/Validate/Barcode/Gtin14.php index 98ccda82c50..6f291b8e3bc 100644 --- a/lib/zend/Zend/Validate/Barcode/Gtin14.php +++ b/lib/zend/Zend/Validate/Barcode/Gtin14.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Barcode/AdapterAbstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Barcode_Gtin14 extends Zend_Validate_Barcode_AdapterAbstract diff --git a/lib/zend/Zend/Validate/Barcode/Identcode.php b/lib/zend/Zend/Validate/Barcode/Identcode.php index 6287f6e9b2c..3f622fa639d 100644 --- a/lib/zend/Zend/Validate/Barcode/Identcode.php +++ b/lib/zend/Zend/Validate/Barcode/Identcode.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Barcode/AdapterAbstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Barcode_Identcode extends Zend_Validate_Barcode_AdapterAbstract diff --git a/lib/zend/Zend/Validate/Barcode/Intelligentmail.php b/lib/zend/Zend/Validate/Barcode/Intelligentmail.php index 9df61663ee0..cfa2a82e6dc 100644 --- a/lib/zend/Zend/Validate/Barcode/Intelligentmail.php +++ b/lib/zend/Zend/Validate/Barcode/Intelligentmail.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Barcode/AdapterAbstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Barcode_IntelligentMail extends Zend_Validate_Barcode_AdapterAbstract @@ -48,8 +48,6 @@ class Zend_Validate_Barcode_IntelligentMail extends Zend_Validate_Barcode_Adapte * Constructor * * Sets check flag to false. - * - * @return void */ public function __construct() { diff --git a/lib/zend/Zend/Validate/Barcode/Issn.php b/lib/zend/Zend/Validate/Barcode/Issn.php index 5c6783e29d2..a74fa5379ec 100644 --- a/lib/zend/Zend/Validate/Barcode/Issn.php +++ b/lib/zend/Zend/Validate/Barcode/Issn.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Barcode/AdapterAbstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Barcode_Issn extends Zend_Validate_Barcode_AdapterAbstract diff --git a/lib/zend/Zend/Validate/Barcode/Itf14.php b/lib/zend/Zend/Validate/Barcode/Itf14.php index 17dc9f175a3..4adc7447b21 100644 --- a/lib/zend/Zend/Validate/Barcode/Itf14.php +++ b/lib/zend/Zend/Validate/Barcode/Itf14.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Barcode/AdapterAbstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Barcode_Itf14 extends Zend_Validate_Barcode_AdapterAbstract diff --git a/lib/zend/Zend/Validate/Barcode/Leitcode.php b/lib/zend/Zend/Validate/Barcode/Leitcode.php index ca59ef2c5b0..b41b079ea9b 100644 --- a/lib/zend/Zend/Validate/Barcode/Leitcode.php +++ b/lib/zend/Zend/Validate/Barcode/Leitcode.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Barcode/AdapterAbstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Barcode_Leitcode extends Zend_Validate_Barcode_AdapterAbstract diff --git a/lib/zend/Zend/Validate/Barcode/Planet.php b/lib/zend/Zend/Validate/Barcode/Planet.php index 5383bd9d1e1..227bc25d275 100644 --- a/lib/zend/Zend/Validate/Barcode/Planet.php +++ b/lib/zend/Zend/Validate/Barcode/Planet.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Barcode/AdapterAbstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Barcode_Planet extends Zend_Validate_Barcode_AdapterAbstract diff --git a/lib/zend/Zend/Validate/Barcode/Postnet.php b/lib/zend/Zend/Validate/Barcode/Postnet.php index b8798add34a..5aed312cbf3 100644 --- a/lib/zend/Zend/Validate/Barcode/Postnet.php +++ b/lib/zend/Zend/Validate/Barcode/Postnet.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Barcode/AdapterAbstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Barcode_Postnet extends Zend_Validate_Barcode_AdapterAbstract diff --git a/lib/zend/Zend/Validate/Barcode/Royalmail.php b/lib/zend/Zend/Validate/Barcode/Royalmail.php index de6a4c8350e..98fa38e64e2 100644 --- a/lib/zend/Zend/Validate/Barcode/Royalmail.php +++ b/lib/zend/Zend/Validate/Barcode/Royalmail.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Barcode/AdapterAbstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Barcode_Royalmail extends Zend_Validate_Barcode_AdapterAbstract diff --git a/lib/zend/Zend/Validate/Barcode/Sscc.php b/lib/zend/Zend/Validate/Barcode/Sscc.php index c8c45253a43..e624d7d79c3 100644 --- a/lib/zend/Zend/Validate/Barcode/Sscc.php +++ b/lib/zend/Zend/Validate/Barcode/Sscc.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Barcode/AdapterAbstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Barcode_Sscc extends Zend_Validate_Barcode_AdapterAbstract diff --git a/lib/zend/Zend/Validate/Barcode/Upca.php b/lib/zend/Zend/Validate/Barcode/Upca.php index ab425b17ff0..7757f2b1b4d 100644 --- a/lib/zend/Zend/Validate/Barcode/Upca.php +++ b/lib/zend/Zend/Validate/Barcode/Upca.php @@ -14,9 +14,9 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: Upca.php 20096 2010-01-06 02:05:09Z bkarwin $ + * @version $Id$ */ /** @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Barcode/AdapterAbstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Barcode_Upca extends Zend_Validate_Barcode_AdapterAbstract @@ -49,4 +49,4 @@ class Zend_Validate_Barcode_Upca extends Zend_Validate_Barcode_AdapterAbstract * @var string */ protected $_checksum = '_gtin'; -} \ No newline at end of file +} diff --git a/lib/zend/Zend/Validate/Barcode/Upce.php b/lib/zend/Zend/Validate/Barcode/Upce.php index 399e40eae0f..1b2482578f1 100644 --- a/lib/zend/Zend/Validate/Barcode/Upce.php +++ b/lib/zend/Zend/Validate/Barcode/Upce.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Barcode/AdapterAbstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Barcode_Upce extends Zend_Validate_Barcode_AdapterAbstract diff --git a/lib/zend/Zend/Validate/Between.php b/lib/zend/Zend/Validate/Between.php index bf4d793ecad..53b68261dda 100644 --- a/lib/zend/Zend/Validate/Between.php +++ b/lib/zend/Zend/Validate/Between.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Abstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Between extends Zend_Validate_Abstract @@ -94,7 +94,7 @@ class Zend_Validate_Between extends Zend_Validate_Abstract * 'inclusive' => boolean, inclusive border values * * @param array|Zend_Config $options - * @return void + * @throws Zend_Validate_Exception */ public function __construct($options) { diff --git a/lib/zend/Zend/Validate/Callback.php b/lib/zend/Zend/Validate/Callback.php index e43c20e119a..bb12ecf78d8 100644 --- a/lib/zend/Zend/Validate/Callback.php +++ b/lib/zend/Zend/Validate/Callback.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Abstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Callback extends Zend_Validate_Abstract @@ -49,7 +49,7 @@ class Zend_Validate_Callback extends Zend_Validate_Abstract */ protected $_messageTemplates = array( self::INVALID_VALUE => "'%value%' is not valid", - self::INVALID_CALLBACK => "Failure within the callback, exception returned", + self::INVALID_CALLBACK => "An exception has been raised within the callback", ); /** @@ -69,10 +69,8 @@ class Zend_Validate_Callback extends Zend_Validate_Abstract /** * Sets validator options * - * @param string|array $callback - * @param mixed $max - * @param boolean $inclusive - * @return void + * @param mixed $callback + * @throws Zend_Validate_Exception */ public function __construct($callback = null) { @@ -107,6 +105,7 @@ class Zend_Validate_Callback extends Zend_Validate_Abstract * Sets the callback * * @param string|array $callback + * @throws Zend_Validate_Exception * @return Zend_Validate_Callback Provides a fluent interface */ public function setCallback($callback) @@ -132,7 +131,7 @@ class Zend_Validate_Callback extends Zend_Validate_Abstract /** * Sets options for the callback * - * @param mixed $max + * @param mixed $options * @return Zend_Validate_Callback Provides a fluent interface */ public function setOptions($options) diff --git a/lib/zend/Zend/Validate/Ccnum.php b/lib/zend/Zend/Validate/Ccnum.php index 605e6a33bed..c3c7029a388 100644 --- a/lib/zend/Zend/Validate/Ccnum.php +++ b/lib/zend/Zend/Validate/Ccnum.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Abstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Ccnum extends Zend_Validate_Abstract diff --git a/lib/zend/Zend/Validate/CreditCard.php b/lib/zend/Zend/Validate/CreditCard.php index ca54579b3bf..170b622507d 100644 --- a/lib/zend/Zend/Validate/CreditCard.php +++ b/lib/zend/Zend/Validate/CreditCard.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Abstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_CreditCard extends Zend_Validate_Abstract @@ -64,13 +64,13 @@ class Zend_Validate_CreditCard extends Zend_Validate_Abstract * @var array */ protected $_messageTemplates = array( - self::CHECKSUM => "Luhn algorithm (mod-10 checksum) failed on '%value%'", + self::CHECKSUM => "'%value%' seems to contain an invalid checksum", self::CONTENT => "'%value%' must contain only digits", - self::INVALID => "Invalid type given, value should be a string", + self::INVALID => "Invalid type given. String expected", self::LENGTH => "'%value%' contains an invalid amount of digits", self::PREFIX => "'%value%' is not from an allowed institute", - self::SERVICE => "Validation of '%value%' has been failed by the service", - self::SERVICEFAILURE => "The service returned a failure while validating '%value%'", + self::SERVICE => "'%value%' seems to be an invalid creditcard number", + self::SERVICEFAILURE => "An exception has been raised while validating '%value%'", ); /** @@ -136,7 +136,7 @@ class Zend_Validate_CreditCard extends Zend_Validate_Abstract /** * Constructor * - * @param string|array $type OPTIONAL Type of CCI to allow + * @param string|array|Zend_Config $options OPTIONAL Type of CCI to allow */ public function __construct($options = array()) { @@ -176,7 +176,7 @@ class Zend_Validate_CreditCard extends Zend_Validate_Abstract * Sets CCIs which are accepted by validation * * @param string|array $type Type to allow for validation - * @return Zend_Validate_CreditCard Provides a fluid interface + * @return Zend_Validate_CreditCard Provides a fluent interface */ public function setType($type) { @@ -188,7 +188,7 @@ class Zend_Validate_CreditCard extends Zend_Validate_Abstract * Adds a CCI to be accepted by validation * * @param string|array $type Type to allow for validation - * @return Zend_Validate_CreditCard Provides a fluid interface + * @return Zend_Validate_CreditCard Provides a fluent interface */ public function addType($type) { @@ -222,7 +222,9 @@ class Zend_Validate_CreditCard extends Zend_Validate_Abstract /** * Sets a new callback for service validation * - * @param unknown_type $service + * @param mixed $service + * @throws Zend_Validate_Exception + * @return $this */ public function setService($service) { diff --git a/lib/zend/Zend/Validate/Date.php b/lib/zend/Zend/Validate/Date.php index 7e473a85f7e..e875aaf550f 100644 --- a/lib/zend/Zend/Validate/Date.php +++ b/lib/zend/Zend/Validate/Date.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Abstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Date extends Zend_Validate_Abstract @@ -42,7 +42,7 @@ class Zend_Validate_Date extends Zend_Validate_Abstract * @var array */ protected $_messageTemplates = array( - self::INVALID => "Invalid type given, value should be string, integer, array or Zend_Date", + self::INVALID => "Invalid type given. String, integer, array or Zend_Date expected", self::INVALID_DATE => "'%value%' does not appear to be a valid date", self::FALSEFORMAT => "'%value%' does not fit the date format '%format%'", ); @@ -71,8 +71,7 @@ class Zend_Validate_Date extends Zend_Validate_Abstract /** * Sets validator options * - * @param string|Zend_Config $options OPTIONAL - * @return void + * @param string|array|Zend_Config $options OPTIONAL */ public function __construct($options = array()) { diff --git a/lib/zend/Zend/Validate/Db/Abstract.php b/lib/zend/Zend/Validate/Db/Abstract.php index ddda9179f31..ffee51f2671 100644 --- a/lib/zend/Zend/Validate/Db/Abstract.php +++ b/lib/zend/Zend/Validate/Db/Abstract.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -30,7 +30,7 @@ require_once 'Zend/Validate/Abstract.php'; * @category Zend * @package Zend_Validate * @uses Zend_Validate_Abstract - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ abstract class Zend_Validate_Db_Abstract extends Zend_Validate_Abstract @@ -45,8 +45,8 @@ abstract class Zend_Validate_Db_Abstract extends Zend_Validate_Abstract * @var array Message templates */ protected $_messageTemplates = array( - self::ERROR_NO_RECORD_FOUND => 'No record matching %value% was found', - self::ERROR_RECORD_FOUND => 'A record matching %value% was found', + self::ERROR_NO_RECORD_FOUND => "No record matching '%value%' was found", + self::ERROR_RECORD_FOUND => "A record matching '%value%' was found", ); /** @@ -76,6 +76,12 @@ abstract class Zend_Validate_Db_Abstract extends Zend_Validate_Abstract */ protected $_adapter = null; + /** + * Select object to use. can be set, or will be auto-generated + * @var Zend_Db_Select + */ + protected $_select; + /** * Provides basic configuration for use with Zend_Validate_Db Validators * Setting $exclude allows a single record to be excluded from matching. @@ -91,9 +97,14 @@ abstract class Zend_Validate_Db_Abstract extends Zend_Validate_Abstract * 'adapter' => An optional database adapter to use * * @param array|Zend_Config $options Options to use for this validator + * @throws Zend_Validate_Exception */ public function __construct($options) { + if ($options instanceof Zend_Db_Select) { + $this->setSelect($options); + return; + } if ($options instanceof Zend_Config) { $options = $options->toArray(); } else if (func_num_args() > 1) { @@ -142,10 +153,21 @@ abstract class Zend_Validate_Db_Abstract extends Zend_Validate_Abstract /** * Returns the set adapter * + * @throws Zend_Validate_Exception * @return Zend_Db_Adapter */ public function getAdapter() { + /** + * Check for an adapter being defined. if not, fetch the default adapter. + */ + if ($this->_adapter === null) { + $this->_adapter = Zend_Db_Table_Abstract::getDefaultAdapter(); + if (null === $this->_adapter) { + require_once 'Zend/Validate/Exception.php'; + throw new Zend_Validate_Exception('No database adapter present'); + } + } return $this->_adapter; } @@ -153,6 +175,7 @@ abstract class Zend_Validate_Db_Abstract extends Zend_Validate_Abstract * Sets a new database adapter * * @param Zend_Db_Adapter_Abstract $adapter + * @throws Zend_Validate_Exception * @return Zend_Validate_Db_Abstract */ public function setAdapter($adapter) @@ -254,6 +277,61 @@ abstract class Zend_Validate_Db_Abstract extends Zend_Validate_Abstract return $this; } + /** + * Sets the select object to be used by the validator + * + * @param Zend_Db_Select $select + * @throws Zend_Validate_Exception + * @return Zend_Validate_Db_Abstract + */ + public function setSelect($select) + { + if (!$select instanceof Zend_Db_Select) { + throw new Zend_Validate_Exception('Select option must be a valid ' . + 'Zend_Db_Select object'); + } + $this->_select = $select; + return $this; + } + + /** + * Gets the select object to be used by the validator. + * If no select object was supplied to the constructor, + * then it will auto-generate one from the given table, + * schema, field, and adapter options. + * + * @return Zend_Db_Select The Select object which will be used + */ + public function getSelect() + { + if (null === $this->_select) { + $db = $this->getAdapter(); + /** + * Build select object + */ + $select = new Zend_Db_Select($db); + $select->from($this->_table, array($this->_field), $this->_schema); + if ($db->supportsParameters('named')) { + $select->where($db->quoteIdentifier($this->_field, true).' = :value'); // named + } else { + $select->where($db->quoteIdentifier($this->_field, true).' = ?'); // positional + } + if ($this->_exclude !== null) { + if (is_array($this->_exclude)) { + $select->where( + $db->quoteIdentifier($this->_exclude['field'], true) . + ' != ?', $this->_exclude['value'] + ); + } else { + $select->where($this->_exclude); + } + } + $select->limit(1); + $this->_select = $select; + } + return $this->_select; + } + /** * Run query and returns matches, or null if no matches are found. * @@ -262,36 +340,15 @@ abstract class Zend_Validate_Db_Abstract extends Zend_Validate_Abstract */ protected function _query($value) { - /** - * Check for an adapter being defined. if not, fetch the default adapter. - */ - if ($this->_adapter === null) { - $this->_adapter = Zend_Db_Table_Abstract::getDefaultAdapter(); - if (null === $this->_adapter) { - require_once 'Zend/Validate/Exception.php'; - throw new Zend_Validate_Exception('No database adapter present'); - } - } - - /** - * Build select object - */ - $select = new Zend_Db_Select($this->_adapter); - $select->from($this->_table, array($this->_field), $this->_schema) - ->where($this->_adapter->quoteIdentifier($this->_field, true).' = ?', $value); - if ($this->_exclude !== null) { - if (is_array($this->_exclude)) { - $select->where($this->_adapter->quoteIdentifier($this->_exclude['field'], true).' != ?', $this->_exclude['value']); - } else { - $select->where($this->_exclude); - } - } - $select->limit(1); - + $select = $this->getSelect(); /** * Run query */ - $result = $this->_adapter->fetchRow($select, array(), Zend_Db::FETCH_ASSOC); + $result = $select->getAdapter()->fetchRow( + $select, + array('value' => $value), // this should work whether db supports positional or named params + Zend_Db::FETCH_ASSOC + ); return $result; } diff --git a/lib/zend/Zend/Validate/Db/NoRecordExists.php b/lib/zend/Zend/Validate/Db/NoRecordExists.php index 816c8f0a9b6..4dba8bc6315 100644 --- a/lib/zend/Zend/Validate/Db/NoRecordExists.php +++ b/lib/zend/Zend/Validate/Db/NoRecordExists.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -30,7 +30,7 @@ require_once 'Zend/Validate/Db/Abstract.php'; * @category Zend * @package Zend_Validate * @uses Zend_Validate_Db_Abstract - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Db_NoRecordExists extends Zend_Validate_Db_Abstract diff --git a/lib/zend/Zend/Validate/Db/RecordExists.php b/lib/zend/Zend/Validate/Db/RecordExists.php index 4fc02ca6d4d..540af13bc68 100644 --- a/lib/zend/Zend/Validate/Db/RecordExists.php +++ b/lib/zend/Zend/Validate/Db/RecordExists.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -30,7 +30,7 @@ require_once 'Zend/Validate/Db/Abstract.php'; * @category Zend * @package Zend_Validate * @uses Zend_Validate_Db_Abstract - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Db_RecordExists extends Zend_Validate_Db_Abstract diff --git a/lib/zend/Zend/Validate/Digits.php b/lib/zend/Zend/Validate/Digits.php index 59a45f90ddc..411c4c5b349 100644 --- a/lib/zend/Zend/Validate/Digits.php +++ b/lib/zend/Zend/Validate/Digits.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Abstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Digits extends Zend_Validate_Abstract @@ -49,9 +49,9 @@ class Zend_Validate_Digits extends Zend_Validate_Abstract * @var array */ protected $_messageTemplates = array( - self::NOT_DIGITS => "'%value%' contains characters which are not digits; but only digits are allowed", + self::NOT_DIGITS => "'%value%' must contain only digits", self::STRING_EMPTY => "'%value%' is an empty string", - self::INVALID => "Invalid type given, value should be string, integer or float", + self::INVALID => "Invalid type given. String, integer or float expected", ); /** diff --git a/lib/zend/Zend/Validate/EmailAddress.php b/lib/zend/Zend/Validate/EmailAddress.php index 7e9f0f0c72c..8bffcaec39d 100644 --- a/lib/zend/Zend/Validate/EmailAddress.php +++ b/lib/zend/Zend/Validate/EmailAddress.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -32,7 +32,7 @@ require_once 'Zend/Validate/Hostname.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_EmailAddress extends Zend_Validate_Abstract @@ -51,29 +51,38 @@ class Zend_Validate_EmailAddress extends Zend_Validate_Abstract * @var array */ protected $_messageTemplates = array( - self::INVALID => "Invalid type given, value should be a string", - self::INVALID_FORMAT => "'%value%' is no valid email address in the basic format local-part@hostname", - self::INVALID_HOSTNAME => "'%hostname%' is no valid hostname for email address '%value%'", + self::INVALID => "Invalid type given. String expected", + self::INVALID_FORMAT => "'%value%' is not a valid email address in the basic format local-part@hostname", + self::INVALID_HOSTNAME => "'%hostname%' is not a valid hostname for email address '%value%'", self::INVALID_MX_RECORD => "'%hostname%' does not appear to have a valid MX record for the email address '%value%'", - self::INVALID_SEGMENT => "'%hostname%' is not in a routable network segment. The email address '%value%' should not be resolved from public network.", + self::INVALID_SEGMENT => "'%hostname%' is not in a routable network segment. The email address '%value%' should not be resolved from public network", self::DOT_ATOM => "'%localPart%' can not be matched against dot-atom format", self::QUOTED_STRING => "'%localPart%' can not be matched against quoted-string format", - self::INVALID_LOCAL_PART => "'%localPart%' is no valid local part for email address '%value%'", + self::INVALID_LOCAL_PART => "'%localPart%' is not a valid local part for email address '%value%'", self::LENGTH_EXCEEDED => "'%value%' exceeds the allowed length", ); /** + * As of RFC5753 (JAN 2010), the following blocks are no longer reserved: + * - 128.0.0.0/16 + * - 191.255.0.0/16 + * - 223.255.255.0/24 + * @see http://tools.ietf.org/html/rfc5735#page-6 + * + * As of RFC6598 (APR 2012), the following blocks are now reserved: + * - 100.64.0.0/10 + * @see http://tools.ietf.org/html/rfc6598#section-7 + * * @see http://en.wikipedia.org/wiki/IPv4 * @var array */ protected $_invalidIp = array( '0' => '0.0.0.0/8', '10' => '10.0.0.0/8', + '100' => '100.64.0.0/10', '127' => '127.0.0.0/8', - '128' => '128.0.0.0/16', '169' => '169.254.0.0/16', '172' => '172.16.0.0/12', - '191' => '191.255.0.0/16', '192' => array( '192.0.0.0/24', '192.0.2.0/24', @@ -81,7 +90,6 @@ class Zend_Validate_EmailAddress extends Zend_Validate_Abstract '192.168.0.0/16' ), '198' => '198.18.0.0/15', - '223' => '223.255.255.0/24', '224' => '224.0.0.0/4', '240' => '240.0.0.0/4' ); @@ -124,8 +132,7 @@ class Zend_Validate_EmailAddress extends Zend_Validate_Abstract * 'mx' => If MX check should be enabled, boolean * 'deep' => If a deep MX check should be done, boolean * - * @param array|Zend_Config $options OPTIONAL - * @return void + * @param array|string|Zend_Config $options OPTIONAL */ public function __construct($options = array()) { @@ -163,7 +170,7 @@ class Zend_Validate_EmailAddress extends Zend_Validate_Abstract * Set options for the email validator * * @param array $options - * @return Zend_Validate_EmailAddress fluid interface + * @return Zend_Validate_EmailAddress Provides a fluent inteface */ public function setOptions(array $options = array()) { @@ -177,6 +184,8 @@ class Zend_Validate_EmailAddress extends Zend_Validate_Abstract } else { $this->setHostnameValidator($options['hostname']); } + } elseif ($this->_options['hostname'] == null) { + $this->setHostnameValidator(); } if (array_key_exists('mx', $options)) { @@ -205,17 +214,17 @@ class Zend_Validate_EmailAddress extends Zend_Validate_Abstract */ public function setMessage($messageString, $messageKey = null) { - $messageKeys = $messageKey; if ($messageKey === null) { - $keys = array_keys($this->_messageTemplates); - $messageKeys = current($keys); + $this->_options['hostname']->setMessage($messageString); + parent::setMessage($messageString); + return $this; } - if (!isset($this->_messageTemplates[$messageKeys])) { + if (!isset($this->_messageTemplates[$messageKey])) { $this->_options['hostname']->setMessage($messageString, $messageKey); } - $this->_messageTemplates[$messageKeys] = $messageString; + $this->_messageTemplates[$messageKey] = $messageString; return $this; } @@ -232,7 +241,7 @@ class Zend_Validate_EmailAddress extends Zend_Validate_Abstract /** * @param Zend_Validate_Hostname $hostnameValidator OPTIONAL * @param int $allow OPTIONAL - * @return void + * @return $this */ public function setHostnameValidator(Zend_Validate_Hostname $hostnameValidator = null, $allow = Zend_Validate_Hostname::ALLOW_DNS) { @@ -273,7 +282,8 @@ class Zend_Validate_EmailAddress extends Zend_Validate_Abstract * This only applies when DNS hostnames are validated * * @param boolean $mx Set allowed to true to validate for MX records, and false to not validate them - * @return Zend_Validate_EmailAddress Fluid Interface + * @throws Zend_Validate_Exception + * @return Zend_Validate_EmailAddress Provides a fluent inteface */ public function setValidateMx($mx) { @@ -300,7 +310,7 @@ class Zend_Validate_EmailAddress extends Zend_Validate_Abstract * Set whether we check MX record should be a deep validation * * @param boolean $deep Set deep to true to perform a deep validation process for MX records - * @return Zend_Validate_EmailAddress Fluid Interface + * @return Zend_Validate_EmailAddress Provides a fluent inteface */ public function setDeepMxCheck($deep) { @@ -323,7 +333,7 @@ class Zend_Validate_EmailAddress extends Zend_Validate_Abstract * or only the local part of the email address * * @param boolean $domain - * @return Zend_Validate_EmailAddress Fluid Interface + * @return Zend_Validate_EmailAddress Provides a fluent inteface */ public function setDomainCheck($domain = true) { @@ -414,15 +424,12 @@ class Zend_Validate_EmailAddress extends Zend_Validate_Abstract if (preg_match('/^[' . $atext . ']+(\x2e+[' . $atext . ']+)*$/', $this->_localPart)) { $result = true; } else { - // Try quoted string format + // Try quoted string format (RFC 5321 Chapter 4.1.2) - // Quoted-string characters are: DQUOTE *([FWS] qtext/quoted-pair) [FWS] DQUOTE - // qtext: Non white space controls, and the rest of the US-ASCII characters not - // including "\" or the quote character - $noWsCtl = '\x01-\x08\x0b\x0c\x0e-\x1f\x7f'; - $qtext = $noWsCtl . '\x21\x23-\x5b\x5d-\x7e'; - $ws = '\x20\x09'; - if (preg_match('/^\x22([' . $ws . $qtext . '])*[$ws]?\x22$/', $this->_localPart)) { + // Quoted-string characters are: DQUOTE *(qtext/quoted-pair) DQUOTE + $qtext = '\x20-\x21\x23-\x5b\x5d-\x7e'; // %d32-33 / %d35-91 / %d93-126 + $quotedPair = '\x20-\x7e'; // %d92 %d32-126 + if (preg_match('/^"(['. $qtext .']|\x5c[' . $quotedPair . '])*"$/', $this->localPart)) { $result = true; } else { $this->_error(self::DOT_ATOM); @@ -442,7 +449,14 @@ class Zend_Validate_EmailAddress extends Zend_Validate_Abstract private function _validateMXRecords() { $mxHosts = array(); - $result = getmxrr($this->_hostname, $mxHosts); + $hostname = $this->_hostname; + + //decode IDN domain name if possible + if (function_exists('idn_to_ascii')) { + $hostname = idn_to_ascii($this->_hostname); + } + + $result = getmxrr($hostname, $mxHosts); if (!$result) { $this->_error(self::INVALID_MX_RECORD); } else if ($this->_options['deep'] && function_exists('checkdnsrr')) { diff --git a/lib/zend/Zend/Validate/Exception.php b/lib/zend/Zend/Validate/Exception.php index 750e70cb63b..4a4e2b2cbd4 100644 --- a/lib/zend/Zend/Validate/Exception.php +++ b/lib/zend/Zend/Validate/Exception.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Exception.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Exception extends Zend_Exception diff --git a/lib/zend/Zend/Validate/File/Count.php b/lib/zend/Zend/Validate/File/Count.php index 8a0a430fd05..aa822dfb14b 100644 --- a/lib/zend/Zend/Validate/File/Count.php +++ b/lib/zend/Zend/Validate/File/Count.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -29,7 +29,7 @@ require_once 'Zend/Validate/Abstract.php'; * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_File_Count extends Zend_Validate_Abstract @@ -101,7 +101,7 @@ class Zend_Validate_File_Count extends Zend_Validate_Abstract * 'max': Maximum filecount * * @param integer|array|Zend_Config $options Options for the adapter - * @return void + * @throws Zend_Validate_Exception */ public function __construct($options) { @@ -210,6 +210,7 @@ class Zend_Validate_File_Count extends Zend_Validate_Abstract * Adds a file for validation * * @param string|array $file + * @return $this */ public function addFile($file) { diff --git a/lib/zend/Zend/Validate/File/Crc32.php b/lib/zend/Zend/Validate/File/Crc32.php index 29e8bb3e5aa..9fd47271c65 100644 --- a/lib/zend/Zend/Validate/File/Crc32.php +++ b/lib/zend/Zend/Validate/File/Crc32.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -29,7 +29,7 @@ require_once 'Zend/Validate/File/Hash.php'; * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_File_Crc32 extends Zend_Validate_File_Hash @@ -47,7 +47,7 @@ class Zend_Validate_File_Crc32 extends Zend_Validate_File_Hash protected $_messageTemplates = array( self::DOES_NOT_MATCH => "File '%value%' does not match the given crc32 hashes", self::NOT_DETECTED => "A crc32 hash could not be evaluated for the given file", - self::NOT_FOUND => "File '%value%' could not be found", + self::NOT_FOUND => "File '%value%' is not readable or does not exist", ); /** @@ -61,7 +61,8 @@ class Zend_Validate_File_Crc32 extends Zend_Validate_File_Hash * Sets validator options * * @param string|array|Zend_Config $options - * @return void + * @throws Zend_Validate_Exception + * @return Zend_Validate_File_Crc32 */ public function __construct($options) { @@ -176,4 +177,4 @@ class Zend_Validate_File_Crc32 extends Zend_Validate_File_Hash return $this->_throw($file, self::DOES_NOT_MATCH); } -} \ No newline at end of file +} diff --git a/lib/zend/Zend/Validate/File/ExcludeExtension.php b/lib/zend/Zend/Validate/File/ExcludeExtension.php index 57fe95a7e0b..e894af6a342 100644 --- a/lib/zend/Zend/Validate/File/ExcludeExtension.php +++ b/lib/zend/Zend/Validate/File/ExcludeExtension.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -29,7 +29,7 @@ require_once 'Zend/Validate/File/Extension.php'; * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_File_ExcludeExtension extends Zend_Validate_File_Extension @@ -45,7 +45,7 @@ class Zend_Validate_File_ExcludeExtension extends Zend_Validate_File_Extension */ protected $_messageTemplates = array( self::FALSE_EXTENSION => "File '%value%' has a false extension", - self::NOT_FOUND => "File '%value%' could not be found", + self::NOT_FOUND => "File '%value%' is not readable or does not exist", ); /** diff --git a/lib/zend/Zend/Validate/File/ExcludeMimeType.php b/lib/zend/Zend/Validate/File/ExcludeMimeType.php index 233eee5975b..27d4f5ac3bc 100644 --- a/lib/zend/Zend/Validate/File/ExcludeMimeType.php +++ b/lib/zend/Zend/Validate/File/ExcludeMimeType.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -29,7 +29,7 @@ require_once 'Zend/Validate/File/MimeType.php'; * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_File_ExcludeMimeType extends Zend_Validate_File_MimeType @@ -38,6 +38,15 @@ class Zend_Validate_File_ExcludeMimeType extends Zend_Validate_File_MimeType const NOT_DETECTED = 'fileExcludeMimeTypeNotDetected'; const NOT_READABLE = 'fileExcludeMimeTypeNotReadable'; + /** + * @var array Error message templates + */ + protected $_messageTemplates = array( + self::FALSE_TYPE => "File '%value%' has a false mimetype of '%type%'", + self::NOT_DETECTED => "The mimetype of file '%value%' could not be detected", + self::NOT_READABLE => "File '%value%' is not readable or does not exist", + ); + /** * Defined by Zend_Validate_Interface * @@ -64,27 +73,10 @@ class Zend_Validate_File_ExcludeMimeType extends Zend_Validate_File_MimeType return $this->_throw($file, self::NOT_READABLE); } - $mimefile = $this->getMagicFile(); - if (class_exists('finfo', false)) { - $const = defined('FILEINFO_MIME_TYPE') ? FILEINFO_MIME_TYPE : FILEINFO_MIME; - if (!empty($mimefile)) { - $mime = new finfo($const, $mimefile); - } else { - $mime = new finfo($const); - } + $this->_type = $this->_detectMimeType($value); - if (!empty($mime)) { - $this->_type = $mime->file($value); - } - unset($mime); - } - - if (empty($this->_type)) { - if (function_exists('mime_content_type') && ini_get('mime_magic.magicfile')) { - $this->_type = mime_content_type($value); - } elseif ($this->_headerCheck) { - $this->_type = $file['type']; - } + if (empty($this->_type) && $this->_headerCheck) { + $this->_type = $file['type']; } if (empty($this->_type)) { diff --git a/lib/zend/Zend/Validate/File/Exists.php b/lib/zend/Zend/Validate/File/Exists.php index ffa5affe6de..8da1ccdd7d8 100644 --- a/lib/zend/Zend/Validate/File/Exists.php +++ b/lib/zend/Zend/Validate/File/Exists.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -29,7 +29,7 @@ require_once 'Zend/Validate/Abstract.php'; * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_File_Exists extends Zend_Validate_Abstract @@ -63,7 +63,7 @@ class Zend_Validate_File_Exists extends Zend_Validate_Abstract * Sets validator options * * @param string|array|Zend_Config $directory - * @return void + * @throws Zend_Validate_Exception */ public function __construct($directory = array()) { @@ -113,6 +113,7 @@ class Zend_Validate_File_Exists extends Zend_Validate_Abstract * Adds the file directory which will be checked * * @param string|array $directory The directory to add for validation + * @throws Zend_Validate_Exception * @return Zend_Validate_File_Extension Provides a fluent interface */ public function addDirectory($directory) diff --git a/lib/zend/Zend/Validate/File/Extension.php b/lib/zend/Zend/Validate/File/Extension.php index ed5fff25e5b..92f9f06a87f 100644 --- a/lib/zend/Zend/Validate/File/Extension.php +++ b/lib/zend/Zend/Validate/File/Extension.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -29,7 +29,7 @@ require_once 'Zend/Validate/Abstract.php'; * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_File_Extension extends Zend_Validate_Abstract @@ -45,7 +45,7 @@ class Zend_Validate_File_Extension extends Zend_Validate_Abstract */ protected $_messageTemplates = array( self::FALSE_EXTENSION => "File '%value%' has a false extension", - self::NOT_FOUND => "File '%value%' could not be found", + self::NOT_FOUND => "File '%value%' is not readable or does not exist", ); /** @@ -71,8 +71,7 @@ class Zend_Validate_File_Extension extends Zend_Validate_Abstract /** * Sets validator options * - * @param string|array|Zend_Config $options - * @return void + * @param string|array|Zend_Config $options */ public function __construct($options) { @@ -196,6 +195,12 @@ class Zend_Validate_File_Extension extends Zend_Validate_Abstract $info['extension'] = substr($file['name'], strrpos($file['name'], '.') + 1); } else { $info = pathinfo($value); + if (!array_key_exists('extension', $info)) { + // From the manual at http://php.net/pathinfo: + // "If the path does not have an extension, no extension element + // will be returned (see second example below)." + return false; + } } $extensions = $this->getExtension(); diff --git a/lib/zend/Zend/Validate/File/FilesSize.php b/lib/zend/Zend/Validate/File/FilesSize.php index 9565f876f30..b6481334162 100644 --- a/lib/zend/Zend/Validate/File/FilesSize.php +++ b/lib/zend/Zend/Validate/File/FilesSize.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -29,7 +29,7 @@ require_once 'Zend/Validate/File/Size.php'; * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_File_FilesSize extends Zend_Validate_File_Size @@ -64,7 +64,7 @@ class Zend_Validate_File_FilesSize extends Zend_Validate_File_Size * It also accepts an array with the keys 'min' and 'max' * * @param integer|array|Zend_Config $options Options for this validator - * @return void + * @throws Zend_Validate_Exception */ public function __construct($options) { diff --git a/lib/zend/Zend/Validate/File/Hash.php b/lib/zend/Zend/Validate/File/Hash.php index 9d72fd21dae..54b036756fc 100644 --- a/lib/zend/Zend/Validate/File/Hash.php +++ b/lib/zend/Zend/Validate/File/Hash.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -29,7 +29,7 @@ require_once 'Zend/Validate/Abstract.php'; * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_File_Hash extends Zend_Validate_Abstract @@ -47,7 +47,7 @@ class Zend_Validate_File_Hash extends Zend_Validate_Abstract protected $_messageTemplates = array( self::DOES_NOT_MATCH => "File '%value%' does not match the given hashes", self::NOT_DETECTED => "A hash could not be evaluated for the given file", - self::NOT_FOUND => "File '%value%' could not be found" + self::NOT_FOUND => "File '%value%' is not readable or does not exist" ); /** @@ -61,7 +61,7 @@ class Zend_Validate_File_Hash extends Zend_Validate_Abstract * Sets validator options * * @param string|array $options - * @return void + * @throws Zend_Validate_Exception */ public function __construct($options) { @@ -109,6 +109,7 @@ class Zend_Validate_File_Hash extends Zend_Validate_Abstract * Adds the hash for one or multiple files * * @param string|array $options + * @throws Zend_Validate_Exception * @return Zend_Validate_File_Hash Provides a fluent interface */ public function addHash($options) diff --git a/lib/zend/Zend/Validate/File/ImageSize.php b/lib/zend/Zend/Validate/File/ImageSize.php index 42d5e3c0cc0..871fef84ffb 100644 --- a/lib/zend/Zend/Validate/File/ImageSize.php +++ b/lib/zend/Zend/Validate/File/ImageSize.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -29,7 +29,7 @@ require_once 'Zend/Validate/Abstract.php'; * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_File_ImageSize extends Zend_Validate_Abstract @@ -53,7 +53,7 @@ class Zend_Validate_File_ImageSize extends Zend_Validate_Abstract self::HEIGHT_TOO_BIG => "Maximum allowed height for image '%value%' should be '%maxheight%' but '%height%' detected", self::HEIGHT_TOO_SMALL => "Minimum expected height for image '%value%' should be '%minheight%' but '%height%' detected", self::NOT_DETECTED => "The size of image '%value%' could not be detected", - self::NOT_READABLE => "File '%value%' can not be read", + self::NOT_READABLE => "File '%value%' is not readable or does not exist", ); /** @@ -120,7 +120,7 @@ class Zend_Validate_File_ImageSize extends Zend_Validate_Abstract * - maxwidth * * @param Zend_Config|array $options - * @return void + * @throws Zend_Validate_Exception */ public function __construct($options) { diff --git a/lib/zend/Zend/Validate/File/IsCompressed.php b/lib/zend/Zend/Validate/File/IsCompressed.php index 0b491d9842e..ce59423bd2b 100644 --- a/lib/zend/Zend/Validate/File/IsCompressed.php +++ b/lib/zend/Zend/Validate/File/IsCompressed.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -29,7 +29,7 @@ require_once 'Zend/Validate/File/MimeType.php'; * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_File_IsCompressed extends Zend_Validate_File_MimeType @@ -46,15 +46,14 @@ class Zend_Validate_File_IsCompressed extends Zend_Validate_File_MimeType */ protected $_messageTemplates = array( self::FALSE_TYPE => "File '%value%' is not compressed, '%type%' detected", - self::NOT_DETECTED => "The mimetype of file '%value%' could not been detected", - self::NOT_READABLE => "File '%value%' can not be read", + self::NOT_DETECTED => "The mimetype of file '%value%' could not be detected", + self::NOT_READABLE => "File '%value%' is not readable or does not exist", ); /** * Sets validator options * - * @param string|array|Zend_Config $compression - * @return void + * @param string|array|Zend_Config $mimetype */ public function __construct($mimetype = array()) { @@ -94,6 +93,7 @@ class Zend_Validate_File_IsCompressed extends Zend_Validate_File_MimeType 'application/x-stuffit', 'application/x-tar', 'application/zip', + 'application/x-zip', 'application/zoo', 'multipart/x-gzip', ); diff --git a/lib/zend/Zend/Validate/File/IsImage.php b/lib/zend/Zend/Validate/File/IsImage.php index 23c996092d0..09a6e42ab2f 100644 --- a/lib/zend/Zend/Validate/File/IsImage.php +++ b/lib/zend/Zend/Validate/File/IsImage.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -29,7 +29,7 @@ require_once 'Zend/Validate/File/MimeType.php'; * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_File_IsImage extends Zend_Validate_File_MimeType @@ -47,14 +47,13 @@ class Zend_Validate_File_IsImage extends Zend_Validate_File_MimeType protected $_messageTemplates = array( self::FALSE_TYPE => "File '%value%' is no image, '%type%' detected", self::NOT_DETECTED => "The mimetype of file '%value%' could not be detected", - self::NOT_READABLE => "File '%value%' can not be read", + self::NOT_READABLE => "File '%value%' is not readable or does not exist", ); /** * Sets validator options * - * @param string|array|Zend_Config $mimetype - * @return void + * @param string|array|Zend_Config $mimetype */ public function __construct($mimetype = array()) { diff --git a/lib/zend/Zend/Validate/File/Md5.php b/lib/zend/Zend/Validate/File/Md5.php index c1d5d0d0c0c..bfe0b6046ed 100644 --- a/lib/zend/Zend/Validate/File/Md5.php +++ b/lib/zend/Zend/Validate/File/Md5.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -29,7 +29,7 @@ require_once 'Zend/Validate/File/Hash.php'; * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_File_Md5 extends Zend_Validate_File_Hash @@ -47,7 +47,7 @@ class Zend_Validate_File_Md5 extends Zend_Validate_File_Hash protected $_messageTemplates = array( self::DOES_NOT_MATCH => "File '%value%' does not match the given md5 hashes", self::NOT_DETECTED => "A md5 hash could not be evaluated for the given file", - self::NOT_FOUND => "File '%value%' could not be found", + self::NOT_FOUND => "File '%value%' is not readable or does not exist", ); /** @@ -63,7 +63,8 @@ class Zend_Validate_File_Md5 extends Zend_Validate_File_Hash * $hash is the hash we accept for the file $file * * @param string|array $options - * @return void + * @throws Zend_Validate_Exception + * @return Zend_Validate_File_Md5 */ public function __construct($options) { @@ -93,7 +94,6 @@ class Zend_Validate_File_Md5 extends Zend_Validate_File_Hash * Sets the md5 hash for one or multiple files * * @param string|array $options - * @param string $algorithm (Deprecated) Algorithm to use, fixed to md5 * @return Zend_Validate_File_Hash Provides a fluent interface */ public function setHash($options) @@ -123,7 +123,6 @@ class Zend_Validate_File_Md5 extends Zend_Validate_File_Hash * Adds the md5 hash for one or multiple files * * @param string|array $options - * @param string $algorithm (Deprecated) Algorithm to use, fixed to md5 * @return Zend_Validate_File_Hash Provides a fluent interface */ public function addHash($options) diff --git a/lib/zend/Zend/Validate/File/MimeType.php b/lib/zend/Zend/Validate/File/MimeType.php index f04a4d9120c..8741488368d 100644 --- a/lib/zend/Zend/Validate/File/MimeType.php +++ b/lib/zend/Zend/Validate/File/MimeType.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -29,18 +29,17 @@ require_once 'Zend/Validate/Abstract.php'; * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_File_MimeType extends Zend_Validate_Abstract { - /**#@+ + /** * @const Error type constants */ const FALSE_TYPE = 'fileMimeTypeFalse'; const NOT_DETECTED = 'fileMimeTypeNotDetected'; const NOT_READABLE = 'fileMimeTypeNotReadable'; - /**#@-*/ /** * @var array Error message templates @@ -48,7 +47,7 @@ class Zend_Validate_File_MimeType extends Zend_Validate_Abstract protected $_messageTemplates = array( self::FALSE_TYPE => "File '%value%' has a false mimetype of '%type%'", self::NOT_DETECTED => "The mimetype of file '%value%' could not be detected", - self::NOT_READABLE => "File '%value%' can not be read", + self::NOT_READABLE => "File '%value%' is not readable or does not exist", ); /** @@ -102,6 +101,12 @@ class Zend_Validate_File_MimeType extends Zend_Validate_Abstract '/usr/share/file/magic.mgc', ); + /** + * Indicates whether use of $_magicFiles should be attempted. + * @var boolean + */ + protected $_tryCommonMagicFiles = true; + /** * Option to allow header check * @@ -109,13 +114,20 @@ class Zend_Validate_File_MimeType extends Zend_Validate_Abstract */ protected $_headerCheck = false; + /** + * Holds error information returned by finfo_open + * + * @var array + */ + protected $_finfoError; + /** * Sets validator options * * Mimetype to accept * * @param string|array $mimetype MimeType - * @return void + * @throws Zend_Validate_Exception */ public function __construct($mimetype) { @@ -144,14 +156,22 @@ class Zend_Validate_File_MimeType extends Zend_Validate_Abstract /** * Returns the actual set magicfile * + * Note that for PHP 5.3.0 or higher, we don't use $_ENV['MAGIC'] or try to + * find a magic file in a common location as PHP now has a built-in internal + * magic file. + * * @return string */ public function getMagicFile() { - if (null === $this->_magicfile) { + if (version_compare(PHP_VERSION, '5.3.0', '<') + && null === $this->_magicfile) { if (!empty($_ENV['MAGIC'])) { $this->setMagicFile($_ENV['MAGIC']); - } elseif (!(@ini_get("safe_mode") == 'On' || @ini_get("safe_mode") === 1)) { + } elseif ( + !(@ini_get("safe_mode") == 'On' || @ini_get("safe_mode") === 1) + && $this->shouldTryCommonMagicFiles() // @see ZF-11784 + ) { require_once 'Zend/Validate/Exception.php'; foreach ($this->_magicFiles as $file) { // supressing errors which are thrown due to openbase_dir restrictions @@ -181,7 +201,7 @@ class Zend_Validate_File_MimeType extends Zend_Validate_Abstract * * @param string $file * @throws Zend_Validate_Exception When finfo can not read the magicfile - * @return Zend_Validate_File_MimeType Provides fluid interface + * @return Zend_Validate_File_MimeType Provides a fluent interface */ public function setMagicFile($file) { @@ -191,16 +211,22 @@ class Zend_Validate_File_MimeType extends Zend_Validate_Abstract $this->_magicfile = null; require_once 'Zend/Validate/Exception.php'; throw new Zend_Validate_Exception('Magicfile can not be set. There is no finfo extension installed'); - } else if (!is_readable($file)) { + } else if (!is_file($file) || !is_readable($file)) { require_once 'Zend/Validate/Exception.php'; throw new Zend_Validate_Exception('The given magicfile can not be read'); } else { $const = defined('FILEINFO_MIME_TYPE') ? FILEINFO_MIME_TYPE : FILEINFO_MIME; - $this->_finfo = @finfo_open($const, $file); + set_error_handler(array($this, '_errorHandler'), E_NOTICE | E_WARNING); + $this->_finfo = finfo_open($const, $file); + restore_error_handler(); if (empty($this->_finfo)) { $this->_finfo = null; require_once 'Zend/Validate/Exception.php'; - throw new Zend_Validate_Exception('The given magicfile is not accepted by finfo'); + throw new Zend_Validate_Exception( + sprintf('The given magicfile ("%s") is not accepted by finfo', $file), + null, + $this->_finfoError + ); } else { $this->_magicfile = $file; } @@ -209,6 +235,32 @@ class Zend_Validate_File_MimeType extends Zend_Validate_Abstract return $this; } + /** + * Enables or disables attempts to try the common magic file locations + * specified by Zend_Validate_File_MimeType::_magicFiles + * + * @param boolean $flag + * @return Zend_Validate_File_MimeType Provides fluent interface + * @see http://framework.zend.com/issues/browse/ZF-11784 + */ + public function setTryCommonMagicFilesFlag($flag = true) + { + $this->_tryCommonMagicFiles = (boolean) $flag; + + return $this; + } + + /** + * Accessor for Zend_Validate_File_MimeType::_magicFiles + * + * @return boolean + * @see http://framework.zend.com/issues/browse/ZF-11784 + */ + public function shouldTryCommonMagicFiles() + { + return $this->_tryCommonMagicFiles; + } + /** * Returns the Header Check option * @@ -223,8 +275,8 @@ class Zend_Validate_File_MimeType extends Zend_Validate_Abstract * Defines if the http header should be used * Note that this is unsave and therefor the default value is false * - * @param boolean $checkHeader - * @return Zend_Validate_File_MimeType Provides fluid interface + * @param boolean $headerCheck + * @return Zend_Validate_File_MimeType Provides a fluent interface */ public function enableHeaderCheck($headerCheck = true) { @@ -266,6 +318,7 @@ class Zend_Validate_File_MimeType extends Zend_Validate_Abstract * Adds the mimetypes * * @param string|array $mimetype The mimetypes to add for validation + * @throws Zend_Validate_Exception * @return Zend_Validate_File_Extension Provides a fluent interface */ public function addMimeType($mimetype) @@ -329,27 +382,7 @@ class Zend_Validate_File_MimeType extends Zend_Validate_Abstract return $this->_throw($file, self::NOT_READABLE); } - $mimefile = $this->getMagicFile(); - if (class_exists('finfo', false)) { - $const = defined('FILEINFO_MIME_TYPE') ? FILEINFO_MIME_TYPE : FILEINFO_MIME; - if (!empty($mimefile) && empty($this->_finfo)) { - $this->_finfo = @finfo_open($const, $mimefile); - } - - if (empty($this->_finfo)) { - $this->_finfo = @finfo_open($const); - } - - $this->_type = null; - if (!empty($this->_finfo)) { - $this->_type = finfo_file($this->_finfo, $value); - } - } - - if (empty($this->_type) && - (function_exists('mime_content_type') && ini_get('mime_magic.magicfile'))) { - $this->_type = mime_content_type($value); - } + $this->_type = $this->_detectMimeType($value); if (empty($this->_type) && $this->_headerCheck) { $this->_type = $file['type']; @@ -389,4 +422,55 @@ class Zend_Validate_File_MimeType extends Zend_Validate_Abstract $this->_error($errorType); return false; } + + /** + * Try to detect mime type of given file. + * @param string $file File which mime type should be detected + * @return string File mime type or null if not detected + */ + protected function _detectMimeType($file) + { + $mimefile = $this->getMagicFile(); + $type = null; + + if (class_exists('finfo', false)) { + $const = defined('FILEINFO_MIME_TYPE') ? FILEINFO_MIME_TYPE : FILEINFO_MIME; + + if (!empty($mimefile) && empty($this->_finfo)) { + set_error_handler(array($this, '_errorHandler'), E_NOTICE | E_WARNING); + $this->_finfo = finfo_open($const, $mimefile); + restore_error_handler(); + } + + if (empty($this->_finfo)) { + set_error_handler(array($this, '_errorHandler'), E_NOTICE | E_WARNING); + $this->_finfo = finfo_open($const); + restore_error_handler(); + } + + if (!empty($this->_finfo)) { + $type = finfo_file($this->_finfo, $file); + } + } + + if (empty($type) && + (function_exists('mime_content_type') && ini_get('mime_magic.magicfile'))) { + $type = mime_content_type($file); + } + + return $type; + } + + /** + * Saves the provided error information by finfo_open to this instance + * + * @param integer $errno + * @param string $errstr + * @param string $errfile + * @param integer $errline + */ + protected function _errorHandler($errno, $errstr, $errfile, $errline) + { + $this->_finfoError = new ErrorException($errstr, $errno, 0, $errfile, $errline); + } } diff --git a/lib/zend/Zend/Validate/File/NotExists.php b/lib/zend/Zend/Validate/File/NotExists.php index 8fb5efe9e00..bf58dce229e 100644 --- a/lib/zend/Zend/Validate/File/NotExists.php +++ b/lib/zend/Zend/Validate/File/NotExists.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -29,7 +29,7 @@ require_once 'Zend/Validate/File/Exists.php'; * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_File_NotExists extends Zend_Validate_File_Exists diff --git a/lib/zend/Zend/Validate/File/Sha1.php b/lib/zend/Zend/Validate/File/Sha1.php index 18bb9f1a9dc..e4076139bb2 100644 --- a/lib/zend/Zend/Validate/File/Sha1.php +++ b/lib/zend/Zend/Validate/File/Sha1.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -29,7 +29,7 @@ require_once 'Zend/Validate/File/Hash.php'; * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_File_Sha1 extends Zend_Validate_File_Hash @@ -47,7 +47,7 @@ class Zend_Validate_File_Sha1 extends Zend_Validate_File_Hash protected $_messageTemplates = array( self::DOES_NOT_MATCH => "File '%value%' does not match the given sha1 hashes", self::NOT_DETECTED => "A sha1 hash could not be evaluated for the given file", - self::NOT_FOUND => "File '%value%' could not be found", + self::NOT_FOUND => "File '%value%' is not readable or does not exist", ); /** @@ -63,7 +63,8 @@ class Zend_Validate_File_Sha1 extends Zend_Validate_File_Hash * $hash is the hash we accept for the file $file * * @param string|array $options - * @return void + * @throws Zend_Validate_Exception + * @return Zend_Validate_File_Sha1 */ public function __construct($options) { diff --git a/lib/zend/Zend/Validate/File/Size.php b/lib/zend/Zend/Validate/File/Size.php index 5f7922276b5..bc9dea0d231 100644 --- a/lib/zend/Zend/Validate/File/Size.php +++ b/lib/zend/Zend/Validate/File/Size.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -29,7 +29,7 @@ require_once 'Zend/Validate/Abstract.php'; * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_File_Size extends Zend_Validate_Abstract @@ -48,7 +48,7 @@ class Zend_Validate_File_Size extends Zend_Validate_Abstract protected $_messageTemplates = array( self::TOO_BIG => "Maximum allowed size for file '%value%' is '%max%' but '%size%' detected", self::TOO_SMALL => "Minimum expected size for file '%value%' is '%min%' but '%size%' detected", - self::NOT_FOUND => "File '%value%' could not be found", + self::NOT_FOUND => "File '%value%' is not readable or does not exist", ); /** @@ -99,6 +99,7 @@ class Zend_Validate_File_Size extends Zend_Validate_Abstract * 'bytestring': Use bytestring or real size for messages * * @param integer|array $options Options for the adapter + * @throws Zend_Validate_Exception */ public function __construct($options) { diff --git a/lib/zend/Zend/Validate/File/Upload.php b/lib/zend/Zend/Validate/File/Upload.php index 1bb0e3c4370..5eae769846a 100644 --- a/lib/zend/Zend/Validate/File/Upload.php +++ b/lib/zend/Zend/Validate/File/Upload.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -29,7 +29,7 @@ require_once 'Zend/Validate/Abstract.php'; * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_File_Upload extends Zend_Validate_Abstract @@ -78,8 +78,7 @@ class Zend_Validate_File_Upload extends Zend_Validate_Abstract * If no files are given the $_FILES array will be used automatically. * NOTE: This validator will only work with HTTP POST uploads! * - * @param array|Zend_Config $files Array of files in syntax of Zend_File_Transfer - * @return void + * @param array|Zend_Config $files Array of files in syntax of Zend_File_Transfer */ public function __construct($files = array()) { @@ -93,7 +92,7 @@ class Zend_Validate_File_Upload extends Zend_Validate_Abstract /** * Returns the array of set files * - * @param string $files (Optional) The file to return in detail + * @param string $file (Optional) The file to return in detail * @return array * @throws Zend_Validate_Exception If file is not found */ @@ -136,6 +135,11 @@ class Zend_Validate_File_Upload extends Zend_Validate_Abstract $this->_files = $files; } + // see ZF-10738 + if (is_null($this->_files)) { + $this->_files = array(); + } + foreach($this->_files as $file => $content) { if (!isset($content['error'])) { unset($this->_files[$file]); @@ -152,6 +156,7 @@ class Zend_Validate_File_Upload extends Zend_Validate_Abstract * * @param string $value Single file to check for upload errors, when giving null the $_FILES array * from initialization will be used + * @param string|null $file * @return boolean */ public function isValid($value, $file = null) @@ -180,40 +185,40 @@ class Zend_Validate_File_Upload extends Zend_Validate_Abstract switch($content['error']) { case 0: if (!is_uploaded_file($content['tmp_name'])) { - $this->_throw($file, self::ATTACK); + $this->_throw($content, self::ATTACK); } break; case 1: - $this->_throw($file, self::INI_SIZE); + $this->_throw($content, self::INI_SIZE); break; case 2: - $this->_throw($file, self::FORM_SIZE); + $this->_throw($content, self::FORM_SIZE); break; case 3: - $this->_throw($file, self::PARTIAL); + $this->_throw($content, self::PARTIAL); break; case 4: - $this->_throw($file, self::NO_FILE); + $this->_throw($content, self::NO_FILE); break; case 6: - $this->_throw($file, self::NO_TMP_DIR); + $this->_throw($content, self::NO_TMP_DIR); break; case 7: - $this->_throw($file, self::CANT_WRITE); + $this->_throw($content, self::CANT_WRITE); break; case 8: - $this->_throw($file, self::EXTENSION); + $this->_throw($content, self::EXTENSION); break; default: - $this->_throw($file, self::UNKNOWN); + $this->_throw($content, self::UNKNOWN); break; } } diff --git a/lib/zend/Zend/Validate/File/WordCount.php b/lib/zend/Zend/Validate/File/WordCount.php index 5b76c3e6ffd..42c79a5bd53 100644 --- a/lib/zend/Zend/Validate/File/WordCount.php +++ b/lib/zend/Zend/Validate/File/WordCount.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -29,7 +29,7 @@ require_once 'Zend/Validate/File/Count.php'; * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_File_WordCount extends Zend_Validate_File_Count @@ -48,7 +48,7 @@ class Zend_Validate_File_WordCount extends Zend_Validate_File_Count protected $_messageTemplates = array( self::TOO_MUCH => "Too much words, maximum '%max%' are allowed but '%count%' were counted", self::TOO_LESS => "Too less words, minimum '%min%' are expected but '%count%' were counted", - self::NOT_FOUND => "File '%value%' could not be found", + self::NOT_FOUND => "File '%value%' is not readable or does not exist", ); /** diff --git a/lib/zend/Zend/Validate/Float.php b/lib/zend/Zend/Validate/Float.php index c74286aa219..f0879a54100 100644 --- a/lib/zend/Zend/Validate/Float.php +++ b/lib/zend/Zend/Validate/Float.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -32,7 +32,7 @@ require_once 'Zend/Locale/Format.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Float extends Zend_Validate_Abstract @@ -44,7 +44,7 @@ class Zend_Validate_Float extends Zend_Validate_Abstract * @var array */ protected $_messageTemplates = array( - self::INVALID => "Invalid type given, value should be float, string, or integer", + self::INVALID => "Invalid type given. String, integer or float expected", self::NOT_FLOAT => "'%value%' does not appear to be a float", ); @@ -91,6 +91,7 @@ class Zend_Validate_Float extends Zend_Validate_Abstract * Sets the locale to use * * @param string|Zend_Locale $locale + * @return $this */ public function setLocale($locale = null) { diff --git a/lib/zend/Zend/Validate/GreaterThan.php b/lib/zend/Zend/Validate/GreaterThan.php index f9df5f09b9c..5dd0579cdb6 100644 --- a/lib/zend/Zend/Validate/GreaterThan.php +++ b/lib/zend/Zend/Validate/GreaterThan.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Abstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_GreaterThan extends Zend_Validate_Abstract @@ -60,7 +60,7 @@ class Zend_Validate_GreaterThan extends Zend_Validate_Abstract * Sets validator options * * @param mixed|Zend_Config $min - * @return void + * @throws Zend_Validate_Exception */ public function __construct($min) { diff --git a/lib/zend/Zend/Validate/Hex.php b/lib/zend/Zend/Validate/Hex.php index aa0e0a04b19..c6f780974d6 100644 --- a/lib/zend/Zend/Validate/Hex.php +++ b/lib/zend/Zend/Validate/Hex.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Abstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Hex extends Zend_Validate_Abstract @@ -41,7 +41,7 @@ class Zend_Validate_Hex extends Zend_Validate_Abstract * @var array */ protected $_messageTemplates = array( - self::INVALID => "Invalid type given, value should be a string", + self::INVALID => "Invalid type given. String expected", self::NOT_HEX => "'%value%' has not only hexadecimal digit characters", ); diff --git a/lib/zend/Zend/Validate/Hostname.php b/lib/zend/Zend/Validate/Hostname.php index 3e9eac72589..dc04961aa53 100644 --- a/lib/zend/Zend/Validate/Hostname.php +++ b/lib/zend/Zend/Validate/Hostname.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -41,36 +41,38 @@ require_once 'Zend/Validate/Ip.php'; * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Hostname extends Zend_Validate_Abstract { - const INVALID = 'hostnameInvalid'; - const IP_ADDRESS_NOT_ALLOWED = 'hostnameIpAddressNotAllowed'; - const UNKNOWN_TLD = 'hostnameUnknownTld'; - const INVALID_DASH = 'hostnameDashCharacter'; - const INVALID_HOSTNAME_SCHEMA = 'hostnameInvalidHostnameSchema'; - const UNDECIPHERABLE_TLD = 'hostnameUndecipherableTld'; - const INVALID_HOSTNAME = 'hostnameInvalidHostname'; - const INVALID_LOCAL_NAME = 'hostnameInvalidLocalName'; - const LOCAL_NAME_NOT_ALLOWED = 'hostnameLocalNameNotAllowed'; const CANNOT_DECODE_PUNYCODE = 'hostnameCannotDecodePunycode'; + const INVALID = 'hostnameInvalid'; + const INVALID_DASH = 'hostnameDashCharacter'; + const INVALID_HOSTNAME = 'hostnameInvalidHostname'; + const INVALID_HOSTNAME_SCHEMA = 'hostnameInvalidHostnameSchema'; + const INVALID_LOCAL_NAME = 'hostnameInvalidLocalName'; + const INVALID_URI = 'hostnameInvalidUri'; + const IP_ADDRESS_NOT_ALLOWED = 'hostnameIpAddressNotAllowed'; + const LOCAL_NAME_NOT_ALLOWED = 'hostnameLocalNameNotAllowed'; + const UNDECIPHERABLE_TLD = 'hostnameUndecipherableTld'; + const UNKNOWN_TLD = 'hostnameUnknownTld'; /** * @var array */ protected $_messageTemplates = array( - self::INVALID => "Invalid type given, value should be a string", - self::IP_ADDRESS_NOT_ALLOWED => "'%value%' appears to be an IP address, but IP addresses are not allowed", - self::UNKNOWN_TLD => "'%value%' appears to be a DNS hostname but cannot match TLD against known list", - self::INVALID_DASH => "'%value%' appears to be a DNS hostname but contains a dash in an invalid position", - self::INVALID_HOSTNAME_SCHEMA => "'%value%' appears to be a DNS hostname but cannot match against hostname schema for TLD '%tld%'", - self::UNDECIPHERABLE_TLD => "'%value%' appears to be a DNS hostname but cannot extract TLD part", - self::INVALID_HOSTNAME => "'%value%' does not match the expected structure for a DNS hostname", - self::INVALID_LOCAL_NAME => "'%value%' does not appear to be a valid local network name", - self::LOCAL_NAME_NOT_ALLOWED => "'%value%' appears to be a local network name but local network names are not allowed", self::CANNOT_DECODE_PUNYCODE => "'%value%' appears to be a DNS hostname but the given punycode notation cannot be decoded", + self::INVALID => "Invalid type given. String expected", + self::INVALID_DASH => "'%value%' appears to be a DNS hostname but contains a dash in an invalid position", + self::INVALID_HOSTNAME => "'%value%' does not match the expected structure for a DNS hostname", + self::INVALID_HOSTNAME_SCHEMA => "'%value%' appears to be a DNS hostname but cannot match against hostname schema for TLD '%tld%'", + self::INVALID_LOCAL_NAME => "'%value%' does not appear to be a valid local network name", + self::INVALID_URI => "'%value%' does not appear to be a valid URI hostname", + self::IP_ADDRESS_NOT_ALLOWED => "'%value%' appears to be an IP address, but IP addresses are not allowed", + self::LOCAL_NAME_NOT_ALLOWED => "'%value%' appears to be a local network name but local network names are not allowed", + self::UNDECIPHERABLE_TLD => "'%value%' appears to be a DNS hostname but cannot extract TLD part", + self::UNKNOWN_TLD => "'%value%' appears to be a DNS hostname but cannot match TLD against known list", ); /** @@ -98,35 +100,875 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract /** * Allows all types of hostnames */ - const ALLOW_ALL = 7; + const ALLOW_URI = 8; + + /** + * Allows all types of hostnames + */ + const ALLOW_ALL = 15; /** * Array of valid top-level-domains * - * @see ftp://data.iana.org/TLD/tlds-alpha-by-domain.txt List of all TLDs by domain + * Version 2014112800, Last Updated Fri Nov 28 07:07:01 2014 UTC + * + * @see http://data.iana.org/TLD/tlds-alpha-by-domain.txt List of all TLDs by domain * @see http://www.iana.org/domains/root/db/ Official list of supported TLDs * @var array */ protected $_validTlds = array( - 'ac', 'ad', 'ae', 'aero', 'af', 'ag', 'ai', 'al', 'am', 'an', 'ao', 'aq', 'ar', 'arpa', - 'as', 'asia', 'at', 'au', 'aw', 'ax', 'az', 'ba', 'bb', 'bd', 'be', 'bf', 'bg', 'bh', 'bi', - 'biz', 'bj', 'bm', 'bn', 'bo', 'br', 'bs', 'bt', 'bv', 'bw', 'by', 'bz', 'ca', 'cat', 'cc', - 'cd', 'cf', 'cg', 'ch', 'ci', 'ck', 'cl', 'cm', 'cn', 'co', 'com', 'coop', 'cr', 'cu', - 'cv', 'cx', 'cy', 'cz', 'de', 'dj', 'dk', 'dm', 'do', 'dz', 'ec', 'edu', 'ee', 'eg', 'er', - 'es', 'et', 'eu', 'fi', 'fj', 'fk', 'fm', 'fo', 'fr', 'ga', 'gb', 'gd', 'ge', 'gf', 'gg', - 'gh', 'gi', 'gl', 'gm', 'gn', 'gov', 'gp', 'gq', 'gr', 'gs', 'gt', 'gu', 'gw', 'gy', 'hk', - 'hm', 'hn', 'hr', 'ht', 'hu', 'id', 'ie', 'il', 'im', 'in', 'info', 'int', 'io', 'iq', - 'ir', 'is', 'it', 'je', 'jm', 'jo', 'jobs', 'jp', 'ke', 'kg', 'kh', 'ki', 'km', 'kn', 'kp', - 'kr', 'kw', 'ky', 'kz', 'la', 'lb', 'lc', 'li', 'lk', 'lr', 'ls', 'lt', 'lu', 'lv', 'ly', - 'ma', 'mc', 'md', 'me', 'mg', 'mh', 'mil', 'mk', 'ml', 'mm', 'mn', 'mo', 'mobi', 'mp', - 'mq', 'mr', 'ms', 'mt', 'mu', 'museum', 'mv', 'mw', 'mx', 'my', 'mz', 'na', 'name', 'nc', - 'ne', 'net', 'nf', 'ng', 'ni', 'nl', 'no', 'np', 'nr', 'nu', 'nz', 'om', 'org', 'pa', 'pe', - 'pf', 'pg', 'ph', 'pk', 'pl', 'pm', 'pn', 'pr', 'pro', 'ps', 'pt', 'pw', 'py', 'qa', 're', - 'ro', 'rs', 'ru', 'rw', 'sa', 'sb', 'sc', 'sd', 'se', 'sg', 'sh', 'si', 'sj', 'sk', 'sl', - 'sm', 'sn', 'so', 'sr', 'st', 'su', 'sv', 'sy', 'sz', 'tc', 'td', 'tel', 'tf', 'tg', 'th', - 'tj', 'tk', 'tl', 'tm', 'tn', 'to', 'tp', 'tr', 'travel', 'tt', 'tv', 'tw', 'tz', 'ua', - 'ug', 'uk', 'um', 'us', 'uy', 'uz', 'va', 'vc', 've', 'vg', 'vi', 'vn', 'vu', 'wf', 'ws', - 'ye', 'yt', 'yu', 'za', 'zm', 'zw' + 'abogado', + 'ac', + 'academy', + 'accountants', + 'active', + 'actor', + 'ad', + 'ae', + 'aero', + 'af', + 'ag', + 'agency', + 'ai', + 'airforce', + 'al', + 'allfinanz', + 'alsace', + 'am', + 'an', + 'android', + 'ao', + 'aq', + 'ar', + 'archi', + 'army', + 'arpa', + 'as', + 'asia', + 'associates', + 'at', + 'attorney', + 'au', + 'auction', + 'audio', + 'autos', + 'aw', + 'ax', + 'axa', + 'az', + 'ba', + 'band', + 'bar', + 'bargains', + 'bayern', + 'bb', + 'bd', + 'be', + 'beer', + 'berlin', + 'best', + 'bf', + 'bg', + 'bh', + 'bi', + 'bid', + 'bike', + 'bio', + 'biz', + 'bj', + 'black', + 'blackfriday', + 'bloomberg', + 'blue', + 'bm', + 'bmw', + 'bn', + 'bnpparibas', + 'bo', + 'boo', + 'boutique', + 'br', + 'brussels', + 'bs', + 'bt', + 'budapest', + 'build', + 'builders', + 'business', + 'buzz', + 'bv', + 'bw', + 'by', + 'bz', + 'bzh', + 'ca', + 'cab', + 'cal', + 'camera', + 'camp', + 'cancerresearch', + 'capetown', + 'capital', + 'caravan', + 'cards', + 'care', + 'career', + 'careers', + 'casa', + 'cash', + 'cat', + 'catering', + 'cc', + 'cd', + 'center', + 'ceo', + 'cern', + 'cf', + 'cg', + 'ch', + 'channel', + 'cheap', + 'christmas', + 'chrome', + 'church', + 'ci', + 'citic', + 'city', + 'ck', + 'cl', + 'claims', + 'cleaning', + 'click', + 'clinic', + 'clothing', + 'club', + 'cm', + 'cn', + 'co', + 'coach', + 'codes', + 'coffee', + 'college', + 'cologne', + 'com', + 'community', + 'company', + 'computer', + 'condos', + 'construction', + 'consulting', + 'contractors', + 'cooking', + 'cool', + 'coop', + 'country', + 'cr', + 'credit', + 'creditcard', + 'cricket', + 'crs', + 'cruises', + 'cu', + 'cuisinella', + 'cv', + 'cw', + 'cx', + 'cy', + 'cymru', + 'cz', + 'dad', + 'dance', + 'dating', + 'day', + 'de', + 'deals', + 'degree', + 'delivery', + 'democrat', + 'dental', + 'dentist', + 'desi', + 'diamonds', + 'diet', + 'digital', + 'direct', + 'directory', + 'discount', + 'dj', + 'dk', + 'dm', + 'dnp', + 'do', + 'domains', + 'durban', + 'dvag', + 'dz', + 'eat', + 'ec', + 'edu', + 'education', + 'ee', + 'eg', + 'email', + 'emerck', + 'energy', + 'engineer', + 'engineering', + 'enterprises', + 'equipment', + 'er', + 'es', + 'esq', + 'estate', + 'et', + 'eu', + 'eus', + 'events', + 'everbank', + 'exchange', + 'expert', + 'exposed', + 'fail', + 'farm', + 'feedback', + 'fi', + 'finance', + 'financial', + 'firmdale', + 'fish', + 'fishing', + 'fitness', + 'fj', + 'fk', + 'flights', + 'florist', + 'flsmidth', + 'fly', + 'fm', + 'fo', + 'foo', + 'forsale', + 'foundation', + 'fr', + 'frl', + 'frogans', + 'fund', + 'furniture', + 'futbol', + 'ga', + 'gal', + 'gallery', + 'gb', + 'gbiz', + 'gd', + 'ge', + 'gent', + 'gf', + 'gg', + 'gh', + 'gi', + 'gift', + 'gifts', + 'gives', + 'gl', + 'glass', + 'gle', + 'global', + 'globo', + 'gm', + 'gmail', + 'gmo', + 'gmx', + 'gn', + 'google', + 'gop', + 'gov', + 'gp', + 'gq', + 'gr', + 'graphics', + 'gratis', + 'green', + 'gripe', + 'gs', + 'gt', + 'gu', + 'guide', + 'guitars', + 'guru', + 'gw', + 'gy', + 'hamburg', + 'haus', + 'healthcare', + 'help', + 'here', + 'hiphop', + 'hiv', + 'hk', + 'hm', + 'hn', + 'holdings', + 'holiday', + 'homes', + 'horse', + 'host', + 'hosting', + 'house', + 'how', + 'hr', + 'ht', + 'hu', + 'ibm', + 'id', + 'ie', + 'il', + 'im', + 'immo', + 'immobilien', + 'in', + 'industries', + 'info', + 'ing', + 'ink', + 'institute', + 'insure', + 'int', + 'international', + 'investments', + 'io', + 'iq', + 'ir', + 'is', + 'it', + 'je', + 'jetzt', + 'jm', + 'jo', + 'jobs', + 'joburg', + 'jp', + 'juegos', + 'kaufen', + 'ke', + 'kg', + 'kh', + 'ki', + 'kim', + 'kitchen', + 'kiwi', + 'km', + 'kn', + 'koeln', + 'kp', + 'kr', + 'krd', + 'kred', + 'kw', + 'ky', + 'kz', + 'la', + 'lacaixa', + 'land', + 'lawyer', + 'lb', + 'lc', + 'lds', + 'lease', + 'legal', + 'lgbt', + 'li', + 'life', + 'lighting', + 'limited', + 'limo', + 'link', + 'lk', + 'loans', + 'london', + 'lotto', + 'lr', + 'ls', + 'lt', + 'ltda', + 'lu', + 'luxe', + 'luxury', + 'lv', + 'ly', + 'ma', + 'madrid', + 'maison', + 'management', + 'mango', + 'market', + 'marketing', + 'mc', + 'md', + 'me', + 'media', + 'meet', + 'melbourne', + 'meme', + 'memorial', + 'menu', + 'mg', + 'mh', + 'miami', + 'mil', + 'mini', + 'mk', + 'ml', + 'mm', + 'mn', + 'mo', + 'mobi', + 'moda', + 'moe', + 'monash', + 'money', + 'mormon', + 'mortgage', + 'moscow', + 'motorcycles', + 'mov', + 'mp', + 'mq', + 'mr', + 'ms', + 'mt', + 'mu', + 'museum', + 'mv', + 'mw', + 'mx', + 'my', + 'mz', + 'na', + 'nagoya', + 'name', + 'navy', + 'nc', + 'ne', + 'net', + 'network', + 'neustar', + 'new', + 'nexus', + 'nf', + 'ng', + 'ngo', + 'nhk', + 'ni', + 'ninja', + 'nl', + 'no', + 'np', + 'nr', + 'nra', + 'nrw', + 'nu', + 'nyc', + 'nz', + 'okinawa', + 'om', + 'ong', + 'onl', + 'ooo', + 'org', + 'organic', + 'otsuka', + 'ovh', + 'pa', + 'paris', + 'partners', + 'parts', + 'party', + 'pe', + 'pf', + 'pg', + 'ph', + 'pharmacy', + 'photo', + 'photography', + 'photos', + 'physio', + 'pics', + 'pictures', + 'pink', + 'pizza', + 'pk', + 'pl', + 'place', + 'plumbing', + 'pm', + 'pn', + 'pohl', + 'poker', + 'post', + 'pr', + 'praxi', + 'press', + 'pro', + 'prod', + 'productions', + 'prof', + 'properties', + 'property', + 'ps', + 'pt', + 'pub', + 'pw', + 'py', + 'qa', + 'qpon', + 'quebec', + 're', + 'realtor', + 'recipes', + 'red', + 'rehab', + 'reise', + 'reisen', + 'reit', + 'ren', + 'rentals', + 'repair', + 'report', + 'republican', + 'rest', + 'restaurant', + 'reviews', + 'rich', + 'rio', + 'rip', + 'ro', + 'rocks', + 'rodeo', + 'rs', + 'rsvp', + 'ru', + 'ruhr', + 'rw', + 'ryukyu', + 'sa', + 'saarland', + 'sarl', + 'sb', + 'sc', + 'sca', + 'scb', + 'schmidt', + 'schule', + 'science', + 'scot', + 'sd', + 'se', + 'services', + 'sexy', + 'sg', + 'sh', + 'shiksha', + 'shoes', + 'si', + 'singles', + 'sj', + 'sk', + 'sl', + 'sm', + 'sn', + 'so', + 'social', + 'software', + 'sohu', + 'solar', + 'solutions', + 'soy', + 'space', + 'spiegel', + 'sr', + 'st', + 'su', + 'supplies', + 'supply', + 'support', + 'surf', + 'surgery', + 'suzuki', + 'sv', + 'sx', + 'sy', + 'sydney', + 'systems', + 'sz', + 'taipei', + 'tatar', + 'tattoo', + 'tax', + 'tc', + 'td', + 'technology', + 'tel', + 'tf', + 'tg', + 'th', + 'tienda', + 'tips', + 'tirol', + 'tj', + 'tk', + 'tl', + 'tm', + 'tn', + 'to', + 'today', + 'tokyo', + 'tools', + 'top', + 'town', + 'toys', + 'tp', + 'tr', + 'trade', + 'training', + 'travel', + 'tt', + 'tui', + 'tv', + 'tw', + 'tz', + 'ua', + 'ug', + 'uk', + 'university', + 'uno', + 'uol', + 'us', + 'uy', + 'uz', + 'va', + 'vacations', + 'vc', + 've', + 'vegas', + 'ventures', + 'versicherung', + 'vet', + 'vg', + 'vi', + 'viajes', + 'villas', + 'vision', + 'vlaanderen', + 'vn', + 'vodka', + 'vote', + 'voting', + 'voto', + 'voyage', + 'vu', + 'wales', + 'wang', + 'watch', + 'webcam', + 'website', + 'wed', + 'wedding', + 'wf', + 'whoswho', + 'wien', + 'wiki', + 'williamhill', + 'wme', + 'work', + 'works', + 'world', + 'ws', + 'wtc', + 'wtf', + 'xn--1qqw23a', + 'xn--3bst00m', + 'xn--3ds443g', + 'xn--3e0b707e', + 'xn--45brj9c', + 'xn--45q11c', + 'xn--4gbrim', + 'xn--55qw42g', + 'xn--55qx5d', + 'xn--6frz82g', + 'xn--6qq986b3xl', + 'xn--80adxhks', + 'xn--80ao21a', + 'xn--80asehdb', + 'xn--80aswg', + 'xn--90a3ac', + 'xn--c1avg', + 'xn--cg4bki', + 'xn--clchc0ea0b2g2a9gcd', + 'xn--czr694b', + 'xn--czru2d', + 'xn--d1acj3b', + 'xn--d1alf', + 'xn--fiq228c5hs', + 'xn--fiq64b', + 'xn--fiqs8s', + 'xn--fiqz9s', + 'xn--flw351e', + 'xn--fpcrj9c3d', + 'xn--fzc2c9e2c', + 'xn--gecrj9c', + 'xn--h2brj9c', + 'xn--i1b6b1a6a2e', + 'xn--io0a7i', + 'xn--j1amh', + 'xn--j6w193g', + 'xn--kprw13d', + 'xn--kpry57d', + 'xn--kput3i', + 'xn--l1acc', + 'xn--lgbbat1ad8j', + 'xn--mgb9awbf', + 'xn--mgba3a4f16a', + 'xn--mgbaam7a8h', + 'xn--mgbab2bd', + 'xn--mgbayh7gpa', + 'xn--mgbbh1a71e', + 'xn--mgbc0a9azcg', + 'xn--mgberp4a5d4ar', + 'xn--mgbx4cd0ab', + 'xn--ngbc5azd', + 'xn--node', + 'xn--nqv7f', + 'xn--nqv7fs00ema', + 'xn--o3cw4h', + 'xn--ogbpf8fl', + 'xn--p1acf', + 'xn--p1ai', + 'xn--pgbs0dh', + 'xn--q9jyb4c', + 'xn--qcka1pmc', + 'xn--rhqv96g', + 'xn--s9brj9c', + 'xn--ses554g', + 'xn--unup4y', + 'xn--vermgensberater-ctb', + 'xn--vermgensberatung-pwb', + 'xn--vhquv', + 'xn--wgbh1c', + 'xn--wgbl6a', + 'xn--xhq521b', + 'xn--xkc2al3hye2a', + 'xn--xkc2dl3a5ee0h', + 'xn--yfro4i67o', + 'xn--ygbi2ammx', + 'xn--zfr164b', + 'xxx', + 'xyz', + 'yachts', + 'yandex', + 'ye', + 'yoga', + 'yokohama', + 'youtube', + 'yt', + 'za', + 'zip', + 'zm', + 'zone', + 'zw', + '测试', + 'परीक्षा', + '佛山', + '集团', + '在线', + '한국', + 'ভারত', + '八卦', + 'موقع', + 'বাংলা', + '公益', + '公司', + '移动', + '我爱你', + 'москва', + 'испытание', + 'қаз', + 'онлайн', + 'сайт', + 'срб', + 'бел', + '테스트', + 'орг', + '삼성', + 'சிங்கப்பூர்', + '商标', + '商城', + 'дети', + 'мкд', + 'טעסט', + '中文网', + '中信', + '中国', + '中國', + '谷歌', + 'భారత్', + 'ලංකා', + '測試', + 'ભારત', + 'भारत', + 'آزمایشی', + 'பரிட்சை', + 'संगठन', + '网络', + 'укр', + '香港', + 'δοκιμή', + 'إختبار', + '台湾', + '台灣', + '手机', + 'мон', + 'الجزائر', + 'عمان', + 'ایران', + 'امارات', + 'بازار', + 'پاکستان', + 'الاردن', + 'بھارت', + 'المغرب', + 'السعودية', + 'سودان', + 'عراق', + 'مليسيا', + 'شبكة', + 'გე', + '机构', + '组织机构', + 'ไทย', + 'سورية', + 'рус', + 'рф', + 'تونس', + 'みんな', + 'グーグル', + '世界', + 'ਭਾਰਤ', + '网址', + '游戏', + 'vermögensberater', + 'vermögensberatung', + '企业', + 'مصر', + 'قطر', + '广东', + 'இலங்கை', + 'இந்தியா', + 'հայ', + '新加坡', + 'فلسطين', + 'テスト', + '政务', ); /** @@ -144,6 +986,7 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract * (.BIZ) International http://www.iana.org/domains/idn-tables/ * (.BR) Brazil http://registro.br/faq/faq6.html * (.BV) Bouvett Island http://www.norid.no/domeneregistrering/idn/idn_nyetegn.en.html + * (.CA) Canada http://www.iana.org/domains/idn-tables/tables/ca_fr_1.0.html * (.CAT) Catalan http://www.iana.org/domains/idn-tables/tables/cat_ca_1.0.html * (.CH) Switzerland https://nic.switch.ch/reg/ocView.action?res=EF6GW2JBPVTG67DLNIQXU234MN6SC33JNQQGI7L6#anhang1 * (.CL) Chile http://www.iana.org/domains/idn-tables/tables/cl_latn_1.0.html @@ -172,6 +1015,7 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract * (.PR) Puerto Rico http://www.nic.pr/idn_rules.asp * (.PT) Portugal https://online.dns.pt/dns_2008/do?com=DS;8216320233;111;+PAGE(4000058)+K-CAT-CODIGO(C.125)+RCNT(100); * (.RU) Russia http://www.iana.org/domains/idn-tables/tables/ru_ru-ru_1.0.html + * (.RS) Serbia http://www.iana.org/domains/idn-tables/tables/rs_sr-rs_1.0.pdf * (.SA) Saudi Arabia http://www.iana.org/domains/idn-tables/tables/sa_ar_1.0.html * (.SE) Sweden http://www.iis.se/english/IDN_campaignsite.shtml?lang=en * (.SH) Saint Helena http://www.nic.sh/SH-IDN-Policy.pdf @@ -179,6 +1023,7 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract * (.TH) Thailand http://www.iana.org/domains/idn-tables/tables/th_th-th_1.0.html * (.TM) Turkmenistan http://www.nic.tm/TM-IDN-Policy.pdf * (.TR) Turkey https://www.nic.tr/index.php + * (.UA) Ukraine http://www.iana.org/domains/idn-tables/tables/ua_cyrl_1.2.html * (.VE) Venice http://www.iana.org/domains/idn-tables/tables/ve_es_1.0.html * (.VN) Vietnam http://www.vnnic.vn/english/5-6-300-2-2-04-20071115.htm#1.%20Introduction * @@ -192,24 +1037,27 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract 'BIZ' => 'Hostname/Biz.php', 'BR' => array(1 => '/^[\x{002d}0-9a-zà-ãçéíó-õúü]{1,63}$/iu'), 'BV' => array(1 => '/^[\x{002d}0-9a-zàáä-éêñ-ôöøüčđńŋšŧž]{1,63}$/iu'), + 'CA' => array(1 => '/^[\x{002d}0-9a-zàâæçéèêëîïôœùûüÿ\x{00E0}\x{00E2}\x{00E7}\x{00E8}\x{00E9}\x{00EA}\x{00EB}\x{00EE}\x{00EF}\x{00F4}\x{00F9}\x{00FB}\x{00FC}\x{00E6}\x{0153}\x{00FF}]{1,63}$/iu'), 'CAT' => array(1 => '/^[\x{002d}0-9a-z·àç-éíïòóúü]{1,63}$/iu'), 'CH' => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿœ]{1,63}$/iu'), 'CL' => array(1 => '/^[\x{002d}0-9a-záéíñóúü]{1,63}$/iu'), 'CN' => 'Hostname/Cn.php', - 'COM' => 'Zend/Validate/Hostname/Com.php', - 'DE' => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿăąāćĉčċďđĕěėęēğĝġģĥħĭĩįīıĵķĺľļłńňņŋŏőōœĸŕřŗśŝšşťţŧŭůűũųūŵŷźžż]{1,63}$/iu'), - 'DK' => array(1 => '/^[\x{002d}0-9a-zäéöü]{1,63}$/iu'), + 'COM' => 'Hostname/Com.php', + 'DE' => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿăąāćĉčċďđĕěėęēğĝġģĥħĭĩįīıĵķĺľļłńňņŋŏőōœĸŕřŗśŝšşťßţŧŭůűũųūŵŷźžż]{1,63}$/iu'), + 'DK' => array(1 => '/^[\x{002d}0-9a-zäéöüæøå]{1,63}$/iu'), 'ES' => array(1 => '/^[\x{002d}0-9a-zàáçèéíïñòóúü·]{1,63}$/iu'), 'EU' => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿ]{1,63}$/iu', 2 => '/^[\x{002d}0-9a-zāăąćĉċčďđēĕėęěĝğġģĥħĩīĭįıĵķĺļľŀłńņňʼnŋōŏőœŕŗřśŝšťŧũūŭůűųŵŷźżž]{1,63}$/iu', 3 => '/^[\x{002d}0-9a-zșț]{1,63}$/iu', 4 => '/^[\x{002d}0-9a-zΐάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύώ]{1,63}$/iu', 5 => '/^[\x{002d}0-9a-zабвгдежзийклмнопрстуфхцчшщъыьэюя]{1,63}$/iu', - 6 => '/^[\x{002d}0-9a-zἀ-ἇἐ-ἕἠ-ἧἰ-ἷὀ-ὅὐ-ὗὠ-ὧὰ-ώᾀ-ᾇᾐ-ᾗᾠ-ᾧᾰ-ᾴᾶᾷῂῃῄῆῇῐ-ΐῖῗῠ-ῧῲῳῴῶῷ]{1,63}$/iu'), + 6 => '/^[\x{002d}0-9a-zἀ-ἇἐ-ἕἠ-ἧἰ-ἷὀ-ὅὐ-ὗὠ-ὧὰ-ὼώᾀ-ᾇᾐ-ᾗᾠ-ᾧᾰ-ᾴᾶᾷῂῃῄῆῇῐ-ῒΐῖῗῠ-ῧῲῳῴῶῷ]{1,63}$/iu'), 'FI' => array(1 => '/^[\x{002d}0-9a-zäåö]{1,63}$/iu'), 'GR' => array(1 => '/^[\x{002d}0-9a-zΆΈΉΊΌΎ-ΡΣ-ώἀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙὛὝὟ-ώᾀ-ᾴᾶ-ᾼῂῃῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲῳῴῶ-ῼ]{1,63}$/iu'), - 'HK' => 'Zend/Validate/Hostname/Cn.php', + 'HK' => 'Hostname/Cn.php', 'HU' => array(1 => '/^[\x{002d}0-9a-záéíóöúüőű]{1,63}$/iu'), + 'IL' => array(1 => '/^[\x{002d}0-9\x{05D0}-\x{05EA}]{1,63}$/iu', + 2 => '/^[\x{002d}0-9a-z]{1,63}$/i'), 'INFO'=> array(1 => '/^[\x{002d}0-9a-zäåæéöøü]{1,63}$/iu', 2 => '/^[\x{002d}0-9a-záéíóöúüőű]{1,63}$/iu', 3 => '/^[\x{002d}0-9a-záæéíðóöúýþ]{1,63}$/iu', @@ -220,15 +1068,16 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract 8 => '/^[\x{002d}0-9a-záéíñóúü]{1,63}$/iu'), 'IO' => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿăąāćĉčċďđĕěėęēğĝġģĥħĭĩįīıĵķĺľļłńňņŋŏőōœĸŕřŗśŝšşťţŧŭůűũųūŵŷźžż]{1,63}$/iu'), 'IS' => array(1 => '/^[\x{002d}0-9a-záéýúíóþæöð]{1,63}$/iu'), - 'JP' => 'Zend/Validate/Hostname/Jp.php', + 'IT' => array(1 => '/^[\x{002d}0-9a-zàâäèéêëìîïòôöùûüæœçÿß-]{1,63}$/iu'), + 'JP' => 'Hostname/Jp.php', 'KR' => array(1 => '/^[\x{AC00}-\x{D7A3}]{1,17}$/iu'), 'LI' => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿœ]{1,63}$/iu'), 'LT' => array(1 => '/^[\x{002d}0-9ąčęėįšųūž]{1,63}$/iu'), 'MD' => array(1 => '/^[\x{002d}0-9ăâîşţ]{1,63}$/iu'), 'MUSEUM' => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿāăąćċčďđēėęěğġģħīįıķĺļľłńņňŋōőœŕŗřśşšţťŧūůűųŵŷźżžǎǐǒǔ\x{01E5}\x{01E7}\x{01E9}\x{01EF}ə\x{0292}ẁẃẅỳ]{1,63}$/iu'), - 'NET' => 'Zend/Validate/Hostname/Com.php', + 'NET' => 'Hostname/Com.php', 'NO' => array(1 => '/^[\x{002d}0-9a-zàáä-éêñ-ôöøüčđńŋšŧž]{1,63}$/iu'), - 'NU' => 'Zend/Validate/Hostname/Com.php', + 'NU' => 'Hostname/Com.php', 'ORG' => array(1 => '/^[\x{002d}0-9a-záéíñóúü]{1,63}$/iu', 2 => '/^[\x{002d}0-9a-zóąćęłńśźż]{1,63}$/iu', 3 => '/^[\x{002d}0-9a-záäåæéëíðóöøúüýþ]{1,63}$/iu', @@ -272,21 +1121,43 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract 33=> '/^[\x{002d}0-9א-ת]{1,63}$/iu'), 'PR' => array(1 => '/^[\x{002d}0-9a-záéíóúñäëïüöâêîôûàèùæçœãõ]{1,63}$/iu'), 'PT' => array(1 => '/^[\x{002d}0-9a-záàâãçéêíóôõú]{1,63}$/iu'), + 'RS' => array(1 => '/^[\x{002D}\x{0030}-\x{0039}\x{0061}-\x{007A}\x{0107}\x{010D}\x{0111}\x{0161}\x{017E}]{1,63}$/iu)'), 'RU' => array(1 => '/^[\x{002d}0-9а-яё]{1,63}$/iu'), 'SA' => array(1 => '/^[\x{002d}.0-9\x{0621}-\x{063A}\x{0641}-\x{064A}\x{0660}-\x{0669}]{1,63}$/iu'), 'SE' => array(1 => '/^[\x{002d}0-9a-zäåéöü]{1,63}$/iu'), 'SH' => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿăąāćĉčċďđĕěėęēğĝġģĥħĭĩįīıĵķĺľļłńňņŋŏőōœĸŕřŗśŝšşťţŧŭůűũųūŵŷźžż]{1,63}$/iu'), + 'SI' => array( + 1 => '/^[\x{002d}0-9a-zà-öø-ÿ]{1,63}$/iu', + 2 => '/^[\x{002d}0-9a-zāăąćĉċčďđēĕėęěĝğġģĥħĩīĭįıĵķĺļľŀłńņňʼnŋōŏőœŕŗřśŝšťŧũūŭůűųŵŷźżž]{1,63}$/iu', + 3 => '/^[\x{002d}0-9a-zșț]{1,63}$/iu'), 'SJ' => array(1 => '/^[\x{002d}0-9a-zàáä-éêñ-ôöøüčđńŋšŧž]{1,63}$/iu'), 'TH' => array(1 => '/^[\x{002d}0-9a-z\x{0E01}-\x{0E3A}\x{0E40}-\x{0E4D}\x{0E50}-\x{0E59}]{1,63}$/iu'), 'TM' => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿāăąćĉċčďđēėęěĝġģĥħīįĵķĺļľŀłńņňŋőœŕŗřśŝşšţťŧūŭůűųŵŷźżž]{1,63}$/iu'), - 'TW' => 'Zend/Validate/Hostname/Cn.php', + 'TW' => 'Hostname/Cn.php', 'TR' => array(1 => '/^[\x{002d}0-9a-zğıüşöç]{1,63}$/iu'), + 'UA' => array(1 => '/^[\x{002d}0-9a-zабвгдежзийклмнопрстуфхцчшщъыьэюяѐёђѓєѕіїјљњћќѝўџґӂʼ]{1,63}$/iu'), 'VE' => array(1 => '/^[\x{002d}0-9a-záéíóúüñ]{1,63}$/iu'), 'VN' => array(1 => '/^[ÀÁÂÃÈÉÊÌÍÒÓÔÕÙÚÝàáâãèéêìíòóôõùúýĂăĐđĨĩŨũƠơƯư\x{1EA0}-\x{1EF9}]{1,63}$/iu'), - 'ایران' => array(1 => '/^[\x{0621}-\x{0624}\x{0626}-\x{063A}\x{0641}\x{0642}\x{0644}-\x{0648}\x{067E}\x{0686}\x{0698}\x{06A9}\x{06AF}\x{06CC}\x{06F0}-\x{06F9}]{1,30}$/iu'), - '中国' => 'Zend/Validate/Hostname/Cn.php', - '公司' => 'Zend/Validate/Hostname/Cn.php', - '网络' => 'Zend/Validate/Hostname/Cn.php' + 'мон' => array(1 => '/^[\x{002d}0-9\x{0430}-\x{044F}]{1,63}$/iu'), + 'срб' => array(1 => '/^[\x{002d}0-9а-ик-шђјљњћџ]{1,63}$/iu'), + 'сайт' => array(1 => '/^[\x{002d}0-9а-яёіїѝйўґг]{1,63}$/iu'), + 'онлайн' => array(1 => '/^[\x{002d}0-9а-яёіїѝйўґг]{1,63}$/iu'), + '中国' => 'Hostname/Cn.php', + '中國' => 'Hostname/Cn.php', + 'ලංකා' => array(1 => '/^[\x{0d80}-\x{0dff}]{1,63}$/iu'), + '香港' => 'Hostname/Cn.php', + '台湾' => 'Hostname/Cn.php', + '台灣' => 'Hostname/Cn.php', + 'امارات' => array(1 => '/^[\x{0621}-\x{0624}\x{0626}-\x{063A}\x{0641}\x{0642}\x{0644}-\x{0648}\x{067E}\x{0686}\x{0698}\x{06A9}\x{06AF}\x{06CC}\x{06F0}-\x{06F9}]{1,30}$/iu'), + 'الاردن' => array(1 => '/^[\x{0621}-\x{0624}\x{0626}-\x{063A}\x{0641}\x{0642}\x{0644}-\x{0648}\x{067E}\x{0686}\x{0698}\x{06A9}\x{06AF}\x{06CC}\x{06F0}-\x{06F9}]{1,30}$/iu'), + 'السعودية' => array(1 => '/^[\x{0621}-\x{0624}\x{0626}-\x{063A}\x{0641}\x{0642}\x{0644}-\x{0648}\x{067E}\x{0686}\x{0698}\x{06A9}\x{06AF}\x{06CC}\x{06F0}-\x{06F9}]{1,30}$/iu'), + 'ไทย' => array(1 => '/^[\x{002d}0-9a-z\x{0E01}-\x{0E3A}\x{0E40}-\x{0E4D}\x{0E50}-\x{0E59}]{1,63}$/iu'), + 'рф' => array(1 => '/^[\x{002d}0-9а-яё]{1,63}$/iu'), + 'تونس' => array(1 => '/^[\x{0621}-\x{0624}\x{0626}-\x{063A}\x{0641}\x{0642}\x{0644}-\x{0648}\x{067E}\x{0686}\x{0698}\x{06A9}\x{06AF}\x{06CC}\x{06F0}-\x{06F9}]{1,30}$/iu'), + 'مصر' => array(1 => '/^[\x{0621}-\x{0624}\x{0626}-\x{063A}\x{0641}\x{0642}\x{0644}-\x{0648}\x{067E}\x{0686}\x{0698}\x{06A9}\x{06AF}\x{06CC}\x{06F0}-\x{06F9}]{1,30}$/iu'), + 'இலங்கை' => array(1 => '/^[\x{0b80}-\x{0bff}]{1,63}$/iu'), + 'فلسطين' => array(1 => '/^[\x{0621}-\x{0624}\x{0626}-\x{063A}\x{0641}\x{0642}\x{0644}-\x{0648}\x{067E}\x{0686}\x{0698}\x{06A9}\x{06AF}\x{06CC}\x{06F0}-\x{06F9}]{1,30}$/iu'), + 'شبكة' => array(1 => '/^[\x{0621}-\x{0624}\x{0626}-\x{063A}\x{0641}\x{0642}\x{0644}-\x{0648}\x{067E}\x{0686}\x{0698}\x{06A9}\x{06AF}\x{06CC}\x{06F0}-\x{06F9}]{1,30}$/iu'), ); protected $_idnLength = array( @@ -315,12 +1186,8 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract /** * Sets validator options * - * @param integer $allow OPTIONAL Set what types of hostname to allow (default ALLOW_DNS) - * @param boolean $validateIdn OPTIONAL Set whether IDN domains are validated (default true) - * @param boolean $validateTld OPTIONAL Set whether the TLD element of a hostname is validated (default true) - * @param Zend_Validate_Ip $ipValidator OPTIONAL - * @return void * @see http://www.iana.org/cctld/specifications-policies-cctlds-01apr02.htm Technical Specifications for ccTLDs + * @param array $options Validator options */ public function __construct($options = array()) { @@ -397,7 +1264,7 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract /** * @param Zend_Validate_Ip $ipValidator OPTIONAL - * @return void; + * @return Zend_Validate_Hostname */ public function setIpValidator(Zend_Validate_Ip $ipValidator = null) { @@ -447,6 +1314,7 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract * This only applies when DNS hostnames are validated * * @param boolean $allowed Set allowed to true to validate IDNs, and false to not validate them + * @return $this */ public function setValidateIdn ($allowed) { @@ -470,6 +1338,7 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract * This only applies when DNS hostnames are validated * * @param boolean $allowed Set allowed to true to validate TLDs, and false to not validate them + * @return $this */ public function setValidateTld ($allowed) { @@ -495,7 +1364,7 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract $this->_setValue($value); // Check input against IP address schema - if (preg_match('/^[0-9.a-e:.]*$/i', $value) && + if (preg_match('/^[0-9a-f:.]*$/i', $value) && $this->_options['ip']->setTranslator($this->getTranslator())->isValid($value)) { if (!($this->_options['allow'] & self::ALLOW_IP)) { $this->_error(self::IP_ADDRESS_NOT_ALLOWED); @@ -505,20 +1374,52 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract } } - // Check input against DNS hostname schema + // RFC3986 3.2.2 states: + // + // The rightmost domain label of a fully qualified domain name + // in DNS may be followed by a single "." and should be if it is + // necessary to distinguish between the complete domain name and + // some local domain. + // + // (see ZF-6363) + + // Local hostnames are allowed to be partitial (ending '.') + if ($this->_options['allow'] & self::ALLOW_LOCAL) { + if (substr($value, -1) === '.') { + $value = substr($value, 0, -1); + if (substr($value, -1) === '.') { + // Empty hostnames (ending '..') are not allowed + $this->_error(self::INVALID_LOCAL_NAME); + return false; + } + } + } + $domainParts = explode('.', $value); + + // Prevent partitial IP V4 adresses (ending '.') + if ((count($domainParts) == 4) && preg_match('/^[0-9.a-e:.]*$/i', $value) && + $this->_options['ip']->setTranslator($this->getTranslator())->isValid($value)) { + $this->_error(self::INVALID_LOCAL_NAME); + } + + // Check input against DNS hostname schema if ((count($domainParts) > 1) && (strlen($value) >= 4) && (strlen($value) <= 254)) { $status = false; - $origenc = iconv_get_encoding('internal_encoding'); - iconv_set_encoding('internal_encoding', 'UTF-8'); + $origenc = PHP_VERSION_ID < 50600 + ? iconv_get_encoding('internal_encoding') + : ini_get('default_charset'); + if (PHP_VERSION_ID < 50600) { + iconv_set_encoding('internal_encoding', 'UTF-8'); + } else { + ini_set('default_charset', 'UTF-8'); + } do { // First check TLD $matches = array(); - if (preg_match('/([^.]{2,10})$/i', end($domainParts), $matches) || - (end($domainParts) == 'ایران') || (end($domainParts) == '中国') || - (end($domainParts) == '公司') || (end($domainParts) == '网络')) { - + if (preg_match('/([^.]{2,63})$/iu', end($domainParts), $matches) + || (array_key_exists(end($domainParts), $this->_validIdns))) { reset($domainParts); // Hostname characters are: *(label dot)(label dot label); max 254 chars @@ -527,13 +1428,17 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract // ldh: alpha / digit / dash // Match TLD against known list - $this->_tld = strtolower($matches[1]); + $this->_tld = $matches[1]; if ($this->_options['tld']) { - if (!in_array($this->_tld, $this->_validTlds)) { + if (!in_array(strtolower($this->_tld), $this->_validTlds) + && !in_array($this->_tld, $this->_validTlds)) { $this->_error(self::UNKNOWN_TLD); $status = false; break; } + // We have already validated that the TLD is fine. We don't want it to go through the below + // checks as new UTF-8 TLDs will incorrectly fail if there is no IDN regex for it. + array_pop($domainParts); } /** @@ -553,6 +1458,12 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract // Check each hostname part $check = 0; foreach ($domainParts as $domainPart) { + // If some domain part is empty (i.e. zend..com), it's invalid + if (empty($domainPart) && $domainPart !== '0') { + $this->_error(self::INVALID_HOSTNAME); + return false; + } + // Decode Punycode domainnames to IDN if (strpos($domainPart, 'xn--') === 0) { $domainPart = $this->decodePunycode(substr($domainPart, 4)); @@ -573,7 +1484,7 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract // Check each domain part $checked = false; foreach($regexChars as $regexKey => $regexChar) { - $status = @preg_match($regexChar, $domainPart); + $status = preg_match($regexChar, $domainPart); if ($status > 0) { $length = 63; if (array_key_exists(strtoupper($this->_tld), $this->_idnLength) @@ -607,7 +1518,11 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract } } while (false); - iconv_set_encoding('internal_encoding', $origenc); + if (PHP_VERSION_ID < 50600) { + iconv_set_encoding('internal_encoding', $origenc); + } else { + ini_set('default_charset', $origenc); + } // If the input passes as an Internet domain name, and domain names are allowed, then the hostname // passes validation if ($status && ($this->_options['allow'] & self::ALLOW_DNS)) { @@ -617,8 +1532,17 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract $this->_error(self::INVALID_HOSTNAME); } + // Check for URI Syntax (RFC3986) + if ($this->_options['allow'] & self::ALLOW_URI) { + if (preg_match("/^([a-zA-Z0-9-._~!$&\'()*+,;=]|%[[:xdigit:]]{2}){1,254}$/i", $value)) { + return true; + } else { + $this->_error(self::INVALID_URI); + } + } + // Check input against local network name schema; last chance to pass validation - $regexLocal = '/^(([a-zA-Z0-9\x2d]{1,63}\x2e)*[a-zA-Z0-9\x2d]{1,63}){1,254}$/'; + $regexLocal = '/^(([a-zA-Z0-9\x2d]{1,63}\x2e)*[a-zA-Z0-9\x2d]{1,63}[\x2e]{0,1}){1,254}$/'; $status = @preg_match($regexLocal, $value); // If the input passes as a local network name, and local network names are allowed, then the @@ -650,22 +1574,19 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract */ protected function decodePunycode($encoded) { - $found = preg_match('/([^a-z0-9\x2d]{1,10})$/i', $encoded); - if (empty($encoded) || ($found > 0)) { - // no punycode encoded string, return as is + if (!preg_match('/^[a-z0-9-]+$/i', $encoded)) { + // no punycode encoded string $this->_error(self::CANNOT_DECODE_PUNYCODE); return false; } + $decoded = array(); $separator = strrpos($encoded, '-'); if ($separator > 0) { for ($x = 0; $x < $separator; ++$x) { // prepare decoding matrix $decoded[] = ord($encoded[$x]); } - } else { - $this->_error(self::CANNOT_DECODE_PUNYCODE); - return false; } $lengthd = count($decoded); diff --git a/lib/zend/Zend/Validate/Hostname/Biz.php b/lib/zend/Zend/Validate/Hostname/Biz.php index 090dffd6cfb..eb1bea22d9d 100644 --- a/lib/zend/Zend/Validate/Hostname/Biz.php +++ b/lib/zend/Zend/Validate/Hostname/Biz.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -24,7 +24,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ return array( diff --git a/lib/zend/Zend/Validate/Hostname/Cn.php b/lib/zend/Zend/Validate/Hostname/Cn.php index 33138b98df3..816e499a9b0 100644 --- a/lib/zend/Zend/Validate/Hostname/Cn.php +++ b/lib/zend/Zend/Validate/Hostname/Cn.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -24,7 +24,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ return array( diff --git a/lib/zend/Zend/Validate/Hostname/Com.php b/lib/zend/Zend/Validate/Hostname/Com.php index 931b80742a4..873dd522b7f 100644 --- a/lib/zend/Zend/Validate/Hostname/Com.php +++ b/lib/zend/Zend/Validate/Hostname/Com.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -24,7 +24,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ return array( @@ -184,8 +184,6 @@ return array( 68 => '/^[\x{A000}-\x{A48F}]{1,63}$/iu', 69 => '/^[\x{A490}-\x{A4CF}]{1,63}$/iu', 70 => '/^[\x{AC00}-\x{D7AF}]{1,63}$/iu', - 71 => '/^[\x{D800}-\x{DB7F}]{1,63}$/iu', - 72 => '/^[\x{DC00}-\x{DFFF}]{1,63}$/iu', 73 => '/^[\x{F900}-\x{FAFF}]{1,63}$/iu', 74 => '/^[\x{FB00}-\x{FB4F}]{1,63}$/iu', 75 => '/^[\x{FB50}-\x{FDFF}]{1,63}$/iu', @@ -195,4 +193,4 @@ return array( 79 => '/^[\x{20000}-\x{2A6DF}]{1,63}$/iu', 80 => '/^[\x{2F800}-\x{2FA1F}]{1,63}$/iu' -); \ No newline at end of file +); diff --git a/lib/zend/Zend/Validate/Hostname/Jp.php b/lib/zend/Zend/Validate/Hostname/Jp.php index be0946781bc..caca994b941 100644 --- a/lib/zend/Zend/Validate/Hostname/Jp.php +++ b/lib/zend/Zend/Validate/Hostname/Jp.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -24,7 +24,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ return array( diff --git a/lib/zend/Zend/Validate/Iban.php b/lib/zend/Zend/Validate/Iban.php index ba9450b821c..e19c1a8d0e5 100644 --- a/lib/zend/Zend/Validate/Iban.php +++ b/lib/zend/Zend/Validate/Iban.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -29,7 +29,7 @@ require_once 'Zend/Validate/Abstract.php'; * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Iban extends Zend_Validate_Abstract @@ -63,51 +63,76 @@ class Zend_Validate_Iban extends Zend_Validate_Abstract */ protected $_ibanregex = array( 'AD' => '/^AD[0-9]{2}[0-9]{8}[A-Z0-9]{12}$/', + 'AE' => '/^AE[0-9]{2}[0-9]{3}[0-9]{16}$/', + 'AL' => '/^AL[0-9]{2}[0-9]{8}[A-Z0-9]{16}$/', 'AT' => '/^AT[0-9]{2}[0-9]{5}[0-9]{11}$/', + 'AZ' => '/^AZ[0-9]{2}[0-9]{4}[A-Z0-9]{20}$/', 'BA' => '/^BA[0-9]{2}[0-9]{6}[0-9]{10}$/', 'BE' => '/^BE[0-9]{2}[0-9]{3}[0-9]{9}$/', 'BG' => '/^BG[0-9]{2}[A-Z]{4}[0-9]{4}[0-9]{2}[A-Z0-9]{8}$/', + 'BH' => '/^BH[0-9]{2}[A-Z]{4}[A-Z0-9]{14}$/', + 'BR' => '/^BR[0-9]{2}[0-9]{8}[0-9]{5}[0-9]{10}[A-Z]{1}[A-Z0-9]{1}$/', 'CH' => '/^CH[0-9]{2}[0-9]{5}[A-Z0-9]{12}$/', + 'CR' => '/^CR[0-9]{2}[0-9]{3}[0-9]{14}$/', 'CS' => '/^CS[0-9]{2}[0-9]{3}[0-9]{15}$/', 'CY' => '/^CY[0-9]{2}[0-9]{8}[A-Z0-9]{16}$/', 'CZ' => '/^CZ[0-9]{2}[0-9]{4}[0-9]{16}$/', 'DE' => '/^DE[0-9]{2}[0-9]{8}[0-9]{10}$/', 'DK' => '/^DK[0-9]{2}[0-9]{4}[0-9]{10}$/', + 'DO' => '/^DO[0-9]{2}[A-Z0-9]{4}[0-9]{20}$/', 'EE' => '/^EE[0-9]{2}[0-9]{4}[0-9]{12}$/', 'ES' => '/^ES[0-9]{2}[0-9]{8}[0-9]{12}$/', - 'FR' => '/^FR[0-9]{2}[0-9]{10}[A-Z0-9]{13}$/', + 'FR' => '/^FR[0-9]{2}[0-9]{10}[A-Z0-9]{11}[0-9]{2}$/', 'FI' => '/^FI[0-9]{2}[0-9]{6}[0-9]{8}$/', + 'FO' => '/^FO[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}$/', 'GB' => '/^GB[0-9]{2}[A-Z]{4}[0-9]{14}$/', + 'GE' => '/^GE[0-9]{2}[A-Z]{2}[0-9]{16}$/', 'GI' => '/^GI[0-9]{2}[A-Z]{4}[A-Z0-9]{15}$/', + 'GL' => '/^GL[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}$/', 'GR' => '/^GR[0-9]{2}[0-9]{7}[A-Z0-9]{16}$/', + 'GT' => '/^GT[0-9]{2}[A-Z0-9]{4}[A-Z0-9]{20}$/', 'HR' => '/^HR[0-9]{2}[0-9]{7}[0-9]{10}$/', 'HU' => '/^HU[0-9]{2}[0-9]{7}[0-9]{1}[0-9]{15}[0-9]{1}$/', 'IE' => '/^IE[0-9]{2}[A-Z0-9]{4}[0-9]{6}[0-9]{8}$/', + 'IL' => '/^IL[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{13}$/', 'IS' => '/^IS[0-9]{2}[0-9]{4}[0-9]{18}$/', 'IT' => '/^IT[0-9]{2}[A-Z]{1}[0-9]{10}[A-Z0-9]{12}$/', + 'KW' => '/^KW[0-9]{2}[A-Z]{4}[0-9]{3}[0-9]{22}$/', + 'KZ' => '/^KZ[A-Z]{2}[0-9]{2}[0-9]{3}[A-Z0-9]{13}$/', + 'LB' => '/^LB[0-9]{2}[0-9]{4}[A-Z0-9]{20}$/', 'LI' => '/^LI[0-9]{2}[0-9]{5}[A-Z0-9]{12}$/', 'LU' => '/^LU[0-9]{2}[0-9]{3}[A-Z0-9]{13}$/', 'LT' => '/^LT[0-9]{2}[0-9]{5}[0-9]{11}$/', 'LV' => '/^LV[0-9]{2}[A-Z]{4}[A-Z0-9]{13}$/', + 'MC' => '/^MC[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}$/', + 'MD' => '/^MD[0-9]{2}[A-Z0-9]{20}$/', + 'ME' => '/^ME[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}$/', 'MK' => '/^MK[0-9]{2}[A-Z]{3}[A-Z0-9]{10}[0-9]{2}$/', + 'MR' => '/^MR13[0-9]{5}[0-9]{5}[0-9]{11}[0-9]{2}$/', + 'MU' => '/^MU[0-9]{2}[A-Z]{4}[0-9]{2}[0-9]{2}[0-9]{12}[0-9]{3}[A-Z]{2}$/', 'MT' => '/^MT[0-9]{2}[A-Z]{4}[0-9]{5}[A-Z0-9]{18}$/', 'NL' => '/^NL[0-9]{2}[A-Z]{4}[0-9]{10}$/', 'NO' => '/^NO[0-9]{2}[0-9]{4}[0-9]{7}$/', + 'PK' => '/^PK[0-9]{2}[A-Z]{4}[0-9]{16}$/', 'PL' => '/^PL[0-9]{2}[0-9]{8}[0-9]{16}$/', + 'PS' => '/^PS[0-9]{2}[A-Z]{4}[0-9]{21}$/', 'PT' => '/^PT[0-9]{2}[0-9]{8}[0-9]{13}$/', 'RO' => '/^RO[0-9]{2}[A-Z]{4}[A-Z0-9]{16}$/', + 'RS' => '/^RS[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}$/', + 'SA' => '/^SA[0-9]{2}[0-9]{2}[A-Z0-9]{18}$/', 'SE' => '/^SE[0-9]{2}[0-9]{3}[0-9]{17}$/', 'SI' => '/^SI[0-9]{2}[0-9]{5}[0-9]{8}[0-9]{2}$/', 'SK' => '/^SK[0-9]{2}[0-9]{4}[0-9]{16}$/', + 'SM' => '/^SM[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}$/', 'TN' => '/^TN[0-9]{2}[0-9]{5}[0-9]{15}$/', - 'TR' => '/^TR[0-9]{2}[0-9]{5}[A-Z0-9]{17}$/' + 'TR' => '/^TR[0-9]{2}[0-9]{5}[A-Z0-9]{17}$/', + 'VG' => '/^VG[0-9]{2}[A-Z]{4}[0-9]{16}$/' ); /** * Sets validator options * - * @param string|Zend_Config|Zend_Locale $locale OPTIONAL - * @return void + * @param string|Zend_Config|Zend_Locale $locale OPTIONAL */ public function __construct($locale = null) { @@ -149,6 +174,8 @@ class Zend_Validate_Iban extends Zend_Validate_Abstract * Sets the locale option * * @param string|Zend_Locale $locale + * @throws Zend_Locale_Exception + * @throws Zend_Validate_Exception * @return Zend_Validate_Date provides a fluent interface */ public function setLocale($locale = null) diff --git a/lib/zend/Zend/Validate/Identical.php b/lib/zend/Zend/Validate/Identical.php index b78cb2b0c9e..97f3b8cce72 100644 --- a/lib/zend/Zend/Validate/Identical.php +++ b/lib/zend/Zend/Validate/Identical.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -25,7 +25,7 @@ require_once 'Zend/Validate/Abstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Identical extends Zend_Validate_Abstract @@ -64,8 +64,7 @@ class Zend_Validate_Identical extends Zend_Validate_Abstract /** * Sets validator options * - * @param mixed $token - * @return void + * @param mixed $token */ public function __construct($token = null) { @@ -102,7 +101,7 @@ class Zend_Validate_Identical extends Zend_Validate_Abstract */ public function setToken($token) { - $this->_tokenString = (string) $token; + $this->_tokenString = $token; $this->_token = $token; return $this; } @@ -121,6 +120,7 @@ class Zend_Validate_Identical extends Zend_Validate_Abstract * Sets the strict parameter * * @param Zend_Validate_Identical + * @return $this */ public function setStrict($strict) { @@ -140,7 +140,7 @@ class Zend_Validate_Identical extends Zend_Validate_Abstract */ public function isValid($value, $context = null) { - $this->_setValue((string) $value); + $this->_setValue($value); if (($context !== null) && isset($context) && array_key_exists($this->getToken(), $context)) { $token = $context[$this->getToken()]; diff --git a/lib/zend/Zend/Validate/InArray.php b/lib/zend/Zend/Validate/InArray.php index 9b4ae7f34c7..3f3ec243a24 100644 --- a/lib/zend/Zend/Validate/InArray.php +++ b/lib/zend/Zend/Validate/InArray.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Abstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_InArray extends Zend_Validate_Abstract @@ -65,8 +65,8 @@ class Zend_Validate_InArray extends Zend_Validate_Abstract /** * Sets validator options * - * @param array|Zend_Config $haystack - * @return void + * @param array|Zend_Config $options Validator options + * @throws Zend_Validate_Exception */ public function __construct($options) { diff --git a/lib/zend/Zend/Validate/Int.php b/lib/zend/Zend/Validate/Int.php index 828e7232409..1bcf31dba0b 100644 --- a/lib/zend/Zend/Validate/Int.php +++ b/lib/zend/Zend/Validate/Int.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -32,7 +32,7 @@ require_once 'Zend/Locale/Format.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Int extends Zend_Validate_Abstract @@ -44,7 +44,7 @@ class Zend_Validate_Int extends Zend_Validate_Abstract * @var array */ protected $_messageTemplates = array( - self::INVALID => "Invalid type given, value should be string or integer", + self::INVALID => "Invalid type given. String or integer expected", self::NOT_INT => "'%value%' does not appear to be an integer", ); @@ -93,6 +93,7 @@ class Zend_Validate_Int extends Zend_Validate_Abstract * Sets the locale to use * * @param string|Zend_Locale $locale + * @return $this */ public function setLocale($locale = null) { diff --git a/lib/zend/Zend/Validate/Interface.php b/lib/zend/Zend/Validate/Interface.php index 6f020e0a1b8..f1d0883c305 100644 --- a/lib/zend/Zend/Validate/Interface.php +++ b/lib/zend/Zend/Validate/Interface.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -22,7 +22,7 @@ /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ interface Zend_Validate_Interface @@ -36,7 +36,7 @@ interface Zend_Validate_Interface * * @param mixed $value * @return boolean - * @throws Zend_Valid_Exception If validation of $value is impossible + * @throws Zend_Validate_Exception If validation of $value is impossible */ public function isValid($value); diff --git a/lib/zend/Zend/Validate/Ip.php b/lib/zend/Zend/Validate/Ip.php index cebac55a088..ede95e92c02 100644 --- a/lib/zend/Zend/Validate/Ip.php +++ b/lib/zend/Zend/Validate/Ip.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Abstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Ip extends Zend_Validate_Abstract @@ -39,7 +39,7 @@ class Zend_Validate_Ip extends Zend_Validate_Abstract * @var array */ protected $_messageTemplates = array( - self::INVALID => "Invalid type given, value should be a string", + self::INVALID => "Invalid type given. String expected", self::NOT_IP_ADDRESS => "'%value%' does not appear to be a valid IP address", ); @@ -57,7 +57,6 @@ class Zend_Validate_Ip extends Zend_Validate_Abstract * Sets validator options * * @param array $options OPTIONAL Options to set, see the manual for all available options - * @return void */ public function __construct($options = array()) { @@ -91,6 +90,7 @@ class Zend_Validate_Ip extends Zend_Validate_Abstract * Sets the options for this validator * * @param array $options + * @throws Zend_Validate_Exception * @return Zend_Validate_Ip */ public function setOptions($options) @@ -141,6 +141,7 @@ class Zend_Validate_Ip extends Zend_Validate_Abstract * Validates an IPv4 address * * @param string $value + * @return bool */ protected function _validateIPv4($value) { $ip2long = ip2long($value); diff --git a/lib/zend/Zend/Validate/Isbn.php b/lib/zend/Zend/Validate/Isbn.php index c8345f27279..86c0c5c4960 100644 --- a/lib/zend/Zend/Validate/Isbn.php +++ b/lib/zend/Zend/Validate/Isbn.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Abstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Isbn extends Zend_Validate_Abstract @@ -44,8 +44,8 @@ class Zend_Validate_Isbn extends Zend_Validate_Abstract * @var array */ protected $_messageTemplates = array( - self::INVALID => "Invalid type given, value should be string or integer", - self::NO_ISBN => "'%value%' is no valid ISBN number", + self::INVALID => "Invalid type given. String or integer expected", + self::NO_ISBN => "'%value%' is not a valid ISBN number", ); /** @@ -67,7 +67,6 @@ class Zend_Validate_Isbn extends Zend_Validate_Abstract * * @param Zend_Config|array $options * @throws Zend_Validate_Exception When $options is not valid - * @return void */ public function __construct($options = array()) { diff --git a/lib/zend/Zend/Validate/Ldap/Dn.php b/lib/zend/Zend/Validate/Ldap/Dn.php new file mode 100644 index 00000000000..3033cec1ef0 --- /dev/null +++ b/lib/zend/Zend/Validate/Ldap/Dn.php @@ -0,0 +1,65 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_Validate + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @version $Id: Abstract.php 24807 2012-05-15 12:10:42Z adamlundrigan $ + */ + +/** + * @see Zend_Validate_Interface + */ +require_once 'Zend/Validate/Abstract.php'; + +/** + * @category Zend + * @package Zend_Validate + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_Validate_Ldap_Dn extends Zend_Validate_Abstract +{ + + const MALFORMED = 'malformed'; + + /** + * Validation failure message template definitions. + * + * @var array + */ + protected $_messageTemplates = array( + self::MALFORMED => 'DN is malformed', + ); + + /** + * Defined by Zend_Validate_Interface. + * + * Returns true if and only if $value is a valid DN. + * + * @param string $value The value to be validated. + * + * @return boolean + */ + public function isValid($value) + { + $valid = Zend_Ldap_Dn::checkDn($value); + if ($valid === false) { + $this->_error(self::MALFORMED); + return false; + } + return true; + } +} diff --git a/lib/zend/Zend/Validate/LessThan.php b/lib/zend/Zend/Validate/LessThan.php index ef3e195da17..41c28115bd8 100644 --- a/lib/zend/Zend/Validate/LessThan.php +++ b/lib/zend/Zend/Validate/LessThan.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Abstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_LessThan extends Zend_Validate_Abstract @@ -59,7 +59,7 @@ class Zend_Validate_LessThan extends Zend_Validate_Abstract * Sets validator options * * @param mixed|Zend_Config $max - * @return void + * @throws Zend_Validate_Exception */ public function __construct($max) { diff --git a/lib/zend/Zend/Validate/NotEmpty.php b/lib/zend/Zend/Validate/NotEmpty.php index 7cc53fef620..1bb3ceb82e6 100644 --- a/lib/zend/Zend/Validate/NotEmpty.php +++ b/lib/zend/Zend/Validate/NotEmpty.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,36 +27,42 @@ require_once 'Zend/Validate/Abstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_NotEmpty extends Zend_Validate_Abstract { - const BOOLEAN = 1; - const INTEGER = 2; - const FLOAT = 4; - const STRING = 8; - const ZERO = 16; - const EMPTY_ARRAY = 32; - const NULL = 64; - const PHP = 127; - const SPACE = 128; - const ALL = 255; + const BOOLEAN = 1; + const INTEGER = 2; + const FLOAT = 4; + const STRING = 8; + const ZERO = 16; + const EMPTY_ARRAY = 32; + const NULL = 64; + const PHP = 127; + const SPACE = 128; + const OBJECT = 256; + const OBJECT_STRING = 512; + const OBJECT_COUNT = 1024; + const ALL = 2047; const INVALID = 'notEmptyInvalid'; const IS_EMPTY = 'isEmpty'; protected $_constants = array( - self::BOOLEAN => 'boolean', - self::INTEGER => 'integer', - self::FLOAT => 'float', - self::STRING => 'string', - self::ZERO => 'zero', - self::EMPTY_ARRAY => 'array', - self::NULL => 'null', - self::PHP => 'php', - self::SPACE => 'space', - self::ALL => 'all' + self::BOOLEAN => 'boolean', + self::INTEGER => 'integer', + self::FLOAT => 'float', + self::STRING => 'string', + self::ZERO => 'zero', + self::EMPTY_ARRAY => 'array', + self::NULL => 'null', + self::PHP => 'php', + self::SPACE => 'space', + self::OBJECT => 'object', + self::OBJECT_STRING => 'objectstring', + self::OBJECT_COUNT => 'objectcount', + self::ALL => 'all', ); /** @@ -64,7 +70,7 @@ class Zend_Validate_NotEmpty extends Zend_Validate_Abstract */ protected $_messageTemplates = array( self::IS_EMPTY => "Value is required and can't be empty", - self::INVALID => "Invalid type given, value should be float, string, array, boolean or integer", + self::INVALID => "Invalid type given. String, integer, float, boolean or array expected", ); /** @@ -72,7 +78,7 @@ class Zend_Validate_NotEmpty extends Zend_Validate_Abstract * * @var integer */ - protected $_type = 237; + protected $_type = 493; /** * Constructor @@ -151,14 +157,50 @@ class Zend_Validate_NotEmpty extends Zend_Validate_Abstract */ public function isValid($value) { - if (!is_null($value) && !is_string($value) && !is_int($value) && !is_float($value) && - !is_bool($value) && !is_array($value)) { + if ($value !== null && !is_string($value) && !is_int($value) && !is_float($value) && + !is_bool($value) && !is_array($value) && !is_object($value)) { $this->_error(self::INVALID); return false; } $type = $this->getType(); $this->_setValue($value); + $object = false; + + // OBJECT_COUNT (countable object) + if ($type >= self::OBJECT_COUNT) { + $type -= self::OBJECT_COUNT; + $object = true; + + if (is_object($value) && ($value instanceof Countable) && (count($value) == 0)) { + $this->_error(self::IS_EMPTY); + return false; + } + } + + // OBJECT_STRING (object's toString) + if ($type >= self::OBJECT_STRING) { + $type -= self::OBJECT_STRING; + $object = true; + + if ((is_object($value) && (!method_exists($value, '__toString'))) || + (is_object($value) && (method_exists($value, '__toString')) && (((string) $value) == ""))) { + $this->_error(self::IS_EMPTY); + return false; + } + } + + // OBJECT (object) + if ($type >= self::OBJECT) { + $type -= self::OBJECT; + // fall trough, objects are always not empty + } else if ($object === false) { + // object not allowed but object given -> return false + if (is_object($value)) { + $this->_error(self::IS_EMPTY); + return false; + } + } // SPACE (' ') if ($type >= self::SPACE) { @@ -172,7 +214,7 @@ class Zend_Validate_NotEmpty extends Zend_Validate_Abstract // NULL (null) if ($type >= self::NULL) { $type -= self::NULL; - if (is_null($value)) { + if ($value === null) { $this->_error(self::IS_EMPTY); return false; } diff --git a/lib/zend/Zend/Validate/PostCode.php b/lib/zend/Zend/Validate/PostCode.php index b969d15d986..7f00d04db86 100644 --- a/lib/zend/Zend/Validate/PostCode.php +++ b/lib/zend/Zend/Validate/PostCode.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -32,7 +32,7 @@ require_once 'Zend/Locale/Format.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_PostCode extends Zend_Validate_Abstract @@ -44,7 +44,7 @@ class Zend_Validate_PostCode extends Zend_Validate_Abstract * @var array */ protected $_messageTemplates = array( - self::INVALID => "Invalid type given. The value should be a string or a integer", + self::INVALID => "Invalid type given. String or integer expected", self::NO_MATCH => "'%value%' does not appear to be a postal code", ); @@ -119,7 +119,7 @@ class Zend_Validate_PostCode extends Zend_Validate_Abstract * @param string|Zend_Locale $locale * @throws Zend_Validate_Exception On unrecognised region * @throws Zend_Validate_Exception On not detected format - * @return Zend_Validate_PostCode Provides fluid interface + * @return Zend_Validate_PostCode Provides a fluent interface */ public function setLocale($locale = null) { @@ -162,7 +162,7 @@ class Zend_Validate_PostCode extends Zend_Validate_Abstract * * @param string $format * @throws Zend_Validate_Exception On empty format - * @return Zend_Validate_PostCode Provides fluid interface + * @return Zend_Validate_PostCode Provides a fluent interface */ public function setFormat($format) { diff --git a/lib/zend/Zend/Validate/Regex.php b/lib/zend/Zend/Validate/Regex.php index 3c31eb9789e..5b4360a228b 100644 --- a/lib/zend/Zend/Validate/Regex.php +++ b/lib/zend/Zend/Validate/Regex.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Abstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Regex extends Zend_Validate_Abstract @@ -40,7 +40,7 @@ class Zend_Validate_Regex extends Zend_Validate_Abstract * @var array */ protected $_messageTemplates = array( - self::INVALID => "Invalid type given, value should be string, integer or float", + self::INVALID => "Invalid type given. String, integer or float expected", self::NOT_MATCH => "'%value%' does not match against pattern '%pattern%'", self::ERROROUS => "There was an internal error while using the pattern '%pattern%'", ); @@ -64,7 +64,6 @@ class Zend_Validate_Regex extends Zend_Validate_Abstract * * @param string|Zend_Config $pattern * @throws Zend_Validate_Exception On missing 'pattern' parameter - * @return void */ public function __construct($pattern) { diff --git a/lib/zend/Zend/Validate/Sitemap/Changefreq.php b/lib/zend/Zend/Validate/Sitemap/Changefreq.php index dc7cb3dbb65..b9f653f431a 100644 --- a/lib/zend/Zend/Validate/Sitemap/Changefreq.php +++ b/lib/zend/Zend/Validate/Sitemap/Changefreq.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Validate * @subpackage Sitemap - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -33,7 +33,7 @@ require_once 'Zend/Validate/Abstract.php'; * @category Zend * @package Zend_Validate * @subpackage Sitemap - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Sitemap_Changefreq extends Zend_Validate_Abstract @@ -51,8 +51,8 @@ class Zend_Validate_Sitemap_Changefreq extends Zend_Validate_Abstract * @var array */ protected $_messageTemplates = array( - self::NOT_VALID => "'%value%' is no valid sitemap changefreq", - self::INVALID => "Invalid type given, the value should be a string", + self::NOT_VALID => "'%value%' is not a valid sitemap changefreq", + self::INVALID => "Invalid type given. String expected", ); /** diff --git a/lib/zend/Zend/Validate/Sitemap/Lastmod.php b/lib/zend/Zend/Validate/Sitemap/Lastmod.php index cd3932ad9fc..1e81828f1c2 100644 --- a/lib/zend/Zend/Validate/Sitemap/Lastmod.php +++ b/lib/zend/Zend/Validate/Sitemap/Lastmod.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Validate * @subpackage Sitemap - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -33,7 +33,7 @@ require_once 'Zend/Validate/Abstract.php'; * @category Zend * @package Zend_Validate * @subpackage Sitemap - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Sitemap_Lastmod extends Zend_Validate_Abstract @@ -57,8 +57,8 @@ class Zend_Validate_Sitemap_Lastmod extends Zend_Validate_Abstract * @var array */ protected $_messageTemplates = array( - self::NOT_VALID => "'%value%' is no valid sitemap lastmod", - self::INVALID => "Invalid type given, the value should be a string", + self::NOT_VALID => "'%value%' is not a valid sitemap lastmod", + self::INVALID => "Invalid type given. String expected", ); /** diff --git a/lib/zend/Zend/Validate/Sitemap/Loc.php b/lib/zend/Zend/Validate/Sitemap/Loc.php index 4a8f62b1044..24c78ed8a9f 100644 --- a/lib/zend/Zend/Validate/Sitemap/Loc.php +++ b/lib/zend/Zend/Validate/Sitemap/Loc.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Validate * @subpackage Sitemap - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -38,7 +38,7 @@ require_once 'Zend/Uri.php'; * @category Zend * @package Zend_Validate * @subpackage Sitemap - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Sitemap_Loc extends Zend_Validate_Abstract @@ -56,8 +56,8 @@ class Zend_Validate_Sitemap_Loc extends Zend_Validate_Abstract * @var array */ protected $_messageTemplates = array( - self::NOT_VALID => "'%value%' is no valid sitemap location", - self::INVALID => "Invalid type given, the value should be a string", + self::NOT_VALID => "'%value%' is not a valid sitemap location", + self::INVALID => "Invalid type given. String expected", ); /** diff --git a/lib/zend/Zend/Validate/Sitemap/Priority.php b/lib/zend/Zend/Validate/Sitemap/Priority.php index 1cabb8b4d24..0f85f0997e1 100644 --- a/lib/zend/Zend/Validate/Sitemap/Priority.php +++ b/lib/zend/Zend/Validate/Sitemap/Priority.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Validate * @subpackage Sitemap - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -33,7 +33,7 @@ require_once 'Zend/Validate/Abstract.php'; * @category Zend * @package Zend_Validate * @subpackage Sitemap - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_Sitemap_Priority extends Zend_Validate_Abstract @@ -51,8 +51,8 @@ class Zend_Validate_Sitemap_Priority extends Zend_Validate_Abstract * @var array */ protected $_messageTemplates = array( - self::NOT_VALID => "'%value%' is no valid sitemap priority", - self::INVALID => "Invalid type given, the value should be a integer, a float or a numeric string", + self::NOT_VALID => "'%value%' is not a valid sitemap priority", + self::INVALID => "Invalid type given. Numeric string, integer or float expected", ); /** diff --git a/lib/zend/Zend/Validate/StringLength.php b/lib/zend/Zend/Validate/StringLength.php index 313b6ea8a84..b562c42fd09 100644 --- a/lib/zend/Zend/Validate/StringLength.php +++ b/lib/zend/Zend/Validate/StringLength.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -27,7 +27,7 @@ require_once 'Zend/Validate/Abstract.php'; /** * @category Zend * @package Zend_Validate - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Validate_StringLength extends Zend_Validate_Abstract @@ -40,7 +40,7 @@ class Zend_Validate_StringLength extends Zend_Validate_Abstract * @var array */ protected $_messageTemplates = array( - self::INVALID => "Invalid type given, value should be a string", + self::INVALID => "Invalid type given. String expected", self::TOO_SHORT => "'%value%' is less than %min% characters long", self::TOO_LONG => "'%value%' is more than %max% characters long", ); @@ -79,8 +79,7 @@ class Zend_Validate_StringLength extends Zend_Validate_Abstract /** * Sets validator options * - * @param integer|array|Zend_Config $options - * @return void + * @param integer|array|Zend_Config $options */ public function __construct($options = array()) { @@ -194,19 +193,30 @@ class Zend_Validate_StringLength extends Zend_Validate_Abstract * Sets a new encoding to use * * @param string $encoding + * @throws Zend_Validate_Exception * @return Zend_Validate_StringLength */ public function setEncoding($encoding = null) { if ($encoding !== null) { - $orig = iconv_get_encoding('internal_encoding'); - $result = iconv_set_encoding('internal_encoding', $encoding); + $orig = PHP_VERSION_ID < 50600 + ? iconv_get_encoding('internal_encoding') + : ini_get('default_charset'); + if (PHP_VERSION_ID < 50600) { + $result = iconv_set_encoding('internal_encoding', $encoding); + } else { + $result = ini_set('default_charset', $encoding); + } if (!$result) { require_once 'Zend/Validate/Exception.php'; throw new Zend_Validate_Exception('Given encoding not supported on this OS!'); } - iconv_set_encoding('internal_encoding', $orig); + if (PHP_VERSION_ID < 50600) { + iconv_set_encoding('internal_encoding', $orig); + } else { + ini_set('default_charset', $orig); + } } $this->_encoding = $encoding; diff --git a/lib/zend/Zend/Version.php b/lib/zend/Zend/Version.php index e1e8de226b4..a5f244f711e 100644 --- a/lib/zend/Zend/Version.php +++ b/lib/zend/Zend/Version.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Version - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -24,7 +24,7 @@ * * @category Zend * @package Zend_Version - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ final class Zend_Version @@ -32,14 +32,21 @@ final class Zend_Version /** * Zend Framework version identification - see compareVersion() */ - const VERSION = '1.10.6'; + const VERSION = '1.12.16'; + + /** + * The latest stable version Zend Framework available + * + * @var string + */ + protected static $_latestVersion; /** * Compare the specified Zend Framework version string $version * with the current Zend_Version::VERSION of Zend Framework. * * @param string $version A version string (e.g. "0.7.1"). - * @return boolean -1 if the $version is older, + * @return int -1 if the $version is older, * 0 if they are the same, * and +1 if $version is newer. * @@ -50,4 +57,25 @@ final class Zend_Version $version = preg_replace('/(\d)pr(\d?)/', '$1a$2', $version); return version_compare($version, strtolower(self::VERSION)); } + + /** + * Fetches the version of the latest stable release + * + * @link http://framework.zend.com/download/latest + * @return string + */ + public static function getLatest() + { + if (null === self::$_latestVersion) { + self::$_latestVersion = 'not available'; + + $handle = fopen('http://framework.zend.com/api/zf-version', 'r'); + if (false !== $handle) { + self::$_latestVersion = stream_get_contents($handle); + fclose($handle); + } + } + + return self::$_latestVersion; + } } diff --git a/lib/zend/Zend/View.php b/lib/zend/Zend/View.php new file mode 100644 index 00000000000..6b8f3e56508 --- /dev/null +++ b/lib/zend/Zend/View.php @@ -0,0 +1,160 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_View + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @version $Id$ + */ + + +/** + * Abstract master class for extension. + */ +require_once 'Zend/View/Abstract.php'; + + +/** + * Concrete class for handling view scripts. + * + * @category Zend + * @package Zend_View + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * + * Convenience methods for build in helpers (@see __call): + * + * @method string baseUrl($file = null) + * @method string currency($value = null, $currency = null) + * @method Zend_View_Helper_Cycle cycle(array $data = array(), $name = Zend_View_Helper_Cycle::DEFAULT_NAME) + * @method Zend_View_Helper_Doctype doctype($doctype = null) + * @method string fieldset($name, $content, $attribs = null) + * @method string form($name, $attribs = null, $content = false) + * @method string formButton($name, $value = null, $attribs = null) + * @method string formCheckbox($name, $value = null, $attribs = null, array $checkedOptions = null) + * @method string formErrors($errors, array $options = null) + * @method string formFile($name, $attribs = null) + * @method string formHidden($name, $value = null, array $attribs = null) + * @method string formImage($name, $value = null, $attribs = null) + * @method string formLabel($name, $value = null, array $attribs = null) + * @method string formMultiCheckbox($name, $value = null, $attribs = null, $options = null, $listsep = "<br />\n") + * @method string formNote($name, $value = null) + * @method string formPassword($name, $value = null, $attribs = null) + * @method string formRadio($name, $value = null, $attribs = null, $options = null, $listsep = "<br />\n") + * @method string formReset($name = '', $value = 'Reset', $attribs = null) + * @method string formSelect($name, $value = null, $attribs = null, $options = null, $listsep = "<br />\n") + * @method string formSubmit($name, $value = null, $attribs = null) + * @method string formText($name, $value = null, $attribs = null) + * @method string formTextarea($name, $value = null, $attribs = null) + * @method Zend_View_Helper_Gravatar gravatar($email = "", $options = array(), $attribs = array()) + * @method Zend_View_Helper_HeadLink headLink(array $attributes = null, $placement = Zend_View_Helper_Placeholder_Container_Abstract::APPEND) + * @method Zend_View_Helper_HeadMeta headMeta($content = null, $keyValue = null, $keyType = 'name', $modifiers = array(), $placement = Zend_View_Helper_Placeholder_Container_Abstract::APPEND) + * @method Zend_View_Helper_HeadScript headScript($mode = Zend_View_Helper_HeadScript::FILE, $spec = null, $placement = 'APPEND', array $attrs = array(), $type = 'text/javascript') + * @method Zend_View_Helper_HeadStyle headStyle($content = null, $placement = 'APPEND', $attributes = array()) + * @method Zend_View_Helper_HeadTitle headTitle($title = null, $setType = null) + * @method string htmlFlash($data, array $attribs = array(), array $params = array(), $content = null) + * @method string htmlList(array $items, $ordered = false, $attribs = false, $escape = true) + * @method string htmlObject($data, $type, array $attribs = array(), array $params = array(), $content = null) + * @method string htmlPage($data, array $attribs = array(), array $params = array(), $content = null) + * @method string htmlQuicktime($data, array $attribs = array(), array $params = array(), $content = null) + * @method Zend_View_Helper_InlineScript inlineScript($mode = Zend_View_Helper_HeadScript::FILE, $spec = null, $placement = 'APPEND', array $attrs = array(), $type = 'text/javascript') + * @method string|void json($data, $keepLayouts = false, $encodeData = true) + * @method Zend_View_Helper_Layout layout() + * @method Zend_View_Helper_Navigation navigation(Zend_Navigation_Container $container = null) + * @method string paginationControl(Zend_Paginator $paginator = null, $scrollingStyle = null, $partial = null, $params = null) + * @method string partial($name = null, $module = null, $model = null) + * @method string partialLoop($name = null, $module = null, $model = null) + * @method Zend_View_Helper_Placeholder_Container_Abstract placeholder($name) + * @method void renderToPlaceholder($script, $placeholder) + * @method string serverUrl($requestUri = null) + * @method string translate($messageid = null) + * @method string url(array $urlOptions = array(), $name = null, $reset = false, $encode = true) + * @method Zend_Http_UserAgent userAgent(Zend_Http_UserAgent $userAgent = null) + */ +class Zend_View extends Zend_View_Abstract +{ + /** + * Whether or not to use streams to mimic short tags + * @var bool + */ + private $_useViewStream = false; + + /** + * Whether or not to use stream wrapper if short_open_tag is false + * @var bool + */ + private $_useStreamWrapper = false; + + /** + * Constructor + * + * Register Zend_View_Stream stream wrapper if short tags are disabled. + * + * @param array $config + * @return void + */ + public function __construct($config = array()) + { + $this->_useViewStream = (bool) ini_get('short_open_tag') ? false : true; + if ($this->_useViewStream) { + if (!in_array('zend.view', stream_get_wrappers())) { + require_once 'Zend/View/Stream.php'; + stream_wrapper_register('zend.view', 'Zend_View_Stream'); + } + } + + if (array_key_exists('useStreamWrapper', $config)) { + $this->setUseStreamWrapper($config['useStreamWrapper']); + } + + parent::__construct($config); + } + + /** + * Set flag indicating if stream wrapper should be used if short_open_tag is off + * + * @param bool $flag + * @return Zend_View + */ + public function setUseStreamWrapper($flag) + { + $this->_useStreamWrapper = (bool) $flag; + return $this; + } + + /** + * Should the stream wrapper be used if short_open_tag is off? + * + * @return bool + */ + public function useStreamWrapper() + { + return $this->_useStreamWrapper; + } + + /** + * Includes the view script in a scope with only public $this variables. + * + * @param string The view script to execute. + */ + protected function _run() + { + if ($this->_useViewStream && $this->useStreamWrapper()) { + include 'zend.view://' . func_get_arg(0); + } else { + include func_get_arg(0); + } + } +} diff --git a/lib/zend/Zend/View/Abstract.php b/lib/zend/Zend/View/Abstract.php new file mode 100644 index 00000000000..ffcefee19b8 --- /dev/null +++ b/lib/zend/Zend/View/Abstract.php @@ -0,0 +1,1200 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_View + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @version $Id$ + */ + +/** @see Zend_Loader */ +require_once 'Zend/Loader.php'; + +/** @see Zend_Loader_PluginLoader */ +require_once 'Zend/Loader/PluginLoader.php'; + +/** @see Zend_View_Interface */ +require_once 'Zend/View/Interface.php'; + +/** + * Abstract class for Zend_View to help enforce private constructs. + * + * @category Zend + * @package Zend_View + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +abstract class Zend_View_Abstract implements Zend_View_Interface +{ + /** + * Path stack for script, helper, and filter directories. + * + * @var array + */ + private $_path = array( + 'script' => array(), + 'helper' => array(), + 'filter' => array(), + ); + + /** + * Script file name to execute + * + * @var string + */ + private $_file = null; + + /** + * Instances of helper objects. + * + * @var array + */ + private $_helper = array(); + + /** + * Map of helper => class pairs to help in determining helper class from + * name + * @var array + */ + private $_helperLoaded = array(); + + /** + * Map of helper => classfile pairs to aid in determining helper classfile + * @var array + */ + private $_helperLoadedDir = array(); + + /** + * Stack of Zend_View_Filter names to apply as filters. + * @var array + */ + private $_filter = array(); + + /** + * Stack of Zend_View_Filter objects that have been loaded + * @var array + */ + private $_filterClass = array(); + + /** + * Map of filter => class pairs to help in determining filter class from + * name + * @var array + */ + private $_filterLoaded = array(); + + /** + * Map of filter => classfile pairs to aid in determining filter classfile + * @var array + */ + private $_filterLoadedDir = array(); + + /** + * Callback for escaping. + * + * @var string + */ + private $_escape = 'htmlspecialchars'; + + /** + * Encoding to use in escaping mechanisms; defaults to utf-8 + * @var string + */ + private $_encoding = 'UTF-8'; + + /** + * Flag indicating whether or not LFI protection for rendering view scripts is enabled + * @var bool + */ + private $_lfiProtectionOn = true; + + /** + * Plugin loaders + * @var array + */ + private $_loaders = array(); + + /** + * Plugin types + * @var array + */ + private $_loaderTypes = array('filter', 'helper'); + + /** + * Strict variables flag; when on, undefined variables accessed in the view + * scripts will trigger notices + * @var boolean + */ + private $_strictVars = false; + + /** + * Constructor. + * + * @param array $config Configuration key-value pairs. + */ + public function __construct($config = array()) + { + // set inital paths and properties + $this->setScriptPath(null); + + // $this->setHelperPath(null); + $this->setFilterPath(null); + + // user-defined escaping callback + if (array_key_exists('escape', $config)) { + $this->setEscape($config['escape']); + } + + // encoding + if (array_key_exists('encoding', $config)) { + $this->setEncoding($config['encoding']); + } + + // base path + if (array_key_exists('basePath', $config)) { + $prefix = 'Zend_View'; + if (array_key_exists('basePathPrefix', $config)) { + $prefix = $config['basePathPrefix']; + } + $this->setBasePath($config['basePath'], $prefix); + } + + // user-defined view script path + if (array_key_exists('scriptPath', $config)) { + $this->addScriptPath($config['scriptPath']); + } + + // user-defined helper path + if (array_key_exists('helperPath', $config)) { + if (is_array($config['helperPath'])) { + foreach ($config['helperPath'] as $prefix => $path) { + $this->addHelperPath($path, $prefix); + } + } else { + $prefix = 'Zend_View_Helper'; + if (array_key_exists('helperPathPrefix', $config)) { + $prefix = $config['helperPathPrefix']; + } + $this->addHelperPath($config['helperPath'], $prefix); + } + } + + // user-defined filter path + if (array_key_exists('filterPath', $config)) { + if (is_array($config['filterPath'])) { + foreach ($config['filterPath'] as $prefix => $path) { + $this->addFilterPath($path, $prefix); + } + } else { + $prefix = 'Zend_View_Filter'; + if (array_key_exists('filterPathPrefix', $config)) { + $prefix = $config['filterPathPrefix']; + } + $this->addFilterPath($config['filterPath'], $prefix); + } + } + + // user-defined filters + if (array_key_exists('filter', $config)) { + $this->addFilter($config['filter']); + } + + // strict vars + if (array_key_exists('strictVars', $config)) { + $this->strictVars($config['strictVars']); + } + + // LFI protection flag + if (array_key_exists('lfiProtectionOn', $config)) { + $this->setLfiProtection($config['lfiProtectionOn']); + } + + if (array_key_exists('assign', $config) + && is_array($config['assign']) + ) { + foreach ($config['assign'] as $key => $value) { + $this->assign($key, $value); + } + } + + $this->init(); + } + + /** + * Return the template engine object + * + * Returns the object instance, as it is its own template engine + * + * @return Zend_View_Abstract + */ + public function getEngine() + { + return $this; + } + + /** + * Allow custom object initialization when extending Zend_View_Abstract or + * Zend_View + * + * Triggered by {@link __construct() the constructor} as its final action. + * + * @return void + */ + public function init() + { + } + + /** + * Prevent E_NOTICE for nonexistent values + * + * If {@link strictVars()} is on, raises a notice. + * + * @param string $key + * @return null + */ + public function __get($key) + { + if ($this->_strictVars) { + trigger_error('Key "' . $key . '" does not exist', E_USER_NOTICE); + } + + return null; + } + + /** + * Allows testing with empty() and isset() to work inside + * templates. + * + * @param string $key + * @return boolean + */ + public function __isset($key) + { + if ('_' != substr($key, 0, 1)) { + return isset($this->$key); + } + + return false; + } + + /** + * Directly assigns a variable to the view script. + * + * Checks first to ensure that the caller is not attempting to set a + * protected or private member (by checking for a prefixed underscore); if + * not, the public member is set; otherwise, an exception is raised. + * + * @param string $key The variable name. + * @param mixed $val The variable value. + * @return void + * @throws Zend_View_Exception if an attempt to set a private or protected + * member is detected + */ + public function __set($key, $val) + { + if ('_' != substr($key, 0, 1)) { + $this->$key = $val; + return; + } + + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception('Setting private or protected class members is not allowed'); + $e->setView($this); + throw $e; + } + + /** + * Allows unset() on object properties to work + * + * @param string $key + * @return void + */ + public function __unset($key) + { + if ('_' != substr($key, 0, 1) && isset($this->$key)) { + unset($this->$key); + } + } + + /** + * Accesses a helper object from within a script. + * + * If the helper class has a 'view' property, sets it with the current view + * object. + * + * @param string $name The helper name. + * @param array $args The parameters for the helper. + * @return string The result of the helper output. + */ + public function __call($name, $args) + { + // is the helper already loaded? + $helper = $this->getHelper($name); + + // call the helper method + return call_user_func_array( + array($helper, $name), + $args + ); + } + + /** + * Given a base path, sets the script, helper, and filter paths relative to it + * + * Assumes a directory structure of: + * <code> + * basePath/ + * scripts/ + * helpers/ + * filters/ + * </code> + * + * @param string $path + * @param string $prefix Prefix to use for helper and filter paths + * @return Zend_View_Abstract + */ + public function setBasePath($path, $classPrefix = 'Zend_View') + { + $path = rtrim($path, '/'); + $path = rtrim($path, '\\'); + $path .= DIRECTORY_SEPARATOR; + $classPrefix = rtrim($classPrefix, '_') . '_'; + $this->setScriptPath($path . 'scripts'); + $this->setHelperPath($path . 'helpers', $classPrefix . 'Helper'); + $this->setFilterPath($path . 'filters', $classPrefix . 'Filter'); + return $this; + } + + /** + * Given a base path, add script, helper, and filter paths relative to it + * + * Assumes a directory structure of: + * <code> + * basePath/ + * scripts/ + * helpers/ + * filters/ + * </code> + * + * @param string $path + * @param string $prefix Prefix to use for helper and filter paths + * @return Zend_View_Abstract + */ + public function addBasePath($path, $classPrefix = 'Zend_View') + { + $path = rtrim($path, '/'); + $path = rtrim($path, '\\'); + $path .= DIRECTORY_SEPARATOR; + $classPrefix = rtrim($classPrefix, '_') . '_'; + $this->addScriptPath($path . 'scripts'); + $this->addHelperPath($path . 'helpers', $classPrefix . 'Helper'); + $this->addFilterPath($path . 'filters', $classPrefix . 'Filter'); + return $this; + } + + /** + * Adds to the stack of view script paths in LIFO order. + * + * @param string|array The directory (-ies) to add. + * @return Zend_View_Abstract + */ + public function addScriptPath($path) + { + $this->_addPath('script', $path); + return $this; + } + + /** + * Resets the stack of view script paths. + * + * To clear all paths, use Zend_View::setScriptPath(null). + * + * @param string|array The directory (-ies) to set as the path. + * @return Zend_View_Abstract + */ + public function setScriptPath($path) + { + $this->_path['script'] = array(); + $this->_addPath('script', $path); + return $this; + } + + /** + * Return full path to a view script specified by $name + * + * @param string $name + * @return false|string False if script not found + * @throws Zend_View_Exception if no script directory set + */ + public function getScriptPath($name) + { + try { + $path = $this->_script($name); + return $path; + } catch (Zend_View_Exception $e) { + if (strstr($e->getMessage(), 'no view script directory set')) { + throw $e; + } + + return false; + } + } + + /** + * Returns an array of all currently set script paths + * + * @return array + */ + public function getScriptPaths() + { + return $this->_getPaths('script'); + } + + /** + * Set plugin loader for a particular plugin type + * + * @param Zend_Loader_PluginLoader $loader + * @param string $type + * @return Zend_View_Abstract + */ + public function setPluginLoader(Zend_Loader_PluginLoader $loader, $type) + { + $type = strtolower($type); + if (!in_array($type, $this->_loaderTypes)) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception(sprintf('Invalid plugin loader type "%s"', $type)); + $e->setView($this); + throw $e; + } + + $this->_loaders[$type] = $loader; + return $this; + } + + /** + * Retrieve plugin loader for a specific plugin type + * + * @param string $type + * @return Zend_Loader_PluginLoader + */ + public function getPluginLoader($type) + { + $type = strtolower($type); + if (!in_array($type, $this->_loaderTypes)) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception(sprintf('Invalid plugin loader type "%s"; cannot retrieve', $type)); + $e->setView($this); + throw $e; + } + + if (!array_key_exists($type, $this->_loaders)) { + $prefix = 'Zend_View_'; + $pathPrefix = 'Zend/View/'; + + $pType = ucfirst($type); + switch ($type) { + case 'filter': + case 'helper': + default: + $prefix .= $pType; + $pathPrefix .= $pType; + $loader = new Zend_Loader_PluginLoader(array( + $prefix => $pathPrefix + )); + $this->_loaders[$type] = $loader; + break; + } + } + return $this->_loaders[$type]; + } + + /** + * Adds to the stack of helper paths in LIFO order. + * + * @param string|array The directory (-ies) to add. + * @param string $classPrefix Class prefix to use with classes in this + * directory; defaults to Zend_View_Helper + * @return Zend_View_Abstract + */ + public function addHelperPath($path, $classPrefix = 'Zend_View_Helper_') + { + return $this->_addPluginPath('helper', $classPrefix, (array) $path); + } + + /** + * Resets the stack of helper paths. + * + * To clear all paths, use Zend_View::setHelperPath(null). + * + * @param string|array $path The directory (-ies) to set as the path. + * @param string $classPrefix The class prefix to apply to all elements in + * $path; defaults to Zend_View_Helper + * @return Zend_View_Abstract + */ + public function setHelperPath($path, $classPrefix = 'Zend_View_Helper_') + { + unset($this->_loaders['helper']); + return $this->addHelperPath($path, $classPrefix); + } + + /** + * Get full path to a helper class file specified by $name + * + * @param string $name + * @return string|false False on failure, path on success + */ + public function getHelperPath($name) + { + return $this->_getPluginPath('helper', $name); + } + + /** + * Returns an array of all currently set helper paths + * + * @return array + */ + public function getHelperPaths() + { + return $this->getPluginLoader('helper')->getPaths(); + } + + /** + * Registers a helper object, bypassing plugin loader + * + * @param Zend_View_Helper_Abstract|object $helper + * @param string $name + * @return Zend_View_Abstract + * @throws Zend_View_Exception + */ + public function registerHelper($helper, $name) + { + if (!is_object($helper)) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception('View helper must be an object'); + $e->setView($this); + throw $e; + } + + if (!$helper instanceof Zend_View_Interface) { + if (!method_exists($helper, $name)) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception( + 'View helper must implement Zend_View_Interface or have a method matching the name provided' + ); + $e->setView($this); + throw $e; + } + } + + if (method_exists($helper, 'setView')) { + $helper->setView($this); + } + + $name = ucfirst($name); + $this->_helper[$name] = $helper; + return $this; + } + + /** + * Get a helper by name + * + * @param string $name + * @return object + */ + public function getHelper($name) + { + return $this->_getPlugin('helper', $name); + } + + /** + * Get array of all active helpers + * + * Only returns those that have already been instantiated. + * + * @return array + */ + public function getHelpers() + { + return $this->_helper; + } + + /** + * Adds to the stack of filter paths in LIFO order. + * + * @param string|array The directory (-ies) to add. + * @param string $classPrefix Class prefix to use with classes in this + * directory; defaults to Zend_View_Filter + * @return Zend_View_Abstract + */ + public function addFilterPath($path, $classPrefix = 'Zend_View_Filter_') + { + return $this->_addPluginPath('filter', $classPrefix, (array) $path); + } + + /** + * Resets the stack of filter paths. + * + * To clear all paths, use Zend_View::setFilterPath(null). + * + * @param string|array The directory (-ies) to set as the path. + * @param string $classPrefix The class prefix to apply to all elements in + * $path; defaults to Zend_View_Filter + * @return Zend_View_Abstract + */ + public function setFilterPath($path, $classPrefix = 'Zend_View_Filter_') + { + unset($this->_loaders['filter']); + return $this->addFilterPath($path, $classPrefix); + } + + /** + * Get full path to a filter class file specified by $name + * + * @param string $name + * @return string|false False on failure, path on success + */ + public function getFilterPath($name) + { + return $this->_getPluginPath('filter', $name); + } + + /** + * Get a filter object by name + * + * @param string $name + * @return object + */ + public function getFilter($name) + { + return $this->_getPlugin('filter', $name); + } + + /** + * Return array of all currently active filters + * + * Only returns those that have already been instantiated. + * + * @return array + */ + public function getFilters() + { + return $this->_filter; + } + + /** + * Returns an array of all currently set filter paths + * + * @return array + */ + public function getFilterPaths() + { + return $this->getPluginLoader('filter')->getPaths(); + } + + /** + * Return associative array of path types => paths + * + * @return array + */ + public function getAllPaths() + { + $paths = $this->_path; + $paths['helper'] = $this->getHelperPaths(); + $paths['filter'] = $this->getFilterPaths(); + return $paths; + } + + /** + * Add one or more filters to the stack in FIFO order. + * + * @param string|array One or more filters to add. + * @return Zend_View_Abstract + */ + public function addFilter($name) + { + foreach ((array) $name as $val) { + $this->_filter[] = $val; + } + return $this; + } + + /** + * Resets the filter stack. + * + * To clear all filters, use Zend_View::setFilter(null). + * + * @param string|array One or more filters to set. + * @return Zend_View_Abstract + */ + public function setFilter($name) + { + $this->_filter = array(); + $this->addFilter($name); + return $this; + } + + /** + * Sets the _escape() callback. + * + * @param mixed $spec The callback for _escape() to use. + * @return Zend_View_Abstract + */ + public function setEscape($spec) + { + $this->_escape = $spec; + return $this; + } + + /** + * Set LFI protection flag + * + * @param bool $flag + * @return Zend_View_Abstract + */ + public function setLfiProtection($flag) + { + $this->_lfiProtectionOn = (bool) $flag; + return $this; + } + + /** + * Return status of LFI protection flag + * + * @return bool + */ + public function isLfiProtectionOn() + { + return $this->_lfiProtectionOn; + } + + /** + * Assigns variables to the view script via differing strategies. + * + * Zend_View::assign('name', $value) assigns a variable called 'name' + * with the corresponding $value. + * + * Zend_View::assign($array) assigns the array keys as variable + * names (with the corresponding array values). + * + * @see __set() + * @param string|array The assignment strategy to use. + * @param mixed (Optional) If assigning a named variable, use this + * as the value. + * @return Zend_View_Abstract Fluent interface + * @throws Zend_View_Exception if $spec is neither a string nor an array, + * or if an attempt to set a private or protected member is detected + */ + public function assign($spec, $value = null) + { + // which strategy to use? + if (is_string($spec)) { + // assign by name and value + if ('_' == substr($spec, 0, 1)) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception('Setting private or protected class members is not allowed'); + $e->setView($this); + throw $e; + } + $this->$spec = $value; + } elseif (is_array($spec)) { + // assign from associative array + $error = false; + foreach ($spec as $key => $val) { + if ('_' == substr($key, 0, 1)) { + $error = true; + break; + } + $this->$key = $val; + } + if ($error) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception('Setting private or protected class members is not allowed'); + $e->setView($this); + throw $e; + } + } else { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception('assign() expects a string or array, received ' . gettype($spec)); + $e->setView($this); + throw $e; + } + + return $this; + } + + /** + * Return list of all assigned variables + * + * Returns all public properties of the object. Reflection is not used + * here as testing reflection properties for visibility is buggy. + * + * @return array + */ + public function getVars() + { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if ('_' == substr($key, 0, 1)) { + unset($vars[$key]); + } + } + + return $vars; + } + + /** + * Clear all assigned variables + * + * Clears all variables assigned to Zend_View either via {@link assign()} or + * property overloading ({@link __set()}). + * + * @return void + */ + public function clearVars() + { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if ('_' != substr($key, 0, 1)) { + unset($this->$key); + } + } + } + + /** + * Processes a view script and returns the output. + * + * @param string $name The script name to process. + * @return string The script output. + */ + public function render($name) + { + // find the script file name using the parent private method + $this->_file = $this->_script($name); + unset($name); // remove $name from local scope + + ob_start(); + $this->_run($this->_file); + + return $this->_filter(ob_get_clean()); // filter output + } + + /** + * Escapes a value for output in a view script. + * + * If escaping mechanism is one of htmlspecialchars or htmlentities, uses + * {@link $_encoding} setting. + * + * @param mixed $var The output to escape. + * @return mixed The escaped value. + */ + public function escape($var) + { + if (in_array($this->_escape, array('htmlspecialchars', 'htmlentities'))) { + return call_user_func($this->_escape, $var, ENT_COMPAT, $this->_encoding); + } + + if (1 == func_num_args()) { + return call_user_func($this->_escape, $var); + } + $args = func_get_args(); + return call_user_func_array($this->_escape, $args); + } + + /** + * Set encoding to use with htmlentities() and htmlspecialchars() + * + * @param string $encoding + * @return Zend_View_Abstract + */ + public function setEncoding($encoding) + { + $this->_encoding = $encoding; + return $this; + } + + /** + * Return current escape encoding + * + * @return string + */ + public function getEncoding() + { + return $this->_encoding; + } + + /** + * Enable or disable strict vars + * + * If strict variables are enabled, {@link __get()} will raise a notice + * when a variable is not defined. + * + * Use in conjunction with {@link Zend_View_Helper_DeclareVars the declareVars() helper} + * to enforce strict variable handling in your view scripts. + * + * @param boolean $flag + * @return Zend_View_Abstract + */ + public function strictVars($flag = true) + { + $this->_strictVars = ($flag) ? true : false; + + return $this; + } + + /** + * Finds a view script from the available directories. + * + * @param string $name The base name of the script. + * @return void + */ + protected function _script($name) + { + if ($this->isLfiProtectionOn() && preg_match('#\.\.[\\\/]#', $name)) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception('Requested scripts may not include parent directory traversal ("../", "..\\" notation)'); + $e->setView($this); + throw $e; + } + + if (0 == count($this->_path['script'])) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception('no view script directory set; unable to determine location for view script'); + $e->setView($this); + throw $e; + } + + foreach ($this->_path['script'] as $dir) { + if (is_readable($dir . $name)) { + return $dir . $name; + } + } + + require_once 'Zend/View/Exception.php'; + $message = "script '$name' not found in path (" + . implode(PATH_SEPARATOR, $this->_path['script']) + . ")"; + $e = new Zend_View_Exception($message); + $e->setView($this); + throw $e; + } + + /** + * Applies the filter callback to a buffer. + * + * @param string $buffer The buffer contents. + * @return string The filtered buffer. + */ + private function _filter($buffer) + { + // loop through each filter class + foreach ($this->_filter as $name) { + // load and apply the filter class + $filter = $this->getFilter($name); + $buffer = call_user_func(array($filter, 'filter'), $buffer); + } + + // done! + return $buffer; + } + + /** + * Adds paths to the path stack in LIFO order. + * + * Zend_View::_addPath($type, 'dirname') adds one directory + * to the path stack. + * + * Zend_View::_addPath($type, $array) adds one directory for + * each array element value. + * + * In the case of filter and helper paths, $prefix should be used to + * specify what class prefix to use with the given path. + * + * @param string $type The path type ('script', 'helper', or 'filter'). + * @param string|array $path The path specification. + * @param string $prefix Class prefix to use with path (helpers and filters + * only) + * @return void + */ + private function _addPath($type, $path, $prefix = null) + { + foreach ((array) $path as $dir) { + // attempt to strip any possible separator and + // append the system directory separator + $dir = rtrim($dir, '/'); + $dir = rtrim($dir, '\\'); + $dir .= '/'; + + switch ($type) { + case 'script': + // add to the top of the stack. + array_unshift($this->_path[$type], $dir); + break; + case 'filter': + case 'helper': + default: + // add as array with prefix and dir keys + array_unshift($this->_path[$type], array('prefix' => $prefix, 'dir' => $dir)); + break; + } + } + } + + /** + * Resets the path stack for helpers and filters. + * + * @param string $type The path type ('helper' or 'filter'). + * @param string|array $path The directory (-ies) to set as the path. + * @param string $classPrefix Class prefix to apply to elements of $path + */ + private function _setPath($type, $path, $classPrefix = null) + { + $dir = DIRECTORY_SEPARATOR . ucfirst($type) . DIRECTORY_SEPARATOR; + + switch ($type) { + case 'script': + $this->_path[$type] = array(dirname(__FILE__) . $dir); + $this->_addPath($type, $path); + break; + case 'filter': + case 'helper': + default: + $this->_path[$type] = array(array( + 'prefix' => 'Zend_View_' . ucfirst($type) . '_', + 'dir' => dirname(__FILE__) . $dir + )); + $this->_addPath($type, $path, $classPrefix); + break; + } + } + + /** + * Return all paths for a given path type + * + * @param string $type The path type ('helper', 'filter', 'script') + * @return array + */ + private function _getPaths($type) + { + return $this->_path[$type]; + } + + /** + * Register helper class as loaded + * + * @param string $name + * @param string $class + * @param string $file path to class file + * @return void + */ + private function _setHelperClass($name, $class, $file) + { + $this->_helperLoadedDir[$name] = $file; + $this->_helperLoaded[$name] = $class; + } + + /** + * Register filter class as loaded + * + * @param string $name + * @param string $class + * @param string $file path to class file + * @return void + */ + private function _setFilterClass($name, $class, $file) + { + $this->_filterLoadedDir[$name] = $file; + $this->_filterLoaded[$name] = $class; + } + + /** + * Add a prefixPath for a plugin type + * + * @param string $type + * @param string $classPrefix + * @param array $paths + * @return Zend_View_Abstract + */ + private function _addPluginPath($type, $classPrefix, array $paths) + { + $loader = $this->getPluginLoader($type); + foreach ($paths as $path) { + $loader->addPrefixPath($classPrefix, $path); + } + return $this; + } + + /** + * Get a path to a given plugin class of a given type + * + * @param string $type + * @param string $name + * @return string|false + */ + private function _getPluginPath($type, $name) + { + $loader = $this->getPluginLoader($type); + if ($loader->isLoaded($name)) { + return $loader->getClassPath($name); + } + + try { + $loader->load($name); + return $loader->getClassPath($name); + } catch (Zend_Loader_Exception $e) { + return false; + } + } + + /** + * Retrieve a plugin object + * + * @param string $type + * @param string $name + * @return object + */ + private function _getPlugin($type, $name) + { + $name = ucfirst($name); + switch ($type) { + case 'filter': + $storeVar = '_filterClass'; + $store = $this->_filterClass; + break; + case 'helper': + $storeVar = '_helper'; + $store = $this->_helper; + break; + } + + if (!isset($store[$name])) { + $class = $this->getPluginLoader($type)->load($name); + $store[$name] = new $class(); + if (method_exists($store[$name], 'setView')) { + $store[$name]->setView($this); + } + } + + $this->$storeVar = $store; + return $store[$name]; + } + + /** + * Use to include the view script in a scope that only allows public + * members. + * + * @return mixed + */ + abstract protected function _run(); +} diff --git a/lib/zend/Zend/View/Exception.php b/lib/zend/Zend/View/Exception.php new file mode 100644 index 00000000000..93078bcf8e1 --- /dev/null +++ b/lib/zend/Zend/View/Exception.php @@ -0,0 +1,51 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_View + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @version $Id$ + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + + +/** + * Zend_Exception + */ +require_once 'Zend/Exception.php'; + + +/** + * Exception for Zend_View class. + * + * @category Zend + * @package Zend_View + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_View_Exception extends Zend_Exception +{ + protected $view = null; + + public function setView(Zend_View_Interface $view = null) + { + $this->view = $view; + return $this; + } + + public function getView() + { + return $this->view; + } +} diff --git a/lib/zend/Zend/Service/DeveloperGarden/Response/IpLocation/GeoCoordinatesType.php b/lib/zend/Zend/View/Helper/Abstract.php similarity index 50% rename from lib/zend/Zend/Service/DeveloperGarden/Response/IpLocation/GeoCoordinatesType.php rename to lib/zend/Zend/View/Helper/Abstract.php index 0b295f3cc79..da481bbe337 100644 --- a/lib/zend/Zend/Service/DeveloperGarden/Response/IpLocation/GeoCoordinatesType.php +++ b/lib/zend/Zend/View/Helper/Abstract.php @@ -13,54 +13,52 @@ * to license@zend.com so we can send you a copy immediately. * * @category Zend - * @package Zend_Service - * @subpackage DeveloperGarden - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ /** - * @see Zend_Service_DeveloperGarden_Response_BaseType + * @see Zend_View_Helper_Interface */ -require_once 'Zend/Service/DeveloperGarden/Response/BaseType.php'; +require_once 'Zend/View/Helper/Interface.php'; /** * @category Zend - * @package Zend_Service - * @subpackage DeveloperGarden - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @author Marco Kaiser + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class Zend_Service_DeveloperGarden_Response_IpLocation_GeoCoordinatesType - extends Zend_Service_DeveloperGarden_Response_BaseType +abstract class Zend_View_Helper_Abstract implements Zend_View_Helper_Interface { /** + * View object * - * @var float + * @var Zend_View_Interface */ - public $geoLatitude = null; + public $view = null; /** + * Set the View object * - * @var float + * @param Zend_View_Interface $view + * @return Zend_View_Helper_Abstract */ - public $geoLongitude = null; - - /** - * @return float - */ - public function getLatitude() + public function setView(Zend_View_Interface $view) { - return $this->geoLatitude; + $this->view = $view; + return $this; } /** - * @return float + * Strategy pattern: currently unutilized + * + * @return void */ - public function getLongitude() + public function direct() { - return $this->geoLongitude; } } diff --git a/lib/zend/Zend/View/Helper/Action.php b/lib/zend/Zend/View/Helper/Action.php new file mode 100644 index 00000000000..a4b83af5826 --- /dev/null +++ b/lib/zend/Zend/View/Helper/Action.php @@ -0,0 +1,164 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @version $Id$ + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +/** Zend_View_Helper_Abstract.php */ +require_once 'Zend/View/Helper/Abstract.php'; + +/** + * Helper for rendering output of a controller action + * + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_View_Helper_Action extends Zend_View_Helper_Abstract +{ + /** + * @var string + */ + public $defaultModule; + + /** + * @var Zend_Controller_Dispatcher_Interface + */ + public $dispatcher; + + /** + * @var Zend_Controller_Request_Abstract + */ + public $request; + + /** + * @var Zend_Controller_Response_Abstract + */ + public $response; + + /** + * Constructor + * + * Grab local copies of various MVC objects + * + * @return void + */ + public function __construct() + { + $front = Zend_Controller_Front::getInstance(); + $modules = $front->getControllerDirectory(); + if (empty($modules)) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception('Action helper depends on valid front controller instance'); + $e->setView($this->view); + throw $e; + } + + $request = $front->getRequest(); + $response = $front->getResponse(); + + if (empty($request) || empty($response)) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception('Action view helper requires both a registered request and response object in the front controller instance'); + $e->setView($this->view); + throw $e; + } + + $this->request = clone $request; + $this->response = clone $response; + $this->dispatcher = clone $front->getDispatcher(); + $this->defaultModule = $front->getDefaultModule(); + } + + /** + * Reset object states + * + * @return void + */ + public function resetObjects() + { + $params = $this->request->getUserParams(); + foreach (array_keys($params) as $key) { + $this->request->setParam($key, null); + } + + $this->response->clearBody(); + $this->response->clearHeaders() + ->clearRawHeaders(); + } + + /** + * Retrieve rendered contents of a controller action + * + * If the action results in a forward or redirect, returns empty string. + * + * @param string $action + * @param string $controller + * @param string $module Defaults to default module + * @param array $params + * @return string + */ + public function action($action, $controller, $module = null, array $params = array()) + { + $this->resetObjects(); + if (null === $module) { + $module = $this->defaultModule; + } + + // clone the view object to prevent over-writing of view variables + $viewRendererObj = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer'); + Zend_Controller_Action_HelperBroker::addHelper(clone $viewRendererObj); + + $this->request->setParams($params) + ->setModuleName($module) + ->setControllerName($controller) + ->setActionName($action) + ->setDispatched(true); + + $this->dispatcher->dispatch($this->request, $this->response); + + // reset the viewRenderer object to it's original state + Zend_Controller_Action_HelperBroker::addHelper($viewRendererObj); + + + if (!$this->request->isDispatched() + || $this->response->isRedirect()) + { + // forwards and redirects render nothing + return ''; + } + + $return = $this->response->getBody(); + $this->resetObjects(); + return $return; + } + + /** + * Clone the current View + * + * @return Zend_View_Interface + */ + public function cloneView() + { + $view = clone $this->view; + $view->clearVars(); + return $view; + } +} diff --git a/lib/zend/Zend/View/Helper/BaseUrl.php b/lib/zend/Zend/View/Helper/BaseUrl.php new file mode 100644 index 00000000000..8af36bbdda2 --- /dev/null +++ b/lib/zend/Zend/View/Helper/BaseUrl.php @@ -0,0 +1,116 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @version $Id$ + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +/** @see Zend_View_Helper_Abstract */ +require_once 'Zend/View/Helper/Abstract.php'; + +/** + * Helper for retrieving the BaseUrl + * + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_View_Helper_BaseUrl extends Zend_View_Helper_Abstract +{ + /** + * BaseUrl + * + * @var string + */ + protected $_baseUrl; + + /** + * Returns site's base url, or file with base url prepended + * + * $file is appended to the base url for simplicity + * + * @param string|null $file + * @return string + */ + public function baseUrl($file = null) + { + // Get baseUrl + $baseUrl = $this->getBaseUrl(); + + // Remove trailing slashes + if (null !== $file) { + $file = '/' . ltrim($file, '/\\'); + } + + return $baseUrl . $file; + } + + /** + * Set BaseUrl + * + * @param string $base + * @return Zend_View_Helper_BaseUrl + */ + public function setBaseUrl($base) + { + $this->_baseUrl = rtrim($base, '/\\'); + return $this; + } + + /** + * Get BaseUrl + * + * @return string + */ + public function getBaseUrl() + { + if ($this->_baseUrl === null) { + /** @see Zend_Controller_Front */ + require_once 'Zend/Controller/Front.php'; + $baseUrl = Zend_Controller_Front::getInstance()->getBaseUrl(); + + // Remove scriptname, eg. index.php from baseUrl + $baseUrl = $this->_removeScriptName($baseUrl); + + $this->setBaseUrl($baseUrl); + } + + return $this->_baseUrl; + } + + /** + * Remove Script filename from baseurl + * + * @param string $url + * @return string + */ + protected function _removeScriptName($url) + { + if (!isset($_SERVER['SCRIPT_NAME'])) { + // We can't do much now can we? (Well, we could parse out by ".") + return $url; + } + + if (($pos = strripos($url, basename($_SERVER['SCRIPT_NAME']))) !== false) { + $url = substr($url, 0, $pos); + } + + return $url; + } +} diff --git a/lib/zend/Zend/View/Helper/Currency.php b/lib/zend/Zend/View/Helper/Currency.php new file mode 100644 index 00000000000..592185f7195 --- /dev/null +++ b/lib/zend/Zend/View/Helper/Currency.php @@ -0,0 +1,120 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @version $Id$ + */ + +/** Zend_View_Helper_Abstract.php */ +require_once 'Zend/View/Helper/Abstract.php'; + +/** + * Currency view helper + * + * @category Zend + * @package Zend_View + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_View_Helper_Currency extends Zend_View_Helper_Abstract +{ + /** + * Currency object + * + * @var Zend_Currency + */ + protected $_currency; + + /** + * Constructor for manually handling + * + * @param Zend_Currency $currency Instance of Zend_Currency + * @return void + */ + public function __construct($currency = null) + { + if ($currency === null) { + require_once 'Zend/Registry.php'; + if (Zend_Registry::isRegistered('Zend_Currency')) { + $currency = Zend_Registry::get('Zend_Currency'); + } + } + + $this->setCurrency($currency); + } + + /** + * Output a formatted currency + * + * @param integer|float $value Currency value to output + * @param string|Zend_Locale|array $currency OPTIONAL Currency to use for + * this call + * @return string Formatted currency + */ + public function currency($value = null, $currency = null) + { + if ($value === null) { + return $this; + } + + if (is_string($currency) || ($currency instanceof Zend_Locale)) { + require_once 'Zend/Locale.php'; + if (Zend_Locale::isLocale($currency)) { + $currency = array('locale' => $currency); + } + } + + if (is_string($currency)) { + $currency = array('currency' => $currency); + } + + if (is_array($currency)) { + return $this->_currency->toCurrency($value, $currency); + } + + return $this->_currency->toCurrency($value); + } + + /** + * Sets a currency to use + * + * @param Zend_Currency|String|Zend_Locale $currency Currency to use + * @throws Zend_View_Exception When no or a false currency was set + * @return Zend_View_Helper_Currency + */ + public function setCurrency($currency = null) + { + if (!$currency instanceof Zend_Currency) { + require_once 'Zend/Currency.php'; + $currency = new Zend_Currency($currency); + } + $this->_currency = $currency; + + return $this; + } + + /** + * Retrieve currency object + * + * @return Zend_Currency|null + */ + public function getCurrency() + { + return $this->_currency; + } +} diff --git a/lib/zend/Zend/View/Helper/Cycle.php b/lib/zend/Zend/View/Helper/Cycle.php new file mode 100644 index 00000000000..eb5fd5132bc --- /dev/null +++ b/lib/zend/Zend/View/Helper/Cycle.php @@ -0,0 +1,225 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @version $Id$ + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +/** + * Helper for alternating between set of values + * + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_View_Helper_Cycle implements Iterator +{ + + /** + * Default name + * @var string + */ + const DEFAULT_NAME = 'default'; + + /** + * Pointers + * + * @var array + */ + protected $_pointers = array(self::DEFAULT_NAME =>-1) ; + + /** + * Array of values + * + * @var array + */ + protected $_data = array(self::DEFAULT_NAME=>array()); + + /** + * Actual name of cycle + * + * @var string + */ + protected $_name = self::DEFAULT_NAME; + + /** + * Add elements to alternate + * + * @param array $data + * @param string $name + * @return Zend_View_Helper_Cycle + */ + public function cycle(array $data = array(), $name = self::DEFAULT_NAME) + { + if(!empty($data)) + $this->_data[$name] = $data; + + $this->setName($name); + return $this; + } + + /** + * Add elements to alternate + * + * @param array $data + * @param string $name + * @return Zend_View_Helper_Cycle + */ + public function assign(Array $data , $name = self::DEFAULT_NAME) + { + $this->setName($name); + $this->_data[$name] = $data; + $this->rewind(); + return $this; + } + + /** + * Sets actual name of cycle + * + * @param string $name + * @return Zend_View_Helper_Cycle + */ + public function setName($name = self::DEFAULT_NAME) + { + $this->_name = $name; + + if(!isset($this->_data[$this->_name])) + $this->_data[$this->_name] = array(); + + if(!isset($this->_pointers[$this->_name])) + $this->rewind(); + + return $this; + } + + /** + * Gets actual name of cycle + * + * @return string + */ + public function getName() + { + return $this->_name; + } + + + /** + * Return all elements + * + * @return array + */ + public function getAll() + { + return $this->_data[$this->_name]; + } + + /** + * Turn helper into string + * + * @return string + */ + public function toString() + { + return (string) $this->_data[$this->_name][$this->key()]; + } + + /** + * Cast to string + * + * @return string + */ + public function __toString() + { + return $this->toString(); + } + + /** + * Move to next value + * + * @return Zend_View_Helper_Cycle + */ + public function next() + { + $count = count($this->_data[$this->_name]); + if ($this->_pointers[$this->_name] == ($count - 1)) + $this->_pointers[$this->_name] = 0; + else + $this->_pointers[$this->_name] = ++$this->_pointers[$this->_name]; + return $this; + } + + /** + * Move to previous value + * + * @return Zend_View_Helper_Cycle + */ + public function prev() + { + $count = count($this->_data[$this->_name]); + if ($this->_pointers[$this->_name] <= 0) + $this->_pointers[$this->_name] = $count - 1; + else + $this->_pointers[$this->_name] = --$this->_pointers[$this->_name]; + return $this; + } + + /** + * Return iteration number + * + * @return int + */ + public function key() + { + if ($this->_pointers[$this->_name] < 0) + return 0; + else + return $this->_pointers[$this->_name]; + } + + /** + * Rewind pointer + * + * @return Zend_View_Helper_Cycle + */ + public function rewind() + { + $this->_pointers[$this->_name] = -1; + return $this; + } + + /** + * Check if element is valid + * + * @return bool + */ + public function valid() + { + return isset($this->_data[$this->_name][$this->key()]); + } + + /** + * Return current element + * + * @return mixed + */ + public function current() + { + return $this->_data[$this->_name][$this->key()]; + } +} diff --git a/lib/zend/Zend/View/Helper/DeclareVars.php b/lib/zend/Zend/View/Helper/DeclareVars.php new file mode 100644 index 00000000000..4663d4a41c1 --- /dev/null +++ b/lib/zend/Zend/View/Helper/DeclareVars.php @@ -0,0 +1,95 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @version $Id$ + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +/** Zend_View_Helper_Abstract.php */ +require_once 'Zend/View/Helper/Abstract.php'; + +/** + * Helper for declaring default values of template variables + * + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_View_Helper_DeclareVars extends Zend_View_Helper_Abstract +{ + /** + * The view object that created this helper object. + * @var Zend_View + */ + public $view; + + /** + * Declare template vars to set default values and avoid notices when using strictVars + * + * Primarily for use when using {@link Zend_View_Abstract::strictVars() Zend_View strictVars()}, + * this helper can be used to declare template variables that may or may + * not already be set in the view object, as well as to set default values. + * Arrays passed as arguments to the method will be used to set default + * values; otherwise, if the variable does not exist, it is set to an empty + * string. + * + * Usage: + * <code> + * $this->declareVars( + * 'varName1', + * 'varName2', + * array('varName3' => 'defaultValue', + * 'varName4' => array() + * ) + * ); + * </code> + * + * @param string|array variable number of arguments, all string names of variables to test + * @return void + */ + public function declareVars() + { + $args = func_get_args(); + foreach($args as $key) { + if (is_array($key)) { + foreach ($key as $name => $value) { + $this->_declareVar($name, $value); + } + } else if (!isset($view->$key)) { + $this->_declareVar($key); + } + } + } + + /** + * Set a view variable + * + * Checks to see if a $key is set in the view object; if not, sets it to $value. + * + * @param string $key + * @param string $value Defaults to an empty string + * @return void + */ + protected function _declareVar($key, $value = '') + { + if (!isset($this->view->$key)) { + $this->view->$key = $value; + } + } +} diff --git a/lib/zend/Zend/View/Helper/Doctype.php b/lib/zend/Zend/View/Helper/Doctype.php new file mode 100644 index 00000000000..ca63b4dea77 --- /dev/null +++ b/lib/zend/Zend/View/Helper/Doctype.php @@ -0,0 +1,242 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @version $Id$ + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +/** Zend_Registry */ +require_once 'Zend/Registry.php'; + +/** Zend_View_Helper_Abstract.php */ +require_once 'Zend/View/Helper/Abstract.php'; + +/** + * Helper for setting and retrieving the doctype + * + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_View_Helper_Doctype extends Zend_View_Helper_Abstract +{ + /**#@+ + * DocType constants + */ + const XHTML11 = 'XHTML11'; + const XHTML1_STRICT = 'XHTML1_STRICT'; + const XHTML1_TRANSITIONAL = 'XHTML1_TRANSITIONAL'; + const XHTML1_FRAMESET = 'XHTML1_FRAMESET'; + const XHTML1_RDFA = 'XHTML1_RDFA'; + const XHTML1_RDFA11 = 'XHTML1_RDFA11'; + const XHTML_BASIC1 = 'XHTML_BASIC1'; + const XHTML5 = 'XHTML5'; + const HTML4_STRICT = 'HTML4_STRICT'; + const HTML4_LOOSE = 'HTML4_LOOSE'; + const HTML4_FRAMESET = 'HTML4_FRAMESET'; + const HTML5 = 'HTML5'; + const CUSTOM_XHTML = 'CUSTOM_XHTML'; + const CUSTOM = 'CUSTOM'; + /**#@-*/ + + /** + * Default DocType + * @var string + */ + protected $_defaultDoctype = self::HTML4_LOOSE; + + /** + * Registry containing current doctype and mappings + * @var ArrayObject + */ + protected $_registry; + + /** + * Registry key in which helper is stored + * @var string + */ + protected $_regKey = 'Zend_View_Helper_Doctype'; + + /** + * Constructor + * + * Map constants to doctype strings, and set default doctype + * + * @return void + */ + public function __construct() + { + if (!Zend_Registry::isRegistered($this->_regKey)) { + $this->_registry = new ArrayObject(array( + 'doctypes' => array( + self::XHTML11 => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">', + self::XHTML1_STRICT => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">', + self::XHTML1_TRANSITIONAL => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">', + self::XHTML1_FRAMESET => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">', + self::XHTML1_RDFA => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN" "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">', + self::XHTML1_RDFA11 => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.1//EN" "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-2.dtd">', + self::XHTML_BASIC1 => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.0//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic10.dtd">', + self::XHTML5 => '<!DOCTYPE html>', + self::HTML4_STRICT => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">', + self::HTML4_LOOSE => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">', + self::HTML4_FRAMESET => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">', + self::HTML5 => '<!DOCTYPE html>', + ) + )); + Zend_Registry::set($this->_regKey, $this->_registry); + $this->setDoctype($this->_defaultDoctype); + } else { + $this->_registry = Zend_Registry::get($this->_regKey); + } + } + + /** + * Set or retrieve doctype + * + * @param string $doctype + * @return Zend_View_Helper_Doctype + */ + public function doctype($doctype = null) + { + if (null !== $doctype) { + switch ($doctype) { + case self::XHTML11: + case self::XHTML1_STRICT: + case self::XHTML1_TRANSITIONAL: + case self::XHTML1_FRAMESET: + case self::XHTML_BASIC1: + case self::XHTML1_RDFA: + case self::XHTML1_RDFA11: + case self::XHTML5: + case self::HTML4_STRICT: + case self::HTML4_LOOSE: + case self::HTML4_FRAMESET: + case self::HTML5: + $this->setDoctype($doctype); + break; + default: + if (substr($doctype, 0, 9) != '<!DOCTYPE') { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception('The specified doctype is malformed'); + $e->setView($this->view); + throw $e; + } + if (stristr($doctype, 'xhtml')) { + $type = self::CUSTOM_XHTML; + } else { + $type = self::CUSTOM; + } + $this->setDoctype($type); + $this->_registry['doctypes'][$type] = $doctype; + break; + } + } + + return $this; + } + + /** + * Set doctype + * + * @param string $doctype + * @return Zend_View_Helper_Doctype + */ + public function setDoctype($doctype) + { + $this->_registry['doctype'] = $doctype; + return $this; + } + + /** + * Retrieve doctype + * + * @return string + */ + public function getDoctype() + { + return $this->_registry['doctype']; + } + + /** + * Get doctype => string mappings + * + * @return array + */ + public function getDoctypes() + { + return $this->_registry['doctypes']; + } + + /** + * Is doctype XHTML? + * + * @return boolean + */ + public function isXhtml() + { + return (stristr($this->getDoctype(), 'xhtml') ? true : false); + } + + /** + * Is doctype strict? + * + * @return boolean + */ + public function isStrict() + { + switch ( $this->getDoctype() ) + { + case self::XHTML1_STRICT: + case self::XHTML11: + case self::HTML4_STRICT: + return true; + default: + return false; + } + } + + /** + * Is doctype HTML5? (HeadMeta uses this for validation) + * + * @return booleean + */ + public function isHtml5() { + return (stristr($this->doctype(), '<!DOCTYPE html>') ? true : false); + } + + /** + * Is doctype RDFa? + * + * @return booleean + */ + public function isRdfa() { + return (stristr($this->getDoctype(), 'rdfa') ? true : false); + } + + /** + * String representation of doctype + * + * @return string + */ + public function __toString() + { + $doctypes = $this->getDoctypes(); + return $doctypes[$this->getDoctype()]; + } +} diff --git a/lib/zend/Zend/View/Helper/Fieldset.php b/lib/zend/Zend/View/Helper/Fieldset.php new file mode 100644 index 00000000000..fce37b9341e --- /dev/null +++ b/lib/zend/Zend/View/Helper/Fieldset.php @@ -0,0 +1,79 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @version $Id$ + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +/** Zend_View_Helper_FormElement */ +require_once 'Zend/View/Helper/FormElement.php'; + +/** + * Helper for rendering fieldsets + * + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_View_Helper_Fieldset extends Zend_View_Helper_FormElement +{ + /** + * Render HTML form + * + * @param string $name Form name + * @param string $content Form content + * @param array $attribs HTML form attributes + * @return string + */ + public function fieldset($name, $content, $attribs = null) + { + $info = $this->_getInfo($name, $content, $attribs); + extract($info); + + // get legend + $legend = ''; + if (isset($attribs['legend'])) { + $legendString = trim($attribs['legend']); + if (!empty($legendString)) { + $legend = '<legend>' + . (($escape) ? $this->view->escape($legendString) : $legendString) + . '</legend>' . PHP_EOL; + } + unset($attribs['legend']); + } + + // get id + if (!empty($id)) { + $id = ' id="' . $this->view->escape($id) . '"'; + } else { + $id = ''; + } + + // render fieldset + $xhtml = '<fieldset' + . $id + . $this->_htmlAttribs($attribs) + . '>' + . $legend + . $content + . '</fieldset>'; + + return $xhtml; + } +} diff --git a/lib/zend/Zend/View/Helper/Form.php b/lib/zend/Zend/View/Helper/Form.php new file mode 100644 index 00000000000..514bdd9016a --- /dev/null +++ b/lib/zend/Zend/View/Helper/Form.php @@ -0,0 +1,86 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @version $Id$ + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +/** Zend_View_Helper_FormElement */ +require_once 'Zend/View/Helper/FormElement.php'; + +/** + * Helper for rendering HTML forms + * + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_View_Helper_Form extends Zend_View_Helper_FormElement +{ + /** + * Render HTML form + * + * @param string $name Form name + * @param null|array $attribs HTML form attributes + * @param false|string $content Form content + * @return string + */ + public function form($name, $attribs = null, $content = false) + { + $info = $this->_getInfo($name, $content, $attribs); + extract($info); + + if (!empty($id)) { + $id = ' id="' . $this->view->escape($id) . '"'; + } else { + $id = ''; + } + + if (array_key_exists('id', $attribs) && empty($attribs['id'])) { + unset($attribs['id']); + } + + if (!empty($name) && !($this->_isXhtml() && $this->_isStrictDoctype())) { + $name = ' name="' . $this->view->escape($name) . '"'; + } else { + $name = ''; + } + + if ($this->_isHtml5() && array_key_exists('action', $attribs) && !$attribs['action']) { + unset($attribs['action']); + } + + if ( array_key_exists('name', $attribs) && empty($attribs['id'])) { + unset($attribs['id']); + } + + $xhtml = '<form' + . $id + . $name + . $this->_htmlAttribs($attribs) + . '>'; + + if (false !== $content) { + $xhtml .= $content + . '</form>'; + } + + return $xhtml; + } +} diff --git a/lib/zend/Zend/View/Helper/FormButton.php b/lib/zend/Zend/View/Helper/FormButton.php new file mode 100644 index 00000000000..abdd9f8f33f --- /dev/null +++ b/lib/zend/Zend/View/Helper/FormButton.php @@ -0,0 +1,105 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @version $Id$ + */ + + +/** + * Abstract class for extension + */ +require_once 'Zend/View/Helper/FormElement.php'; + + +/** + * Helper to generate a "button" element + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_View_Helper_FormButton extends Zend_View_Helper_FormElement +{ + /** + * Generates a 'button' element. + * + * @access public + * + * @param string|array $name If a string, the element name. If an + * array, all other parameters are ignored, and the array elements + * are extracted in place of added parameters. + * + * @param mixed $value The element value. + * + * @param array $attribs Attributes for the element tag. + * + * @return string The element XHTML. + */ + public function formButton($name, $value = null, $attribs = null) + { + $info = $this->_getInfo($name, $value, $attribs); + extract($info); // name, id, value, attribs, options, listsep, disable, escape + + // Get content + $content = ''; + if (isset($attribs['content'])) { + $content = $attribs['content']; + unset($attribs['content']); + } else { + $content = $value; + } + + // Ensure type is sane + $type = 'button'; + if (isset($attribs['type'])) { + $attribs['type'] = strtolower($attribs['type']); + if (in_array($attribs['type'], array('submit', 'reset', 'button'))) { + $type = $attribs['type']; + } + unset($attribs['type']); + } + + // build the element + if ($disable) { + $attribs['disabled'] = 'disabled'; + } + + $content = ($escape) ? $this->view->escape($content) : $content; + + $xhtml = '<button' + . ' name="' . $this->view->escape($name) . '"' + . ' id="' . $this->view->escape($id) . '"' + . ' type="' . $type . '"'; + + // add a value if one is given + if (!empty($value)) { + $xhtml .= ' value="' . $this->view->escape($value) . '"'; + } + + // add attributes and close start tag + $xhtml .= $this->_htmlAttribs($attribs) . '>'; + + // add content and end tag + $xhtml .= $content . '</button>'; + + return $xhtml; + } +} diff --git a/lib/zend/Zend/View/Helper/FormCheckbox.php b/lib/zend/Zend/View/Helper/FormCheckbox.php new file mode 100644 index 00000000000..fd6f4ae5b5d --- /dev/null +++ b/lib/zend/Zend/View/Helper/FormCheckbox.php @@ -0,0 +1,164 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @version $Id$ + */ + + +/** + * Abstract class for extension + */ +require_once 'Zend/View/Helper/FormElement.php'; + + +/** + * Helper to generate a "checkbox" element + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_View_Helper_FormCheckbox extends Zend_View_Helper_FormElement +{ + /** + * Default checked/unchecked options + * @var array + */ + protected static $_defaultCheckedOptions = array( + 'checkedValue' => '1', + 'uncheckedValue' => '0' + ); + + /** + * Generates a 'checkbox' element. + * + * @access public + * + * @param string|array $name If a string, the element name. If an + * array, all other parameters are ignored, and the array elements + * are extracted in place of added parameters. + * @param mixed $value The element value. + * @param array $attribs Attributes for the element tag. + * @return string The element XHTML. + */ + public function formCheckbox($name, $value = null, $attribs = null, array $checkedOptions = null) + { + $info = $this->_getInfo($name, $value, $attribs); + extract($info); // name, id, value, attribs, options, listsep, disable + + $checked = false; + if (isset($attribs['checked']) && $attribs['checked']) { + $checked = true; + unset($attribs['checked']); + } elseif (isset($attribs['checked'])) { + $checked = false; + unset($attribs['checked']); + } + + $checkedOptions = self::determineCheckboxInfo($value, $checked, $checkedOptions); + + // is the element disabled? + $disabled = ''; + if ($disable) { + $disabled = ' disabled="disabled"'; + } + + // build the element + $xhtml = ''; + if ((!$disable && !strstr($name, '[]')) + && (empty($attribs['disableHidden']) || !$attribs['disableHidden']) + ) { + $xhtml = $this->_hidden($name, $checkedOptions['uncheckedValue']); + } + + if (array_key_exists('disableHidden', $attribs)) { + unset($attribs['disableHidden']); + } + + $xhtml .= '<input type="checkbox"' + . ' name="' . $this->view->escape($name) . '"' + . ' id="' . $this->view->escape($id) . '"' + . ' value="' . $this->view->escape($checkedOptions['checkedValue']) . '"' + . $checkedOptions['checkedString'] + . $disabled + . $this->_htmlAttribs($attribs) + . $this->getClosingBracket(); + + return $xhtml; + } + + /** + * Determine checkbox information + * + * @param string $value + * @param bool $checked + * @param array|null $checkedOptions + * @return array + */ + public static function determineCheckboxInfo($value, $checked, array $checkedOptions = null) + { + // Checked/unchecked values + $checkedValue = null; + $uncheckedValue = null; + if (is_array($checkedOptions)) { + if (array_key_exists('checkedValue', $checkedOptions)) { + $checkedValue = (string) $checkedOptions['checkedValue']; + unset($checkedOptions['checkedValue']); + } + if (array_key_exists('uncheckedValue', $checkedOptions)) { + $uncheckedValue = (string) $checkedOptions['uncheckedValue']; + unset($checkedOptions['uncheckedValue']); + } + if (null === $checkedValue) { + $checkedValue = (string) array_shift($checkedOptions); + } + if (null === $uncheckedValue) { + $uncheckedValue = (string) array_shift($checkedOptions); + } + } elseif ($value !== null) { + $uncheckedValue = self::$_defaultCheckedOptions['uncheckedValue']; + } else { + $checkedValue = self::$_defaultCheckedOptions['checkedValue']; + $uncheckedValue = self::$_defaultCheckedOptions['uncheckedValue']; + } + + // is the element checked? + $checkedString = ''; + if ($checked || ((string) $value === $checkedValue)) { + $checkedString = ' checked="checked"'; + $checked = true; + } else { + $checked = false; + } + + // Checked value should be value if no checked options provided + if ($checkedValue == null) { + $checkedValue = $value; + } + + return array( + 'checked' => $checked, + 'checkedString' => $checkedString, + 'checkedValue' => $checkedValue, + 'uncheckedValue' => $uncheckedValue, + ); + } +} diff --git a/lib/zend/Zend/View/Helper/FormElement.php b/lib/zend/Zend/View/Helper/FormElement.php new file mode 100644 index 00000000000..8c1373b38ce --- /dev/null +++ b/lib/zend/Zend/View/Helper/FormElement.php @@ -0,0 +1,204 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @version $Id$ + */ + +/** + * @see Zend_View_Helper_HtmlElement + */ +require_once 'Zend/View/Helper/HtmlElement.php'; + +/** + * Base helper for form elements. Extend this, don't use it on its own. + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +abstract class Zend_View_Helper_FormElement extends Zend_View_Helper_HtmlElement +{ + /** + * @var Zend_Translate_Adapter|null + */ + protected $_translator; + + /** + * Get translator + * + * @return Zend_Translate_Adapter|null + */ + public function getTranslator() + { + return $this->_translator; + } + + /** + * Set translator + * + * @param Zend_Translate|Zend_Translate_Adapter|null $translator + * @return Zend_View_Helper_FormElement + */ + public function setTranslator($translator = null) + { + if (null === $translator) { + $this->_translator = null; + } elseif ($translator instanceof Zend_Translate_Adapter) { + $this->_translator = $translator; + } elseif ($translator instanceof Zend_Translate) { + $this->_translator = $translator->getAdapter(); + } else { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception('Invalid translator specified'); + $e->setView($this->view); + throw $e; + } + return $this; + } + + /** + * Converts parameter arguments to an element info array. + * + * E.g, formExample($name, $value, $attribs, $options, $listsep) is + * the same thing as formExample(array('name' => ...)). + * + * Note that you cannot pass a 'disable' param; you need to pass + * it as an 'attribs' key. + * + * @access protected + * + * @return array An element info array with keys for name, value, + * attribs, options, listsep, disable, and escape. + */ + protected function _getInfo($name, $value = null, $attribs = null, + $options = null, $listsep = null + ) { + // the baseline info. note that $name serves a dual purpose; + // if an array, it's an element info array that will override + // these baseline values. as such, ignore it for the 'name' + // if it's an array. + $info = array( + 'name' => is_array($name) ? '' : $name, + 'id' => is_array($name) ? '' : $name, + 'value' => $value, + 'attribs' => $attribs, + 'options' => $options, + 'listsep' => $listsep, + 'disable' => false, + 'escape' => true, + ); + + // override with named args + if (is_array($name)) { + // only set keys that are already in info + foreach ($info as $key => $val) { + if (isset($name[$key])) { + $info[$key] = $name[$key]; + } + } + + // If all helper options are passed as an array, attribs may have + // been as well + if (null === $attribs) { + $attribs = $info['attribs']; + } + } + + $attribs = (array)$attribs; + + // Normalize readonly tag + if (array_key_exists('readonly', $attribs)) { + $attribs['readonly'] = 'readonly'; + } + + // Disable attribute + if (array_key_exists('disable', $attribs)) { + if (is_scalar($attribs['disable'])) { + // disable the element + $info['disable'] = (bool)$attribs['disable']; + } else if (is_array($attribs['disable'])) { + $info['disable'] = $attribs['disable']; + } + } + + // Set ID for element + if (array_key_exists('id', $attribs)) { + $info['id'] = (string)$attribs['id']; + } else if ('' !== $info['name']) { + $info['id'] = trim(strtr($info['name'], + array('[' => '-', ']' => '')), '-'); + } + + // Remove NULL name attribute override + if (array_key_exists('name', $attribs) && is_null($attribs['name'])) { + unset($attribs['name']); + } + + // Override name in info if specified in attribs + if (array_key_exists('name', $attribs) && $attribs['name'] != $info['name']) { + $info['name'] = $attribs['name']; + } + + // Determine escaping from attributes + if (array_key_exists('escape', $attribs)) { + $info['escape'] = (bool)$attribs['escape']; + } + + // Determine listsetp from attributes + if (array_key_exists('listsep', $attribs)) { + $info['listsep'] = (string)$attribs['listsep']; + } + + // Remove attribs that might overwrite the other keys. We do this LAST + // because we needed the other attribs values earlier. + foreach ($info as $key => $val) { + if (array_key_exists($key, $attribs)) { + unset($attribs[$key]); + } + } + $info['attribs'] = $attribs; + + // done! + return $info; + } + + /** + * Creates a hidden element. + * + * We have this as a common method because other elements often + * need hidden elements for their operation. + * + * @access protected + * + * @param string $name The element name. + * @param string $value The element value. + * @param array $attribs Attributes for the element. + * + * @return string A hidden element. + */ + protected function _hidden($name, $value = null, $attribs = null) + { + return '<input type="hidden"' + . ' name="' . $this->view->escape($name) . '"' + . ' value="' . $this->view->escape($value) . '"' + . $this->_htmlAttribs($attribs) . $this->getClosingBracket(); + } +} diff --git a/lib/zend/Zend/View/Helper/FormErrors.php b/lib/zend/Zend/View/Helper/FormErrors.php new file mode 100644 index 00000000000..4e092b1157b --- /dev/null +++ b/lib/zend/Zend/View/Helper/FormErrors.php @@ -0,0 +1,167 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @version $Id$ + */ + +/** + * Abstract class for extension + */ +require_once 'Zend/View/Helper/FormElement.php'; + + +/** + * Helper to render errors for a form element + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_View_Helper_FormErrors extends Zend_View_Helper_FormElement +{ + /** + * @var Zend_Form_Element + */ + protected $_element; + + /**#@+ + * @var string Element block start/end tags and separator + */ + protected $_htmlElementEnd = '</li></ul>'; + protected $_htmlElementStart = '<ul%s><li>'; + protected $_htmlElementSeparator = '</li><li>'; + /**#@-*/ + + /** + * Render form errors + * + * @param string|array $errors Error(s) to render + * @param array $options + * @return string + */ + public function formErrors($errors, array $options = null) + { + $escape = true; + if (isset($options['escape'])) { + $escape = (bool) $options['escape']; + unset($options['escape']); + } + + if (empty($options['class'])) { + $options['class'] = 'errors'; + } + + if (isset($options['elementStart'])) { + $this->setElementStart($options['elementStart']); + } + if (isset($options['elementEnd'])) { + $this->setElementEnd($options['elementEnd']); + } + if (isset($options['elementSeparator'])) { + $this->setElementSeparator($options['elementSeparator']); + } + + $start = $this->getElementStart(); + if (strstr($start, '%s')) { + $attribs = $this->_htmlAttribs($options); + $start = sprintf($start, $attribs); + } + + if ($escape) { + foreach ($errors as $key => $error) { + $errors[$key] = $this->view->escape($error); + } + } + + $html = $start + . implode($this->getElementSeparator(), (array) $errors) + . $this->getElementEnd(); + + return $html; + } + + /** + * Set end string for displaying errors + * + * @param string $string + * @return Zend_View_Helper_FormErrors + */ + public function setElementEnd($string) + { + $this->_htmlElementEnd = (string) $string; + return $this; + } + + /** + * Retrieve end string for displaying errors + * + * @return string + */ + public function getElementEnd() + { + return $this->_htmlElementEnd; + } + + /** + * Set separator string for displaying errors + * + * @param string $string + * @return Zend_View_Helper_FormErrors + */ + public function setElementSeparator($string) + { + $this->_htmlElementSeparator = (string) $string; + return $this; + } + + /** + * Retrieve separator string for displaying errors + * + * @return string + */ + public function getElementSeparator() + { + return $this->_htmlElementSeparator; + } + + /** + * Set start string for displaying errors + * + * @param string $string + * @return Zend_View_Helper_FormErrors + */ + public function setElementStart($string) + { + $this->_htmlElementStart = (string) $string; + return $this; + } + + /** + * Retrieve start string for displaying errors + * + * @return string + */ + public function getElementStart() + { + return $this->_htmlElementStart; + } + +} diff --git a/lib/zend/Zend/View/Helper/FormFile.php b/lib/zend/Zend/View/Helper/FormFile.php new file mode 100644 index 00000000000..1ea7bfc85c7 --- /dev/null +++ b/lib/zend/Zend/View/Helper/FormFile.php @@ -0,0 +1,75 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @version $Id$ + */ + + +/** + * Abstract class for extension + */ +require_once 'Zend/View/Helper/FormElement.php'; + + +/** + * Helper to generate a "file" element + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_View_Helper_FormFile extends Zend_View_Helper_FormElement +{ + /** + * Generates a 'file' element. + * + * @access public + * + * @param string|array $name If a string, the element name. If an + * array, all other parameters are ignored, and the array elements + * are extracted in place of added parameters. + * + * @param array $attribs Attributes for the element tag. + * + * @return string The element XHTML. + */ + public function formFile($name, $attribs = null) + { + $info = $this->_getInfo($name, null, $attribs); + extract($info); // name, id, value, attribs, options, listsep, disable + + // is it disabled? + $disabled = ''; + if ($disable) { + $disabled = ' disabled="disabled"'; + } + + // build the element + $xhtml = '<input type="file"' + . ' name="' . $this->view->escape($name) . '"' + . ' id="' . $this->view->escape($id) . '"' + . $disabled + . $this->_htmlAttribs($attribs) + . $this->getClosingBracket(); + + return $xhtml; + } +} diff --git a/lib/zend/Zend/View/Helper/FormHidden.php b/lib/zend/Zend/View/Helper/FormHidden.php new file mode 100644 index 00000000000..fbd2b7396a2 --- /dev/null +++ b/lib/zend/Zend/View/Helper/FormHidden.php @@ -0,0 +1,66 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @version $Id$ + */ + + +/** + * Abstract class for extension + */ +require_once 'Zend/View/Helper/FormElement.php'; + + +/** + * Helper to generate a "hidden" element + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_View_Helper_FormHidden extends Zend_View_Helper_FormElement +{ + /** + * Generates a 'hidden' element. + * + * @access public + * + * @param string|array $name If a string, the element name. If an + * array, all other parameters are ignored, and the array elements + * are extracted in place of added parameters. + * @param mixed $value The element value. + * @param array $attribs Attributes for the element tag. + * @return string The element XHTML. + */ + public function formHidden($name, $value = null, array $attribs = null) + { + $info = $this->_getInfo($name, $value, $attribs); + extract($info); // name, value, attribs, options, listsep, disable + if (isset($id)) { + if (isset($attribs) && is_array($attribs)) { + $attribs['id'] = $id; + } else { + $attribs = array('id' => $id); + } + } + return $this->_hidden($name, $value, $attribs); + } +} diff --git a/lib/zend/Zend/View/Helper/FormImage.php b/lib/zend/Zend/View/Helper/FormImage.php new file mode 100644 index 00000000000..be3daa3d074 --- /dev/null +++ b/lib/zend/Zend/View/Helper/FormImage.php @@ -0,0 +1,95 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @version $Id$ + */ + + +/** + * Abstract class for extension + */ +require_once 'Zend/View/Helper/FormElement.php'; + + +/** + * Helper to generate an "image" element + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_View_Helper_FormImage extends Zend_View_Helper_FormElement +{ + /** + * Generates an 'image' element. + * + * @access public + * + * @param string|array $name If a string, the element name. If an + * array, all other parameters are ignored, and the array elements + * are extracted in place of added parameters. + * + * @param mixed $value The source ('src="..."') for the image. + * + * @param array $attribs Attributes for the element tag. + * + * @return string The element XHTML. + */ + public function formImage($name, $value = null, $attribs = null) + { + $info = $this->_getInfo($name, $value, $attribs); + extract($info); // name, value, attribs, options, listsep, disable + + // Determine if we should use the value or the src attribute + if (isset($attribs['src'])) { + $src = ' src="' . $this->view->escape($attribs['src']) . '"'; + unset($attribs['src']); + } else { + $src = ' src="' . $this->view->escape($value) . '"'; + unset($value); + } + + // Do we have a value? + if (isset($value) && !empty($value)) { + $value = ' value="' . $this->view->escape($value) . '"'; + } else { + $value = ''; + } + + // Disabled? + $disabled = ''; + if ($disable) { + $disabled = ' disabled="disabled"'; + } + + // build the element + $xhtml = '<input type="image"' + . ' name="' . $this->view->escape($name) . '"' + . ' id="' . $this->view->escape($id) . '"' + . $src + . $value + . $disabled + . $this->_htmlAttribs($attribs) + . $this->getClosingBracket(); + + return $xhtml; + } +} diff --git a/lib/zend/Zend/View/Helper/FormLabel.php b/lib/zend/Zend/View/Helper/FormLabel.php new file mode 100644 index 00000000000..f4e034f9bba --- /dev/null +++ b/lib/zend/Zend/View/Helper/FormLabel.php @@ -0,0 +1,72 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @version $Id$ + */ + +/** Zend_View_Helper_FormElement **/ +require_once 'Zend/View/Helper/FormElement.php'; + +/** + * Form label helper + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_View_Helper_FormLabel extends Zend_View_Helper_FormElement +{ + /** + * Generates a 'label' element. + * + * @param string $name The form element name for which the label is being generated + * @param string $value The label text + * @param array $attribs Form element attributes (used to determine if disabled) + * @return string The element XHTML. + */ + public function formLabel($name, $value = null, array $attribs = null) + { + $info = $this->_getInfo($name, $value, $attribs); + extract($info); // name, value, attribs, options, listsep, disable, escape + + // build the element + if ($disable) { + // disabled; display nothing + return ''; + } + + $value = ($escape) ? $this->view->escape($value) : $value; + $for = (empty($attribs['disableFor']) || !$attribs['disableFor']) + ? ' for="' . $this->view->escape($id) . '"' + : ''; + if (array_key_exists('disableFor', $attribs)) { + unset($attribs['disableFor']); + } + + // enabled; display label + $xhtml = '<label' + . $for + . $this->_htmlAttribs($attribs) + . '>' . $value . '</label>'; + + return $xhtml; + } +} diff --git a/lib/zend/Zend/View/Helper/FormMultiCheckbox.php b/lib/zend/Zend/View/Helper/FormMultiCheckbox.php new file mode 100644 index 00000000000..49386cc4541 --- /dev/null +++ b/lib/zend/Zend/View/Helper/FormMultiCheckbox.php @@ -0,0 +1,74 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @version $Id$ + */ + + +/** Zend_View_Helper_FormRadio */ +require_once 'Zend/View/Helper/FormRadio.php'; + + +/** + * Helper to generate a set of checkbox button elements + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_View_Helper_FormMultiCheckbox extends Zend_View_Helper_FormRadio +{ + /** + * Input type to use + * @var string + */ + protected $_inputType = 'checkbox'; + + /** + * Whether or not this element represents an array collection by default + * @var bool + */ + protected $_isArray = true; + + /** + * Generates a set of checkbox button elements. + * + * @access public + * + * @param string|array $name If a string, the element name. If an + * array, all other parameters are ignored, and the array elements + * are extracted in place of added parameters. + * + * @param mixed $value The checkbox value to mark as 'checked'. + * + * @param array $options An array of key-value pairs where the array + * key is the checkbox value, and the array value is the radio text. + * + * @param array|string $attribs Attributes added to each radio. + * + * @return string The radio buttons XHTML. + */ + public function formMultiCheckbox($name, $value = null, $attribs = null, + $options = null, $listsep = "<br />\n") + { + return $this->formRadio($name, $value, $attribs, $options, $listsep); + } +} diff --git a/lib/zend/Zend/View/Helper/FormNote.php b/lib/zend/Zend/View/Helper/FormNote.php new file mode 100644 index 00000000000..e051fdcc311 --- /dev/null +++ b/lib/zend/Zend/View/Helper/FormNote.php @@ -0,0 +1,61 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @version $Id$ + */ + + +/** + * Abstract class for extension + */ +require_once 'Zend/View/Helper/FormElement.php'; + + +/** + * Helper to show an HTML note + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_View_Helper_FormNote extends Zend_View_Helper_FormElement +{ + /** + * Helper to show a "note" based on a hidden value. + * + * @access public + * + * @param string|array $name If a string, the element name. If an + * array, all other parameters are ignored, and the array elements + * are extracted in place of added parameters. + * + * @param array $value The note to display. HTML is *not* escaped; the + * note is displayed as-is. + * + * @return string The element XHTML. + */ + public function formNote($name, $value = null) + { + $info = $this->_getInfo($name, $value); + extract($info); // name, value, attribs, options, listsep, disable + return $value; + } +} diff --git a/lib/zend/Zend/View/Helper/FormPassword.php b/lib/zend/Zend/View/Helper/FormPassword.php new file mode 100644 index 00000000000..cb42c4b75c1 --- /dev/null +++ b/lib/zend/Zend/View/Helper/FormPassword.php @@ -0,0 +1,89 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @version $Id$ + */ + + +/** + * Abstract class for extension + */ +require_once 'Zend/View/Helper/FormElement.php'; + + +/** + * Helper to generate a "password" element + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_View_Helper_FormPassword extends Zend_View_Helper_FormElement +{ + /** + * Generates a 'password' element. + * + * @access public + * + * @param string|array $name If a string, the element name. If an + * array, all other parameters are ignored, and the array elements + * are extracted in place of added parameters. + * + * @param mixed $value The element value. + * + * @param array $attribs Attributes for the element tag. + * + * @return string The element XHTML. + */ + public function formPassword($name, $value = null, $attribs = null) + { + $info = $this->_getInfo($name, $value, $attribs); + extract($info); // name, value, attribs, options, listsep, disable + + // is it disabled? + $disabled = ''; + if ($disable) { + // disabled + $disabled = ' disabled="disabled"'; + } + + // determine the XHTML value + $valueString = ' value=""'; + if (array_key_exists('renderPassword', $attribs)) { + if ($attribs['renderPassword']) { + $valueString = ' value="' . $this->view->escape($value) . '"'; + } + unset($attribs['renderPassword']); + } + + // render the element + $xhtml = '<input type="password"' + . ' name="' . $this->view->escape($name) . '"' + . ' id="' . $this->view->escape($id) . '"' + . $valueString + . $disabled + . $this->_htmlAttribs($attribs) + . $this->getClosingBracket(); + + return $xhtml; + } + +} diff --git a/lib/zend/Zend/View/Helper/FormRadio.php b/lib/zend/Zend/View/Helper/FormRadio.php new file mode 100644 index 00000000000..fa26a076b45 --- /dev/null +++ b/lib/zend/Zend/View/Helper/FormRadio.php @@ -0,0 +1,187 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @version $Id$ + */ + + +/** + * Abstract class for extension + */ +require_once 'Zend/View/Helper/FormElement.php'; + + +/** + * Helper to generate a set of radio button elements + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_View_Helper_FormRadio extends Zend_View_Helper_FormElement +{ + /** + * Input type to use + * @var string + */ + protected $_inputType = 'radio'; + + /** + * Whether or not this element represents an array collection by default + * @var bool + */ + protected $_isArray = false; + + /** + * Generates a set of radio button elements. + * + * @access public + * + * @param string|array $name If a string, the element name. If an + * array, all other parameters are ignored, and the array elements + * are extracted in place of added parameters. + * + * @param mixed $value The radio value to mark as 'checked'. + * + * @param array $options An array of key-value pairs where the array + * key is the radio value, and the array value is the radio text. + * + * @param array|string $attribs Attributes added to each radio. + * + * @return string The radio buttons XHTML. + */ + public function formRadio($name, $value = null, $attribs = null, + $options = null, $listsep = "<br />\n") + { + + $info = $this->_getInfo($name, $value, $attribs, $options, $listsep); + extract($info); // name, value, attribs, options, listsep, disable + + // retrieve attributes for labels (prefixed with 'label_' or 'label') + $label_attribs = array(); + foreach ($attribs as $key => $val) { + $tmp = false; + $keyLen = strlen($key); + if ((6 < $keyLen) && (substr($key, 0, 6) == 'label_')) { + $tmp = substr($key, 6); + } elseif ((5 < $keyLen) && (substr($key, 0, 5) == 'label')) { + $tmp = substr($key, 5); + } + + if ($tmp) { + // make sure first char is lowercase + $tmp[0] = strtolower($tmp[0]); + $label_attribs[$tmp] = $val; + unset($attribs[$key]); + } + } + + $labelPlacement = 'append'; + foreach ($label_attribs as $key => $val) { + switch (strtolower($key)) { + case 'placement': + unset($label_attribs[$key]); + $val = strtolower($val); + if (in_array($val, array('prepend', 'append'))) { + $labelPlacement = $val; + } + break; + } + } + + // the radio button values and labels + $options = (array) $options; + + // build the element + $xhtml = ''; + $list = array(); + + // should the name affect an array collection? + $name = $this->view->escape($name); + if ($this->_isArray && ('[]' != substr($name, -2))) { + $name .= '[]'; + } + + // ensure value is an array to allow matching multiple times + $value = (array) $value; + + // Set up the filter - Alnum + hyphen + underscore + require_once 'Zend/Filter/PregReplace.php'; + $pattern = @preg_match('/\pL/u', 'a') + ? '/[^\p{L}\p{N}\-\_]/u' // Unicode + : '/[^a-zA-Z0-9\-\_]/'; // No Unicode + $filter = new Zend_Filter_PregReplace($pattern, ""); + + // add radio buttons to the list. + foreach ($options as $opt_value => $opt_label) { + + // Should the label be escaped? + if ($escape) { + $opt_label = $this->view->escape($opt_label); + } + + // is it disabled? + $disabled = ''; + if (true === $disable) { + $disabled = ' disabled="disabled"'; + } elseif (is_array($disable) && in_array($opt_value, $disable)) { + $disabled = ' disabled="disabled"'; + } + + // is it checked? + $checked = ''; + if (in_array($opt_value, $value)) { + $checked = ' checked="checked"'; + } + + // generate ID + $optId = $id . '-' . $filter->filter($opt_value); + + // Wrap the radios in labels + $radio = '<label' + . $this->_htmlAttribs($label_attribs) . '>' + . (('prepend' == $labelPlacement) ? $opt_label : '') + . '<input type="' . $this->_inputType . '"' + . ' name="' . $name . '"' + . ' id="' . $optId . '"' + . ' value="' . $this->view->escape($opt_value) . '"' + . $checked + . $disabled + . $this->_htmlAttribs($attribs) + . $this->getClosingBracket() + . (('append' == $labelPlacement) ? $opt_label : '') + . '</label>'; + + // add to the array of radio buttons + $list[] = $radio; + } + + // XHTML or HTML for standard list separator? + if (!$this->_isXhtml() && false !== strpos($listsep, '<br />')) { + $listsep = str_replace('<br />', '<br>', $listsep); + } + + // done! + $xhtml .= implode($listsep, $list); + + return $xhtml; + } +} diff --git a/lib/zend/Zend/View/Helper/FormReset.php b/lib/zend/Zend/View/Helper/FormReset.php new file mode 100644 index 00000000000..a4e62826dea --- /dev/null +++ b/lib/zend/Zend/View/Helper/FormReset.php @@ -0,0 +1,82 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @version $Id$ + */ + + +/** + * Abstract class for extension + */ +require_once 'Zend/View/Helper/FormElement.php'; + + +/** + * Helper to generate a "reset" button + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_View_Helper_FormReset extends Zend_View_Helper_FormElement +{ + /** + * Generates a 'reset' button. + * + * @access public + * + * @param string|array $name If a string, the element name. If an + * array, all other parameters are ignored, and the array elements + * are extracted in place of added parameters. + * + * @param mixed $value The element value. + * + * @param array $attribs Attributes for the element tag. + * + * @return string The element XHTML. + */ + public function formReset($name = '', $value = 'Reset', $attribs = null) + { + $info = $this->_getInfo($name, $value, $attribs); + extract($info); // name, value, attribs, options, listsep, disable + + // check if disabled + $disabled = ''; + if ($disable) { + $disabled = ' disabled="disabled"'; + } + + // Render button + $xhtml = '<input type="reset"' + . ' name="' . $this->view->escape($name) . '"' + . ' id="' . $this->view->escape($id) . '"' + . $disabled; + + // add a value if one is given + if (! empty($value)) { + $xhtml .= ' value="' . $this->view->escape($value) . '"'; + } + + // add attributes, close, and return + $xhtml .= $this->_htmlAttribs($attribs) . $this->getClosingBracket(); + return $xhtml; + } +} diff --git a/lib/zend/Zend/View/Helper/FormSelect.php b/lib/zend/Zend/View/Helper/FormSelect.php new file mode 100644 index 00000000000..8654f3d0e7b --- /dev/null +++ b/lib/zend/Zend/View/Helper/FormSelect.php @@ -0,0 +1,200 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @version $Id$ + */ + + +/** + * Abstract class for extension + */ +require_once 'Zend/View/Helper/FormElement.php'; + + +/** + * Helper to generate "select" list of options + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_View_Helper_FormSelect extends Zend_View_Helper_FormElement +{ + /** + * Generates 'select' list of options. + * + * @access public + * + * @param string|array $name If a string, the element name. If an + * array, all other parameters are ignored, and the array elements + * are extracted in place of added parameters. + * + * @param mixed $value The option value to mark as 'selected'; if an + * array, will mark all values in the array as 'selected' (used for + * multiple-select elements). + * + * @param array|string $attribs Attributes added to the 'select' tag. + * the optional 'optionClasses' attribute is used to add a class to + * the options within the select (associative array linking the option + * value to the desired class) + * + * @param array $options An array of key-value pairs where the array + * key is the radio value, and the array value is the radio text. + * + * @param string $listsep When disabled, use this list separator string + * between list values. + * + * @return string The select tag and options XHTML. + */ + public function formSelect($name, $value = null, $attribs = null, + $options = null, $listsep = "<br />\n") + { + $info = $this->_getInfo($name, $value, $attribs, $options, $listsep); + extract($info); // name, id, value, attribs, options, listsep, disable + + // force $value to array so we can compare multiple values to multiple + // options; also ensure it's a string for comparison purposes. + $value = array_map('strval', (array) $value); + + // check if element may have multiple values + $multiple = ''; + + if (substr($name, -2) == '[]') { + // multiple implied by the name + $multiple = ' multiple="multiple"'; + } + + if (isset($attribs['multiple'])) { + // Attribute set + if ($attribs['multiple']) { + // True attribute; set multiple attribute + $multiple = ' multiple="multiple"'; + + // Make sure name indicates multiple values are allowed + if (!empty($multiple) && (substr($name, -2) != '[]')) { + $name .= '[]'; + } + } else { + // False attribute; ensure attribute not set + $multiple = ''; + } + unset($attribs['multiple']); + } + + // handle the options classes + $optionClasses = array(); + if (isset($attribs['optionClasses'])) { + $optionClasses = $attribs['optionClasses']; + unset($attribs['optionClasses']); + } + + // now start building the XHTML. + $disabled = ''; + if (true === $disable) { + $disabled = ' disabled="disabled"'; + } + + // Build the surrounding select element first. + $xhtml = '<select' + . ' name="' . $this->view->escape($name) . '"' + . ' id="' . $this->view->escape($id) . '"' + . $multiple + . $disabled + . $this->_htmlAttribs($attribs) + . ">\n "; + + // build the list of options + $list = array(); + $translator = $this->getTranslator(); + foreach ((array) $options as $opt_value => $opt_label) { + if (is_array($opt_label)) { + $opt_disable = ''; + if (is_array($disable) && in_array($opt_value, $disable)) { + $opt_disable = ' disabled="disabled"'; + } + if (null !== $translator) { + $opt_value = $translator->translate($opt_value); + } + $opt_id = ' id="' . $this->view->escape($id) . '-optgroup-' + . $this->view->escape($opt_value) . '"'; + $list[] = '<optgroup' + . $opt_disable + . $opt_id + . ' label="' . $this->view->escape($opt_value) .'">'; + foreach ($opt_label as $val => $lab) { + $list[] = $this->_build($val, $lab, $value, $disable, $optionClasses); + } + $list[] = '</optgroup>'; + } else { + $list[] = $this->_build($opt_value, $opt_label, $value, $disable, $optionClasses); + } + } + + // add the options to the xhtml and close the select + $xhtml .= implode("\n ", $list) . "\n</select>"; + + return $xhtml; + } + + /** + * Builds the actual <option> tag + * + * @param string $value Options Value + * @param string $label Options Label + * @param array $selected The option value(s) to mark as 'selected' + * @param array|bool $disable Whether the select is disabled, or individual options are + * @param array $optionClasses The classes to associate with each option value + * @return string Option Tag XHTML + */ + protected function _build($value, $label, $selected, $disable, $optionClasses = array()) + { + if (is_bool($disable)) { + $disable = array(); + } + + $class = null; + if (array_key_exists($value, $optionClasses)) { + $class = $optionClasses[$value]; + } + + + $opt = '<option' + . ' value="' . $this->view->escape($value) . '"'; + + if ($class) { + $opt .= ' class="' . $class . '"'; + } + // selected? + if (in_array((string) $value, $selected)) { + $opt .= ' selected="selected"'; + } + + // disabled? + if (in_array($value, $disable)) { + $opt .= ' disabled="disabled"'; + } + + $opt .= '>' . $this->view->escape($label) . "</option>"; + + return $opt; + } + +} diff --git a/lib/zend/Zend/View/Helper/FormSubmit.php b/lib/zend/Zend/View/Helper/FormSubmit.php new file mode 100644 index 00000000000..72223e203e3 --- /dev/null +++ b/lib/zend/Zend/View/Helper/FormSubmit.php @@ -0,0 +1,81 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @version $Id$ + */ + + +/** + * Abstract class for extension + */ +require_once 'Zend/View/Helper/FormElement.php'; + + +/** + * Helper to generate a "submit" button + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_View_Helper_FormSubmit extends Zend_View_Helper_FormElement +{ + /** + * Generates a 'submit' button. + * + * @access public + * + * @param string|array $name If a string, the element name. If an + * array, all other parameters are ignored, and the array elements + * are extracted in place of added parameters. + * + * @param mixed $value The element value. + * + * @param array $attribs Attributes for the element tag. + * + * @return string The element XHTML. + */ + public function formSubmit($name, $value = null, $attribs = null) + { + $info = $this->_getInfo($name, $value, $attribs); + extract($info); // name, value, attribs, options, listsep, disable, id + // check if disabled + $disabled = ''; + if ($disable) { + $disabled = ' disabled="disabled"'; + } + + if ($id) { + $id = ' id="' . $this->view->escape($id) . '"'; + } + + // Render the button. + $xhtml = '<input type="submit"' + . ' name="' . $this->view->escape($name) . '"' + . $id + . ' value="' . $this->view->escape($value) . '"' + . $disabled + . $this->_htmlAttribs($attribs) + . $this->getClosingBracket(); + + return $xhtml; + } +} diff --git a/lib/zend/Zend/View/Helper/FormText.php b/lib/zend/Zend/View/Helper/FormText.php new file mode 100644 index 00000000000..9b9f58135ea --- /dev/null +++ b/lib/zend/Zend/View/Helper/FormText.php @@ -0,0 +1,78 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @version $Id$ + */ + + +/** + * Abstract class for extension + */ +require_once 'Zend/View/Helper/FormElement.php'; + + +/** + * Helper to generate a "text" element + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_View_Helper_FormText extends Zend_View_Helper_FormElement +{ + /** + * Generates a 'text' element. + * + * @access public + * + * @param string|array $name If a string, the element name. If an + * array, all other parameters are ignored, and the array elements + * are used in place of added parameters. + * + * @param mixed $value The element value. + * + * @param array $attribs Attributes for the element tag. + * + * @return string The element XHTML. + */ + public function formText($name, $value = null, $attribs = null) + { + $info = $this->_getInfo($name, $value, $attribs); + extract($info); // name, value, attribs, options, listsep, disable + + // build the element + $disabled = ''; + if ($disable) { + // disabled + $disabled = ' disabled="disabled"'; + } + + $xhtml = '<input type="text"' + . ' name="' . $this->view->escape($name) . '"' + . ' id="' . $this->view->escape($id) . '"' + . ' value="' . $this->view->escape($value) . '"' + . $disabled + . $this->_htmlAttribs($attribs) + . $this->getClosingBracket(); + + return $xhtml; + } +} diff --git a/lib/zend/Zend/View/Helper/FormTextarea.php b/lib/zend/Zend/View/Helper/FormTextarea.php new file mode 100644 index 00000000000..c384fc4da6b --- /dev/null +++ b/lib/zend/Zend/View/Helper/FormTextarea.php @@ -0,0 +1,104 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @version $Id$ + */ + + +/** + * Abstract class for extension + */ +require_once 'Zend/View/Helper/FormElement.php'; + + +/** + * Helper to generate a "textarea" element + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_View_Helper_FormTextarea extends Zend_View_Helper_FormElement +{ + /** + * The default number of rows for a textarea. + * + * @access public + * + * @var int + */ + public $rows = 24; + + /** + * The default number of columns for a textarea. + * + * @access public + * + * @var int + */ + public $cols = 80; + + /** + * Generates a 'textarea' element. + * + * @access public + * + * @param string|array $name If a string, the element name. If an + * array, all other parameters are ignored, and the array elements + * are extracted in place of added parameters. + * + * @param mixed $value The element value. + * + * @param array $attribs Attributes for the element tag. + * + * @return string The element XHTML. + */ + public function formTextarea($name, $value = null, $attribs = null) + { + $info = $this->_getInfo($name, $value, $attribs); + extract($info); // name, value, attribs, options, listsep, disable + + // is it disabled? + $disabled = ''; + if ($disable) { + // disabled. + $disabled = ' disabled="disabled"'; + } + + // Make sure that there are 'rows' and 'cols' values + // as required by the spec. noted by Orjan Persson. + if (empty($attribs['rows'])) { + $attribs['rows'] = (int) $this->rows; + } + if (empty($attribs['cols'])) { + $attribs['cols'] = (int) $this->cols; + } + + // build the element + $xhtml = '<textarea name="' . $this->view->escape($name) . '"' + . ' id="' . $this->view->escape($id) . '"' + . $disabled + . $this->_htmlAttribs($attribs) . '>' + . $this->view->escape($value) . '</textarea>'; + + return $xhtml; + } +} diff --git a/lib/zend/Zend/View/Helper/Gravatar.php b/lib/zend/Zend/View/Helper/Gravatar.php new file mode 100644 index 00000000000..dab1f799f62 --- /dev/null +++ b/lib/zend/Zend/View/Helper/Gravatar.php @@ -0,0 +1,363 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com) + * @version $Id: Doctype.php 16971 2009-07-22 18:05:45Z mikaelkael $ + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +/** Zend_View_Helper_HtmlElement */ +require_once 'Zend/View/Helper/HtmlElement.php'; + +/** + * Helper for retrieving avatars from gravatar.com + * + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @link http://pl.gravatar.com/site/implement/url + */ +class Zend_View_Helper_Gravatar extends Zend_View_Helper_HtmlElement +{ + + /** + * URL to gravatar service + */ + const GRAVATAR_URL = 'http://www.gravatar.com/avatar'; + /** + * Secure URL to gravatar service + */ + const GRAVATAR_URL_SECURE = 'https://secure.gravatar.com/avatar'; + + /** + * Gravatar rating + */ + const RATING_G = 'g'; + const RATING_PG = 'pg'; + const RATING_R = 'r'; + const RATING_X = 'x'; + + /** + * Default gravatar image value constants + */ + const DEFAULT_404 = '404'; + const DEFAULT_MM = 'mm'; + const DEFAULT_IDENTICON = 'identicon'; + const DEFAULT_MONSTERID = 'monsterid'; + const DEFAULT_WAVATAR = 'wavatar'; + + /** + * Options + * + * @var array + */ + protected $_options = array( + 'img_size' => 80, + 'default_img' => self::DEFAULT_MM, + 'rating' => self::RATING_G, + 'secure' => null, + ); + + /** + * Email Adress + * + * @var string + */ + protected $_email; + + /** + * Attributes for HTML image tag + * + * @var array + */ + protected $_attribs; + + /** + * Returns an avatar from gravatar's service. + * + * $options may include the following: + * - 'img_size' int height of img to return + * - 'default_img' string img to return if email adress has not found + * - 'rating' string rating parameter for avatar + * - 'secure' bool load from the SSL or Non-SSL location + * + * @see http://pl.gravatar.com/site/implement/url + * @see http://pl.gravatar.com/site/implement/url More information about gravatar's service. + * @param string|null $email Email adress. + * @param null|array $options Options + * @param array $attribs Attributes for image tag (title, alt etc.) + * @return Zend_View_Helper_Gravatar + */ + public function gravatar($email = "", $options = array(), $attribs = array()) + { + $this->setEmail($email); + $this->setOptions($options); + $this->setAttribs($attribs); + return $this; + } + + /** + * Configure state + * + * @param array $options + * @return Zend_View_Helper_Gravatar + */ + public function setOptions(array $options) + { + foreach ($options as $key => $value) { + $method = 'set' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key))); + if (method_exists($this, $method)) { + $this->{$method}($value); + } + } + return $this; + } + + /** + * Get img size + * + * @return int The img size + */ + public function getImgSize() + { + return $this->_options['img_size']; + } + + /** + * Set img size in pixels + * + * @param int $imgSize Size of img must be between 1 and 512 + * @return Zend_View_Helper_Gravatar + */ + public function setImgSize($imgSize) + { + $this->_options['img_size'] = (int) $imgSize; + return $this; + } + + /** + * Get default img + * + * @return string + */ + public function getDefaultImg() + { + return $this->_options['default_img']; + } + + /** + * Set default img + * + * Can be either an absolute URL to an image, or one of the DEFAULT_* constants + * + * @param string $defaultImg + * @link http://pl.gravatar.com/site/implement/url More information about default image. + * @return Zend_View_Helper_Gravatar + */ + public function setDefaultImg($defaultImg) + { + $this->_options['default_img'] = urlencode($defaultImg); + return $this; + } + + /** + * Set rating value + * + * Must be one of the RATING_* constants + * + * @param string $rating Value for rating. Allowed values are: g, px, r,x + * @link http://pl.gravatar.com/site/implement/url More information about rating. + * @throws Zend_View_Exception + */ + public function setRating($rating) + { + switch ($rating) { + case self::RATING_G: + case self::RATING_PG: + case self::RATING_R: + case self::RATING_X: + $this->_options['rating'] = $rating; + break; + default: + require_once 'Zend/View/Exception.php'; + throw new Zend_View_Exception(sprintf( + 'The rating value "%s" is not allowed', + $rating + )); + } + return $this; + } + + /** + * Get rating value + * + * @return string + */ + public function getRating() + { + return $this->_options['rating']; + } + + /** + * Set email adress + * + * @param string $email + * @return Zend_View_Helper_Gravatar + */ + public function setEmail( $email ) + { + $this->_email = $email; + return $this; + } + + /** + * Get email adress + * + * @return string + */ + public function getEmail() + { + return $this->_email; + } + + /** + * Load from an SSL or No-SSL location? + * + * @param bool $flag + * @return Zend_View_Helper_Gravatar + */ + public function setSecure($flag) + { + $this->_options['secure'] = ($flag === null) ? null : (bool) $flag; + return $this; + } + + /** + * Get an SSL or a No-SSL location + * + * @return bool + */ + public function getSecure() + { + if ($this->_options['secure'] === null) { + return (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off'); + } + return $this->_options['secure']; + } + + /** + * Get attribs of image + * + * Warning! + * If you set src attrib, you get it, but this value will be overwritten in + * protected method _setSrcAttribForImg(). And finally your get other src + * value! + * + * @return array + */ + public function getAttribs() + { + return $this->_attribs; + } + + /** + * Set attribs for image tag + * + * Warning! You shouldn't set src attrib for image tag. + * This attrib is overwritten in protected method _setSrcAttribForImg(). + * This method(_setSrcAttribForImg) is called in public method getImgTag(). + + * @param array $attribs + * @return Zend_View_Helper_Gravatar + */ + public function setAttribs(array $attribs) + { + $this->_attribs = $attribs; + return $this; + } + + /** + * Get URL to gravatar's service. + * + * @return string URL + */ + protected function _getGravatarUrl() + { + return ($this->getSecure() === false) ? self::GRAVATAR_URL : self::GRAVATAR_URL_SECURE; + } + + /** + * Get avatar url (including size, rating and default image oprions) + * + * @return string + */ + protected function _getAvatarUrl() + { + $src = $this->_getGravatarUrl() + . '/' + . md5(strtolower(trim($this->getEmail()))) + . '?s=' + . $this->getImgSize() + . '&d=' + . $this->getDefaultImg() + . '&r=' + . $this->getRating(); + return $src; + } + + /** + * Set src attrib for image. + * + * You shouldn't set a own url value! + * It sets value, uses protected method _getAvatarUrl. + * + * If already exsist overwritten. + */ + protected function _setSrcAttribForImg() + { + $attribs = $this->getAttribs(); + $attribs['src'] = $this->_getAvatarUrl(); + $this->setAttribs($attribs); + } + + /** + * Return valid image tag + * + * @return string + */ + public function getImgTag() + { + $this->_setSrcAttribForImg(); + $html = '<img' + . $this->_htmlAttribs($this->getAttribs()) + . $this->getClosingBracket(); + + return $html; + } + + /** + * Return valid image tag + * + * @return string + */ + public function __toString() + { + return $this->getImgTag(); + + } +} diff --git a/lib/zend/Zend/View/Helper/HeadLink.php b/lib/zend/Zend/View/Helper/HeadLink.php new file mode 100644 index 00000000000..61bf0a29d3b --- /dev/null +++ b/lib/zend/Zend/View/Helper/HeadLink.php @@ -0,0 +1,478 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @version $Id$ + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +/** Zend_View_Helper_Placeholder_Container_Standalone */ +require_once 'Zend/View/Helper/Placeholder/Container/Standalone.php'; + +/** + * Zend_Layout_View_Helper_HeadLink + * + * @see http://www.w3.org/TR/xhtml1/dtds.html + * @uses Zend_View_Helper_Placeholder_Container_Standalone + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @method $this appendAlternate($href, $type, $title, $extras) + * @method $this appendStylesheet($href, $media = 'screen', $conditionalStylesheet = false, array $extras = array()) + * @method $this offsetSetAlternate($index, $href, $type, $title, $extras) + * @method $this offsetSetStylesheet($index, $href, $media = 'screen', $conditionalStylesheet = false, array $extras = array()) + * @method $this prependAlternate($href, $type, $title, $extras) + * @method $this prependStylesheet($href, $media = 'screen', $conditionalStylesheet = false, array $extras = array()) + * @method $this setAlternate($href, $type, $title, $extras) + * @method $this setStylesheet($href, $media = 'screen', $conditionalStylesheet = false, array $extras = array()) + */ +class Zend_View_Helper_HeadLink extends Zend_View_Helper_Placeholder_Container_Standalone +{ + /** + * $_validAttributes + * + * @var array + */ + protected $_itemKeys = array( + 'charset', + 'href', + 'hreflang', + 'id', + 'media', + 'rel', + 'rev', + 'type', + 'title', + 'extras', + 'sizes', + ); + + /** + * @var string registry key + */ + protected $_regKey = 'Zend_View_Helper_HeadLink'; + + /** + * Constructor + * + * Use PHP_EOL as separator + * + * @return void + */ + public function __construct() + { + parent::__construct(); + $this->setSeparator(PHP_EOL); + } + + /** + * headLink() - View Helper Method + * + * Returns current object instance. Optionally, allows passing array of + * values to build link. + * + * @return Zend_View_Helper_HeadLink + */ + public function headLink(array $attributes = null, $placement = Zend_View_Helper_Placeholder_Container_Abstract::APPEND) + { + if (null !== $attributes) { + $item = $this->createData($attributes); + switch ($placement) { + case Zend_View_Helper_Placeholder_Container_Abstract::SET: + $this->set($item); + break; + case Zend_View_Helper_Placeholder_Container_Abstract::PREPEND: + $this->prepend($item); + break; + case Zend_View_Helper_Placeholder_Container_Abstract::APPEND: + default: + $this->append($item); + break; + } + } + return $this; + } + + /** + * Overload method access + * + * Creates the following virtual methods: + * - appendStylesheet($href, $media, $conditionalStylesheet, $extras) + * - offsetSetStylesheet($index, $href, $media, $conditionalStylesheet, $extras) + * - prependStylesheet($href, $media, $conditionalStylesheet, $extras) + * - setStylesheet($href, $media, $conditionalStylesheet, $extras) + * - appendAlternate($href, $type, $title, $extras) + * - offsetSetAlternate($index, $href, $type, $title, $extras) + * - prependAlternate($href, $type, $title, $extras) + * - setAlternate($href, $type, $title, $extras) + * + * Items that may be added in the future: + * - Navigation? need to find docs on this + * - public function appendStart() + * - public function appendContents() + * - public function appendPrev() + * - public function appendNext() + * - public function appendIndex() + * - public function appendEnd() + * - public function appendGlossary() + * - public function appendAppendix() + * - public function appendHelp() + * - public function appendBookmark() + * - Other? + * - public function appendCopyright() + * - public function appendChapter() + * - public function appendSection() + * - public function appendSubsection() + * + * @param mixed $method + * @param mixed $args + * @return void + */ + public function __call($method, $args) + { + if (preg_match('/^(?P<action>set|(ap|pre)pend|offsetSet)(?P<type>Stylesheet|Alternate)$/', $method, $matches)) { + $argc = count($args); + $action = $matches['action']; + $type = $matches['type']; + $index = null; + + if ('offsetSet' == $action) { + if (0 < $argc) { + $index = array_shift($args); + --$argc; + } + } + + if (1 > $argc) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception(sprintf('%s requires at least one argument', $method)); + $e->setView($this->view); + throw $e; + } + + if (is_array($args[0])) { + $item = $this->createData($args[0]); + } else { + $dataMethod = 'createData' . $type; + $item = $this->$dataMethod($args); + } + + if ($item) { + if ('offsetSet' == $action) { + $this->offsetSet($index, $item); + } else { + $this->$action($item); + } + } + + return $this; + } + + return parent::__call($method, $args); + } + + /** + * Check if value is valid + * + * @param mixed $value + * @return boolean + */ + protected function _isValid($value) + { + if (!$value instanceof stdClass) { + return false; + } + + $vars = get_object_vars($value); + $keys = array_keys($vars); + $intersection = array_intersect($this->_itemKeys, $keys); + if (empty($intersection)) { + return false; + } + + return true; + } + + /** + * append() + * + * @param array $value + * @return void + */ + public function append($value) + { + if (!$this->_isValid($value)) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception('append() expects a data token; please use one of the custom append*() methods'); + $e->setView($this->view); + throw $e; + } + + return $this->getContainer()->append($value); + } + + /** + * offsetSet() + * + * @param string|int $index + * @param array $value + * @return void + */ + public function offsetSet($index, $value) + { + if (!$this->_isValid($value)) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception('offsetSet() expects a data token; please use one of the custom offsetSet*() methods'); + $e->setView($this->view); + throw $e; + } + + return $this->getContainer()->offsetSet($index, $value); + } + + /** + * prepend() + * + * @param array $value + * @return Zend_Layout_ViewHelper_HeadLink + */ + public function prepend($value) + { + if (!$this->_isValid($value)) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception('prepend() expects a data token; please use one of the custom prepend*() methods'); + $e->setView($this->view); + throw $e; + } + + return $this->getContainer()->prepend($value); + } + + /** + * set() + * + * @param array $value + * @return Zend_Layout_ViewHelper_HeadLink + */ + public function set($value) + { + if (!$this->_isValid($value)) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception('set() expects a data token; please use one of the custom set*() methods'); + $e->setView($this->view); + throw $e; + } + + return $this->getContainer()->set($value); + } + + + /** + * Create HTML link element from data item + * + * @param stdClass $item + * @return string + */ + public function itemToString(stdClass $item) + { + $attributes = (array) $item; + $link = '<link '; + + foreach ($this->_itemKeys as $itemKey) { + if (isset($attributes[$itemKey])) { + if(is_array($attributes[$itemKey])) { + foreach($attributes[$itemKey] as $key => $value) { + $link .= sprintf('%s="%s" ', $key, ($this->_autoEscape) ? $this->_escape($value) : $value); + } + } else { + $link .= sprintf('%s="%s" ', $itemKey, ($this->_autoEscape) ? $this->_escape($attributes[$itemKey]) : $attributes[$itemKey]); + } + } + } + + if ($this->view instanceof Zend_View_Abstract) { + $link .= ($this->view->doctype()->isXhtml()) ? '/>' : '>'; + } else { + $link .= '/>'; + } + + if (($link == '<link />') || ($link == '<link >')) { + return ''; + } + + if (isset($attributes['conditionalStylesheet']) + && !empty($attributes['conditionalStylesheet']) + && is_string($attributes['conditionalStylesheet'])) + { + if (str_replace(' ', '', $attributes['conditionalStylesheet']) === '!IE') { + $link = '<!-->' . $link . '<!--'; + } + $link = '<!--[if ' . $attributes['conditionalStylesheet'] . ']>' . $link . '<![endif]-->'; + } + + return $link; + } + + /** + * Render link elements as string + * + * @param string|int $indent + * @return string + */ + public function toString($indent = null) + { + $indent = (null !== $indent) + ? $this->getWhitespace($indent) + : $this->getIndent(); + + $items = array(); + $this->getContainer()->ksort(); + foreach ($this as $item) { + $items[] = $this->itemToString($item); + } + + return $indent . implode($this->_escape($this->getSeparator()) . $indent, $items); + } + + /** + * Create data item for stack + * + * @param array $attributes + * @return stdClass + */ + public function createData(array $attributes) + { + $data = (object) $attributes; + return $data; + } + + /** + * Create item for stylesheet link item + * + * @param array $args + * @return stdClass|false Returns fals if stylesheet is a duplicate + */ + public function createDataStylesheet(array $args) + { + $rel = 'stylesheet'; + $type = 'text/css'; + $media = 'screen'; + $conditionalStylesheet = false; + $href = array_shift($args); + + if ($this->_isDuplicateStylesheet($href)) { + return false; + } + + if (0 < count($args)) { + $media = array_shift($args); + if(is_array($media)) { + $media = implode(',', $media); + } else { + $media = (string) $media; + } + } + if (0 < count($args)) { + $conditionalStylesheet = array_shift($args); + if(!empty($conditionalStylesheet) && is_string($conditionalStylesheet)) { + $conditionalStylesheet = (string) $conditionalStylesheet; + } else { + $conditionalStylesheet = null; + } + } + + if(0 < count($args) && is_array($args[0])) { + $extras = array_shift($args); + $extras = (array) $extras; + } + + $attributes = compact('rel', 'type', 'href', 'media', 'conditionalStylesheet', 'extras'); + return $this->createData($this->_applyExtras($attributes)); + } + + /** + * Is the linked stylesheet a duplicate? + * + * @param string $uri + * @return bool + */ + protected function _isDuplicateStylesheet($uri) + { + foreach ($this->getContainer() as $item) { + if (($item->rel == 'stylesheet') && ($item->href == $uri)) { + return true; + } + } + return false; + } + + /** + * Create item for alternate link item + * + * @param array $args + * @return stdClass + */ + public function createDataAlternate(array $args) + { + if (3 > count($args)) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception(sprintf('Alternate tags require 3 arguments; %s provided', count($args))); + $e->setView($this->view); + throw $e; + } + + $rel = 'alternate'; + $href = array_shift($args); + $type = array_shift($args); + $title = array_shift($args); + + if(0 < count($args) && is_array($args[0])) { + $extras = array_shift($args); + $extras = (array) $extras; + + if(isset($extras['media']) && is_array($extras['media'])) { + $extras['media'] = implode(',', $extras['media']); + } + } + + $href = (string) $href; + $type = (string) $type; + $title = (string) $title; + + $attributes = compact('rel', 'href', 'type', 'title', 'extras'); + return $this->createData($this->_applyExtras($attributes)); + } + + /** + * Apply any overrides specified in the 'extras' array + * @param array $attributes + * @return array + */ + protected function _applyExtras($attributes) + { + if (isset($attributes['extras'])) { + foreach ($attributes['extras'] as $eKey=>$eVal) { + if (isset($attributes[$eKey])) { + $attributes[$eKey] = $eVal; + unset($attributes['extras'][$eKey]); + } + } + } + return $attributes; + } +} diff --git a/lib/zend/Zend/View/Helper/HeadMeta.php b/lib/zend/Zend/View/Helper/HeadMeta.php new file mode 100644 index 00000000000..de58edd5dcc --- /dev/null +++ b/lib/zend/Zend/View/Helper/HeadMeta.php @@ -0,0 +1,449 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @version $Id$ + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +/** Zend_View_Helper_Placeholder_Container_Standalone */ +require_once 'Zend/View/Helper/Placeholder/Container/Standalone.php'; + +/** + * Zend_Layout_View_Helper_HeadMeta + * + * @see http://www.w3.org/TR/xhtml1/dtds.html + * @uses Zend_View_Helper_Placeholder_Container_Standalone + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @method $this appendHttpEquiv($keyValue, $content, $conditionalHttpEquiv) + * @method $this appendName($keyValue, $content, $conditionalName) + * @method $this appendProperty($property, $content, $modifiers) + * @method $this offsetSetHttpEquiv($index, $keyValue, $content, $conditionalHttpEquiv) + * @method $this offsetSetName($index, $keyValue, $content, $conditionalName) + * @method $this offsetSetProperty($index, $property, $content, $modifiers) + * @method $this prependHttpEquiv($keyValue, $content, $conditionalHttpEquiv) + * @method $this prependName($keyValue, $content, $conditionalName) + * @method $this prependProperty($property, $content, $modifiers) + * @method $this setCharset($charset) + * @method $this setHttpEquiv($keyValue, $content, $modifiers) + * @method $this setName($keyValue, $content, $modifiers) + * @method $this setProperty($property, $content, $modifiers) + */ +class Zend_View_Helper_HeadMeta extends Zend_View_Helper_Placeholder_Container_Standalone +{ + /** + * Types of attributes + * @var array + */ + protected $_typeKeys = array('name', 'http-equiv', 'charset', 'property'); + protected $_requiredKeys = array('content'); + protected $_modifierKeys = array('lang', 'scheme'); + + /** + * @var string registry key + */ + protected $_regKey = 'Zend_View_Helper_HeadMeta'; + + /** + * Constructor + * + * Set separator to PHP_EOL + * + * @return void + */ + public function __construct() + { + parent::__construct(); + $this->setSeparator(PHP_EOL); + } + + /** + * Retrieve object instance; optionally add meta tag + * + * @param string $content + * @param string $keyValue + * @param string $keyType + * @param array $modifiers + * @param string $placement + * @return Zend_View_Helper_HeadMeta + */ + public function headMeta($content = null, $keyValue = null, $keyType = 'name', $modifiers = array(), $placement = Zend_View_Helper_Placeholder_Container_Abstract::APPEND) + { + if ((null !== $content) && (null !== $keyValue)) { + $item = $this->createData($keyType, $keyValue, $content, $modifiers); + $action = strtolower($placement); + switch ($action) { + case 'append': + case 'prepend': + case 'set': + $this->$action($item); + break; + default: + $this->append($item); + break; + } + } + + return $this; + } + + protected function _normalizeType($type) + { + switch ($type) { + case 'Name': + return 'name'; + case 'HttpEquiv': + return 'http-equiv'; + case 'Property': + return 'property'; + default: + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception(sprintf('Invalid type "%s" passed to _normalizeType', $type)); + $e->setView($this->view); + throw $e; + } + } + + /** + * Overload method access + * + * Allows the following 'virtual' methods: + * - appendName($keyValue, $content, $modifiers = array()) + * - offsetGetName($index, $keyValue, $content, $modifers = array()) + * - prependName($keyValue, $content, $modifiers = array()) + * - setName($keyValue, $content, $modifiers = array()) + * - appendHttpEquiv($keyValue, $content, $modifiers = array()) + * - offsetGetHttpEquiv($index, $keyValue, $content, $modifers = array()) + * - prependHttpEquiv($keyValue, $content, $modifiers = array()) + * - setHttpEquiv($keyValue, $content, $modifiers = array()) + * - appendProperty($keyValue, $content, $modifiers = array()) + * - offsetGetProperty($index, $keyValue, $content, $modifiers = array()) + * - prependProperty($keyValue, $content, $modifiers = array()) + * - setProperty($keyValue, $content, $modifiers = array()) + * + * @param string $method + * @param array $args + * @return Zend_View_Helper_HeadMeta + */ + public function __call($method, $args) + { + if (preg_match('/^(?P<action>set|(pre|ap)pend|offsetSet)(?P<type>Name|HttpEquiv|Property)$/', $method, $matches)) { + $action = $matches['action']; + $type = $this->_normalizeType($matches['type']); + $argc = count($args); + $index = null; + + if ('offsetSet' == $action) { + if (0 < $argc) { + $index = array_shift($args); + --$argc; + } + } + + if (2 > $argc) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception('Too few arguments provided; requires key value, and content'); + $e->setView($this->view); + throw $e; + } + + if (3 > $argc) { + $args[] = array(); + } + + $item = $this->createData($type, $args[0], $args[1], $args[2]); + + if ('offsetSet' == $action) { + return $this->offsetSet($index, $item); + } + + $this->$action($item); + return $this; + } + + return parent::__call($method, $args); + } + + /** + * Create an HTML5-style meta charset tag. Something like <meta charset="utf-8"> + * + * Not valid in a non-HTML5 doctype + * + * @param string $charset + * @return Zend_View_Helper_HeadMeta Provides a fluent interface + */ + public function setCharset($charset) + { + $item = new stdClass; + $item->type = 'charset'; + $item->charset = $charset; + $item->content = null; + $item->modifiers = array(); + $this->set($item); + return $this; + } + + /** + * Determine if item is valid + * + * @param mixed $item + * @return boolean + */ + protected function _isValid($item) + { + if ((!$item instanceof stdClass) + || !isset($item->type) + || !isset($item->modifiers)) + { + return false; + } + + $isHtml5 = is_null($this->view) ? false : $this->view->doctype()->isHtml5(); + + if (!isset($item->content) + && (! $isHtml5 || (! $isHtml5 && $item->type !== 'charset'))) { + return false; + } + + // <meta property= ... /> is only supported with doctype RDFa + if ( !is_null($this->view) && !$this->view->doctype()->isRdfa() + && $item->type === 'property') { + return false; + } + + return true; + } + + /** + * Append + * + * @param string $value + * @return void + * @throws Zend_View_Exception + */ + public function append($value) + { + if (!$this->_isValid($value)) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception('Invalid value passed to append; please use appendMeta()'); + $e->setView($this->view); + throw $e; + } + + return $this->getContainer()->append($value); + } + + /** + * OffsetSet + * + * @param string|int $index + * @param string $value + * @return void + * @throws Zend_View_Exception + */ + public function offsetSet($index, $value) + { + if (!$this->_isValid($value)) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception('Invalid value passed to offsetSet; please use offsetSetName() or offsetSetHttpEquiv()'); + $e->setView($this->view); + throw $e; + } + + return $this->getContainer()->offsetSet($index, $value); + } + + /** + * OffsetUnset + * + * @param string|int $index + * @return void + * @throws Zend_View_Exception + */ + public function offsetUnset($index) + { + if (!in_array($index, $this->getContainer()->getKeys())) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception('Invalid index passed to offsetUnset()'); + $e->setView($this->view); + throw $e; + } + + return $this->getContainer()->offsetUnset($index); + } + + /** + * Prepend + * + * @param string $value + * @return void + * @throws Zend_View_Exception + */ + public function prepend($value) + { + if (!$this->_isValid($value)) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception('Invalid value passed to prepend; please use prependMeta()'); + $e->setView($this->view); + throw $e; + } + + return $this->getContainer()->prepend($value); + } + + /** + * Set + * + * @param string $value + * @return void + * @throws Zend_View_Exception + */ + public function set($value) + { + if (!$this->_isValid($value)) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception('Invalid value passed to set; please use setMeta()'); + $e->setView($this->view); + throw $e; + } + + $container = $this->getContainer(); + foreach ($container->getArrayCopy() as $index => $item) { + if ($item->type == $value->type && $item->{$item->type} == $value->{$value->type}) { + $this->offsetUnset($index); + } + } + + return $this->append($value); + } + + /** + * Build meta HTML string + * + * @param string $type + * @param string $typeValue + * @param string $content + * @param array $modifiers + * @return string + */ + public function itemToString(stdClass $item) + { + if (!in_array($item->type, $this->_typeKeys)) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception(sprintf('Invalid type "%s" provided for meta', $item->type)); + $e->setView($this->view); + throw $e; + } + $type = $item->type; + + $modifiersString = ''; + foreach ($item->modifiers as $key => $value) { + if (!is_null($this->view) && $this->view->doctype()->isHtml5() + && $key == 'scheme') { + require_once 'Zend/View/Exception.php'; + throw new Zend_View_Exception('Invalid modifier ' + . '"scheme" provided; not supported by HTML5'); + } + if (!in_array($key, $this->_modifierKeys)) { + continue; + } + $modifiersString .= $key . '="' . $this->_escape($value) . '" '; + } + + if ($this->view instanceof Zend_View_Abstract) { + if ($this->view->doctype()->isHtml5() + && $type == 'charset') { + $tpl = ($this->view->doctype()->isXhtml()) + ? '<meta %s="%s"/>' + : '<meta %s="%s">'; + } elseif ($this->view->doctype()->isXhtml()) { + $tpl = '<meta %s="%s" content="%s" %s/>'; + } else { + $tpl = '<meta %s="%s" content="%s" %s>'; + } + } else { + $tpl = '<meta %s="%s" content="%s" %s/>'; + } + + $meta = sprintf( + $tpl, + $type, + $this->_escape($item->$type), + $this->_escape($item->content), + $modifiersString + ); + + if (isset($item->modifiers['conditional']) + && !empty($item->modifiers['conditional']) + && is_string($item->modifiers['conditional'])) + { + if (str_replace(' ', '', $item->modifiers['conditional']) === '!IE') { + $meta = '<!-->' . $meta . '<!--'; + } + $meta = '<!--[if ' . $this->_escape($item->modifiers['conditional']) . ']>' . $meta . '<![endif]-->'; + } + + return $meta; + } + + /** + * Render placeholder as string + * + * @param string|int $indent + * @return string + */ + public function toString($indent = null) + { + $indent = (null !== $indent) + ? $this->getWhitespace($indent) + : $this->getIndent(); + + $items = array(); + $this->getContainer()->ksort(); + try { + foreach ($this as $item) { + $items[] = $this->itemToString($item); + } + } catch (Zend_View_Exception $e) { + trigger_error($e->getMessage(), E_USER_WARNING); + return ''; + } + return $indent . implode($this->_escape($this->getSeparator()) . $indent, $items); + } + + /** + * Create data item for inserting into stack + * + * @param string $type + * @param string $typeValue + * @param string $content + * @param array $modifiers + * @return stdClass + */ + public function createData($type, $typeValue, $content, array $modifiers) + { + $data = new stdClass; + $data->type = $type; + $data->$type = $typeValue; + $data->content = $content; + $data->modifiers = $modifiers; + return $data; + } +} diff --git a/lib/zend/Zend/View/Helper/HeadScript.php b/lib/zend/Zend/View/Helper/HeadScript.php new file mode 100644 index 00000000000..062bed1b0cd --- /dev/null +++ b/lib/zend/Zend/View/Helper/HeadScript.php @@ -0,0 +1,520 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @version $Id$ + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +/** Zend_View_Helper_Placeholder_Container_Standalone */ +require_once 'Zend/View/Helper/Placeholder/Container/Standalone.php'; + +/** + * Helper for setting and retrieving script elements for HTML head section + * + * @uses Zend_View_Helper_Placeholder_Container_Standalone + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @method $this appendFile($src, $type = 'text/javascript', array $attrs = array()) + * @method $this appendScript($script, $type = 'text/javascript', array $attrs = array()) + * @method $this offsetSetFile($index, $src, $type = 'text/javascript', array $attrs = array()) + * @method $this offsetSetScript($index, $script, $type = 'text/javascript', array $attrs = array()) + * @method $this prependFile($src, $type = 'text/javascript', array $attrs = array()) + * @method $this prependScript($script, $type = 'text/javascript', array $attrs = array()) + * @method $this setFile($src, $type = 'text/javascript', array $attrs = array()) + * @method $this setScript($script, $type = 'text/javascript', array $attrs = array()) + */ +class Zend_View_Helper_HeadScript extends Zend_View_Helper_Placeholder_Container_Standalone +{ + /**#@+ + * Script type contants + * @const string + */ + const FILE = 'FILE'; + const SCRIPT = 'SCRIPT'; + /**#@-*/ + + /** + * Registry key for placeholder + * @var string + */ + protected $_regKey = 'Zend_View_Helper_HeadScript'; + + /** + * Are arbitrary attributes allowed? + * @var bool + */ + protected $_arbitraryAttributes = false; + + /**#@+ + * Capture type and/or attributes (used for hinting during capture) + * @var string + */ + protected $_captureLock; + protected $_captureScriptType = null; + protected $_captureScriptAttrs = null; + protected $_captureType; + /**#@-*/ + + /** + * Optional allowed attributes for script tag + * @var array + */ + protected $_optionalAttributes = array( + 'charset', 'defer', 'language', 'src' + ); + + /** + * Required attributes for script tag + * @var string + */ + protected $_requiredAttributes = array('type'); + + /** + * Whether or not to format scripts using CDATA; used only if doctype + * helper is not accessible + * @var bool + */ + public $useCdata = false; + + /** + * Constructor + * + * Set separator to PHP_EOL. + * + * @return void + */ + public function __construct() + { + parent::__construct(); + $this->setSeparator(PHP_EOL); + } + + /** + * Return headScript object + * + * Returns headScript helper object; optionally, allows specifying a script + * or script file to include. + * + * @param string $mode Script or file + * @param string $spec Script/url + * @param string $placement Append, prepend, or set + * @param array $attrs Array of script attributes + * @param string $type Script type and/or array of script attributes + * @return Zend_View_Helper_HeadScript + */ + public function headScript($mode = Zend_View_Helper_HeadScript::FILE, $spec = null, $placement = 'APPEND', array $attrs = array(), $type = 'text/javascript') + { + if ((null !== $spec) && is_string($spec)) { + $action = ucfirst(strtolower($mode)); + $placement = strtolower($placement); + switch ($placement) { + case 'set': + case 'prepend': + case 'append': + $action = $placement . $action; + break; + default: + $action = 'append' . $action; + break; + } + $this->$action($spec, $type, $attrs); + } + + return $this; + } + + /** + * Start capture action + * + * @param mixed $captureType + * @param string $typeOrAttrs + * @return void + */ + public function captureStart($captureType = Zend_View_Helper_Placeholder_Container_Abstract::APPEND, $type = 'text/javascript', $attrs = array()) + { + if ($this->_captureLock) { + require_once 'Zend/View/Helper/Placeholder/Container/Exception.php'; + $e = new Zend_View_Helper_Placeholder_Container_Exception('Cannot nest headScript captures'); + $e->setView($this->view); + throw $e; + } + + $this->_captureLock = true; + $this->_captureType = $captureType; + $this->_captureScriptType = $type; + $this->_captureScriptAttrs = $attrs; + ob_start(); + } + + /** + * End capture action and store + * + * @return void + */ + public function captureEnd() + { + $content = ob_get_clean(); + $type = $this->_captureScriptType; + $attrs = $this->_captureScriptAttrs; + $this->_captureScriptType = null; + $this->_captureScriptAttrs = null; + $this->_captureLock = false; + + switch ($this->_captureType) { + case Zend_View_Helper_Placeholder_Container_Abstract::SET: + case Zend_View_Helper_Placeholder_Container_Abstract::PREPEND: + case Zend_View_Helper_Placeholder_Container_Abstract::APPEND: + $action = strtolower($this->_captureType) . 'Script'; + break; + default: + $action = 'appendScript'; + break; + } + $this->$action($content, $type, $attrs); + } + + /** + * Overload method access + * + * Allows the following method calls: + * - appendFile($src, $type = 'text/javascript', $attrs = array()) + * - offsetSetFile($index, $src, $type = 'text/javascript', $attrs = array()) + * - prependFile($src, $type = 'text/javascript', $attrs = array()) + * - setFile($src, $type = 'text/javascript', $attrs = array()) + * - appendScript($script, $type = 'text/javascript', $attrs = array()) + * - offsetSetScript($index, $src, $type = 'text/javascript', $attrs = array()) + * - prependScript($script, $type = 'text/javascript', $attrs = array()) + * - setScript($script, $type = 'text/javascript', $attrs = array()) + * + * @param string $method + * @param array $args + * @return Zend_View_Helper_HeadScript + * @throws Zend_View_Exception if too few arguments or invalid method + */ + public function __call($method, $args) + { + if (preg_match('/^(?P<action>set|(ap|pre)pend|offsetSet)(?P<mode>File|Script)$/', $method, $matches)) { + if (1 > count($args)) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception(sprintf('Method "%s" requires at least one argument', $method)); + $e->setView($this->view); + throw $e; + } + + $action = $matches['action']; + $mode = strtolower($matches['mode']); + $type = 'text/javascript'; + $attrs = array(); + + if ('offsetSet' == $action) { + $index = array_shift($args); + if (1 > count($args)) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception(sprintf('Method "%s" requires at least two arguments, an index and source', $method)); + $e->setView($this->view); + throw $e; + } + } + + $content = $args[0]; + + if (isset($args[1])) { + $type = (string) $args[1]; + } + if (isset($args[2])) { + $attrs = (array) $args[2]; + } + + switch ($mode) { + case 'script': + $item = $this->createData($type, $attrs, $content); + if ('offsetSet' == $action) { + $this->offsetSet($index, $item); + } else { + $this->$action($item); + } + break; + case 'file': + default: + if (!$this->_isDuplicate($content) || $action=='set') { + $attrs['src'] = $content; + $item = $this->createData($type, $attrs); + if ('offsetSet' == $action) { + $this->offsetSet($index, $item); + } else { + $this->$action($item); + } + } + break; + } + + return $this; + } + + return parent::__call($method, $args); + } + + /** + * Is the file specified a duplicate? + * + * @param string $file + * @return bool + */ + protected function _isDuplicate($file) + { + foreach ($this->getContainer() as $item) { + if (($item->source === null) + && array_key_exists('src', $item->attributes) + && ($file == $item->attributes['src'])) + { + return true; + } + } + return false; + } + + /** + * Is the script provided valid? + * + * @param mixed $value + * @param string $method + * @return bool + */ + protected function _isValid($value) + { + if ((!$value instanceof stdClass) + || !isset($value->type) + || (!isset($value->source) && !isset($value->attributes))) + { + return false; + } + + return true; + } + + /** + * Override append + * + * @param string $value + * @return void + */ + public function append($value) + { + if (!$this->_isValid($value)) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception('Invalid argument passed to append(); please use one of the helper methods, appendScript() or appendFile()'); + $e->setView($this->view); + throw $e; + } + + return $this->getContainer()->append($value); + } + + /** + * Override prepend + * + * @param string $value + * @return void + */ + public function prepend($value) + { + if (!$this->_isValid($value)) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception('Invalid argument passed to prepend(); please use one of the helper methods, prependScript() or prependFile()'); + $e->setView($this->view); + throw $e; + } + + return $this->getContainer()->prepend($value); + } + + /** + * Override set + * + * @param string $value + * @return void + */ + public function set($value) + { + if (!$this->_isValid($value)) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception('Invalid argument passed to set(); please use one of the helper methods, setScript() or setFile()'); + $e->setView($this->view); + throw $e; + } + + return $this->getContainer()->set($value); + } + + /** + * Override offsetSet + * + * @param string|int $index + * @param mixed $value + * @return void + */ + public function offsetSet($index, $value) + { + if (!$this->_isValid($value)) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception('Invalid argument passed to offsetSet(); please use one of the helper methods, offsetSetScript() or offsetSetFile()'); + $e->setView($this->view); + throw $e; + } + + return $this->getContainer()->offsetSet($index, $value); + } + + /** + * Set flag indicating if arbitrary attributes are allowed + * + * @param bool $flag + * @return Zend_View_Helper_HeadScript + */ + public function setAllowArbitraryAttributes($flag) + { + $this->_arbitraryAttributes = (bool) $flag; + return $this; + } + + /** + * Are arbitrary attributes allowed? + * + * @return bool + */ + public function arbitraryAttributesAllowed() + { + return $this->_arbitraryAttributes; + } + + /** + * Create script HTML + * + * @param string $type + * @param array $attributes + * @param string $content + * @param string|int $indent + * @return string + */ + public function itemToString($item, $indent, $escapeStart, $escapeEnd) + { + $attrString = ''; + if (!empty($item->attributes)) { + foreach ($item->attributes as $key => $value) { + if ((!$this->arbitraryAttributesAllowed() && !in_array($key, $this->_optionalAttributes)) + || in_array($key, array('conditional', 'noescape'))) + { + continue; + } + if ('defer' == $key) { + $value = 'defer'; + } + $attrString .= sprintf(' %s="%s"', $key, ($this->_autoEscape) ? $this->_escape($value) : $value); + } + } + + $addScriptEscape = !(isset($item->attributes['noescape']) && filter_var($item->attributes['noescape'], FILTER_VALIDATE_BOOLEAN)); + + $type = ($this->_autoEscape) ? $this->_escape($item->type) : $item->type; + $html = '<script type="' . $type . '"' . $attrString . '>'; + if (!empty($item->source)) { + $html .= PHP_EOL ; + + if ($addScriptEscape) { + $html .= $indent . ' ' . $escapeStart . PHP_EOL; + } + + $html .= $indent . ' ' . $item->source; + + if ($addScriptEscape) { + $html .= $indent . ' ' . $escapeEnd . PHP_EOL; + } + + $html .= $indent; + } + $html .= '</script>'; + + if (isset($item->attributes['conditional']) + && !empty($item->attributes['conditional']) + && is_string($item->attributes['conditional'])) + { + // inner wrap with comment end and start if !IE + if (str_replace(' ', '', $item->attributes['conditional']) === '!IE') { + $html = '<!-->' . $html . '<!--'; + } + $html = $indent . '<!--[if ' . $item->attributes['conditional'] . ']>' . $html . '<![endif]-->'; + } else { + $html = $indent . $html; + } + + return $html; + } + + /** + * Retrieve string representation + * + * @param string|int $indent + * @return string + */ + public function toString($indent = null) + { + $indent = (null !== $indent) + ? $this->getWhitespace($indent) + : $this->getIndent(); + + if ($this->view) { + $useCdata = $this->view->doctype()->isXhtml() ? true : false; + } else { + $useCdata = $this->useCdata ? true : false; + } + $escapeStart = ($useCdata) ? '//<![CDATA[' : '//<!--'; + $escapeEnd = ($useCdata) ? '//]]>' : '//-->'; + + $items = array(); + $this->getContainer()->ksort(); + foreach ($this as $item) { + if (!$this->_isValid($item)) { + continue; + } + + $items[] = $this->itemToString($item, $indent, $escapeStart, $escapeEnd); + } + + $return = implode($this->getSeparator(), $items); + return $return; + } + + /** + * Create data item containing all necessary components of script + * + * @param string $type + * @param array $attributes + * @param string $content + * @return stdClass + */ + public function createData($type, array $attributes, $content = null) + { + $data = new stdClass(); + $data->type = $type; + $data->attributes = $attributes; + $data->source = $content; + return $data; + } +} diff --git a/lib/zend/Zend/View/Helper/HeadStyle.php b/lib/zend/Zend/View/Helper/HeadStyle.php new file mode 100644 index 00000000000..fc571bc9e02 --- /dev/null +++ b/lib/zend/Zend/View/Helper/HeadStyle.php @@ -0,0 +1,433 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @version $Id$ + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +/** Zend_View_Helper_Placeholder_Container_Standalone */ +require_once 'Zend/View/Helper/Placeholder/Container/Standalone.php'; + +/** + * Helper for setting and retrieving stylesheets + * + * @uses Zend_View_Helper_Placeholder_Container_Standalone + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @method $this appendStyle($content, array $attributes = array()) + * @method $this offsetSetStyle($index, $content, array $attributes = array()) + * @method $this prependStyle($content, array $attributes = array()) + * @method $this setStyle($content, array $attributes = array()) + */ +class Zend_View_Helper_HeadStyle extends Zend_View_Helper_Placeholder_Container_Standalone +{ + /** + * Registry key for placeholder + * @var string + */ + protected $_regKey = 'Zend_View_Helper_HeadStyle'; + + /** + * Allowed optional attributes + * @var array + */ + protected $_optionalAttributes = array('lang', 'title', 'media', 'dir'); + + /** + * Allowed media types + * @var array + */ + protected $_mediaTypes = array( + 'all', 'aural', 'braille', 'handheld', 'print', + 'projection', 'screen', 'tty', 'tv' + ); + + /** + * Capture type and/or attributes (used for hinting during capture) + * @var string + */ + protected $_captureAttrs = null; + + /** + * Capture lock + * @var bool + */ + protected $_captureLock; + + /** + * Capture type (append, prepend, set) + * @var string + */ + protected $_captureType; + + /** + * Constructor + * + * Set separator to PHP_EOL. + * + * @return void + */ + public function __construct() + { + parent::__construct(); + $this->setSeparator(PHP_EOL); + } + + /** + * Return headStyle object + * + * Returns headStyle helper object; optionally, allows specifying + * + * @param string $content Stylesheet contents + * @param string $placement Append, prepend, or set + * @param string|array $attributes Optional attributes to utilize + * @return Zend_View_Helper_HeadStyle + */ + public function headStyle($content = null, $placement = 'APPEND', $attributes = array()) + { + if ((null !== $content) && is_string($content)) { + switch (strtoupper($placement)) { + case 'SET': + $action = 'setStyle'; + break; + case 'PREPEND': + $action = 'prependStyle'; + break; + case 'APPEND': + default: + $action = 'appendStyle'; + break; + } + $this->$action($content, $attributes); + } + + return $this; + } + + /** + * Overload method calls + * + * Allows the following method calls: + * - appendStyle($content, $attributes = array()) + * - offsetSetStyle($index, $content, $attributes = array()) + * - prependStyle($content, $attributes = array()) + * - setStyle($content, $attributes = array()) + * + * @param string $method + * @param array $args + * @return void + * @throws Zend_View_Exception When no $content provided or invalid method + */ + public function __call($method, $args) + { + if (preg_match('/^(?P<action>set|(ap|pre)pend|offsetSet)(Style)$/', $method, $matches)) { + $index = null; + $argc = count($args); + $action = $matches['action']; + + if ('offsetSet' == $action) { + if (0 < $argc) { + $index = array_shift($args); + --$argc; + } + } + + if (1 > $argc) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception(sprintf('Method "%s" requires minimally content for the stylesheet', $method)); + $e->setView($this->view); + throw $e; + } + + $content = $args[0]; + $attrs = array(); + if (isset($args[1])) { + $attrs = (array) $args[1]; + } + + $item = $this->createData($content, $attrs); + + if ('offsetSet' == $action) { + $this->offsetSet($index, $item); + } else { + $this->$action($item); + } + + return $this; + } + + return parent::__call($method, $args); + } + + /** + * Determine if a value is a valid style tag + * + * @param mixed $value + * @param string $method + * @return boolean + */ + protected function _isValid($value) + { + if ((!$value instanceof stdClass) + || !isset($value->content) + || !isset($value->attributes)) + { + return false; + } + + return true; + } + + /** + * Override append to enforce style creation + * + * @param mixed $value + * @return void + */ + public function append($value) + { + if (!$this->_isValid($value)) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception('Invalid value passed to append; please use appendStyle()'); + $e->setView($this->view); + throw $e; + } + + return $this->getContainer()->append($value); + } + + /** + * Override offsetSet to enforce style creation + * + * @param string|int $index + * @param mixed $value + * @return void + */ + public function offsetSet($index, $value) + { + if (!$this->_isValid($value)) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception('Invalid value passed to offsetSet; please use offsetSetStyle()'); + $e->setView($this->view); + throw $e; + } + + return $this->getContainer()->offsetSet($index, $value); + } + + /** + * Override prepend to enforce style creation + * + * @param mixed $value + * @return void + */ + public function prepend($value) + { + if (!$this->_isValid($value)) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception('Invalid value passed to prepend; please use prependStyle()'); + $e->setView($this->view); + throw $e; + } + + return $this->getContainer()->prepend($value); + } + + /** + * Override set to enforce style creation + * + * @param mixed $value + * @return void + */ + public function set($value) + { + if (!$this->_isValid($value)) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception('Invalid value passed to set; please use setStyle()'); + $e->setView($this->view); + throw $e; + } + + return $this->getContainer()->set($value); + } + + /** + * Start capture action + * + * @param mixed $captureType + * @param string $typeOrAttrs + * @return void + */ + public function captureStart($type = Zend_View_Helper_Placeholder_Container_Abstract::APPEND, $attrs = null) + { + if ($this->_captureLock) { + require_once 'Zend/View/Helper/Placeholder/Container/Exception.php'; + $e = new Zend_View_Helper_Placeholder_Container_Exception('Cannot nest headStyle captures'); + $e->setView($this->view); + throw $e; + } + + $this->_captureLock = true; + $this->_captureAttrs = $attrs; + $this->_captureType = $type; + ob_start(); + } + + /** + * End capture action and store + * + * @return void + */ + public function captureEnd() + { + $content = ob_get_clean(); + $attrs = $this->_captureAttrs; + $this->_captureAttrs = null; + $this->_captureLock = false; + + switch ($this->_captureType) { + case Zend_View_Helper_Placeholder_Container_Abstract::SET: + $this->setStyle($content, $attrs); + break; + case Zend_View_Helper_Placeholder_Container_Abstract::PREPEND: + $this->prependStyle($content, $attrs); + break; + case Zend_View_Helper_Placeholder_Container_Abstract::APPEND: + default: + $this->appendStyle($content, $attrs); + break; + } + } + + /** + * Convert content and attributes into valid style tag + * + * @param stdClass $item Item to render + * @param string $indent Indentation to use + * @return string + */ + public function itemToString(stdClass $item, $indent) + { + $attrString = ''; + if (!empty($item->attributes)) { + $enc = 'UTF-8'; + if ($this->view instanceof Zend_View_Interface + && method_exists($this->view, 'getEncoding') + ) { + $enc = $this->view->getEncoding(); + } + foreach ($item->attributes as $key => $value) { + if (!in_array($key, $this->_optionalAttributes)) { + continue; + } + if ('media' == $key) { + if(false === strpos($value, ',')) { + if (!in_array($value, $this->_mediaTypes)) { + continue; + } + } else { + $media_types = explode(',', $value); + $value = ''; + foreach($media_types as $type) { + $type = trim($type); + if (!in_array($type, $this->_mediaTypes)) { + continue; + } + $value .= $type .','; + } + $value = substr($value, 0, -1); + } + } + $attrString .= sprintf(' %s="%s"', $key, htmlspecialchars($value, ENT_COMPAT, $enc)); + } + } + + $escapeStart = $indent . '<!--'. PHP_EOL; + $escapeEnd = $indent . '-->'. PHP_EOL; + if (isset($item->attributes['conditional']) + && !empty($item->attributes['conditional']) + && is_string($item->attributes['conditional']) + ) { + $escapeStart = null; + $escapeEnd = null; + } + + $html = '<style type="text/css"' . $attrString . '>' . PHP_EOL + . $escapeStart . $indent . $item->content . PHP_EOL . $escapeEnd + . '</style>'; + + if (null == $escapeStart && null == $escapeEnd) { + if (str_replace(' ', '', $item->attributes['conditional']) === '!IE') { + $html = '<!-->' . $html . '<!--'; + } + $html = '<!--[if ' . $item->attributes['conditional'] . ']>' . $html . '<![endif]-->'; + } + + return $html; + } + + /** + * Create string representation of placeholder + * + * @param string|int $indent + * @return string + */ + public function toString($indent = null) + { + $indent = (null !== $indent) + ? $this->getWhitespace($indent) + : $this->getIndent(); + + $items = array(); + $this->getContainer()->ksort(); + foreach ($this as $item) { + if (!$this->_isValid($item)) { + continue; + } + $items[] = $this->itemToString($item, $indent); + } + + $return = $indent . implode($this->getSeparator() . $indent, $items); + $return = preg_replace("/(\r\n?|\n)/", '$1' . $indent, $return); + return $return; + } + + /** + * Create data item for use in stack + * + * @param string $content + * @param array $attributes + * @return stdClass + */ + public function createData($content, array $attributes) + { + if (!isset($attributes['media'])) { + $attributes['media'] = 'screen'; + } else if(is_array($attributes['media'])) { + $attributes['media'] = implode(',', $attributes['media']); + } + + $data = new stdClass(); + $data->content = $content; + $data->attributes = $attributes; + + return $data; + } +} diff --git a/lib/zend/Zend/View/Helper/HeadTitle.php b/lib/zend/Zend/View/Helper/HeadTitle.php new file mode 100644 index 00000000000..8f3d9d0dbc0 --- /dev/null +++ b/lib/zend/Zend/View/Helper/HeadTitle.php @@ -0,0 +1,222 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @version $Id$ + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +/** Zend_View_Helper_Placeholder_Container_Standalone */ +require_once 'Zend/View/Helper/Placeholder/Container/Standalone.php'; + +/** + * Helper for setting and retrieving title element for HTML head + * + * @uses Zend_View_Helper_Placeholder_Container_Standalone + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_View_Helper_HeadTitle extends Zend_View_Helper_Placeholder_Container_Standalone +{ + /** + * Registry key for placeholder + * @var string + */ + protected $_regKey = 'Zend_View_Helper_HeadTitle'; + + /** + * Whether or not auto-translation is enabled + * @var boolean + */ + protected $_translate = false; + + /** + * Translation object + * + * @var Zend_Translate_Adapter + */ + protected $_translator; + + /** + * Default title rendering order (i.e. order in which each title attached) + * + * @var string + */ + protected $_defaultAttachOrder = null; + + /** + * Retrieve placeholder for title element and optionally set state + * + * @param string $title + * @param string $setType + * @return Zend_View_Helper_HeadTitle + */ + public function headTitle($title = null, $setType = null) + { + if (null === $setType) { + $setType = (null === $this->getDefaultAttachOrder()) + ? Zend_View_Helper_Placeholder_Container_Abstract::APPEND + : $this->getDefaultAttachOrder(); + } + $title = (string) $title; + if ($title !== '') { + if ($setType == Zend_View_Helper_Placeholder_Container_Abstract::SET) { + $this->set($title); + } elseif ($setType == Zend_View_Helper_Placeholder_Container_Abstract::PREPEND) { + $this->prepend($title); + } else { + $this->append($title); + } + } + + return $this; + } + + /** + * Set a default order to add titles + * + * @param string $setType + */ + public function setDefaultAttachOrder($setType) + { + if (!in_array($setType, array( + Zend_View_Helper_Placeholder_Container_Abstract::APPEND, + Zend_View_Helper_Placeholder_Container_Abstract::SET, + Zend_View_Helper_Placeholder_Container_Abstract::PREPEND + ))) { + require_once 'Zend/View/Exception.php'; + throw new Zend_View_Exception("You must use a valid attach order: 'PREPEND', 'APPEND' or 'SET'"); + } + + $this->_defaultAttachOrder = $setType; + return $this; + } + + /** + * Get the default attach order, if any. + * + * @return mixed + */ + public function getDefaultAttachOrder() + { + return $this->_defaultAttachOrder; + } + + /** + * Sets a translation Adapter for translation + * + * @param Zend_Translate|Zend_Translate_Adapter $translate + * @return Zend_View_Helper_HeadTitle + */ + public function setTranslator($translate) + { + if ($translate instanceof Zend_Translate_Adapter) { + $this->_translator = $translate; + } elseif ($translate instanceof Zend_Translate) { + $this->_translator = $translate->getAdapter(); + } else { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception("You must set an instance of Zend_Translate or Zend_Translate_Adapter"); + $e->setView($this->view); + throw $e; + } + return $this; + } + + /** + * Retrieve translation object + * + * If none is currently registered, attempts to pull it from the registry + * using the key 'Zend_Translate'. + * + * @return Zend_Translate_Adapter|null + */ + public function getTranslator() + { + if (null === $this->_translator) { + require_once 'Zend/Registry.php'; + if (Zend_Registry::isRegistered('Zend_Translate')) { + $this->setTranslator(Zend_Registry::get('Zend_Translate')); + } + } + return $this->_translator; + } + + /** + * Enables translation + * + * @return Zend_View_Helper_HeadTitle + */ + public function enableTranslation() + { + $this->_translate = true; + return $this; + } + + /** + * Disables translation + * + * @return Zend_View_Helper_HeadTitle + */ + public function disableTranslation() + { + $this->_translate = false; + return $this; + } + + /** + * Turn helper into string + * + * @param string|null $indent + * @param string|null $locale + * @return string + */ + public function toString($indent = null, $locale = null) + { + $indent = (null !== $indent) + ? $this->getWhitespace($indent) + : $this->getIndent(); + + $items = array(); + + if($this->_translate && $translator = $this->getTranslator()) { + foreach ($this as $item) { + $items[] = $translator->translate($item, $locale); + } + } else { + foreach ($this as $item) { + $items[] = $item; + } + } + + $separator = $this->getSeparator(); + $output = ''; + if(($prefix = $this->getPrefix())) { + $output .= $prefix; + } + $output .= implode($separator, $items); + if(($postfix = $this->getPostfix())) { + $output .= $postfix; + } + + $output = ($this->_autoEscape) ? $this->_escape($output) : $output; + + return $indent . '<title>' . $output . ''; + } +} diff --git a/lib/zend/Zend/View/Helper/HtmlElement.php b/lib/zend/Zend/View/Helper/HtmlElement.php new file mode 100644 index 00000000000..263fcd32d22 --- /dev/null +++ b/lib/zend/Zend/View/Helper/HtmlElement.php @@ -0,0 +1,167 @@ +_closingBracket) { + if ($this->_isXhtml()) { + $this->_closingBracket = ' />'; + } else { + $this->_closingBracket = '>'; + } + } + + return $this->_closingBracket; + } + + /** + * Is doctype XHTML? + * + * @return boolean + */ + protected function _isXhtml() + { + $doctype = $this->view->doctype(); + return $doctype->isXhtml(); + } + + /** + * Is doctype HTML5? + * + * @return boolean + */ + protected function _isHtml5() + { + $doctype = $this->view->doctype(); + return $doctype->isHtml5(); + } + + /** + * Is doctype strict? + * + * @return boolean + */ + protected function _isStrictDoctype() + { + $doctype = $this->view->doctype(); + return $doctype->isStrict(); + } + + /** + * Converts an associative array to a string of tag attributes. + * + * @access public + * + * @param array $attribs From this array, each key-value pair is + * converted to an attribute name and value. + * + * @return string The XHTML for the attributes. + */ + protected function _htmlAttribs($attribs) + { + $xhtml = ''; + foreach ((array) $attribs as $key => $val) { + $key = $this->view->escape($key); + + if (('on' == substr($key, 0, 2)) || ('constraints' == $key)) { + // Don't escape event attributes; _do_ substitute double quotes with singles + if (!is_scalar($val)) { + // non-scalar data should be cast to JSON first + require_once 'Zend/Json.php'; + $val = Zend_Json::encode($val); + } + // Escape single quotes inside event attribute values. + // This will create html, where the attribute value has + // single quotes around it, and escaped single quotes or + // non-escaped double quotes inside of it + $val = str_replace('\'', ''', $val); + } else { + if (is_array($val)) { + $val = implode(' ', $val); + } + $val = $this->view->escape($val); + } + + if ('id' == $key) { + $val = $this->_normalizeId($val); + } + + if (strpos($val, '"') !== false) { + $xhtml .= " $key='$val'"; + } else { + $xhtml .= " $key=\"$val\""; + } + + } + return $xhtml; + } + + /** + * Normalize an ID + * + * @param string $value + * @return string + */ + protected function _normalizeId($value) + { + if (strstr($value, '[')) { + if ('[]' == substr($value, -2)) { + $value = substr($value, 0, strlen($value) - 2); + } + $value = trim($value, ']'); + $value = str_replace('][', '-', $value); + $value = str_replace('[', '-', $value); + } + return $value; + } +} diff --git a/lib/zend/Zend/View/Helper/HtmlFlash.php b/lib/zend/Zend/View/Helper/HtmlFlash.php new file mode 100644 index 00000000000..3edcf1afcef --- /dev/null +++ b/lib/zend/Zend/View/Helper/HtmlFlash.php @@ -0,0 +1,60 @@ + $data, + 'quality' => 'high'), $params); + + return $this->htmlObject($data, self::TYPE, $attribs, $params, $content); + } +} diff --git a/lib/zend/Zend/View/Helper/HtmlList.php b/lib/zend/Zend/View/Helper/HtmlList.php new file mode 100644 index 00000000000..471ade4808f --- /dev/null +++ b/lib/zend/Zend/View/Helper/HtmlList.php @@ -0,0 +1,90 @@ +setView($this->view); + throw $e; + } + + $list = ''; + + foreach ($items as $item) { + if (!is_array($item)) { + if ($escape) { + $item = $this->view->escape($item); + } + $list .= '
  • ' . $item . '
  • ' . self::EOL; + } else { + if (6 < strlen($list)) { + $list = substr($list, 0, strlen($list) - 6) + . $this->htmlList($item, $ordered, $attribs, $escape) . '' . self::EOL; + } else { + $list .= '
  • ' . $this->htmlList($item, $ordered, $attribs, $escape) . '
  • ' . self::EOL; + } + } + } + + if ($attribs) { + $attribs = $this->_htmlAttribs($attribs); + } else { + $attribs = ''; + } + + $tag = 'ul'; + if ($ordered) { + $tag = 'ol'; + } + + return '<' . $tag . $attribs . '>' . self::EOL . $list . '' . self::EOL; + } +} diff --git a/lib/zend/Zend/View/Helper/HtmlObject.php b/lib/zend/Zend/View/Helper/HtmlObject.php new file mode 100644 index 00000000000..1eddfea5eeb --- /dev/null +++ b/lib/zend/Zend/View/Helper/HtmlObject.php @@ -0,0 +1,80 @@ + $data, + 'type' => $type), $attribs); + + // Params + $paramHtml = array(); + $closingBracket = $this->getClosingBracket(); + + foreach ($params as $param => $options) { + if (is_string($options)) { + $options = array('value' => $options); + } + + $options = array_merge(array('name' => $param), $options); + + $paramHtml[] = '_htmlAttribs($options) . $closingBracket; + } + + // Content + if (is_array($content)) { + $content = implode(self::EOL, $content); + } + + // Object header + $xhtml = '_htmlAttribs($attribs) . '>' . self::EOL + . implode(self::EOL, $paramHtml) . self::EOL + . ($content ? $content . self::EOL : '') + . ''; + + return $xhtml; + } +} diff --git a/lib/zend/Zend/View/Helper/HtmlPage.php b/lib/zend/Zend/View/Helper/HtmlPage.php new file mode 100644 index 00000000000..e7b8b0f200c --- /dev/null +++ b/lib/zend/Zend/View/Helper/HtmlPage.php @@ -0,0 +1,75 @@ + self::ATTRIB_CLASSID); + + /** + * Output a html object tag + * + * @param string $data The html url + * @param array $attribs Attribs for the object tag + * @param array $params Params for in the object tag + * @param string $content Alternative content + * @return string + */ + public function htmlPage($data, array $attribs = array(), array $params = array(), $content = null) + { + // Attrs + $attribs = array_merge($this->_attribs, $attribs); + + // Params + $params = array_merge(array('data' => $data), $params); + + return $this->htmlObject($data, self::TYPE, $attribs, $params, $content); + } +} diff --git a/lib/zend/Zend/View/Helper/HtmlQuicktime.php b/lib/zend/Zend/View/Helper/HtmlQuicktime.php new file mode 100644 index 00000000000..6c200dbcecb --- /dev/null +++ b/lib/zend/Zend/View/Helper/HtmlQuicktime.php @@ -0,0 +1,82 @@ + self::ATTRIB_CLASSID, + 'codebase' => self::ATTRIB_CODEBASE); + + /** + * Output a quicktime movie object tag + * + * @param string $data The quicktime file + * @param array $attribs Attribs for the object tag + * @param array $params Params for in the object tag + * @param string $content Alternative content + * @return string + */ + public function htmlQuicktime($data, array $attribs = array(), array $params = array(), $content = null) + { + // Attrs + $attribs = array_merge($this->_attribs, $attribs); + + // Params + $params = array_merge(array('src' => $data), $params); + + return $this->htmlObject($data, self::TYPE, $attribs, $params, $content); + } +} diff --git a/lib/zend/Zend/View/Helper/InlineScript.php b/lib/zend/Zend/View/Helper/InlineScript.php new file mode 100644 index 00000000000..978c6b812b5 --- /dev/null +++ b/lib/zend/Zend/View/Helper/InlineScript.php @@ -0,0 +1,61 @@ +headScript($mode, $spec, $placement, $attrs, $type); + } +} diff --git a/lib/zend/Zend/View/Helper/Interface.php b/lib/zend/Zend/View/Helper/Interface.php new file mode 100644 index 00000000000..c7e761b2a56 --- /dev/null +++ b/lib/zend/Zend/View/Helper/Interface.php @@ -0,0 +1,46 @@ +true|false + * this array can contains a 'keepLayout'=>true|false and/or 'encodeData'=>true|false + * that will not be passed to Zend_Json::encode method but will be used here + * @param bool $encodeData + * @return string|void + */ + public function json($data, $keepLayouts = false, $encodeData = true) + { + $options = array(); + if (is_array($keepLayouts)) { + $options = $keepLayouts; + + $keepLayouts = false; + if (array_key_exists('keepLayouts', $options)) { + $keepLayouts = $options['keepLayouts']; + unset($options['keepLayouts']); + } + + if (array_key_exists('encodeData', $options)) { + $encodeData = $options['encodeData']; + unset($options['encodeData']); + } + } + + if ($encodeData) { + $data = Zend_Json::encode($data, null, $options); + } + if (!$keepLayouts) { + require_once 'Zend/Layout.php'; + $layout = Zend_Layout::getMvcInstance(); + if ($layout instanceof Zend_Layout) { + $layout->disableLayout(); + } + } + + $response = Zend_Controller_Front::getInstance()->getResponse(); + $response->setHeader('Content-Type', 'application/json', true); + return $data; + } +} diff --git a/lib/zend/Zend/View/Helper/Layout.php b/lib/zend/Zend/View/Helper/Layout.php new file mode 100644 index 00000000000..286a9e38e7e --- /dev/null +++ b/lib/zend/Zend/View/Helper/Layout.php @@ -0,0 +1,81 @@ +_layout) { + require_once 'Zend/Layout.php'; + $this->_layout = Zend_Layout::getMvcInstance(); + if (null === $this->_layout) { + // Implicitly creates layout object + $this->_layout = new Zend_Layout(); + } + } + + return $this->_layout; + } + + /** + * Set layout object + * + * @param Zend_Layout $layout + * @return Zend_Layout_Controller_Action_Helper_Layout + */ + public function setLayout(Zend_Layout $layout) + { + $this->_layout = $layout; + return $this; + } + + /** + * Return layout object + * + * Usage: $this->layout()->setLayout('alternate'); + * + * @return Zend_Layout + */ + public function layout() + { + return $this->getLayout(); + } +} diff --git a/lib/zend/Zend/View/Helper/Navigation.php b/lib/zend/Zend/View/Helper/Navigation.php new file mode 100644 index 00000000000..2e82ef6a291 --- /dev/null +++ b/lib/zend/Zend/View/Helper/Navigation.php @@ -0,0 +1,350 @@ +setContainer($container); + } + + return $this; + } + + /** + * Magic overload: Proxy to other navigation helpers or the container + * + * Examples of usage from a view script or layout: + * + * // proxy to Menu helper and render container: + * echo $this->navigation()->menu(); + * + * // proxy to Breadcrumbs helper and set indentation: + * $this->navigation()->breadcrumbs()->setIndent(8); + * + * // proxy to container and find all pages with 'blog' route: + * $blogPages = $this->navigation()->findAllByRoute('blog'); + * + * + * @param string $method helper name or method name in + * container + * @param array $arguments [optional] arguments to pass + * @return mixed returns what the proxied call returns + * @throws Zend_View_Exception if proxying to a helper, and the + * helper is not an instance of the + * interface specified in + * {@link findHelper()} + * @throws Zend_Navigation_Exception if method does not exist in container + */ + public function __call($method, array $arguments = array()) + { + // check if call should proxy to another helper + if ($helper = $this->findHelper($method, false)) { + return call_user_func_array(array($helper, $method), $arguments); + } + + // default behaviour: proxy call to container + return parent::__call($method, $arguments); + } + + /** + * Returns the helper matching $proxy + * + * The helper must implement the interface + * {@link Zend_View_Helper_Navigation_Helper}. + * + * @param string $proxy helper name + * @param bool $strict [optional] whether + * exceptions should be + * thrown if something goes + * wrong. Default is true. + * @return Zend_View_Helper_Navigation_Helper helper instance + * @throws Zend_Loader_PluginLoader_Exception if $strict is true and + * helper cannot be found + * @throws Zend_View_Exception if $strict is true and + * helper does not implement + * the specified interface + */ + public function findHelper($proxy, $strict = true) + { + if (isset($this->_helpers[$proxy])) { + return $this->_helpers[$proxy]; + } + + if (!$this->view->getPluginLoader('helper')->getPaths(self::NS)) { + // Add navigation helper path at the beginning + $paths = $this->view->getHelperPaths(); + $this->view->setHelperPath(null); + + $this->view->addHelperPath( + str_replace('_', '/', self::NS), + self::NS); + + foreach ($paths as $ns => $path) { + $this->view->addHelperPath($path, $ns); + } + } + + if ($strict) { + $helper = $this->view->getHelper($proxy); + } else { + try { + $helper = $this->view->getHelper($proxy); + } catch (Zend_Loader_PluginLoader_Exception $e) { + return null; + } + } + + if (!$helper instanceof Zend_View_Helper_Navigation_Helper) { + if ($strict) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception(sprintf( + 'Proxy helper "%s" is not an instance of ' . + 'Zend_View_Helper_Navigation_Helper', + get_class($helper))); + $e->setView($this->view); + throw $e; + } + + return null; + } + + $this->_inject($helper); + $this->_helpers[$proxy] = $helper; + + return $helper; + } + + /** + * Injects container, ACL, and translator to the given $helper if this + * helper is configured to do so + * + * @param Zend_View_Helper_Navigation_Helper $helper helper instance + * @return void + */ + protected function _inject(Zend_View_Helper_Navigation_Helper $helper) + { + if ($this->getInjectContainer() && !$helper->hasContainer()) { + $helper->setContainer($this->getContainer()); + } + + if ($this->getInjectAcl()) { + if (!$helper->hasAcl()) { + $helper->setAcl($this->getAcl()); + } + if (!$helper->hasRole()) { + $helper->setRole($this->getRole()); + } + } + + if ($this->getInjectTranslator() && !$helper->hasTranslator()) { + $helper->setTranslator($this->getTranslator()); + } + } + + // Accessors: + + /** + * Sets the default proxy to use in {@link render()} + * + * @param string $proxy default proxy + * @return Zend_View_Helper_Navigation fluent interface, returns self + */ + public function setDefaultProxy($proxy) + { + $this->_defaultProxy = (string) $proxy; + return $this; + } + + /** + * Returns the default proxy to use in {@link render()} + * + * @return string the default proxy to use in {@link render()} + */ + public function getDefaultProxy() + { + return $this->_defaultProxy; + } + + /** + * Sets whether container should be injected when proxying + * + * @param bool $injectContainer [optional] whether container should + * be injected when proxying. Default + * is true. + * @return Zend_View_Helper_Navigation fluent interface, returns self + */ + public function setInjectContainer($injectContainer = true) + { + $this->_injectContainer = (bool) $injectContainer; + return $this; + } + + /** + * Returns whether container should be injected when proxying + * + * @return bool whether container should be injected when proxying + */ + public function getInjectContainer() + { + return $this->_injectContainer; + } + + /** + * Sets whether ACL should be injected when proxying + * + * @param bool $injectAcl [optional] whether ACL should be + * injected when proxying. Default is + * true. + * @return Zend_View_Helper_Navigation fluent interface, returns self + */ + public function setInjectAcl($injectAcl = true) + { + $this->_injectAcl = (bool) $injectAcl; + return $this; + } + + /** + * Returns whether ACL should be injected when proxying + * + * @return bool whether ACL should be injected when proxying + */ + public function getInjectAcl() + { + return $this->_injectAcl; + } + + /** + * Sets whether translator should be injected when proxying + * + * @param bool $injectTranslator [optional] whether translator should + * be injected when proxying. Default + * is true. + * @return Zend_View_Helper_Navigation fluent interface, returns self + */ + public function setInjectTranslator($injectTranslator = true) + { + $this->_injectTranslator = (bool) $injectTranslator; + return $this; + } + + /** + * Returns whether translator should be injected when proxying + * + * @return bool whether translator should be injected when proxying + */ + public function getInjectTranslator() + { + return $this->_injectTranslator; + } + + // Zend_View_Helper_Navigation_Helper: + + /** + * Renders helper + * + * @param Zend_Navigation_Container $container [optional] container to + * render. Default is to + * render the container + * registered in the helper. + * @return string helper output + * @throws Zend_Loader_PluginLoader_Exception if helper cannot be found + * @throws Zend_View_Exception if helper doesn't implement + * the interface specified in + * {@link findHelper()} + */ + public function render(Zend_Navigation_Container $container = null) + { + $helper = $this->findHelper($this->getDefaultProxy()); + return $helper->render($container); + } +} diff --git a/lib/zend/Zend/View/Helper/Navigation/Breadcrumbs.php b/lib/zend/Zend/View/Helper/Navigation/Breadcrumbs.php new file mode 100644 index 00000000000..10755c3df49 --- /dev/null +++ b/lib/zend/Zend/View/Helper/Navigation/Breadcrumbs.php @@ -0,0 +1,331 @@ +setContainer($container); + } + + return $this; + } + + // Accessors: + + /** + * Sets breadcrumb separator + * + * @param string $separator separator string + * @return Zend_View_Helper_Navigation_Breadcrumbs fluent interface, + * returns self + */ + public function setSeparator($separator) + { + if (is_string($separator)) { + $this->_separator = $separator; + } + + return $this; + } + + /** + * Returns breadcrumb separator + * + * @return string breadcrumb separator + */ + public function getSeparator() + { + return $this->_separator; + } + + /** + * Sets whether last page in breadcrumbs should be hyperlinked + * + * @param bool $linkLast whether last page should + * be hyperlinked + * @return Zend_View_Helper_Navigation_Breadcrumbs fluent interface, + * returns self + */ + public function setLinkLast($linkLast) + { + $this->_linkLast = (bool) $linkLast; + return $this; + } + + /** + * Returns whether last page in breadcrumbs should be hyperlinked + * + * @return bool whether last page in breadcrumbs should be hyperlinked + */ + public function getLinkLast() + { + return $this->_linkLast; + } + + /** + * Sets which partial view script to use for rendering menu + * + * @param string|array $partial partial view script or + * null. If an array is + * given, it is expected to + * contain two values; + * the partial view script + * to use, and the module + * where the script can be + * found. + * @return Zend_View_Helper_Navigation_Breadcrumbs fluent interface, + * returns self + */ + public function setPartial($partial) + { + if (null === $partial || is_string($partial) || is_array($partial)) { + $this->_partial = $partial; + } + + return $this; + } + + /** + * Returns partial view script to use for rendering menu + * + * @return string|array|null + */ + public function getPartial() + { + return $this->_partial; + } + + // Render methods: + + /** + * Renders breadcrumbs by chaining 'a' elements with the separator + * registered in the helper + * + * @param Zend_Navigation_Container $container [optional] container to + * render. Default is to + * render the container + * registered in the helper. + * @return string helper output + */ + public function renderStraight(Zend_Navigation_Container $container = null) + { + if (null === $container) { + $container = $this->getContainer(); + } + + // find deepest active + if (!$active = $this->findActive($container)) { + return ''; + } + + $active = $active['page']; + + // put the deepest active page last in breadcrumbs + if ($this->getLinkLast()) { + $html = $this->htmlify($active); + } else { + $html = $active->getLabel(); + if ($this->getUseTranslator() && $t = $this->getTranslator()) { + $html = $t->translate($html); + } + $html = $this->view->escape($html); + } + + // walk back to root + while ($parent = $active->getParent()) { + if ($parent instanceof Zend_Navigation_Page) { + // prepend crumb to html + $html = $this->htmlify($parent) + . $this->getSeparator() + . $html; + } + + if ($parent === $container) { + // at the root of the given container + break; + } + + $active = $parent; + } + + return strlen($html) ? $this->getIndent() . $html : ''; + } + + /** + * Renders the given $container by invoking the partial view helper + * + * The container will simply be passed on as a model to the view script, + * so in the script it will be available in $this->container. + * + * @param Zend_Navigation_Container $container [optional] container to + * pass to view script. + * Default is to use the + * container registered in the + * helper. + * @param string|array $partial [optional] partial view + * script to use. Default is + * to use the partial + * registered in the helper. + * If an array is given, it is + * expected to contain two + * values; the partial view + * script to use, and the + * module where the script can + * be found. + * @return string helper output + */ + public function renderPartial(Zend_Navigation_Container $container = null, + $partial = null) + { + if (null === $container) { + $container = $this->getContainer(); + } + + if (null === $partial) { + $partial = $this->getPartial(); + } + + if (empty($partial)) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception( + 'Unable to render menu: No partial view script provided' + ); + $e->setView($this->view); + throw $e; + } + + // put breadcrumb pages in model + $model = array('pages' => array()); + if ($active = $this->findActive($container)) { + $active = $active['page']; + $model['pages'][] = $active; + while ($parent = $active->getParent()) { + if ($parent instanceof Zend_Navigation_Page) { + $model['pages'][] = $parent; + } else { + break; + } + + if ($parent === $container) { + // break if at the root of the given container + break; + } + + $active = $parent; + } + $model['pages'] = array_reverse($model['pages']); + } + + if (is_array($partial)) { + if (count($partial) != 2) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception( + 'Unable to render menu: A view partial supplied as ' + . 'an array must contain two values: partial view ' + . 'script and module where script can be found' + ); + $e->setView($this->view); + throw $e; + } + + return $this->view->partial($partial[0], $partial[1], $model); + } + + return $this->view->partial($partial, null, $model); + } + + // Zend_View_Helper_Navigation_Helper: + + /** + * Renders helper + * + * Implements {@link Zend_View_Helper_Navigation_Helper::render()}. + * + * @param Zend_Navigation_Container $container [optional] container to + * render. Default is to + * render the container + * registered in the helper. + * @return string helper output + */ + public function render(Zend_Navigation_Container $container = null) + { + if ($partial = $this->getPartial()) { + return $this->renderPartial($container, $partial); + } else { + return $this->renderStraight($container); + } + } +} diff --git a/lib/zend/Zend/View/Helper/Navigation/Helper.php b/lib/zend/Zend/View/Helper/Navigation/Helper.php new file mode 100644 index 00000000000..e7d5878160c --- /dev/null +++ b/lib/zend/Zend/View/Helper/Navigation/Helper.php @@ -0,0 +1,212 @@ +_container = $container; + return $this; + } + + /** + * Returns the navigation container helper operates on by default + * + * Implements {@link Zend_View_Helper_Navigation_Interface::getContainer()}. + * + * If a helper is not explicitly set in this helper instance by calling + * {@link setContainer()} or by passing it through the helper entry point, + * this method will look in {@link Zend_Registry} for a container by using + * the key 'Zend_Navigation'. + * + * If no container is set, and nothing is found in Zend_Registry, a new + * container will be instantiated and stored in the helper. + * + * @return Zend_Navigation_Container navigation container + */ + public function getContainer() + { + if (null === $this->_container) { + // try to fetch from registry first + require_once 'Zend/Registry.php'; + if (Zend_Registry::isRegistered('Zend_Navigation')) { + $nav = Zend_Registry::get('Zend_Navigation'); + if ($nav instanceof Zend_Navigation_Container) { + return $this->_container = $nav; + } + } + + // nothing found in registry, create new container + require_once 'Zend/Navigation.php'; + $this->_container = new Zend_Navigation(); + } + + return $this->_container; + } + + /** + * Sets the minimum depth a page must have to be included when rendering + * + * @param int $minDepth [optional] minimum + * depth. Default is + * null, which sets + * no minimum depth. + * @return Zend_View_Helper_Navigation_HelperAbstract fluent interface, + * returns self + */ + public function setMinDepth($minDepth = null) + { + if (null === $minDepth || is_int($minDepth)) { + $this->_minDepth = $minDepth; + } else { + $this->_minDepth = (int) $minDepth; + } + return $this; + } + + /** + * Returns minimum depth a page must have to be included when rendering + * + * @return int|null minimum depth or null + */ + public function getMinDepth() + { + if (!is_int($this->_minDepth) || $this->_minDepth < 0) { + return 0; + } + return $this->_minDepth; + } + + /** + * Sets the maximum depth a page can have to be included when rendering + * + * @param int $maxDepth [optional] maximum + * depth. Default is + * null, which sets no + * maximum depth. + * @return Zend_View_Helper_Navigation_HelperAbstract fluent interface, + * returns self + */ + public function setMaxDepth($maxDepth = null) + { + if (null === $maxDepth || is_int($maxDepth)) { + $this->_maxDepth = $maxDepth; + } else { + $this->_maxDepth = (int) $maxDepth; + } + return $this; + } + + /** + * Returns maximum depth a page can have to be included when rendering + * + * @return int|null maximum depth or null + */ + public function getMaxDepth() + { + return $this->_maxDepth; + } + + /** + * Set the indentation string for using in {@link render()}, optionally a + * number of spaces to indent with + * + * @param string|int $indent indentation string or + * number of spaces + * @return Zend_View_Helper_Navigation_HelperAbstract fluent interface, + * returns self + */ + public function setIndent($indent) + { + $this->_indent = $this->_getWhitespace($indent); + return $this; + } + + /** + * Returns indentation (format output is respected) + * + * @return string indentation string or an empty string + */ + public function getIndent() + { + if (false === $this->getFormatOutput()) { + return ''; + } + + return $this->_indent; + } + + /** + * Returns the EOL character (format output is respected) + * + * @see self::EOL + * @see getFormatOutput() + * + * @return string standard EOL charater or an empty string + */ + public function getEOL() + { + if (false === $this->getFormatOutput()) { + return ''; + } + + return self::EOL; + } + + /** + * Sets whether HTML/XML output should be formatted + * + * @param bool $formatOutput [optional] whether output + * should be formatted. Default + * is true. + * + * @return Zend_View_Helper_Navigation_Sitemap fluent interface, returns + * self + */ + public function setFormatOutput($formatOutput = true) + { + $this->_formatOutput = (bool)$formatOutput; + + return $this; + } + + /** + * Returns whether HTML/XML output should be formatted + * + * @return bool whether HTML/XML output should be formatted + */ + public function getFormatOutput() + { + return $this->_formatOutput; + } + + /** + * Sets prefix for IDs when they are normalized + * + * @param string $prefix Prefix for IDs + * @return Zend_View_Helper_Navigation_HelperAbstract fluent interface, returns self + */ + public function setPrefixForId($prefix) + { + if (is_string($prefix)) { + $this->_prefixForId = trim($prefix); + } + + return $this; + } + + /** + * Returns prefix for IDs when they are normalized + * + * @return string Prefix for + */ + public function getPrefixForId() + { + if (null === $this->_prefixForId) { + $prefix = get_class($this); + $this->_prefixForId = strtolower( + trim(substr($prefix, strrpos($prefix, '_')), '_') + ) . '-'; + } + + return $this->_prefixForId; + } + + /** + * Skip the current prefix for IDs when they are normalized + * + * @param bool $flag + * @return Zend_View_Helper_Navigation_HelperAbstract fluent interface, returns self + */ + public function skipPrefixForId($flag = true) + { + $this->_skipPrefixForId = (bool) $flag; + return $this; + } + + /** + * Sets translator to use in helper + * + * Implements {@link Zend_View_Helper_Navigation_Helper::setTranslator()}. + * + * @param mixed $translator [optional] translator. + * Expects an object of + * type + * {@link Zend_Translate_Adapter} + * or {@link Zend_Translate}, + * or null. Default is + * null, which sets no + * translator. + * @return Zend_View_Helper_Navigation_HelperAbstract fluent interface, + * returns self + */ + public function setTranslator($translator = null) + { + if (null == $translator || + $translator instanceof Zend_Translate_Adapter) { + $this->_translator = $translator; + } elseif ($translator instanceof Zend_Translate) { + $this->_translator = $translator->getAdapter(); + } + + return $this; + } + + /** + * Returns translator used in helper + * + * Implements {@link Zend_View_Helper_Navigation_Helper::getTranslator()}. + * + * @return Zend_Translate_Adapter|null translator or null + */ + public function getTranslator() + { + if (null === $this->_translator) { + require_once 'Zend/Registry.php'; + if (Zend_Registry::isRegistered('Zend_Translate')) { + $this->setTranslator(Zend_Registry::get('Zend_Translate')); + } + } + + return $this->_translator; + } + + /** + * Sets ACL to use when iterating pages + * + * Implements {@link Zend_View_Helper_Navigation_Helper::setAcl()}. + * + * @param Zend_Acl $acl [optional] ACL object. + * Default is null. + * @return Zend_View_Helper_Navigation_HelperAbstract fluent interface, + * returns self + */ + public function setAcl(Zend_Acl $acl = null) + { + $this->_acl = $acl; + return $this; + } + + /** + * Returns ACL or null if it isn't set using {@link setAcl()} or + * {@link setDefaultAcl()} + * + * Implements {@link Zend_View_Helper_Navigation_Helper::getAcl()}. + * + * @return Zend_Acl|null ACL object or null + */ + public function getAcl() + { + if ($this->_acl === null && self::$_defaultAcl !== null) { + return self::$_defaultAcl; + } + + return $this->_acl; + } + + /** + * Sets ACL role(s) to use when iterating pages + * + * Implements {@link Zend_View_Helper_Navigation_Helper::setRole()}. + * + * @param mixed $role [optional] role to + * set. Expects a string, + * an instance of type + * {@link Zend_Acl_Role_Interface}, + * or null. Default is + * null, which will set + * no role. + * @throws Zend_View_Exception if $role is invalid + * @return Zend_View_Helper_Navigation_HelperAbstract fluent interface, + * returns self + */ + public function setRole($role = null) + { + if (null === $role || is_string($role) || + $role instanceof Zend_Acl_Role_Interface) { + $this->_role = $role; + } else { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception(sprintf( + '$role must be a string, null, or an instance of ' + . 'Zend_Acl_Role_Interface; %s given', + gettype($role) + )); + $e->setView($this->view); + throw $e; + } + + return $this; + } + + /** + * Returns ACL role to use when iterating pages, or null if it isn't set + * using {@link setRole()} or {@link setDefaultRole()} + * + * Implements {@link Zend_View_Helper_Navigation_Helper::getRole()}. + * + * @return string|Zend_Acl_Role_Interface|null role or null + */ + public function getRole() + { + if ($this->_role === null && self::$_defaultRole !== null) { + return self::$_defaultRole; + } + + return $this->_role; + } + + /** + * Sets whether ACL should be used + * + * Implements {@link Zend_View_Helper_Navigation_Helper::setUseAcl()}. + * + * @param bool $useAcl [optional] whether ACL + * should be used. + * Default is true. + * @return Zend_View_Helper_Navigation_HelperAbstract fluent interface, + * returns self + */ + public function setUseAcl($useAcl = true) + { + $this->_useAcl = (bool) $useAcl; + return $this; + } + + /** + * Returns whether ACL should be used + * + * Implements {@link Zend_View_Helper_Navigation_Helper::getUseAcl()}. + * + * @return bool whether ACL should be used + */ + public function getUseAcl() + { + return $this->_useAcl; + } + + /** + * Return renderInvisible flag + * + * @return bool + */ + public function getRenderInvisible() + { + return $this->_renderInvisible; + } + + /** + * Render invisible items? + * + * @param bool $renderInvisible [optional] boolean flag + * @return Zend_View_Helper_Navigation_HelperAbstract fluent interface + * returns self + */ + public function setRenderInvisible($renderInvisible = true) + { + $this->_renderInvisible = (bool) $renderInvisible; + return $this; + } + + /** + * Sets whether translator should be used + * + * Implements {@link Zend_View_Helper_Navigation_Helper::setUseTranslator()}. + * + * @param bool $useTranslator [optional] whether + * translator should be + * used. Default is true. + * @return Zend_View_Helper_Navigation_HelperAbstract fluent interface, + * returns self + */ + public function setUseTranslator($useTranslator = true) + { + $this->_useTranslator = (bool) $useTranslator; + return $this; + } + + /** + * Returns whether translator should be used + * + * Implements {@link Zend_View_Helper_Navigation_Helper::getUseTranslator()}. + * + * @return bool whether translator should be used + */ + public function getUseTranslator() + { + return $this->_useTranslator; + } + + // Magic overloads: + + /** + * Magic overload: Proxy calls to the navigation container + * + * @param string $method method name in container + * @param array $arguments [optional] arguments to pass + * @return mixed returns what the container returns + * @throws Zend_Navigation_Exception if method does not exist in container + */ + public function __call($method, array $arguments = array()) + { + return call_user_func_array( + array($this->getContainer(), $method), + $arguments); + } + + /** + * Magic overload: Proxy to {@link render()}. + * + * This method will trigger an E_USER_ERROR if rendering the helper causes + * an exception to be thrown. + * + * Implements {@link Zend_View_Helper_Navigation_Helper::__toString()}. + * + * @return string + */ + public function __toString() + { + try { + return $this->render(); + } catch (Exception $e) { + $msg = get_class($e) . ': ' . $e->getMessage(); + trigger_error($msg, E_USER_ERROR); + return ''; + } + } + + // Public methods: + + /** + * Finds the deepest active page in the given container + * + * @param Zend_Navigation_Container $container container to search + * @param int|null $minDepth [optional] minimum depth + * required for page to be + * valid. Default is to use + * {@link getMinDepth()}. A + * null value means no minimum + * depth required. + * @param int|null $minDepth [optional] maximum depth + * a page can have to be + * valid. Default is to use + * {@link getMaxDepth()}. A + * null value means no maximum + * depth required. + * @return array an associative array with + * the values 'depth' and + * 'page', or an empty array + * if not found + */ + public function findActive(Zend_Navigation_Container $container, + $minDepth = null, + $maxDepth = -1) + { + if (!is_int($minDepth)) { + $minDepth = $this->getMinDepth(); + } + if ((!is_int($maxDepth) || $maxDepth < 0) && null !== $maxDepth) { + $maxDepth = $this->getMaxDepth(); + } + + $found = null; + $foundDepth = -1; + $iterator = new RecursiveIteratorIterator($container, + RecursiveIteratorIterator::CHILD_FIRST); + + foreach ($iterator as $page) { + $currDepth = $iterator->getDepth(); + if ($currDepth < $minDepth || !$this->accept($page)) { + // page is not accepted + continue; + } + + if ($page->isActive(false) && $currDepth > $foundDepth) { + // found an active page at a deeper level than before + $found = $page; + $foundDepth = $currDepth; + } + } + + if (is_int($maxDepth) && $foundDepth > $maxDepth) { + while ($foundDepth > $maxDepth) { + if (--$foundDepth < $minDepth) { + $found = null; + break; + } + + $found = $found->getParent(); + if (!$found instanceof Zend_Navigation_Page) { + $found = null; + break; + } + } + } + + if ($found) { + return array('page' => $found, 'depth' => $foundDepth); + } else { + return array(); + } + } + + /** + * Checks if the helper has a container + * + * Implements {@link Zend_View_Helper_Navigation_Helper::hasContainer()}. + * + * @return bool whether the helper has a container or not + */ + public function hasContainer() + { + return null !== $this->_container; + } + + /** + * Checks if the helper has an ACL instance + * + * Implements {@link Zend_View_Helper_Navigation_Helper::hasAcl()}. + * + * @return bool whether the helper has a an ACL instance or not + */ + public function hasAcl() + { + return null !== $this->_acl; + } + + /** + * Checks if the helper has an ACL role + * + * Implements {@link Zend_View_Helper_Navigation_Helper::hasRole()}. + * + * @return bool whether the helper has a an ACL role or not + */ + public function hasRole() + { + return null !== $this->_role; + } + + /** + * Checks if the helper has a translator + * + * Implements {@link Zend_View_Helper_Navigation_Helper::hasTranslator()}. + * + * @return bool whether the helper has a translator or not + */ + public function hasTranslator() + { + return null !== $this->_translator; + } + + /** + * Returns an HTML string containing an 'a' element for the given page + * + * @param Zend_Navigation_Page $page page to generate HTML for + * @return string HTML string for the given page + */ + public function htmlify(Zend_Navigation_Page $page) + { + // get label and title for translating + $label = $page->getLabel(); + $title = $page->getTitle(); + + if ($this->getUseTranslator() && $t = $this->getTranslator()) { + if (is_string($label) && !empty($label)) { + $label = $t->translate($label); + } + if (is_string($title) && !empty($title)) { + $title = $t->translate($title); + } + } + + // get attribs for anchor element + $attribs = array_merge( + array( + 'id' => $page->getId(), + 'title' => $title, + 'class' => $page->getClass(), + 'href' => $page->getHref(), + 'target' => $page->getTarget() + ), + $page->getCustomHtmlAttribs() + ); + + return '_htmlAttribs($attribs) . '>' + . $this->view->escape($label) + . ''; + } + + // Iterator filter methods: + + /** + * Determines whether a page should be accepted when iterating + * + * Rules: + * - If a page is not visible it is not accepted, unless RenderInvisible has + * been set to true. + * - If helper has no ACL, page is accepted + * - If helper has ACL, but no role, page is not accepted + * - If helper has ACL and role: + * - Page is accepted if it has no resource or privilege + * - Page is accepted if ACL allows page's resource or privilege + * - If page is accepted by the rules above and $recursive is true, the page + * will not be accepted if it is the descendant of a non-accepted page. + * + * @param Zend_Navigation_Page $page page to check + * @param bool $recursive [optional] if true, page will not + * be accepted if it is the + * descendant of a page that is not + * accepted. Default is true. + * @return bool whether page should be accepted + */ + public function accept(Zend_Navigation_Page $page, $recursive = true) + { + // accept by default + $accept = true; + + if (!$page->isVisible(false) && !$this->getRenderInvisible()) { + // don't accept invisible pages + $accept = false; + } elseif ($this->getUseAcl() && !$this->_acceptAcl($page)) { + // acl is not amused + $accept = false; + } + + if ($accept && $recursive) { + $parent = $page->getParent(); + if ($parent instanceof Zend_Navigation_Page) { + $accept = $this->accept($parent, true); + } + } + + return $accept; + } + + /** + * Determines whether a page should be accepted by ACL when iterating + * + * Rules: + * - If helper has no ACL, page is accepted + * - If page has a resource or privilege defined, page is accepted + * if the ACL allows access to it using the helper's role + * - If page has no resource or privilege, page is accepted + * + * @param Zend_Navigation_Page $page page to check + * @return bool whether page is accepted by ACL + */ + protected function _acceptAcl(Zend_Navigation_Page $page) + { + if (!$acl = $this->getAcl()) { + // no acl registered means don't use acl + return true; + } + + $role = $this->getRole(); + $resource = $page->getResource(); + $privilege = $page->getPrivilege(); + + if ($resource || $privilege) { + // determine using helper role and page resource/privilege + return $acl->isAllowed($role, $resource, $privilege); + } + + return true; + } + + // Util methods: + + /** + * Retrieve whitespace representation of $indent + * + * @param int|string $indent + * @return string + */ + protected function _getWhitespace($indent) + { + if (is_int($indent)) { + $indent = str_repeat(' ', $indent); + } + + return (string) $indent; + } + + /** + * Converts an associative array to a string of tag attributes. + * + * Overloads {@link Zend_View_Helper_HtmlElement::_htmlAttribs()}. + * + * @param array $attribs an array where each key-value pair is converted + * to an attribute name and value + * @return string an attribute string + */ + protected function _htmlAttribs($attribs) + { + // filter out null values and empty string values + foreach ($attribs as $key => $value) { + if ($value === null || (is_string($value) && !strlen($value))) { + unset($attribs[$key]); + } + } + + return parent::_htmlAttribs($attribs); + } + + /** + * Normalize an ID + * + * Extends {@link Zend_View_Helper_HtmlElement::_normalizeId()}. + * + * @param string $value ID + * @return string Normalized ID + */ + protected function _normalizeId($value) + { + if (false === $this->_skipPrefixForId) { + $prefix = $this->getPrefixForId(); + + if (strlen($prefix)) { + return $prefix . $value; + } + } + + return parent::_normalizeId($value); + } + + // Static methods: + + /** + * Sets default ACL to use if another ACL is not explicitly set + * + * @param Zend_Acl $acl [optional] ACL object. Default is null, which + * sets no ACL object. + * @return void + */ + public static function setDefaultAcl(Zend_Acl $acl = null) + { + self::$_defaultAcl = $acl; + } + + /** + * Sets default ACL role(s) to use when iterating pages if not explicitly + * set later with {@link setRole()} + * + * @param mixed $role [optional] role to set. Expects null, + * string, or an instance of + * {@link Zend_Acl_Role_Interface}. + * Default is null, which sets no default + * role. + * @throws Zend_View_Exception if role is invalid + * @return void + */ + public static function setDefaultRole($role = null) + { + if (null === $role || + is_string($role) || + $role instanceof Zend_Acl_Role_Interface) { + self::$_defaultRole = $role; + } else { + require_once 'Zend/View/Exception.php'; + throw new Zend_View_Exception( + '$role must be null|string|Zend_Acl_Role_Interface' + ); + } + } +} diff --git a/lib/zend/Zend/View/Helper/Navigation/Links.php b/lib/zend/Zend/View/Helper/Navigation/Links.php new file mode 100644 index 00000000000..5d05c1008b4 --- /dev/null +++ b/lib/zend/Zend/View/Helper/Navigation/Links.php @@ -0,0 +1,783 @@ + elements + * + * @category Zend + * @package Zend_View + * @subpackage Helper + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_View_Helper_Navigation_Links + extends Zend_View_Helper_Navigation_HelperAbstract +{ + /**#@+ + * Constants used for specifying which link types to find and render + * + * @var int + */ + const RENDER_ALTERNATE = 0x0001; + const RENDER_STYLESHEET = 0x0002; + const RENDER_START = 0x0004; + const RENDER_NEXT = 0x0008; + const RENDER_PREV = 0x0010; + const RENDER_CONTENTS = 0x0020; + const RENDER_INDEX = 0x0040; + const RENDER_GLOSSARY = 0x0080; + const RENDER_COPYRIGHT = 0x0100; + const RENDER_CHAPTER = 0x0200; + const RENDER_SECTION = 0x0400; + const RENDER_SUBSECTION = 0x0800; + const RENDER_APPENDIX = 0x1000; + const RENDER_HELP = 0x2000; + const RENDER_BOOKMARK = 0x4000; + const RENDER_CUSTOM = 0x8000; + const RENDER_ALL = 0xffff; + /**#@+**/ + + /** + * Maps render constants to W3C link types + * + * @var array + */ + protected static $_RELATIONS = array( + self::RENDER_ALTERNATE => 'alternate', + self::RENDER_STYLESHEET => 'stylesheet', + self::RENDER_START => 'start', + self::RENDER_NEXT => 'next', + self::RENDER_PREV => 'prev', + self::RENDER_CONTENTS => 'contents', + self::RENDER_INDEX => 'index', + self::RENDER_GLOSSARY => 'glossary', + self::RENDER_COPYRIGHT => 'copyright', + self::RENDER_CHAPTER => 'chapter', + self::RENDER_SECTION => 'section', + self::RENDER_SUBSECTION => 'subsection', + self::RENDER_APPENDIX => 'appendix', + self::RENDER_HELP => 'help', + self::RENDER_BOOKMARK => 'bookmark' + ); + + /** + * The helper's render flag + * + * @see render() + * @see setRenderFlag() + * @var int + */ + protected $_renderFlag = self::RENDER_ALL; + + /** + * Root container + * + * Used for preventing methods to traverse above the container given to + * the {@link render()} method. + * + * @see _findRoot() + * + * @var Zend_Navigation_Container + */ + protected $_root; + + /** + * View helper entry point: + * Retrieves helper and optionally sets container to operate on + * + * @param Zend_Navigation_Container $container [optional] container to + * operate on + * @return Zend_View_Helper_Navigation_Links fluent interface, returns + * self + */ + public function links(Zend_Navigation_Container $container = null) + { + if (null !== $container) { + $this->setContainer($container); + } + + return $this; + } + + /** + * Magic overload: Proxy calls to {@link findRelation()} or container + * + * Examples of finder calls: + * + * // METHOD // SAME AS + * $h->findRelNext($page); // $h->findRelation($page, 'rel', 'next') + * $h->findRevSection($page); // $h->findRelation($page, 'rev', 'section'); + * $h->findRelFoo($page); // $h->findRelation($page, 'rel', 'foo'); + * + * + * @param string $method method name + * @param array $arguments method arguments + * @throws Zend_Navigation_Exception if method does not exist in container + */ + public function __call($method, array $arguments = array()) + { + if (@preg_match('/find(Rel|Rev)(.+)/', $method, $match)) { + return $this->findRelation($arguments[0], + strtolower($match[1]), + strtolower($match[2])); + } + + return parent::__call($method, $arguments); + } + + // Accessors: + + /** + * Sets the helper's render flag + * + * The helper uses the bitwise '&' operator against the hex values of the + * render constants. This means that the flag can is "bitwised" value of + * the render constants. Examples: + * + * // render all links except glossary + * $flag = Zend_View_Helper_Navigation_Links:RENDER_ALL ^ + * Zend_View_Helper_Navigation_Links:RENDER_GLOSSARY; + * $helper->setRenderFlag($flag); + * + * // render only chapters and sections + * $flag = Zend_View_Helper_Navigation_Links:RENDER_CHAPTER | + * Zend_View_Helper_Navigation_Links:RENDER_SECTION; + * $helper->setRenderFlag($flag); + * + * // render only relations that are not native W3C relations + * $helper->setRenderFlag(Zend_View_Helper_Navigation_Links:RENDER_CUSTOM); + * + * // render all relations (default) + * $helper->setRenderFlag(Zend_View_Helper_Navigation_Links:RENDER_ALL); + * + * + * Note that custom relations can also be rendered directly using the + * {@link renderLink()} method. + * + * @param int $renderFlag render flag + * @return Zend_View_Helper_Navigation_Links fluent interface, returns self + */ + public function setRenderFlag($renderFlag) + { + $this->_renderFlag = (int) $renderFlag; + return $this; + } + + /** + * Returns the helper's render flag + * + * @return int render flag + */ + public function getRenderFlag() + { + return $this->_renderFlag; + } + + // Finder methods: + + /** + * Finds all relations (forward and reverse) for the given $page + * + * The form of the returned array: + * + * // $page denotes an instance of Zend_Navigation_Page + * $returned = array( + * 'rel' => array( + * 'alternate' => array($page, $page, $page), + * 'start' => array($page), + * 'next' => array($page), + * 'prev' => array($page), + * 'canonical' => array($page) + * ), + * 'rev' => array( + * 'section' => array($page) + * ) + * ); + * + * + * @param Zend_Navigation_Page $page page to find links for + * @return array related pages + */ + public function findAllRelations(Zend_Navigation_Page $page, + $flag = null) + { + if (!is_int($flag)) { + $flag = self::RENDER_ALL; + } + + $result = array('rel' => array(), 'rev' => array()); + $native = array_values(self::$_RELATIONS); + + foreach (array_keys($result) as $rel) { + $meth = 'getDefined' . ucfirst($rel); + $types = array_merge($native, array_diff($page->$meth(), $native)); + + foreach ($types as $type) { + if (!$relFlag = array_search($type, self::$_RELATIONS)) { + $relFlag = self::RENDER_CUSTOM; + } + if (!($flag & $relFlag)) { + continue; + } + if ($found = $this->findRelation($page, $rel, $type)) { + if (!is_array($found)) { + $found = array($found); + } + $result[$rel][$type] = $found; + } + } + } + + return $result; + } + + /** + * Finds relations of the given $rel=$type from $page + * + * This method will first look for relations in the page instance, then + * by searching the root container if nothing was found in the page. + * + * @param Zend_Navigation_Page $page page to find relations for + * @param string $rel relation, "rel" or "rev" + * @param string $type link type, e.g. 'start', 'next' + * @return Zend_Navigaiton_Page|array|null page(s), or null if not found + * @throws Zend_View_Exception if $rel is not "rel" or "rev" + */ + public function findRelation(Zend_Navigation_Page $page, $rel, $type) + { + if (!in_array($rel, array('rel', 'rev'))) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception(sprintf( + 'Invalid argument: $rel must be "rel" or "rev"; "%s" given', + $rel)); + $e->setView($this->view); + throw $e; + } + + if (!$result = $this->_findFromProperty($page, $rel, $type)) { + $result = $this->_findFromSearch($page, $rel, $type); + } + + return $result; + } + + /** + * Finds relations of given $type for $page by checking if the + * relation is specified as a property of $page + * + * @param Zend_Navigation_Page $page page to find relations for + * @param string $rel relation, 'rel' or 'rev' + * @param string $type link type, e.g. 'start', 'next' + * @return Zend_Navigation_Page|array|null page(s), or null if not found + */ + protected function _findFromProperty(Zend_Navigation_Page $page, $rel, $type) + { + $method = 'get' . ucfirst($rel); + if ($result = $page->$method($type)) { + if ($result = $this->_convertToPages($result)) { + if (!is_array($result)) { + $result = array($result); + } + + foreach ($result as $key => $page) { + if (!$this->accept($page)) { + unset($result[$key]); + } + } + + return count($result) == 1 ? $result[0] : $result; + } + } + + return null; + } + + /** + * Finds relations of given $rel=$type for $page by using the helper to + * search for the relation in the root container + * + * @param Zend_Navigation_Page $page page to find relations for + * @param string $rel relation, 'rel' or 'rev' + * @param string $type link type, e.g. 'start', 'next', etc + * @return array|null array of pages, or null if not found + */ + protected function _findFromSearch(Zend_Navigation_Page $page, $rel, $type) + { + $found = null; + + $method = 'search' . ucfirst($rel) . ucfirst($type); + if (method_exists($this, $method)) { + $found = $this->$method($page); + } + + return $found; + } + + // Search methods: + + /** + * Searches the root container for the forward 'start' relation of the given + * $page + * + * From {@link http://www.w3.org/TR/html4/types.html#type-links}: + * Refers to the first document in a collection of documents. This link type + * tells search engines which document is considered by the author to be the + * starting point of the collection. + * + * @param Zend_Navigation_Page $page page to find relation for + * @return Zend_Navigation_Page|null page or null + */ + public function searchRelStart(Zend_Navigation_Page $page) + { + $found = $this->_findRoot($page); + if (!$found instanceof Zend_Navigation_Page) { + $found->rewind(); + $found = $found->current(); + } + + if ($found === $page || !$this->accept($found)) { + $found = null; + } + + return $found; + } + + /** + * Searches the root container for the forward 'next' relation of the given + * $page + * + * From {@link http://www.w3.org/TR/html4/types.html#type-links}: + * Refers to the next document in a linear sequence of documents. User + * agents may choose to preload the "next" document, to reduce the perceived + * load time. + * + * @param Zend_Navigation_Page $page page to find relation for + * @return Zend_Navigation_Page|null page(s) or null + */ + public function searchRelNext(Zend_Navigation_Page $page) + { + $found = null; + $break = false; + $iterator = new RecursiveIteratorIterator($this->_findRoot($page), + RecursiveIteratorIterator::SELF_FIRST); + foreach ($iterator as $intermediate) { + if ($intermediate === $page) { + // current page; break at next accepted page + $break = true; + continue; + } + + if ($break && $this->accept($intermediate)) { + $found = $intermediate; + break; + } + } + + return $found; + } + + /** + * Searches the root container for the forward 'prev' relation of the given + * $page + * + * From {@link http://www.w3.org/TR/html4/types.html#type-links}: + * Refers to the previous document in an ordered series of documents. Some + * user agents also support the synonym "Previous". + * + * @param Zend_Navigation_Page $page page to find relation for + * @return Zend_Navigation_Page|null page or null + */ + public function searchRelPrev(Zend_Navigation_Page $page) + { + $found = null; + $prev = null; + $iterator = new RecursiveIteratorIterator( + $this->_findRoot($page), + RecursiveIteratorIterator::SELF_FIRST); + foreach ($iterator as $intermediate) { + if (!$this->accept($intermediate)) { + continue; + } + if ($intermediate === $page) { + $found = $prev; + break; + } + + $prev = $intermediate; + } + + return $found; + } + + /** + * Searches the root container for forward 'chapter' relations of the given + * $page + * + * From {@link http://www.w3.org/TR/html4/types.html#type-links}: + * Refers to a document serving as a chapter in a collection of documents. + * + * @param Zend_Navigation_Page $page page to find relation for + * @return Zend_Navigation_Page|array|null page(s) or null + */ + public function searchRelChapter(Zend_Navigation_Page $page) + { + $found = array(); + + // find first level of pages + $root = $this->_findRoot($page); + + // find start page(s) + $start = $this->findRelation($page, 'rel', 'start'); + if (!is_array($start)) { + $start = array($start); + } + + foreach ($root as $chapter) { + // exclude self and start page from chapters + if ($chapter !== $page && + !in_array($chapter, $start) && + $this->accept($chapter)) { + $found[] = $chapter; + } + } + + switch (count($found)) { + case 0: + return null; + case 1: + return $found[0]; + default: + return $found; + } + } + + /** + * Searches the root container for forward 'section' relations of the given + * $page + * + * From {@link http://www.w3.org/TR/html4/types.html#type-links}: + * Refers to a document serving as a section in a collection of documents. + * + * @param Zend_Navigation_Page $page page to find relation for + * @return Zend_Navigation_Page|array|null page(s) or null + */ + public function searchRelSection(Zend_Navigation_Page $page) + { + $found = array(); + + // check if given page has pages and is a chapter page + if ($page->hasPages() && $this->_findRoot($page)->hasPage($page)) { + foreach ($page as $section) { + if ($this->accept($section)) { + $found[] = $section; + } + } + } + + switch (count($found)) { + case 0: + return null; + case 1: + return $found[0]; + default: + return $found; + } + } + + /** + * Searches the root container for forward 'subsection' relations of the + * given $page + * + * From {@link http://www.w3.org/TR/html4/types.html#type-links}: + * Refers to a document serving as a subsection in a collection of + * documents. + * + * @param Zend_Navigation_Page $page page to find relation for + * @return Zend_Navigation_Page|array|null page(s) or null + */ + public function searchRelSubsection(Zend_Navigation_Page $page) + { + $found = array(); + + if ($page->hasPages()) { + // given page has child pages, loop chapters + foreach ($this->_findRoot($page) as $chapter) { + // is page a section? + if ($chapter->hasPage($page)) { + foreach ($page as $subsection) { + if ($this->accept($subsection)) { + $found[] = $subsection; + } + } + } + } + } + + switch (count($found)) { + case 0: + return null; + case 1: + return $found[0]; + default: + return $found; + } + } + + /** + * Searches the root container for the reverse 'section' relation of the + * given $page + * + * From {@link http://www.w3.org/TR/html4/types.html#type-links}: + * Refers to a document serving as a section in a collection of documents. + * + * @param Zend_Navigation_Page $page page to find relation for + * @return Zend_Navigation_Page|null page(s) or null + */ + public function searchRevSection(Zend_Navigation_Page $page) + { + $found = null; + + if ($parent = $page->getParent()) { + if ($parent instanceof Zend_Navigation_Page && + $this->_findRoot($page)->hasPage($parent)) { + $found = $parent; + } + } + + return $found; + } + + /** + * Searches the root container for the reverse 'section' relation of the + * given $page + * + * From {@link http://www.w3.org/TR/html4/types.html#type-links}: + * Refers to a document serving as a subsection in a collection of + * documents. + * + * @param Zend_Navigation_Page $page page to find relation for + * @return Zend_Navigation_Page|null page(s) or null + */ + public function searchRevSubsection(Zend_Navigation_Page $page) + { + $found = null; + + if ($parent = $page->getParent()) { + if ($parent instanceof Zend_Navigation_Page) { + $root = $this->_findRoot($page); + foreach ($root as $chapter) { + if ($chapter->hasPage($parent)) { + $found = $parent; + break; + } + } + } + } + + return $found; + } + + // Util methods: + + /** + * Returns the root container of the given page + * + * When rendering a container, the render method still store the given + * container as the root container, and unset it when done rendering. This + * makes sure finder methods will not traverse above the container given + * to the render method. + * + * @param Zend_Navigaiton_Page $page page to find root for + * @return Zend_Navigation_Container the root container of the given page + */ + protected function _findRoot(Zend_Navigation_Page $page) + { + if ($this->_root) { + return $this->_root; + } + + $root = $page; + + while ($parent = $page->getParent()) { + $root = $parent; + if ($parent instanceof Zend_Navigation_Page) { + $page = $parent; + } else { + break; + } + } + + return $root; + } + + /** + * Converts a $mixed value to an array of pages + * + * @param mixed $mixed mixed value to get page(s) from + * @param bool $recursive whether $value should be looped + * if it is an array or a config + * @return Zend_Navigation_Page|array|null empty if unable to convert + */ + protected function _convertToPages($mixed, $recursive = true) + { + if (is_object($mixed)) { + if ($mixed instanceof Zend_Navigation_Page) { + // value is a page instance; return directly + return $mixed; + } elseif ($mixed instanceof Zend_Navigation_Container) { + // value is a container; return pages in it + $pages = array(); + foreach ($mixed as $page) { + $pages[] = $page; + } + return $pages; + } elseif ($mixed instanceof Zend_Config) { + // convert config object to array and extract + return $this->_convertToPages($mixed->toArray(), $recursive); + } + } elseif (is_string($mixed)) { + // value is a string; make an URI page + return Zend_Navigation_Page::factory(array( + 'type' => 'uri', + 'uri' => $mixed + )); + } elseif (is_array($mixed) && !empty($mixed)) { + if ($recursive && is_numeric(key($mixed))) { + // first key is numeric; assume several pages + $pages = array(); + foreach ($mixed as $value) { + if ($value = $this->_convertToPages($value, false)) { + $pages[] = $value; + } + } + return $pages; + } else { + // pass array to factory directly + try { + $page = Zend_Navigation_Page::factory($mixed); + return $page; + } catch (Exception $e) { + } + } + } + + // nothing found + return null; + } + + // Render methods: + + /** + * Renders the given $page as a link element, with $attrib = $relation + * + * @param Zend_Navigation_Page $page the page to render the link for + * @param string $attrib the attribute to use for $type, + * either 'rel' or 'rev' + * @param string $relation relation type, muse be one of; + * alternate, appendix, bookmark, + * chapter, contents, copyright, + * glossary, help, home, index, next, + * prev, section, start, stylesheet, + * subsection + * @return string rendered link element + * @throws Zend_View_Exception if $attrib is invalid + */ + public function renderLink(Zend_Navigation_Page $page, $attrib, $relation) + { + if (!in_array($attrib, array('rel', 'rev'))) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception(sprintf( + 'Invalid relation attribute "%s", must be "rel" or "rev"', + $attrib)); + $e->setView($this->view); + throw $e; + } + + if (!$href = $page->getHref()) { + return ''; + } + + // TODO: add more attribs + // http://www.w3.org/TR/html401/struct/links.html#h-12.2 + $attribs = array( + $attrib => $relation, + 'href' => $href, + 'title' => $page->getLabel() + ); + + return '_htmlAttribs($attribs) . + $this->getClosingBracket(); + } + + // Zend_View_Helper_Navigation_Helper: + + /** + * Renders helper + * + * Implements {@link Zend_View_Helper_Navigation_Helper::render()}. + * + * @param Zend_Navigation_Container $container [optional] container to + * render. Default is to + * render the container + * registered in the helper. + * @return string helper output + */ + public function render(Zend_Navigation_Container $container = null) + { + if (null === $container) { + $container = $this->getContainer(); + } + + if ($active = $this->findActive($container)) { + $active = $active['page']; + } else { + // no active page + return ''; + } + + $output = ''; + $indent = $this->getIndent(); + $this->_root = $container; + + $result = $this->findAllRelations($active, $this->getRenderFlag()); + foreach ($result as $attrib => $types) { + foreach ($types as $relation => $pages) { + foreach ($pages as $page) { + if ($r = $this->renderLink($page, $attrib, $relation)) { + $output .= $indent . $r . $this->getEOL(); + } + } + } + } + + $this->_root = null; + + // return output (trim last newline by spec) + return strlen($output) ? rtrim($output, self::EOL) : ''; + } +} diff --git a/lib/zend/Zend/View/Helper/Navigation/Menu.php b/lib/zend/Zend/View/Helper/Navigation/Menu.php new file mode 100644 index 00000000000..da3faee84a8 --- /dev/null +++ b/lib/zend/Zend/View/Helper/Navigation/Menu.php @@ -0,0 +1,1099 @@ +setContainer($container); + } + + return $this; + } + + // Accessors: + + /** + * Sets CSS class to use for the first 'ul' element when rendering + * + * @param string $ulClass CSS class to set + * @return Zend_View_Helper_Navigation_Menu fluent interface, returns self + */ + public function setUlClass($ulClass) + { + if (is_string($ulClass)) { + $this->_ulClass = $ulClass; + } + + return $this; + } + + /** + * Returns CSS class to use for the first 'ul' element when rendering + * + * @return string CSS class + */ + public function getUlClass() + { + return $this->_ulClass; + } + + /** + * Sets unique identifier (id) to use for the first 'ul' element when + * rendering + * + * @param string|null $ulId Unique identifier (id) to set + * @return Zend_View_Helper_Navigation_Menu fluent interface, returns self + */ + public function setUlId($ulId) + { + if (is_string($ulId)) { + $this->_ulId = $ulId; + } + + return $this; + } + + /** + * Returns unique identifier (id) to use for the first 'ul' element when + * rendering + * + * @return string|null Unique identifier (id); Default is 'null' + */ + public function getUlId() + { + return $this->_ulId; + } + + /** + * Sets CSS class to use for the active elements when rendering + * + * @param string $activeClass CSS class to set + * @return Zend_View_Helper_Navigation_Menu fluent interface, returns self + */ + public function setActiveClass($activeClass) + { + if (is_string($activeClass)) { + $this->_activeClass = $activeClass; + } + + return $this; + } + + /** + * Returns CSS class to use for the active elements when rendering + * + * @return string CSS class + */ + public function getActiveClass() + { + return $this->_activeClass; + } + + /** + * Sets CSS class to use for the parent li elements when rendering + * + * @param string $parentClass CSS class to set to parents + * @return Zend_View_Helper_Navigation_Menu fluent interface, returns self + */ + public function setParentClass($parentClass) + { + if (is_string($parentClass)) { + $this->_parentClass = $parentClass; + } + + return $this; + } + + /** + * Returns CSS class to use for the parent lie elements when rendering + * + * @return string CSS class + */ + public function getParentClass() + { + return $this->_parentClass; + } + + /** + * Enables/disables rendering of parent class to the li element + * + * @param bool $flag [optional] render with parent + * class. Default is true. + * @return Zend_View_Helper_Navigation_Menu fluent interface, returns self + */ + public function setRenderParentClass($flag = true) + { + $this->_renderParentClass = (bool) $flag; + return $this; + } + + /** + * Returns flag indicating whether parent class should be rendered to the li + * element + * + * @return bool whether parent class should be rendered + */ + public function getRenderParentClass() + { + return $this->_renderParentClass; + } + + /** + * Sets a flag indicating whether only active branch should be rendered + * + * @param bool $flag [optional] render only active + * branch. Default is true. + * @return Zend_View_Helper_Navigation_Menu fluent interface, returns self + */ + public function setOnlyActiveBranch($flag = true) + { + $this->_onlyActiveBranch = (bool) $flag; + return $this; + } + + /** + * Returns a flag indicating whether only active branch should be rendered + * + * By default, this value is false, meaning the entire menu will be + * be rendered. + * + * @return bool whether only active branch should be rendered + */ + public function getOnlyActiveBranch() + { + return $this->_onlyActiveBranch; + } + + /** + * Sets a flag indicating whether to expand all sibling nodes of the active branch + * + * @param bool $flag [optional] expand all siblings of + * nodes in the active branch. Default is true. + * @return Zend_View_Helper_Navigation_Menu fluent interface, returns self + */ + public function setExpandSiblingNodesOfActiveBranch($flag = true) + { + $this->_expandSiblingNodesOfActiveBranch = (bool) $flag; + return $this; + } + + /** + * Returns a flag indicating whether to expand all sibling nodes of the active branch + * + * By default, this value is false, meaning the entire menu will be + * be rendered. + * + * @return bool whether siblings of nodes in the active branch should be expanded + */ + public function getExpandSiblingNodesOfActiveBranch() + { + return $this->_expandSiblingNodesOfActiveBranch; + } + + /** + * Enables/disables rendering of parents when only rendering active branch + * + * See {@link setOnlyActiveBranch()} for more information. + * + * @param bool $flag [optional] render parents when + * rendering active branch. + * Default is true. + * @return Zend_View_Helper_Navigation_Menu fluent interface, returns self + */ + public function setRenderParents($flag = true) + { + $this->_renderParents = (bool) $flag; + return $this; + } + + /** + * Returns flag indicating whether parents should be rendered when rendering + * only the active branch + * + * By default, this value is true. + * + * @return bool whether parents should be rendered + */ + public function getRenderParents() + { + return $this->_renderParents; + } + + /** + * Sets which partial view script to use for rendering menu + * + * @param string|array $partial partial view script or null. If + * an array is given, it is + * expected to contain two values; + * the partial view script to use, + * and the module where the script + * can be found. + * @return Zend_View_Helper_Navigation_Menu fluent interface, returns self + */ + public function setPartial($partial) + { + if (null === $partial || is_string($partial) || is_array($partial)) { + $this->_partial = $partial; + } + + return $this; + } + + /** + * Returns partial view script to use for rendering menu + * + * @return string|array|null + */ + public function getPartial() + { + return $this->_partial; + } + + /** + * Adds CSS class from page to li element + * + * Before: + * + *
  • + * Bar + *
  • + *
    + * + * After: + * + *
  • + * Bar + *
  • + *
    + * + * @param bool $flag [optional] adds CSS class from + * page to li element + * + * @return Zend_View_Helper_Navigation_Menu fluent interface, returns self + */ + public function addPageClassToLi($flag = true) + { + $this->_addPageClassToLi = (bool) $flag; + + return $this; + } + + /** + * Returns a flag indicating whether the CSS class from page to be added to + * li element + * + * @return bool + */ + public function getAddPageClassToLi() + { + return $this->_addPageClassToLi; + } + + /** + * Set the inner indentation string for using in {@link render()}, optionally + * a number of spaces to indent with + * + * @param string|int $indent indentation string or + * number of spaces + * @return Zend_View_Helper_Navigation_HelperAbstract fluent interface, + * returns self + */ + public function setInnerIndent($indent) + { + $this->_innerIndent = $this->_getWhitespace($indent); + + return $this; + } + + /** + * Returns inner indentation (format output is respected) + * + * @see getFormatOutput() + * + * @return string indentation string or an empty string + */ + public function getInnerIndent() + { + if (false === $this->getFormatOutput()) { + return ''; + } + + return $this->_innerIndent; + } + + // Public methods: + + /** + * Returns an HTML string containing an 'a' element for the given page if + * the page's href is not empty, and a 'span' element if it is empty + * + * Overrides {@link Zend_View_Helper_Navigation_Abstract::htmlify()}. + * + * @param Zend_Navigation_Page $page page to generate HTML for + * @return string HTML string for the given page + */ + public function htmlify(Zend_Navigation_Page $page) + { + // get label and title for translating + $label = $page->getLabel(); + $title = $page->getTitle(); + + // translate label and title? + if ($this->getUseTranslator() && $t = $this->getTranslator()) { + if (is_string($label) && !empty($label)) { + $label = $t->translate($label); + } + if (is_string($title) && !empty($title)) { + $title = $t->translate($title); + } + } + + // get attribs for element + $attribs = array( + 'id' => $page->getId(), + 'title' => $title, + ); + + if (false === $this->getAddPageClassToLi()) { + $attribs['class'] = $page->getClass(); + } + + // does page have a href? + if ($href = $page->getHref()) { + $element = 'a'; + $attribs['href'] = $href; + $attribs['target'] = $page->getTarget(); + $attribs['accesskey'] = $page->getAccessKey(); + } else { + $element = 'span'; + } + + // Add custom HTML attributes + $attribs = array_merge($attribs, $page->getCustomHtmlAttribs()); + + return '<' . $element . $this->_htmlAttribs($attribs) . '>' + . $this->view->escape($label) + . ''; + } + + /** + * Normalizes given render options + * + * @param array $options [optional] options to normalize + * @return array normalized options + */ + protected function _normalizeOptions(array $options = array()) + { + // Ident + if (isset($options['indent'])) { + $options['indent'] = $this->_getWhitespace($options['indent']); + } else { + $options['indent'] = $this->getIndent(); + } + + // Inner ident + if (isset($options['innerIndent'])) { + $options['innerIndent'] = + $this->_getWhitespace($options['innerIndent']); + } else { + $options['innerIndent'] = $this->getInnerIndent(); + } + + // UL class + if (isset($options['ulClass']) && $options['ulClass'] !== null) { + $options['ulClass'] = (string) $options['ulClass']; + } else { + $options['ulClass'] = $this->getUlClass(); + } + + // UL id + if (isset($options['ulId']) && $options['ulId'] !== null) { + $options['ulId'] = (string) $options['ulId']; + } else { + $options['ulId'] = $this->getUlId(); + } + + // Active class + if (isset($options['activeClass']) && $options['activeClass'] !== null + ) { + $options['activeClass'] = (string) $options['activeClass']; + } else { + $options['activeClass'] = $this->getActiveClass(); + } + + // Parent class + if (isset($options['parentClass']) && $options['parentClass'] !== null) { + $options['parentClass'] = (string) $options['parentClass']; + } else { + $options['parentClass'] = $this->getParentClass(); + } + + // Minimum depth + if (array_key_exists('minDepth', $options)) { + if (null !== $options['minDepth']) { + $options['minDepth'] = (int) $options['minDepth']; + } + } else { + $options['minDepth'] = $this->getMinDepth(); + } + + if ($options['minDepth'] < 0 || $options['minDepth'] === null) { + $options['minDepth'] = 0; + } + + // Maximum depth + if (array_key_exists('maxDepth', $options)) { + if (null !== $options['maxDepth']) { + $options['maxDepth'] = (int) $options['maxDepth']; + } + } else { + $options['maxDepth'] = $this->getMaxDepth(); + } + + // Only active branch + if (!isset($options['onlyActiveBranch'])) { + $options['onlyActiveBranch'] = $this->getOnlyActiveBranch(); + } + + // Expand sibling nodes of active branch + if (!isset($options['expandSiblingNodesOfActiveBranch'])) { + $options['expandSiblingNodesOfActiveBranch'] = $this->getExpandSiblingNodesOfActiveBranch(); + } + + // Render parents? + if (!isset($options['renderParents'])) { + $options['renderParents'] = $this->getRenderParents(); + } + + // Render parent class? + if (!isset($options['renderParentClass'])) { + $options['renderParentClass'] = $this->getRenderParentClass(); + } + + // Add page CSS class to LI element + if (!isset($options['addPageClassToLi'])) { + $options['addPageClassToLi'] = $this->getAddPageClassToLi(); + } + + return $options; + } + + // Render methods: + + /** + * Renders the deepest active menu within [$minDepth, $maxDeth], (called + * from {@link renderMenu()}) + * + * @param Zend_Navigation_Container $container container to render + * @param string $ulClass CSS class for first UL + * @param string $indent initial indentation + * @param string $innerIndent inner indentation + * @param int|null $minDepth minimum depth + * @param int|null $maxDepth maximum depth + * @param string|null $ulId unique identifier (id) + * for first UL + * @param bool $addPageClassToLi adds CSS class from + * page to li element + * @param string|null $activeClass CSS class for active + * element + * @param string $parentClass CSS class for parent + * li's + * @param bool $renderParentClass Render parent class? + * @return string rendered menu (HTML) + */ + protected function _renderDeepestMenu(Zend_Navigation_Container $container, + $ulClass, + $indent, + $innerIndent, + $minDepth, + $maxDepth, + $ulId, + $addPageClassToLi, + $activeClass, + $parentClass, + $renderParentClass) + { + if (!$active = $this->findActive($container, $minDepth - 1, $maxDepth)) { + return ''; + } + + // special case if active page is one below minDepth + if ($active['depth'] < $minDepth) { + if (!$active['page']->hasPages()) { + return ''; + } + } else if (!$active['page']->hasPages()) { + // found pages has no children; render siblings + $active['page'] = $active['page']->getParent(); + } else if (is_int($maxDepth) && $active['depth'] + 1 > $maxDepth) { + // children are below max depth; render siblings + $active['page'] = $active['page']->getParent(); + } + + $attribs = array( + 'class' => $ulClass, + 'id' => $ulId, + ); + + // We don't need a prefix for the menu ID (backup) + $skipValue = $this->_skipPrefixForId; + $this->skipPrefixForId(); + + $html = $indent . '_htmlAttribs($attribs) + . '>' + . $this->getEOL(); + + // Reset prefix for IDs + $this->_skipPrefixForId = $skipValue; + + foreach ($active['page'] as $subPage) { + if (!$this->accept($subPage)) { + continue; + } + + $liClass = ''; + if ($subPage->isActive(true) && $addPageClassToLi) { + $liClass = $this->_htmlAttribs( + array('class' => $activeClass . ' ' . $subPage->getClass()) + ); + } else if ($subPage->isActive(true)) { + $liClass = $this->_htmlAttribs(array('class' => $activeClass)); + } else if ($addPageClassToLi) { + $liClass = $this->_htmlAttribs( + array('class' => $subPage->getClass()) + ); + } + $html .= $indent . $innerIndent . '' . $this->getEOL(); + $html .= $indent . str_repeat($innerIndent, 2) . $this->htmlify($subPage) + . $this->getEOL(); + $html .= $indent . $innerIndent . '' . $this->getEOL(); + } + + $html .= $indent . ''; + + return $html; + } + + /** + * Renders a normal menu (called from {@link renderMenu()}) + * + * @param Zend_Navigation_Container $container container to render + * @param string $ulClass CSS class for first UL + * @param string $indent initial indentation + * @param string $innerIndent inner indentation + * @param int|null $minDepth minimum depth + * @param int|null $maxDepth maximum depth + * @param bool $onlyActive render only active branch? + * @param bool $expandSibs render siblings of active + * branch nodes? + * @param string|null $ulId unique identifier (id) + * for first UL + * @param bool $addPageClassToLi adds CSS class from + * page to li element + * @param string|null $activeClass CSS class for active + * element + * @param string $parentClass CSS class for parent + * li's + * @param bool $renderParentClass Render parent class? + * @return string rendered menu (HTML) + */ + protected function _renderMenu(Zend_Navigation_Container $container, + $ulClass, + $indent, + $innerIndent, + $minDepth, + $maxDepth, + $onlyActive, + $expandSibs, + $ulId, + $addPageClassToLi, + $activeClass, + $parentClass, + $renderParentClass) + { + $html = ''; + + // find deepest active + if ($found = $this->findActive($container, $minDepth, $maxDepth)) { + $foundPage = $found['page']; + $foundDepth = $found['depth']; + } else { + $foundPage = null; + } + + // create iterator + $iterator = new RecursiveIteratorIterator($container, + RecursiveIteratorIterator::SELF_FIRST); + if (is_int($maxDepth)) { + $iterator->setMaxDepth($maxDepth); + } + + // iterate container + $prevDepth = -1; + foreach ($iterator as $page) { + $depth = $iterator->getDepth(); + $isActive = $page->isActive(true); + if ($depth < $minDepth || !$this->accept($page)) { + // page is below minDepth or not accepted by acl/visibilty + continue; + } else if ($expandSibs && $depth > $minDepth) { + // page is not active itself, but might be in the active branch + $accept = false; + if ($foundPage) { + if ($foundPage->hasPage($page)) { + // accept if page is a direct child of the active page + $accept = true; + } else if ($page->getParent()->isActive(true)) { + // page is a sibling of the active branch... + $accept = true; + } + } + if (!$isActive && !$accept) { + continue; + } + } else if ($onlyActive && !$isActive) { + // page is not active itself, but might be in the active branch + $accept = false; + if ($foundPage) { + if ($foundPage->hasPage($page)) { + // accept if page is a direct child of the active page + $accept = true; + } else if ($foundPage->getParent()->hasPage($page)) { + // page is a sibling of the active page... + if (!$foundPage->hasPages() || + is_int($maxDepth) && $foundDepth + 1 > $maxDepth) { + // accept if active page has no children, or the + // children are too deep to be rendered + $accept = true; + } + } + } + + if (!$accept) { + continue; + } + } + + // make sure indentation is correct + $depth -= $minDepth; + $myIndent = $indent . str_repeat($innerIndent, $depth * 2); + + if ($depth > $prevDepth) { + $attribs = array(); + + // start new ul tag + if (0 == $depth) { + $attribs = array( + 'class' => $ulClass, + 'id' => $ulId, + ); + } + + // We don't need a prefix for the menu ID (backup) + $skipValue = $this->_skipPrefixForId; + $this->skipPrefixForId(); + + $html .= $myIndent . '_htmlAttribs($attribs) + . '>' + . $this->getEOL(); + + // Reset prefix for IDs + $this->_skipPrefixForId = $skipValue; + } else if ($prevDepth > $depth) { + // close li/ul tags until we're at current depth + for ($i = $prevDepth; $i > $depth; $i--) { + $ind = $indent . str_repeat($innerIndent, $i * 2); + $html .= $ind . $innerIndent . '' . $this->getEOL(); + $html .= $ind . '' . $this->getEOL(); + } + // close previous li tag + $html .= $myIndent . $innerIndent . '' . $this->getEOL(); + } else { + // close previous li tag + $html .= $myIndent . $innerIndent . '' . $this->getEOL(); + } + + // render li tag and page + $liClasses = array(); + // Is page active? + if ($isActive) { + $liClasses[] = $activeClass; + } + // Add CSS class from page to LI? + if ($addPageClassToLi) { + $liClasses[] = $page->getClass(); + } + // Add CSS class for parents to LI? + if ($renderParentClass && $page->hasChildren()) { + // Check max depth + if ((is_int($maxDepth) && ($depth + 1 < $maxDepth)) + || !is_int($maxDepth) + ) { + $liClasses[] = $parentClass; + } + } + + $html .= $myIndent . $innerIndent . '_htmlAttribs(array('class' => implode(' ', $liClasses))) + . '>' . $this->getEOL() + . $myIndent . str_repeat($innerIndent, 2) + . $this->htmlify($page) + . $this->getEOL(); + + // store as previous depth for next iteration + $prevDepth = $depth; + } + + if ($html) { + // done iterating container; close open ul/li tags + for ($i = $prevDepth+1; $i > 0; $i--) { + $myIndent = $indent . str_repeat($innerIndent . $innerIndent, $i - 1); + $html .= $myIndent . $innerIndent . '' . $this->getEOL() + . $myIndent . '' . $this->getEOL(); + } + $html = rtrim($html, $this->getEOL()); + } + + return $html; + } + + /** + * Renders helper + * + * Renders a HTML 'ul' for the given $container. If $container is not given, + * the container registered in the helper will be used. + * + * Available $options: + * + * + * @param Zend_Navigation_Container $container [optional] container to + * create menu from. Default + * is to use the container + * retrieved from + * {@link getContainer()}. + * @param array $options [optional] options for + * controlling rendering + * @return string rendered menu + */ + public function renderMenu(Zend_Navigation_Container $container = null, + array $options = array()) + { + if (null === $container) { + $container = $this->getContainer(); + } + + $options = $this->_normalizeOptions($options); + + if ($options['onlyActiveBranch'] && !$options['renderParents']) { + $html = $this->_renderDeepestMenu( + $container, + $options['ulClass'], + $options['indent'], + $options['innerIndent'], + $options['minDepth'], + $options['maxDepth'], + $options['ulId'], + $options['addPageClassToLi'], + $options['activeClass'], + $options['parentClass'], + $options['renderParentClass'] + ); + } else { + $html = $this->_renderMenu( + $container, + $options['ulClass'], + $options['indent'], + $options['innerIndent'], + $options['minDepth'], + $options['maxDepth'], + $options['onlyActiveBranch'], + $options['expandSiblingNodesOfActiveBranch'], + $options['ulId'], + $options['addPageClassToLi'], + $options['activeClass'], + $options['parentClass'], + $options['renderParentClass'] + ); + } + + return $html; + } + + /** + * Renders the inner-most sub menu for the active page in the $container + * + * This is a convenience method which is equivalent to the following call: + * + * renderMenu($container, array( + * 'indent' => $indent, + * 'ulClass' => $ulClass, + * 'minDepth' => null, + * 'maxDepth' => null, + * 'onlyActiveBranch' => true, + * 'renderParents' => false + * )); + * + * + * @param Zend_Navigation_Container $container [optional] container to + * render. Default is to render + * the container registered in + * the helper. + * @param string|null $ulClass [optional] CSS class to + * use for UL element. Default + * is to use the value from + * {@link getUlClass()}. + * @param string|int $indent [optional] indentation as + * a string or number of + * spaces. Default is to use + * the value retrieved from + * {@link getIndent()}. + * @param string|null $ulId [optional] Unique identifier + * (id) use for UL element + * @param bool $addPageClassToLi adds CSS class from + * page to li element + * @param string|int $innerIndent [optional] inner + * indentation as a string + * or number of spaces. + * Default is to use the + * {@link getInnerIndent()}. + * @return string rendered content + */ + public function renderSubMenu(Zend_Navigation_Container $container = null, + $ulClass = null, + $indent = null, + $ulId = null, + $addPageClassToLi = false, + $innerIndent = null) + { + return $this->renderMenu($container, array( + 'indent' => $indent, + 'innerIndent' => $innerIndent, + 'ulClass' => $ulClass, + 'minDepth' => null, + 'maxDepth' => null, + 'onlyActiveBranch' => true, + 'renderParents' => false, + 'ulId' => $ulId, + 'addPageClassToLi' => $addPageClassToLi, + )); + } + + /** + * Renders the given $container by invoking the partial view helper + * + * The container will simply be passed on as a model to the view script + * as-is, and will be available in the partial script as 'container', e.g. + * echo 'Number of pages: ', count($this->container);. + * + * @param Zend_Navigation_Container $container [optional] container to + * pass to view script. Default + * is to use the container + * registered in the helper. + * @param string|array $partial [optional] partial view + * script to use. Default is to + * use the partial registered + * in the helper. If an array + * is given, it is expected to + * contain two values; the + * partial view script to use, + * and the module where the + * script can be found. + * @return string helper output + * + * @throws Zend_View_Exception When no partial script is set + */ + public function renderPartial(Zend_Navigation_Container $container = null, + $partial = null) + { + if (null === $container) { + $container = $this->getContainer(); + } + + if (null === $partial) { + $partial = $this->getPartial(); + } + + if (empty($partial)) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception( + 'Unable to render menu: No partial view script provided' + ); + $e->setView($this->view); + throw $e; + } + + $model = array( + 'container' => $container + ); + + if (is_array($partial)) { + if (count($partial) != 2) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception( + 'Unable to render menu: A view partial supplied as ' + . 'an array must contain two values: partial view ' + . 'script and module where script can be found' + ); + $e->setView($this->view); + throw $e; + } + + return $this->view->partial($partial[0], $partial[1], $model); + } + + return $this->view->partial($partial, null, $model); + } + + // Zend_View_Helper_Navigation_Helper: + + /** + * Renders menu + * + * Implements {@link Zend_View_Helper_Navigation_Helper::render()}. + * + * If a partial view is registered in the helper, the menu will be rendered + * using the given partial script. If no partial is registered, the menu + * will be rendered as an 'ul' element by the helper's internal method. + * + * @see renderPartial() + * @see renderMenu() + * + * @param Zend_Navigation_Container $container [optional] container to + * render. Default is to + * render the container + * registered in the helper. + * @return string helper output + */ + public function render(Zend_Navigation_Container $container = null) + { + if ($partial = $this->getPartial()) { + return $this->renderPartial($container, $partial); + } else { + return $this->renderMenu($container); + } + } +} diff --git a/lib/zend/Zend/View/Helper/Navigation/Sitemap.php b/lib/zend/Zend/View/Helper/Navigation/Sitemap.php new file mode 100644 index 00000000000..b93808a2c6b --- /dev/null +++ b/lib/zend/Zend/View/Helper/Navigation/Sitemap.php @@ -0,0 +1,444 @@ + tag + * + * @var string + */ + const SITEMAP_NS = 'http://www.sitemaps.org/schemas/sitemap/0.9'; + + /** + * Schema URL + * + * @var string + */ + const SITEMAP_XSD = 'http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd'; + + /** + * Whether the XML declaration should be included in XML output + * + * @var bool + */ + protected $_useXmlDeclaration = true; + + /** + * Whether sitemap should be validated using Zend_Validate_Sitemap_* + * + * @var bool + */ + protected $_useSitemapValidators = true; + + /** + * Whether sitemap should be schema validated when generated + * + * @var bool + */ + protected $_useSchemaValidation = false; + + /** + * Server url + * + * @var string + */ + protected $_serverUrl; + + /** + * View helper entry point: + * Retrieves helper and optionally sets container to operate on + * + * @param Zend_Navigation_Container $container [optional] container to + * operate on + * @return Zend_View_Helper_Navigation_Sitemap fluent interface, returns + * self + */ + public function sitemap(Zend_Navigation_Container $container = null) + { + if (null !== $container) { + $this->setContainer($container); + } + + return $this; + } + + // Accessors: + + /** + * Sets whether the XML declaration should be used in output + * + * @param bool $useXmlDecl whether XML delcaration + * should be rendered + * @return Zend_View_Helper_Navigation_Sitemap fluent interface, returns + * self + */ + public function setUseXmlDeclaration($useXmlDecl) + { + $this->_useXmlDeclaration = (bool) $useXmlDecl; + return $this; + } + + /** + * Returns whether the XML declaration should be used in output + * + * @return bool whether the XML declaration should be used in output + */ + public function getUseXmlDeclaration() + { + return $this->_useXmlDeclaration; + } + + /** + * Sets whether sitemap should be validated using Zend_Validate_Sitemap_* + * + * @param bool $useSitemapValidators whether sitemap validators + * should be used + * @return Zend_View_Helper_Navigation_Sitemap fluent interface, returns + * self + */ + public function setUseSitemapValidators($useSitemapValidators) + { + $this->_useSitemapValidators = (bool) $useSitemapValidators; + return $this; + } + + /** + * Returns whether sitemap should be validated using Zend_Validate_Sitemap_* + * + * @return bool whether sitemap should be validated using validators + */ + public function getUseSitemapValidators() + { + return $this->_useSitemapValidators; + } + + /** + * Sets whether sitemap should be schema validated when generated + * + * @param bool $schemaValidation whether sitemap should + * validated using XSD Schema + * @return Zend_View_Helper_Navigation_Sitemap fluent interface, returns + * self + */ + public function setUseSchemaValidation($schemaValidation) + { + $this->_useSchemaValidation = (bool) $schemaValidation; + return $this; + } + + /** + * Returns true if sitemap should be schema validated when generated + * + * @return bool + */ + public function getUseSchemaValidation() + { + return $this->_useSchemaValidation; + } + + /** + * Sets server url (scheme and host-related stuff without request URI) + * + * E.g. http://www.example.com + * + * @param string $serverUrl server URL to set (only + * scheme and host) + * @throws Zend_Uri_Exception if invalid server URL + * @return Zend_View_Helper_Navigation_Sitemap fluent interface, returns + * self + */ + public function setServerUrl($serverUrl) + { + require_once 'Zend/Uri.php'; + $uri = Zend_Uri::factory($serverUrl); + $uri->setFragment(''); + $uri->setPath(''); + $uri->setQuery(''); + + if ($uri->valid()) { + $this->_serverUrl = $uri->getUri(); + } else { + require_once 'Zend/Uri/Exception.php'; + $e = new Zend_Uri_Exception(sprintf( + 'Invalid server URL: "%s"', + $serverUrl)); + $e->setView($this->view); + throw $e; + } + + return $this; + } + + /** + * Returns server URL + * + * @return string server URL + */ + public function getServerUrl() + { + if (!isset($this->_serverUrl)) { + $this->_serverUrl = $this->view->serverUrl(); + } + + return $this->_serverUrl; + } + + // Helper methods: + + /** + * Escapes string for XML usage + * + * @param string $string string to escape + * @return string escaped string + */ + protected function _xmlEscape($string) + { + $enc = 'UTF-8'; + if ($this->view instanceof Zend_View_Interface + && method_exists($this->view, 'getEncoding') + ) { + $enc = $this->view->getEncoding(); + } + + // do not encode existing HTML entities + return htmlspecialchars($string, ENT_QUOTES, $enc, false); + } + + // Public methods: + + /** + * Returns an escaped absolute URL for the given page + * + * @param Zend_Navigation_Page $page page to get URL from + * @return string + */ + public function url(Zend_Navigation_Page $page) + { + $href = $page->getHref(); + + if (!isset($href{0})) { + // no href + return ''; + } elseif ($href{0} == '/') { + // href is relative to root; use serverUrl helper + $url = $this->getServerUrl() . $href; + } elseif (preg_match('/^[a-z]+:/im', (string) $href)) { + // scheme is given in href; assume absolute URL already + $url = (string) $href; + } else { + // href is relative to current document; use url helpers + $url = $this->getServerUrl() + . rtrim($this->view->url(), '/') . '/' + . $href; + } + + return $this->_xmlEscape($url); + } + + /** + * Returns a DOMDocument containing the Sitemap XML for the given container + * + * @param Zend_Navigation_Container $container [optional] container to get + * breadcrumbs from, defaults + * to what is registered in the + * helper + * @return DOMDocument DOM representation of the + * container + * @throws Zend_View_Exception if schema validation is on + * and the sitemap is invalid + * according to the sitemap + * schema, or if sitemap + * validators are used and the + * loc element fails validation + */ + public function getDomSitemap(Zend_Navigation_Container $container = null) + { + if (null === $container) { + $container = $this->getContainer(); + } + + // check if we should validate using our own validators + if ($this->getUseSitemapValidators()) { + require_once 'Zend/Validate/Sitemap/Changefreq.php'; + require_once 'Zend/Validate/Sitemap/Lastmod.php'; + require_once 'Zend/Validate/Sitemap/Loc.php'; + require_once 'Zend/Validate/Sitemap/Priority.php'; + + // create validators + $locValidator = new Zend_Validate_Sitemap_Loc(); + $lastmodValidator = new Zend_Validate_Sitemap_Lastmod(); + $changefreqValidator = new Zend_Validate_Sitemap_Changefreq(); + $priorityValidator = new Zend_Validate_Sitemap_Priority(); + } + + // create document + $dom = new DOMDocument('1.0', 'UTF-8'); + $dom->formatOutput = $this->getFormatOutput(); + + // ...and urlset (root) element + $urlSet = $dom->createElementNS(self::SITEMAP_NS, 'urlset'); + $dom->appendChild($urlSet); + + // create iterator + $iterator = new RecursiveIteratorIterator($container, + RecursiveIteratorIterator::SELF_FIRST); + + $maxDepth = $this->getMaxDepth(); + if (is_int($maxDepth)) { + $iterator->setMaxDepth($maxDepth); + } + $minDepth = $this->getMinDepth(); + if (!is_int($minDepth) || $minDepth < 0) { + $minDepth = 0; + } + + // iterate container + foreach ($iterator as $page) { + if ($iterator->getDepth() < $minDepth || !$this->accept($page)) { + // page should not be included + continue; + } + + // get absolute url from page + if (!$url = $this->url($page)) { + // skip page if it has no url (rare case) + continue; + } + + // create url node for this page + $urlNode = $dom->createElementNS(self::SITEMAP_NS, 'url'); + $urlSet->appendChild($urlNode); + + if ($this->getUseSitemapValidators() && + !$locValidator->isValid($url)) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception(sprintf( + 'Encountered an invalid URL for Sitemap XML: "%s"', + $url)); + $e->setView($this->view); + throw $e; + } + + // put url in 'loc' element + $urlNode->appendChild($dom->createElementNS(self::SITEMAP_NS, + 'loc', $url)); + + // add 'lastmod' element if a valid lastmod is set in page + if (isset($page->lastmod)) { + $lastmod = strtotime((string) $page->lastmod); + + // prevent 1970-01-01... + if ($lastmod !== false) { + $lastmod = date('c', $lastmod); + } + + if (!$this->getUseSitemapValidators() || + $lastmodValidator->isValid($lastmod)) { + $urlNode->appendChild( + $dom->createElementNS(self::SITEMAP_NS, 'lastmod', + $lastmod) + ); + } + } + + // add 'changefreq' element if a valid changefreq is set in page + if (isset($page->changefreq)) { + $changefreq = $page->changefreq; + if (!$this->getUseSitemapValidators() || + $changefreqValidator->isValid($changefreq)) { + $urlNode->appendChild( + $dom->createElementNS(self::SITEMAP_NS, 'changefreq', + $changefreq) + ); + } + } + + // add 'priority' element if a valid priority is set in page + if (isset($page->priority)) { + $priority = $page->priority; + if (!$this->getUseSitemapValidators() || + $priorityValidator->isValid($priority)) { + $urlNode->appendChild( + $dom->createElementNS(self::SITEMAP_NS, 'priority', + $priority) + ); + } + } + } + + // validate using schema if specified + if ($this->getUseSchemaValidation()) { + if (!@$dom->schemaValidate(self::SITEMAP_XSD)) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception(sprintf( + 'Sitemap is invalid according to XML Schema at "%s"', + self::SITEMAP_XSD)); + $e->setView($this->view); + throw $e; + } + } + + return $dom; + } + + // Zend_View_Helper_Navigation_Helper: + + /** + * Renders helper + * + * Implements {@link Zend_View_Helper_Navigation_Helper::render()}. + * + * @param Zend_Navigation_Container $container [optional] container to + * render. Default is to + * render the container + * registered in the helper. + * @return string helper output + */ + public function render(Zend_Navigation_Container $container = null) + { + $dom = $this->getDomSitemap($container); + + $xml = $this->getUseXmlDeclaration() ? + $dom->saveXML() : + $dom->saveXML($dom->documentElement); + + return rtrim($xml, self::EOL); + } +} diff --git a/lib/zend/Zend/View/Helper/PaginationControl.php b/lib/zend/Zend/View/Helper/PaginationControl.php new file mode 100644 index 00000000000..6f5929a22dd --- /dev/null +++ b/lib/zend/Zend/View/Helper/PaginationControl.php @@ -0,0 +1,145 @@ +view = $view; + return $this; + } + + /** + * Sets the default view partial. + * + * @param string|array $partial View partial + */ + public static function setDefaultViewPartial($partial) + { + self::$_defaultViewPartial = $partial; + } + + /** + * Gets the default view partial + * + * @return string|array + */ + public static function getDefaultViewPartial() + { + return self::$_defaultViewPartial; + } + + /** + * Render the provided pages. This checks if $view->paginator is set and, + * if so, uses that. Also, if no scrolling style or partial are specified, + * the defaults will be used (if set). + * + * @param Zend_Paginator (Optional) $paginator + * @param string $scrollingStyle (Optional) Scrolling style + * @param string $partial (Optional) View partial + * @param array|string $params (Optional) params to pass to the partial + * @return string + * @throws Zend_View_Exception + */ + public function paginationControl(Zend_Paginator $paginator = null, $scrollingStyle = null, $partial = null, $params = null) + { + if ($paginator === null) { + if (isset($this->view->paginator) and $this->view->paginator !== null and $this->view->paginator instanceof Zend_Paginator) { + $paginator = $this->view->paginator; + } else { + /** + * @see Zend_View_Exception + */ + require_once 'Zend/View/Exception.php'; + + $e = new Zend_View_Exception('No paginator instance provided or incorrect type'); + $e->setView($this->view); + throw $e; + } + } + + if ($partial === null) { + if (self::$_defaultViewPartial === null) { + /** + * @see Zend_View_Exception + */ + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception('No view partial provided and no default set'); + $e->setView($this->view); + throw $e; + } + + $partial = self::$_defaultViewPartial; + } + + $pages = get_object_vars($paginator->getPages($scrollingStyle)); + + if ($params !== null) { + $pages = array_merge($pages, (array) $params); + } + + if (is_array($partial)) { + if (count($partial) != 2) { + /** + * @see Zend_View_Exception + */ + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception('A view partial supplied as an array must contain two values: the filename and its module'); + $e->setView($this->view); + throw $e; + } + + if ($partial[1] !== null) { + return $this->view->partial($partial[0], $partial[1], $pages); + } + + $partial = $partial[0]; + } + + return $this->view->partial($partial, $pages); + } +} diff --git a/lib/zend/Zend/View/Helper/Partial.php b/lib/zend/Zend/View/Helper/Partial.php new file mode 100644 index 00000000000..733f563b9bb --- /dev/null +++ b/lib/zend/Zend/View/Helper/Partial.php @@ -0,0 +1,153 @@ +cloneView(); + if (isset($this->partialCounter)) { + $view->partialCounter = $this->partialCounter; + } + if (isset($this->partialTotalCount)) { + $view->partialTotalCount = $this->partialTotalCount; + } + + if ((null !== $module) && is_string($module)) { + require_once 'Zend/Controller/Front.php'; + $moduleDir = Zend_Controller_Front::getInstance()->getControllerDirectory($module); + if (null === $moduleDir) { + require_once 'Zend/View/Helper/Partial/Exception.php'; + $e = new Zend_View_Helper_Partial_Exception('Cannot render partial; module does not exist'); + $e->setView($this->view); + throw $e; + } + $viewsDir = dirname($moduleDir) . '/views'; + $view->addBasePath($viewsDir); + } elseif ((null == $model) && (null !== $module) + && (is_array($module) || is_object($module))) + { + $model = $module; + } + + if (!empty($model)) { + if (is_array($model)) { + $view->assign($model); + } elseif (is_object($model)) { + if (null !== ($objectKey = $this->getObjectKey())) { + $view->assign($objectKey, $model); + } elseif (method_exists($model, 'toArray')) { + $view->assign($model->toArray()); + } else { + $view->assign(get_object_vars($model)); + } + } + } + + return $view->render($name); + } + + /** + * Clone the current View + * + * @return Zend_View_Interface + */ + public function cloneView() + { + $view = clone $this->view; + $view->clearVars(); + return $view; + } + + /** + * Set object key + * + * @param string $key + * @return Zend_View_Helper_Partial + */ + public function setObjectKey($key) + { + if (null === $key) { + $this->_objectKey = null; + } else { + $this->_objectKey = (string) $key; + } + + return $this; + } + + /** + * Retrieve object key + * + * The objectKey is the variable to which an object in the iterator will be + * assigned. + * + * @return null|string + */ + public function getObjectKey() + { + return $this->_objectKey; + } +} diff --git a/lib/zend/Zend/View/Helper/Partial/Exception.php b/lib/zend/Zend/View/Helper/Partial/Exception.php new file mode 100644 index 00000000000..9355fd35240 --- /dev/null +++ b/lib/zend/Zend/View/Helper/Partial/Exception.php @@ -0,0 +1,39 @@ +setView($this->view); + throw $e; + } + + if (is_object($model) + && (!$model instanceof Traversable) + && method_exists($model, 'toArray') + ) { + $model = $model->toArray(); + } + + $content = ''; + // reset the counter if it's call again + $this->partialCounter = 0; + $this->partialTotalCount = count($model); + + foreach ($model as $item) { + // increment the counter variable + $this->partialCounter++; + + $content .= $this->partial($name, $module, $item); + } + + return $content; + } +} diff --git a/lib/zend/Zend/View/Helper/Placeholder.php b/lib/zend/Zend/View/Helper/Placeholder.php new file mode 100644 index 00000000000..c726b401db6 --- /dev/null +++ b/lib/zend/Zend/View/Helper/Placeholder.php @@ -0,0 +1,87 @@ +_registry = Zend_View_Helper_Placeholder_Registry::getRegistry(); + } + + + /** + * Placeholder helper + * + * @param string $name + * @return Zend_View_Helper_Placeholder_Container_Abstract + */ + public function placeholder($name) + { + $name = (string) $name; + return $this->_registry->getContainer($name); + } + + /** + * Retrieve the registry + * + * @return Zend_View_Helper_Placeholder_Registry + */ + public function getRegistry() + { + return $this->_registry; + } +} diff --git a/lib/zend/Zend/View/Helper/Placeholder/Container.php b/lib/zend/Zend/View/Helper/Placeholder/Container.php new file mode 100644 index 00000000000..10e706d3b6e --- /dev/null +++ b/lib/zend/Zend/View/Helper/Placeholder/Container.php @@ -0,0 +1,36 @@ +exchangeArray(array($value)); + } + + /** + * Prepend a value to the top of the container + * + * @param mixed $value + * @return void + */ + public function prepend($value) + { + $values = $this->getArrayCopy(); + array_unshift($values, $value); + $this->exchangeArray($values); + } + + /** + * Retrieve container value + * + * If single element registered, returns that element; otherwise, + * serializes to array. + * + * @return mixed + */ + public function getValue() + { + if (1 == count($this)) { + $keys = $this->getKeys(); + $key = array_shift($keys); + return $this[$key]; + } + + return $this->getArrayCopy(); + } + + /** + * Set prefix for __toString() serialization + * + * @param string $prefix + * @return Zend_View_Helper_Placeholder_Container + */ + public function setPrefix($prefix) + { + $this->_prefix = (string) $prefix; + return $this; + } + + /** + * Retrieve prefix + * + * @return string + */ + public function getPrefix() + { + return $this->_prefix; + } + + /** + * Set postfix for __toString() serialization + * + * @param string $postfix + * @return Zend_View_Helper_Placeholder_Container + */ + public function setPostfix($postfix) + { + $this->_postfix = (string) $postfix; + return $this; + } + + /** + * Retrieve postfix + * + * @return string + */ + public function getPostfix() + { + return $this->_postfix; + } + + /** + * Set separator for __toString() serialization + * + * Used to implode elements in container + * + * @param string $separator + * @return Zend_View_Helper_Placeholder_Container + */ + public function setSeparator($separator) + { + $this->_separator = (string) $separator; + return $this; + } + + /** + * Retrieve separator + * + * @return string + */ + public function getSeparator() + { + return $this->_separator; + } + + /** + * Set the indentation string for __toString() serialization, + * optionally, if a number is passed, it will be the number of spaces + * + * @param string|int $indent + * @return Zend_View_Helper_Placeholder_Container_Abstract + */ + public function setIndent($indent) + { + $this->_indent = $this->getWhitespace($indent); + return $this; + } + + /** + * Retrieve indentation + * + * @return string + */ + public function getIndent() + { + return $this->_indent; + } + + /** + * Retrieve whitespace representation of $indent + * + * @param int|string $indent + * @return string + */ + public function getWhitespace($indent) + { + if (is_int($indent)) { + $indent = str_repeat(' ', $indent); + } + + return (string) $indent; + } + + /** + * Start capturing content to push into placeholder + * + * @param int|string $type How to capture content into placeholder; append, prepend, or set + * @param null $key + * @throws Zend_View_Helper_Placeholder_Container_Exception + * @return void + */ + public function captureStart($type = Zend_View_Helper_Placeholder_Container_Abstract::APPEND, $key = null) + { + if ($this->_captureLock) { + require_once 'Zend/View/Helper/Placeholder/Container/Exception.php'; + $e = new Zend_View_Helper_Placeholder_Container_Exception('Cannot nest placeholder captures for the same placeholder'); + $e->setView($this->view); + throw $e; + } + + $this->_captureLock = true; + $this->_captureType = $type; + if ((null !== $key) && is_scalar($key)) { + $this->_captureKey = (string) $key; + } + ob_start(); + } + + /** + * End content capture + * + * @return void + */ + public function captureEnd() + { + $data = ob_get_clean(); + $key = null; + $this->_captureLock = false; + if (null !== $this->_captureKey) { + $key = $this->_captureKey; + } + switch ($this->_captureType) { + case self::SET: + if (null !== $key) { + $this[$key] = $data; + } else { + $this->exchangeArray(array($data)); + } + break; + case self::PREPEND: + if (null !== $key) { + $array = array($key => $data); + $values = $this->getArrayCopy(); + $final = $array + $values; + $this->exchangeArray($final); + } else { + $this->prepend($data); + } + break; + case self::APPEND: + default: + if (null !== $key) { + if (empty($this[$key])) { + $this[$key] = $data; + } else { + $this[$key] .= $data; + } + } else { + $this[$this->nextIndex()] = $data; + } + break; + } + } + + /** + * Get keys + * + * @return array + */ + public function getKeys() + { + $array = $this->getArrayCopy(); + return array_keys($array); + } + + /** + * Next Index + * + * as defined by the PHP manual + * @return int + */ + public function nextIndex() + { + $keys = $this->getKeys(); + if (0 == count($keys)) { + return 0; + } + + return $nextIndex = max($keys) + 1; + } + + /** + * Render the placeholder + * + * @param null $indent + * @return string + */ + public function toString($indent = null) + { + // Check items + if (0 === $this->count()) { + return ''; + } + + $indent = ($indent !== null) + ? $this->getWhitespace($indent) + : $this->getIndent(); + + $items = $this->getArrayCopy(); + $return = $indent + . $this->getPrefix() + . implode($this->getSeparator(), $items) + . $this->getPostfix(); + $return = preg_replace("/(\r\n?|\n)/", '$1' . $indent, $return); + return $return; + } + + /** + * Serialize object to string + * + * @return string + */ + public function __toString() + { + return $this->toString(); + } +} diff --git a/lib/zend/Zend/View/Helper/Placeholder/Container/Exception.php b/lib/zend/Zend/View/Helper/Placeholder/Container/Exception.php new file mode 100644 index 00000000000..da15f6e746a --- /dev/null +++ b/lib/zend/Zend/View/Helper/Placeholder/Container/Exception.php @@ -0,0 +1,39 @@ +setRegistry(Zend_View_Helper_Placeholder_Registry::getRegistry()); + $this->setContainer($this->getRegistry()->getContainer($this->_regKey)); + } + + /** + * Retrieve registry + * + * @return Zend_View_Helper_Placeholder_Registry + */ + public function getRegistry() + { + return $this->_registry; + } + + /** + * Set registry object + * + * @param Zend_View_Helper_Placeholder_Registry $registry + * @return Zend_View_Helper_Placeholder_Container_Standalone + */ + public function setRegistry(Zend_View_Helper_Placeholder_Registry $registry) + { + $this->_registry = $registry; + return $this; + } + + /** + * Set whether or not auto escaping should be used + * + * @param bool $autoEscape whether or not to auto escape output + * @return Zend_View_Helper_Placeholder_Container_Standalone + */ + public function setAutoEscape($autoEscape = true) + { + $this->_autoEscape = ($autoEscape) ? true : false; + return $this; + } + + /** + * Return whether autoEscaping is enabled or disabled + * + * return bool + */ + public function getAutoEscape() + { + return $this->_autoEscape; + } + + /** + * Escape a string + * + * @param string $string + * @return string + */ + protected function _escape($string) + { + $enc = 'UTF-8'; + if ($this->view instanceof Zend_View_Interface + && method_exists($this->view, 'getEncoding') + ) { + $enc = $this->view->getEncoding(); + } + + return htmlspecialchars((string) $string, ENT_COMPAT, $enc); + } + + /** + * Set container on which to operate + * + * @param Zend_View_Helper_Placeholder_Container_Abstract $container + * @return Zend_View_Helper_Placeholder_Container_Standalone + */ + public function setContainer(Zend_View_Helper_Placeholder_Container_Abstract $container) + { + $this->_container = $container; + return $this; + } + + /** + * Retrieve placeholder container + * + * @return Zend_View_Helper_Placeholder_Container_Abstract + */ + public function getContainer() + { + return $this->_container; + } + + /** + * Overloading: set property value + * + * @param string $key + * @param mixed $value + * @return void + */ + public function __set($key, $value) + { + $container = $this->getContainer(); + $container[$key] = $value; + } + + /** + * Overloading: retrieve property + * + * @param string $key + * @return mixed + */ + public function __get($key) + { + $container = $this->getContainer(); + if (isset($container[$key])) { + return $container[$key]; + } + + return null; + } + + /** + * Overloading: check if property is set + * + * @param string $key + * @return bool + */ + public function __isset($key) + { + $container = $this->getContainer(); + return isset($container[$key]); + } + + /** + * Overloading: unset property + * + * @param string $key + * @return void + */ + public function __unset($key) + { + $container = $this->getContainer(); + if (isset($container[$key])) { + unset($container[$key]); + } + } + + /** + * Overload + * + * Proxy to container methods + * + * @param string $method + * @param array $args + * @return mixed + */ + public function __call($method, $args) + { + $container = $this->getContainer(); + if (method_exists($container, $method)) { + $return = call_user_func_array(array($container, $method), $args); + if ($return === $container) { + // If the container is returned, we really want the current object + return $this; + } + return $return; + } + + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception('Method "' . $method . '" does not exist'); + $e->setView($this->view); + throw $e; + } + + /** + * String representation + * + * @return string + */ + public function toString() + { + return $this->getContainer()->toString(); + } + + /** + * Cast to string representation + * + * @return string + */ + public function __toString() + { + return $this->toString(); + } + + /** + * Countable + * + * @return int + */ + public function count() + { + $container = $this->getContainer(); + return count($container); + } + + /** + * ArrayAccess: offsetExists + * + * @param string|int $offset + * @return bool + */ + public function offsetExists($offset) + { + return $this->getContainer()->offsetExists($offset); + } + + /** + * ArrayAccess: offsetGet + * + * @param string|int $offset + * @return mixed + */ + public function offsetGet($offset) + { + return $this->getContainer()->offsetGet($offset); + } + + /** + * ArrayAccess: offsetSet + * + * @param string|int $offset + * @param mixed $value + * @return void + */ + public function offsetSet($offset, $value) + { + return $this->getContainer()->offsetSet($offset, $value); + } + + /** + * ArrayAccess: offsetUnset + * + * @param string|int $offset + * @return void + */ + public function offsetUnset($offset) + { + return $this->getContainer()->offsetUnset($offset); + } + + /** + * IteratorAggregate: get Iterator + * + * @return Iterator + */ + public function getIterator() + { + return $this->getContainer()->getIterator(); + } +} diff --git a/lib/zend/Zend/View/Helper/Placeholder/Registry.php b/lib/zend/Zend/View/Helper/Placeholder/Registry.php new file mode 100644 index 00000000000..b4a10c8c8f1 --- /dev/null +++ b/lib/zend/Zend/View/Helper/Placeholder/Registry.php @@ -0,0 +1,188 @@ +_items[$key] = new $this->_containerClass($value); + return $this->_items[$key]; + } + + /** + * Retrieve a placeholder container + * + * @param string $key + * @return Zend_View_Helper_Placeholder_Container_Abstract + */ + public function getContainer($key) + { + $key = (string) $key; + if (isset($this->_items[$key])) { + return $this->_items[$key]; + } + + $container = $this->createContainer($key); + + return $container; + } + + /** + * Does a particular container exist? + * + * @param string $key + * @return bool + */ + public function containerExists($key) + { + $key = (string) $key; + $return = array_key_exists($key, $this->_items); + return $return; + } + + /** + * Set the container for an item in the registry + * + * @param string $key + * @param Zend_View_Placeholder_Container_Abstract $container + * @return Zend_View_Placeholder_Registry + */ + public function setContainer($key, Zend_View_Helper_Placeholder_Container_Abstract $container) + { + $key = (string) $key; + $this->_items[$key] = $container; + return $this; + } + + /** + * Delete a container + * + * @param string $key + * @return bool + */ + public function deleteContainer($key) + { + $key = (string) $key; + if (isset($this->_items[$key])) { + unset($this->_items[$key]); + return true; + } + + return false; + } + + /** + * Set the container class to use + * + * @param string $name + * @return Zend_View_Helper_Placeholder_Registry + */ + public function setContainerClass($name) + { + if (!class_exists($name)) { + require_once 'Zend/Loader.php'; + Zend_Loader::loadClass($name); + } + + $reflection = new ReflectionClass($name); + if (!$reflection->isSubclassOf(new ReflectionClass('Zend_View_Helper_Placeholder_Container_Abstract'))) { + require_once 'Zend/View/Helper/Placeholder/Registry/Exception.php'; + $e = new Zend_View_Helper_Placeholder_Registry_Exception('Invalid Container class specified'); + $e->setView($this->view); + throw $e; + } + + $this->_containerClass = $name; + return $this; + } + + /** + * Retrieve the container class + * + * @return string + */ + public function getContainerClass() + { + return $this->_containerClass; + } +} diff --git a/lib/zend/Zend/View/Helper/Placeholder/Registry/Exception.php b/lib/zend/Zend/View/Helper/Placeholder/Registry/Exception.php new file mode 100644 index 00000000000..6bffa198a89 --- /dev/null +++ b/lib/zend/Zend/View/Helper/Placeholder/Registry/Exception.php @@ -0,0 +1,39 @@ +view->placeholder($placeholder)->captureStart(); + echo $this->view->render($script); + $this->view->placeholder($placeholder)->captureEnd(); + } +} diff --git a/lib/zend/Zend/View/Helper/ServerUrl.php b/lib/zend/Zend/View/Helper/ServerUrl.php new file mode 100644 index 00000000000..c38ec8bc86a --- /dev/null +++ b/lib/zend/Zend/View/Helper/ServerUrl.php @@ -0,0 +1,148 @@ +setScheme($scheme); + + if (isset($_SERVER['HTTP_HOST']) && !empty($_SERVER['HTTP_HOST'])) { + $this->setHost($_SERVER['HTTP_HOST']); + } else if (isset($_SERVER['SERVER_NAME'], $_SERVER['SERVER_PORT'])) { + $name = $_SERVER['SERVER_NAME']; + $port = $_SERVER['SERVER_PORT']; + + if (($scheme == 'http' && $port == 80) || + ($scheme == 'https' && $port == 443)) { + $this->setHost($name); + } else { + $this->setHost($name . ':' . $port); + } + } + } + + /** + * View helper entry point: + * Returns the current host's URL like http://site.com + * + * @param string|boolean $requestUri [optional] if true, the request URI + * found in $_SERVER will be appended + * as a path. If a string is given, it + * will be appended as a path. Default + * is to not append any path. + * @return string server url + */ + public function serverUrl($requestUri = null) + { + if ($requestUri === true) { + $path = $_SERVER['REQUEST_URI']; + } else if (is_string($requestUri)) { + $path = $requestUri; + } else { + $path = ''; + } + + return $this->getScheme() . '://' . $this->getHost() . $path; + } + + /** + * Returns host + * + * @return string host + */ + public function getHost() + { + return $this->_host; + } + + /** + * Sets host + * + * @param string $host new host + * @return Zend_View_Helper_ServerUrl fluent interface, returns self + */ + public function setHost($host) + { + $this->_host = $host; + return $this; + } + + /** + * Returns scheme (typically http or https) + * + * @return string scheme (typically http or https) + */ + public function getScheme() + { + return $this->_scheme; + } + + /** + * Sets scheme (typically http or https) + * + * @param string $scheme new scheme (typically http or https) + * @return Zend_View_Helper_ServerUrl fluent interface, returns self + */ + public function setScheme($scheme) + { + $this->_scheme = $scheme; + return $this; + } +} diff --git a/lib/zend/Zend/View/Helper/Translate.php b/lib/zend/Zend/View/Helper/Translate.php new file mode 100644 index 00000000000..f66a560b0d9 --- /dev/null +++ b/lib/zend/Zend/View/Helper/Translate.php @@ -0,0 +1,180 @@ +setTranslator($translate); + } + } + + /** + * Translate a message + * You can give multiple params or an array of params. + * If you want to output another locale just set it as last single parameter + * Example 1: translate('%1\$s + %2\$s', $value1, $value2, $locale); + * Example 2: translate('%1\$s + %2\$s', array($value1, $value2), $locale); + * + * @param string $messageid Id of the message to be translated + * @return string|Zend_View_Helper_Translate Translated message + */ + public function translate($messageid = null) + { + if ($messageid === null) { + return $this; + } + + $translate = $this->getTranslator(); + $options = func_get_args(); + + array_shift($options); + $count = count($options); + $locale = null; + if ($count > 0) { + if (Zend_Locale::isLocale($options[($count - 1)], null, false) !== false) { + $locale = array_pop($options); + } + } + + if ((count($options) === 1) and (is_array($options[0]) === true)) { + $options = $options[0]; + } + + if ($translate !== null) { + $messageid = $translate->translate($messageid, $locale); + } + + if (count($options) === 0) { + return $messageid; + } + + return vsprintf($messageid, $options); + } + + /** + * Sets a translation Adapter for translation + * + * @param Zend_Translate|Zend_Translate_Adapter $translate Instance of Zend_Translate + * @throws Zend_View_Exception When no or a false instance was set + * @return Zend_View_Helper_Translate + */ + public function setTranslator($translate) + { + if ($translate instanceof Zend_Translate_Adapter) { + $this->_translator = $translate; + } else if ($translate instanceof Zend_Translate) { + $this->_translator = $translate->getAdapter(); + } else { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception('You must set an instance of Zend_Translate or Zend_Translate_Adapter'); + $e->setView($this->view); + throw $e; + } + + return $this; + } + + /** + * Retrieve translation object + * + * @return Zend_Translate_Adapter|null + */ + public function getTranslator() + { + if ($this->_translator === null) { + require_once 'Zend/Registry.php'; + if (Zend_Registry::isRegistered('Zend_Translate')) { + $this->setTranslator(Zend_Registry::get('Zend_Translate')); + } + } + + return $this->_translator; + } + + /** + * Set's an new locale for all further translations + * + * @param string|Zend_Locale $locale New locale to set + * @throws Zend_View_Exception When no Zend_Translate instance was set + * @return Zend_View_Helper_Translate + */ + public function setLocale($locale = null) + { + $translate = $this->getTranslator(); + if ($translate === null) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception('You must set an instance of Zend_Translate or Zend_Translate_Adapter'); + $e->setView($this->view); + throw $e; + } + + $translate->setLocale($locale); + return $this; + } + + /** + * Returns the set locale for translations + * + * @throws Zend_View_Exception When no Zend_Translate instance was set + * @return string|Zend_Locale + */ + public function getLocale() + { + $translate = $this->getTranslator(); + if ($translate === null) { + require_once 'Zend/View/Exception.php'; + $e = new Zend_View_Exception('You must set an instance of Zend_Translate or Zend_Translate_Adapter'); + $e->setView($this->view); + throw $e; + } + + return $translate->getLocale(); + } +} diff --git a/lib/zend/Zend/View/Helper/Url.php b/lib/zend/Zend/View/Helper/Url.php new file mode 100644 index 00000000000..fbf7b690e63 --- /dev/null +++ b/lib/zend/Zend/View/Helper/Url.php @@ -0,0 +1,51 @@ +getRouter(); + return $router->assemble($urlOptions, $name, $reset, $encode); + } +} diff --git a/lib/zend/Zend/View/Helper/UserAgent.php b/lib/zend/Zend/View/Helper/UserAgent.php new file mode 100644 index 00000000000..708ccda6513 --- /dev/null +++ b/lib/zend/Zend/View/Helper/UserAgent.php @@ -0,0 +1,83 @@ +setUserAgent($userAgent); + } + return $this->getUserAgent(); + } + + /** + * Set UserAgent instance + * + * @param Zend_Http_UserAgent $userAgent + * @return Zend_View_Helper_UserAgent + */ + public function setUserAgent(Zend_Http_UserAgent $userAgent) + { + $this->_userAgent = $userAgent; + return $this; + } + + /** + * Retrieve UserAgent instance + * + * If none set, instantiates one using no configuration + * + * @return Zend_Http_UserAgent + */ + public function getUserAgent() + { + if (null === $this->_userAgent) { + require_once 'Zend/Http/UserAgent.php'; + $this->setUserAgent(new Zend_Http_UserAgent()); + } + return $this->_userAgent; + } +} diff --git a/lib/zend/Zend/View/Interface.php b/lib/zend/Zend/View/Interface.php new file mode 100644 index 00000000000..496ec7108ec --- /dev/null +++ b/lib/zend/Zend/View/Interface.php @@ -0,0 +1,137 @@ + value pairs to set en + * masse. + * + * @see __set() + * @param string|array $spec The assignment strategy to use (key or array of key + * => value pairs) + * @param mixed $value (Optional) If assigning a named variable, use this + * as the value. + * @return void + */ + public function assign($spec, $value = null); + + /** + * Clear all assigned variables + * + * Clears all variables assigned to Zend_View either via {@link assign()} or + * property overloading ({@link __get()}/{@link __set()}). + * + * @return void + */ + public function clearVars(); + + /** + * Processes a view script and returns the output. + * + * @param string $name The script name to process. + * @return string The script output. + */ + public function render($name); +} diff --git a/lib/zend/Zend/View/Stream.php b/lib/zend/Zend/View/Stream.php new file mode 100644 index 00000000000..ae8d52419e4 --- /dev/null +++ b/lib/zend/Zend/View/Stream.php @@ -0,0 +1,183 @@ +_data = file_get_contents($path); + + /** + * If reading the file failed, update our local stat store + * to reflect the real stat of the file, then return on failure + */ + if ($this->_data === false) { + $this->_stat = stat($path); + return false; + } + + /** + * Convert to long-form and to + * + */ + $this->_data = preg_replace('/\<\?\=/', "_data); + $this->_data = preg_replace('/<\?(?!xml|php)/s', '_data); + + /** + * file_get_contents() won't update PHP's stat cache, so we grab a stat + * of the file to prevent additional reads should the script be + * requested again, which will make include() happy. + */ + $this->_stat = stat($path); + + return true; + } + + /** + * Included so that __FILE__ returns the appropriate info + * + * @return array + */ + public function url_stat() + { + return $this->_stat; + } + + /** + * Reads from the stream. + */ + public function stream_read($count) + { + $ret = substr($this->_data, $this->_pos, $count); + $this->_pos += strlen($ret); + return $ret; + } + + + /** + * Tells the current position in the stream. + */ + public function stream_tell() + { + return $this->_pos; + } + + + /** + * Tells if we are at the end of the stream. + */ + public function stream_eof() + { + return $this->_pos >= strlen($this->_data); + } + + + /** + * Stream statistics. + */ + public function stream_stat() + { + return $this->_stat; + } + + + /** + * Seek to a specific point in the stream. + */ + public function stream_seek($offset, $whence) + { + switch ($whence) { + case SEEK_SET: + if ($offset < strlen($this->_data) && $offset >= 0) { + $this->_pos = $offset; + return true; + } else { + return false; + } + break; + + case SEEK_CUR: + if ($offset >= 0) { + $this->_pos += $offset; + return true; + } else { + return false; + } + break; + + case SEEK_END: + if (strlen($this->_data) + $offset >= 0) { + $this->_pos = strlen($this->_data) + $offset; + return true; + } else { + return false; + } + break; + + default: + return false; + } + } +} diff --git a/lib/zend/Zend/Xml/Exception.php b/lib/zend/Zend/Xml/Exception.php new file mode 100644 index 00000000000..b58c249512f --- /dev/null +++ b/lib/zend/Zend/Xml/Exception.php @@ -0,0 +1,36 @@ + 0) { + return true; + } + return false; + } + + /** + * Scan XML string for potential XXE and XEE attacks + * + * @param string $xml + * @param DomDocument $dom + * @throws Zend_Xml_Exception + * @return SimpleXMLElement|DomDocument|boolean + */ + public static function scan($xml, DOMDocument $dom = null) + { + // If running with PHP-FPM we perform an heuristic scan + // We cannot use libxml_disable_entity_loader because of this bug + // @see https://bugs.php.net/bug.php?id=64938 + if (self::isPhpFpm()) { + self::heuristicScan($xml); + } + + if (null === $dom) { + $simpleXml = true; + $dom = new DOMDocument(); + } + + if (!self::isPhpFpm()) { + $loadEntities = libxml_disable_entity_loader(true); + $useInternalXmlErrors = libxml_use_internal_errors(true); + } + + // Load XML with network access disabled (LIBXML_NONET) + // error disabled with @ for PHP-FPM scenario + set_error_handler(array('Zend_Xml_Security', 'loadXmlErrorHandler'), E_WARNING); + + $result = $dom->loadXml($xml, LIBXML_NONET); + restore_error_handler(); + + if (!$result) { + // Entity load to previous setting + if (!self::isPhpFpm()) { + libxml_disable_entity_loader($loadEntities); + libxml_use_internal_errors($useInternalXmlErrors); + } + return false; + } + + // Scan for potential XEE attacks using ENTITY, if not PHP-FPM + if (!self::isPhpFpm()) { + foreach ($dom->childNodes as $child) { + if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) { + if ($child->entities->length > 0) { + require_once 'Exception.php'; + throw new Zend_Xml_Exception(self::ENTITY_DETECT); + } + } + } + } + + // Entity load to previous setting + if (!self::isPhpFpm()) { + libxml_disable_entity_loader($loadEntities); + libxml_use_internal_errors($useInternalXmlErrors); + } + + if (isset($simpleXml)) { + $result = simplexml_import_dom($dom); + if (!$result instanceof SimpleXMLElement) { + return false; + } + return $result; + } + return $dom; + } + + /** + * Scan XML file for potential XXE/XEE attacks + * + * @param string $file + * @param DOMDocument $dom + * @throws Zend_Xml_Exception + * @return SimpleXMLElement|DomDocument + */ + public static function scanFile($file, DOMDocument $dom = null) + { + if (!file_exists($file)) { + require_once 'Exception.php'; + throw new Zend_Xml_Exception( + "The file $file specified doesn't exist" + ); + } + return self::scan(file_get_contents($file), $dom); + } + + /** + * Return true if PHP is running with PHP-FPM + * + * This method is mainly used to determine whether or not heuristic checks + * (vs libxml checks) should be made, due to threading issues in libxml; + * under php-fpm, threading becomes a concern. + * + * However, PHP versions 5.5.22+ and 5.6.6+ contain a patch to the + * libxml support in PHP that makes the libxml checks viable; in such + * versions, this method will return false to enforce those checks, which + * are more strict and accurate than the heuristic checks. + * + * @return boolean + */ + public static function isPhpFpm() + { + $isVulnerableVersion = ( + version_compare(PHP_VERSION, '5.5.22', 'lt') + || ( + version_compare(PHP_VERSION, '5.6', 'gte') + && version_compare(PHP_VERSION, '5.6.6', 'lt') + ) + ); + + if (substr(php_sapi_name(), 0, 3) === 'fpm' && $isVulnerableVersion) { + return true; + } + return false; + } + + /** + * Determine and return the string(s) to use for the $generator) { + $prefix = call_user_func($generator, '<' . '?xml'); + if (0 === strncmp($xml, $prefix, strlen($prefix))) { + return $encoding; + } + } + + // Fallback + return 'UTF-8'; + } + + /** + * Attempt to detect the specified XML encoding. + * + * Using the file's encoding, determines if an "encoding" attribute is + * present and well-formed in the XML declaration; if so, it returns a + * list with both the ASCII representation of that declaration and the + * original file encoding. + * + * If not, a list containing only the provided file encoding is returned. + * + * @param string $xml + * @param string $fileEncoding + * @return string[] Potential XML encodings + */ + protected static function detectXmlEncoding($xml, $fileEncoding) + { + $encodingMap = self::getAsciiEncodingMap(); + $generator = $encodingMap[$fileEncoding]; + $encAttr = call_user_func($generator, 'encoding="'); + $quote = call_user_func($generator, '"'); + $close = call_user_func($generator, '>'); + + $closePos = strpos($xml, $close); + if (false === $closePos) { + return array($fileEncoding); + } + + $encPos = strpos($xml, $encAttr); + if (false === $encPos + || $encPos > $closePos + ) { + return array($fileEncoding); + } + + $encPos += strlen($encAttr); + $quotePos = strpos($xml, $quote, $encPos); + if (false === $quotePos) { + return array($fileEncoding); + } + + $encoding = self::substr($xml, $encPos, $quotePos); + return array( + // Following line works because we're only supporting 8-bit safe encodings at this time. + str_replace('\0', '', $encoding), // detected encoding + $fileEncoding, // file encoding + ); + } + + /** + * Return a list of BOM maps. + * + * Returns a list of common encoding -> BOM maps, along with the character + * length to compare against. + * + * @link https://en.wikipedia.org/wiki/Byte_order_mark + * @return array + */ + protected static function getBomMap() + { + return array( + array( + 'encoding' => 'UTF-32BE', + 'bom' => pack('CCCC', 0x00, 0x00, 0xfe, 0xff), + 'length' => 4, + ), + array( + 'encoding' => 'UTF-32LE', + 'bom' => pack('CCCC', 0xff, 0xfe, 0x00, 0x00), + 'length' => 4, + ), + array( + 'encoding' => 'GB-18030', + 'bom' => pack('CCCC', 0x84, 0x31, 0x95, 0x33), + 'length' => 4, + ), + array( + 'encoding' => 'UTF-16BE', + 'bom' => pack('CC', 0xfe, 0xff), + 'length' => 2, + ), + array( + 'encoding' => 'UTF-16LE', + 'bom' => pack('CC', 0xff, 0xfe), + 'length' => 2, + ), + array( + 'encoding' => 'UTF-8', + 'bom' => pack('CCC', 0xef, 0xbb, 0xbf), + 'length' => 3, + ), + ); + } + + /** + * Return a map of encoding => generator pairs. + * + * Returns a map of encoding => generator pairs, where the generator is a + * callable that accepts a string and returns the appropriate byte order + * sequence of that string for the encoding. + * + * @return array + */ + protected static function getAsciiEncodingMap() + { + return array( + 'UTF-32BE' => array(__CLASS__, 'encodeToUTF32BE'), + 'UTF-32LE' => array(__CLASS__, 'encodeToUTF32LE'), + 'UTF-32odd1' => array(__CLASS__, 'encodeToUTF32odd1'), + 'UTF-32odd2' => array(__CLASS__, 'encodeToUTF32odd2'), + 'UTF-16BE' => array(__CLASS__, 'encodeToUTF16BE'), + 'UTF-16LE' => array(__CLASS__, 'encodeToUTF16LE'), + 'UTF-8' => array(__CLASS__, 'encodeToUTF8'), + 'GB-18030' => array(__CLASS__, 'encodeToUTF8'), + ); + } + + /** + * Binary-safe substr. + * + * substr() is not binary-safe; this method loops by character to ensure + * multi-byte characters are aggregated correctly. + * + * @param string $string + * @param int $start + * @param int $end + * @return string + */ + protected static function substr($string, $start, $end) + { + $substr = ''; + for ($i = $start; $i < $end; $i += 1) { + $substr .= $string[$i]; + } + return $substr; + } + + /** + * Generate an entity comparison based on the given encoding. + * + * This patch is internal only, and public only so it can be used as a + * callable to pass to array_map. + * + * @internal + * @param string $encoding + * @return string + */ + public static function generateEntityComparison($encoding) + { + $encodingMap = self::getAsciiEncodingMap(); + $generator = isset($encodingMap[$encoding]) ? $encodingMap[$encoding] : $encodingMap['UTF-8']; + return call_user_func($generator, '_lastRequest = $request; - iconv_set_encoding('input_encoding', 'UTF-8'); - iconv_set_encoding('output_encoding', 'UTF-8'); - iconv_set_encoding('internal_encoding', 'UTF-8'); + if (PHP_VERSION_ID < 50600) { + iconv_set_encoding('input_encoding', 'UTF-8'); + iconv_set_encoding('output_encoding', 'UTF-8'); + iconv_set_encoding('internal_encoding', 'UTF-8'); + } else { + ini_set('input_encoding', 'UTF-8'); + ini_set('output_encoding', 'UTF-8'); + ini_set('default_charset', 'UTF-8'); + } $http = $this->getHttpClient(); if($http->getUri() === null) { @@ -294,7 +300,7 @@ class Zend_XmlRpc_Client $response = new Zend_XmlRpc_Response(); } $this->_lastResponse = $response; - $this->_lastResponse->loadXml($httpResponse->getBody()); + $this->_lastResponse->loadXml(trim($httpResponse->getBody())); } /** @@ -333,22 +339,33 @@ class Zend_XmlRpc_Client if (!is_array($params)) { $params = array($params); } - foreach ($params as $key => $param) { + foreach ($params as $key => $param) + { if ($param instanceof Zend_XmlRpc_Value) { continue; } - $type = Zend_XmlRpc_Value::AUTO_DETECT_TYPE; - foreach ($signatures as $signature) { - if (!is_array($signature)) { - continue; + if (count($signatures) > 1) { + $type = Zend_XmlRpc_Value::getXmlRpcTypeByValue($param); + foreach ($signatures as $signature) { + if (!is_array($signature)) { + continue; + } + if (isset($signature['parameters'][$key])) { + if ($signature['parameters'][$key] == $type) { + break; + } + } } + } elseif (isset($signatures[0]['parameters'][$key])) { + $type = $signatures[0]['parameters'][$key]; + } else { + $type = null; + } - if (isset($signature['parameters'][$key])) { - $type = $signature['parameters'][$key]; - $type = in_array($type, $validTypes) ? $type : Zend_XmlRpc_Value::AUTO_DETECT_TYPE; - } + if (empty($type) || !in_array($type, $validTypes)) { + $type = Zend_XmlRpc_Value::AUTO_DETECT_TYPE; } $params[$key] = Zend_XmlRpc_Value::getXmlRpcValue($param, $type); diff --git a/lib/zend/Zend/XmlRpc/Client/Exception.php b/lib/zend/Zend/XmlRpc/Client/Exception.php index 0192b5ae12c..d82601da6f0 100644 --- a/lib/zend/Zend/XmlRpc/Client/Exception.php +++ b/lib/zend/Zend/XmlRpc/Client/Exception.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_XmlRpc * @subpackage Client - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -33,7 +33,7 @@ require_once 'Zend/XmlRpc/Exception.php'; * @category Zend * @package Zend_XmlRpc * @subpackage Client - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_XmlRpc_Client_Exception extends Zend_XmlRpc_Exception diff --git a/lib/zend/Zend/XmlRpc/Client/FaultException.php b/lib/zend/Zend/XmlRpc/Client/FaultException.php index bedd26aa805..14ffac3adf1 100644 --- a/lib/zend/Zend/XmlRpc/Client/FaultException.php +++ b/lib/zend/Zend/XmlRpc/Client/FaultException.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_XmlRpc * @subpackage Client - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -31,7 +31,7 @@ require_once 'Zend/XmlRpc/Client/Exception.php'; * @category Zend * @package Zend_XmlRpc * @subpackage Client - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_XmlRpc_Client_FaultException extends Zend_XmlRpc_Client_Exception diff --git a/lib/zend/Zend/XmlRpc/Client/HttpException.php b/lib/zend/Zend/XmlRpc/Client/HttpException.php index 2a9ca37fb52..c4186acde7e 100644 --- a/lib/zend/Zend/XmlRpc/Client/HttpException.php +++ b/lib/zend/Zend/XmlRpc/Client/HttpException.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_XmlRpc * @subpackage Client - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -34,7 +34,7 @@ require_once 'Zend/XmlRpc/Client/Exception.php'; * @category Zend * @package Zend_XmlRpc * @subpackage Client - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_XmlRpc_Client_HttpException extends Zend_XmlRpc_Client_Exception diff --git a/lib/zend/Zend/XmlRpc/Client/IntrospectException.php b/lib/zend/Zend/XmlRpc/Client/IntrospectException.php index 9cf0158a1e1..51fb30e8dbc 100644 --- a/lib/zend/Zend/XmlRpc/Client/IntrospectException.php +++ b/lib/zend/Zend/XmlRpc/Client/IntrospectException.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_XmlRpc * @subpackage Client - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -33,7 +33,7 @@ require_once 'Zend/XmlRpc/Client/Exception.php'; * @category Zend * @package Zend_XmlRpc * @subpackage Client - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_XmlRpc_Client_IntrospectException extends Zend_XmlRpc_Client_Exception diff --git a/lib/zend/Zend/XmlRpc/Client/ServerIntrospection.php b/lib/zend/Zend/XmlRpc/Client/ServerIntrospection.php index dcfd98e9282..68848d11121 100644 --- a/lib/zend/Zend/XmlRpc/Client/ServerIntrospection.php +++ b/lib/zend/Zend/XmlRpc/Client/ServerIntrospection.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_XmlRpc * @subpackage Client - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -26,7 +26,7 @@ * @category Zend * @package Zend_XmlRpc * @subpackage Client - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_XmlRpc_Client_ServerIntrospection diff --git a/lib/zend/Zend/XmlRpc/Client/ServerProxy.php b/lib/zend/Zend/XmlRpc/Client/ServerProxy.php index 3231230c098..516619773b9 100644 --- a/lib/zend/Zend/XmlRpc/Client/ServerProxy.php +++ b/lib/zend/Zend/XmlRpc/Client/ServerProxy.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_XmlRpc * @subpackage Client - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -29,7 +29,7 @@ * @category Zend * @package Zend_XmlRpc * @subpackage Client - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_XmlRpc_Client_ServerProxy diff --git a/lib/zend/Zend/XmlRpc/Exception.php b/lib/zend/Zend/XmlRpc/Exception.php index ca688ad6321..d3350515a73 100644 --- a/lib/zend/Zend/XmlRpc/Exception.php +++ b/lib/zend/Zend/XmlRpc/Exception.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_XmlRpc - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -29,7 +29,7 @@ require_once 'Zend/Exception.php'; /** * @category Zend * @package Zend_XmlRpc - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_XmlRpc_Exception extends Zend_Exception diff --git a/lib/zend/Zend/XmlRpc/Fault.php b/lib/zend/Zend/XmlRpc/Fault.php index 265984ade8b..25a5b7d0103 100644 --- a/lib/zend/Zend/XmlRpc/Fault.php +++ b/lib/zend/Zend/XmlRpc/Fault.php @@ -14,7 +14,7 @@ * * @package Zend_XmlRpc * @subpackage Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -36,7 +36,7 @@ require_once 'Zend/XmlRpc/Value.php'; * * @category Zend * @package Zend_XmlRpc - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_XmlRpc_Fault diff --git a/lib/zend/Zend/XmlRpc/Generator/DomDocument.php b/lib/zend/Zend/XmlRpc/Generator/DomDocument.php index afcffc88bdd..88bc05fa0cd 100644 --- a/lib/zend/Zend/XmlRpc/Generator/DomDocument.php +++ b/lib/zend/Zend/XmlRpc/Generator/DomDocument.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_XmlRpc * @subpackage Generator - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -98,4 +98,4 @@ class Zend_XmlRpc_Generator_DomDocument extends Zend_XmlRpc_Generator_GeneratorA $this->_dom = new DOMDocument('1.0', $this->_encoding); $this->_currentElement = $this->_dom; } -} \ No newline at end of file +} diff --git a/lib/zend/Zend/XmlRpc/Generator/GeneratorAbstract.php b/lib/zend/Zend/XmlRpc/Generator/GeneratorAbstract.php index abfea1ab589..03afcd696f4 100644 --- a/lib/zend/Zend/XmlRpc/Generator/GeneratorAbstract.php +++ b/lib/zend/Zend/XmlRpc/Generator/GeneratorAbstract.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_XmlRpc * @subpackage Generator - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -47,7 +47,7 @@ abstract class Zend_XmlRpc_Generator_GeneratorAbstract * Start XML element * * Method opens a new XML element with an element name and an optional value - * + * * @param string $name XML tag name * @param string $value Optional value of the XML tag * @return Zend_XmlRpc_Generator_Abstract Fluent interface @@ -86,7 +86,7 @@ abstract class Zend_XmlRpc_Generator_GeneratorAbstract /** * Return encoding - * + * * @return string */ public function getEncoding() @@ -143,7 +143,7 @@ abstract class Zend_XmlRpc_Generator_GeneratorAbstract /** * End XML element - * + * * @param string $name */ abstract protected function _closeElement($name); diff --git a/lib/zend/Zend/XmlRpc/Generator/XmlWriter.php b/lib/zend/Zend/XmlRpc/Generator/XmlWriter.php index 51d5d00ee59..a84e11d3bf4 100644 --- a/lib/zend/Zend/XmlRpc/Generator/XmlWriter.php +++ b/lib/zend/Zend/XmlRpc/Generator/XmlWriter.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_XmlRpc * @subpackage Generator - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -87,6 +87,7 @@ class Zend_XmlRpc_Generator_XmlWriter extends Zend_XmlRpc_Generator_GeneratorAbs public function saveXml() { - return $this->_xmlWriter->flush(false); + $xml = $this->_xmlWriter->flush(false); + return $xml; } -} \ No newline at end of file +} diff --git a/lib/zend/Zend/XmlRpc/Request.php b/lib/zend/Zend/XmlRpc/Request.php index 2a11a3ac062..73bb9670a33 100644 --- a/lib/zend/Zend/XmlRpc/Request.php +++ b/lib/zend/Zend/XmlRpc/Request.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Controller - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -28,6 +28,12 @@ require_once 'Zend/XmlRpc/Value.php'; */ require_once 'Zend/XmlRpc/Fault.php'; +/** @see Zend_Xml_Security */ +require_once 'Zend/Xml/Security.php'; + +/** @see Zend_Xml_Exception */ +require_once 'Zend/Xml/Exception.php'; + /** * XmlRpc Request object * @@ -41,7 +47,7 @@ require_once 'Zend/XmlRpc/Fault.php'; * * @category Zend * @package Zend_XmlRpc - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -303,15 +309,12 @@ class Zend_XmlRpc_Request return false; } - // @see ZF-12293 - disable external entities for security purposes - $loadEntities = libxml_disable_entity_loader(true); try { - $xml = new SimpleXMLElement($request); - } catch (Exception $e) { + $xml = Zend_Xml_Security::scan($request); + } catch (Zend_Xml_Exception $e) { // Not valid XML $this->_fault = new Zend_XmlRpc_Fault(631); $this->_fault->setEncoding($this->getEncoding()); - libxml_disable_entity_loader($loadEntities); return false; } @@ -320,7 +323,6 @@ class Zend_XmlRpc_Request // Missing method name $this->_fault = new Zend_XmlRpc_Fault(632); $this->_fault->setEncoding($this->getEncoding()); - libxml_disable_entity_loader($loadEntities); return false; } @@ -334,7 +336,6 @@ class Zend_XmlRpc_Request if (!isset($param->value)) { $this->_fault = new Zend_XmlRpc_Fault(633); $this->_fault->setEncoding($this->getEncoding()); - libxml_disable_entity_loader($loadEntities); return false; } @@ -345,7 +346,6 @@ class Zend_XmlRpc_Request } catch (Exception $e) { $this->_fault = new Zend_XmlRpc_Fault(636); $this->_fault->setEncoding($this->getEncoding()); - libxml_disable_entity_loader($loadEntities); return false; } } @@ -354,7 +354,6 @@ class Zend_XmlRpc_Request $this->_params = $argv; } - libxml_disable_entity_loader($loadEntities); $this->_xml = $request; return true; diff --git a/lib/zend/Zend/XmlRpc/Request/Http.php b/lib/zend/Zend/XmlRpc/Request/Http.php index fd438f67b44..df058a1a84a 100644 --- a/lib/zend/Zend/XmlRpc/Request/Http.php +++ b/lib/zend/Zend/XmlRpc/Request/Http.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Controller - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -32,7 +32,7 @@ require_once 'Zend/XmlRpc/Request.php'; * * @category Zend * @package Zend_XmlRpc - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ diff --git a/lib/zend/Zend/XmlRpc/Request/Stdin.php b/lib/zend/Zend/XmlRpc/Request/Stdin.php index b81005e17e9..d6bb539e199 100644 --- a/lib/zend/Zend/XmlRpc/Request/Stdin.php +++ b/lib/zend/Zend/XmlRpc/Request/Stdin.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Controller - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -32,7 +32,7 @@ require_once 'Zend/XmlRpc/Request.php'; * * @category Zend * @package Zend_XmlRpc - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ diff --git a/lib/zend/Zend/XmlRpc/Response.php b/lib/zend/Zend/XmlRpc/Response.php index 144b7bb6ab9..be5a6cbb4e5 100644 --- a/lib/zend/Zend/XmlRpc/Response.php +++ b/lib/zend/Zend/XmlRpc/Response.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Controller - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -28,6 +28,12 @@ require_once 'Zend/XmlRpc/Value.php'; */ require_once 'Zend/XmlRpc/Fault.php'; +/** @see Zend_Xml_Security */ +require_once 'Zend/Xml/Security.php'; + +/** @see Zend_Xml_Exception */ +require_once 'Zend/Xml/Exception.php'; + /** * XmlRpc Response * @@ -35,7 +41,7 @@ require_once 'Zend/XmlRpc/Fault.php'; * * @category Zend * @package Zend_XmlRpc - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -177,8 +183,8 @@ class Zend_XmlRpc_Response } try { - $xml = new SimpleXMLElement($response); - } catch (Exception $e) { + $xml = Zend_Xml_Security::scan($response); + } catch (Zend_Xml_Exception $e) { // Not valid XML $this->_fault = new Zend_XmlRpc_Fault(651); $this->_fault->setEncoding($this->getEncoding()); @@ -202,6 +208,7 @@ class Zend_XmlRpc_Response try { if (!isset($xml->params) || !isset($xml->params->param) || !isset($xml->params->param->value)) { + require_once 'Zend/XmlRpc/Value/Exception.php'; throw new Zend_XmlRpc_Value_Exception('Missing XML-RPC value in XML'); } $valueXml = $xml->params->param->value->asXML(); diff --git a/lib/zend/Zend/XmlRpc/Response/Http.php b/lib/zend/Zend/XmlRpc/Response/Http.php index 751a4dc3189..5bc246ba678 100644 --- a/lib/zend/Zend/XmlRpc/Response/Http.php +++ b/lib/zend/Zend/XmlRpc/Response/Http.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Controller - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -29,7 +29,7 @@ require_once 'Zend/XmlRpc/Response.php'; * @uses Zend_XmlRpc_Response * @category Zend * @package Zend_XmlRpc - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ diff --git a/lib/zend/Zend/XmlRpc/Server.php b/lib/zend/Zend/XmlRpc/Server.php index ed8c354da57..1c747084b0c 100644 --- a/lib/zend/Zend/XmlRpc/Server.php +++ b/lib/zend/Zend/XmlRpc/Server.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_XmlRpc * @subpackage Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -111,7 +111,7 @@ require_once 'Zend/Server/Reflection/Method.php'; * @category Zend * @package Zend_XmlRpc * @subpackage Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_XmlRpc_Server extends Zend_Server_Abstract @@ -278,13 +278,13 @@ class Zend_XmlRpc_Server extends Zend_Server_Abstract throw new Zend_XmlRpc_Server_Exception('Invalid method class', 610); } - $argv = null; + $args = null; if (2 < func_num_args()) { - $argv = func_get_args(); - $argv = array_slice($argv, 2); + $args = func_get_args(); + $args = array_slice($args, 2); } - $dispatchable = Zend_Server_Reflection::reflectClass($class, $argv, $namespace); + $dispatchable = Zend_Server_Reflection::reflectClass($class, $args, $namespace); foreach ($dispatchable->getMethods() as $reflection) { $this->_buildSignature($reflection, $class); } diff --git a/lib/zend/Zend/XmlRpc/Server/Cache.php b/lib/zend/Zend/XmlRpc/Server/Cache.php index 32ee69bd5a3..7c52902b62f 100644 --- a/lib/zend/Zend/XmlRpc/Server/Cache.php +++ b/lib/zend/Zend/XmlRpc/Server/Cache.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_XmlRpc * @subpackage Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -29,7 +29,7 @@ require_once 'Zend/Server/Cache.php'; * @category Zend * @package Zend_XmlRpc * @subpackage Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_XmlRpc_Server_Cache extends Zend_Server_Cache diff --git a/lib/zend/Zend/XmlRpc/Server/Exception.php b/lib/zend/Zend/XmlRpc/Server/Exception.php index eb4fe1bed08..36952623b43 100644 --- a/lib/zend/Zend/XmlRpc/Server/Exception.php +++ b/lib/zend/Zend/XmlRpc/Server/Exception.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_XmlRpc * @subpackage Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -33,7 +33,7 @@ require_once 'Zend/XmlRpc/Exception.php'; * @category Zend * @package Zend_XmlRpc * @subpackage Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_XmlRpc_Server_Exception extends Zend_XmlRpc_Exception diff --git a/lib/zend/Zend/XmlRpc/Server/Fault.php b/lib/zend/Zend/XmlRpc/Server/Fault.php index 82b851f34ad..8ccb9ba4161 100644 --- a/lib/zend/Zend/XmlRpc/Server/Fault.php +++ b/lib/zend/Zend/XmlRpc/Server/Fault.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_XmlRpc * @subpackage Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -44,7 +44,7 @@ require_once 'Zend/XmlRpc/Fault.php'; * @category Zend * @package Zend_XmlRpc * @subpackage Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_XmlRpc_Server_Fault extends Zend_XmlRpc_Fault diff --git a/lib/zend/Zend/XmlRpc/Server/System.php b/lib/zend/Zend/XmlRpc/Server/System.php index d49d0fc3e72..340eb1cd739 100644 --- a/lib/zend/Zend/XmlRpc/Server/System.php +++ b/lib/zend/Zend/XmlRpc/Server/System.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_XmlRpc * @subpackage Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -26,7 +26,7 @@ * @category Zend * @package Zend_XmlRpc * @subpackage Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_XmlRpc_Server_System diff --git a/lib/zend/Zend/XmlRpc/Value.php b/lib/zend/Zend/XmlRpc/Value.php index 4d0fe8c2c94..6b224499649 100644 --- a/lib/zend/Zend/XmlRpc/Value.php +++ b/lib/zend/Zend/XmlRpc/Value.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_XmlRpc * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -31,7 +31,7 @@ * from PHP variables, XML string or by specifing the exact XML-RPC natvie type * * @package Zend_XmlRpc - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ abstract class Zend_XmlRpc_Value @@ -252,6 +252,43 @@ abstract class Zend_XmlRpc_Value } } + /** + * Get XML-RPC type for a PHP native variable + * + * @static + * @param mixed $value + * @return string + */ + public static function getXmlRpcTypeByValue($value) + { + if (is_object($value)) { + if ($value instanceof Zend_XmlRpc_Value) { + return $value->getType(); + } elseif (($value instanceof Zend_Date) || ($value instanceof DateTime)) { + return self::XMLRPC_TYPE_DATETIME; + } + return self::getXmlRpcTypeByValue(get_object_vars($value)); + } elseif (is_array($value)) { + if (!empty($value) && is_array($value) && (array_keys($value) !== range(0, count($value) - 1))) { + return self::XMLRPC_TYPE_STRUCT; + } + return self::XMLRPC_TYPE_ARRAY; + } elseif (is_int($value)) { + return ($value > PHP_INT_MAX) ? self::XMLRPC_TYPE_I8 : self::XMLRPC_TYPE_INTEGER; + } elseif (is_double($value)) { + return self::XMLRPC_TYPE_DOUBLE; + } elseif (is_bool($value)) { + return self::XMLRPC_TYPE_BOOLEAN; + } elseif (is_null($value)) { + return self::XMLRPC_TYPE_NIL; + } elseif (is_string($value)) { + return self::XMLRPC_TYPE_STRING; + } + throw new Zend_XmlRpc_Value_Exception(sprintf( + 'No matching XMLRPC type found for php type %s.', + gettype($value) + )); + } /** * Transform a PHP native variable into a XML-RPC native value @@ -263,56 +300,52 @@ abstract class Zend_XmlRpc_Value */ protected static function _phpVarToNativeXmlRpc($value) { - switch (gettype($value)) { - case 'object': - // Check to see if it's an XmlRpc value - if ($value instanceof Zend_XmlRpc_Value) { - return $value; - } + // @see http://framework.zend.com/issues/browse/ZF-8623 + if (is_object($value)) { + if ($value instanceof Zend_XmlRpc_Value) { + return $value; + } + if ($value instanceof Zend_Crypt_Math_BigInteger) { + require_once 'Zend/XmlRpc/Value/Exception.php'; + throw new Zend_XmlRpc_Value_Exception( + 'Using Zend_Crypt_Math_BigInteger to get an ' . + 'instance of Zend_XmlRpc_Value_BigInteger is not ' . + 'available anymore.' + ); + } + } - if ($value instanceof Zend_Crypt_Math_BigInteger) { - require_once 'Zend/XmlRpc/Value/BigInteger.php'; - return new Zend_XmlRpc_Value_BigInteger($value); - } + switch (self::getXmlRpcTypeByValue($value)) + { + case self::XMLRPC_TYPE_DATETIME: + require_once 'Zend/XmlRpc/Value/DateTime.php'; + return new Zend_XmlRpc_Value_DateTime($value); - if ($value instanceof Zend_Date or $value instanceof DateTime) { - require_once 'Zend/XmlRpc/Value/DateTime.php'; - return new Zend_XmlRpc_Value_DateTime($value); - } - - // Otherwise, we convert the object into a struct - $value = get_object_vars($value); - // Break intentionally omitted - case 'array': - // Default native type for a PHP array (a simple numeric array) is 'array' + case self::XMLRPC_TYPE_ARRAY: require_once 'Zend/XmlRpc/Value/Array.php'; - $obj = 'Zend_XmlRpc_Value_Array'; + return new Zend_XmlRpc_Value_Array($value); - // Determine if this is an associative array - if (!empty($value) && is_array($value) && (array_keys($value) !== range(0, count($value) - 1))) { - require_once 'Zend/XmlRpc/Value/Struct.php'; - $obj = 'Zend_XmlRpc_Value_Struct'; - } - return new $obj($value); + case self::XMLRPC_TYPE_STRUCT: + require_once 'Zend/XmlRpc/Value/Struct.php'; + return new Zend_XmlRpc_Value_Struct($value); - case 'integer': + case self::XMLRPC_TYPE_INTEGER: require_once 'Zend/XmlRpc/Value/Integer.php'; return new Zend_XmlRpc_Value_Integer($value); - case 'double': + case self::XMLRPC_TYPE_DOUBLE: require_once 'Zend/XmlRpc/Value/Double.php'; return new Zend_XmlRpc_Value_Double($value); - case 'boolean': + case self::XMLRPC_TYPE_BOOLEAN: require_once 'Zend/XmlRpc/Value/Boolean.php'; return new Zend_XmlRpc_Value_Boolean($value); - case 'NULL': - case 'null': + case self::XMLRPC_TYPE_NIL: require_once 'Zend/XmlRpc/Value/Nil.php'; - return new Zend_XmlRpc_Value_Nil(); + return new Zend_XmlRpc_Value_Nil; - case 'string': + case self::XMLRPC_TYPE_STRING: // Fall through to the next case default: // If type isn't identified (or identified as string), it treated as string @@ -467,14 +500,22 @@ abstract class Zend_XmlRpc_Value } } + //if there is a child element, try to parse type for it + if (!$type && $value instanceof SimpleXMLElement) { + self::_extractTypeAndValue($value->children(), $type, $value); + } + // If no type was specified, the default is string if (!$type) { $type = self::XMLRPC_TYPE_STRING; + if (preg_match('#^.*$#', $xml->asXML())) { + $value = str_replace(array('', ''), '', $xml->asXML()); + } } } /** - * @param $xml + * @param string $xml * @return void */ protected function _setXML($xml) diff --git a/lib/zend/Zend/XmlRpc/Value/Array.php b/lib/zend/Zend/XmlRpc/Value/Array.php index 8fed1a39f78..60f68b29628 100644 --- a/lib/zend/Zend/XmlRpc/Value/Array.php +++ b/lib/zend/Zend/XmlRpc/Value/Array.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_XmlRpc * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -31,7 +31,7 @@ require_once 'Zend/XmlRpc/Value/Collection.php'; * @category Zend * @package Zend_XmlRpc * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_XmlRpc_Value_Array extends Zend_XmlRpc_Value_Collection diff --git a/lib/zend/Zend/XmlRpc/Value/Base64.php b/lib/zend/Zend/XmlRpc/Value/Base64.php index ea1e5d8e887..eee61bae5ca 100644 --- a/lib/zend/Zend/XmlRpc/Value/Base64.php +++ b/lib/zend/Zend/XmlRpc/Value/Base64.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_XmlRpc * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -31,7 +31,7 @@ require_once 'Zend/XmlRpc/Value/Scalar.php'; * @category Zend * @package Zend_XmlRpc * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_XmlRpc_Value_Base64 extends Zend_XmlRpc_Value_Scalar @@ -65,4 +65,4 @@ class Zend_XmlRpc_Value_Base64 extends Zend_XmlRpc_Value_Scalar { return base64_decode($this->_value); } -} \ No newline at end of file +} diff --git a/lib/zend/Zend/XmlRpc/Value/BigInteger.php b/lib/zend/Zend/XmlRpc/Value/BigInteger.php index 1ce84bb2d3a..b636a5814f9 100644 --- a/lib/zend/Zend/XmlRpc/Value/BigInteger.php +++ b/lib/zend/Zend/XmlRpc/Value/BigInteger.php @@ -1,4 +1,5 @@ _integer = new Zend_Crypt_Math_BigInteger(); - $this->_value = $this->_integer->init($this->_value); - + $integer = new Zend_Crypt_Math_BigInteger; + $this->_value = $integer->init($value); $this->_type = self::XMLRPC_TYPE_I8; } /** - * Return bigint value object + * Return bigint value * - * @return Zend_Crypt_Math_BigInteger + * @return string */ public function getValue() { - return $this->_integer; + return $this->_value; } } diff --git a/lib/zend/Zend/XmlRpc/Value/Boolean.php b/lib/zend/Zend/XmlRpc/Value/Boolean.php index cb25cdd76c6..1a91872ca02 100644 --- a/lib/zend/Zend/XmlRpc/Value/Boolean.php +++ b/lib/zend/Zend/XmlRpc/Value/Boolean.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_XmlRpc * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -31,7 +31,7 @@ require_once 'Zend/XmlRpc/Value/Scalar.php'; * @category Zend * @package Zend_XmlRpc * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_XmlRpc_Value_Boolean extends Zend_XmlRpc_Value_Scalar @@ -60,4 +60,4 @@ class Zend_XmlRpc_Value_Boolean extends Zend_XmlRpc_Value_Scalar { return (bool)$this->_value; } -} \ No newline at end of file +} diff --git a/lib/zend/Zend/XmlRpc/Value/Collection.php b/lib/zend/Zend/XmlRpc/Value/Collection.php index ad5fbc07d90..2ef9a9a3d50 100644 --- a/lib/zend/Zend/XmlRpc/Value/Collection.php +++ b/lib/zend/Zend/XmlRpc/Value/Collection.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_XmlRpc * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -31,7 +31,7 @@ require_once 'Zend/XmlRpc/Value.php'; * @category Zend * @package Zend_XmlRpc * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ abstract class Zend_XmlRpc_Value_Collection extends Zend_XmlRpc_Value diff --git a/lib/zend/Zend/XmlRpc/Value/DateTime.php b/lib/zend/Zend/XmlRpc/Value/DateTime.php index 6386c7e427c..18d9991dc11 100644 --- a/lib/zend/Zend/XmlRpc/Value/DateTime.php +++ b/lib/zend/Zend/XmlRpc/Value/DateTime.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_XmlRpc * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -31,7 +31,7 @@ require_once 'Zend/XmlRpc/Value/Scalar.php'; * @category Zend * @package Zend_XmlRpc * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_XmlRpc_Value_DateTime extends Zend_XmlRpc_Value_Scalar @@ -48,7 +48,7 @@ class Zend_XmlRpc_Value_DateTime extends Zend_XmlRpc_Value_Scalar * * @var string */ - protected $_isoFormatString = 'YYYYMMddTHH:mm:ss'; + protected $_isoFormatString = 'yyyyMMddTHH:mm:ss'; /** * Set the value of a dateTime.iso8601 native type @@ -69,13 +69,13 @@ class Zend_XmlRpc_Value_DateTime extends Zend_XmlRpc_Value_Scalar } elseif (is_numeric($value)) { // The value is numeric, we make sure it is an integer $this->_value = date($this->_phpFormatString, (int)$value); } else { - $timestamp = strtotime($value); - if ($timestamp === false || $timestamp == -1) { // cannot convert the value to a timestamp + $timestamp = new DateTime($value); + if ($timestamp === false) { // cannot convert the value to a timestamp require_once 'Zend/XmlRpc/Value/Exception.php'; throw new Zend_XmlRpc_Value_Exception('Cannot convert given value \''. $value .'\' to a timestamp'); } - $this->_value = date($this->_phpFormatString, $timestamp); // Convert the timestamp to iso8601 format + $this->_value = $timestamp->format($this->_phpFormatString); // Convert the timestamp to iso8601 format } } diff --git a/lib/zend/Zend/XmlRpc/Value/Double.php b/lib/zend/Zend/XmlRpc/Value/Double.php index a4033ed42f6..6251879f069 100644 --- a/lib/zend/Zend/XmlRpc/Value/Double.php +++ b/lib/zend/Zend/XmlRpc/Value/Double.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_XmlRpc * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -31,7 +31,7 @@ require_once 'Zend/XmlRpc/Value/Scalar.php'; * @category Zend * @package Zend_XmlRpc * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_XmlRpc_Value_Double extends Zend_XmlRpc_Value_Scalar diff --git a/lib/zend/Zend/XmlRpc/Value/Exception.php b/lib/zend/Zend/XmlRpc/Value/Exception.php index 6e79ce4626d..3a18f28e736 100644 --- a/lib/zend/Zend/XmlRpc/Value/Exception.php +++ b/lib/zend/Zend/XmlRpc/Value/Exception.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_XmlRpc * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -31,7 +31,7 @@ require_once 'Zend/XmlRpc/Exception.php'; * @category Zend * @package Zend_XmlRpc * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_XmlRpc_Value_Exception extends Zend_XmlRpc_Exception diff --git a/lib/zend/Zend/XmlRpc/Value/Integer.php b/lib/zend/Zend/XmlRpc/Value/Integer.php index 5c99387c385..2ad5c840d55 100644 --- a/lib/zend/Zend/XmlRpc/Value/Integer.php +++ b/lib/zend/Zend/XmlRpc/Value/Integer.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_XmlRpc * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -31,7 +31,7 @@ require_once 'Zend/XmlRpc/Value/Scalar.php'; * @category Zend * @package Zend_XmlRpc * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_XmlRpc_Value_Integer extends Zend_XmlRpc_Value_Scalar diff --git a/lib/zend/Zend/XmlRpc/Value/Nil.php b/lib/zend/Zend/XmlRpc/Value/Nil.php index 760872d7f22..67305d0d8d9 100644 --- a/lib/zend/Zend/XmlRpc/Value/Nil.php +++ b/lib/zend/Zend/XmlRpc/Value/Nil.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_XmlRpc * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -31,7 +31,7 @@ require_once 'Zend/XmlRpc/Value/Scalar.php'; * @category Zend * @package Zend_XmlRpc * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_XmlRpc_Value_Nil extends Zend_XmlRpc_Value_Scalar diff --git a/lib/zend/Zend/XmlRpc/Value/Scalar.php b/lib/zend/Zend/XmlRpc/Value/Scalar.php index ec1af5443e2..86397d20912 100644 --- a/lib/zend/Zend/XmlRpc/Value/Scalar.php +++ b/lib/zend/Zend/XmlRpc/Value/Scalar.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_XmlRpc * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -31,7 +31,7 @@ require_once 'Zend/XmlRpc/Value.php'; * @category Zend * @package Zend_XmlRpc * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ abstract class Zend_XmlRpc_Value_Scalar extends Zend_XmlRpc_Value @@ -50,4 +50,4 @@ abstract class Zend_XmlRpc_Value_Scalar extends Zend_XmlRpc_Value ->closeElement($this->_type) ->closeElement('value'); } -} \ No newline at end of file +} diff --git a/lib/zend/Zend/XmlRpc/Value/String.php b/lib/zend/Zend/XmlRpc/Value/String.php index 98996157e0b..37ac5b83216 100644 --- a/lib/zend/Zend/XmlRpc/Value/String.php +++ b/lib/zend/Zend/XmlRpc/Value/String.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_XmlRpc * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -29,7 +29,7 @@ require_once 'Zend/XmlRpc/Value/Scalar.php'; /** * @package Zend_XmlRpc * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_XmlRpc_Value_String extends Zend_XmlRpc_Value_Scalar @@ -57,4 +57,4 @@ class Zend_XmlRpc_Value_String extends Zend_XmlRpc_Value_Scalar { return (string)$this->_value; } -} \ No newline at end of file +} diff --git a/lib/zend/Zend/XmlRpc/Value/Struct.php b/lib/zend/Zend/XmlRpc/Value/Struct.php index 04baedb7f94..5272eb508db 100644 --- a/lib/zend/Zend/XmlRpc/Value/Struct.php +++ b/lib/zend/Zend/XmlRpc/Value/Struct.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_XmlRpc * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ @@ -31,7 +31,7 @@ require_once 'Zend/XmlRpc/Value/Collection.php'; * @category Zend * @package Zend_XmlRpc * @subpackage Value - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_XmlRpc_Value_Struct extends Zend_XmlRpc_Value_Collection @@ -72,4 +72,4 @@ class Zend_XmlRpc_Value_Struct extends Zend_XmlRpc_Value_Collection $generator->closeElement('struct') ->closeElement('value'); } -} \ No newline at end of file +} diff --git a/lib/zend/readme_moodle.txt b/lib/zend/readme_moodle.txt index 1df8e7647af..2c1d1c8973e 100644 --- a/lib/zend/readme_moodle.txt +++ b/lib/zend/readme_moodle.txt @@ -1,12 +1,25 @@ Description of Zend framework 1.10.6 import into Moodle -Please note the zend framework is severly crippled - everything not needed in /webservice/* is removed. +Please note the zend framework is modified - some packages are removed. + +Delete all the files from the Moodle lib/zend/Zend folder. +Copy all the files from the zend/library/Zend folder into the Moodle lib/zend/Zend folder. + +Audit the Classes we actually use - and delete libraries that are not used directly or indirectly by any of them. + +Libraries I think are safe to remove: + +Application/ Tool/ Application.php Barcode/ Barcode.php Captcha/ Form/ Form.php Dojo/ Dojo.php Cloud/ +CodeGenerator/ Console/ Test/ Db.php Db/ Paginator.php Paginator/ Session.php Session/ Feed.php Feed/ +Auth/Adapter/DbTable.php Queue/Adapter/Db/ Queue/Adapter/Db.php Debug.php Dom/ EventManager/ File/ Ldap.php +Ldap/ Auth/Adapter/Ldap.php Locale/Data Mail.php Mail/ Markup.php Markup/ Measure/ Memory.php Memory/ Pdf.php Pdf/ +Mime.php Mime/ Mobile/ OpenId.php OpenId/ Auth/Adapter/OpenId.php ProgressBar.php ProgressBar Queue.php Queue/ +Search/ Serializer.php Serializer/ Stdlib/ Tag/ Text/ TimeSync.php TimeSync/ Translate.php Translate/ +Log/Writer/Firebug.php Wildfire/ Service/ShortUrl/ Service/WindowsAzure/ + + + Do not use outside of our /webservice/* or mnet !! - Changes: -* lots of files removed -* small fix to error reporting in reflection (MDL-21460, ZF-8980) -* SOAP and XMLRPC servers overwrite the fault() functions -* synced and renamed file to version in ZF 1.10.6 (MDL-30603, ZF-11080) -* import security patch (MDL-34284, ZF2012-01, ZF-12293) +* Update to 1.12.16 - this is more or less vanilla now except for the above folders removed.