This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * This file is part of Chirp package |
||
4 | * |
||
5 | * Copyright (c) 2015 Alberto Pagliarini |
||
6 | * |
||
7 | * Licensed under the MIT license |
||
8 | * https://github.com/batopa/chirp/blob/master/LICENSE |
||
9 | */ |
||
10 | namespace Bato\Chirp; |
||
11 | |||
12 | use Bato\Chirp\Utility\Parser; |
||
13 | use MongoDB\Client; |
||
14 | use Abraham\TwitterOAuth\TwitterOAuth; |
||
15 | |||
16 | /** |
||
17 | * Chirp Class |
||
18 | * |
||
19 | * Help to create a cache for Twitter using MongoDB |
||
20 | * |
||
21 | */ |
||
22 | class Chirp |
||
23 | { |
||
24 | |||
25 | /** |
||
26 | * The Database object |
||
27 | * |
||
28 | * @var \MongoDB\Database |
||
29 | */ |
||
30 | private $db = null; |
||
31 | |||
32 | /** |
||
33 | * The instance of TwitterOAuth |
||
34 | * |
||
35 | * @var \Abraham\TwitterOAuth\TwitterOAuth |
||
36 | */ |
||
37 | private $twitter; |
||
38 | |||
39 | /** |
||
40 | * Constructor |
||
41 | * |
||
42 | * Passing $twitterAuthConf and/or $mongoConf it tries to setup them |
||
43 | * |
||
44 | * $twitterAuthConf must contain |
||
45 | * - consumer_key |
||
46 | * - consumer_secret |
||
47 | * - oauth_access_token |
||
48 | * - oauth_access_token_secret |
||
49 | * |
||
50 | * $mongoConf must contain |
||
51 | * - db: the name of mongo database to use |
||
52 | * |
||
53 | * and can contain |
||
54 | * - uri |
||
55 | * - uriOptions |
||
56 | * - driverOptions |
||
57 | * |
||
58 | * used for MongoDB connection |
||
59 | * |
||
60 | * @see \MongoDB\Client for $mongoConf |
||
61 | * @param array $twitterAuthConf |
||
62 | * @param array $mongoDbConf |
||
63 | */ |
||
64 | public function __construct(array $twitterAuthConf = array(), array $mongoDbConf = array()) |
||
65 | { |
||
66 | if (!empty($twitterAuthConf)) { |
||
67 | $this->setupTwitter($twitterAuthConf); |
||
68 | } |
||
69 | if (!empty($mongoDbConf)) { |
||
70 | $this->setupMongoDb($mongoDbConf); |
||
71 | } |
||
72 | } |
||
73 | |||
74 | /** |
||
75 | * Setup TwitterOAuth |
||
76 | * |
||
77 | * $twitterAuthConf must contain |
||
78 | * - consumer_key |
||
79 | * - consumer_secret |
||
80 | * - oauth_access_token |
||
81 | * - oauth_access_token_secret |
||
82 | * |
||
83 | * @param array $twitterAuthConf |
||
84 | * @return $this |
||
85 | */ |
||
86 | public function setupTwitter(array $twitterAuthConf) |
||
87 | { |
||
88 | $twitterAuthConf += [ |
||
89 | 'consumer_key' => null, |
||
90 | 'consumer_secret' => null, |
||
91 | 'oauth_access_token' => null, |
||
92 | 'oauth_access_token_secret' => null |
||
93 | ]; |
||
94 | $this->twitter = new TwitterOAuth( |
||
95 | $twitterAuthConf['consumer_key'], |
||
96 | $twitterAuthConf['consumer_secret'], |
||
97 | $twitterAuthConf['oauth_access_token'], |
||
98 | $twitterAuthConf['oauth_access_token_secret'] |
||
99 | ); |
||
100 | $this->twitter->setDecodeJsonAsArray(true); |
||
101 | return $this; |
||
102 | } |
||
103 | |||
104 | /** |
||
105 | * Setup MongoDB connection |
||
106 | * |
||
107 | * $mongoDbConf must contain |
||
108 | * - db: the name of mongo database to use |
||
109 | * |
||
110 | * and can contain |
||
111 | * - uri |
||
112 | * - uriOptions |
||
113 | * - driverOptions |
||
114 | * |
||
115 | * @see \MongoDB\Client for $mongoConf |
||
116 | * @param array $mongoDbConf |
||
117 | * @return $this |
||
118 | */ |
||
119 | public function setupMongoDb(array $mongoDbConf) |
||
120 | { |
||
121 | $mongoDbConf += [ |
||
122 | 'uri' => 'mongodb://localhost:27017', |
||
123 | 'uriOptions' => [], |
||
124 | 'driverOptions' => [], |
||
125 | 'db' => '' |
||
126 | ]; |
||
127 | $client = new Client($mongoDbConf['uri'], $mongoDbConf['uriOptions'], $mongoDbConf['driverOptions']); |
||
128 | $this->db = $client->selectDatabase($mongoDbConf['db']); |
||
129 | return $this; |
||
130 | } |
||
131 | |||
132 | /** |
||
133 | * Return TwitterOAuth instance |
||
134 | * |
||
135 | * @return \Abraham\TwitterOAuth\TwitterOAuth |
||
136 | */ |
||
137 | public function getTwitter() |
||
138 | { |
||
139 | if (empty($this->twitter)) { |
||
140 | throw new \RuntimeException( |
||
141 | 'You have to setup twitter before use it. See \Bato\Chirp\Chirp::setupTwitter()' |
||
142 | ); |
||
143 | } |
||
144 | return $this->twitter; |
||
145 | } |
||
146 | |||
147 | /** |
||
148 | * Return the instance of MongoDB database |
||
149 | * |
||
150 | * @return \MongoDB\Database |
||
151 | */ |
||
152 | public function getDb() |
||
153 | { |
||
154 | if (empty($this->db)) { |
||
155 | throw new \RuntimeException( |
||
156 | 'You have to setup MongoDB connection before use it. See \Bato\Chirp\Chirp::setupMongoDb()' |
||
157 | ); |
||
158 | } |
||
159 | return $this->db; |
||
160 | } |
||
161 | |||
162 | /** |
||
163 | * Starting from twitter endpoint return the related collection |
||
164 | * It replaces "/" with "-" after removing trailing "/", for example: |
||
165 | * |
||
166 | * endpoint "statuses/user_timeline" corresponds to "statuses-user_timeline" collection |
||
167 | * |
||
168 | * @param string $endpoint [description] |
||
169 | * @return \MongoDB\Collection |
||
170 | */ |
||
171 | public function getCollection($endpoint) |
||
172 | { |
||
173 | $name = Parser::normalize($endpoint); |
||
174 | return $this->getDb() |
||
175 | ->selectCollection($name); |
||
176 | } |
||
177 | |||
178 | /** |
||
179 | * Perform a Twitter request |
||
180 | * |
||
181 | * @param string $endpoint the endpoint for example 'statuses/user_timeline' |
||
182 | * @param array $query an array that specify query string to use with the endpoint |
||
183 | * @param string $requestMethod the http request method |
||
184 | * @return array |
||
185 | */ |
||
186 | public function request($endpoint, $query = [], $requestMethod = 'get') |
||
187 | { |
||
188 | $validMethods = ['get', 'post', 'put', 'delete']; |
||
189 | $requestMethod = strtolower($requestMethod); |
||
190 | if (!in_array($requestMethod, $validMethods)) { |
||
191 | throw new \UnexpectedValueException('Unsupported http request method ' . $requestMethod); |
||
192 | } |
||
193 | $response = $this->getTwitter() |
||
194 | ->{$requestMethod}($endpoint, $query); |
||
195 | |||
196 | return $response; |
||
197 | } |
||
198 | |||
199 | /** |
||
200 | * Read results from a collection (default self::collection) |
||
201 | * using $filter to filter results |
||
202 | * |
||
203 | * If $options['limit'] = 1 return a \MongoDB\BSONDocument object |
||
204 | * else return an array or a cursor depending from $options['returnType'] |
||
205 | * |
||
206 | * @param string $endpoint |
||
207 | * @param array $filter |
||
208 | * @param array $options |
||
209 | * @return object|array |
||
210 | */ |
||
211 | public function read($endpoint, array $filter = [], array $options = []) |
||
212 | { |
||
213 | $options += ['returnType' => 'array']; |
||
214 | $collection = $this->getCollection($endpoint); |
||
215 | // delegate to MongoDB\Collection::findOne() |
||
216 | if (isset($options['limit']) && $options['limit'] === 1) { |
||
217 | return $collection->findOne($filter, $options); |
||
218 | } |
||
219 | $cursor = $collection->find($filter, $options); |
||
220 | return ($options['returnType'] == 'array') ? iterator_to_array($cursor) : $cursor; |
||
221 | } |
||
222 | |||
223 | /** |
||
224 | * Perform twitter request and save results in db. |
||
225 | * |
||
226 | * Possible $options are: |
||
227 | * - query: an array used for compose query string |
||
228 | * - grep: an array used for look up. Results matching the grep criteria will be saved. |
||
229 | * Example |
||
230 | * ``` |
||
231 | * [ |
||
232 | * 'key_to_look_up' => ['match1', 'match2'], |
||
233 | * 'other_key_to_look_up' => ['match3'] |
||
234 | * ] |
||
235 | * ``` |
||
236 | * - require: an array of string of keys required. |
||
237 | * Only results with those fields will be saved. |
||
238 | * Use point separtated string to go deep in results, for example |
||
239 | * `'key1.key2.key3'` checks against`[ 'key1' => ['key2' => ['key3' => 'some_value']]] ` |
||
240 | * |
||
241 | * @param string $endpoint the twitter endpoint for example 'statuses/user_timeline' |
||
242 | * @param array $options |
||
243 | * @return array |
||
244 | */ |
||
245 | public function write($endpoint, array $options = []) |
||
246 | { |
||
247 | $options = $this->prepareWriteOptions($options); |
||
248 | $response = $this->request($endpoint, $options['query']); |
||
249 | if (empty($response)) { |
||
250 | return ['saved' => [], 'read'=> []]; |
||
251 | } |
||
252 | |||
253 | if (array_key_exists('errors', $response)) { |
||
254 | return $response; |
||
255 | } |
||
256 | |||
257 | $collection = $this->getCollection($endpoint); |
||
258 | $tweets = $this->filterToSave($response, $collection, $options); |
||
259 | if (!empty($tweets)) { |
||
260 | $collection->insertMany($tweets); |
||
261 | } |
||
262 | |||
263 | return [ |
||
264 | 'saved' => $tweets, |
||
265 | 'read'=> $response |
||
266 | ]; |
||
267 | } |
||
268 | |||
269 | /** |
||
270 | * Check and return $options to be used in self::write() |
||
271 | * |
||
272 | * @param array $options |
||
273 | * @return array |
||
274 | */ |
||
275 | private function prepareWriteOptions($options) |
||
276 | { |
||
277 | $options += [ |
||
278 | 'query' => [], |
||
279 | 'grep' => [], |
||
280 | 'require' => [] |
||
281 | ]; |
||
282 | foreach (['query', 'grep', 'require'] as $test) { |
||
283 | if (!is_array($options[$test])) { |
||
284 | throw new \UnexpectedValueException('"' . $test . '" option must be an array'); |
||
285 | } |
||
286 | } |
||
287 | $options['query'] = array_filter($options['query']); |
||
288 | return $options; |
||
289 | } |
||
290 | |||
291 | /** |
||
292 | * Given an array of tweets and a collection |
||
293 | * return the tweets that missing from the collection |
||
294 | * |
||
295 | * @see self::write() for $options |
||
296 | * @param array $tweets |
||
297 | * @param \MongoDB\Collection $collection |
||
298 | * @param array $options |
||
299 | * @return array |
||
300 | */ |
||
301 | private function filterToSave(array $tweets, \MongoDB\Collection $collection, array $options) |
||
302 | { |
||
303 | $toSave = []; |
||
304 | foreach ($tweets as $key => $tweet) { |
||
305 | if (!Parser::match($tweet, $options)) { |
||
306 | continue; |
||
307 | } |
||
308 | |||
309 | $countTweets = $collection->count(['id_str' => $tweet['id_str']]); |
||
0 ignored issues
–
show
|
|||
310 | if ($countTweets === 0) { |
||
311 | $toSave[] = $tweet; |
||
312 | } |
||
313 | } |
||
314 | return $toSave; |
||
315 | } |
||
316 | } |
||
317 |
This method has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.