Skip to content

Commit 351888d

Browse files
committed
2.3.0-beta2
1 parent 98c3872 commit 351888d

File tree

6 files changed

+58
-45
lines changed

6 files changed

+58
-45
lines changed

_build/config/phpthumbof.config.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
'packageNameLower' => 'phpthumbof',
1717
'packageDescription' => 'A better phpThumbOf',
1818
'version' => '2.3.0',
19-
'release' => 'beta1',
19+
'release' => 'beta2',
2020
'author' => 'Jason Grant',
2121
'email' => '',
2222
'authorUrl' => 'https://github.com/oo12',

_build/data/transport.settings.php

+8
Original file line numberDiff line numberDiff line change
@@ -151,4 +151,12 @@ function stripPhpTags($filename) {
151151
'area' => 'Amazon S3',
152152
), '', true, true);
153153

154+
$systemSettings[$ssIdx] = $modx->newObject('modSystemSetting');
155+
$systemSettings[$ssIdx++]->fromArray(array (
156+
'key' => 'pthumb.s3_cache_path',
157+
'xtype' => 'textfield',
158+
'namespace' => 'phpthumbof',
159+
'area' => 'Amazon S3',
160+
), '', true, true);
161+
154162
return $systemSettings;

core/components/phpthumbof/docs/changelog.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
pThumb
22
======
33

4-
2.3.0-beta1 [22.12.2013]
4+
2.3.0-beta2 [11.01.2014]
55
------------------------
66

