refactored 80%
[pharext/pharext.org] / app / Github / API / Call.php
1 <?php
2
3 namespace app\Github\API;
4
5 use app\Github\API;
6 use app\Github\Storage\Item;
7 use http\Client\Response;
8 use http\QueryString;
9 use http\Url;
10 use merry\Config;
11
12 use React\Promise;
13
14 abstract class Call
15 {
16 /**
17 * @var Config
18 */
19 protected $config;
20
21 /**
22 * @var \app\Gituhub\API
23 */
24 protected $api;
25
26 /**
27 * @var array
28 */
29 protected $args = [];
30
31 /**
32 * @var \http\Url
33 */
34 protected $url;
35
36 /**
37 * @var QueryString
38 */
39 protected $query;
40
41 /**
42 * @var \React\Promise\Deferred
43 */
44 protected $deferred;
45
46 /**
47 * @return Request
48 */
49 abstract protected function request();
50
51 /**
52 * @return array
53 */
54 abstract protected function response(Response $response);
55
56 /**
57 * @param API $api
58 * @param array $args
59 */
60 function __construct(API $api, array $args = null) {
61 $this->api = $api;
62 $this->config = $this->api->getConfig();
63 $this->url = new Url($this->config->api->url, null, 0);
64 $this->deferred = new Promise\Deferred;
65
66 if ($args) {
67 $this->args = $args;
68 }
69 if (isset($this->config->api->call->{$this}->args)) {
70 $this->args += $this->config->api->call->{$this}->args->toArray();
71 }
72 }
73
74 /**
75 * @return \React\Promise\Promise
76 */
77 function __invoke() {
78 if ($this->readFromCache($this->result)) {
79 return new Promise\FulfilledPromise($this->result);
80 } else {
81 $this->api->getClient()->enqueue(
82 $this->request(),
83 function($response) {
84 try {
85 $this->deferred->resolve($this->response($response));
86 } catch (\Exception $e) {
87 $this->deferred->reject($e);
88 }
89 return true;
90 }
91 );
92 return $this->deferred->promise();
93 }
94 }
95
96 /**
97 * Get type of call
98 * @return string
99 */
100 function __toString() {
101 $parts = explode("\\", get_class($this));
102 return strtolower(end($parts));
103 }
104
105 /**
106 * Get associated cache storage
107 * @param int $ttl out param of configure ttl
108 * @return Storage
109 */
110 function getCache(&$ttl = null) {
111 if (isset($this->config->storage->cache->{$this}->ttl)) {
112 $ttl = $this->config->storage->cache->{$this}->ttl;
113 }
114 return $this->api->getCacheStorage();
115 }
116
117 function getCacheKey() {
118 $args = $this->args;
119 unset($args["fresh"]);
120 if (isset($args["page"]) && !strcmp($args["page"], "1")) {
121 unset($args["page"]);
122 }
123 ksort($args);
124 return sprintf("%s:%s:%s", $this->api->getToken(), $this,
125 new QueryString($args));
126 }
127
128 function readFromCache(array &$value = null) {
129 if (!empty($this->args["fresh"])) {
130 return false;
131 }
132 if (!($cache = $this->api->getCacheStorage())) {
133 return false;
134 }
135 if (!strlen($key = $this->getCacheKey())) {
136 return false;
137 }
138 if (!$cache->get($key, $cached)) {
139 return false;
140 }
141 if (null !== $this->api->getMaxAge() && $cached->getAge() > $this->api->getMaxAge()) {
142 return false;
143 }
144 $this->api->getLogger()->debug("Cache-Hit: $this", $this->args);
145 $value = $cached->getValue();
146 return true;
147 }
148
149 function saveToCache(array $fresh) {
150 if (($cache = $this->api->getCacheStorage())) {
151 if (isset($this->config->storage->cache->{$this}->ttl)) {
152 $ttl = $this->config->storage->cache->{$this}->ttl;
153 } else {
154 $ttl = null;
155 }
156
157 $key = $this->getCacheKey();
158 $cache->set($key, new Item($fresh, $ttl));
159 }
160 }
161
162 function dropFromCache() {
163 if (($cache = $this->api->getCacheStorage())) {
164 $key = $this->getCacheKey();
165 $cache->del($key);
166 }
167 }
168 }