CacheListener   A
last analyzed

Complexity

Total Complexity 15

Size/Duplication

Total Lines 180
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 7

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 15
lcom 2
cbo 7
dl 0
loc 180
ccs 50
cts 50
cp 1
rs 10
c 0
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A getCache() 0 4 1
A setCache() 0 6 1
A getCacheableActions() 0 4 1
A setCacheableActions() 0 6 1
A attach() 0 5 1
A onSendPre() 0 18 3
A onSendPost() 0 19 3
A isActionCacheable() 0 6 1
A generateCacheId() 0 12 2
1
<?php
2
3
namespace PamiModule\Listener;
4
5
use PAMI\Message\OutgoingMessage;
6
use PamiModule\Service\Client;
7
use Zend\Cache\Storage\StorageInterface;
8
use Zend\EventManager\EventInterface;
9
use Zend\EventManager\EventManagerInterface;
10
use Zend\EventManager\ListenerAggregateInterface;
11
use Zend\EventManager\ListenerAggregateTrait;
12
13
/**
14
 * Class CacheListener.
15
 */
16
class CacheListener implements ListenerAggregateInterface
17
{
18
    use ListenerAggregateTrait;
19
20
    /**
21
     * Cache instance.
22
     *
23
     * @var StorageInterface
24
     */
25
    protected $cache;
26
    /**
27
     * Cacheable actions.
28
     *
29
     * @var array
30
     */
31
    protected $cacheableActions = [];
32
33
    /**
34
     * CacheListener constructor.
35
     *
36
     * @param StorageInterface $cache            Cache to use
37
     * @param array            $cacheableActions Actions to cache
38
     */
39 3
    public function __construct(StorageInterface $cache, $cacheableActions = [])
40
    {
41 3
        $this->setCache($cache);
42 3
        $this->setCacheableActions($cacheableActions);
43 3
    }
44
45
    /**
46
     * Return the cache storage.
47
     *
48
     * @return StorageInterface
49
     */
50 1
    public function getCache()
51
    {
52 1
        return $this->cache;
53
    }
54
55
    /**
56
     * Set the cache storage to use.
57
     *
58
     * @param StorageInterface $cache Cache storage to use
59
     *
60
     * @return $this
61
     */
62 3
    public function setCache(StorageInterface $cache)
63
    {
64 3
        $this->cache = $cache;
65
66 3
        return $this;
67
    }
68
69
    /**
70
     * Return the action classes to cache.
71
     *
72
     * @return array
73
     */
74 1
    public function getCacheableActions()
75
    {
76 1
        return $this->cacheableActions;
77
    }
78
79
    /**
80
     * Set the actions to cache.
81
     *
82
     * @param array $cacheableActions Actions to cache
83
     *
84
     * @return $this
85
     */
86 3
    public function setCacheableActions(array $cacheableActions)
87
    {
88 3
        $this->cacheableActions = array_map('strtolower', $cacheableActions);
89
90 3
        return $this;
91
    }
92
93
    /**
94
     * Attach one or more listeners.
95
     *
96
     * Implementors may add an optional $priority argument; the EventManager
97
     * implementation will pass this to the aggregate.
98
     *
99
     * @param EventManagerInterface $events   The event manager
100
     * @param int                   $priority
101
     */
102 1
    public function attach(EventManagerInterface $events, $priority = 1)
103
    {
104 1
        $this->listeners[] = $events->attach('sendAction.pre', [$this, 'onSendPre'], $priority);
105 1
        $this->listeners[] = $events->attach('sendAction.post', [$this, 'onSendPost'], $priority);
106 1
    }
107
108
    /**
109
     * Triggered on sendAction.pre.
110
     *
111
     * @param EventInterface $event Triggered event
112
     *
113
     * @throws \Zend\Cache\Exception\ExceptionInterface
114
     *
115
     * @return void|\PAMI\Message\Response\ResponseMessage
116
     */
117 2
    public function onSendPre(EventInterface $event)
118
    {
119
        /* @var OutgoingMessage $action */
120 2
        $action = $event->getParam('action');
121
        /* @var Client $client */
122 2
        $client = $event->getTarget();
123
124 2
        if (!$this->isActionCacheable($action)) {
125 1
            return;
126
        }
127
128 1
        $cacheId = $this->generateCacheId($action, $client->getHost());
129
130 1
        if ($this->cache->hasItem($cacheId)) {
131
            // If cached item is an instance of \PAMI\Message\Response\ResponseMessage, the execution will be stopped
132 1
            return $this->cache->getItem($cacheId);
133
        }
134 1
    }
135
136
    /**
137
     * Triggered on sendAction.post.
138
     *
139
     * @param EventInterface $event Triggered event
140
     */
141 2
    public function onSendPost(EventInterface $event)
142
    {
143
        /* @var OutgoingMessage $action */
144 2
        $action = $event->getParam('action');
145
        /* @var Client $client */
146 2
        $client = $event->getTarget();
147
148 2
        if (!$this->isActionCacheable($action)) {
149 1
            return;
150
        }
151
152
        /* @var \PAMI\Message\Response\ResponseMessage $response */
153 1
        $response = $event->getParam('response');
154 1
        $cacheId = $this->generateCacheId($action, $client->getHost());
155
156 1
        if ($response->isSuccess()) {
157 1
            $this->cache->setItem($cacheId, $response);
158 1
        }
159 1
    }
160
161
    /**
162
     * Return true if we can cache the action.
163
     *
164
     * @param OutgoingMessage $action Requested action
165
     *
166
     * @return bool
167
     */
168 2
    protected function isActionCacheable(OutgoingMessage $action)
169
    {
170 2
        $actionName = $action->getKey('Action');
171
172 2
        return in_array(strtolower($actionName), $this->cacheableActions, true);
173
    }
174
175
    /**
176
     * Generate a cache ID based on action keys.
177
     *
178
     * @param OutgoingMessage $action The action
179
     * @param string          $prefix Cache ID prefix
180
     *
181
     * @return string
182
     */
183 1
    protected function generateCacheId(OutgoingMessage $action, $prefix = '')
184
    {
185 1
        $removeKeys = ['actionid'];
186 1
        $keys = $action->getKeys();
187 1
        $keys = array_diff_key($keys, array_flip($removeKeys));
188 1
        $variables = $action->getVariables();
189 1
        $variables = is_array($variables) ? $variables : [];
190 1
        ksort($keys);
191 1
        ksort($variables);
192
193 1
        return md5($prefix . json_encode(array_merge($keys, $variables)));
194
    }
195
}
196