-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathExtension.php
More file actions
316 lines (271 loc) · 10.4 KB
/
Copy pathExtension.php
File metadata and controls
316 lines (271 loc) · 10.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
<?php
// Google+ extension for Bolt
namespace Bolt\Extension\DanielKulbe\GooglePlus;
use Bolt\Translation\Translator as Trans;
use Guzzle\Http\StaticClient as Client;
use Guzzle\Http\Url as Url;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpFoundation\Response;
class Extension extends \Bolt\BaseExtension
{
// @const string Extension name
const NAME = 'Google+';
// @const string API base URL
const API = 'https://www.googleapis.com/plus/v1/people';
// @var array API cUrl request options
private static $curl_options = array(
CURLOPT_CONNECTTIMEOUT => 20,
CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.31',
CURLOPT_AUTOREFERER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => 0,
CURLOPT_SSL_VERIFYHOST => 0
);
// @var int Runtime, for to compare with local files time.
private $runtime;
// @var array Allowed file formats for saveFile()
// @see http://php.net/manual/en/image.constants.php
private static $fileFormats = array(
'.jpg' => IMAGETYPE_JPEG,
'.png' => IMAGETYPE_PNG,
'.gif' => IMAGETYPE_GIF,
);
/**
* Get the extension's human readable name
*
* @return string
*/
public function getName()
{
return Extension::NAME;
}
/**
* Add Twig settings in 'frontend' environment
*
* @return void
*/
public function initialize()
{
// Add Extension template path
$this->app['twig.loader.filesystem']->addPath(__DIR__ . '/assets');
// Add theme template path (makes sure it is also available in async environment)
$this->app['twig.loader.filesystem']->addPath($this->app['paths']['themepath']);
// Set up the routes for the widgets
$this->app->match("/googleplus/{type}", array($this, 'renderWidget'));
// Add Javascript widget Twig function and loader to frontend
if ($this->app['config']->getWhichEnd() == 'frontend') {
$this->addTwigFunction('googlewidget', 'renderWidgetHolder');
$this->addJavascript('assets/loader.js', array('late' => true, 'priority' => 1000));
}
$this->runtime = time();
}
/**
* Set the defaults for configuration parameters
*
* @return array
*/
protected function getDefaultConfig()
{
return array(
# 'app_developer_key' => ''
'cache' => true,
'defer' => true,
'files' => false,
'filedir' => 'googleplus',
'profile' => array(
'user' => 'me',
'template' => 'gplus_profile.twig'
),
'activity' => array(
'user' => 'me',
'results' => 10,
'template' => 'gplus_feed.twig'
)
);
}
/**
* Get the duration (in seconds) for the cache.
*
* @return int;
*/
protected function cacheDuration()
{
// in minutes..
$duration = $this->app['config']->get('general/caching/duration', 10);
// in seconds.
return intval($duration) * 60;
}
/**
* Save external files to filesystem
*
* @param $url string
* @return string
*/
protected function saveFile ($url)
{
list($width, $height, $type, $attr) = getimagesize($url);
if (false === $ext = array_search(
$type, // safe for external URLs
Extension::$fileFormats,
true
)) {
$this->app['logger.system']->warning("[GooglePlus]: saveFile() remote file '{$url}' has an invalid format (".$type.").", ['event' => 'extension']);
} else {
$basename = sprintf('/%s/%s', $this->config['filedir'], hash('sha1', $url).$ext);
$filename = sprintf(
'%s/files%s',
$this->app['paths']['rootpath'],
$basename
);
// Check for doubles.
if ( is_file($filename) && filectime($filename) > ($this->runtime - $this->cacheDuration()) ) {
return $basename;
}
// Make sure the folder exists.
$fileSystem = new Filesystem();
$fileSystem->mkdir(dirname($filename));
if (is_writable(dirname($filename))) {
// Yes, we can create the file!
$fileSystem->copy($url, $filename, true); // true: make sure, we overwrite an existing old file
$this->app['logger.system']->info("[GooglePlus]: saveFile() copied file '{$url}' as '{$basename}'.", ['event' => 'extension']);
return $basename;
}
$this->app['logger.system']->warning("[GooglePlus]: saveFile() couldn't write '{$url}' as '{$filename}'.", ['event' => 'extension']);
}
return $url;
}
/**
* Replace external file urls with local paths
*
* @param $values array
* @return array
*/
protected function localFiles (array $values = array())
{
if (!empty($values)) {
# PROFILE: image
if (isset($values['record']['image']))
$values['record']['image']['url'] = $this->saveFile(str_replace('sz=50', 'sz=100', $values['record']['image']['url']));
// (including a little trick to get a larger profile image)
# PROFILE: cover
if (isset($values['record']['cover']))
$values['record']['cover']['coverPhoto']['url'] = $this->saveFile($values['record']['cover']['coverPhoto']['url']);
# FEED: attachment image
if (isset($values['record']['items'])) foreach ($values['record']['items'] as $key => $item) {
if (count($item['object']['attachments']) > 0) foreach ($item['object']['attachments'] as $a_key => $a_item) {
if (isset($a_item['image']))
$values['record']['items'][$key]['object']['attachments'][$a_key]['image']['url'] = $this->saveFile($a_item['image']['url']);
}
}
}
return $values;
}
/**
* Retrieve a fully response object from Google+ API Service.
*
* @param $method string
* @return mixed
*/
protected function handleRequest($method = 'profile')
{
$export = array(
'status' => false,
'record' => "Edit 'config.yml' to set up your Google API developer key or OAuth2 access."
);
// Google+ API Public access
if (isset($this->config['app_developer_key']) && !empty($this->config['app_developer_key'])) {
// Factory API base url
$url = Url::factory(Extension::API);
// Build API request
switch ($method) {
case 'profile':
default:
$url = $url->addPath('/' . $this->config['profile']['user'])
->setQuery('key='.$this->config['app_developer_key']);
break;
case 'activity':
$url = $url->addPath('/' . $this->config['activity']['user'] . '/activities/public')
->setQuery('maxResults='.$this->config['activity']['results'].'&key='.$this->config['app_developer_key']);
break;
}
// Request data
$request = Client::get($url, Extension::$curl_options)->getBody()->__toString();
$export = array(
'status' => true,
'record' => json_decode($request, true)
);
}
return $export;
}
/**
* Render the Google+ profile box
*
* @return string
*/
public function googlePlusProfile ()
{
$cachekey= 'widget_gog_profile';
if ($this->app['cache']->contains($cachekey)) {
return $this->app['cache']->fetch($cachekey);
}
$twigValues = $this->handleRequest('profile');
if ($this->config['files']) $twigValues = $this->localFiles($twigValues);
$cache = $this->config['cache'] === true ? $this->cacheDuration() : 0;
$html = $this->app['render']->render($this->config['profile']['template'], $twigValues)->__toString();
$this->app['cache']->save($cachekey, $html, $cache);
return $html;
}
/**
* Render the Google+ public activity feed
*
* @return string
*/
public function googlePlusFeed ()
{
$cachekey = 'widget_gog_feed';
if ($this->app['cache']->contains($cachekey)) {
return $this->app['cache']->fetch($cachekey);
}
$twigValues = $this->handleRequest('activity');
if ($this->config['files']) $twigValues = $this->localFiles($twigValues);
$cache = $this->config['cache'] === true ? $this->cacheDuration() : 0;
$html = $this->app['render']->render($this->config['activity']['template'], $twigValues)->__toString();
$this->app['cache']->save($cachekey, $html, $cache);
return $html;
}
/**
* Render the widget holder for Frontend
*
* @param string $type Widgettype
* @return \Twig_Markup Rendered Twig Markup
*/
public function renderWidgetHolder($type)
{
$str = sprintf(
"<section><div class='widget-gog' id='widget-gog-%s' data-key='%s'%s>%s</div></section>",
$type,
$type,
!$this->config['defer'] ? '' : " data-defer='true'",
$this->config['defer'] ? '' : $this->{'googlePlus'.ucfirst($type)}()
);
return new \Twig_Markup($str, 'UTF-8');
}
/**
* Render deferred Request
*
* @param string $type Widgettype
* @return \Symfony\Component\HttpFoundation\Response
*/
public function renderWidget($type) {
$this->app['extensions']->clearSnippetQueue();
$this->app['extensions']->disableJquery();
$this->app['debugbar'] = false;
if (true === $this->app['request']->isXmlHttpRequest() && 'GET' == $this->app['request']->getMethod()) {
$body = $this->{'googlePlus'.ucfirst($type)}();
return new Response($body, Response::HTTP_OK, array('Cache-Control' => 's-maxage=180, public'));
} else {
return new Response(Trans::__('Permission denied'), Response::HTTP_FORBIDDEN);
}
}
}