added missing module fixer and updated imagecache_actions

This commit is contained in:
Bachir Soussi Chiadmi
2018-03-21 17:06:08 +01:00
parent 3f7e130321
commit 0bcc558ed5
83 changed files with 6386 additions and 2517 deletions

View File

@@ -1,10 +1,10 @@
README for the Image styleds admin Drupal module
------------------------------------------------
Project page: http://drupal.org/project/imagecache_actions
Project page: https://drupal.org/project/imagecache_actions
Current and past maintainers for Image styles admin:
- fietserwin (http://drupal.org/user/750928)
- fietserwin (https://drupal.org/user/750928)
Release notes for 7.x-1.x-dev
@@ -24,12 +24,12 @@ a test/showcase sute of styles. Finally, it allows everybody to test D8 image
module features in real life.
This module is not a replacement for the features module
(http://drupal.org/project/features). If you are serious about configuration
(https://drupal.org/project/features). If you are serious about configuration
management and want to distribute styles to other systems, use features.
Use this module for 1 time export/imports between different sites, "copy &
paste" reuse within a site, and when reporting issues to the imagecache_actions
issue queue.
issue queue.
TODO

View File

@@ -0,0 +1,52 @@
table#image-styles {
table-layout: fixed;
}
#image-styles th.style-name {
width: 20%;
}
#image-styles th.effects {
width: 30%;
}
#image-styles th.settings {
width: 15%;
}
#image-styles td {
vertical-align: top;
}
#image-styles .expand.inner {
background: transparent url(/misc/menu-collapsed.png) left 0.6em no-repeat;
margin-left: -12px;
padding-left: 12px;
}
#image-styles .expanded.expand.inner {
background: transparent url(/misc/menu-expanded.png) left 0.6em no-repeat;
}
#image-styles .description {
cursor: pointer;
}
#image-styles .description .inner {
overflow: hidden; /* truncates descriptions if too long */
text-overflow: ellipsis;
white-space: nowrap;
}
#image-styles .description .expanded.inner {
overflow: visible;
white-space: normal;
}
#image-styles .description .expanded .details {
display: block;
}
#image-styles .description .expanded .separator {
display: none;
}

View File