77
- [#3] Add Amazon S3 support
88
- Improve naming for remote files
9+
- [#17] Fix file paths when using phpThumb on Windows
910

1011

1112
2.2.2-pl2 [06.12.2013]

core/components/phpthumbof/lexicon/en/default.inc.php

+6-3
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,16 @@
6565
$_lang['setting_pthumb.clean_level_desc'] = 'How to clean the caches on site refresh. The cache manager plugin processes all 3 caches: phpThumbOf style, pThumb style, and remote images.<br /><strong>0</strong>: (default) Do nothing<br /><strong>1</strong>: Clean the caches separately based on the "Max Cache *" system settings (core &gt; phpThumb)<br /><strong>2</strong>: Delete all cached images';
6666

6767
$_lang['setting_pthumb.s3_output'] = 'S3 Output Media Source';
68-
$_lang['setting_pthumb.s3_output_desc'] = 'ID number of the S3 media source to use for output. May be overridden with the &amp;s3output property.';
68+
$_lang['setting_pthumb.s3_output_desc'] = 'ID number of the S3 media source to use for output. May be overridden with the <em>&amp;s3output</em> property.';
6969

7070
$_lang['setting_pthumb.s3_headers'] = 'S3 Additional Headers';
7171
$_lang['setting_pthumb.s3_headers_desc'] = 'Specify additional HTTP headers for S3 objects. One per line in the format <strong>header: value</strong>';
7272

73-
$_lang['setting_pthumb.s3_multi_img'] = 'Optimize for multiple images';
74-
$_lang['setting_pthumb.s3_multi_img_desc'] = 'Controls how pThumb checks for cached thumbnails on S3<br /><strong>Yes</strong>: Retreive a list of all objects in the bucket, then use this list for all subsequent pThumb calls on the page (1 S3 request total)<br /><strong>No</strong>: Check the existence of each thumbnail object individually (separate S3 request for each image)<br />May be overridden with the &amp;s3multiImg property. Multi is faster the more the thumbnails on a page and the fewer the objects in the S3 bucket. In some rough testing I found Multi is better when X > 1 + Y/250, where X is the number of thumbnails on a page and Y is the number of objects in the bucket.';
73+
$_lang['setting_pthumb.s3_multi_img'] = 'Optimize for Multiple Images';
74+
$_lang['setting_pthumb.s3_multi_img_desc'] = 'Controls how pThumb checks for cached thumbnails on S3.<br /><strong>Yes</strong>: Retreive a list of all objects in the bucket, then use this list for all subsequent pThumb calls on the page (1 S3 request total)<br /><strong>No</strong>: Check the existence of each thumbnail object individually (separate S3 request for each image)<br />May be overridden with the <em>&amp;s3multiImg</em> property. Multi is faster the more the thumbnails on a page and the fewer the objects in the S3 bucket. In some quick testing I found Multi is better when X > 1 + Y/250, where X is the number of thumbnails on a page and Y is the number of objects in the bucket.';
75+
76+
$_lang['setting_pthumb.s3_cache_path'] = 'S3 Cache Path Prefix';
77+
$_lang['setting_pthumb.s3_cache_path_desc'] = 'A subdirectory where all cached images will be stored in the S3 bucket(s).';
7578

7679

7780
$_lang['prop_pthumb.debug_desc'] = 'Write debug messages to the MODX error log.';

core/components/phpthumbof/model/phpthumbof.class.php

+40-39
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class phpThumbOf {
3030

3131
protected $modx;
3232
protected $config;
33-
protected $cacheimgRegex = '/.+\.(?:[0-9a-f]{8}|[0-9a-f]{32})\.(?:jpe?g|png|gif)$/';
33+
protected $cacheimgRegex;
3434

3535
private $input;
3636

@@ -62,7 +62,13 @@ function __construct(modX &$modx, &$settings_cache, $options, $s3info = 0) {
6262
parse_str($modx->getOption('pthumb.global_defaults', null, ''), $this->config['globalDefaults']);
6363
$this->config['useResizerGlobal'] = $modx->getOption('phpthumbof.use_resizer', null, FALSE);
6464
$this->config['s3outputMSglobal'] = $modx->getOption('pthumb.s3_output', null, 0, true);
65-
$this->config['s3multiImgGlobal'] = $modx->getOption('pthumb.s3_multi_img', null, false) || $s3info;
65+
if ( $this->config['s3cachePath'] = trim($modx->getOption('pthumb.s3_cache_path', null, ''), '/') ) {
66+
$this->config['s3cachePath'] .= '/'; // only added if the string isn't empty
67+
}
68+
$this->config['s3multiImgGlobal'] = $s3info ? true : $modx->getOption('pthumb.s3_multi_img', null, false);
69+
if ($s3info) { // used by the cache cleaner class
70+
$this->cacheimgRegex = '/^' . str_replace('/', '\/', $this->config['s3cachePath']) . '.+\.(?:[0-9a-f]{8}|[0-9a-f]{32})\.(?:jpe?g|png|gif)$/'; // for safety, only select images with a hash
71+
}
6672
}
6773
// these can't be cached
6874
$this->config['debug'] = empty($options['debug']) ? FALSE : TRUE;
@@ -71,13 +77,16 @@ function __construct(modX &$modx, &$settings_cache, $options, $s3info = 0) {
7177
if ( $this->config['s3outputMS'] = (int) (isset($options['s3output']) ? $options['s3output'] : $this->config['s3outputMSglobal']) ) {
7278
$this->config['s3outKey'] = "s3out{$this->config['s3outputMS']}";
7379
if (!isset($this->config[$this->config['s3outKey']])) { // if this MS isn't cached already
80+
$this->config["{$this->config['s3outKey']}_ok"] = false;
7481
$this->config[$this->config['s3outKey']] = $modx->getObject('modMediaSource', $this->config['s3outputMS']);
7582
$s3obj =& $this->config[$this->config['s3outKey']];
7683
if (strpos(get_class($s3obj), 'modS3MediaSource') === false) { // check for valid S3 media source
7784
$modx->log(modX::LOG_LEVEL_ERROR, "[pThumb] No such S3 output media source: {$this->config['s3outputMS']}");
7885
$this->config['s3outputMS'] = 0; // prevent any further S3 processing this time through
86+
$this->config[$this->config['s3outKey']] = false;
7987
}
8088
else { // initialize MS
89+
$this->config["{$this->config['s3outKey']}_ok"] = true;
8190
$s3properties = $s3obj->getPropertyList();
8291
$this->config["{$this->config['s3outKey']}_url"] = $s3properties['url'];
8392
$s3obj->bucket = $s3properties['bucket'];
@@ -86,24 +95,24 @@ function __construct(modX &$modx, &$settings_cache, $options, $s3info = 0) {
8695
define('AWS_SECRET_KEY', $s3properties['secret_key']);
8796
try { $s3obj->driver = new AmazonS3(); }
8897
catch (Exception $e) {
89-
$this->modx->log(modX::LOG_LEVEL_ERROR, "[pThumb] Error connecting to S3 media source {$this->config['s3outputMS']}: " . $e->getMessage());
98+
$modx->log(modX::LOG_LEVEL_ERROR, "[pThumb] Error connecting to S3 media source {$this->config['s3outputMS']}: " . $e->getMessage());
99+
$this->config["{$this->config['s3outKey']}_ok"] = false;
90100
$this->config['s3outputMS'] = 0;
91101
}
92102
}
93103
}
94104
}
95105
$this->config['s3multiImg'] = isset($options['s3multiImg']) ? $options['s3multiImg'] : $this->config['s3multiImgGlobal'];
96-
if ($this->config['s3outputMS'] && $this->config['s3multiImg'] && !isset($this->config[$this->config['s3outKey'] . '_images'])) {
106+
if ($this->config['s3outputMS'] && $this->config["{$this->config['s3outKey']}_ok"] && $this->config['s3multiImg'] && !isset($this->config[$this->config['s3outKey'] . '_images'])) { // get a list of all objects in the bucket
97107
$s3obj =& $this->config[$this->config['s3outKey']];
98-
$start = microtime(true); ////
99108
$opt = array();
100109
$objects = array();
101-
do {
110+
do { // list_objects only gets 1000 objects at a time, so we'll loop if necessary
102111
$list = $s3obj->driver->list_objects($s3obj->bucket, $opt);
103112
if (is_string($list->body)) {
104113
$list->body = new CFSimpleXML($list->body);
105114
}
106-
if ($s3info) {
115+
if ($s3info) { // also store last modified time and file size
107116
foreach ($list->body->Contents as $obj) {
108117
$key = (string) $obj->Key;
109118
if (preg_match($this->cacheimgRegex, $key)) {
@@ -114,17 +123,14 @@ function __construct(modX &$modx, &$settings_cache, $options, $s3info = 0) {
114123
}
115124
}
116125
}
117-
elseif ($keys = $list->body->query('descendant-or-self::Key')->map_string(null)) {
126+
elseif ( $keys = $list->body->query('descendant-or-self::Key')->map_string(null) ) { // otherwise just get object names
118127
$objects = array_merge($objects, $keys);
119128
}
120129
$body = (array) $list->body;
121-
$opt = array(
122-
'marker' => (isset($body['Contents']) && is_array($body['Contents'])) ? ((string) end($body['Contents'])->Key) : ((string) $list->body->Contents->Key)
123-
);
130+
$opt = array('marker' => (isset($body['Contents']) && is_array($body['Contents'])) ? ((string) end($body['Contents'])->Key) : ((string) $list->body->Contents->Key)); // set starting point for next request
124131
} while ((string) $list->body->IsTruncated === 'true');
125132
$this->config[$this->config['s3outKey'] . '_images'] = $objects;
126-
$this->config[$this->config['s3outKey'] . '_time'] = round(microtime(true) - $start, 3); ////
127-
// echo var_export($objects, true) . "!\n\n"; ////
133+
unset($objects);
128134
}
129135
}
130136

@@ -152,6 +158,7 @@ public function debugmsg($msg, $phpthumbDebug = FALSE) {
152158
* Returns the filename of the cached image on success or $src on failure
153159
*/
154160
public function createThumbnail($src, $options) {
161+
/* Find input file */
155162
$isRemote = preg_match('/^(?:https?:)?\/\/((?:.+?)\.(?:.+?))\/(.+)/i', $src, $matches); // check for absolute URLs
156163
if ($isRemote && MODX_HTTP_HOST === strtolower($matches[1])) { // if it's the same server we're running on
157164
$isRemote = false; // then it's not really remote
@@ -230,8 +237,7 @@ public function createThumbnail($src, $options) {
230237
}
231238
$this->input = $file;
232239

233-
234-
/* Process options. Set $ptOptions */
240+
/* Process options. Set $ptOptions */
235241
if (!is_array($options)) { // convert options string to array
236242
parse_str($options, $ptOptions);
237243
}
@@ -264,7 +270,7 @@ public function createThumbnail($src, $options) {
264270
$ptOptions = array_merge($this->config['globalDefaults'], $ptOptions);
265271

266272

267-
/* Determine cache filename. Set $cacheKey and $cacheUrl */
273+
/* Determine cache filename. Set $cacheKey and $cacheUrl */
268274
$modflags = (int) $this->config['useResizer']; // keep cached image from being stale if useResizer changes
269275
if ($this->config['checkModTime']) {
270276
$modflags .= @filemtime($this->input);
@@ -297,32 +303,24 @@ public function createThumbnail($src, $options) {
297303
$cacheKey = "{$this->config['cachePath']}$cacheFilenamePrefix$cacheFilename";
298304
$cacheUrl = "{$this->config['cachePathUrl']}$cacheFilenamePrefix" . rawurlencode($cacheFilename);
299305

300-
/* Look for cached file */
301-
$start = ''; ////
306+
/* Look for cached file */
302307
if ($this->config['s3outputMS']) { // check for file in S3 MS
303308
$s3out =& $this->config[$this->config['s3outKey']];
309+
$cacheFilenamePrefix = $this->config['s3cachePath'] . $cacheFilenamePrefix;
304310
$s3cacheUrl = $this->config["{$this->config['s3outKey']}_url"] . $cacheFilenamePrefix . rawurlencode($cacheFilename);
305311
$cacheFilename = "$cacheFilenamePrefix$cacheFilename";
306-
if (in_array($cacheFilename, $this->config[$this->config['s3outKey'] . '_images'])) {
307-
return $s3cacheUrl . '?m=' . $this->config[$this->config['s3outKey'] . '_time']; ////
308-
}
309-
$start = microtime(true); ////
310-
try {
311-
if (method_exists($s3out->driver, 'if_object_exists')) {
312-
if ($s3out->driver->if_object_exists($s3out->bucket, $cacheFilename)) {
313-
$start = '?s=' . round(microtime(true) - $start, 3); ////
314-
return $s3cacheUrl . $start; ////
315-
}
312+
if (isset($this->config[$this->config['s3outKey'] . '_images'])) { // we have a list of all objects in the bucket
313+
if (in_array($cacheFilename, $this->config[$this->config['s3outKey'] . '_images'], true)) {
314+
return $s3cacheUrl;
316315
}
317-
else { throw new Exception('Source setup failed'); }
318-
$start = '?s=' . round(microtime(true) - $start, 3); ////
319316
}
320-
catch (Exception $e) {
321-
$this->modx->log(modX::LOG_LEVEL_ERROR, "[pThumb] Error connecting to S3 media source {$this->config['s3outputMS']}: " . $e->getMessage());
322-
if (file_exists($cacheKey)) { // fall back to local cached image
323-
return $cacheUrl;
317+
elseif ($this->config["{$this->config['s3outKey']}_ok"]) { // otherwise check individual object
318+
if ($s3out->driver->if_object_exists($s3out->bucket, $cacheFilename)) {
319+
return $s3cacheUrl;
324320
}
325-
$this->config['s3outputMS'] = 0; // so output won't be written back to S3
321+
}
322+
elseif (file_exists($cacheKey)) { // if the MS didn't initialize properly, fall back to local cached image
323+
return $cacheUrl;
326324
}
327325
}
328326
elseif (file_exists($cacheKey)) { // If the file's in the cache, we're done.
@@ -336,7 +334,7 @@ public function createThumbnail($src, $options) {
336334
}
337335
}
338336

339-
/* Generate Thumbnail */
337+
/* Generate Thumbnail */
340338
if ($this->config['useResizer']) { // use Resizer
341339
static $resizer_obj = array();
342340
if (!class_exists('Resizer')) { // set up Resizer. We'll reuse this object for any subsequent images on the page
@@ -389,7 +387,8 @@ public function createThumbnail($src, $options) {
389387
$writeSuccess = $this->phpThumb->RenderToFile($cacheKey);
390388
}
391389

392-
if ($writeSuccess) { // write it to the cache file
390+
/* Write thumbnail */
391+
if ($writeSuccess) {
393392
if (!isset($this->config['newFilePermissions'])) {
394393
$this->config['newFilePermissions'] = octdec($this->modx->getOption('new_file_permissions', null, '0664'));
395394
}
@@ -412,8 +411,10 @@ public function createThumbnail($src, $options) {
412411
'headers' => $this->config['s3headers']
413412
));
414413
if ($s3response->isOK()) {
415-
$this->config[$this->config['s3outKey'] . '_images'][] = $cacheFilename;
416-
return $s3cacheUrl . $start; ////
414+
if (isset($this->config[$this->config['s3outKey'] . '_images'])) {
415+
$this->config[$this->config['s3outKey'] . '_images'][] = $cacheFilename;
416+
}
417+
return $s3cacheUrl;
417418
}
418419
else { $this->debugmsg("Error uploading $cacheFilename to S3 bucket {$s3out->bucket} (media source {$this->config['s3outputMS']})"); }
419420
}

core/components/phpthumbof/model/pthumbcachecleaner.class.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ public function cleanCache() {
148148
}
149149
else {
150150
foreach ($fileset as $file) {
151-
if ($this->rmfile($fullfilename, $isS3, $s3out)) {
151+
if (@unlink($file)) {
152152
++$deleted;
153153
}
154154
}

0 commit comments

Comments
 (0)