View source
<?php
include_once dirname(__FILE__) . '/imageapi_optimize.features.inc';
define('IMAGEAPI_OPTIMIZE_STORAGE_NORMAL', 1);
define('IMAGEAPI_OPTIMIZE_STORAGE_OVERRIDE', 2);
define('IMAGEAPI_OPTIMIZE_STORAGE_DEFAULT', 4);
define('IMAGEAPI_OPTIMIZE_STORAGE_EDITABLE', IMAGEAPI_OPTIMIZE_STORAGE_NORMAL | IMAGEAPI_OPTIMIZE_STORAGE_OVERRIDE);
define('IMAGEAPI_OPTIMIZE_STORAGE_MODULE', IMAGEAPI_OPTIMIZE_STORAGE_OVERRIDE | IMAGEAPI_OPTIMIZE_STORAGE_DEFAULT);
function imageapi_optimize_help($path, $arg) {
switch ($path) {
case 'admin/help#imageapi_optimize':
$output = '';
$output .= '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('The ImageAPI Optimize module allows you to optimize images on your website. It allows you to configure <em>ImageAPI Optimize pipelines</em> that can be used for optimizing images, and provides an <em>Image effect</em> that can be used in image styles.') . '</p>';
$output .= '<h3>' . t('Uses') . '</h3>';
$output .= '<dl>';
$output .= '<dt>' . t('Optimizing images') . '</dt>';
$output .= '<dd>' . t('With the ImageAPI Optimize module you can use either local executables or remote services for optimizting images. These services are executed in a <a href="@imageapi_optimize">pipeline</a>. Once you have a defined pipeline configured then you can add an effect to an <a href="@image">image style</a> so that all images generated with that style use the pipeline at the end for optimization.', array(
'@imageapi_optimize' => url('admin/config/media/imageapi-optimize'),
'@image' => url('admin/config/media/image-styles'),
)) . '<dd>';
$output .= '</dl>';
return $output;
case 'admin/config/media/imageapi-optimize':
return '<p>' . t('ImageAPI Optimize pipelines can use local executable programs or remote services for optimizing images. Once you have configured a pipeline you may want to add the ImageAPI Optimize effect to an <a href="">image style</a> to use that pipeline.', array(
'@imageapi_optimize' => url('admin/config/media/imageapi-optimize'),
'@image' => url('admin/config/media/image-styles'),
)) . '</p>';
case 'admin/config/media/imageapi-optimize/edit/%/add/%':
$processor = imageapi_optimize_processor_definition_load($arg[7]);
if (isset($processor['help']) || !empty($processor['url'])) {
if (!empty($processor['url'])) {
$text = l(isset($processor['help']) ? $processor['help'] : $processor['url'], $processor['url'], array(
'external' => TRUE,
'attributes' => array(
'target' => '_blank',
),
));
}
else {
$text = isset($processor['help']) ? $processor['help'] : $processor['url'];
}
return '<p>' . $text . '</p>';
}
else {
return NULL;
}
case 'admin/config/media/imageapi-optimize/edit/%/processors/%':
$processor = $arg[5] == 'add' ? imageapi_optimize_processor_definition_load($arg[6]) : imageapi_optimize_processor_load($arg[7], $arg[5]);
if (isset($processor['help']) || !empty($processor['url'])) {
if (!empty($processor['url'])) {
$text = l(isset($processor['help']) ? $processor['help'] : $processor['url'], $processor['url'], array(
'external' => TRUE,
'attributes' => array(
'target' => '_blank',
),
));
}
else {
$text = isset($processor['help']) ? $processor['help'] : $processor['url'];
}
return '<p>' . $text . '</p>';
}
else {
return NULL;
}
}
}
function imageapi_optimize_menu() {
$items['admin/config/media/imageapi-optimize'] = array(
'title' => 'Imageapi optimize',
'description' => 'Configure pipelines that can be used for optimizing images on display.',
'page callback' => 'imageapi_optimize_pipeline_list',
'access arguments' => array(
'administer imageapi optimize',
),
'file' => 'imageapi_optimize.admin.inc',
);
$items['admin/config/media/imageapi-optimize/list'] = array(
'title' => 'List',
'description' => 'List the current imageapi optimize pipelines on the site.',
'page callback' => 'imageapi_optimize_pipeline_list',
'access arguments' => array(
'administer imageapi optimize',
),
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => 0,
'file' => 'imageapi_optimize.admin.inc',
);
$items['admin/config/media/imageapi-optimize/usage'] = array(
'title' => 'Usages',
'description' => 'List the current imageapi optimize pipelines usages on the site.',
'page callback' => 'imageapi_optimize_pipeline_usage_list',
'access arguments' => array(
'administer imageapi optimize',
),
'type' => MENU_LOCAL_TASK,
'weight' => 1,
'file' => 'imageapi_optimize.admin.inc',
);
$items['admin/config/media/imageapi-optimize/add'] = array(
'title' => 'Add pipeline',
'description' => 'Add a new imageapi optmize pipeline.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'imageapi_optimize_pipeline_add_form',
),
'access arguments' => array(
'administer imageapi optimize',
),
'type' => MENU_LOCAL_ACTION,
'weight' => 2,
'file' => 'imageapi_optimize.admin.inc',
);
$items['admin/config/media/imageapi-optimize/edit/%imageapi_optimize_pipeline'] = array(
'title' => 'Edit pipeline',
'description' => 'Configure an imageapi optimize pipeline.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'imageapi_optimize_pipeline_form',
5,
),
'access arguments' => array(
'administer imageapi optimize',
),
'file' => 'imageapi_optimize.admin.inc',
);
$items['admin/config/media/imageapi-optimize/delete/%imageapi_optimize_pipeline'] = array(
'title' => 'Delete pipeline',
'description' => 'Delete an imageapi optimize pipeline.',
'load arguments' => array(
NULL,
(string) IMAGEAPI_OPTIMIZE_STORAGE_NORMAL,
),
'page callback' => 'drupal_get_form',
'page arguments' => array(
'imageapi_optimize_pipeline_delete_form',
5,
),
'access arguments' => array(
'administer imageapi optimize',
),
'file' => 'imageapi_optimize.admin.inc',
);
$items['admin/config/media/imageapi-optimize/revert/%imageapi_optimize_pipeline'] = array(
'title' => 'Revert pipeline',
'description' => 'Revert an imageapi optimize pipeline.',
'load arguments' => array(
NULL,
(string) IMAGEAPI_OPTIMIZE_STORAGE_OVERRIDE,
),
'page callback' => 'drupal_get_form',
'page arguments' => array(
'imageapi_optimize_pipeline_revert_form',
5,
),
'access arguments' => array(
'administer imageapi optimize',
),
'file' => 'imageapi_optimize.admin.inc',
);
$items['admin/config/media/imageapi-optimize/edit/%imageapi_optimize_pipeline/processors/%imageapi_optimize_processor'] = array(
'title' => 'Edit imageapi optimize processor',
'description' => 'Edit an existing processor within a pipeline.',
'load arguments' => array(
5,
(string) IMAGEAPI_OPTIMIZE_STORAGE_EDITABLE,
),
'page callback' => 'drupal_get_form',
'page arguments' => array(
'imageapi_optimize_processor_form',
5,
7,
),
'access arguments' => array(
'administer imageapi optimize',
),
'file' => 'imageapi_optimize.admin.inc',
);
$items['admin/config/media/imageapi-optimize/edit/%imageapi_optimize_pipeline/processors/%imageapi_optimize_processor/delete'] = array(
'title' => 'Delete imageapi optimize processor',
'description' => 'Delete an existing processor from a pipeline.',
'load arguments' => array(
5,
(string) IMAGEAPI_OPTIMIZE_STORAGE_EDITABLE,
),
'page callback' => 'drupal_get_form',
'page arguments' => array(
'imageapi_optimize_processor_delete_form',
5,
7,
),
'access arguments' => array(
'administer imageapi optimize',
),
'file' => 'imageapi_optimize.admin.inc',
);
$items['admin/config/media/imageapi-optimize/edit/%imageapi_optimize_pipeline/add/%imageapi_optimize_processor_definition'] = array(
'title' => 'Add imageapi optimize procesor',
'description' => 'Add a new processor to a pipeline.',
'load arguments' => array(
5,
),
'page callback' => 'drupal_get_form',
'page arguments' => array(
'imageapi_optimize_processor_form',
5,
7,
),
'access arguments' => array(
'administer imageapi optimize',
),
'file' => 'imageapi_optimize.admin.inc',
);
return $items;
}
function imageapi_optimize_theme() {
return array(
'imageapi_optimize_pipeline_list' => array(
'variables' => array(
'pipelines' => NULL,
),
),
'imageapi_optimize_pipeline_usage' => array(
'variables' => array(
'usages' => NULL,
'description' => '',
),
),
'imageapi_optimize_pipeline_processors' => array(
'render element' => 'form',
),
);
}
function imageapi_optimize_permission() {
return array(
'administer imageapi optimize' => array(
'title' => t('Administer imageapi optimize'),
'description' => t('Create and modify pipelines for generating image optimizations.'),
),
);
}
function imageapi_optimize_pipelines() {
$pipelines =& drupal_static(__FUNCTION__);
if (!isset($pipelines)) {
if ($cache = cache_get('imageapi_optimize_pipelines', 'cache')) {
$pipelines = $cache->data;
}
else {
$pipelines = array();
foreach (module_implements('imageapi_optimize_default_pipelines') as $module) {
$module_pipelines = module_invoke($module, 'imageapi_optimize_default_pipelines');
foreach ($module_pipelines as $pipeline_name => $pipeline) {
$pipeline['name'] = $pipeline_name;
$pipeline['label'] = empty($pipeline['label']) ? $pipeline_name : $pipeline['label'];
$pipeline['module'] = $module;
$pipeline['storage'] = IMAGEAPI_OPTIMIZE_STORAGE_DEFAULT;
foreach ($pipeline['processors'] as $key => $processor) {
$definition = imageapi_optimize_processor_definition_load($processor['name']);
$processor = array_merge($definition, $processor);
$pipeline['processors'][$key] = $processor;
}
$pipelines[$pipeline_name] = $pipeline;
}
}
$user_pipelines = db_select('imageapi_optimize_pipelines', NULL, array(
'fetch' => PDO::FETCH_ASSOC,
))
->fields('imageapi_optimize_pipelines')
->orderBy('name')
->execute()
->fetchAllAssoc('name', PDO::FETCH_ASSOC);
foreach ($user_pipelines as $pipeline_name => $pipeline) {
$pipeline['module'] = NULL;
$pipeline['storage'] = IMAGEAPI_OPTIMIZE_STORAGE_NORMAL;
$pipeline['processors'] = imageapi_optimize_pipeline_processors($pipeline);
if (isset($pipelines[$pipeline_name]['module'])) {
$pipeline['module'] = $pipelines[$pipeline_name]['module'];
$pipeline['storage'] = IMAGEAPI_OPTIMIZE_STORAGE_OVERRIDE;
}
$pipelines[$pipeline_name] = $pipeline;
}
drupal_alter('imageapi_optimize_pipelines', $pipelines);
cache_set('imageapi_optimize_pipelines', $pipelines);
}
}
return $pipelines;
}
function imageapi_optimize_pipeline_load($name = NULL, $isid = NULL, $include = NULL) {
$pipelines = imageapi_optimize_pipelines();
if (isset($name) && isset($pipelines[$name])) {
$pipeline = $pipelines[$name];
}
if (!isset($name) && isset($isid)) {
foreach ($pipelines as $name => $database_pipeline) {
if (isset($database_pipeline['isid']) && $database_pipeline['isid'] == $isid) {
$pipeline = $database_pipeline;
break;
}
}
}
if (isset($pipeline) && (!isset($include) || $pipeline['storage'] & (int) $include)) {
return $pipeline;
}
return FALSE;
}
function imageapi_optimize_pipeline_save($pipeline) {
if (isset($pipeline['isid']) && is_numeric($pipeline['isid'])) {
$old_pipeline = imageapi_optimize_pipeline_load(NULL, $pipeline['isid']);
imageapi_optimize_pipeline_flush($old_pipeline);
drupal_write_record('imageapi_optimize_pipelines', $pipeline, 'isid');
if ($old_pipeline['name'] != $pipeline['name']) {
$pipeline['old_name'] = $old_pipeline['name'];
}
}
else {
if (empty($pipeline['label'])) {
$pipeline['label'] = $pipeline['name'];
}
drupal_write_record('imageapi_optimize_pipelines', $pipeline);
$pipeline['is_new'] = TRUE;
}
module_invoke_all('imageapi_optimize_pipeline_save', $pipeline);
imageapi_optimize_pipeline_flush($pipeline);
return $pipeline;
}
function imageapi_optimize_pipeline_delete($pipeline, $replacement_pipeline_name = '') {
imageapi_optimize_pipeline_flush($pipeline);
db_delete('imageapi_optimize_processors')
->condition('isid', $pipeline['isid'])
->execute();
db_delete('imageapi_optimize_pipelines')
->condition('isid', $pipeline['isid'])
->execute();
$pipeline['old_name'] = $pipeline['name'];
$pipeline['name'] = $replacement_pipeline_name;
module_invoke_all('imageapi_optimize_pipeline_delete', $pipeline);
return TRUE;
}
function imageapi_optimize_pipeline_processors($pipeline) {
$processors = imageapi_optimize_processors();
$pipeline_processors = array();
foreach ($processors as $processor) {
if ($pipeline['isid'] == $processor['isid']) {
$pipeline_processors[$processor['ieid']] = $processor;
}
}
return $pipeline_processors;
}
function imageapi_optimize_pipeline_options($include_empty = TRUE, $output = CHECK_PLAIN) {
$pipelines = imageapi_optimize_pipelines();
$options = array();
if ($include_empty && !empty($pipelines)) {
$options[''] = t('<none>');
}
foreach ($pipelines as $name => $pipeline) {
$options[$name] = $output == PASS_THROUGH ? $pipeline['label'] : check_plain($pipeline['label']);
}
if (empty($options)) {
$options[''] = t('No defined pipelines');
}
return $options;
}
function imageapi_optimize_pipeline_flush($pipeline) {
module_invoke_all('imageapi_optimize_pipeline_flush', $pipeline);
cache_clear_all('imageapi_optimize_pipelines', 'cache');
cache_clear_all('imageapi_optimize_processors:', 'cache', TRUE);
drupal_static_reset('imageapi_optimize_pipelines');
drupal_static_reset('imageapi_optimize_processors');
$styles = image_styles();
foreach ($styles as $style) {
foreach ($style['effects'] as $effect) {
if ($effect['name'] == 'imageapi_optimize' && isset($effect['data']['pipeline']) && $effect['data']['pipeline'] == $pipeline['name']) {
image_style_flush($style);
}
}
}
}
function imageapi_optimize_default_pipeline_save($pipeline) {
$pipeline = imageapi_optimize_pipeline_save($pipeline);
$processors = array();
foreach ($pipeline['processors'] as $processor) {
$processor['isid'] = $pipeline['isid'];
$processor = imageapi_optimize_processor_save($processor);
$processors[$processor['ieid']] = $processor;
}
$pipeline['processors'] = $processors;
return $pipeline;
}
function imageapi_optimize_default_pipeline_revert($pipeline) {
imageapi_optimize_pipeline_flush($pipeline);
db_delete('imageapi_optimize_processors')
->condition('isid', $pipeline['isid'])
->execute();
db_delete('imageapi_optimize_pipelines')
->condition('isid', $pipeline['isid'])
->execute();
return TRUE;
}
function imageapi_optimize_processor_definitions() {
global $language;
$langcode = $language->language;
$processors =& drupal_static(__FUNCTION__);
if (!isset($processors)) {
if ($cache = cache_get("imageapi_optimize_processors:{$langcode}")) {
$processors = $cache->data;
}
else {
$processors = array();
foreach (module_implements('imageapi_optimize_processor_info') as $module) {
foreach (module_invoke($module, 'imageapi_optimize_processor_info') as $name => $processor) {
$processor['module'] = $module;
$processor['name'] = $name;
$processor['data'] = isset($processor['data']) ? $processor['data'] : array();
$processors[$name] = $processor;
}
}
uasort($processors, '_imageapi_optimize_processor_definitions_sort');
drupal_alter('imageapi_optimize_processor_info', $processors);
cache_set("imageapi_optimize_processors:{$langcode}", $processors);
}
}
return $processors;
}
function imageapi_optimize_processor_definition_load($processor, $pipeline_name = NULL) {
$definitions = imageapi_optimize_processor_definitions();
if (isset($pipeline_name)) {
$pipeline = imageapi_optimize_pipeline_load($pipeline_name, NULL);
if ($pipeline['storage'] == IMAGEAPI_OPTIMIZE_STORAGE_DEFAULT) {
return FALSE;
}
}
return isset($definitions[$processor]) ? $definitions[$processor] : FALSE;
}
function imageapi_optimize_processors() {
$processors =& drupal_static(__FUNCTION__);
if (!isset($processors)) {
$processors = array();
$result = db_select('imageapi_optimize_processors', NULL, array(
'fetch' => PDO::FETCH_ASSOC,
))
->fields('imageapi_optimize_processors')
->orderBy('imageapi_optimize_processors.weight', 'ASC')
->execute();
foreach ($result as $processor) {
$processor['data'] = unserialize($processor['data']);
$definition = imageapi_optimize_processor_definition_load($processor['name']);
if ($definition) {
$processor = array_merge($definition, $processor);
$processors[$processor['ieid']] = $processor;
}
}
}
return $processors;
}
function imageapi_optimize_processor_load($ieid, $pipeline_name, $include = NULL) {
if (($pipeline = imageapi_optimize_pipeline_load($pipeline_name, NULL, $include)) && isset($pipeline['processors'][$ieid])) {
return $pipeline['processors'][$ieid];
}
return FALSE;
}
function imageapi_optimize_processor_save($processor) {
if (!empty($processor['ieid'])) {
drupal_write_record('imageapi_optimize_processors', $processor, 'ieid');
}
else {
drupal_write_record('imageapi_optimize_processors', $processor);
}
$pipeline = imageapi_optimize_pipeline_load(NULL, $processor['isid']);
imageapi_optimize_pipeline_flush($pipeline);
return $processor;
}
function imageapi_optimize_processor_delete($processor) {
db_delete('imageapi_optimize_processors')
->condition('ieid', $processor['ieid'])
->execute();
$pipeline = imageapi_optimize_pipeline_load(NULL, $processor['isid']);
imageapi_optimize_pipeline_flush($pipeline);
}
function _imageapi_optimize_processor_definitions_sort($a, $b) {
return strcasecmp($a['name'], $b['name']);
}
function imageapi_optimize_hook_info() {
$hooks = array();
$group = 'imageapi_optimize';
$hooks['imageapi_optimize_processor_info'] = array(
'group' => $group,
);
$hooks['imageapi_optimize_default_pipelines'] = array(
'group' => $group,
);
$hooks['imageapi_optimize_default_pipelines_alter'] = array(
'group' => $group,
);
$hooks['imageapi_optimize_pipelines_alter'] = array(
'group' => $group,
);
return $hooks;
}
function image_imageapi_optimize_save(stdClass $image, $destination) {
if (isset($image->imageapi_optimize_original_toolkit) && isset($image->imageapi_optimize_pipeline) && $image->toolkit != $image->imageapi_optimize_original_toolkit) {
$original_toolkit = $image->imageapi_optimize_original_toolkit;
$pipeline = $image->imageapi_optimize_pipeline;
unset($image->imageapi_optimize_original_toolkit);
unset($image->imageapi_optimize_pipeline);
$image->toolkit = $original_toolkit;
if (image_toolkit_invoke('save', $image, array(
$destination,
))) {
imageapi_optimize_optimize_file($pipeline, $destination, $image);
return TRUE;
}
}
return FALSE;
}
function imageapi_optimize_optimize_file($pipeline, $drupal_filepath, $image = NULL) {
$return = TRUE;
if ($pipeline = imageapi_optimize_pipeline_load($pipeline)) {
if (is_null($image)) {
$image = image_load($drupal_filepath);
}
foreach ($pipeline['processors'] as $processor) {
$processor_handler = imageapi_optimize_processor_handler($processor);
$return = $return && $processor_handler
->process($image, $drupal_filepath);
}
}
return $return;
}
function imageapi_optimize_image_effect_info() {
$effects = array();
$effects['imageapi_optimize'] = array(
'label' => t('ImageAPI Optimize'),
'help' => t('This will optmize the image using the selected options, this should be the last effect in the preset'),
'effect callback' => 'imageapi_optimize_optimize_effect',
'form callback' => 'imageapi_optimize_optimize_effect_form',
'dimensions passthrough' => TRUE,
);
return $effects;
}
function imageapi_optimize_optimize_effect(stdClass $image, $options) {
if (!empty($options['pipeline']) && imageapi_optimize_pipeline_load($options['pipeline'])) {
$image->imageapi_optimize_original_toolkit = $image->toolkit;
$image->toolkit = 'imageapi_optimize';
$image->imageapi_optimize_pipeline = $options['pipeline'];
}
}
function imageapi_optimize_optimize_effect_form($data) {
$form = array();
$form['pipeline'] = array(
'#type' => 'radios',
'#title' => t('Pipeline'),
'#required' => TRUE,
'#options' => imageapi_optimize_pipeline_options(FALSE, PASS_THROUGH),
'#default_value' => isset($data['pipeline']) ? $data['pipeline'] : '',
);
return $form;
}
function imageapi_optimize_form_image_style_form_alter(&$form, &$form_state, $form_id) {
$form['#validate'][] = 'imageapi_optimize_form_image_style_validate';
$form['effects']['new']['add']['#validate'][] = 'imageapi_optimize_form_image_style_validate';
$style = $form_state['image_style'];
foreach ($style['effects'] as $effect) {
if ($effect['name'] == 'imageapi_optimize') {
unset($form['effects']['new']['new']['#options']['imageapi_optimize']);
}
}
}
function imageapi_optimize_form_image_style_validate($form, &$form_state) {
$style = $form_state['image_style'];
$weights = array();
$imageapi_optimize_effects_id = NULL;
if (!empty($form_state['values']['effects'])) {
foreach ($form_state['values']['effects'] as $ieid => $effect_data) {
if (isset($style['effects'][$ieid])) {
$effect = $style['effects'][$ieid];
if ($effect['name'] == 'imageapi_optimize') {
$imageapi_optimize_effects_id = $ieid;
}
else {
$weights[] = $effect_data['weight'];
}
}
}
}
if ($form_state['triggering_element']['#value'] == $form['effects']['new']['add']['#value']) {
$weights[] = $form_state['values']['weight'];
}
if (isset($imageapi_optimize_effects_id) && !empty($weights)) {
form_set_value($form['effects'][$imageapi_optimize_effects_id]['weight'], max($weights) + 1, $form_state);
}
}
function imageapi_optimize_processor_handler(array $processor) {
$handler_class = $processor['handler'];
$handler = new $handler_class($processor['data']);
return $handler;
}
function imageapi_optimize_processor_integer_validate($element, &$form_state) {
$value = empty($element['#allow_negative']) ? $element['#value'] : preg_replace('/^-/', '', $element['#value']);
if ($element['#value'] != '' && (!is_numeric($value) || intval($value) <= 0)) {
if (empty($element['#allow_negative'])) {
form_error($element, t('!name must be an integer.', array(
'!name' => $element['#title'],
)));
}
else {
form_error($element, t('!name must be a positive integer.', array(
'!name' => $element['#title'],
)));
}
}
}
function imageapi_optimize_pipeline_usage() {
$usages = array();
$pipelines = imageapi_optimize_pipelines();
foreach (image_styles() as $style_name => $style) {
$usage = array();
$usage['name'] = $style_name;
$usage['label'] = empty($style['label']) ? $style_name : $style['label'];
if (isset($style['effects'])) {
foreach ($style['effects'] as $effect) {
if ($effect['module'] == 'imageapi_optimize' && $effect['name'] == 'imageapi_optimize' && isset($effect['data']['pipeline'])) {
if (isset($pipelines[$effect['data']['pipeline']])) {
$usage['pipeline_name'] = $effect['data']['pipeline'];
$usage['pipeline_label'] = $pipelines[$effect['data']['pipeline']]['label'];
}
}
}
}
$usages[] = $usage;
}
return $usages;
}