@@ -16,7 +16,9 @@
*/
function image_styles_admin_duplicate_page_callback($style) {
$duplicate_style = image_styles_admin_duplicate($style);
drupal_set_message(t('Style %name has been duplicated to %new_name.', array('%name' => $style['name'], '%new_name' => $duplicate_style['name'])));
drupal_set_message(t('Style %name has been duplicated to %new_name.', array(
'%name' => isset($style['label']) ? $style['label'] : $style['name'],
'%new_name' => isset($duplicate_style['label']) ? $duplicate_style['label'] : $duplicate_style['name'])));
drupal_goto('admin/config/media/image-styles');
}
@@ -29,14 +31,19 @@ function image_styles_admin_duplicate_page_callback($style) {
* The preferred name for the new style. If left empty, the new name will be
* based on the name of the style to duplicate. In both cases and when
* necessary, the new name will be made unique by adding some suffix to it.
* @param string|null $new_style_label
* The preferred label for the new style. If left empty, the new label will be
* based on the label of the style to duplicate. If that one is also empty,
* no label will be defined for the new style, so Drupal (>=7.23) will create
* one.
*
* @return array
* An image style array with the newly created copy of the given style.
*
* @see image_style_name_validate()
*/
function image_styles_admin_duplicate($style, $new_style_name = NULL) {
// Find a unique name for copy.
function image_styles_admin_duplicate($style, $new_style_name = NULL, $new_style_label = NULL) {
// Find a unique name for the copy.
// Step 1: Find the base: name without things like '-copy' or '-copy-1'
$style_name_base = empty($new_style_name) ? $style['name'] : $new_style_name;
if (preg_match('/-copy(-\d+)?$/', $style_name_base)) {
@@ -58,6 +65,25 @@ function image_styles_admin_duplicate($style, $new_style_name = NULL) {
}
$style['name'] = $style_name;
// Step 4: Find a new label for the copy.
if (isset($new_style_label) || isset($style['label'])) {
$style_label = empty($new_style_label) ? $style['label'] : $new_style_label;
$copy = t('copy');
if (preg_match("/ $copy( \d+)?$/", $style_label)) {
$style_label = substr($style_label, 0, strpos($style_label, " $copy"));
}
// Step 4a: Add " copy" to it (if the name comes from the current style).
if (empty($new_style_label)) {
$style_label .= " $copy";
}
// Step 4b: Make "unique" (based on the number added to the name)
if ($i > 0) {
$style['label'] .= " $i";
}
}
// Unset isid to save it as a new style.
unset($style['isid']);
$style = image_style_save($style);
@@ -74,31 +100,35 @@ function image_styles_admin_duplicate($style, $new_style_name = NULL) {
}
/**
* drupal_get_form callback: form to export an image style.
*
* @param array $style
* An image style array.
*/
* drupal_get_form callback: form to export an image style.
*
* @param array $form
* @param array $form_state
* @param array $style
* An image style array.
*
* @return array
*/
function image_styles_admin_export_form($form, $form_state, $style) {
drupal_set_title(format_string('%page_name @style_name', array('%page_name' => t('Export image style'), '@style_name' => $style['name'])), PASS_THROUGH);
drupal_set_title(format_string('%page_name @style_name',
array('%page_name' => t('Export image style'), '@style_name' => isset($style['label']) ? $style['label'] : $style['name'])),
PASS_THROUGH);
$form['serialized_style'] = array(
'#type' => 'textarea',
'#rows' => 5,
'#title' => t('Image style export data'),
'#default_value' => serialize($style),
'#default_value' => image_styles_admin_export_serialize($style),
'#attributes' => array('readonly' =>'readonly'),
'#description' => t('Copy the contents of this field to the clipboard and, on another site, paste it in the textarea of an %page_title page.', array('%page_title' => t('Import image style'))),
'#description' => t('Copy the contents of this field to the clipboard and, on another site, paste it in the textarea of an %page_title page.',
array('%page_title' => t('Import image style'))),
);
return $form;
}
/**
* drupal_get_form callback: form to import an image style.
*
* @param array $style
* An image style array.
*/
function image_styles_admin_import_form($form, $form_state) {
function image_styles_admin_import_form($form/*, $form_state*/) {
$form['serialized_style'] = array(
'#type' => 'textarea',
'#rows' => 5,
@@ -121,7 +151,8 @@ function image_styles_admin_import_form($form, $form_state) {
* Callback to validate the import style form.
*/
function image_styles_admin_import_form_validate($form, &$form_state) {
if (image_styles_admin_import_extract_style($form_state['values']['serialized_style']) === FALSE) {
$import = image_styles_admin_unify_newlines($form_state['values']['serialized_style']);
if (image_styles_admin_import_extract_style($import) === FALSE) {
form_set_error('serialized_style', t('The %field cannot be imported as an image style.', array('%field' => t('Image style import data'))));
}
}
@@ -130,19 +161,64 @@ function image_styles_admin_import_form_validate($form, &$form_state) {
* Callback to process form submission of the import style form.
*/
function image_styles_admin_import_form_submit($form, &$form_state) {
$style = image_styles_admin_import_extract_style($form_state['values']['serialized_style']);
$import = image_styles_admin_unify_newlines($form_state['values']['serialized_style']);
$style = image_styles_admin_import_extract_style($import);
// Import the style by "duplicating" it, but prevent adding the -copy suffix
// by passing the requested name as 2nd parameter.
$new_style = image_styles_admin_duplicate($style, $style['name']);
// by passing the requested name and label as 2nd and 3rd parameter.
$new_style = image_styles_admin_duplicate($style, $style['name'], isset($style['label']) ? $style['label'] : NULL);
if ($new_style['name'] === $style['name']) {
drupal_set_message(t('Style %name has been imported.', array('%name' => $style['name'])));
}
else {
drupal_set_message(t('Style %name has been imported as %new_name.', array('%name' => $style['name'], '%new_name' => $new_style['name'])));
drupal_set_message(t('Style %name has been imported as %new_name.', array(
'%name' => isset($style['label']) ? $style['label'] : $style['name'],
'%new_name' => isset($new_style['label']) ? $new_style['label'] : $new_style['name'])));
}
drupal_goto('admin/config/media/image-styles');
}
/**
* Serializes image style data so it can be exported.
*
* @param array $style
* An image style array.
*
* @return string
* The serialized image style. Keys that are not needed for import are not
* serialized.
*/
function image_styles_admin_export_serialize($style) {
$style = array_intersect_key($style, array('name' => 0, 'label' => 0, 'effects' => 0));
foreach ($style['effects'] as &$effect) {
$effect = array_intersect_key($effect, array('weight' => 0, 'name' => 0, 'data' => 0));
}
array_walk_recursive($style, function(&$value) {
if (is_string($value)) {
$value = image_styles_admin_unify_newlines($value);
}
});
return serialize($style);
}
/**
* Unifies newlines in the string to the Unix newline standard.
*
* #2636314: textareas may convert newlines to the underlying OS style: convert
* all new lines to Unix style before unserializing. As string length is in the
* serialized data, we must ensure that we also do this on each array value
* before serializing.
*
* @param string $str
*
* @return string
*/
function image_styles_admin_unify_newlines($str) {
$str = str_replace("\r\n", "\n", $str);
$str = str_replace("\r", "\n", $str);
return $str;
}
/**
* Unserializes and validates a string into image style data.
*
@@ -154,25 +230,31 @@ function image_styles_admin_import_form_submit($form, &$form_state) {
* image style data.
*/
function image_styles_admin_import_extract_style($import) {
$style = @unserialize($import);
$style = unserialize($import);
// Check if the contents of the textarea could be unserialized into an array.
if (!is_array($style)) {
return FALSE;
}
// Check if the required keys are available, we will ignore the other.
$style = array_intersect_key($style, array('name' => 0, 'effects' => 0));
if (count($style) !== 2) {
// Filter out keys that we do not process.
$style = array_intersect_key($style, array('name' => 0, 'label' => 0, 'effects' => 0));
// 'name' is required and must be "machine name" string.
if (!isset($style['name']) || !is_string($style['name']) || preg_match('/[0-9a-z_\-]+/', $style['name']) !== 1) {
return FALSE;
}
// 'name' must be "machine name" string
if (!is_string($style['name']) || preg_match('/[0-9a-z_\-]+/', $style['name']) !== 1) {
// Optional 'label' must be a string.
if (isset($style['label']) && !is_string($style['label'])) {
return FALSE;
}
// 'effects' must be an array
if (!is_array($style['effects'])) {
// 'effects' is required and must be an array.
if (!isset($style['effects']) || !is_array($style['effects'])) {
return FALSE;
}
// Check effects elements
foreach ($style['effects'] as &$effect) {
// an effect must be an array.
@@ -197,6 +279,7 @@ function image_styles_admin_import_extract_style($import) {
return FALSE;
}
}
// @todo: are there any security implications for creating styles like this?
// - Unserialize() is save in itself: it only creates data (except possibly
// for__wakeup(), but that can only be in already existing code: safe
@@ -209,14 +292,14 @@ function image_styles_admin_import_extract_style($import) {
// contain invalid values. This is acceptable as it can also be done by
// operating directly on the database. In Drupal this is not normally
// checked for during processing: error messages will make clear that the
// data has been played with. Can incorrect dat be abused? It may contain:
// data has been played with. Can incorrect data be abused? It may contain:
// - incorrect types: we do not know the data structure of the various
// effects, so we cannot check that and have to accept it as it comes.
// Effects should check_plain in summary theme and convert to int/float
// whenever possible befoire using it in commands.
// whenever possible before using it in commands.
// - PHP code, but that may be valid content for the text or custom effects:
// Effects should check_plain in summary theme and convert to int/float
// whenever possible befoire using it in commands.
// whenever possible before using it in commands.
// @todo: if the style contains an effect that contains PHP code, the user
// should need the 'use PHP for settings' permission.
// - HTML and or JS code: when used as parameter, this normally won't hurt.

View File

@@ -1,13 +1,13 @@
name = Image styles admin
description = Provides additional administrative image style functionality.
description = Provides additional administrative functionality to duplicate, export or import image styles.
package = Media
core = 7.x
dependencies[] = image
; Information added by drupal.org packaging script on 2012-12-04
version = "7.x-1.1"
; Information added by Drupal.org packaging script on 2018-03-20
version = "7.x-1.9"
core = "7.x"
project = "imagecache_actions"
datestamp = "1354653754"
datestamp = "1521550387"

View File

@@ -0,0 +1,19 @@
(function($) {
"use strict";
Drupal.behaviors.imageStylesAdmin = {
attach: function(context) {
$('#image-styles').find('th.expand-all').once('expand-all', function() {
$(this).click(function() {
$('#image-styles').find('td.description .inner.expand').addClass('expanded');
});
});
$('#image-styles').find('td.description').once('description', function() {
$('.inner.expand', $(this)).click(function() {
$(this).toggleClass('expanded');
});
});
}
};
})(jQuery);

View File

@@ -41,36 +41,122 @@ function image_styles_admin_menu() {
* Implements hook_preprocess_HOOK for theme image_style_list.
*/
function image_styles_admin_preprocess_image_style_list(&$variables) {
// Tell imagecache_actions_preprocess_image_style_list to preprocess the next
// call to theme_table()
$flag = TRUE;
image_styles_admin_preprocess_table($flag);
// Sort the image styles by name.
uasort($variables['styles'], function ($a, $b) {
return strcasecmp($a['label'], $b['label']);
});
// Tell imagecache_actions_preprocess_table to preprocess the next call to
// theme_table().
$image_styles = array_values($variables['styles']);
image_styles_admin_preprocess_table($image_styles);
// Add CSS and JS files.
drupal_add_css(drupal_get_path('module', 'image_styles_admin') . '/image_styles_admin.css');
if (base_path() !== '/') {
$base_path = base_path();
drupal_add_css("
#image-styles .expand.inner { background-image: url($base_path/misc/menu-collapsed.png) }
#image-styles .expanded.expand.inner { background-image: url($base_path/misc/menu-expanded.png) }",
array('type' => 'inline'));
}
drupal_add_js(drupal_get_path('module', 'image_styles_admin') . '/image_styles_admin.js');
}
/**
* Implements hook_preprocess_HOOK for theme table.
*/
function image_styles_admin_preprocess_table(&$variables) {
static $is_in_image_style_list = FALSE;
static $image_styles = NULL;
if (is_bool($variables)) {
// Called from imagecache_actions_style_duplicate(): set flag
$is_in_image_style_list = $variables;
// If called from image_styles_admin_preprocess_image_style_list(), the
// parameter will be a sequential array.
if (key($variables) === 0) {
$image_styles = $variables;
}
else if ($is_in_image_style_list) {
// Normal preprocess hook call: only process if theme('table', ...) has been
// called by theme_image_style_list()
$variables['header'][2]['colspan'] = 4;
foreach ($variables['rows'] as &$row) {
array_splice($row, 2, 0, array($row[2], $row[2]));
// Replace edit with duplicate in text and href
$row[3] = str_replace('>' . t('edit') . '<', '>' . t('duplicate') . '<', $row[3]);
$row[3] = preg_replace('/\/edit\/([-a-z0-9_]+)"/', '/duplicate/\1"', $row[3]);
// Replace edit with export in text and href
$row[4] = str_replace('>' . t('edit') . '<', '>' . t('export') . '<', $row[4]);
$row[4] = preg_replace('/\/edit\/([-a-z0-9_]+)"/', '/export/\1"', $row[4]);
else if (!empty($image_styles)) {
// Normal preprocess hook call: we only process if theme('table', ...) has
// been called via theme_image_style_list() and we have a non empty list of
// styles;
// Set an ID on the table so it can be targeted by our CSS.
$variables['attributes']['id'] = 'image-styles';
// Add a class to the Style name and Settings columns for styling.
foreach ($variables['header'] as &$cell) {
$temp_cell = is_string($cell) ? array('data' => $cell) : $cell;
$class_names = array(
'style-name' => t('Style name'),
'settings' => t('Settings'),
);
foreach ($class_names as $class => $name) {
if ($temp_cell['data'] == $name) {
$temp_cell['class'][] = $class;
$cell = $temp_cell;
}
}
}
// Add the effects column header.
array_splice($variables['header'], 1, 0, array(array(
'data' => t('Effects') . ' <span class="description expand" role="button">(' . t('expand all') . ')</span>',
'class' => array('effects expand-all')
)));
// Add a column with a summary of all effects to each row.
foreach ($variables['rows'] as $i => &$row) {
$style = $image_styles[$i];
$effects_list = array();
foreach ($style['effects'] as $key => $effect) {
$definition = image_effect_definition_load($effect['name']);
$effect = array_merge($definition, $effect);
$style['effects'][$key] = $effect;
$effect_details = isset($effect['summary theme']) ? theme($effect['summary theme'], array('data' => $effect['data'])) : '';
$effects_list[] = '<span class="details">' . $effect['label'] . ' ' . $effect_details . '</span>';
}
// Add the effects summary column to the row.
$effects_summary = array(
'data' => '<div class="inner expand" role="button">' . implode('<span class="separator">, </span>', $effects_list) . '</div>',
'class' => 'description'
);
array_splice($row, 1, 0, array($effects_summary));
}
// Find the column with the edit link in it.
$i = 0;
$first_row = reset($variables['rows']);
foreach ($first_row as $i => &$cell) {
$cell_data = is_array($cell) ? $cell['data'] : $cell;
if (strpos($cell_data, '>' . t('edit') . '<') !== FALSE) {
break;
}
}
// Increase the colspan for the column with the edit link to include the
// duplicate and export links as well. This *should* be 2, but Drupal core
// specifies 1 more than should be there.
$variables['header'][$i]['colspan'] += 1;
// Add the 2 links to each row by duplicating the edit link and then
// changing the text and the link.
$edit_column = $i;
foreach ($variables['rows'] as &$row) {
$i = $edit_column;
// Duplicate the edit link twice.
array_splice($row, $i + 1, 0, array($row[$i], $row[$i]));
// Replace edit with duplicate in text and href
$i++;
$row[$i] = str_replace('>' . t('edit') . '<', '>' . t('duplicate') . '<', $row[$i]);
$row[$i] = preg_replace('#/admin/config/media/image-styles/edit/#', '/admin/config/media/image-styles/duplicate/', $row[$i]);
// Replace edit with export in text and href
$i++;
$row[$i] = str_replace('>' . t('edit') . '<', '>' . t('export') . '<', $row[$i]);
$row[$i] = preg_replace('#/admin/config/media/image-styles/edit/#', '/admin/config/media/image-styles/export/', $row[$i]);
}
// Don't preprocess subsequent calls to theme_table().
$is_in_image_style_list = FALSE;
$image_styles = NULL;
}
}