Skip to content

Commit

Permalink
Merge pull request #253 from davidyell/thumbnail-shell
Browse files Browse the repository at this point in the history
Thumbnail shell
  • Loading branch information
josegonzalez committed Feb 17, 2015
2 parents 0547d52 + 0054a29 commit 8189986
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 0 deletions.
110 changes: 110 additions & 0 deletions Console/Command/ThumbnailShell.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<?php
App::uses('AppShell', 'Console/Command');
App::uses('ConnectionManager', 'Model');
App::uses('Model', 'Model');
App::uses('UploadBehavior', 'Upload.Model/Behavior');
App::uses('ShellUploadBehavior', 'Upload.Model/Behavior');

/**
* Thumbnail Shell
* This shell can be used to generate new thumbnail images when model settings
* for the thumbnail sizes changes.
*
* @author David Yell <[email protected]>
*/
class ThumbnailShell extends AppShell {

/**
* Return the shell options
*
* @return ConsoleOptionParser
*/
public function getOptionParser() {
$parser = parent::getOptionParser();
$parser->addSubcommand('generate', ['help' => 'Find models and regenerate the thumbnails.']);
return $parser;
}

/**
* Regenerate thumbnails for images linked in the database
*
* @return void
*/
public function generate() {
$modelName = $this->in(__('Which model would you like to regenerate thumbnails for?'));

try {
$this->loadModel($modelName);
} catch (Exception $exc) {
$this->out(__('<error>' . $exc->getMessage() . '</error>'));
exit;
}

if (get_class($this->{$modelName}) === 'AppModel') {
$this->out(__("<error>Model '$modelName' not found.</error>"));
exit;
}

if (!$this->{$modelName}->Behaviors->attached('Upload')) {
$this->out(__("<error>Model '$modelName' does not use the Upload behavior.</error>"));
exit;
}

$uploadBehavior = new ShellUploadBehavior;
$behaviorConfig = $this->{$modelName}->actsAs['Upload.Upload'];

foreach ($behaviorConfig as $field => $config) {
$mergedConfig = array_merge($uploadBehavior->defaults, $config);

$options = array(
'isThumbnail' => true,
'path' => $mergedConfig['path'],
'rootDir' => $mergedConfig['rootDir'],
);

$files = $this->{$modelName}->find('all', [
'fields' => [$this->{$modelName}->primaryKey, $field, $mergedConfig['fields']['dir']],
'conditions' => [
$field . " IS NOT NULL"
]
]);

foreach ($files as $file) {
$this->{$modelName}->Behaviors->load('ShellUpload', $behaviorConfig);
$sourceFilePath = $this->{$modelName}->path($field, $options) . $file[$modelName][$mergedConfig['fields']['dir']] . DS . $file[$modelName][$field];
$this->{$modelName}->Behaviors->unload('ShellUpload');

if (!file_exists($sourceFilePath)) {
continue;
}

// $field needs to be an array like uploading an image
$fieldData = [
'name' => basename($sourceFilePath),
'type' => mime_content_type($sourceFilePath),
'size' => filesize($sourceFilePath),
'tmp_name' => $sourceFilePath,
'error' => UPLOAD_ERR_OK
];

$data = [
$this->{$modelName}->primaryKey => $file[$modelName][$this->{$modelName}->primaryKey],
$field => $fieldData,
$config['fields']['dir'] => $file[$modelName][$this->{$modelName}->primaryKey],
];

if ($this->{$modelName}->hasField('modified')) {
$data['modified'] = false;
}

$this->{$modelName}->set($data);

if ($this->{$modelName}->save(null, false)) {
$this->out(__("Created thumbnails in {$file[$modelName][$mergedConfig['fields']['dir']]} for {$file[$modelName][$field]}"));
} else {
$this->out(__("<error> Could not create thumbnails in {$file[$modelName][$mergedConfig['fields']['dir']]} for {$file[$modelName][$field]}</error>"));
}
}
}
}
}
36 changes: 36 additions & 0 deletions Model/Behavior/ShellUploadBehavior.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php
App::uses('UploadBehavior', 'Upload.Model/Behavior');

/**
* A wrapping behavior for the UploadBehavior so that it's protected methods
* can be accessed from the shell.
*
*/
class ShellUploadBehavior extends UploadBehavior {

/**
* Wrapper method for getting the path
*
* @param Model $model The instance of the model
* @param string $field The name of the upload field
* @param array $options The options array
* @return string
*/
public function path(Model $model, $field, $options = []) {
return parent::_path($model, $field, $options);
}

/**
* Wrapper method for thumbnail creation
*
* @param Model $model The model instance
* @param string $field The name of the upload field
* @param string $path The path to the source image
* @param string $thumbnailPath The path in which to create the thumbnails
* @throws Exception
* @return void
*/
public function createThumbnails(Model $model, $field, $path, $thumbnailPath) {
return parent::_createThumbnails($model, $field, $path, $thumbnailPath);
}
}
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Contents:
Generating thumbnails <thumbnails>
Validating uploads <validation>
File import behavior <file-import-behavior>
Thumbnail generation shell <thumbnail-shell>


Indices and tables
Expand Down
24 changes: 24 additions & 0 deletions docs/thumbnail-shell.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
Thumbnail shell
---------------

What it does
~~~~~~~~~~~~
The shell will look through your database for images and regenerate the thumbnails based on
your models Upload behaviour configuration. This allows you to change your thumbnail configuration and run the
shell to update your images without having to re-upload the image.

How it works
~~~~~~~~~~~~
The shell takes the model you provide and checks that the Upload plugin is present and configured. Then it will loop
though all the images checking that the configured upload field is populated in the database and also ensuring that the
file exists on the file system. Then it will regenerate the thumbnails using the current model configuration.

Running the shell
~~~~~~~~~~~~~~~~~
You can run the shell from the command line as you would any cake shell.

.. code:: bash
Console/cake upload.thumbnail generate
You will then be asked which model you want to process, and the shell will then process your images.

0 comments on commit 8189986

Please sign in to comment.