ran security updates on contrib modules
ctools, video_embed_field, migrate, views_bulk_operations
This commit is contained in:
parent
5d30d9bcee
commit
f7cd9c0858
@ -6,9 +6,9 @@ package = Chaos tool suite
|
||||
version = CTOOLS_MODULE_VERSION
|
||||
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-03-18
|
||||
version = "7.x-1.7"
|
||||
; Information added by Drupal.org packaging script on 2015-08-19
|
||||
version = "7.x-1.9"
|
||||
core = "7.x"
|
||||
project = "ctools"
|
||||
datestamp = "1426696183"
|
||||
datestamp = "1440020680"
|
||||
|
||||
|
@ -9,9 +9,9 @@ files[] = includes/math-expr.inc
|
||||
files[] = includes/stylizer.inc
|
||||
files[] = tests/css_cache.test
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-03-18
|
||||
version = "7.x-1.7"
|
||||
; Information added by Drupal.org packaging script on 2015-08-19
|
||||
version = "7.x-1.9"
|
||||
core = "7.x"
|
||||
project = "ctools"
|
||||
datestamp = "1426696183"
|
||||
datestamp = "1440020680"
|
||||
|
||||
|
@ -23,7 +23,7 @@ define('CTOOLS_API_VERSION', '2.0.8');
|
||||
* ; Requires CTools v7.x-1.4 or newer.
|
||||
* dependencies[] = ctools (>=1.4)
|
||||
*/
|
||||
define('CTOOLS_MODULE_VERSION', '7.x-1.7');
|
||||
define('CTOOLS_MODULE_VERSION', '7.x-1.9');
|
||||
|
||||
/**
|
||||
* Test the CTools API version.
|
||||
@ -617,6 +617,27 @@ function ctools_registry_files_alter(&$files, $indexed_modules) {
|
||||
return _ctools_registry_files_alter($files, $indexed_modules);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// FAPI hooks that must be in the .module file.
|
||||
|
||||
/**
|
||||
* Alter the comment form to get a little more control over it.
|
||||
*/
|
||||
function ctools_form_comment_form_alter(&$form, &$form_state) {
|
||||
if (!empty($form_state['ctools comment alter'])) {
|
||||
// Force the form to post back to wherever we are.
|
||||
$form['#action'] = url($_GET['q'], array('fragment' => 'comment-form'));
|
||||
if (empty($form['#submit'])) {
|
||||
$form['#submit'] = array('comment_form_submit');
|
||||
}
|
||||
$form['#submit'][] = 'ctools_node_comment_form_submit';
|
||||
}
|
||||
}
|
||||
|
||||
function ctools_node_comment_form_submit(&$form, &$form_state) {
|
||||
$form_state['redirect'][0] = $_GET['q'];
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// CTools hook implementations.
|
||||
|
||||
@ -1018,3 +1039,50 @@ function ctools_ctools_entity_context_alter(&$plugin, &$entity, $plugin_id) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_field_create_field().
|
||||
*/
|
||||
function ctools_field_create_field($field) {
|
||||
ctools_flush_field_caches();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_field_create_instance().
|
||||
*/
|
||||
function ctools_field_create_instance($instance) {
|
||||
ctools_flush_field_caches();
|
||||
}
|
||||
/**
|
||||
* Implements hook_field_delete_field().
|
||||
*/
|
||||
function ctools_field_delete_field($field) {
|
||||
ctools_flush_field_caches();
|
||||
}
|
||||
/**
|
||||
* Implements hook_field_delete_instance().
|
||||
*/
|
||||
function ctools_field_delete_instance($instance) {
|
||||
ctools_flush_field_caches();
|
||||
}
|
||||
/**
|
||||
* Implements hook_field_update_field().
|
||||
*/
|
||||
function ctools_field_update_field($field, $prior_field, $has_data) {
|
||||
ctools_flush_field_caches();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_field_update_instance().
|
||||
*/
|
||||
function ctools_field_update_instance($instance, $prior_instance) {
|
||||
ctools_flush_field_caches();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear field related caches.
|
||||
*/
|
||||
function ctools_flush_field_caches() {
|
||||
// Clear caches of 'Entity field' content type plugin.
|
||||
cache_clear_all('ctools_entity_field_content_type_content_types', 'cache');
|
||||
}
|
||||
|
@ -5,9 +5,9 @@ package = Chaos tool suite
|
||||
version = CTOOLS_MODULE_VERSION
|
||||
dependencies[] = ctools
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-03-18
|
||||
version = "7.x-1.7"
|
||||
; Information added by Drupal.org packaging script on 2015-08-19
|
||||
version = "7.x-1.9"
|
||||
core = "7.x"
|
||||
project = "ctools"
|
||||
datestamp = "1426696183"
|
||||
datestamp = "1440020680"
|
||||
|
||||
|
@ -5,9 +5,9 @@ version = CTOOLS_MODULE_VERSION
|
||||
dependencies[] = ctools
|
||||
core = 7.x
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-03-18
|
||||
version = "7.x-1.7"
|
||||
; Information added by Drupal.org packaging script on 2015-08-19
|
||||
version = "7.x-1.9"
|
||||
core = "7.x"
|
||||
project = "ctools"
|
||||
datestamp = "1426696183"
|
||||
datestamp = "1440020680"
|
||||
|
||||
|
@ -524,7 +524,7 @@ function ctools_ajax_sample_wizard_next(&$form_state) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the 'finish' click on teh add/edit pane form wizard.
|
||||
* Handle the 'finish' click on the add/edit pane form wizard.
|
||||
*
|
||||
* All we need to do is set a flag so the return can handle adding
|
||||
* the pane.
|
||||
|
@ -5,9 +5,9 @@ package = Chaos tool suite
|
||||
version = CTOOLS_MODULE_VERSION
|
||||
dependencies[] = ctools
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-03-18
|
||||
version = "7.x-1.7"
|
||||
; Information added by Drupal.org packaging script on 2015-08-19
|
||||
version = "7.x-1.9"
|
||||
core = "7.x"
|
||||
project = "ctools"
|
||||
datestamp = "1426696183"
|
||||
datestamp = "1440020680"
|
||||
|
||||
|
@ -8,9 +8,9 @@ dependencies[] = page_manager
|
||||
dependencies[] = advanced_help
|
||||
core = 7.x
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-03-18
|
||||
version = "7.x-1.7"
|
||||
; Information added by Drupal.org packaging script on 2015-08-19
|
||||
version = "7.x-1.9"
|
||||
core = "7.x"
|
||||
project = "ctools"
|
||||
datestamp = "1426696183"
|
||||
datestamp = "1440020680"
|
||||
|
||||
|
@ -341,7 +341,16 @@ function ctools_content_editable($type, $subtype, $conf) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ($function = ctools_plugin_get_function($subtype, 'check editable')) {
|
||||
$function = FALSE;
|
||||
|
||||
if (!empty($subtype['check editable'])) {
|
||||
$function = ctools_plugin_get_function($subtype, 'check editable');
|
||||
}
|
||||
elseif (!empty($type['check editable'])) {
|
||||
$function = ctools_plugin_get_function($type, 'check editable');
|
||||
}
|
||||
|
||||
if ($function) {
|
||||
return $function($type, $subtype, $conf);
|
||||
}
|
||||
|
||||
|
@ -736,6 +736,15 @@ function ctools_edit_context_form_defaults($form, &$form_state) {
|
||||
'#default_value' => $conf['keyword'],
|
||||
);
|
||||
|
||||
if ($type_info['key'] == 'requiredcontexts') {
|
||||
$form['optional'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Context is optional'),
|
||||
'#default_value' => !empty($form_state['conf']['optional']),
|
||||
'#description' => t('This context need not be present for the component to function.'),
|
||||
);
|
||||
}
|
||||
|
||||
$form['#submit'][] = 'ctools_edit_context_form_defaults_submit';
|
||||
|
||||
return $form;
|
||||
@ -752,6 +761,9 @@ function ctools_edit_context_form_defaults_submit(&$form, &$form_state) {
|
||||
$form_state['conf']['default'] = $form_state['values']['default'];
|
||||
$form_state['conf']['title'] = $form_state['values']['title'];
|
||||
}
|
||||
if ($form_state['type info']['key'] == 'requiredcontexts') {
|
||||
$form_state['conf']['optional'] = $form_state['values']['optional'];
|
||||
}
|
||||
|
||||
$form_state['conf']['identifier'] = $form_state['values']['identifier'];
|
||||
$form_state['conf']['keyword'] = $form_state['values']['keyword'];
|
||||
|
@ -216,7 +216,7 @@ class ctools_context_optional extends ctools_context_required {
|
||||
$context = new ctools_context('any');
|
||||
$context->title = t('No context');
|
||||
$context->identifier = t('No context');
|
||||
$contexts = array_merge(array('empty' => $context), $contexts);
|
||||
$contexts['empty'] = $context;
|
||||
}
|
||||
|
||||
function filter($contexts) {
|
||||
@ -1505,7 +1505,7 @@ function ctools_access($settings, $contexts = array()) {
|
||||
return TRUE;
|
||||
}
|
||||
else if (!$pass && $settings['logic'] == 'and') {
|
||||
// Fail if 'and' and htis rule failed.
|
||||
// Fail if 'and' and this rule failed.
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
@ -172,10 +172,12 @@ function ctools_css_cache($css, $filter = TRUE) {
|
||||
// @todo Is this slow? Does it matter if it is?
|
||||
$filename = $path . '/' . md5($css) . '.css';
|
||||
|
||||
// This will do renames if the file already exists, ensuring we don't
|
||||
// accidentally overwrite other files who share the same md5. Yes this
|
||||
// is a very miniscule chance but it's safe.
|
||||
$filename = file_unmanaged_save_data($css, $filename);
|
||||
// Generally md5 is considered unique enough to sign file downloads.
|
||||
// So this replaces already existing files based on the assumption that two
|
||||
// files with the same hash are identical content wise.
|
||||
// If we rename, the cache folder can potentially fill up with thousands of
|
||||
// files with the same content.
|
||||
$filename = file_unmanaged_save_data($css, $filename, FILE_EXISTS_REPLACE);
|
||||
|
||||
return $filename;
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ function ctools_jump_menu($form, &$form_state, $select, $options = array()) {
|
||||
'hide' => TRUE,
|
||||
);
|
||||
|
||||
ctools_add_js('jump-menu');
|
||||
$form['#attached']['js'][] = ctools_attach_js('jump-menu');
|
||||
|
||||
if (!empty($options['choose'])) {
|
||||
$select = array('' => $options['choose']) + $select;
|
||||
|
@ -271,7 +271,7 @@ class ctools_math_expr {
|
||||
} elseif (in_array($op, $ops) and !$expecting_op) {
|
||||
return $this->trigger("unexpected operator '$op'");
|
||||
} else { // I don't even want to know what you did to get here
|
||||
return $this->trigger("an unexpected error occured");
|
||||
return $this->trigger("an unexpected error occurred");
|
||||
}
|
||||
if ($index == strlen($expr)) {
|
||||
if (in_array($op, $ops)) { // did we end with an operator? bad.
|
||||
|
@ -66,6 +66,7 @@ function ctools_modal_add_js() {
|
||||
drupal_add_library('system', 'jquery.form');
|
||||
drupal_add_library('system', 'drupal.progress');
|
||||
drupal_add_library('system', 'drupal.ajax');
|
||||
drupal_add_library('system', 'ui');
|
||||
ctools_add_js('modal');
|
||||
|
||||
ctools_add_css('modal');
|
||||
|
@ -79,7 +79,9 @@ function ctools_plugin_api_info($owner, $api, $minimum_version, $current_version
|
||||
}
|
||||
|
||||
// Only process if version is between minimum and current, inclusive.
|
||||
if (version_compare($version, $minimum_version, '>=') && version_compare($version, $current_version, '<=')) {
|
||||
if (($version == $minimum_version) || ($version == $current_version)
|
||||
|| (version_compare($version, $minimum_version, '>=')
|
||||
&& version_compare($version, $current_version, '<='))) {
|
||||
if (!isset($info['path'])) {
|
||||
$info['path'] = drupal_get_path('module', $module);
|
||||
}
|
||||
@ -110,7 +112,7 @@ function ctools_plugin_api_info($owner, $api, $minimum_version, $current_version
|
||||
}
|
||||
|
||||
// Allow other modules to hook in.
|
||||
drupal_alter($hook, $cache[$owner][$api]);
|
||||
drupal_alter($hook, $cache[$owner][$api], $owner, $api);
|
||||
}
|
||||
|
||||
return $cache[$owner][$api];
|
||||
@ -213,7 +215,7 @@ function ctools_plugin_api_get_hook($owner, $api) {
|
||||
*/
|
||||
function ctools_get_plugins($module, $type, $id = NULL) {
|
||||
// Store local caches of plugins and plugin info so we don't have to do full
|
||||
// lookups everytime.
|
||||
// lookups every time.
|
||||
static $drupal_static_fast;
|
||||
if (!isset($drupal_static_fast)) {
|
||||
$drupal_static_fast['plugins'] = &drupal_static('ctools_plugins', array());
|
||||
|
@ -500,7 +500,7 @@ class ctools_stylizer_image_processor {
|
||||
$palette[$luminosity_input]['green'] = $green;
|
||||
$palette[$luminosity_input]['blue'] = $blue;
|
||||
|
||||
// Now we complete the palette, first we'll do it tothe black, and then to
|
||||
// Now we complete the palette, first we'll do it to the black, and then to
|
||||
// the white.
|
||||
|
||||
// From input to black
|
||||
|
@ -25,7 +25,8 @@ function _ctools_uuid_generate_com() {
|
||||
* Generates an universally unique identifier using the PECL extension.
|
||||
*/
|
||||
function _ctools_uuid_generate_pecl() {
|
||||
return uuid_create(UUID_TYPE_DEFAULT);
|
||||
$uuid_type = UUID_TYPE_DEFAULT;
|
||||
return uuid_create($uuid_type);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -48,7 +48,8 @@
|
||||
modalOptions: {
|
||||
opacity: .55,
|
||||
background: '#fff'
|
||||
}
|
||||
},
|
||||
modalClass: 'default'
|
||||
};
|
||||
|
||||
var settings = {};
|
||||
@ -97,8 +98,8 @@
|
||||
resize();
|
||||
|
||||
$('span.modal-title', Drupal.CTools.Modal.modal).html(Drupal.CTools.Modal.currentSettings.loadingText);
|
||||
Drupal.CTools.Modal.modalContent(Drupal.CTools.Modal.modal, settings.modalOptions, settings.animation, settings.animationSpeed);
|
||||
$('#modalContent .modal-content').html(Drupal.theme(settings.throbberTheme));
|
||||
Drupal.CTools.Modal.modalContent(Drupal.CTools.Modal.modal, settings.modalOptions, settings.animation, settings.animationSpeed, settings.modalClass);
|
||||
$('#modalContent .modal-content').html(Drupal.theme(settings.throbberTheme)).addClass('ctools-modal-loading');
|
||||
|
||||
// Position autocomplete results based on the scroll position of the modal.
|
||||
$('#modalContent .modal-content').delegate('input.form-autocomplete', 'keyup', function() {
|
||||
@ -299,6 +300,17 @@
|
||||
// Attach behaviors within a modal dialog.
|
||||
var settings = response.settings || ajax.settings || Drupal.settings;
|
||||
Drupal.attachBehaviors('#modalContent', settings);
|
||||
|
||||
if ($('#modal-content').hasClass('ctools-modal-loading')) {
|
||||
$('#modal-content').removeClass('ctools-modal-loading');
|
||||
}
|
||||
else {
|
||||
// If the modal was already shown, and we are simply replacing its
|
||||
// content, then focus on the first focusable element in the modal.
|
||||
// (When first showing the modal, focus will be placed on the close
|
||||
// button by the show() function called above.)
|
||||
$('#modal-content :focusable:first').focus();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -349,8 +361,9 @@
|
||||
* @param css obj of css attributes
|
||||
* @param animation (fadeIn, slideDown, show)
|
||||
* @param speed (valid animation speeds slow, medium, fast or # in ms)
|
||||
* @param modalClass class added to div#modalContent
|
||||
*/
|
||||
Drupal.CTools.Modal.modalContent = function(content, css, animation, speed) {
|
||||
Drupal.CTools.Modal.modalContent = function(content, css, animation, speed, modalClass) {
|
||||
// If our animation isn't set, make it just show/pop
|
||||
if (!animation) {
|
||||
animation = 'show';
|
||||
@ -402,9 +415,56 @@
|
||||
if( docHeight < winHeight ) docHeight = winHeight;
|
||||
|
||||
// Create our divs
|
||||
$('body').append('<div id="modalBackdrop" style="z-index: 1000; display: none;"></div><div id="modalContent" style="z-index: 1001; position: absolute;">' + $(content).html() + '</div>');
|
||||
$('body').append('<div id="modalBackdrop" class="backdrop-' + modalClass + '" style="z-index: 1000; display: none;"></div><div id="modalContent" class="modal-' + modalClass + '" style="z-index: 1001; position: absolute;">' + $(content).html() + '</div>');
|
||||
|
||||
// Keyboard and focus event handler ensures focus stays on modal elements only
|
||||
// Get a list of the tabbable elements in the modal content.
|
||||
var getTabbableElements = function () {
|
||||
var tabbableElements = $('#modalContent :tabbable'),
|
||||
radioButtons = tabbableElements.filter('input[type="radio"]');
|
||||
|
||||
// The list of tabbable elements from jQuery is *almost* right. The
|
||||
// exception is with groups of radio buttons. The list from jQuery will
|
||||
// include all radio buttons, when in fact, only the selected radio button
|
||||
// is tabbable, and if no radio buttons in a group are selected, then only
|
||||
// the first is tabbable.
|
||||
if (radioButtons.length > 0) {
|
||||
// First, build up an index of which groups have an item selected or not.
|
||||
var anySelected = {};
|
||||
radioButtons.each(function () {
|
||||
var name = this.name;
|
||||
|
||||
if (typeof anySelected[name] === 'undefined') {
|
||||
anySelected[name] = radioButtons.filter('input[name="' + name + '"]:checked').length !== 0;
|
||||
}
|
||||
});
|
||||
|
||||
// Next filter out the radio buttons that aren't really tabbable.
|
||||
var found = {};
|
||||
tabbableElements = tabbableElements.filter(function () {
|
||||
var keep = true;
|
||||
|
||||
if (this.type == 'radio') {
|
||||
if (anySelected[this.name]) {
|
||||
// Only keep the selected one.
|
||||
keep = this.checked;
|
||||
}
|
||||
else {
|
||||
// Only keep the first one.
|
||||
if (found[this.name]) {
|
||||
keep = false;
|
||||
}
|
||||
found[this.name] = true;
|
||||
}
|
||||
}
|
||||
|
||||
return keep;
|
||||
});
|
||||
}
|
||||
|
||||
return tabbableElements.get();
|
||||
};
|
||||
|
||||
// Keyboard and focus event handler ensures only modal elements gain focus.
|
||||
modalEventHandler = function( event ) {
|
||||
target = null;
|
||||
if ( event ) { //Mozilla
|
||||
@ -428,7 +488,7 @@
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
$('#modalContent').focus();
|
||||
getTabbableElements()[0].focus();
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
@ -436,6 +496,59 @@
|
||||
$('body').bind( 'focus', modalEventHandler );
|
||||
$('body').bind( 'keypress', modalEventHandler );
|
||||
|
||||
// Keypress handler Ensures you can only TAB to elements within the modal.
|
||||
// Based on the psuedo-code from WAI-ARIA 1.0 Authoring Practices section
|
||||
// 3.3.1 "Trapping Focus".
|
||||
modalTabTrapHandler = function (evt) {
|
||||
// We only care about the TAB key.
|
||||
if (evt.which != 9) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var tabbableElements = getTabbableElements(),
|
||||
firstTabbableElement = tabbableElements[0],
|
||||
lastTabbableElement = tabbableElements[tabbableElements.length - 1],
|
||||
singleTabbableElement = firstTabbableElement == lastTabbableElement,
|
||||
node = evt.target;
|
||||
|
||||
// If this is the first element and the user wants to go backwards, then
|
||||
// jump to the last element.
|
||||
if (node == firstTabbableElement && evt.shiftKey) {
|
||||
if (!singleTabbableElement) {
|
||||
lastTabbableElement.focus();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// If this is the last element and the user wants to go forwards, then
|
||||
// jump to the first element.
|
||||
else if (node == lastTabbableElement && !evt.shiftKey) {
|
||||
if (!singleTabbableElement) {
|
||||
firstTabbableElement.focus();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// If this element isn't in the dialog at all, then jump to the first
|
||||
// or last element to get the user into the game.
|
||||
else if ($.inArray(node, tabbableElements) == -1) {
|
||||
// Make sure the node isn't in another modal (ie. WYSIWYG modal).
|
||||
var parents = $(node).parents().get();
|
||||
for (var i = 0; i < parents.length; ++i) {
|
||||
var position = $(parents[i]).css('position');
|
||||
if (position == 'absolute' || position == 'fixed') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (evt.shiftKey) {
|
||||
lastTabbableElement.focus();
|
||||
}
|
||||
else {
|
||||
firstTabbableElement.focus();
|
||||
}
|
||||
}
|
||||
};
|
||||
$('body').bind('keydown', modalTabTrapHandler);
|
||||
|
||||
// Create our content div, get the dimensions, and hide it
|
||||
var modalContent = $('#modalContent').css('top','-1000px');
|
||||
var mdcTop = wt + ( winHeight / 2 ) - ( modalContent.outerHeight() / 2);
|
||||
@ -457,12 +570,19 @@
|
||||
|
||||
$(document).bind('keydown', modalEventEscapeCloseHandler);
|
||||
|
||||
// Per WAI-ARIA 1.0 Authoring Practices, initial focus should be on the
|
||||
// close button, but we should save the original focus to restore it after
|
||||
// the dialog is closed.
|
||||
var oldFocus = document.activeElement;
|
||||
$('.close').focus();
|
||||
|
||||
// Close the open modal content and backdrop
|
||||
function close() {
|
||||
// Unbind the events
|
||||
$(window).unbind('resize', modalContentResize);
|
||||
$('body').unbind( 'focus', modalEventHandler);
|
||||
$('body').unbind( 'keypress', modalEventHandler );
|
||||
$('body').unbind( 'keydown', modalTabTrapHandler );
|
||||
$('.close').unbind('click', modalContentClose);
|
||||
$('body').unbind('keypress', modalEventEscapeCloseHandler);
|
||||
$(document).trigger('CToolsDetachBehaviors', $('#modalContent'));
|
||||
@ -478,12 +598,19 @@
|
||||
// Remove the content
|
||||
$('#modalContent').remove();
|
||||
$('#modalBackdrop').remove();
|
||||
|
||||
// Restore focus to where it was before opening the dialog
|
||||
$(oldFocus).focus();
|
||||
};
|
||||
|
||||
// Move and resize the modalBackdrop and modalContent on resize of the window
|
||||
modalContentResize = function(){
|
||||
// Move and resize the modalBackdrop and modalContent on window resize.
|
||||
modalContentResize = function(){
|
||||
|
||||
// position code lifted from http://www.quirksmode.org/viewport/compatibility.html
|
||||
// Reset the backdrop height/width to get accurate document size.
|
||||
$('#modalBackdrop').css('height', '').css('width', '');
|
||||
|
||||
// Position code lifted from:
|
||||
// http://www.quirksmode.org/viewport/compatibility.html
|
||||
if (self.pageYOffset) { // all except Explorer
|
||||
var wt = self.pageYOffset;
|
||||
} else if (document.documentElement && document.documentElement.scrollTop) { // Explorer 6 Strict
|
||||
@ -509,8 +636,6 @@
|
||||
modalContent.css('top', mdcTop + 'px').css('left', mdcLeft + 'px').show();
|
||||
};
|
||||
$(window).bind('resize', modalContentResize);
|
||||
|
||||
$('#modalContent').focus();
|
||||
};
|
||||
|
||||
/**
|
||||
@ -533,7 +658,9 @@
|
||||
$(window).unbind('resize', modalContentResize);
|
||||
$('body').unbind('focus', modalEventHandler);
|
||||
$('body').unbind('keypress', modalEventHandler);
|
||||
$('body').unbind( 'keydown', modalTabTrapHandler );
|
||||
$('.close').unbind('click', modalContentClose);
|
||||
$('body').unbind('keypress', modalEventEscapeCloseHandler);
|
||||
$(document).trigger('CToolsDetachBehaviors', $('#modalContent'));
|
||||
|
||||
// jQuery magic loop through the instances and run the animations or removal.
|
||||
|
43
sites/all/modules/contrib/dev/ctools/js/states-show.js
Normal file
43
sites/all/modules/contrib/dev/ctools/js/states-show.js
Normal file
@ -0,0 +1,43 @@
|
||||
/**
|
||||
* @file
|
||||
* Custom state for handling visibility
|
||||
*/
|
||||
|
||||
/**
|
||||
* Add a new state to Drupal #states. We use this to toggle element-invisible
|
||||
* to show/hidden #states elements. This allows elements to be visible to
|
||||
* screen readers.
|
||||
*
|
||||
* To use:
|
||||
* $form['my_form_field'] = array(
|
||||
* ..
|
||||
* // Only show this field if 'some_other_field' is checked.
|
||||
* '#states => array(
|
||||
* 'show' => array(
|
||||
* 'some-other-field' => array('checked' => TRUE),
|
||||
* ),
|
||||
* ),
|
||||
* ..
|
||||
* // Required to load the 'show' state handler.
|
||||
* '#attached' => array(
|
||||
* 'js' => array(ctools_attach_js('states-show')),
|
||||
* ),
|
||||
* );
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
'use strict';
|
||||
|
||||
Drupal.states.State.aliases.hidden = '!show';
|
||||
|
||||
// Show/hide form items by toggling the 'element-invisible' class. This is a
|
||||
// more accessible option than the core 'visible' state.
|
||||
$(document).bind('state:show', function(e) {
|
||||
if (e.trigger) {
|
||||
var element = $(e.target).closest('.form-item, .form-submit, .form-wrapper');
|
||||
element.toggle(e.value);
|
||||
e.value === true ? element.removeClass('element-invisible') : element.addClass('element-invisible');
|
||||
}
|
||||
});
|
||||
|
||||
})(jQuery);
|
@ -5,9 +5,9 @@ dependencies[] = ctools
|
||||
package = Chaos tool suite
|
||||
version = CTOOLS_MODULE_VERSION
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-03-18
|
||||
version = "7.x-1.7"
|
||||
; Information added by Drupal.org packaging script on 2015-08-19
|
||||
version = "7.x-1.9"
|
||||
core = "7.x"
|
||||
project = "ctools"
|
||||
datestamp = "1426696183"
|
||||
datestamp = "1440020680"
|
||||
|
||||
|
@ -440,13 +440,18 @@ function page_manager_cache_load($task_name) {
|
||||
*/
|
||||
function page_manager_handler_get_name($task_name, $handlers, $handler) {
|
||||
$base = str_replace('-', '_', $task_name);
|
||||
$name = '';
|
||||
|
||||
// Optional machine name.
|
||||
if (!empty($handler->conf['name'])) {
|
||||
$name = $base . '__' . $handler->conf['name'];
|
||||
if (count(ctools_export_load_object('page_manager_handlers', 'names', array($name)))) {
|
||||
$name = '';
|
||||
}
|
||||
}
|
||||
|
||||
// If no machine name was provided, generate a unique name.
|
||||
else {
|
||||
// If no machine name was provided or the name is in use, generate a unique name.
|
||||
if (empty($name)) {
|
||||
$base .= '__' . $handler->handler;
|
||||
|
||||
// Use the ctools uuid generator to generate a unique id.
|
||||
@ -472,6 +477,10 @@ function page_manager_handler_add_to_page(&$page, &$handler, $title = NULL) {
|
||||
|
||||
if ($title) {
|
||||
$handler->conf['title'] = $title;
|
||||
$handler->conf['name'] = trim(preg_replace('/[^a-z0-9_]+/', '-', strtolower($title)), '-');
|
||||
}
|
||||
else {
|
||||
$handler->conf['name'] = '';
|
||||
}
|
||||
|
||||
$name = page_manager_handler_get_name($page->task_name, $page->handlers, $handler);
|
||||
|
@ -108,7 +108,7 @@ function page_manager_node_edit($node) {
|
||||
* Callback to handle the process of adding a node.
|
||||
*
|
||||
* This creates a basic $node and passes that off to page_manager_node_edit().
|
||||
* It is modeled after Drupal's node_add() function.
|
||||
* It is modelled after Drupal's node_add() function.
|
||||
*
|
||||
* Unlike node_add() we do not need to check node_access because that was
|
||||
* already checked by the menu system.
|
||||
|
@ -78,10 +78,6 @@ function page_manager_node_view_menu_alter(&$items, $task) {
|
||||
* node view, which is node_page_view().
|
||||
*/
|
||||
function page_manager_node_view_page($node) {
|
||||
// Prep the node to be displayed so all of the regular hooks are triggered.
|
||||
// Also save the output for later, in case it is needed.
|
||||
$default_output = node_page_view($node);
|
||||
|
||||
// Load my task plugin
|
||||
$task = page_manager_get_task('node_view');
|
||||
|
||||
@ -107,6 +103,9 @@ function page_manager_node_view_page($node) {
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare the node to be displayed so all of the regular hooks are triggered.
|
||||
$default_output = node_page_view($node);
|
||||
|
||||
// Otherwise, fall back to the default output generated by node_page_view().
|
||||
return $default_output;
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ function page_manager_page_menu(&$items, $task) {
|
||||
}
|
||||
|
||||
$path = array();
|
||||
$page_arguments = array($subtask_id);
|
||||
$page_arguments = array((string) $subtask_id);
|
||||
$access_arguments = array($subtask->access);
|
||||
$load_arguments = array($subtask_id, '%index', '%map');
|
||||
|
||||
@ -566,7 +566,7 @@ function page_manager_page_form_basic_validate(&$form, &$form_state) {
|
||||
if (strpos($path, '%') === FALSE) {
|
||||
$alias = db_query('SELECT alias, source FROM {url_alias} WHERE alias = :path', array(':path' => $path))->fetchObject();
|
||||
if ($alias) {
|
||||
form_error($form['path'], t('That path is currently assigned to be an alias for @alias. This system cannot override existing aliases.', array('@alias' => $alias->src)));
|
||||
form_error($form['path'], t('That path is currently assigned to be an alias for @alias. This system cannot override existing aliases.', array('@alias' => $alias->source)));
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Plugins are described by creating a $plugin array which will be used
|
||||
* by the system that includes this file.
|
||||
*/
|
||||
$plugin = array(
|
||||
'single' => TRUE,
|
||||
'title' => t('Comment created date'),
|
||||
'icon' => 'icon_comment.png',
|
||||
'description' => t('The date the referenced comment was created.'),
|
||||
'required context' => new ctools_context_required(t('Comment'), 'entity:comment'),
|
||||
'category' => t('Comment'),
|
||||
'defaults' => array(
|
||||
'format' => 'small',
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* Render the custom content type.
|
||||
*/
|
||||
function ctools_comment_created_content_type_render($subtype, $conf, $panel_args, $context) {
|
||||
if (empty($context) || empty($context->data)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get a shortcut to the comment.
|
||||
$comment = $context->data;
|
||||
|
||||
// Build the content type block.
|
||||
$block = new stdClass();
|
||||
$block->module = 'comment_created';
|
||||
$block->title = t('Created date');
|
||||
$block->content = format_date($comment->created, $conf['format']);
|
||||
$block->delta = $comment->cid;
|
||||
|
||||
return $block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an edit form for custom type settings.
|
||||
*/
|
||||
function ctools_comment_created_content_type_edit_form($form, &$form_state) {
|
||||
$conf = $form_state['conf'];
|
||||
$date_types = array();
|
||||
|
||||
foreach (system_get_date_types() as $date_type => $definition) {
|
||||
$date_types[$date_type] = format_date(REQUEST_TIME, $date_type);
|
||||
}
|
||||
$form['format'] = array(
|
||||
'#title' => t('Date format'),
|
||||
'#type' => 'select',
|
||||
'#options' => $date_types,
|
||||
'#default_value' => $conf['format'],
|
||||
);
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit handler for the custom type settings form.
|
||||
*/
|
||||
function ctools_comment_created_content_type_edit_form_submit($form, &$form_state) {
|
||||
// Copy everything from our defaults.
|
||||
foreach (array_keys($form_state['plugin']['defaults']) as $key) {
|
||||
$form_state['conf'][$key] = $form_state['values'][$key];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the administrative title for a type.
|
||||
*/
|
||||
function ctools_comment_created_content_type_admin_title($subtype, $conf, $context) {
|
||||
return t('"@s" created date', array('@s' => $context->identifier));
|
||||
}
|
@ -34,6 +34,14 @@ function ctools_entity_field_content_type_content_types() {
|
||||
return $types;
|
||||
}
|
||||
|
||||
$cache_key = 'ctools_entity_field_content_type_content_types';
|
||||
if ($cache = cache_get($cache_key)) {
|
||||
$types = $cache->data;
|
||||
if (!empty($types)) {
|
||||
return $types;
|
||||
}
|
||||
}
|
||||
|
||||
// This will hold all the individual field content types.
|
||||
$context_types = array();
|
||||
$entities = entity_get_info();
|
||||
@ -82,6 +90,8 @@ function ctools_entity_field_content_type_content_types() {
|
||||
unset($context_types[$key]['types']);
|
||||
}
|
||||
|
||||
cache_set($cache_key, $types);
|
||||
|
||||
return $types;
|
||||
}
|
||||
|
||||
|
@ -57,6 +57,26 @@ function ctools_entity_form_field_content_type_content_types() {
|
||||
}
|
||||
}
|
||||
|
||||
if (module_exists('field_group')) {
|
||||
foreach ($entities as $entity_type => $entity) {
|
||||
foreach ($entity['bundles'] as $type => $bundle) {
|
||||
if ($group_info = field_group_info_groups($entity_type, $type, "form")) {
|
||||
foreach ($group_info as $group_name => $group) {
|
||||
if (!isset($types[$entity_type . ':' . $group_name])) {
|
||||
$types[$entity_type . ':' . $group_name] = array(
|
||||
'category' => t('Form'),
|
||||
'icon' => 'icon_field.png',
|
||||
'title' => t('Group form: @widget_label', array('@widget_label' => $group->label)),
|
||||
'description' => t('Field group on the referenced entity.'),
|
||||
);
|
||||
}
|
||||
$content_types[$entity_type . ':' . $group_name]['types'][$type] = $bundle['label'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create the required context for each field related to the bundle types.
|
||||
foreach ($types as $key => $field_content_type) {
|
||||
list($entity_type, $field_name) = explode(':', $key, 2);
|
||||
@ -85,16 +105,38 @@ function ctools_entity_form_field_content_type_render($subtype, $conf, $panel_ar
|
||||
$ids = entity_extract_ids($entity_type, $entity);
|
||||
$field = field_info_instance($entity_type, $field_name, $ids[2]);
|
||||
|
||||
// Do not render if the entity type does not have this field.
|
||||
if (empty($field)) {
|
||||
// Check for field groups.
|
||||
if (empty($field) && module_exists('field_group')) {
|
||||
$groups = field_group_info_groups($entity_type, $entity->type, "form");
|
||||
$group = !empty($groups[$field_name]) ? $groups[$field_name] : NULL;
|
||||
}
|
||||
|
||||
// Do not render if the entity type does not have this field or group.
|
||||
if (empty($field) && empty($group)) {
|
||||
return;
|
||||
}
|
||||
$block = new stdClass();
|
||||
|
||||
$block = new stdClass();
|
||||
if (isset($context->form)) {
|
||||
$block->content = array();
|
||||
$block->content[$field_name] = $context->form[$field_name];
|
||||
unset($context->form[$field_name]);
|
||||
if (!empty($field)) {
|
||||
$block->content[$field_name] = $context->form[$field_name];
|
||||
unset($context->form[$field_name]);
|
||||
}
|
||||
else {
|
||||
// Pre-render the form to populate field groups.
|
||||
if (isset($context->form['#pre_render'])) {
|
||||
foreach ($context->form['#pre_render'] as $function) {
|
||||
if (function_exists($function)) {
|
||||
$context->form = $function($context->form);
|
||||
}
|
||||
}
|
||||
unset($context->form['#pre_render']);
|
||||
}
|
||||
|
||||
$block->content[$field_name] = $context->form[$field_name];
|
||||
unset($context->form[$field_name]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$block->content = t('Entity info.');
|
||||
|
@ -77,20 +77,3 @@ function ctools_node_comment_form_content_type_edit_form_submit($form, &$form_st
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Alter the comment form to get a little more control over it.
|
||||
*/
|
||||
function ctools_form_comment_form_alter(&$form, &$form_state) {
|
||||
if (!empty($form_state['ctools comment alter'])) {
|
||||
// Force the form to post back to wherever we are.
|
||||
$form['#action'] = url($_GET['q'], array('fragment' => 'comment-form'));
|
||||
if (empty($form['#submit'])) {
|
||||
$form['#submit'] = array('comment_form_submit');
|
||||
}
|
||||
$form['#submit'][] = 'ctools_node_comment_form_submit';
|
||||
}
|
||||
}
|
||||
|
||||
function ctools_node_comment_form_submit(&$form, &$form_state) {
|
||||
$form_state['redirect'][0] = $_GET['q'];
|
||||
}
|
||||
|
@ -29,6 +29,9 @@ $plugin = array(
|
||||
* Outputs the page title of the current page.
|
||||
*/
|
||||
function ctools_page_title_content_type_render($subtype, $conf, $panel_args) {
|
||||
if (!drupal_get_title()) {
|
||||
return;
|
||||
}
|
||||
// TODO: This should have a setting or something for the markup.
|
||||
if (empty($conf['markup'])) {
|
||||
$conf['markup'] = 'h1';
|
||||
|
@ -18,8 +18,8 @@ function ctools_term_description_content_type_render($subtype, $conf, $panel_arg
|
||||
$block = new stdClass();
|
||||
$block->module = 'node_type';
|
||||
|
||||
$block->title = $term->name;
|
||||
if ($term) {
|
||||
if (!empty($term)) {
|
||||
$block->title = $term->name;
|
||||
$block->content = check_markup($term->description, $term->format, '', TRUE);
|
||||
$block->delta = $term->tid;
|
||||
|
||||
@ -33,6 +33,7 @@ function ctools_term_description_content_type_render($subtype, $conf, $panel_arg
|
||||
}
|
||||
}
|
||||
else {
|
||||
$block->title = '';
|
||||
$block->content = t('Term description goes here.');
|
||||
$block->delta = 'unknown';
|
||||
}
|
||||
|
@ -43,7 +43,9 @@ function ctools_context_create_user($empty, $data = NULL, $conf = FALSE) {
|
||||
if ($data['type'] == 'current') {
|
||||
global $user;
|
||||
$data = user_load($user->uid);
|
||||
$data->logged_in_user = TRUE;
|
||||
if (user_is_logged_in()) {
|
||||
$data->logged_in_user = TRUE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$data = user_load($data['uid']);
|
||||
|
@ -34,15 +34,15 @@ function ctools_context_create_user_edit_form($empty, $user = NULL, $conf = FALS
|
||||
$category = !empty($conf['category']) ? $conf['category'] : FALSE;
|
||||
unset($conf['category']);
|
||||
|
||||
// If no category was specified, use the default 'account'.
|
||||
if (!$category) {
|
||||
$category = 'account';
|
||||
}
|
||||
// Return previously created contexts, per category.
|
||||
static $created = array();
|
||||
if (!empty($created[$category])) {
|
||||
return $created[$category];
|
||||
}
|
||||
// If no category was specified, use the default 'account'.
|
||||
if (!$category) {
|
||||
$category = 'account';
|
||||
}
|
||||
|
||||
$context = new ctools_context(array('form', 'user_edit', 'user_form', 'user_edit_form', 'user', 'entity:user'));
|
||||
// Store this context for later.
|
||||
|
@ -724,7 +724,13 @@ class ctools_export_ui {
|
||||
// Export the handler, which is a fantastic way to clean database IDs out of it.
|
||||
$export = ctools_export_crud_export($this->plugin['schema'], $original);
|
||||
$item = ctools_export_crud_import($this->plugin['schema'], $export);
|
||||
$item->{$this->plugin['export']['key']} = 'clone_of_' . $item->{$this->plugin['export']['key']};
|
||||
|
||||
if (!empty($input[$this->plugin['export']['key']])) {
|
||||
$item->{$this->plugin['export']['key']} = $input[$this->plugin['export']['key']];
|
||||
}
|
||||
else {
|
||||
$item->{$this->plugin['export']['key']} = 'clone_of_' . $item->{$this->plugin['export']['key']};
|
||||
}
|
||||
}
|
||||
|
||||
// Tabs and breadcrumb disappearing, this helps alleviate through cheating.
|
||||
|
@ -185,7 +185,7 @@ function ctools_entity_from_field_context($context, $conf) {
|
||||
$loaded_to_entity = array_shift($loaded_to_entity);
|
||||
|
||||
// Pass current user account and entity type to access callback.
|
||||
if (function_exists($to_entity_info['access callback']) && !call_user_func($to_entity_info['access callback'], 'view', $loaded_to_entity, $account, $to_entity)) {
|
||||
if (isset($to_entity_info['access callback']) && function_exists($to_entity_info['access callback']) && !call_user_func($to_entity_info['access callback'], 'view', $loaded_to_entity)) {
|
||||
return ctools_context_create_empty('entity:' . $to_entity, NULL);
|
||||
}
|
||||
else {
|
||||
|
@ -6,9 +6,9 @@ version = CTOOLS_MODULE_VERSION
|
||||
dependencies[] = ctools
|
||||
dependencies[] = color
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-03-18
|
||||
version = "7.x-1.7"
|
||||
; Information added by Drupal.org packaging script on 2015-08-19
|
||||
version = "7.x-1.9"
|
||||
core = "7.x"
|
||||
project = "ctools"
|
||||
datestamp = "1426696183"
|
||||
datestamp = "1440020680"
|
||||
|
||||
|
@ -5,9 +5,9 @@ dependencies[] = ctools
|
||||
package = Chaos tool suite
|
||||
version = CTOOLS_MODULE_VERSION
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-03-18
|
||||
version = "7.x-1.7"
|
||||
; Information added by Drupal.org packaging script on 2015-08-19
|
||||
version = "7.x-1.9"
|
||||
core = "7.x"
|
||||
project = "ctools"
|
||||
datestamp = "1426696183"
|
||||
datestamp = "1440020680"
|
||||
|
||||
|
@ -8,9 +8,9 @@ hidden = TRUE
|
||||
|
||||
files[] = ctools_export.test
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-03-18
|
||||
version = "7.x-1.7"
|
||||
; Information added by Drupal.org packaging script on 2015-08-19
|
||||
version = "7.x-1.9"
|
||||
core = "7.x"
|
||||
project = "ctools"
|
||||
datestamp = "1426696183"
|
||||
datestamp = "1440020680"
|
||||
|
||||
|
@ -12,9 +12,9 @@ files[] = math_expression.test
|
||||
files[] = math_expression_stack.test
|
||||
hidden = TRUE
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-03-18
|
||||
version = "7.x-1.7"
|
||||
; Information added by Drupal.org packaging script on 2015-08-19
|
||||
version = "7.x-1.9"
|
||||
core = "7.x"
|
||||
project = "ctools"
|
||||
datestamp = "1426696183"
|
||||
datestamp = "1440020680"
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
/**
|
||||
* @file
|
||||
* A cached plugin object that tests inheritence including.
|
||||
* A cached plugin object that tests inheritance including.
|
||||
*/
|
||||
|
||||
class ctoolsCachedPluginArray {}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
/**
|
||||
* @file
|
||||
* A cached plugin object that tests inheritence including.
|
||||
* A cached plugin object that tests inheritance including.
|
||||
*/
|
||||
|
||||
class ctoolsCachedPluginArray2 extends ctoolsCachedPluginArray {}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
/**
|
||||
* @file
|
||||
* A cached plugin object that tests inheritence including.
|
||||
* A cached plugin object that tests inheritance including.
|
||||
*/
|
||||
|
||||
class ctoolsNotCachedPluginArray extends ctoolsNotCachedPluginArray2 {}
|
||||
|
@ -10,9 +10,9 @@ files[] = plugins/views/views_content_plugin_display_ctools_context.inc
|
||||
files[] = plugins/views/views_content_plugin_display_panel_pane.inc
|
||||
files[] = plugins/views/views_content_plugin_style_ctools_context.inc
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-03-18
|
||||
version = "7.x-1.7"
|
||||
; Information added by Drupal.org packaging script on 2015-08-19
|
||||
version = "7.x-1.9"
|
||||
core = "7.x"
|
||||
project = "ctools"
|
||||
datestamp = "1426696183"
|
||||
datestamp = "1440020680"
|
||||
|
||||
|
@ -13,7 +13,7 @@ $plugin = array(
|
||||
'access' => 'administer video styles',
|
||||
// Define the menu item.
|
||||
'menu' => array(
|
||||
'menu prefix' => 'admin/config/media',
|
||||
'menu prefix' => 'admin/config/media/vef',
|
||||
'menu item' => 'vef_video_styles',
|
||||
'menu title' => 'Video Embed Styles',
|
||||
'menu description' => 'Administer Video Embed Field\'s video styles.',
|
||||
|
@ -6,9 +6,9 @@ configure = admin/config/media/vef_video_styles
|
||||
|
||||
dependencies[] = "video_embed_field"
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-17
|
||||
version = "7.x-2.0-beta8+7-dev"
|
||||
; Information added by Drupal.org packaging script on 2015-09-07
|
||||
version = "7.x-2.0-beta11"
|
||||
core = "7.x"
|
||||
project = "video_embed_field"
|
||||
datestamp = "1429278491"
|
||||
datestamp = "1441639440"
|
||||
|
||||
|
@ -24,6 +24,7 @@ function video_embed_brightcove_video_embed_handler_info() {
|
||||
'defaults' => array(
|
||||
'width' => 640,
|
||||
'height' => 360,
|
||||
'class' => '',
|
||||
),
|
||||
);
|
||||
|
||||
@ -57,6 +58,13 @@ function video_embed_brightcove_form($defaults) {
|
||||
'#default_value' => $defaults['height'],
|
||||
);
|
||||
|
||||
$form['class'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Player CSS class'),
|
||||
'#description' => t('CSS class to add to the player'),
|
||||
'#default_value' => $defaults['class'],
|
||||
);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
@ -83,7 +91,7 @@ function video_embed_brightcove_handle_video($url, $settings) {
|
||||
|
||||
if (isset($parameters['id']) && isset($parameters['key'])) {
|
||||
// Embed code.
|
||||
$embed = '<object id="myExperience" class="BrightcoveExperience">
|
||||
$embed = '<object class="@class" id="myExperience" class="BrightcoveExperience">
|
||||
<param name="bgcolor" value="#FFFFFF" />
|
||||
<param name="width" value="@width" />
|
||||
<param name="height" value="@height" />
|
||||
@ -100,6 +108,7 @@ function video_embed_brightcove_handle_video($url, $settings) {
|
||||
'!key' => $parameters['key'],
|
||||
'@width' => $settings['width'],
|
||||
'@height' => $settings['height'],
|
||||
'@class' => $settings['class'],
|
||||
'!videoplayer' => $parameters['player'],
|
||||
));
|
||||
|
||||
@ -152,7 +161,7 @@ function _video_embed_brightcove_get_video_properties($url) {
|
||||
$string = "/(.*){$component['start']}(.*){$component['finish']}/";
|
||||
preg_match($string, $url, $matches);
|
||||
if ($matches && !empty($matches[2])) {
|
||||
$return[$key] = $matches[2];
|
||||
$return[$key] = check_plain($matches[2]);
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
|
@ -5,9 +5,9 @@ package = Media
|
||||
configure = admin/config/media/vef_video_styles
|
||||
|
||||
dependencies[] = "video_embed_field"
|
||||
; Information added by Drupal.org packaging script on 2015-04-17
|
||||
version = "7.x-2.0-beta8+7-dev"
|
||||
; Information added by Drupal.org packaging script on 2015-09-07
|
||||
version = "7.x-2.0-beta11"
|
||||
core = "7.x"
|
||||
project = "video_embed_field"
|
||||
datestamp = "1429278491"
|
||||
datestamp = "1441639440"
|
||||
|
||||
|
@ -25,6 +25,7 @@ function video_embed_facebook_video_embed_handler_info() {
|
||||
'defaults' => array(
|
||||
'width' => 640,
|
||||
'height' => 360,
|
||||
'class' => '',
|
||||
),
|
||||
);
|
||||
|
||||
@ -57,6 +58,13 @@ function video_embed_facebook_form($defaults) {
|
||||
'#default_value' => $defaults['height'],
|
||||
);
|
||||
|
||||
$form['class'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Player CSS class'),
|
||||
'#description' => t('CSS class to add to the player'),
|
||||
'#default_value' => $defaults['class'],
|
||||
);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
@ -90,12 +98,13 @@ function video_embed_facebook_handle_video($url, $settings) {
|
||||
|
||||
if ($id) {
|
||||
// Our embed code.
|
||||
$embed='<iframe src="//www.facebook.com/video/embed?video_id=!id" width="!width" height="!height"></iframe> ';
|
||||
$embed='<iframe class="@class" src="//www.facebook.com/video/embed?video_id=!id" width="@width" height="@height"></iframe> ';
|
||||
// Use format_string to replace our placeholders with the settings values.
|
||||
$embed = format_string($embed, array(
|
||||
'!id' => $id,
|
||||
'!width' => $settings['width'],
|
||||
'!height' => $settings['height'],
|
||||
'@width' => $settings['width'],
|
||||
'@height' => $settings['height'],
|
||||
'@class' => $settings['class'],
|
||||
));
|
||||
|
||||
$video = array(
|
||||
@ -137,10 +146,10 @@ function video_embed_facebook_handle_thumbnail($url) {
|
||||
function _video_embed_facebook_get_video_id($url) {
|
||||
// Parse_url is an easy way to break a url into its components.
|
||||
$matches = array();
|
||||
preg_match('/(.*)?[v|video_id]=([^&#]*)/', $url, $matches);
|
||||
preg_match('/(?:.*)(?:v=|video_id=|videos\/|videos\/v.\.\d+\/)(\d+).*/', $url, $matches);
|
||||
// If the v or video_id get parameters are set, return it.
|
||||
if ($matches && !empty($matches[2])) {
|
||||
return $matches[2];
|
||||
if ($matches && !empty($matches[1])) {
|
||||
return check_plain($matches[1]);
|
||||
}
|
||||
// Otherwise return false.
|
||||
return FALSE;
|
||||
|
@ -32,3 +32,15 @@ function video_embed_field_video_style_form(&$form, &$form_state) {
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* VEF settings page form callback.
|
||||
*/
|
||||
function video_embed_field_settings_form($form, &$form_state) {
|
||||
$form['video_embed_field_youtube_v3_api_key'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Youtube v3 API key'),
|
||||
'#default_value' => variable_get('video_embed_field_youtube_v3_api_key', ''),
|
||||
);
|
||||
return system_settings_form($form);
|
||||
}
|
||||
|
@ -454,7 +454,7 @@ function video_embed_field_field_formatter_view($entity_type, $entity, $field, $
|
||||
if (isset($item['description']) && $item['description'] && $settings['description'] && $instance['settings']['description_field']) {
|
||||
$description = array(
|
||||
'#prefix' => '<div class="video-embed-description">',
|
||||
'#markup' => $item['description'],
|
||||
'#markup' => check_plain($item['description']),
|
||||
'#suffix' => '</div>',
|
||||
);
|
||||
$alt = $item['description'];
|
||||
|
@ -38,6 +38,7 @@ function video_embed_field_video_embed_handler_info() {
|
||||
'modestbranding' => 0,
|
||||
'theme' => 'dark',
|
||||
'iv_load_policy' => 1,
|
||||
'class' => '',
|
||||
),
|
||||
);
|
||||
|
||||
@ -46,6 +47,7 @@ function video_embed_field_video_embed_handler_info() {
|
||||
'function' => 'video_embed_field_handle_vimeo',
|
||||
'thumbnail_function' => 'video_embed_field_handle_vimeo_thumbnail',
|
||||
'thumbnail_default' => drupal_get_path('module', 'video_embed_field') . '/img/vimeo.jpg',
|
||||
'data_function' => '_video_embed_field_get_vimeo_data',
|
||||
'form' => 'video_embed_field_handler_vimeo_form',
|
||||
'form_validate' => 'video_embed_field_handler_vimeo_form_validate',
|
||||
'domains' => array(
|
||||
@ -61,6 +63,7 @@ function video_embed_field_video_embed_handler_info() {
|
||||
'autoplay' => 0,
|
||||
'loop' => 0,
|
||||
'froogaloop' => 0,
|
||||
'class' => ''
|
||||
),
|
||||
);
|
||||
|
||||
@ -146,7 +149,7 @@ function _video_embed_field_get_youtube_id($url) {
|
||||
$id = substr($url, $pos);
|
||||
}
|
||||
}
|
||||
return $id;
|
||||
return check_plain($id);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -163,16 +166,21 @@ function _video_embed_field_get_youtube_id($url) {
|
||||
function video_embed_field_handle_youtube($url, $settings) {
|
||||
$output = array();
|
||||
|
||||
// Grab the minutes and seconds, and just convert it down to seconds.
|
||||
preg_match('/#t=((?P<min>\d+)m)?((?P<sec>\d+)s)?/', $url, $matches);
|
||||
|
||||
// Give it some default data in case there is no #t=...
|
||||
$matches += array(
|
||||
"min" => 0,
|
||||
"sec" => 0,
|
||||
);
|
||||
$time = ($matches["min"] * 60) + $matches["sec"];
|
||||
$settings['start'] = $time;
|
||||
if(preg_match('/#t=((?P<min>\d+)m)?((?P<sec>\d+)s)?((?P<tinsec>\d+))?/', $url, $matches)){
|
||||
if(isset($matches['tinsec'])){
|
||||
$settings['start'] = $matches['tinsec']; // url already in form #t=125 for 2 minutes and 5 seconds
|
||||
} else {
|
||||
// url in form #t=2m5s or with other useless data, this is why we still keep adding the default data..
|
||||
// give it some default data in case there is no #t=...
|
||||
$matches += array(
|
||||
"min" => 0,
|
||||
"sec" => 0,
|
||||
);
|
||||
if ($time = ($matches["min"] * 60) + $matches["sec"]) {
|
||||
$settings['start'] = $time;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$id = _video_embed_field_get_youtube_id($url);
|
||||
if (!$id) {
|
||||
@ -180,11 +188,16 @@ function video_embed_field_handle_youtube($url, $settings) {
|
||||
$output['#markup'] = l($url, $url);
|
||||
return $output;
|
||||
}
|
||||
|
||||
// Add class to variable to avoid adding it to URL param string.
|
||||
$class = $settings['class'];
|
||||
unset($settings['class']);
|
||||
|
||||
// Construct the embed code.
|
||||
$settings['wmode'] = 'opaque';
|
||||
$settings_str = _video_embed_code_get_settings_str($settings);
|
||||
$settings_str = urlencode(_video_embed_code_get_settings_str($settings));
|
||||
|
||||
$output['#markup'] = '<iframe width="' . check_plain($settings['width']) . '" height="' . check_plain($settings['height']) . '" src="//www.youtube.com/embed/' . $id . '?' . $settings_str . '" frameborder="0" allowfullscreen></iframe>';
|
||||
$output['#markup'] = '<iframe class="' . check_plain($class) . '" width="' . check_plain($settings['width']) . '" height="' . check_plain($settings['height']) . '" src="//www.youtube.com/embed/' . $id . '?' . $settings_str . '" frameborder="0" allowfullscreen></iframe>';
|
||||
|
||||
return $output;
|
||||
}
|
||||
@ -243,11 +256,17 @@ function video_embed_field_handle_youtube_data($url) {
|
||||
$id = _video_embed_field_get_youtube_id($url);
|
||||
|
||||
if ($id) {
|
||||
$response = drupal_http_request('http://gdata.youtube.com/feeds/api/videos/' . $id . '?v=2&alt=json');
|
||||
|
||||
$options['v'] = 3;
|
||||
$options['key'] = variable_get('video_embed_field_youtube_v3_api_key', '');
|
||||
$options['part'] = 'snippet';
|
||||
$options['id'] = $id;
|
||||
|
||||
$response = drupal_http_request(url('https://www.googleapis.com/youtube/v3/videos', array('query' => $options)));
|
||||
|
||||
if (!isset($response->error)) {
|
||||
$data = json_decode($response->data);
|
||||
$data = isset($data->entry) ? (array) $data->entry : (array) $data->feed;
|
||||
return _video_embed_field_clean_up_youtube_data($data);
|
||||
return _video_embed_field_clean_up_youtube_data($data->items);
|
||||
}
|
||||
}
|
||||
|
||||
@ -401,6 +420,13 @@ function video_embed_field_handler_youtube_form($defaults) {
|
||||
'#default_value' => $defaults['autohide'],
|
||||
);
|
||||
|
||||
$form['class'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Player CSS class'),
|
||||
'#description' => t('CSS class to add to the player'),
|
||||
'#default_value' => $defaults['class'],
|
||||
);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
@ -489,10 +515,14 @@ function video_embed_field_handle_vimeo($url, $settings) {
|
||||
}
|
||||
unset($settings['froogaloop']);
|
||||
|
||||
// Add class to variable to avoid adding it to URL param string.
|
||||
$class = $settings['class'];
|
||||
unset($settings['class']);
|
||||
|
||||
$settings_str = _video_embed_code_get_settings_str($settings);
|
||||
|
||||
return array(
|
||||
'#markup' => '<iframe id="' . $settings['player_id'] . '" width="' . check_plain($settings['width']) . '" height="' . check_plain($settings['height']) . '" src="//player.vimeo.com/video/' . $id .
|
||||
'#markup' => '<iframe class="' . check_plain($class) . '" id="' . $settings['player_id'] . '" width="' . check_plain($settings['width']) . '" height="' . check_plain($settings['height']) . '" src="//player.vimeo.com/video/' . $id .
|
||||
'?' . $settings_str . '" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowfullscreen></iframe>',
|
||||
);
|
||||
}
|
||||
@ -616,6 +646,13 @@ function video_embed_field_handler_vimeo_form($defaults) {
|
||||
'#default_value' => $defaults['loop'],
|
||||
);
|
||||
|
||||
$form['class'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Player CSS class'),
|
||||
'#description' => t('CSS class to add to the player'),
|
||||
'#default_value' => $defaults['class'],
|
||||
);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@ name = "Video Embed Field"
|
||||
description = "Expose a field type for embedding videos from youtube or vimeo."
|
||||
core = 7.x
|
||||
package = Media
|
||||
configure = admin/config/media/vef_video_styles
|
||||
configure = admin/config/media/vef
|
||||
|
||||
files[] = video_embed_field.migrate.inc
|
||||
files[] = views/handlers/views_embed_field_views_handler_field_thumbnail_path.inc
|
||||
@ -10,9 +10,9 @@ files[] = views/handlers/views_embed_field_views_handler_field_thumbnail_path.in
|
||||
dependencies[] = ctools
|
||||
dependencies[] = image
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-17
|
||||
version = "7.x-2.0-beta8+7-dev"
|
||||
; Information added by Drupal.org packaging script on 2015-09-07
|
||||
version = "7.x-2.0-beta11"
|
||||
core = "7.x"
|
||||
project = "video_embed_field"
|
||||
datestamp = "1429278491"
|
||||
datestamp = "1441639440"
|
||||
|
||||
|
@ -96,6 +96,13 @@ function video_embed_field_schema() {
|
||||
return $schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_uninstall().
|
||||
*/
|
||||
function video_embed_field_uninstall() {
|
||||
variable_del('video_embed_field_youtube_api_key');
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an optional description form.
|
||||
*/
|
||||
@ -363,3 +370,22 @@ function video_embed_field_update_7009() {
|
||||
|
||||
return t('Updated default instance settings');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update styles with empty class parameter.
|
||||
*/
|
||||
function video_embed_field_update_7010() {
|
||||
drupal_get_schema('vef_video_styles', TRUE);
|
||||
ctools_include('export');
|
||||
$styles = ctools_export_load_object('vef_video_styles');
|
||||
foreach ($styles as $style) {
|
||||
foreach ($style->data as &$provider) {
|
||||
if (!isset($provider['class'])) {
|
||||
$provider['class'] = '';
|
||||
}
|
||||
}
|
||||
ctools_export_crud_save('vef_video_styles', $style);
|
||||
}
|
||||
|
||||
return 'Parameter class added to existing styles';
|
||||
}
|
||||
|
@ -93,6 +93,26 @@ function video_embed_field_menu() {
|
||||
'type' => MENU_CALLBACK,
|
||||
);
|
||||
|
||||
$items['admin/config/media/vef'] = array(
|
||||
'title' => 'Video Embed Field',
|
||||
'description' => 'Video Embed Field configuration',
|
||||
'page callback' => 'system_admin_menu_block_page',
|
||||
'access arguments' => array('administer video styles'),
|
||||
'file' => 'system.admin.inc',
|
||||
'file path' => drupal_get_path('module', 'system'),
|
||||
'type' => MENU_NORMAL_ITEM,
|
||||
);
|
||||
|
||||
$items['admin/config/media/vef/settings'] = array(
|
||||
'title' => 'Settings',
|
||||
'description' => 'Video Embed Field module settings',
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('video_embed_field_settings_form'),
|
||||
'file' => 'video_embed_field.admin.inc',
|
||||
'access arguments' => array('administer video styles'),
|
||||
'type' => MENU_NORMAL_ITEM,
|
||||
);
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
@ -577,15 +597,7 @@ function _video_embed_field_get_provider_domains() {
|
||||
* An array containing the allowed video domains.
|
||||
*/
|
||||
function _video_embed_field_get_instance_provider_domains($instance) {
|
||||
$domains = _video_embed_field_get_provider_domains();
|
||||
|
||||
foreach ($domains as $domain => $provider) {
|
||||
if (empty($instance['settings']['allowed_providers'][$provider])) {
|
||||
unset($domains[$domain]);
|
||||
}
|
||||
}
|
||||
|
||||
return $domains;
|
||||
return array_intersect(_video_embed_field_get_provider_domains(), $instance['settings']['allowed_providers']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,5 +0,0 @@
|
||||
Conventions to make porting changes between Drupal 6 and Drupal 7 easier:
|
||||
|
||||
Try to always use specific DBTNG functions such as db_select() instead of the
|
||||
more general db_query(), which needs to be renamed to dbtng_query() under
|
||||
Drupal 6.
|
@ -1,11 +1,31 @@
|
||||
Migrate 2.7
|
||||
Migrate 2.8
|
||||
===========
|
||||
|
||||
Bug fixes
|
||||
- #2415597 - Make batching of SQL sources optional, and force map_joinable FALSE.
|
||||
Features and enhancements
|
||||
- #2379289 - Better handle interaction of --update with highwater marks.
|
||||
- #2403643 - Support an additional level of subfields.
|
||||
- #2472045 - Add language subfields only if field is translatable.
|
||||
- #2474809 - Provide better message for bad dependencies.
|
||||
- #2397791 - Provide detailed field validation errors.
|
||||
- #2309563 - Add support for running migrations via wildcard name.
|
||||
- #2095841 - Abstract mail system disablement for more flexibility.
|
||||
- #2419373 - Provide ability to cache map lookups.
|
||||
- #2141687 - Provide detailed message on file copy error.
|
||||
|
||||
Migrate 2.7 Release Candidate 1
|
||||
===============================
|
||||
Bug fixes
|
||||
Field sanitization added to prevent possibility of XSS - see security advisory
|
||||
https://security.drupal.org/node/155268.
|
||||
- #2447115 - Add xpath handling to the field mapping editor.
|
||||
- #2497015 - Term reference handler would ignore all terms if one was NULL.
|
||||
- #2488560 - MigrateSourceList/MigrateSourceMultiItems iterators prematurely
|
||||
return.
|
||||
- #2446105 - Keep coded DNM source field mappings from overriding UI mappings.
|
||||
- #2415977 - Use temporary:// instead of /tmp for drush logging.
|
||||
- #2475473 - Fix handling of --idlist when map not joined.
|
||||
- #2465387 - Fix handling of --stop option on migrate-import.
|
||||
|
||||
Migrate 2.7
|
||||
===========
|
||||
|
||||
Features and enhancements
|
||||
- #2296911 - Add a source handler for IBM DB2.
|
||||
@ -14,6 +34,7 @@ Features and enhancements
|
||||
- #1751438 - Add spreadsheet source plugin.
|
||||
|
||||
Bug fixes
|
||||
- #2415597 - Make batching of SQL sources optional, and force map_joinable FALSE.
|
||||
- #2403593 - SQL batching messes up cases with altered queries, such as idlist.
|
||||
- #2298969 - Verify wizard validation function exists.
|
||||
- #2268863 - Fix drush --all option.
|
||||
|
@ -301,6 +301,11 @@ abstract class MigrationBase {
|
||||
return $this->disableHooks;
|
||||
}
|
||||
|
||||
/**
|
||||
* An array to track 'mail_system' variable if disabled.
|
||||
*/
|
||||
protected $mailSystem = array();
|
||||
|
||||
/**
|
||||
* Have we already warned about obsolete constructor argumentss on this request?
|
||||
*
|
||||
@ -432,16 +437,11 @@ abstract class MigrationBase {
|
||||
// Record the time limit
|
||||
$this->timeLimit = ini_get('max_execution_time');
|
||||
|
||||
// Prevent any emails from being sent out on migration
|
||||
global $conf;
|
||||
if (!empty($conf['mail_system'])) {
|
||||
foreach ($conf['mail_system'] as $system => $class) {
|
||||
$conf['mail_system'][$system] = 'MigrateMailIgnore';
|
||||
}
|
||||
}
|
||||
else {
|
||||
$conf['mail_system']['default-system'] = 'MigrateMailIgnore';
|
||||
}
|
||||
// Save the current mail system, prior to disabling emails.
|
||||
$this->saveMailSystem();
|
||||
|
||||
// Prevent emails from being sent out during migrations.
|
||||
$this->disableMailSystem();
|
||||
|
||||
// Make sure we clear our semaphores in case of abrupt exit
|
||||
drupal_register_shutdown_function(array($this, 'endProcess'));
|
||||
@ -1355,6 +1355,39 @@ abstract class MigrationBase {
|
||||
}
|
||||
return $time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the current mail system, or set a system default if there is none.
|
||||
*/
|
||||
protected function saveMailSystem() {
|
||||
global $conf;
|
||||
if (empty($conf['mail_system'])) {
|
||||
$conf['mail_system']['default-system'] = 'MigrateMailIgnore';
|
||||
}
|
||||
else {
|
||||
$this->mailSystem = $conf['mail_system'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables mail system to prevent emails from being sent during migrations.
|
||||
*/
|
||||
public function disableMailSystem() {
|
||||
global $conf;
|
||||
if (!empty($conf['mail_system'])) {
|
||||
foreach ($conf['mail_system'] as $system => $class) {
|
||||
$conf['mail_system'][$system] = 'MigrateMailIgnore';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores the original saved mail system for migrations that require it.
|
||||
*/
|
||||
public function restoreMailSystem() {
|
||||
global $conf;
|
||||
$conf['mail_system'] = $this->mailSystem;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure static members (in particular, $displayFunction) get
|
||||
|
@ -141,16 +141,26 @@ abstract class Migration extends MigrationBase {
|
||||
// destination field, keep only the last (so the UI can override a source
|
||||
// field DNM that was defined in code).
|
||||
$no_destination = array();
|
||||
// But also remove a mapping of a source field to nothing, if there is
|
||||
// a mapping to something.
|
||||
$mapped_source_fields = array();
|
||||
/** @var MigrateFieldMapping $mapping */
|
||||
foreach ($this->allFieldMappings as $destination_field => $mapping) {
|
||||
$source_field = $mapping->getSourceField();
|
||||
// If the source field is not mapped to a destination field, the
|
||||
// array index is integer.
|
||||
if (is_int($destination_field)) {
|
||||
$source_field = $mapping->getSourceField();
|
||||
if (isset($no_destination[$source_field])) {
|
||||
unset($this->allFieldMappings[$no_destination[$source_field]]);
|
||||
unset($no_destination[$source_field]);
|
||||
}
|
||||
$no_destination[$source_field] = $destination_field;
|
||||
if (isset($mapped_source_fields[$source_field])) {
|
||||
unset($this->allFieldMappings[$destination_field]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$mapped_source_fields[$source_field] = $source_field;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1267,8 +1277,11 @@ abstract class Migration extends MigrationBase {
|
||||
// Are we dealing with the primary value of the destination field, or a
|
||||
// subfield?
|
||||
$destination = explode(':', $destination);
|
||||
// Count how many levels of fields are in the mapping. We'll use the
|
||||
// last one.
|
||||
$destination_count = count($destination);
|
||||
$destination_field = $destination[0];
|
||||
if (isset($destination[1])) {
|
||||
if ($destination_count == 2) {
|
||||
$subfield = $destination[1];
|
||||
// We're processing the subfield before the primary value, initialize it
|
||||
if (!property_exists($this->destinationValues, $destination_field)) {
|
||||
@ -1282,6 +1295,24 @@ abstract class Migration extends MigrationBase {
|
||||
// Add the subfield value to the arguments array.
|
||||
$this->destinationValues->{$destination_field}['arguments'][$subfield] = $destination_values;
|
||||
}
|
||||
elseif ($destination_count == 3) {
|
||||
$subfield2 = $destination[2];
|
||||
// We're processing the subfield before the primary value, initialize it
|
||||
if (!property_exists($this->destinationValues, $destination_field)) {
|
||||
$this->destinationValues->$destination_field = array();
|
||||
}
|
||||
// We have a value, and need to convert to an array so we can add
|
||||
// arguments.
|
||||
elseif (!is_array($this->destinationValues->$destination_field)) {
|
||||
$this->destinationValues->$destination_field = array($this->destinationValues->$destination_field);
|
||||
}
|
||||
if (!is_array($this->destinationValues->{$destination_field}['arguments'][$destination[1]])) {
|
||||
// Convert first subfield level to an array so we can add to it.
|
||||
$this->destinationValues->{$destination_field}['arguments'][$destination[1]] = array( $this->destinationValues->{$destination_field}['arguments'][$destination[1]] );
|
||||
}
|
||||
// Add the subfield value to the arguments array.
|
||||
$this->destinationValues->{$destination_field}['arguments'][$destination[1]]['arguments'][$subfield2] = $destination_values;
|
||||
}
|
||||
// Just the primary value, the first time through for this field, simply
|
||||
// set it.
|
||||
elseif (!property_exists($this->destinationValues, $destination_field)) {
|
||||
|
@ -303,9 +303,11 @@ abstract class MigrateSource implements Iterator {
|
||||
// highwaters and map rows).
|
||||
$prepared = FALSE;
|
||||
if (!empty($this->idList)) {
|
||||
// Check first source key.
|
||||
if (!in_array(reset($this->currentKey), $this->idList)) {
|
||||
// If this is a compound source key, check the full key.
|
||||
$compoundKey = implode($this->multikeySeparator, $this->currentKey);
|
||||
if (count($this->currentKey) > 1 && !in_array($compoundKey, $this->idList)) {
|
||||
if (count($this->currentKey) == 1 || !in_array($compoundKey, $this->idList)) {
|
||||
// Could not find the key, skip.
|
||||
continue;
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ function migrate_drush_command() {
|
||||
'force' => 'Force an operation to run, even if all dependencies are not satisfied',
|
||||
'group' => 'Name of the migration group to run',
|
||||
'notify' => 'Send email notification upon completion of operation',
|
||||
'wildcard' => 'Process migrations that match a certain pattern. For example, Content*.',
|
||||
);
|
||||
$items['migrate-status'] = array(
|
||||
'description' => 'List all migrations with current status.',
|
||||
@ -161,6 +162,7 @@ function migrate_drush_command() {
|
||||
'migrate-import Article' => 'Import new articles',
|
||||
'migrate-import Article --update' => 'Import new items, and also update previously-imported items',
|
||||
'migrate-import Article --idlist=4,9' => 'Import two specific articles. The ids refer to the value of the primary key in base table',
|
||||
'migrate-import Article --idlist=450:pasta,451' => 'Import two specific articles. A colon can be used to separate parts of compound keys; otherwise, compound keys match by the first key field.',
|
||||
'migrate-import Article --limit="60 seconds" --stop --rollback' =>
|
||||
'Import for up to 60 seconds after stopping and rolling back the Article migration.',
|
||||
'migrate-import Article --limit="100 items"' =>
|
||||
@ -824,15 +826,6 @@ function drush_migrate_rollback($args = NULL) {
|
||||
// Capture non-informational output for mailing
|
||||
ob_start();
|
||||
ob_implicit_flush(FALSE);
|
||||
// Save original mail setup, which Migrate will disable, so we can
|
||||
// restore it later.
|
||||
global $conf;
|
||||
if (!empty($conf['mail_system'])) {
|
||||
$mail_system = $conf['mail_system'];
|
||||
}
|
||||
else {
|
||||
$mail_system = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
$migrations = drush_migrate_get_migrations($args);
|
||||
@ -928,12 +921,6 @@ function drush_migrate_rollback($args = NULL) {
|
||||
|
||||
// Notify user
|
||||
if (drush_get_option('notify')) {
|
||||
if (is_null($mail_system)) {
|
||||
unset($conf['mail_system']);
|
||||
}
|
||||
else {
|
||||
$conf['mail_system'] = $mail_system;
|
||||
}
|
||||
_drush_migrate_notify();
|
||||
}
|
||||
}
|
||||
@ -985,6 +972,14 @@ function drush_migrate_get_migrations($args) {
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif ($wildcard = drush_get_option('wildcard')) {
|
||||
foreach ($migration_objects as $name => $migration) {
|
||||
if (!fnmatch(drupal_strtolower($wildcard), drupal_strtolower($name)) ||
|
||||
!$migration->getEnabled()) {
|
||||
unset($migration_objects[$name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$named_migrations = array();
|
||||
foreach (explode(',', $args) as $name) {
|
||||
@ -1057,18 +1052,23 @@ function drush_migrate_rollback_validate($args = NULL) {
|
||||
|
||||
function drush_migrate_validate_common($args) {
|
||||
if (drush_get_option('all')) {
|
||||
if (!empty($args) || drush_get_option('group')) {
|
||||
return drush_set_error(NULL, dt('You must specify exactly one of a migration name, --all, or --group'));
|
||||
if (!empty($args) || drush_get_option('group') || drush_get_option('wildcard')) {
|
||||
return drush_set_error(NULL, dt('You must specify exactly one of a migration name, --all, or --group, or --wildcard'));
|
||||
}
|
||||
}
|
||||
elseif (drush_get_option('group')) {
|
||||
if (!empty($args) || drush_get_option('all')) {
|
||||
return drush_set_error(NULL, dt('You must specify exactly one of a migration name, --all, or --group'));
|
||||
if (!empty($args) || drush_get_option('all') || drush_get_option('wildcard')) {
|
||||
return drush_set_error(NULL, dt('You must specify exactly one of a migration name, --all, or --group, or --wildcard'));
|
||||
}
|
||||
}
|
||||
elseif (drush_get_option('wildcard')) {
|
||||
if (!empty($args) || drush_get_option('all') || drush_get_option('group')) {
|
||||
return drush_set_error(NULL, dt('You must specify exactly one of a migration name, --all, or --group, or --wildcard'));
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (empty($args)) {
|
||||
return drush_set_error(NULL, dt('You must specify exactly one of a migration name, --all, or --group'));
|
||||
return drush_set_error(NULL, dt('You must specify exactly one of a migration name, --all, or --group, or --wildcard'));
|
||||
}
|
||||
$machine_names = explode(',', $args);
|
||||
|
||||
@ -1107,7 +1107,29 @@ function drush_migrate_validate_common($args) {
|
||||
*/
|
||||
function drush_migrate_pre_migrate_import($args = NULL) {
|
||||
if (drush_get_option('stop')) {
|
||||
drush_invoke('migrate-stop', $args);
|
||||
drush_unset_option('stop');
|
||||
try {
|
||||
/** @var Migration[] $migrations */
|
||||
$migrations = drush_migrate_get_migrations($args);
|
||||
foreach ($migrations as $migration) {
|
||||
$status = $migration->getStatus();
|
||||
if ($status == MigrationBase::STATUS_IMPORTING ||
|
||||
$status == MigrationBase::STATUS_ROLLING_BACK) {
|
||||
drush_log(dt("Stopping '!description' migration", array('!description' => $migration->getMachineName())));
|
||||
$migration->stopProcess();
|
||||
// Give the process a chance to stop.
|
||||
$count = 0;
|
||||
while ($migration->getStatus() != MigrationBase::STATUS_IDLE
|
||||
&& $count++ < 5) {
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (MigrateException $e) {
|
||||
drush_print($e->getMessage());
|
||||
exit;
|
||||
}
|
||||
}
|
||||
if (drush_get_option('rollback')) {
|
||||
drush_unset_option('rollback');
|
||||
@ -1127,15 +1149,6 @@ function drush_migrate_import($args = NULL) {
|
||||
// Capture non-informational output for mailing
|
||||
ob_start();
|
||||
ob_implicit_flush(FALSE);
|
||||
// Save original mail setup, which Migrate will disable, so we can
|
||||
// restore it later.
|
||||
global $conf;
|
||||
if (!empty($conf['mail_system'])) {
|
||||
$mail_system = $conf['mail_system'];
|
||||
}
|
||||
else {
|
||||
$mail_system = NULL;
|
||||
}
|
||||
}
|
||||
$migrations = drush_migrate_get_migrations($args);
|
||||
$options = array();
|
||||
@ -1294,12 +1307,6 @@ function drush_migrate_import($args = NULL) {
|
||||
|
||||
// Notify user
|
||||
if (drush_get_option('notify')) {
|
||||
if (is_null($mail_system)) {
|
||||
unset($conf['mail_system']);
|
||||
}
|
||||
else {
|
||||
$conf['mail_system'] = $mail_system;
|
||||
}
|
||||
_drush_migrate_notify();
|
||||
}
|
||||
}
|
||||
|
@ -51,9 +51,9 @@ files[] = tests/plugins/destinations/term.test
|
||||
files[] = tests/plugins/destinations/user.test
|
||||
files[] = tests/plugins/sources/xml.test
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-02-09
|
||||
version = "7.x-2.7"
|
||||
; Information added by Drupal.org packaging script on 2015-07-01
|
||||
version = "7.x-2.8"
|
||||
core = "7.x"
|
||||
project = "migrate"
|
||||
datestamp = "1423521491"
|
||||
datestamp = "1435760949"
|
||||
|
||||
|
@ -93,11 +93,18 @@ function migrate_migrations($reset = NULL) {
|
||||
$final_migrations[$name] = array();
|
||||
}
|
||||
|
||||
// Fill in the grouped list
|
||||
// Fill in the grouped list.
|
||||
foreach ($migrations as $machine_name => $migration) {
|
||||
$final_migrations[$migration->getGroup()->getName()][$machine_name] = $migration;
|
||||
if (!method_exists($migration, 'getGroup')) {
|
||||
MigrationBase::displayMessage(t('Migration !machine_name is not a valid Migration dependency.', array(
|
||||
'!machine_name' => $machine_name,
|
||||
)));
|
||||
}
|
||||
else {
|
||||
$final_migrations[$migration->getGroup()->getName()][$machine_name] = $migration;
|
||||
}
|
||||
}
|
||||
// Then flatten the list
|
||||
// Flatten the grouped list.
|
||||
$migrations = array();
|
||||
foreach ($final_migrations as $group_name => $group_migrations) {
|
||||
foreach ($group_migrations as $machine_name => $migration) {
|
||||
|
@ -424,15 +424,13 @@ class BeerNodeMigration extends BasicExampleMigration {
|
||||
// subfields of the same field may be grouped on the same line), and indent
|
||||
// subfields to distinguish them from top-level fields.
|
||||
$this->addUnmigratedDestinations(array(
|
||||
'body:format', 'body:language',
|
||||
'body:format',
|
||||
'changed',
|
||||
'comment',
|
||||
'created',
|
||||
'field_migrate_example_country:language',
|
||||
'field_migrate_example_image:destination_dir',
|
||||
'field_migrate_example_image:destination_file',
|
||||
'field_migrate_example_image:file_replace',
|
||||
'field_migrate_example_image:language',
|
||||
'field_migrate_example_image:preserve_files',
|
||||
'field_migrate_example_image:urlencode',
|
||||
'is_new',
|
||||
@ -515,7 +513,7 @@ class BeerCommentMigration extends BasicExampleMigration {
|
||||
// Unmapped destination fields
|
||||
$this->addUnmigratedDestinations(array(
|
||||
'changed',
|
||||
'comment_body:format', 'comment_body:language',
|
||||
'comment_body:format',
|
||||
'created',
|
||||
'homepage',
|
||||
'hostname',
|
||||
|
@ -18,9 +18,9 @@ files[] = wine.inc
|
||||
; For testing table_copy plugin. Since is infrequently used, we comment it out.
|
||||
; files[] = example.table_copy.inc
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-02-09
|
||||
version = "7.x-2.7"
|
||||
; Information added by Drupal.org packaging script on 2015-07-01
|
||||
version = "7.x-2.8"
|
||||
core = "7.x"
|
||||
project = "migrate"
|
||||
datestamp = "1423521491"
|
||||
datestamp = "1435760949"
|
||||
|
||||
|
@ -11,9 +11,9 @@ name = "Migrate example - Oracle"
|
||||
package = "Migration"
|
||||
project = "migrate_example_oracle"
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-02-09
|
||||
version = "7.x-2.7"
|
||||
; Information added by Drupal.org packaging script on 2015-07-01
|
||||
version = "7.x-2.8"
|
||||
core = "7.x"
|
||||
project = "migrate"
|
||||
datestamp = "1423521491"
|
||||
datestamp = "1435760949"
|
||||
|
||||
|
@ -449,7 +449,7 @@ class WineProducerMigration extends AdvancedExampleMigration {
|
||||
|
||||
// Unmapped destination fields
|
||||
$this->addUnmigratedDestinations(array(
|
||||
'body:format', 'body:language',
|
||||
'body:format',
|
||||
'changed',
|
||||
'comment',
|
||||
'created',
|
||||
@ -550,7 +550,7 @@ class WineProducerXMLMigration extends XMLMigration {
|
||||
->xpath('/producer/description');
|
||||
|
||||
$this->addUnmigratedDestinations(array(
|
||||
'body:summary', 'body:format', 'body:language',
|
||||
'body:summary', 'body:format',
|
||||
'changed',
|
||||
'comment',
|
||||
'created',
|
||||
@ -663,7 +663,7 @@ class WineProducerNamespaceXMLMigration extends XMLMigration {
|
||||
->xpath('/pr:producer/pr:description');
|
||||
|
||||
$this->addUnmigratedDestinations(array(
|
||||
'body:summary', 'body:format', 'body:language',
|
||||
'body:summary', 'body:format',
|
||||
'changed',
|
||||
'comment',
|
||||
'created',
|
||||
@ -784,7 +784,7 @@ class WineProducerMultiXMLMigration extends XMLMigration {
|
||||
->xpath('description');
|
||||
|
||||
$this->addUnmigratedDestinations(array(
|
||||
'body:summary', 'body:format', 'body:language',
|
||||
'body:summary', 'body:format',
|
||||
'changed',
|
||||
'comment',
|
||||
'created',
|
||||
@ -907,7 +907,7 @@ class WineProducerMultiNamespaceXMLMigration extends XMLMigration {
|
||||
->xpath('pr:description');
|
||||
|
||||
$this->addUnmigratedDestinations(array(
|
||||
'body:summary', 'body:format', 'body:language',
|
||||
'body:summary', 'body:format',
|
||||
'changed',
|
||||
'comment',
|
||||
'created',
|
||||
@ -1012,7 +1012,7 @@ class WineProducerXMLPullMigration extends XMLMigration {
|
||||
->xpath('description');
|
||||
|
||||
$this->addUnmigratedDestinations(array(
|
||||
'body:summary', 'body:format', 'body:language',
|
||||
'body:summary', 'body:format',
|
||||
'changed',
|
||||
'comment',
|
||||
'created',
|
||||
@ -1119,7 +1119,7 @@ class WineProducerNamespaceXMLPullMigration extends XMLMigration {
|
||||
->xpath('pr:description');
|
||||
|
||||
$this->addUnmigratedDestinations(array(
|
||||
'body:summary', 'body:format', 'body:language',
|
||||
'body:summary', 'body:format',
|
||||
'changed',
|
||||
'comment',
|
||||
'created',
|
||||
@ -1290,12 +1290,11 @@ class WineWineMigration extends AdvancedExampleMigration {
|
||||
|
||||
// Unmapped destination fields
|
||||
$this->addUnmigratedDestinations(array(
|
||||
'body:format', 'body:language',
|
||||
'body:format',
|
||||
'comment',
|
||||
'field_migrate_example_image:destination_dir',
|
||||
'field_migrate_example_image:destination_file',
|
||||
'field_migrate_example_image:file_class',
|
||||
'field_migrate_example_image:language',
|
||||
'field_migrate_example_image:preserve_files',
|
||||
'field_migrate_example_image:source_dir',
|
||||
'field_migrate_example_image:urlencode',
|
||||
@ -1418,7 +1417,7 @@ class WineCommentMigration extends AdvancedExampleMigration {
|
||||
|
||||
// Unmapped destination fields
|
||||
$this->addUnmigratedDestinations(array(
|
||||
'comment_body:format', 'comment_body:language',
|
||||
'comment_body:format',
|
||||
'language',
|
||||
'thread',
|
||||
));
|
||||
@ -1551,14 +1550,13 @@ class WineUpdatesMigration extends AdvancedExampleMigration {
|
||||
$this->addFieldMapping('created');
|
||||
$this->addFieldMapping('changed');
|
||||
$this->addUnmigratedDestinations(array(
|
||||
'body:format', 'body:summary', 'body:language',
|
||||
'body:format', 'body:summary',
|
||||
'comment',
|
||||
'field_migrate_example_image:alt',
|
||||
'field_migrate_example_image:destination_dir',
|
||||
'field_migrate_example_image:destination_file',
|
||||
'field_migrate_example_image:file_class',
|
||||
'field_migrate_example_image:file_replace',
|
||||
'field_migrate_example_image:language',
|
||||
'field_migrate_example_image:preserve_files',
|
||||
'field_migrate_example_image:source_dir',
|
||||
'field_migrate_example_image:title',
|
||||
@ -1623,7 +1621,7 @@ class WineCommentUpdatesMigration extends AdvancedExampleMigration {
|
||||
// Unmapped destination fields
|
||||
$this->addUnmigratedDestinations(array(
|
||||
'changed',
|
||||
'comment_body', 'comment_body:format', 'comment_body:language',
|
||||
'comment_body', 'comment_body:format',
|
||||
'created',
|
||||
'homepage',
|
||||
'hostname',
|
||||
|
@ -24,9 +24,9 @@ name = "migrate_example_baseball"
|
||||
package = "Migration"
|
||||
php = "5.2.4"
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-02-09
|
||||
version = "7.x-2.7"
|
||||
; Information added by Drupal.org packaging script on 2015-07-01
|
||||
version = "7.x-2.8"
|
||||
core = "7.x"
|
||||
project = "migrate"
|
||||
datestamp = "1423521491"
|
||||
datestamp = "1435760949"
|
||||
|
||||
|
@ -6,9 +6,9 @@ core = 7.x
|
||||
dependencies[] = migrate
|
||||
files[] = migrate_ui.wizard.inc
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-02-09
|
||||
version = "7.x-2.7"
|
||||
; Information added by Drupal.org packaging script on 2015-07-01
|
||||
version = "7.x-2.8"
|
||||
core = "7.x"
|
||||
project = "migrate"
|
||||
datestamp = "1423521491"
|
||||
datestamp = "1435760949"
|
||||
|
||||
|
@ -14,7 +14,7 @@ function migrate_ui_migrate_dashboard($form, &$form_state) {
|
||||
|
||||
$build['overview'] = array(
|
||||
'#prefix' => '<div>',
|
||||
'#markup' => migrate_overview(),
|
||||
'#markup' => filter_xss_admin(migrate_overview()),
|
||||
'#suffix' => '</div>',
|
||||
);
|
||||
|
||||
@ -100,7 +100,7 @@ function migrate_ui_migrate_dashboard($form, &$form_state) {
|
||||
l($group_row->title, 'admin/content/migrate/groups/' . $group_row->name);
|
||||
$arguments = unserialize($group_row->arguments);
|
||||
if (!empty($arguments['source_system'])) {
|
||||
$row['source_system'] = $arguments['source_system'];
|
||||
$row['source_system'] = filter_xss_admin($arguments['source_system']);
|
||||
}
|
||||
else {
|
||||
$row['source_system'] = '';
|
||||
@ -212,9 +212,9 @@ function migrate_ui_migrate_group($form, &$form_state, $group_name) {
|
||||
}
|
||||
$row['machinename'] =
|
||||
l($display_name, "admin/content/migrate/groups/$group_name/$machine_name");
|
||||
$row['importrows'] = $total;
|
||||
$row['imported'] = $imported;
|
||||
$row['unprocessed'] = $unprocessed;
|
||||
$row['importrows'] = (int) $total;
|
||||
$row['imported'] = (int) $imported;
|
||||
$row['unprocessed'] = (int) $unprocessed;
|
||||
if (user_access(MIGRATE_ACCESS_ADVANCED)) {
|
||||
if (is_subclass_of($migration, 'Migration')) {
|
||||
$num_messages = $migration->messageCount();
|
||||
@ -231,13 +231,13 @@ function migrate_ui_migrate_group($form, &$form_state, $group_name) {
|
||||
$row['lastthroughput'] = t('Unknown');
|
||||
}
|
||||
else {
|
||||
$row['lastthroughput'] = t('!rate/min', array('!rate' => $rate));
|
||||
$row['lastthroughput'] = t('@rate/min', array('@rate' => $rate));
|
||||
}
|
||||
}
|
||||
else {
|
||||
$row['lastthroughput'] = t('N/A');
|
||||
}
|
||||
$row['lastimported'] = $migration->getLastImported();
|
||||
$row['lastimported'] = check_plain($migration->getLastImported());
|
||||
}
|
||||
$rows[$machine_name] = $row;
|
||||
}
|
||||
@ -497,6 +497,19 @@ function migrate_ui_migrate_submit($form, &$form_state) {
|
||||
}
|
||||
elseif (count($drush_arguments) > 0) {
|
||||
$drush_path = trim(variable_get('migrate_drush_path', ''));
|
||||
// Check that $drush_path works. See migrate_ui_configure_form().
|
||||
if (!is_executable($drush_path)) {
|
||||
$message = t('To enable running operations in the background with <a href="@drush">drush</a>, (which is <a href="@recommended">recommended</a>), some configuration must be done on the server. See the <a href="@config">documentation</a> on <a href="@dorg">drupal.org</a>.',
|
||||
array(
|
||||
'@drush' => 'http://drupal.org/project/drush',
|
||||
'@recommended' => 'http://drupal.org/node/1806824',
|
||||
'@config' => 'http://drupal.org/node/1958170',
|
||||
'@dorg' => 'http://drupal.org/',
|
||||
)
|
||||
);
|
||||
drupal_set_message($message);
|
||||
return;
|
||||
}
|
||||
$uri = $GLOBALS['base_url'];
|
||||
$uid = $GLOBALS['user']->uid;
|
||||
if ($operation == 'import_background') {
|
||||
@ -523,7 +536,7 @@ function migrate_ui_migrate_submit($form, &$form_state) {
|
||||
$limit = $limit['value'] . ' ' . $limit['unit'];
|
||||
$drush_command .= " --limit=\"$limit\"";
|
||||
}
|
||||
$log_file = '/tmp/' . $drush_arguments[0] . $log_suffix;
|
||||
$log_file = drupal_realpath('temporary://' . $drush_arguments[0] . $log_suffix);
|
||||
$drush_command .= " >$log_file 2>&1 &";
|
||||
exec($drush_command, $output, $status);
|
||||
if (variable_get('migrate_drush_mail', 0)) {
|
||||
@ -674,13 +687,24 @@ function migrate_ui_batch_finish($success, $results, $operations) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a message to be displayed later.
|
||||
*
|
||||
* Ignore the message if $level is set to 'debug'.
|
||||
*
|
||||
* @param string $message
|
||||
* the message to be displayed
|
||||
* @param string $level
|
||||
* the type of the message: 'debug', 'completed', 'failed', or a valid $type
|
||||
* used by drupal_set_message()
|
||||
*/
|
||||
function migrate_ui_capture_message($message, $level) {
|
||||
if ($level != 'debug') {
|
||||
// Store each message as an array with keys 'message' and 'level'.
|
||||
global $_migrate_messages;
|
||||
$_migrate_messages[] = array(
|
||||
'message' => $message,
|
||||
'level' => $level,
|
||||
'message' => filter_xss_admin($message),
|
||||
'level' => check_plain($level),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -738,8 +762,8 @@ function migrate_migration_info($form, $form_state, $group_name, $migration_name
|
||||
foreach ($team as $group => $list) {
|
||||
$form['overview'][$group] = array(
|
||||
'#type' => 'item',
|
||||
'#title' => $group,
|
||||
'#markup' => implode(', ', $list),
|
||||
'#title' => filter_xss_admin($group),
|
||||
'#markup' => filter_xss_admin(implode(', ', $list)),
|
||||
);
|
||||
}
|
||||
|
||||
@ -747,7 +771,7 @@ function migrate_migration_info($form, $form_state, $group_name, $migration_name
|
||||
if (count($dependencies) > 0) {
|
||||
$form['overview']['dependencies'] = array(
|
||||
'#title' => t('Dependencies') ,
|
||||
'#markup' => implode(', ', $dependencies),
|
||||
'#markup' => filter_xss_admin(implode(', ', $dependencies)),
|
||||
'#type' => 'item',
|
||||
);
|
||||
}
|
||||
@ -755,14 +779,14 @@ function migrate_migration_info($form, $form_state, $group_name, $migration_name
|
||||
if (count($soft_dependencies) > 0) {
|
||||
$form['overview']['soft_dependencies'] = array(
|
||||
'#title' => t('Soft Dependencies'),
|
||||
'#markup' => implode(', ', $soft_dependencies),
|
||||
'#markup' => filter_xss_admin(implode(', ', $soft_dependencies)),
|
||||
'#type' => 'item',
|
||||
);
|
||||
}
|
||||
|
||||
$form['overview']['group'] = array(
|
||||
'#title' => t('Group:'),
|
||||
'#markup' => $migration->getGroup()->getTitle(),
|
||||
'#markup' => filter_xss_admin($migration->getGroup()->getTitle()),
|
||||
'#type' => 'item',
|
||||
);
|
||||
|
||||
@ -787,7 +811,7 @@ function migrate_migration_info($form, $form_state, $group_name, $migration_name
|
||||
|
||||
$form['overview']['description'] = array(
|
||||
'#title' => t('Description:'),
|
||||
'#markup' => $migration->getDescription(),
|
||||
'#markup' => filter_xss_admin($migration->getDescription()),
|
||||
'#type' => 'item',
|
||||
);
|
||||
|
||||
@ -807,7 +831,7 @@ function migrate_migration_info($form, $form_state, $group_name, $migration_name
|
||||
$form['destination']['type'] = array(
|
||||
'#type' => 'item',
|
||||
'#title' => t('Type'),
|
||||
'#markup' => (string)$destination,
|
||||
'#markup' => filter_xss_admin((string) $destination),
|
||||
);
|
||||
$dest_key = $destination->getKeySchema();
|
||||
$header = array(t('Machine name'), t('Description'));
|
||||
@ -822,7 +846,10 @@ function migrate_migration_info($form, $form_state, $group_name, $migration_name
|
||||
// Add class for mapped/unmapped. Used in summary.
|
||||
$classes[] = !isset($destination_fields[$machine_name]) ? 'migrate-error' : '';
|
||||
}
|
||||
$rows[] = array(array('data' => $machine_name, 'class' => $classes), array('data' => $description, 'class' => $classes));
|
||||
$rows[] = array(
|
||||
array('data' => check_plain($machine_name), 'class' => $classes),
|
||||
array('data' => filter_xss_admin($description), 'class' => $classes),
|
||||
);
|
||||
}
|
||||
$classes = array();
|
||||
|
||||
@ -848,7 +875,7 @@ function migrate_migration_info($form, $form_state, $group_name, $migration_name
|
||||
$form['source']['query'] = array(
|
||||
'#type' => 'item',
|
||||
'#title' => t('Query'),
|
||||
'#markup' => '<pre>' . $source . '</pre>',
|
||||
'#markup' => '<pre>' . filter_xss_admin($source) . '</pre>',
|
||||
);
|
||||
$source_key = $migration->getMap()->getSourceKey();
|
||||
$header = array(t('Machine name'), t('Description'));
|
||||
@ -862,7 +889,10 @@ function migrate_migration_info($form, $form_state, $group_name, $migration_name
|
||||
// Add class for mapped/unmapped. Used in summary.
|
||||
$classes = !isset($source_fields[$machine_name]) ? 'migrate-error' : '';
|
||||
}
|
||||
$rows[] = array(array('data' => $machine_name, 'class' => $classes), array('data' => $description, 'class' => $classes));
|
||||
$rows[] = array(
|
||||
array('data' => check_plain($machine_name), 'class' => $classes),
|
||||
array('data' => filter_xss_admin($description), 'class' => $classes),
|
||||
);
|
||||
}
|
||||
$classes = array();
|
||||
|
||||
@ -887,16 +917,16 @@ function migrate_migration_info($form, $form_state, $group_name, $migration_name
|
||||
if (!is_null($source_field) && !isset($source_fields[$source_field])) {
|
||||
drupal_set_message(t('"!source" was used as source field in the
|
||||
"!destination" mapping but is not in list of source fields', array(
|
||||
'!source' => $source_field,
|
||||
'!destination' => $destination_field
|
||||
'!source' => filter_xss_admin($source_field),
|
||||
'!destination' => filter_xss_admin($destination_field),
|
||||
)),
|
||||
'warning');
|
||||
}
|
||||
if (!is_null($destination_field) && !isset($destination_fields[$destination_field])) {
|
||||
drupal_set_message(t('"!destination" was used as destination field in
|
||||
"!source" mapping but is not in list of destination fields', array(
|
||||
'!source' => $source_field,
|
||||
'!destination' => $destination_field)),
|
||||
'!source' => filter_xss_admin($source_field),
|
||||
'!destination' => filter_xss_admin($destination_field))),
|
||||
'warning');
|
||||
}
|
||||
$descriptions[$mapping->getIssueGroup()][] = $mapping;
|
||||
@ -906,7 +936,7 @@ function migrate_migration_info($form, $form_state, $group_name, $migration_name
|
||||
foreach ($descriptions as $group => $mappings) {
|
||||
$form[$group] = array(
|
||||
'#type' => 'fieldset',
|
||||
'#title' => t('Mapping: !group', array('!group' => $group)),
|
||||
'#title' => t('Mapping: !group', array('!group' => filter_xss_admin($group))),
|
||||
'#group' => 'detail',
|
||||
'#attributes' => array('class' => array('migrate-mapping')),
|
||||
);
|
||||
@ -918,7 +948,7 @@ function migrate_migration_info($form, $form_state, $group_name, $migration_name
|
||||
}
|
||||
$issue_priority = $mapping->getIssuePriority();
|
||||
if (!is_null($issue_priority)) {
|
||||
$classes[] = 'migrate-priority-' . $issue_priority;
|
||||
$classes[] = 'migrate-priority-' . drupal_html_class($issue_priority);
|
||||
$priority = MigrateFieldMapping::$priorities[$issue_priority];
|
||||
$issue_pattern = $migration->getIssuePattern();
|
||||
$issue_number = $mapping->getIssueNumber();
|
||||
@ -942,11 +972,11 @@ function migrate_migration_info($form, $form_state, $group_name, $migration_name
|
||||
$source_field = "<em>$source_field</em>";
|
||||
}
|
||||
$row = array(
|
||||
array('data' => $destination_field, 'class' => $classes),
|
||||
array('data' => $source_field, 'class' => $classes),
|
||||
array('data' => $default, 'class' => $classes),
|
||||
array('data' => $mapping->getDescription(), 'class' => $classes),
|
||||
array('data' => $priority, 'class' => $classes),
|
||||
array('data' => filter_xss_admin($destination_field), 'class' => $classes),
|
||||
array('data' => filter_xss_admin($source_field), 'class' => $classes),
|
||||
array('data' => filter_xss_admin($default), 'class' => $classes),
|
||||
array('data' => filter_xss_admin($mapping->getDescription()), 'class' => $classes),
|
||||
array('data' => filter_xss_admin($priority), 'class' => $classes),
|
||||
);
|
||||
$rows[] = $row;
|
||||
$classes = array();
|
||||
@ -973,7 +1003,7 @@ function migrate_migration_info($form, $form_state, $group_name, $migration_name
|
||||
*/
|
||||
function migrate_ui_edit_mappings($form, $form_state, $group_name,
|
||||
$migration_name) {
|
||||
drupal_set_title(t('Edit !migration', array('!migration' => $migration_name)));
|
||||
drupal_set_title(t('Edit !migration', array('!migration' => filter_xss_admin($migration_name))));
|
||||
|
||||
$form = array();
|
||||
$form['#tree'] = TRUE;
|
||||
@ -1014,6 +1044,9 @@ function migrate_ui_edit_mappings($form, $form_state, $group_name,
|
||||
'#suffix' => '</div>',
|
||||
);
|
||||
|
||||
// So the theme function knows whether to include the xpath column.
|
||||
$form['field_mappings']['#is_xml_migration'] = is_a($migration, 'XMLMigration');
|
||||
|
||||
$form['source_fields'] = array(
|
||||
'#type' => 'fieldset',
|
||||
'#title' => t('Source fields'),
|
||||
@ -1045,10 +1078,14 @@ function migrate_ui_edit_mappings($form, $form_state, $group_name,
|
||||
else {
|
||||
$label_format = '!description';
|
||||
}
|
||||
$label = t($label_format,
|
||||
array('!source_field' => $name, '!description' => $description));
|
||||
$short_label = t($label_format,
|
||||
array('!source_field' => $name, '!description' => $short_description));
|
||||
$label = t($label_format, array(
|
||||
'!source_field' => filter_xss_admin($name),
|
||||
'!description' => filter_xss_admin($description),
|
||||
));
|
||||
$short_label = t($label_format, array(
|
||||
'!source_field' => filter_xss_admin($name),
|
||||
'!description' => filter_xss_admin($short_description),
|
||||
));
|
||||
|
||||
$dnm_value = 0;
|
||||
|
||||
@ -1171,6 +1208,16 @@ function migrate_ui_edit_mappings($form, $form_state, $group_name,
|
||||
'#options' => $source_migration_options,
|
||||
'#default_value' => $source_migration,
|
||||
);
|
||||
|
||||
if (is_a($mapping, 'MigrateXMLFieldMapping')) {
|
||||
/** @var MigrateXMLFieldMapping $mapping */
|
||||
$form['field_mappings'][$name]['xpath'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#default_value' => $mapping->getXpath(),
|
||||
'#size' => 20,
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1213,7 +1260,7 @@ function migrate_ui_edit_mappings($form, $form_state, $group_name,
|
||||
}
|
||||
$form['dependencies'][$machine_name] = array(
|
||||
'#type' => 'select',
|
||||
'#title' => $machine_name,
|
||||
'#title' => check_plain($machine_name),
|
||||
'#default_value' => $default_value,
|
||||
'#options' => $dependency_options,
|
||||
);
|
||||
@ -1275,16 +1322,21 @@ function migrate_ui_edit_mappings_submit(&$form, &$form_state) {
|
||||
$field_mappings = array();
|
||||
$default_values = array();
|
||||
$issue_group_values = array();
|
||||
$xpaths = array();
|
||||
|
||||
$migration = Migration::getInstance($machine_name);
|
||||
if (is_a($migration, 'Migration')) {
|
||||
$xml = is_a($migration, 'XMLMigration') ? TRUE : FALSE;
|
||||
$existing_mappings = $migration->getFieldMappings();
|
||||
$coded_mappings = $migration->getCodedFieldMappings();
|
||||
foreach ($form_state['values']['field_mappings'] as $destination_field => $info) {
|
||||
// Treat an empty string for the default value as NULL.
|
||||
// Treat empty strings as NULL.
|
||||
if ($info['default_value'] === '') {
|
||||
$info['default_value'] = NULL;
|
||||
}
|
||||
if ($xml && $info['xpath'] === '') {
|
||||
$info['xpath'] = NULL;
|
||||
}
|
||||
|
||||
// If this mapping matches a coded mapping but not a stored mapping, remove
|
||||
// it entirely (don't store it in the database) so the coded mapping is not
|
||||
@ -1296,6 +1348,10 @@ function migrate_ui_edit_mappings_submit(&$form, &$form_state) {
|
||||
$coded_mappings[$destination_field]->getDefaultValue();
|
||||
$coded_source_migration =
|
||||
$coded_mappings[$destination_field]->getSourceMigration();
|
||||
if ($xml) {
|
||||
$coded_xpath =
|
||||
$coded_mappings[$destination_field]->getXpath();
|
||||
}
|
||||
if ($info['mapping'] == '-1') {
|
||||
$info['mapping'] = NULL;
|
||||
}
|
||||
@ -1312,6 +1368,7 @@ function migrate_ui_edit_mappings_submit(&$form, &$form_state) {
|
||||
if ($info['mapping'] == $coded_source_field &&
|
||||
$info['default_value'] == $coded_default_value &&
|
||||
$info['source_migration'] == $coded_source_migration &&
|
||||
(!$xml || ($xml && ($info['xpath'] == $coded_xpath))) &&
|
||||
$dnm_matches) {
|
||||
continue;
|
||||
}
|
||||
@ -1321,6 +1378,9 @@ function migrate_ui_edit_mappings_submit(&$form, &$form_state) {
|
||||
$default_values[$destination_field] = $info['default_value'];
|
||||
$source_migrations[$destination_field] = $info['source_migration'];
|
||||
$issue_group_values[$destination_field] = $info['issue_group'];
|
||||
if ($xml) {
|
||||
$xpaths[$destination_field] = $info['xpath'];
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($field_mappings as $destination_field => $source_field) {
|
||||
@ -1342,10 +1402,12 @@ function migrate_ui_edit_mappings_submit(&$form, &$form_state) {
|
||||
$mapping = NULL;
|
||||
if (isset($existing_mappings[$destination_field]) &&
|
||||
$issue_group_values[$destination_field] != 0) {
|
||||
/** @var MigrateFieldMapping $old_mapping */
|
||||
$old_mapping = $existing_mappings[$destination_field];
|
||||
if ($source_field == $old_mapping->getSourceField() &&
|
||||
$default_values[$destination_field] == $old_mapping->getDefaultValue() &&
|
||||
$source_migrations[$destination_field] == $old_mapping->getSourceMigration()) {
|
||||
$source_migrations[$destination_field] == $old_mapping->getSourceMigration() &&
|
||||
(!$xml || ($xml && ($xpaths[$destination_field] == $old_mapping->getXpath())))) {
|
||||
// First, if this mapping matches a previously-stored mapping, we want to
|
||||
// preserve it as it was originally stored.
|
||||
if ($old_mapping->getMappingSource() ==
|
||||
@ -1362,8 +1424,11 @@ function migrate_ui_edit_mappings_submit(&$form, &$form_state) {
|
||||
// We're not skipping this mapping, or preserving an old one, so create the
|
||||
// new mapping.
|
||||
if (!$mapping) {
|
||||
$mapping = new MigrateFieldMapping($destination_field, $source_field);
|
||||
$mapping = _migrate_ui_get_mapping_object($migration, $destination_field, $source_field);
|
||||
$mapping->defaultValue($default);
|
||||
if ($xml && $xpaths[$destination_field]) {
|
||||
$mapping->xpath($xpaths[$destination_field]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($issue_group_values[$destination_field]) {
|
||||
@ -1394,7 +1459,7 @@ function migrate_ui_edit_mappings_submit(&$form, &$form_state) {
|
||||
// If it is marked DNM in the UI, but is not ignored in the code,
|
||||
// generate a DNM mapping.
|
||||
if ($value && !$code_ignored) {
|
||||
$mapping = new MigrateFieldMapping(NULL, $source_field);
|
||||
$mapping = _migrate_ui_get_mapping_object($migration, NULL, $source_field);
|
||||
$mapping->issueGroup(t('DNM'));
|
||||
$arguments['field_mappings'][] = $mapping;
|
||||
}
|
||||
@ -1410,7 +1475,7 @@ function migrate_ui_edit_mappings_submit(&$form, &$form_state) {
|
||||
}
|
||||
}
|
||||
if (!$mapping_found) {
|
||||
$mapping = new MigrateFieldMapping(NULL, $source_field);
|
||||
$mapping = _migrate_ui_get_mapping_object($migration, NULL, $source_field);
|
||||
$arguments['field_mappings'][] = $mapping;
|
||||
}
|
||||
}
|
||||
@ -1436,6 +1501,22 @@ function migrate_ui_edit_mappings_submit(&$form, &$form_state) {
|
||||
"admin/content/migrate/groups/$group_name/$machine_name";
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a field mapping object of the appropriate class.
|
||||
*
|
||||
* @param $migration
|
||||
*
|
||||
* @return MigrateFieldMapping
|
||||
*/
|
||||
function _migrate_ui_get_mapping_object($migration, $destination, $source) {
|
||||
if (is_a($migration, 'XMLMigration')) {
|
||||
return new MigrateXMLFieldMapping($destination, $source);
|
||||
}
|
||||
else {
|
||||
return new MigrateFieldMapping($destination, $source);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Revert callback for the edit mappings form. Remove any field mappings that
|
||||
* were defined through the UI.
|
||||
@ -1469,6 +1550,9 @@ function theme_migrate_ui_field_mapping_form($variables) {
|
||||
if (!empty($elements)) {
|
||||
$header = array(t('DNM'), t('Destination field'), t('Source field'),
|
||||
t('Default value'), t('Source migration'));
|
||||
if (!empty($form['#is_xml_migration'])) {
|
||||
$header[] = t('Xpath');
|
||||
}
|
||||
$rows = array();
|
||||
foreach ($elements as $mapping_key) {
|
||||
$row = array();
|
||||
@ -1479,6 +1563,9 @@ function theme_migrate_ui_field_mapping_form($variables) {
|
||||
$row[] = drupal_render($form[$mapping_key]['mapping']);
|
||||
$row[] = drupal_render($form[$mapping_key]['default_value']);
|
||||
$row[] = drupal_render($form[$mapping_key]['source_migration']);
|
||||
if (!empty($form['#is_xml_migration'])) {
|
||||
$row[] = drupal_render($form[$mapping_key]['xpath']);
|
||||
}
|
||||
$rows[] = $row;
|
||||
}
|
||||
$output .= theme('table', array('header' => $header, 'rows' => $rows));
|
||||
@ -1536,7 +1623,11 @@ function migrate_ui_messages($group_name, $migration_name) {
|
||||
$header = array();
|
||||
// Add a table header for each source key in the migration's map.
|
||||
foreach ($source_key as $key => $map_info) {
|
||||
$header[] = array('data' => $map_info['description'], 'field' => $source_key_map[$key], 'sort' => 'asc');
|
||||
$header[] = array(
|
||||
'data' => filter_xss_admin($map_info['description']),
|
||||
'field' => $source_key_map[$key],
|
||||
'sort' => 'asc',
|
||||
);
|
||||
}
|
||||
|
||||
$header[] = array('data' => t('Level'), 'field' => 'level');
|
||||
@ -1558,12 +1649,18 @@ function migrate_ui_messages($group_name, $migration_name) {
|
||||
// Add a table column for each source key.
|
||||
foreach ($source_key_map_flipped as $source_key => $source_field) {
|
||||
$row[] = array(
|
||||
'data' => $message->{$source_key},
|
||||
'data' => filter_xss_admin($message->{$source_key}),
|
||||
'class' => $classes,
|
||||
);
|
||||
}
|
||||
$row[] = array('data' => $migration->getMessageLevelName($message->level), 'class' => $classes);
|
||||
$row[] = array('data' => $message->message, 'class' => $classes);
|
||||
$row[] = array(
|
||||
'data' => filter_xss_admin($migration->getMessageLevelName($message->level)),
|
||||
'class' => $classes,
|
||||
);
|
||||
$row[] = array(
|
||||
'data' => filter_xss_admin($message->message),
|
||||
'class' => $classes,
|
||||
);
|
||||
|
||||
$rows[] = $row;
|
||||
|
||||
@ -1642,7 +1739,10 @@ function migrate_ui_configure_form($form, &$form_state) {
|
||||
if (!class_exists($row->class_name)) {
|
||||
$migrations[] = $row->machine_name;
|
||||
$migration_list .= '<li>' . t('!migration (class !class)',
|
||||
array('!migration' => $row->machine_name, '!class' => $row->class_name)) . "</li>\n";
|
||||
array(
|
||||
'!migration' => filter_xss_admin($row->machine_name),
|
||||
'!class' => filter_xss_admin($row->class_name),
|
||||
)) . "</li>\n";
|
||||
}
|
||||
}
|
||||
|
||||
@ -1680,7 +1780,7 @@ function migrate_ui_configure_form($form, &$form_state) {
|
||||
// Configure background imports if the drush command has been set.
|
||||
$drush_path = trim(variable_get('migrate_drush_path', ''));
|
||||
$drush_validated = FALSE;
|
||||
if ($drush_path) {
|
||||
if ($drush_path && is_executable($drush_path)) {
|
||||
// Try running a drush status command to verify it's properly configured.
|
||||
$uri = $GLOBALS['base_url'];
|
||||
$uid = $GLOBALS['user']->uid;
|
||||
@ -1818,9 +1918,9 @@ function migrate_ui_configure_form($form, &$form_state) {
|
||||
->condition('type', 'class')
|
||||
->execute()
|
||||
->fetchField();
|
||||
$row['module'] = $module;
|
||||
$row['class'] = $class_name;
|
||||
$row['types'] = implode(', ', $handler->getTypesHandled());
|
||||
$row['module'] = check_plain($module);
|
||||
$row['class'] = check_plain($class_name);
|
||||
$row['types'] = filter_xss_admin(implode(', ', $handler->getTypesHandled()));
|
||||
$default_values[$class_name] = !in_array($class_name, $disabled);
|
||||
$rows[$class_name] = $row;
|
||||
}
|
||||
@ -1855,9 +1955,9 @@ function migrate_ui_configure_form($form, &$form_state) {
|
||||
->condition('type', 'class')
|
||||
->execute()
|
||||
->fetchField();
|
||||
$row['module'] = $module;
|
||||
$row['class'] = $class_name;
|
||||
$row['types'] = implode(', ', $handler->getTypesHandled());
|
||||
$row['module'] = check_plain($module);
|
||||
$row['class'] = check_plain($class_name);
|
||||
$row['types'] = filter_xss_admin(implode(', ', $handler->getTypesHandled()));
|
||||
$default_values[$class_name] = !in_array($class_name, $disabled);
|
||||
$rows[$class_name] = $row;
|
||||
}
|
||||
|
@ -216,7 +216,7 @@ class MigrateDestinationComment extends MigrateDestinationEntity {
|
||||
}
|
||||
|
||||
// Validate field data prior to saving.
|
||||
field_attach_validate('comment', $comment);
|
||||
MigrateDestinationEntity::fieldAttachValidate('comment', $comment);
|
||||
|
||||
migrate_instrument_start('comment_save');
|
||||
comment_save($comment);
|
||||
|
@ -176,4 +176,34 @@ abstract class MigrateDestinationEntity extends MigrateDestination {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform field validation against the field data in an entity. Wraps
|
||||
* field_attach_validate to handle exceptions cleanly and provide maximum
|
||||
* information for identifying the cause of validation errors.
|
||||
*
|
||||
* @param $entity_type
|
||||
* The type of $entity; e.g. 'node' or 'user'.
|
||||
* @param $entity
|
||||
* The entity with fields to validate.
|
||||
*/
|
||||
static public function fieldAttachValidate($entity_type, $entity) {
|
||||
try {
|
||||
field_attach_validate($entity_type, $entity);
|
||||
}
|
||||
catch (FieldValidationException $e) {
|
||||
$migration = Migration::currentMigration();
|
||||
foreach ($e->errors as $field_name => $field_errors) {
|
||||
foreach ($field_errors as $langcode => $errors) {
|
||||
foreach ($errors as $delta => $error_list) {
|
||||
foreach ($error_list as $index => $error) {
|
||||
$message = $error['message'];
|
||||
$migration->saveMessage(t('Field validation error for !field_name: !message',
|
||||
array('!field_name' => $field_name, '!message' => $message)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -342,8 +342,11 @@ class MigrateTextFieldHandler extends MigrateFieldHandler {
|
||||
$fields['format'] = t('Subfield: <a href="@doc">Text format for the field</a>',
|
||||
array('@doc' => 'http://drupal.org/node/1224042#format'));
|
||||
}
|
||||
$fields['language'] = t('Subfield: <a href="@doc">Language for the field</a>',
|
||||
array('@doc' => 'http://drupal.org/node/1224042#language'));
|
||||
$field = field_info_field($instance['field_name']);
|
||||
if (field_is_translatable($instance['entity_type'], $field)) {
|
||||
$fields['language'] = t('Subfield: <a href="@doc">Language for the field</a>',
|
||||
array('@doc' => 'http://drupal.org/node/1224042#language'));
|
||||
}
|
||||
return $fields;
|
||||
}
|
||||
|
||||
@ -469,7 +472,7 @@ class MigrateTaxonomyTermReferenceFieldHandler extends MigrateFieldHandler {
|
||||
else {
|
||||
$arguments = array();
|
||||
}
|
||||
if (empty($values[0])) {
|
||||
if (count($values) == 1 && empty($values[0])) {
|
||||
$values = array();
|
||||
}
|
||||
|
||||
@ -530,7 +533,7 @@ class MigrateTaxonomyTermReferenceFieldHandler extends MigrateFieldHandler {
|
||||
// This term is being created with no fields, but we should still call
|
||||
// field_attach_validate() before saving, as that invokes
|
||||
// hook_field_attach_validate().
|
||||
field_attach_validate('taxonomy_term', $new_term);
|
||||
MigrateDestinationEntity::fieldAttachValidate('taxonomy_term', $new_term);
|
||||
|
||||
taxonomy_term_save($new_term);
|
||||
$tids[] = $new_term->tid;
|
||||
@ -588,9 +591,13 @@ abstract class MigrateFileFieldBaseHandler extends MigrateFieldHandler {
|
||||
$fields = array(
|
||||
'file_class' => t('Option: <a href="@doc">Implementation of MigrateFile to use</a>',
|
||||
array('@doc' => 'http://drupal.org/node/1540106#file_class')),
|
||||
'language' => t('Subfield: Language for the field'),
|
||||
);
|
||||
|
||||
$field = field_info_field($instance['field_name']);
|
||||
if (field_is_translatable($instance['entity_type'], $field)) {
|
||||
$fields['language'] = t('Subfield: Language for the field');
|
||||
}
|
||||
|
||||
// If we can identify the file class mapped to this field, pick up the
|
||||
// subfields specific to that class.
|
||||
if ($migration) {
|
||||
|
@ -389,15 +389,16 @@ class MigrateFileUri extends MigrateFile {
|
||||
// Perform the copy operation, with a cleaned-up path.
|
||||
$this->sourcePath = self::urlencode($this->sourcePath);
|
||||
}
|
||||
if (!@copy($this->sourcePath, $destination)) {
|
||||
$migration = Migration::currentMigration();
|
||||
$migration->saveMessage(t('The specified file %file could not be copied to %destination.',
|
||||
array('%file' => $this->sourcePath, '%destination' => $destination)));
|
||||
return FALSE;
|
||||
}
|
||||
else {
|
||||
try {
|
||||
copy($this->sourcePath, $destination);
|
||||
return TRUE;
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$migration = Migration::currentMigration();
|
||||
$migration->saveMessage(t('The specified file %file could not be copied to %destination: "%exception_msg"',
|
||||
array('%file' => $this->sourcePath, '%destination' => $destination, '%exception_msg' => $e->getMessage())));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -263,7 +263,7 @@ class MigrateDestinationNode extends MigrateDestinationEntity {
|
||||
}
|
||||
|
||||
// Validate field data prior to saving.
|
||||
field_attach_validate('node', $node);
|
||||
MigrateDestinationEntity::fieldAttachValidate('node', $node);
|
||||
|
||||
migrate_instrument_start('node_save');
|
||||
node_save($node);
|
||||
|
@ -258,7 +258,7 @@ class MigrateDestinationTerm extends MigrateDestinationEntity {
|
||||
}
|
||||
|
||||
// Validate field data prior to saving.
|
||||
field_attach_validate('taxonomy_term', $term);
|
||||
MigrateDestinationEntity::fieldAttachValidate('taxonomy_term', $term);
|
||||
|
||||
migrate_instrument_start('taxonomy_term_save');
|
||||
$status = taxonomy_term_save($term);
|
||||
|
@ -231,7 +231,7 @@ class MigrateDestinationUser extends MigrateDestinationEntity {
|
||||
}
|
||||
|
||||
// Validate field data prior to saving.
|
||||
field_attach_validate('user', $account);
|
||||
MigrateDestinationEntity::fieldAttachValidate('user', $account);
|
||||
|
||||
migrate_instrument_start('user_save');
|
||||
$newaccount = user_save($old_account, (array)$account);
|
||||
|
@ -198,8 +198,8 @@ class MigrateSourceList extends MigrateSource {
|
||||
list(, $id) = each($ids);
|
||||
$row->$key_name = $id;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return $row;
|
||||
}
|
||||
|
@ -187,8 +187,8 @@ class MigrateSourceMultiItems extends MigrateSource {
|
||||
$sourceKey = $this->activeMap->getSourceKey();
|
||||
$key_name = key($sourceKey);
|
||||
$row->$key_name = $id;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return $row;
|
||||
}
|
||||
|
@ -376,14 +376,29 @@ class MigrateSourceSQL extends MigrateSource {
|
||||
// 3. If we are using highwater marks, also include rows above the mark.
|
||||
// But, include all rows if the highwater mark is not set.
|
||||
if (isset($this->highwaterField['name']) && $this->activeMigration->getHighwater() !== '') {
|
||||
if (isset($this->highwaterField['alias'])) {
|
||||
$highwater = $this->highwaterField['alias'] . '.' . $this->highwaterField['name'];
|
||||
// But, if there are any existing items marked as needing update which
|
||||
// fall below the highwater mark, and map_joinable is FALSE, those
|
||||
// items will be skipped. Thus, in that case do not add the highwater
|
||||
// optimization to the query.
|
||||
$add_highwater_condition = TRUE;
|
||||
if (!$this->mapJoinable) {
|
||||
$count_needs_update = db_query('SELECT COUNT(*) FROM {' .
|
||||
$this->activeMap->getQualifiedMapTable() . '} WHERE needs_update = 1')
|
||||
->fetchField();
|
||||
if ($count_needs_update > 0) {
|
||||
$add_highwater_condition = FALSE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$highwater = $this->highwaterField['name'];
|
||||
if ($add_highwater_condition) {
|
||||
if (isset($this->highwaterField['alias'])) {
|
||||
$highwater = $this->highwaterField['alias'] . '.' . $this->highwaterField['name'];
|
||||
}
|
||||
else {
|
||||
$highwater = $this->highwaterField['name'];
|
||||
}
|
||||
$conditions->condition($highwater, $this->activeMigration->getHighwater(), '>');
|
||||
$condition_added = TRUE;
|
||||
}
|
||||
$conditions->condition($highwater, $this->activeMigration->getHighwater(), '>');
|
||||
$condition_added = TRUE;
|
||||
}
|
||||
if ($condition_added) {
|
||||
$this->query->condition($conditions);
|
||||
|
@ -69,6 +69,11 @@ class MigrateSQLMap extends MigrateMap {
|
||||
*/
|
||||
protected $ensured;
|
||||
|
||||
/**
|
||||
* Provide caching for Source or Desination Map Lookups.
|
||||
*/
|
||||
protected $cacheMapLookups;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
@ -92,6 +97,13 @@ class MigrateSQLMap extends MigrateMap {
|
||||
$this->trackLastImported = TRUE;
|
||||
}
|
||||
|
||||
if (isset($options['cache_map_lookups'])) {
|
||||
$this->cacheMapLookups = $options['cache_map_lookups'];
|
||||
}
|
||||
else {
|
||||
$this->cacheMapLookups = FALSE;
|
||||
}
|
||||
|
||||
$this->connection = Database::getConnection('default', $connection_key);
|
||||
|
||||
// Default generated table names, limited to 63 characters
|
||||
@ -302,6 +314,16 @@ class MigrateSQLMap extends MigrateMap {
|
||||
*/
|
||||
public function lookupSourceID(array $destination_id) {
|
||||
migrate_instrument_start('lookupSourceID');
|
||||
// Try a cache lookup if enabled.
|
||||
if ($this->cacheMapLookups) {
|
||||
$cache = &drupal_static($this->mapTable . '_sourceIDCache');
|
||||
$serialized = json_encode($destination_id);
|
||||
if (isset($cache[$serialized])) {
|
||||
migrate_instrument_stop('lookupSourceID');
|
||||
return $cache[$serialized];
|
||||
}
|
||||
}
|
||||
|
||||
$query = $this->connection->select($this->mapTable, 'map')
|
||||
->fields('map', $this->sourceKeyMap);
|
||||
foreach ($this->destinationKeyMap as $key_name) {
|
||||
@ -309,6 +331,12 @@ class MigrateSQLMap extends MigrateMap {
|
||||
}
|
||||
$result = $query->execute();
|
||||
$source_id = $result->fetchAssoc();
|
||||
|
||||
// Store the id in a cache if enabled.
|
||||
if ($this->cacheMapLookups) {
|
||||
$cache[$serialized] = $destination_id;
|
||||
}
|
||||
|
||||
migrate_instrument_stop('lookupSourceID');
|
||||
return $source_id;
|
||||
}
|
||||
@ -324,6 +352,16 @@ class MigrateSQLMap extends MigrateMap {
|
||||
*/
|
||||
public function lookupDestinationID(array $source_id) {
|
||||
migrate_instrument_start('lookupDestinationID');
|
||||
// Try a cache lookup if enabled.
|
||||
if ($this->cacheMapLookups) {
|
||||
$cache = &drupal_static($this->mapTable . '_destinationIDCache');
|
||||
$serialized = json_encode($source_id);
|
||||
if (isset($cache[$serialized])) {
|
||||
migrate_instrument_stop('lookupDestinationID');
|
||||
return $cache[$serialized];
|
||||
}
|
||||
}
|
||||
|
||||
$query = $this->connection->select($this->mapTable, 'map')
|
||||
->fields('map', $this->destinationKeyMap);
|
||||
foreach ($this->sourceKeyMap as $key_name) {
|
||||
@ -331,10 +369,15 @@ class MigrateSQLMap extends MigrateMap {
|
||||
}
|
||||
$result = $query->execute();
|
||||
$destination_id = $result->fetchAssoc();
|
||||
|
||||
// Store the id in a cache if enabled.
|
||||
if ($this->cacheMapLookups) {
|
||||
$cache[$serialized] = $destination_id;
|
||||
}
|
||||
|
||||
migrate_instrument_stop('lookupDestinationID');
|
||||
return $destination_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called upon import of one record, we record a mapping from the source key
|
||||
* to the destination key. Also may be called, setting the third parameter to
|
||||
|
@ -40,17 +40,13 @@ class MigrateImportOptionsTest extends DrupalWebTestCase {
|
||||
|
||||
$result = $migration->processImport($options);
|
||||
|
||||
$this->verbose(print_r($timers, 1));
|
||||
$successes = $migration->importedCount();
|
||||
$this->verbose("Total successes: {$successes}");
|
||||
$assertion = format_plural($limit, 'The migration successfully processed 1 item.',
|
||||
'The migration successfully processed @count items.');
|
||||
$this->assertEqual($limit, $successes, $assertion);
|
||||
|
||||
$prepare_row_count = $timers['BeerTermMigration prepareRow']['count'];
|
||||
$this->verbose("prepareRow() count: {$prepare_row_count}");
|
||||
$processed = $migration->processedCount();
|
||||
$this->verbose("Total processed count: {$processed}");
|
||||
$assertion = format_plural($processed, 'The migration executed processRow() on 1 item.',
|
||||
'The migration executed processRow() on @count items.');
|
||||
$this->assertEqual($prepare_row_count, $processed, $assertion);
|
||||
|
@ -18,6 +18,7 @@ function views_bulk_operations_archive_action_info() {
|
||||
// "Create an advanced action" dropdown on admin/config/system/actions.
|
||||
'configurable' => FALSE,
|
||||
'vbo_configurable' => TRUE,
|
||||
'behavior' => array('views_property'),
|
||||
'triggers' => array('any'),
|
||||
);
|
||||
}
|
||||
|
@ -13,11 +13,13 @@ function views_bulk_operations_book_action_info() {
|
||||
'label' => t('Move to book'),
|
||||
'configurable' => TRUE,
|
||||
'behavior' => array('changes_property'),
|
||||
'triggers' => array('any'),
|
||||
);
|
||||
$actions['views_bulk_operations_remove_from_book_action'] = array(
|
||||
'type' => 'node',
|
||||
'label' => t('Remove from book'),
|
||||
'configurable' => FALSE,
|
||||
'triggers' => array('any'),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@ function views_bulk_operations_delete_action_info() {
|
||||
'label' => t('Delete revision'),
|
||||
'configurable' => FALSE,
|
||||
'behavior' => array('deletes_property'),
|
||||
'triggers' => array('any'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -82,6 +82,11 @@ function views_bulk_operations_modify_action($entity, $context) {
|
||||
// The wrapper will automatically modify $entity itself.
|
||||
$wrapper = entity_metadata_wrapper($context['entity_type'], $entity);
|
||||
foreach ($context['selected']['properties'] as $key) {
|
||||
if (!$wrapper->$key->access('update')) {
|
||||
// No access.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (in_array($key, $context['append']['properties'])) {
|
||||
$old_values = $wrapper->$key->value();
|
||||
$wrapper->$key->set($context['properties'][$key]);
|
||||
@ -134,7 +139,7 @@ function views_bulk_operations_modify_action_form($context, &$form_state) {
|
||||
if (!empty($properties)) {
|
||||
$form['properties'] = array(
|
||||
'#type' => 'fieldset',
|
||||
'#title' => 'Properties',
|
||||
'#title' => t('Properties'),
|
||||
);
|
||||
$form['properties']['show_value'] = array(
|
||||
'#suffix' => '<div class="clearfix"></div>',
|
||||
@ -298,7 +303,7 @@ function views_bulk_operations_modify_action_form($context, &$form_state) {
|
||||
$token_type = str_replace('_', '-', $entity_type);
|
||||
$form['tokens'] = array(
|
||||
'#type' => 'fieldset',
|
||||
'#title' => 'Available tokens',
|
||||
'#title' => t('Available tokens'),
|
||||
'#collapsible' => TRUE,
|
||||
'#collapsed' => TRUE,
|
||||
'#weight' => 998,
|
||||
|
@ -10,6 +10,7 @@ function views_bulk_operations_user_cancel_action_info() {
|
||||
'label' => t('Cancel user account'),
|
||||
'configurable' => TRUE,
|
||||
'behavior' => array('deletes_property'),
|
||||
'triggers' => array('any'),
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -45,24 +45,19 @@ function views_bulk_operations_user_roles_action_submit($form, $form_state) {
|
||||
);
|
||||
}
|
||||
|
||||
function views_bulk_operations_user_roles_action(&$user, $context) {
|
||||
$roles = $user->roles;
|
||||
$selected = (is_array($context['add_roles']) ? $context['add_roles'] : array()) +
|
||||
(is_array($context['remove_roles']) ? $context['remove_roles'] : array());
|
||||
$result = db_query("SELECT rid, name FROM {role} WHERE rid IN (:selected)", array(':selected' => array_keys($selected)));
|
||||
foreach ($result as $role) {
|
||||
if (isset($context['add_roles'][$role->rid])) {
|
||||
$add_roles[$role->rid] = $role->name;
|
||||
}
|
||||
if (isset($context['remove_roles'][$role->rid])) {
|
||||
$remove_roles[$role->rid] = $role->name;
|
||||
}
|
||||
function views_bulk_operations_user_roles_action($user, $context) {
|
||||
$wrapper = entity_metadata_wrapper('user', $user);
|
||||
if (!$wrapper->roles->access("update")) {
|
||||
// No access.
|
||||
return;
|
||||
}
|
||||
if (!empty($add_roles)) {
|
||||
$roles += $add_roles;
|
||||
$roles = $wrapper->roles->value();
|
||||
if (is_array($context['add_roles'])) {
|
||||
$roles = array_merge($roles, $context['add_roles']);
|
||||
}
|
||||
if (!empty($remove_roles)) {
|
||||
$roles = array_diff($roles, $remove_roles);
|
||||
if (is_array($context['remove_roles'])) {
|
||||
$roles = array_diff($roles, $context['remove_roles']);
|
||||
}
|
||||
user_save($user, array('roles' => $roles));
|
||||
$wrapper->roles->set($roles);
|
||||
$wrapper->save();
|
||||
}
|
||||
|
@ -3,9 +3,9 @@ description = Provides permission-based access control for actions. Used by View
|
||||
package = Administration
|
||||
core = 7.x
|
||||
|
||||
; Information added by Drupal.org packaging script on 2013-12-23
|
||||
version = "7.x-3.2"
|
||||
; Information added by Drupal.org packaging script on 2015-07-01
|
||||
version = "7.x-3.3"
|
||||
core = "7.x"
|
||||
project = "views_bulk_operations"
|
||||
datestamp = "1387798183"
|
||||
datestamp = "1435764542"
|
||||
|
||||
|
@ -46,21 +46,23 @@
|
||||
});
|
||||
|
||||
// Set up the ability to click anywhere on the row to select it.
|
||||
$('.views-table tbody tr', form).click(function(event) {
|
||||
if (event.target.tagName.toLowerCase() != 'input' && event.target.tagName.toLowerCase() != 'a') {
|
||||
$('input[id^="edit-views-bulk-operations"]:not(:disabled)', this).each(function() {
|
||||
var checked = this.checked;
|
||||
// trigger() toggles the checkmark *after* the event is set,
|
||||
// whereas manually clicking the checkbox toggles it *beforehand*.
|
||||
// that's why we manually set the checkmark first, then trigger the
|
||||
// event (so that listeners get notified), then re-set the checkmark
|
||||
// which the trigger will have toggled. yuck!
|
||||
this.checked = !checked;
|
||||
$(this).trigger('click');
|
||||
this.checked = !checked;
|
||||
});
|
||||
}
|
||||
});
|
||||
if (Drupal.settings.vbo.row_clickable) {
|
||||
$('.views-table tbody tr', form).click(function(event) {
|
||||
if (event.target.tagName.toLowerCase() != 'input' && event.target.tagName.toLowerCase() != 'a') {
|
||||
$('input[id^="edit-views-bulk-operations"]:not(:disabled)', this).each(function() {
|
||||
var checked = this.checked;
|
||||
// trigger() toggles the checkmark *after* the event is set,
|
||||
// whereas manually clicking the checkbox toggles it *beforehand*.
|
||||
// that's why we manually set the checkmark first, then trigger the
|
||||
// event (so that listeners get notified), then re-set the checkmark
|
||||
// which the trigger will have toggled. yuck!
|
||||
this.checked = !checked;
|
||||
$(this).trigger('click');
|
||||
this.checked = !checked;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Drupal.vbo.tableSelectAllPages = function(form) {
|
||||
|
@ -20,7 +20,7 @@ class ViewsBulkOperationsAction extends ViewsBulkOperationsBaseOperation {
|
||||
*/
|
||||
public function getAccessMask() {
|
||||
// Assume edit by default.
|
||||
if (!isset($this->operationInfo['behavior'])) {
|
||||
if (empty($this->operationInfo['behavior'])) {
|
||||
$this->operationInfo['behavior'] = array('changes_property');
|
||||
}
|
||||
|
||||
|
@ -124,6 +124,8 @@ class ViewsBulkOperationsRulesComponent extends ViewsBulkOperationsBaseOperation
|
||||
else {
|
||||
$element = rules_action('component_' . $this->operationInfo['parameters']['component_key']);
|
||||
}
|
||||
$element->execute($data);
|
||||
$wrapper_type = is_array($data) ? "list<{$this->entityType}>" : $this->entityType;
|
||||
$wrapper = entity_metadata_wrapper($wrapper_type, $data);
|
||||
$element->execute($wrapper);
|
||||
}
|
||||
}
|
||||
|
@ -55,6 +55,7 @@ class views_bulk_operations_handler_field_operations extends views_handler_field
|
||||
'contains' => array(
|
||||
'display_type' => array('default' => 0),
|
||||
'enable_select_all_pages' => array('default' => TRUE),
|
||||
'row_clickable' => array('default' => TRUE),
|
||||
'force_single' => array('default' => FALSE),
|
||||
'entity_load_capacity' => array('default' => 10),
|
||||
'skip_batching' => array('default' => 0),
|
||||
@ -63,11 +64,26 @@ class views_bulk_operations_handler_field_operations extends views_handler_field
|
||||
$options['vbo_operations'] = array(
|
||||
'default' => array(),
|
||||
'unpack_translatable' => 'unpack_operations',
|
||||
'export' => 'export_vbo_operations',
|
||||
);
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
function export_vbo_operations($indent, $prefix, $storage, $option, $definition, $parents) {
|
||||
// Anti-recursion, since we use the parent export helper.
|
||||
unset($definition['export']);
|
||||
|
||||
// Find and remove all unselected/disabled operations.
|
||||
foreach ($storage['vbo_operations'] as $operation_id => $operation) {
|
||||
if (empty($operation['selected'])) {
|
||||
unset($storage['vbo_operations'][$operation_id]);
|
||||
}
|
||||
}
|
||||
|
||||
return parent::export_option($indent, $prefix, $storage, $option, $definition, $parents);
|
||||
}
|
||||
|
||||
function unpack_operations(&$translatable, $storage, $option, $definition, $parents, $keys) {
|
||||
$translatable[] = array(
|
||||
'value' => t('- Choose an operation -'),
|
||||
@ -107,6 +123,12 @@ class views_bulk_operations_handler_field_operations extends views_handler_field
|
||||
'#default_value' => $this->options['vbo_settings']['enable_select_all_pages'],
|
||||
'#description' => t('Check this box to enable the ability to select all items on all pages.'),
|
||||
);
|
||||
$form['vbo_settings']['row_clickable'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Make the whole row clickable'),
|
||||
'#default_value' => $this->options['vbo_settings']['row_clickable'],
|
||||
'#description' => t('Check this box to select an item when its row has been clicked. Requires JavaScript.'),
|
||||
);
|
||||
$form['vbo_settings']['force_single'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Force single'),
|
||||
|
@ -9,9 +9,9 @@ php = 5.2.9
|
||||
files[] = plugins/operation_types/base.class.php
|
||||
files[] = views/views_bulk_operations_handler_field_operations.inc
|
||||
|
||||
; Information added by Drupal.org packaging script on 2013-12-23
|
||||
version = "7.x-3.2"
|
||||
; Information added by Drupal.org packaging script on 2015-07-01
|
||||
version = "7.x-3.3"
|
||||
core = "7.x"
|
||||
project = "views_bulk_operations"
|
||||
datestamp = "1387798183"
|
||||
datestamp = "1435764542"
|
||||
|
||||
|
@ -41,21 +41,20 @@ function views_bulk_operations_load_action_includes() {
|
||||
// The list of VBO actions is fairly static, so it's hardcoded for better
|
||||
// performance (hitting the filesystem with file_scan_directory(), and then
|
||||
// caching the result has its cost).
|
||||
$path = drupal_get_path('module', 'views_bulk_operations') . '/actions/';
|
||||
$files = array(
|
||||
'archive.action.inc',
|
||||
'argument_selector.action.inc',
|
||||
'book.action.inc',
|
||||
'delete.action.inc',
|
||||
'modify.action.inc',
|
||||
'script.action.inc',
|
||||
'user_roles.action.inc',
|
||||
'user_cancel.action.inc',
|
||||
'archive.action',
|
||||
'argument_selector.action',
|
||||
'book.action',
|
||||
'delete.action',
|
||||
'modify.action',
|
||||
'script.action',
|
||||
'user_roles.action',
|
||||
'user_cancel.action',
|
||||
);
|
||||
|
||||
if (!$loaded) {
|
||||
foreach ($files as $file) {
|
||||
include_once $path . $file;
|
||||
module_load_include('inc', 'views_bulk_operations', 'actions/' . $file);
|
||||
}
|
||||
$loaded = TRUE;
|
||||
}
|
||||
@ -77,7 +76,7 @@ function views_bulk_operations_load_action_includes() {
|
||||
function views_bulk_operations_cron() {
|
||||
db_delete('queue')
|
||||
->condition('name', db_like('views_bulk_operations_active_queue_'), 'LIKE')
|
||||
->condition('created', REQUEST_TIME - 864000, '<')
|
||||
->condition('created', REQUEST_TIME - 86400, '<')
|
||||
->execute();
|
||||
}
|
||||
|
||||
@ -358,7 +357,7 @@ function views_bulk_operations_form_alter(&$form, &$form_state, $form_id) {
|
||||
*/
|
||||
function views_bulk_operations_views_post_build(&$view) {
|
||||
$vbo = _views_bulk_operations_get_field($view);
|
||||
if ($vbo && $vbo->get_selected_operations() < 1) {
|
||||
if ($vbo && count($vbo->get_selected_operations()) < 1) {
|
||||
$vbo->options['exclude'] = TRUE;
|
||||
}
|
||||
}
|
||||
@ -420,7 +419,7 @@ function theme_views_bulk_operations_select_all($variables) {
|
||||
if ($enable_select_all_pages) {
|
||||
$form['select_all']['or'] = array(
|
||||
'#type' => 'markup',
|
||||
'#markup' => '<em>OR</em>',
|
||||
'#markup' => '<em>' . t('OR') . '</em>',
|
||||
);
|
||||
$form['select_all']['all_pages'] = array(
|
||||
'#type' => 'checkbox',
|
||||
@ -443,6 +442,13 @@ function theme_views_bulk_operations_select_all($variables) {
|
||||
*/
|
||||
function views_bulk_operations_form($form, &$form_state, $vbo) {
|
||||
$form['#attached']['js'][] = drupal_get_path('module', 'views_bulk_operations') . '/js/views_bulk_operations.js';
|
||||
$form['#attached']['js'][] = array(
|
||||
'data' => array('vbo' => array(
|
||||
'row_clickable' => $vbo->get_vbo_option('row_clickable'),
|
||||
)),
|
||||
'type' => 'setting',
|
||||
);
|
||||
|
||||
$form['#attached']['css'][] = drupal_get_path('module', 'views_bulk_operations') . '/css/views_bulk_operations.css';
|
||||
// Wrap the form in a div with specific classes for JS targeting and theming.
|
||||
$class = 'vbo-views-form';
|
||||
@ -595,14 +601,23 @@ function views_bulk_operations_confirm_form($form, &$form_state, $view, $output)
|
||||
$operation = $form_state['operation'];
|
||||
$rows = $form_state['selection'];
|
||||
$query = drupal_get_query_parameters($_GET, array('q'));
|
||||
$title = t('Are you sure you want to perform %operation on the selected items?', array('%operation' => $operation->label()));
|
||||
$form = confirm_form($form,
|
||||
t('Are you sure you want to perform %operation on the selected items?', array('%operation' => $operation->label())),
|
||||
$title,
|
||||
array('path' => $view->get_url(), 'query' => $query),
|
||||
theme('views_bulk_operations_confirmation', array('rows' => $rows, 'vbo' => $vbo, 'operation' => $operation, 'select_all_pages' => $form_state['select_all_pages']))
|
||||
);
|
||||
// Add VBO's submit handler to the Confirm button added by config_form().
|
||||
$form['actions']['submit']['#submit'] = array('views_bulk_operations_form_submit');
|
||||
|
||||
// We can't set the View title here as $view is just a copy of the original,
|
||||
// and our settings changes won't "stick" for the first page load of the
|
||||
// confirmation form. We also can't just call drupal_set_title() directly
|
||||
// because our title will be clobbered by the actual View title later. So
|
||||
// let's tuck the title away in the form for use later.
|
||||
// @see views_bulk_operations_preprocess_views_view()
|
||||
$form['#vbo_confirm_form_title'] = $title;
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
@ -618,7 +633,7 @@ function theme_views_bulk_operations_confirmation($variables) {
|
||||
// Load the entities from the current page, and show their titles.
|
||||
$entities = _views_bulk_operations_entity_load($entity_type, array_values($rows), $vbo->revision);
|
||||
foreach ($entities as $entity) {
|
||||
$items[] = check_plain(_views_bulk_operations_entity_label($entity_type, $entity));
|
||||
$items[] = check_plain(entity_label($entity_type, $entity));
|
||||
}
|
||||
// All rows on all pages have been selected, so show a count of additional items.
|
||||
if ($select_all_pages) {
|
||||
@ -631,6 +646,29 @@ function theme_views_bulk_operations_confirmation($variables) {
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_preprocess_page().
|
||||
*
|
||||
* Hide action links on the configure and confirm pages.
|
||||
*/
|
||||
function views_bulk_operations_preprocess_page(&$variables) {
|
||||
if (isset($_POST['select_all'], $_POST['operation'])) {
|
||||
$variables['action_links'] = array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_preprocess_views_view().
|
||||
*/
|
||||
function views_bulk_operations_preprocess_views_view($variables) {
|
||||
// If we've stored a title for the confirmation form, retrieve it here and
|
||||
// retitle the View.
|
||||
// @see views_bulk_operations_confirm_form()
|
||||
if (array_key_exists('rows', $variables) && is_array($variables['rows']) && array_key_exists('#vbo_confirm_form_title', $variables['rows'])) {
|
||||
$variables['view']->set_title($variables['rows']['#vbo_confirm_form_title']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Goes through the submitted values, and returns
|
||||
* an array of selected rows, in the form of
|
||||
@ -871,7 +909,7 @@ function views_bulk_operations_adjust_selection($queue_name, $operation, $option
|
||||
'views_row' => array(),
|
||||
'position' => array(
|
||||
'current' => ++$context['sandbox']['progress'],
|
||||
'total' => $view->total_rows,
|
||||
'total' => $context['sandbox']['max'],
|
||||
),
|
||||
);
|
||||
// Some operations require full selected rows.
|
||||
@ -1042,7 +1080,7 @@ function views_bulk_operations_queue_item_process($queue_item_data, &$log = NULL
|
||||
$arguments = array(
|
||||
'%operation' => $operation->label(),
|
||||
'@type' => $entity_type,
|
||||
'%title' => _views_bulk_operations_entity_label($entity_type, $entity),
|
||||
'%title' => entity_label($entity_type, $entity),
|
||||
);
|
||||
|
||||
if ($log) {
|
||||
@ -1128,7 +1166,7 @@ function views_bulk_operations_direct_process($operation, $rows, $options) {
|
||||
$context['results']['log'][] = t('Skipped %operation on @type %title due to insufficient permissions.', array(
|
||||
'%operation' => $operation->label(),
|
||||
'@type' => $entity_type,
|
||||
'%title' => _views_bulk_operations_entity_label($entity_type, $entity),
|
||||
'%title' => entity_label($entity_type, $entity),
|
||||
));
|
||||
unset($entities[$id]);
|
||||
}
|
||||
@ -1236,29 +1274,6 @@ function _views_bulk_operations_entity_load($entity_type, $ids, $revision = FALS
|
||||
return $entities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Label function for entities.
|
||||
* Core entities don't declare the "label" key, so entity_label() fails,
|
||||
* and a fallback is needed. This function provides that fallback.
|
||||
*/
|
||||
function _views_bulk_operations_entity_label($entity_type, $entity) {
|
||||
$label = entity_label($entity_type, $entity);
|
||||
if (!$label) {
|
||||
$entity_info = entity_get_info($entity_type);
|
||||
$id_key = $entity_info['entity keys']['id'];
|
||||
// Many entity types (e.g. "user") have a name which fits the label perfectly.
|
||||
if (isset($entity->name)) {
|
||||
$label = $entity->name;
|
||||
}
|
||||
elseif (isset($entity->{$id_key})) {
|
||||
// Fallback to the id key.
|
||||
$label = $entity->{$id_key};
|
||||
}
|
||||
}
|
||||
|
||||
return $label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to report an error.
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user