| 
									
										
										
										
											2008-08-22 09:17:14 -04:00
										 |  |  | <?php | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * This module contains the XRDS parsing code. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * PHP versions 4 and 5 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * LICENSE: See the COPYING file included in this distribution. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @package OpenID | 
					
						
							|  |  |  |  * @author JanRain, Inc. <openid@janrain.com> | 
					
						
							|  |  |  |  * @copyright 2005-2008 Janrain, Inc. | 
					
						
							|  |  |  |  * @license http://www.apache.org/licenses/LICENSE-2.0 Apache | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Require the XPath implementation. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | require_once 'Auth/Yadis/XML.php'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * This match mode means a given service must match ALL filters passed | 
					
						
							|  |  |  |  * to the Auth_Yadis_XRDS::services() call. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | define('SERVICES_YADIS_MATCH_ALL', 101); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * This match mode means a given service must match ANY filters (at | 
					
						
							|  |  |  |  * least one) passed to the Auth_Yadis_XRDS::services() call. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | define('SERVICES_YADIS_MATCH_ANY', 102); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * The priority value used for service elements with no priority | 
					
						
							|  |  |  |  * specified. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | define('SERVICES_YADIS_MAX_PRIORITY', pow(2, 30)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * XRD XML namespace | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | define('Auth_Yadis_XMLNS_XRD_2_0', 'xri://$xrd*($v*2.0)'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * XRDS XML namespace | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | define('Auth_Yadis_XMLNS_XRDS', 'xri://$xrds'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function Auth_Yadis_getNSMap() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return array('xrds' => Auth_Yadis_XMLNS_XRDS, | 
					
						
							|  |  |  |                  'xrd' => Auth_Yadis_XMLNS_XRD_2_0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * @access private | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | function Auth_Yadis_array_scramble($arr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     $result = array(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while (count($arr)) { | 
					
						
							|  |  |  |         $index = array_rand($arr, 1); | 
					
						
							|  |  |  |         $result[] = $arr[$index]; | 
					
						
							|  |  |  |         unset($arr[$index]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return $result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * This class represents a <Service> element in an XRDS document. | 
					
						
							|  |  |  |  * Objects of this type are returned by | 
					
						
							|  |  |  |  * Auth_Yadis_XRDS::services() and | 
					
						
							|  |  |  |  * Auth_Yadis_Yadis::services().  Each object corresponds directly | 
					
						
							|  |  |  |  * to a <Service> element in the XRDS and supplies a | 
					
						
							|  |  |  |  * getElements($name) method which you should use to inspect the | 
					
						
							|  |  |  |  * element's contents.  See {@link Auth_Yadis_Yadis} for more | 
					
						
							|  |  |  |  * information on the role this class plays in Yadis discovery. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @package OpenID | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | class Auth_Yadis_Service { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Creates an empty service object. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function Auth_Yadis_Service() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->element = null; | 
					
						
							|  |  |  |         $this->parser = null; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Return the URIs in the "Type" elements, if any, of this Service | 
					
						
							|  |  |  |      * element. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return array $type_uris An array of Type URI strings. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function getTypes() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $t = array(); | 
					
						
							|  |  |  |         foreach ($this->getElements('xrd:Type') as $elem) { | 
					
						
							|  |  |  |             $c = $this->parser->content($elem); | 
					
						
							|  |  |  |             if ($c) { | 
					
						
							|  |  |  |                 $t[] = $c; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return $t; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function matchTypes($type_uris) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $result = array(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         foreach ($this->getTypes() as $typ) { | 
					
						
							|  |  |  |             if (in_array($typ, $type_uris)) { | 
					
						
							|  |  |  |                 $result[] = $typ; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $result; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Return the URIs in the "URI" elements, if any, of this Service | 
					
						
							|  |  |  |      * element.  The URIs are returned sorted in priority order. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return array $uris An array of URI strings. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function getURIs() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $uris = array(); | 
					
						
							|  |  |  |         $last = array(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         foreach ($this->getElements('xrd:URI') as $elem) { | 
					
						
							|  |  |  |             $uri_string = $this->parser->content($elem); | 
					
						
							|  |  |  |             $attrs = $this->parser->attributes($elem); | 
					
						
							|  |  |  |             if ($attrs && | 
					
						
							|  |  |  |                 array_key_exists('priority', $attrs)) { | 
					
						
							|  |  |  |                 $priority = intval($attrs['priority']); | 
					
						
							|  |  |  |                 if (!array_key_exists($priority, $uris)) { | 
					
						
							|  |  |  |                     $uris[$priority] = array(); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 $uris[$priority][] = $uri_string; | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 $last[] = $uri_string; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $keys = array_keys($uris); | 
					
						
							|  |  |  |         sort($keys); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Rebuild array of URIs.
 | 
					
						
							|  |  |  |         $result = array(); | 
					
						
							|  |  |  |         foreach ($keys as $k) { | 
					
						
							|  |  |  |             $new_uris = Auth_Yadis_array_scramble($uris[$k]); | 
					
						
							|  |  |  |             $result = array_merge($result, $new_uris); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $result = array_merge($result, | 
					
						
							|  |  |  |                               Auth_Yadis_array_scramble($last)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $result; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Returns the "priority" attribute value of this <Service> | 
					
						
							|  |  |  |      * element, if the attribute is present.  Returns null if not. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return mixed $result Null or integer, depending on whether | 
					
						
							|  |  |  |      * this Service element has a 'priority' attribute. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function getPriority() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $attributes = $this->parser->attributes($this->element); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (array_key_exists('priority', $attributes)) { | 
					
						
							|  |  |  |             return intval($attributes['priority']); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return null; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Used to get XML elements from this object's <Service> element. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * This is what you should use to get all custom information out | 
					
						
							|  |  |  |      * of this element. This is used by service filter functions to | 
					
						
							|  |  |  |      * determine whether a service element contains specific tags, | 
					
						
							|  |  |  |      * etc.  NOTE: this only considers elements which are direct | 
					
						
							|  |  |  |      * children of the <Service> element for this object. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param string $name The name of the element to look for | 
					
						
							|  |  |  |      * @return array $list An array of elements with the specified | 
					
						
							|  |  |  |      * name which are direct children of the <Service> element.  The | 
					
						
							|  |  |  |      * nodes returned by this function can be passed to $this->parser | 
					
						
							|  |  |  |      * methods (see {@link Auth_Yadis_XMLParser}). | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function getElements($name) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return $this->parser->evalXPath($name, $this->element); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* | 
					
						
							|  |  |  |  * Return the expiration date of this XRD element, or None if no | 
					
						
							|  |  |  |  * expiration was specified. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @param $default The value to use as the expiration if no expiration | 
					
						
							|  |  |  |  * was specified in the XRD. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | function Auth_Yadis_getXRDExpiration($xrd_element, $default=null) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     $expires_element = $xrd_element->$parser->evalXPath('/xrd:Expires'); | 
					
						
							|  |  |  |     if ($expires_element === null) { | 
					
						
							|  |  |  |         return $default; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         $expires_string = $expires_element->text; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Will raise ValueError if the string is not the expected
 | 
					
						
							|  |  |  |         // format
 | 
					
						
							|  |  |  |         $t = strptime($expires_string, "%Y-%m-%dT%H:%M:%SZ"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ($t === false) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // [int $hour [, int $minute [, int $second [,
 | 
					
						
							|  |  |  |         //  int $month [, int $day [, int $year ]]]]]]
 | 
					
						
							|  |  |  |         return mktime($t['tm_hour'], $t['tm_min'], $t['tm_sec'], | 
					
						
							|  |  |  |                       $t['tm_mon'], $t['tm_day'], $t['tm_year']); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * This class performs parsing of XRDS documents. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should not instantiate this class directly; rather, call | 
					
						
							|  |  |  |  * parseXRDS statically: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * <pre>  $xrds = Auth_Yadis_XRDS::parseXRDS($xml_string);</pre> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * If the XRDS can be parsed and is valid, an instance of | 
					
						
							|  |  |  |  * Auth_Yadis_XRDS will be returned.  Otherwise, null will be | 
					
						
							|  |  |  |  * returned.  This class is used by the Auth_Yadis_Yadis::discover | 
					
						
							|  |  |  |  * method. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @package OpenID | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | class Auth_Yadis_XRDS { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Instantiate a Auth_Yadis_XRDS object.  Requires an XPath | 
					
						
							|  |  |  |      * instance which has been used to parse a valid XRDS document. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2010-06-29 10:24:48 -04:00
										 |  |  |     function Auth_Yadis_XRDS($xmlParser, $xrdNodes) | 
					
						
							| 
									
										
										
										
											2008-08-22 09:17:14 -04:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2010-06-29 10:24:48 -04:00
										 |  |  |         $this->parser = $xmlParser; | 
					
						
							| 
									
										
										
										
											2008-08-22 09:17:14 -04:00
										 |  |  |         $this->xrdNode = $xrdNodes[count($xrdNodes) - 1]; | 
					
						
							| 
									
										
										
										
											2010-06-29 10:24:48 -04:00
										 |  |  |         $this->allXrdNodes = $xrdNodes; | 
					
						
							| 
									
										
										
										
											2008-08-22 09:17:14 -04:00
										 |  |  |         $this->serviceList = array(); | 
					
						
							|  |  |  |         $this->_parse(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Parse an XML string (XRDS document) and return either a | 
					
						
							|  |  |  |      * Auth_Yadis_XRDS object or null, depending on whether the | 
					
						
							|  |  |  |      * XRDS XML is valid. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param string $xml_string An XRDS XML string. | 
					
						
							|  |  |  |      * @return mixed $xrds An instance of Auth_Yadis_XRDS or null, | 
					
						
							|  |  |  |      * depending on the validity of $xml_string | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2010-06-29 10:24:48 -04:00
										 |  |  |     static function parseXRDS($xml_string, $extra_ns_map = null) | 
					
						
							| 
									
										
										
										
											2008-08-22 09:17:14 -04:00
										 |  |  |     { | 
					
						
							|  |  |  |         $_null = null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!$xml_string) { | 
					
						
							|  |  |  |             return $_null; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $parser = Auth_Yadis_getXMLParser(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $ns_map = Auth_Yadis_getNSMap(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ($extra_ns_map && is_array($extra_ns_map)) { | 
					
						
							|  |  |  |             $ns_map = array_merge($ns_map, $extra_ns_map); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!($parser && $parser->init($xml_string, $ns_map))) { | 
					
						
							|  |  |  |             return $_null; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Try to get root element.
 | 
					
						
							|  |  |  |         $root = $parser->evalXPath('/xrds:XRDS[1]'); | 
					
						
							|  |  |  |         if (!$root) { | 
					
						
							|  |  |  |             return $_null; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (is_array($root)) { | 
					
						
							|  |  |  |             $root = $root[0]; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $attrs = $parser->attributes($root); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (array_key_exists('xmlns:xrd', $attrs) && | 
					
						
							|  |  |  |             $attrs['xmlns:xrd'] != Auth_Yadis_XMLNS_XRDS) { | 
					
						
							|  |  |  |             return $_null; | 
					
						
							|  |  |  |         } else if (array_key_exists('xmlns', $attrs) && | 
					
						
							|  |  |  |                    preg_match('/xri/', $attrs['xmlns']) && | 
					
						
							|  |  |  |                    $attrs['xmlns'] != Auth_Yadis_XMLNS_XRD_2_0) { | 
					
						
							|  |  |  |             return $_null; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Get the last XRD node.
 | 
					
						
							|  |  |  |         $xrd_nodes = $parser->evalXPath('/xrds:XRDS[1]/xrd:XRD'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!$xrd_nodes) { | 
					
						
							|  |  |  |             return $_null; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $xrds = new Auth_Yadis_XRDS($parser, $xrd_nodes); | 
					
						
							|  |  |  |         return $xrds; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function _addService($priority, $service) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $priority = intval($priority); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!array_key_exists($priority, $this->serviceList)) { | 
					
						
							|  |  |  |             $this->serviceList[$priority] = array(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->serviceList[$priority][] = $service; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Creates the service list using nodes from the XRDS XML | 
					
						
							|  |  |  |      * document. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function _parse() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->serviceList = array(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $services = $this->parser->evalXPath('xrd:Service', $this->xrdNode); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         foreach ($services as $node) { | 
					
						
							| 
									
										
										
										
											2010-06-29 10:24:48 -04:00
										 |  |  |             $s = new Auth_Yadis_Service(); | 
					
						
							| 
									
										
										
										
											2008-08-22 09:17:14 -04:00
										 |  |  |             $s->element = $node; | 
					
						
							| 
									
										
										
										
											2010-06-29 10:24:48 -04:00
										 |  |  |             $s->parser = $this->parser; | 
					
						
							| 
									
										
										
										
											2008-08-22 09:17:14 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |             $priority = $s->getPriority(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if ($priority === null) { | 
					
						
							|  |  |  |                 $priority = SERVICES_YADIS_MAX_PRIORITY; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             $this->_addService($priority, $s); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Returns a list of service objects which correspond to <Service> | 
					
						
							|  |  |  |      * elements in the XRDS XML document for this object. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * Optionally, an array of filter callbacks may be given to limit | 
					
						
							|  |  |  |      * the list of returned service objects.  Furthermore, the default | 
					
						
							|  |  |  |      * mode is to return all service objects which match ANY of the | 
					
						
							|  |  |  |      * specified filters, but $filter_mode may be | 
					
						
							|  |  |  |      * SERVICES_YADIS_MATCH_ALL if you want to be sure that the | 
					
						
							|  |  |  |      * returned services match all the given filters.  See {@link | 
					
						
							|  |  |  |      * Auth_Yadis_Yadis} for detailed usage information on filter | 
					
						
							|  |  |  |      * functions. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param mixed $filters An array of callbacks to filter the | 
					
						
							|  |  |  |      * returned services, or null if all services are to be returned. | 
					
						
							|  |  |  |      * @param integer $filter_mode SERVICES_YADIS_MATCH_ALL or | 
					
						
							|  |  |  |      * SERVICES_YADIS_MATCH_ANY, depending on whether the returned | 
					
						
							|  |  |  |      * services should match ALL or ANY of the specified filters, | 
					
						
							|  |  |  |      * respectively. | 
					
						
							|  |  |  |      * @return mixed $services An array of {@link | 
					
						
							|  |  |  |      * Auth_Yadis_Service} objects if $filter_mode is a valid | 
					
						
							|  |  |  |      * mode; null if $filter_mode is an invalid mode (i.e., not | 
					
						
							|  |  |  |      * SERVICES_YADIS_MATCH_ANY or SERVICES_YADIS_MATCH_ALL). | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function services($filters = null, | 
					
						
							|  |  |  |                       $filter_mode = SERVICES_YADIS_MATCH_ANY) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $pri_keys = array_keys($this->serviceList); | 
					
						
							|  |  |  |         sort($pri_keys, SORT_NUMERIC); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // If no filters are specified, return the entire service
 | 
					
						
							|  |  |  |         // list, ordered by priority.
 | 
					
						
							|  |  |  |         if (!$filters || | 
					
						
							|  |  |  |             (!is_array($filters))) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             $result = array(); | 
					
						
							|  |  |  |             foreach ($pri_keys as $pri) { | 
					
						
							|  |  |  |                 $result = array_merge($result, $this->serviceList[$pri]); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return $result; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // If a bad filter mode is specified, return null.
 | 
					
						
							|  |  |  |         if (!in_array($filter_mode, array(SERVICES_YADIS_MATCH_ANY, | 
					
						
							|  |  |  |                                           SERVICES_YADIS_MATCH_ALL))) { | 
					
						
							|  |  |  |             return null; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Otherwise, use the callbacks in the filter list to
 | 
					
						
							|  |  |  |         // determine which services are returned.
 | 
					
						
							|  |  |  |         $filtered = array(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         foreach ($pri_keys as $priority_value) { | 
					
						
							|  |  |  |             $service_obj_list = $this->serviceList[$priority_value]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             foreach ($service_obj_list as $service) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 $matches = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 foreach ($filters as $filter) { | 
					
						
							| 
									
										
										
										
											2010-06-29 10:24:48 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |                     if (call_user_func_array($filter, array(&$service))) { | 
					
						
							| 
									
										
										
										
											2008-08-22 09:17:14 -04:00
										 |  |  |                         $matches++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                         if ($filter_mode == SERVICES_YADIS_MATCH_ANY) { | 
					
						
							|  |  |  |                             $pri = $service->getPriority(); | 
					
						
							|  |  |  |                             if ($pri === null) { | 
					
						
							|  |  |  |                                 $pri = SERVICES_YADIS_MAX_PRIORITY; | 
					
						
							|  |  |  |                             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                             if (!array_key_exists($pri, $filtered)) { | 
					
						
							|  |  |  |                                 $filtered[$pri] = array(); | 
					
						
							|  |  |  |                             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                             $filtered[$pri][] = $service; | 
					
						
							|  |  |  |                             break; | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (($filter_mode == SERVICES_YADIS_MATCH_ALL) && | 
					
						
							|  |  |  |                     ($matches == count($filters))) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     $pri = $service->getPriority(); | 
					
						
							|  |  |  |                     if ($pri === null) { | 
					
						
							|  |  |  |                         $pri = SERVICES_YADIS_MAX_PRIORITY; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     if (!array_key_exists($pri, $filtered)) { | 
					
						
							|  |  |  |                         $filtered[$pri] = array(); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     $filtered[$pri][] = $service; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $pri_keys = array_keys($filtered); | 
					
						
							|  |  |  |         sort($pri_keys, SORT_NUMERIC); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $result = array(); | 
					
						
							|  |  |  |         foreach ($pri_keys as $pri) { | 
					
						
							|  |  |  |             $result = array_merge($result, $filtered[$pri]); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $result; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 |