1<?php
2/**
3 * Zend Framework (http://framework.zend.com/)
4 *
5 * @link      http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license   http://framework.zend.com/license/new-bsd New BSD License
8 */
9
10namespace Zend\View\Resolver;
11
12use Countable;
13use IteratorAggregate;
14use Zend\Stdlib\PriorityQueue;
15use Zend\View\Renderer\RendererInterface as Renderer;
16use Zend\View\Resolver\ResolverInterface as Resolver;
17
18class AggregateResolver implements Countable, IteratorAggregate, ResolverInterface
19{
20    const FAILURE_NO_RESOLVERS = 'AggregateResolver_Failure_No_Resolvers';
21    const FAILURE_NOT_FOUND    = 'AggregateResolver_Failure_Not_Found';
22
23    /**
24     * Last lookup failure
25     * @var false|string
26     */
27    protected $lastLookupFailure = false;
28
29    /**
30     * @var Resolver
31     */
32    protected $lastSuccessfulResolver;
33
34    /**
35     * @var PriorityQueue
36     */
37    protected $queue;
38
39    /**
40     * Constructor
41     *
42     * Instantiate the internal priority queue
43     *
44     */
45    public function __construct()
46    {
47        $this->queue = new PriorityQueue();
48    }
49
50    /**
51     * Return count of attached resolvers
52     *
53     * @return int
54     */
55    public function count()
56    {
57        return $this->queue->count();
58    }
59
60    /**
61     * IteratorAggregate: return internal iterator
62     *
63     * @return PriorityQueue
64     */
65    public function getIterator()
66    {
67        return $this->queue;
68    }
69
70    /**
71     * Attach a resolver
72     *
73     * @param  Resolver $resolver
74     * @param  int $priority
75     * @return AggregateResolver
76     */
77    public function attach(Resolver $resolver, $priority = 1)
78    {
79        $this->queue->insert($resolver, $priority);
80        return $this;
81    }
82
83    /**
84     * Resolve a template/pattern name to a resource the renderer can consume
85     *
86     * @param  string $name
87     * @param  null|Renderer $renderer
88     * @return false|string
89     */
90    public function resolve($name, Renderer $renderer = null)
91    {
92        $this->lastLookupFailure      = false;
93        $this->lastSuccessfulResolver = null;
94
95        if (0 === count($this->queue)) {
96            $this->lastLookupFailure = static::FAILURE_NO_RESOLVERS;
97            return false;
98        }
99
100        foreach ($this->queue as $resolver) {
101            $resource = $resolver->resolve($name, $renderer);
102            if ($resource) {
103                // Resource found; return it
104                $this->lastSuccessfulResolver = $resolver;
105                return $resource;
106            }
107        }
108
109        $this->lastLookupFailure = static::FAILURE_NOT_FOUND;
110        return false;
111    }
112
113    /**
114     * Return the last successful resolver, if any
115     *
116     * @return Resolver
117     */
118    public function getLastSuccessfulResolver()
119    {
120        return $this->lastSuccessfulResolver;
121    }
122
123    /**
124     * Get last lookup failure
125     *
126     * @return false|string
127     */
128    public function getLastLookupFailure()
129    {
130        return $this->lastLookupFailure;
131    }
132}
133