diff --git a/sites/all/modules/contrib/content/diff/CHANGELOG.txt b/sites/all/modules/contrib/content/diff/CHANGELOG.txt deleted file mode 100644 index 38696432..00000000 --- a/sites/all/modules/contrib/content/diff/CHANGELOG.txt +++ /dev/null @@ -1,166 +0,0 @@ - -CHANGELOG for Diff 7.x-2.0+13-dev to 7.x-3.x -============================================ - -1) System variable names have been changed ------------------------------------------- - -Considerable changes have occurred. - -2) hook_diff() was removed --------------------------- - -This has been replaced by hook_entity_diff() as of Diff 7.x-3.x. - -3) Field diffs are handled independently by Diff and the field module ---------------------------------------------------------------------- - -Field modules SHOULD NOT implement hook_entity_diff(). - -This is complicated and costly in terms of performance. - -Two new field callbacks are defined to handle these. - - a) MODULE_field_diff_view_prepare() - - Optional: If you need to load data, use MODULE_field_diff_view_prepare(). - - b) MODULE_field_diff_view() - - Recommended: You should implement this to generate the compared data. - -If there is no corresponding hook for a field, the field comparison will try -to guess the value using $item['safe_value'] or $item['value'] properties. - -If you need to make this configurable, there are two additional hooks: - - c) MODULE_field_diff_default_options($field_type) - - You should define any additioal settings here. This shares a global namespace - of the diff module, so you can overwrite core Diff settings here too. - - In saying that, take care not to accidentially do this. - - d) MODULE_field_diff_options_form($field_type, $settings) - - This is where you insert Form API elements to configure your option settings. - -4) Field diffs are now configurable ------------------------------------ - -Each field type defined by core have configurable settings to control the -rendering of the comparison. - - a) Global configuration - - An administration page has been added to handle field type default settings. - - This is the preferred way to configure field settings are these are global to - all fields of this type. - - b) View mode display options - - The display "Diff comparison" is used to control the fields that are displayed - when comparing different revisions. - - The following is a walk-through on how you would configure the Basic page - (page) content types field configuration. - - - Enable "Diff comparison" custom view mode - - Navigate to admin/structure/types/manage/page/display and look at the - Custom Display Settings for this view mode. Check and save. - - - Configure the display - - After Saving this page, a new tab appears "Diff comparison", click this or - navigate directly to admin/structure/types/manage/page/display/diff_standard - - - You can hide or show the fields that you want to display when doing - comparisons. - - If the field has no inbuilt diff support, then the renderred field items - will be compared. - -5) Standard comparison preview / Inline diff view setting ---------------------------------------------------------- - -You can set the view modes used to compare the rendered node. This can be found -in the Diff settings in the Content Type settings page. - -6) Optional CSS and new Boxes styles ------------------------------------- - -This takes the styles from WikiPedia to really spice up the diff page. - -7) Optional JScript extras --------------------------- - -This spices up the revision checkboxes on the revisions page. - -8) Simple past revision token support -------------------------------------- - -Use-case, email notifications when content has changes. If these support tokens, -then you can embed Diffs into these emails. - -9) Extensive string review --------------------------- -See http://drupal.org/node/1785742 - - -10) Inline block settings changes ---------------------------------- -The inline block settings are now in the block configuration page. - -11) And much more... --------------------- - -The complete change log follows: - -Diff 7.x-2.x - o #888680 by Deciphered, Alan D.: Allow modules to interact via drupal_alter() - o #1280892 by Alan D., crea: Diff should track the variables that it defines - o #1304658 by Alan D., kari.kaariainen: Remove links and comments from the comparison preview - o #1122206 by binford2k, Alan D.: Notices thrown by DiffEngine::process_chunk() - o #1175064 by zilverdistel, Alan D.: Provide variables for leading and trailing context - o #1673864 by Alan D.: Allow users to bypass the admin theme when viewing comparisons - o #1673876 by Alan D.: Use Drupal autoloading for classes - o #1673856 by Alan D.: Use hook_form_BASE_FORM_ID_alter() rather than hook_form_alter() - o #1673856 by Alan D.: Normalise line endings - o #114308 by Alan D.: add jQuery for hiding radios that shouldn't show diffs - o #1688840 by Alan D.: Enable new JScript behaviour by default - o #372957 by erykmynn, JuliaKM, lsrzj, andrew_rs, alexpott, et al: HTML Strip for Diff, WYSIWYG Friendly - (This was refactored in the 7.x-3.x branch from the commited 7.x-2.x code) - o #521212 by Alan D., blakehall: Make diff comparison page themable - o #1671484 by Alan D.: Show number of lines changed on revisions page - o #114699 by smokris, Alan D.: Diff module should support Token - o #372957 by c31ck: display either Hide or Show based on what clicking it will do at any time (HTML Strip for Diff) - This was altered for the 7.x-3.x branch. - o #1807510 & #1825202: Simplify Diff administration - o #1812162 by mitchell, Alan D.: 'Highlight changes' block appears on edit form - - Node to Entity changes - ---------------------- - These are roughly tracked in the meta issue #1365750 Generalize API and Integrate with core field types - - o (no issue) by Alan D.: Use entity specific system variables. - o (no issue) by Alan D.: View mode code, new hooks, new API. Massive patch! - - Resolves: - o #248778: Taxonomy diff - o #1550698: Diff of "select from list" fields shows change in key, not change in value - o #1458814: File (and image) field support - o #1418760: Optional setting to honour the display settings - o #1347316: Selectable view mode for inline diffs and "Current revision" display view mode - o #1458906: Improve performances (of existing 7.x-2.x field rendering) - o #1424162: Diff in Taxonomy term description - o #1211282: Image diff support - -The following patches will be posted in the corresponding project queues once -the 7.x-3.x branch is released: - o #1595702 by Alan D., mbilbille: Support of field collection module - o #1350604 by Alan D., johaziel: Datetime diff - o (no issue) by Alan D.: Email field Diff support - o (no issue) by Alan D.: Countries Diff support - o (no issue) by Alan D.: Name field Diff support - o (no issue) by Alan D.: Link field Diff support diff --git a/sites/all/modules/contrib/content/diff/DiffEngine.php b/sites/all/modules/contrib/content/diff/DiffEngine.php index 12366107..04234b76 100644 --- a/sites/all/modules/contrib/content/diff/DiffEngine.php +++ b/sites/all/modules/contrib/content/diff/DiffEngine.php @@ -41,7 +41,7 @@ class _DiffOp { class _DiffOp_Copy extends _DiffOp { var $type = 'copy'; - function _DiffOp_Copy($orig, $closing = FALSE) { + function __construct($orig, $closing = FALSE) { if (!is_array($closing)) { $closing = $orig; } @@ -62,7 +62,7 @@ class _DiffOp_Copy extends _DiffOp { class _DiffOp_Delete extends _DiffOp { var $type = 'delete'; - function _DiffOp_Delete($lines) { + function __construct($lines) { $this->orig = $lines; $this->closing = FALSE; } @@ -80,7 +80,7 @@ class _DiffOp_Delete extends _DiffOp { class _DiffOp_Add extends _DiffOp { var $type = 'add'; - function _DiffOp_Add($lines) { + function __construct($lines) { $this->closing = $lines; $this->orig = FALSE; } @@ -98,7 +98,7 @@ class _DiffOp_Add extends _DiffOp { class _DiffOp_Change extends _DiffOp { var $type = 'change'; - function _DiffOp_Change($orig, $closing) { + function __construct($orig, $closing) { $this->orig = $orig; $this->closing = $closing; } @@ -215,11 +215,17 @@ class _DiffEngine { // Find deletes & adds. $delete = array(); while ($xi < $n_from && $this->xchanged[$xi]) { - $delete[] = $from_lines[$xi++]; + $_fl = $from_lines[$xi++]; + if (strlen($_fl)) { + $delete[] = $_fl; + } } $add = array(); while ($yi < $n_to && $this->ychanged[$yi]) { - $add[] = $to_lines[$yi++]; + $_tl = $to_lines[$yi++]; + if (strlen($_tl)) { + $add[] = $_tl; + } } if ($delete && $add) { $edits[] = new _DiffOp_Change($delete, $add); @@ -576,7 +582,7 @@ class Diff { * (Typically these are lines from a file.) * @param $to_lines array An array of strings. */ - function Diff($from_lines, $to_lines) { + function __construct($from_lines, $to_lines) { $eng = new _DiffEngine; $this->edits = $eng->diff($from_lines, $to_lines); //$this->_check($from_lines, $to_lines); @@ -735,12 +741,11 @@ class MappedDiff extends Diff { * @param $mapped_to_lines array This array should * have the same number of elements as $to_lines. */ - function MappedDiff($from_lines, $to_lines, $mapped_from_lines, $mapped_to_lines) { - + function __construct($from_lines, $to_lines, $mapped_from_lines, $mapped_to_lines) { assert(sizeof($from_lines) == sizeof($mapped_from_lines)); assert(sizeof($to_lines) == sizeof($mapped_to_lines)); - $this->Diff($mapped_from_lines, $mapped_to_lines); + parent::__construct($mapped_from_lines, $mapped_to_lines); $xi = $yi = 0; for ($i = 0; $i < sizeof($this->edits); $i++) { @@ -950,7 +955,7 @@ define('NBSP', ' '); // iso-8859-x non-breaking space. * @subpackage DifferenceEngine */ class _HWLDF_WordAccumulator { - function _HWLDF_WordAccumulator() { + function __construct() { $this->_lines = array(); $this->_line = ''; $this->_group = ''; @@ -1016,11 +1021,11 @@ class WordLevelDiff extends MappedDiff { return 10000; } - function WordLevelDiff($orig_lines, $closing_lines) { + function __construct($orig_lines, $closing_lines) { list($orig_words, $orig_stripped) = $this->_split($orig_lines); list($closing_words, $closing_stripped) = $this->_split($closing_lines); - $this->MappedDiff($orig_words, $closing_words, $orig_stripped, $closing_stripped); + parent::__construct($orig_words, $closing_words, $orig_stripped, $closing_stripped); } function _split($lines) { @@ -1095,7 +1100,7 @@ class DrupalDiffFormatter extends DiffFormatter { 'offset' => array('x' => 0, 'y' => 0), ); - function DrupalDiffFormatter() { + function __construct() { $this->leading_context_lines = variable_get('diff_context_lines_leading', 2); $this->trailing_context_lines = variable_get('diff_context_lines_trailing', 2); } diff --git a/sites/all/modules/contrib/content/diff/css/diff.boxes.css b/sites/all/modules/contrib/content/diff/css/diff.boxes.css index ee1b3116..4af7a48f 100644 --- a/sites/all/modules/contrib/content/diff/css/diff.boxes.css +++ b/sites/all/modules/contrib/content/diff/css/diff.boxes.css @@ -1,5 +1,6 @@ - -html.js .diff-js-hidden { display: none; } +html.js .diff-js-hidden { + display: none; +} /* Reset as many core themes as possible */ table.diff { @@ -8,7 +9,7 @@ table.diff { border: 0 none; width: 98%; border-spacing: 5px; - table-layout: fixed ; + table-layout: fixed; border-collapse: separate; } table.diff tr td:last-child { @@ -24,10 +25,13 @@ table.diff th { border-spacing: 4px; padding: 4px 8px; } -table.diff tr, table.diff tr.even { +table.diff tr, +table.diff tr.even { background: none; } -table.diff tr th, table.diff tr th a, table.diff tr th a:hover { +table.diff tr th, +table.diff tr th a, +table.diff tr th a:hover { color: inherit; font-weight: bold; } @@ -37,28 +41,34 @@ table.diff tr.odd { border-style: none; background: transparent; } -table.diff th a { display: inline; } +table.diff th a { + display: inline; +} /* Main theming */ -table.diff, td.diff-number { - background-color: white +table.diff, +td.diff-number { + background-color: white; } table.diff td.diff-lineno { - font-weight: bold + font-weight: bold; } -table.diff td.diff-addedline, table.diff td.diff-deletedline, table.diff td.diff-context { +table.diff td.diff-addedline, +table.diff td.diff-deletedline, +table.diff td.diff-context { font-size: 88%; vertical-align: top; white-space: -moz-pre-wrap; - white-space: pre-wrap + white-space: pre-wrap; } -table.diff td.diff-addedline, table.diff td.diff-deletedline { +table.diff td.diff-addedline, +table.diff td.diff-deletedline { border-style: solid; border-width: 1px 1px 1px 4px; - border-radius: 0.33em + border-radius: 0.33em; } table.diff td.diff-context { @@ -76,45 +86,46 @@ table.diff td.diff-addedline { } table.diff td.diff-deletedline { - border-color: #ffe49c + border-color: #ffe49c; } .diffchange { font-weight: bold; - text-decoration: none + text-decoration: none; } -table.diff td.diff-addedline .diffchange, table.diff td.diff-deletedline .diffchange { +table.diff td.diff-addedline .diffchange, +table.diff td.diff-deletedline .diffchange { border-radius: 0.33em; - padding: 0.25em 0 + padding: 0.25em 0; } table.diff td.diff-addedline .diffchange { - background: #d8ecff + background: #d8ecff; } table.diff td.diff-deletedline .diffchange { - background: #feeec8 + background: #feeec8; } table.diff table.diff td { - padding: 0.33em 0.66em + padding: 0.33em 0.66em; } table.diff td.diff-marker { width: 2%; text-align: right; font-weight: bold; - font-size: 1.25em + font-size: 1.25em; } table.diff col.diff-content { - width: 48% + width: 48%; } table.diff table.diff td div { word-wrap: break-word; - overflow: auto + overflow: auto; } td.diff-prevlink { text-align: left; @@ -122,3 +133,7 @@ td.diff-prevlink { td.diff-nextlink { text-align: right; } + +table.diff-revisions tr.revision-published td { + background-color: #aaffaa; +} diff --git a/sites/all/modules/contrib/content/diff/css/diff.default.css b/sites/all/modules/contrib/content/diff/css/diff.default.css index a7ab7ffd..78337b93 100644 --- a/sites/all/modules/contrib/content/diff/css/diff.default.css +++ b/sites/all/modules/contrib/content/diff/css/diff.default.css @@ -1,30 +1,47 @@ - -html.js .diff-js-hidden { display: none; } +html.js .diff-js-hidden { + display: none; +} /** * Inline diff metadata */ .diff-inline-metadata { - padding:4px; - border:1px solid #ddd; - background:#fff; - margin:0px 0px 10px; + padding: 4px; + border: 1px solid #ddd; + background: #fff; + margin: 0 0 10px; } -.diff-inline-legend { font-size:11px; } +.diff-inline-legend { + font-size: 11px; +} .diff-inline-legend span, -.diff-inline-legend label { margin-right:5px; } +.diff-inline-legend label { + margin-right: 5px; +} /** * Inline diff markup */ -span.diff-deleted { color:#ccc; } -span.diff-deleted img { border: solid 2px #ccc; } -span.diff-changed { background:#ffb; } -span.diff-changed img { border:solid 2px #ffb; } -span.diff-added { background:#cfc; } -span.diff-added img { border: solid 2px #cfc; } +span.diff-deleted { + color: #ccc; +} +span.diff-deleted img { + border: solid 2px #ccc; +} +span.diff-changed { + background: #ffb; +} +span.diff-changed img { + border: solid 2px #ffb; +} +span.diff-added { + background: #cfc; +} +span.diff-added img { + border: solid 2px #cfc; +} /** * Traditional split diff theming @@ -35,7 +52,8 @@ table.diff { table-layout: fixed; width: 100%; } -table.diff tr.even, table.diff tr.odd { +table.diff tr.even, +table.diff tr.odd { background-color: inherit; border: none; } @@ -45,7 +63,8 @@ td.diff-prevlink { td.diff-nextlink { text-align: right; } -td.diff-section-title, div.diff-section-title { +td.diff-section-title, +div.diff-section-title { background-color: #f0f0ff; font-size: 0.83em; font-weight: bold; @@ -84,3 +103,7 @@ table.diff td div { table.diff td { padding: 0.1ex 0.4em; } + +table.diff-revisions tr.revision-published td { + background-color: #aaffaa; +} diff --git a/sites/all/modules/contrib/content/diff/diff.admin.inc b/sites/all/modules/contrib/content/diff/diff.admin.inc index a9df19ed..8c5202f2 100644 --- a/sites/all/modules/contrib/content/diff/diff.admin.inc +++ b/sites/all/modules/contrib/content/diff/diff.admin.inc @@ -20,17 +20,6 @@ function diff_admin_settings($form, $form_state) { '#empty_option' => t('- None -'), '#description' => t('Alter the CSS used when displaying diff results.'), ); - $form['diff_default_state_node'] = array( - '#type' => 'select', - '#title' => t('Diff default state'), - '#default_value' => variable_get('diff_default_state_node', 'raw'), - '#options' => array( - 'raw' => t('HTML view'), - 'raw_plain' => t('Plain view'), - ), - '#empty_option' => t('- None -'), - '#description' => t('Default display to show when viewing a diff, html tags in diffed result or as plain text.'), - ); $form['diff_radio_behavior'] = array( '#type' => 'select', '#title' => t('Diff radio behavior'), @@ -68,17 +57,50 @@ function diff_admin_settings($form, $form_state) { function diff_admin_global_entity_settings($form, $form_state, $entity_type) { $entity_info = entity_get_info($entity_type); drupal_set_title(t('Diff settings for %entity_label entities', array('%entity_label' => $entity_info['label'])), PASS_THROUGH); + + if ($options = module_invoke_all('entity_diff_options', $entity_type)) { + $form['diff_additional_options_' . $entity_type] = array( + '#type' => 'checkboxes', + '#title' => t('Property options'), + '#default_value' => variable_get('diff_additional_options_' . $entity_type, array()), + '#options' => $options, + ); + } + else { + $form['diff_additional_options_' . $entity_type] = array( + '#type' => 'value', + '#value' => array(), + ); + } + $form['diff_show_header_' . $entity_type] = array( '#type' => 'checkbox', - '#title' => t('Show entity label header'), + '#title' => t('Show entity label row header'), '#default_value' => variable_get('diff_show_header_' . $entity_type, 1), ); + if (user_access('administer permissions')) { + $admin_link = l(t('View the administration theme'), 'admin/people/permissions', array('fragment' => 'edit-view-the-administration-theme')); + } + else { + $admin_link = t('View the administration theme'); + } $form['diff_admin_path_' . $entity_type] = array( '#type' => 'checkbox', - '#title' => t('Treat diff pages as administrative'), - '#description' => t('Diff pages are treated as administrative pages by default, although it is up to each module to enforce this and to implement this optional setting.'), + '#title' => t('Use administration theme'), + '#description' => t('This option will enable users with the !link permission to use the admin theme when doing comparisons.', array('!link' => $admin_link)), '#default_value' => variable_get('diff_admin_path_' . $entity_type, 1), ); + $form['diff_default_state_' . $entity_type] = array( + '#type' => 'select', + '#title' => t('Diff default state'), + '#default_value' => variable_get('diff_default_state_' . $entity_type, 'raw'), + '#options' => array( + 'raw' => t('HTML view'), + 'raw_plain' => t('Plain view'), + ), + '#empty_option' => t('- None -'), + '#description' => t('Default display to show when viewing a diff, html tags in diffed result or as plain text.'), + ); return system_settings_form($form); } diff --git a/sites/all/modules/contrib/content/diff/diff.api.php b/sites/all/modules/contrib/content/diff/diff.api.php index 507293a1..e2b6f848 100644 --- a/sites/all/modules/contrib/content/diff/diff.api.php +++ b/sites/all/modules/contrib/content/diff/diff.api.php @@ -11,27 +11,75 @@ */ /** - * Allow modules to provide a comparison about entities. + * Allow modules to provide a comparison about entity properties. * * @param object $old_entity * The older entity revision. + * * @param object $new_entity * The newer entity revision. + * * @param array $context * An associative array containing: * - entity_type: The entity type; e.g., 'node' or 'user'. - * - view_mode: The view mode to use. Defaults to FALSE. + * - old_entity: The older entity. + * - new_entity: The newer entity. + * - view_mode: The view mode to use. Defaults to FALSE. If no view mode is + * given, the recommended fallback view mode is 'default'. + * - states: An array of view states. These could be one of: + * - raw: The raw value of the diff, the classic 7.x-2.x view. + * - rendered: The rendered HTML as determined by the view mode. Only + * return markup for this state if the value is normally shown + * by this view mode. The user will most likely be able to see + * the raw or raw_plain state, so this is optional. + * + * The rendering state is a work in progress. + * + * Conditionally, you can get these states, but setting these will override + * the user selectable markdown method. + * + * - raw_plain: As raw, but text should be markdowned. + * - rendered_plain: As rendered, but text should be markdowned. * * @return array * An associative array of values keyed by the entity property. * - * @todo - * Investiagate options and document these. + * This is effectively an unnested Form API-like structure. + * + * States are returned as follows: + * + * $results['line'] = array( + * '#name' => t('Line'), + * '#states' => array( + * 'raw' => array( + * '#old' => '
This was the old line number [tag].
', + * '#new' => 'This is the new line [tag].
', + * ), + * 'rendered' => array( + * '#old' => 'This was the old line number 57.
', + * '#new' => 'This is the new line 57.
', + * ), + * ), + * ); + * + * For backwards compatibility, no changes are required to support states, + * but it is recommended to provide a better UI for end users. + * + * For example, the following example is equivalent to returning the raw + * state from the example above. + * + * $results['line'] = array( + * '#name' => t('Line'), + * '#old' => 'This was the old line number [tag].
', + * '#new' => 'This is the new line [tag].
', + * ); */ function hook_entity_diff($old_entity, $new_entity, $context) { + $results = array(); + if ($context['entity_type'] == 'node') { $type = node_type_get_type($new_entity); - $result['title'] = array( + $results['title'] = array( '#name' => $type->title_label, '#old' => array($old_entity->title), '#new' => array($new_entity->title), @@ -41,6 +89,8 @@ function hook_entity_diff($old_entity, $new_entity, $context) { ), ); } + + return $results; } /** @@ -57,7 +107,7 @@ function hook_entity_diff($old_entity, $new_entity, $context) { * * @see hook_entity_diff() */ -function hook_entity_diff_alter($entity_diffs, $context) { +function hook_entity_diff_alter(&$entity_diffs, $context) { } /** diff --git a/sites/all/modules/contrib/content/diff/diff.css b/sites/all/modules/contrib/content/diff/diff.css index a09147c1..8c634a91 100644 --- a/sites/all/modules/contrib/content/diff/diff.css +++ b/sites/all/modules/contrib/content/diff/diff.css @@ -1,30 +1,46 @@ - -html.js .diff-js-hidden { display:none; } +html.js .diff-js-hidden { + display:none; +} /** * Inline diff metadata */ .diff-inline-metadata { - padding:4px; - border:1px solid #ddd; - background:#fff; - margin:0px 0px 10px; - } - -.diff-inline-legend { font-size:11px; } + padding: 4px; + border: 1px solid #ddd; + background: #fff; + margin: 0 0 10px; +} +.diff-inline-legend { + font-size: 11px; +} .diff-inline-legend span, -.diff-inline-legend label { margin-right:5px; } +.diff-inline-legend label { + margin-right: 5px; +} /** * Inline diff markup */ -span.diff-deleted { color:#ccc; } -span.diff-deleted img { border: solid 2px #ccc; } -span.diff-changed { background:#ffb; } -span.diff-changed img { border:solid 2px #ffb; } -span.diff-added { background:#cfc; } -span.diff-added img { border: solid 2px #cfc; } +span.diff-deleted { + color: #ccc; +} +span.diff-deleted img { + border: solid 2px #ccc; +} +span.diff-changed { + background: #ffb; +} +span.diff-changed img { + border: solid 2px #ffb; +} +span.diff-added { + background: #cfc; +} +span.diff-added img { + border: solid 2px #cfc; +} /** * Traditional split diff theming @@ -35,7 +51,8 @@ table.diff { table-layout: fixed; width: 100%; } -table.diff tr.even, table.diff tr.odd { +table.diff tr.even, +table.diff tr.odd { background-color: inherit; border: none; } @@ -45,7 +62,8 @@ td.diff-prevlink { td.diff-nextlink { text-align: right; } -td.diff-section-title, div.diff-section-title { +td.diff-section-title, +div.diff-section-title { background-color: #f0f0ff; font-size: 0.83em; font-weight: bold; diff --git a/sites/all/modules/contrib/content/diff/diff.diff.inc b/sites/all/modules/contrib/content/diff/diff.diff.inc index 63c01b44..8e7f682a 100644 --- a/sites/all/modules/contrib/content/diff/diff.diff.inc +++ b/sites/all/modules/contrib/content/diff/diff.diff.inc @@ -12,17 +12,6 @@ * * This manually invokes hook_diff() to avoid a function name clash with the * PHP 5 (>= 5.3.0) date_diff() function or the Dates modules implementation. - * - * @param object $old_entity - * The older node revision. - * @param object $new_entity - * The newer node revision. - * @param array $context - * An associative array containing: - * - entity_type: The entity type; e.g., 'node' or 'user'. - * - old_entity: The older entity. - * - new_entity: The newer entity. - * - view_mode: The view mode to use. Defaults to FALSE. */ function diff_entity_diff($old_entity, $new_entity, $context) { $return = array(); @@ -52,11 +41,13 @@ function diff_entity_diff($old_entity, $new_entity, $context) { * - old_entity: The older entity. * - new_entity: The newer entity. * - view_mode: The view mode to use. Defaults to FALSE. + * @param string $default_langcode + * (optional) Language code to force comparison in. * * @return array * An associative array of values keyed by the field name and delta value. */ -function diff_entity_fields_diff($old_entity, $new_entity, $context) { +function diff_entity_fields_diff($old_entity, $new_entity, $context, $default_langcode = NULL) { $result = array(); $entity_type = $context['entity_type']; @@ -65,7 +56,7 @@ function diff_entity_fields_diff($old_entity, $new_entity, $context) { $field_context = $context; $actual_mode = FALSE; - list(,, $bundle_name) = entity_extract_ids($entity_type, $new_entity); + list(, , $bundle_name) = entity_extract_ids($entity_type, $new_entity); $instances = field_info_instances($entity_type, $bundle_name); // Some fields piggy back the display settings, so we need to fake these by @@ -98,7 +89,7 @@ function diff_entity_fields_diff($old_entity, $new_entity, $context) { // We provide a loose check on the field access. if (field_access('view', $field, $entity_type) || field_access('edit', $field, $entity_type)) { - $langcode = field_language($entity_type, $new_entity, $field_name); + $langcode = $default_langcode ? $default_langcode : field_language($entity_type, $new_entity, $field_name); $field_context['language'] = $langcode; $field_context['field'] = $field; @@ -136,10 +127,18 @@ function diff_entity_fields_diff($old_entity, $new_entity, $context) { $func = 'diff_field_diff_view'; } + // Copy the static ID cache to ensure this is the same for each comparison. + $original_html_ids = drupal_static('drupal_html_id'); + $html_ids = &drupal_static('drupal_html_id'); + // These callbacks should be independent of revision. $old_context = $field_context; $old_context['entity'] = $old_entity; $old_values = $func($old_items, $old_context); + + // Restores the ID cache to the original. + $html_ids = $original_html_ids; + $new_context = $field_context; $new_context['entity'] = $new_entity; $new_values = $func($new_items, $new_context); @@ -200,22 +199,29 @@ function diff_entity_fields_diff($old_entity, $new_entity, $context) { * An array of strings representing the value, keyed by delta index. */ function diff_field_diff_view($items, $context) { - $diff_items = array(); - $entity = clone $context['entity']; - $langcode = field_language($context['entity_type'], $entity, $context['field']['field_name']); - $view_mode = empty($context['view_mode']) ? 'diff_standard' : $context['view_mode']; - $element = field_view_field($context['entity_type'], $entity, $context['field']['field_name'], $view_mode, $langcode); + // Prevent unnecessary rendering of the field. This also prevents issues + // where field_view_field() will use a language fallback for display that + // may not match the requested diff comparison language. + if (!$items) { + return array(); + } - foreach (element_children($element) as $delta) { - $diff_items[$delta] = drupal_render($element[$delta]); - } + $diff_items = array(); + $entity = clone $context['entity']; + $langcode = field_language($context['entity_type'], $entity, $context['field']['field_name']); + $view_mode = empty($context['view_mode']) ? 'diff_standard' : $context['view_mode']; + $element = field_view_field($context['entity_type'], $entity, $context['field']['field_name'], $view_mode, $langcode); + + foreach (element_children($element) as $delta) { + $diff_items[$delta] = drupal_render($element[$delta]); + } return $diff_items; } /** * Helper function to get the settings for a given field or formatter. * - * @param array $context + * @param array $field_context * This will get the settings for a field. * - field (required): The field that the items belong to. * - entity: The entity that we are looking up. @@ -274,31 +280,6 @@ function diff_global_settings_form(&$subform, $form_state, $type, $settings) { ), ); - /* -This would be cool, but to do anything else than inline with the text appears -to be very hard, requiring a refactoring of both the modules API but also the -DiffFormatter and Diff classes. Diff 8.x-4.x maybe. - - $subform['show_delta'] = array( - '#type' => 'checkbox', - '#title' => t('Show delta values'), - '#default_value' => $settings['show_delta'], - ); - $subform['delta_format'] = array( - '#type' => 'radios', - '#title' => t('Delta insertion method'), - '#default_value' => $settings['delta_format'], - '#options' => array( - 'inline' => t('Prefix to item'), - 'row' => t('Individual row'), - ), - '#states' => array( - 'invisible' => array( - "input[id$='show-delta']" => array('checked' => FALSE), - ), - ), - ); - */ } /** @@ -323,11 +304,8 @@ function _diff_field_default_settings($module, $field_type, $settings = array()) 'markdown' => function_exists($func) ? '' : 'drupal_html_to_text', 'line_counter' => '', 'show_header' => 1, - // Can we? This seems too hard to track in the DiffFormatter as all we - // have is a string or an array of strings. - //'show_delta' => 0, - //'delta_format' => 'row', ); + return $settings; } diff --git a/sites/all/modules/contrib/content/diff/diff.info b/sites/all/modules/contrib/content/diff/diff.info index 5ae077e8..77b73168 100644 --- a/sites/all/modules/contrib/content/diff/diff.info +++ b/sites/all/modules/contrib/content/diff/diff.info @@ -1,12 +1,13 @@ name = Diff description = Show differences between content revisions. core = 7.x +configure = admin/config/content/diff files[] = DiffEngine.php -; Information added by drupal.org packaging script on 2012-11-13 -version = "7.x-3.2" +; Information added by Drupal.org packaging script on 2016-12-20 +version = "7.x-3.3" core = "7.x" project = "diff" -datestamp = "1352784357" +datestamp = "1482211686" diff --git a/sites/all/modules/contrib/content/diff/diff.install b/sites/all/modules/contrib/content/diff/diff.install index 16f1d27c..9d8b585d 100644 --- a/sites/all/modules/contrib/content/diff/diff.install +++ b/sites/all/modules/contrib/content/diff/diff.install @@ -5,6 +5,14 @@ * Provides uninstallation functions. */ +/** + * Implements hook_install(). + */ +function diff_install() { + user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, array('diff view changes')); + user_role_grant_permissions(DRUPAL_AUTHENTICATED_RID, array('diff view changes')); +} + /** * Implements hook_uninstall(). */ @@ -16,6 +24,7 @@ function diff_uninstall() { 'diff_view_mode_', 'diff_admin_path_', 'diff_default_state_', + 'diff_additional_options_', ); foreach ($prefixes as $prefix) { db_delete('variable') @@ -55,27 +64,19 @@ function diff_update_7300() { } } -/** - * Removed diff_update_7301(). - */ - -/** - * Removed diff_update_7302(). - */ - /** * Renames some internal settings names. */ function diff_update_7303() { - // Get current values + // Get current values. $radio = variable_get('diff_script_revisioning', 'simple'); $leading = variable_get('diff_leading_context_lines', 2); $trailing = variable_get('diff_trailing_context_lines', 2); - // Create new variable names + // Create new variable names. variable_set('diff_radio_behavior', $radio); variable_set('diff_context_lines_leading', $leading); variable_set('diff_context_lines_trailing', $trailing); - // Delete old variables + // Delete old variables. variable_del('diff_script_revisioning'); variable_del('diff_leading_context_lines'); variable_del('diff_trailing_context_lines'); @@ -88,8 +89,8 @@ function diff_update_7304() { // This is now always applied to text fields. variable_del('diff_normalise_text'); - // Merge the content type settings for the inline diff block into a single variable. - // diff_update_7300() - show_diff_inline_TYPE to diff_show_diff_inline_node_TYPE + // Merge the content type settings for the inline diff block into a single + // variable. $node_types = array_keys(node_type_get_types()); $enabled_types = array(); foreach ($node_types as $node_type) { @@ -122,3 +123,19 @@ function diff_update_7305() { ->condition('name', db_like('diff_view_mode_inline_') . '%', 'LIKE') ->execute(); } + +/** + * Sets the optional additional node properties to render so that the title + * still shows by default when doing node comparisons. + */ +function diff_update_7306() { + variable_set('diff_additional_options_node', array('title' => 'title')); +} + +/** + * Grants access to the Diff "View Changes" button permission to all users. + */ +function diff_update_7307() { + user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, array('diff view changes')); + user_role_grant_permissions(DRUPAL_AUTHENTICATED_RID, array('diff view changes')); +} diff --git a/sites/all/modules/contrib/content/diff/diff.module b/sites/all/modules/contrib/content/diff/diff.module index f58e1d72..d3050e3b 100644 --- a/sites/all/modules/contrib/content/diff/diff.module +++ b/sites/all/modules/contrib/content/diff/diff.module @@ -39,11 +39,14 @@ function diff_help($path, $arg) { case 'admin/help#diff': $output = '' . t('The Diff module replaces the normal Revisions node tab. Diff enhances the listing of revisions with an option to view the differences between any two content revisions. Access to this feature is controlled with the View revisions permission. The feature can be disabled for an entire content type on the content type configuration page. Diff also provides an optional View changes button while editing a node.') . '
'; return $output; + case 'node/%/revisions/%/view': // The translated strings should match node_help('node/%/revisions'). return '' . t('Revisions allow you to track differences between multiple versions of your content, and revert back to older versions.') . '
'; + case 'node/%/revisions/view/%/%': return '' . t('Comparing two revisions:') . '
'; + } } @@ -104,8 +107,7 @@ function diff_menu() { 'page callback' => 'diff_latest', 'page arguments' => array(1), 'type' => MENU_LOCAL_TASK, - 'access callback' => 'diff_node_revision_access', - 'access arguments' => array(1), + 'access arguments' => array('access content'), 'tab_parent' => 'node/%/revisions/view', 'file' => 'diff.pages.inc', ); @@ -152,10 +154,20 @@ function diff_menu() { ); $items['admin/config/content/diff/entities/node'] = array( - 'title' => 'Node', + 'title' => 'Nodes', + 'description' => 'Node comparison settings.', 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10, ); + $items['admin/config/content/diff/entities/user'] = array( + 'title' => 'Users', + 'description' => 'User diff settings.', + 'file' => 'diff.admin.inc', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('diff_admin_global_entity_settings', 'user'), + 'access arguments' => array('administer site configuration'), + 'type' => MENU_LOCAL_TASK, + ); return $items; } @@ -197,6 +209,18 @@ function diff_node_revision_access($node, $op = 'view') { return $may_revision_this_type && _node_revision_access($node, $op); } +/** + * Implements hook_permission(). + */ +function diff_permission() { + return array( + 'diff view changes' => array( + 'title' => t('Access %view button', array('%view' => t('View changes'))), + 'description' => t('Controls access to the %view button when editing content.', array('%view' => t('View changes'))), + ), + ); +} + /** * Implements hook_hook_info(). */ @@ -238,6 +262,28 @@ function diff_entity_info_alter(&$entity_info) { } } +/** + * Returns a list of all the existing revision numbers. + * + * Clone of node_revision_list() with revision status included. This would be + * an additional join in Drupal 8.x to the {node_field_revision} table. + * + * @param object $node + * The node object. + * + * @return array + * An associative array keyed by node revision number. + */ +function diff_node_revision_list($node) { + $revisions = array(); + $result = db_query('SELECT r.vid, r.title, r.log, r.uid, n.vid AS current_vid, r.status AS status, r.timestamp, u.name FROM {node_revision} r LEFT JOIN {node} n ON n.vid = r.vid INNER JOIN {users} u ON u.uid = r.uid WHERE r.nid = :nid ORDER BY r.vid DESC', array(':nid' => $node->nid)); + foreach ($result as $revision) { + $revisions[$revision->vid] = $revision; + } + + return $revisions; +} + /** * Implements hook_block_info(). */ @@ -287,7 +333,7 @@ function diff_block_view($delta) { $enabled_types = variable_get('diff_show_diff_inline_node_bundles', array()); if (!empty($enabled_types[$node->type])) { $block = array(); - $revisions = node_revision_list($node); + $revisions = diff_node_revision_list($node); if (count($revisions) > 1) { $block['subject'] = t('Highlight changes'); $block['content'] = drupal_get_form('diff_inline_form', $node, $revisions); @@ -302,7 +348,7 @@ function diff_block_view($delta) { */ function diff_node_view_alter(&$build) { $node = $build['#node']; - if (user_access('view revisions') && in_array($node->type, variable_get('diff_show_diff_inline_node_bundles', array()))) { + if (user_access('view revisions') && in_array($node->type, variable_get('diff_show_diff_inline_node_bundles', array()), TRUE)) { // Ugly but cheap way to check that we are viewing a node's revision page. if (arg(2) === 'revisions' && arg(3) === $node->vid) { module_load_include('inc', 'diff', 'diff.pages'); @@ -320,7 +366,9 @@ function diff_node_view_alter(&$build) { function diff_form_node_form_alter(&$form, $form_state) { // Add a 'View changes' button on the node edit form. $node = $form['#node']; - if (variable_get('diff_show_preview_changes_node_' . $node->type, TRUE) && !empty($node->nid)) { + if (variable_get('diff_show_preview_changes_node_' . $node->type, TRUE) + && user_access('diff view changes') + && !empty($node->nid)) { $form['actions']['preview_changes'] = array( '#type' => 'submit', '#value' => t('View changes'), @@ -347,6 +395,9 @@ function diff_form_node_type_form_alter(&$form, $form_state) { '#title' => t('Show View changes button on node edit form'), '#weight' => 10, '#default_value' => variable_get('diff_show_preview_changes_node_' . $type->type, TRUE), + '#description' => t('You can refine access using the "!perm" permission.', array( + '!perm' => t('Access %view button', array('%view' => t('View changes'))), + )), ); $form['diff']['diff_enable_revisions_page_node'] = array( '#type' => 'checkbox', @@ -430,7 +481,7 @@ function diff_node_form_build_preview_changes($form, &$form_state) { $changes = theme('table__diff__preview', array( 'header' => $header, 'rows' => $rows, - 'attributes' => array('class' => 'diff'), + 'attributes' => array('class' => array('diff')), 'colgroups' => _diff_default_cols(), 'sticky' => FALSE, )); @@ -440,6 +491,24 @@ function diff_node_form_build_preview_changes($form, &$form_state) { $form_state['rebuild'] = TRUE; } +/** + * Implementation of hook_features_pipe_COMPONENT_alter(). + */ +function diff_features_pipe_node_alter(&$pipe, $data, $export) { + if (!empty($data)) { + $variables = array( + 'diff_show_preview_changes_node', + 'diff_enable_revisions_page_node', + 'diff_view_mode_preview_node', + ); + foreach ($data as $node_type) { + foreach ($variables as $variable_name) { + $pipe['variable'][] = $variable_name . '_' . $node_type; + } + } + } +} + /** * Implements hook_theme(). */ @@ -483,7 +552,7 @@ function diff_theme() { * The source string to compare from. * @param string $b * The target string to compare to. - * @param boolean $show_header + * @param bool $show_header * Display diff context headers. For example, "Line x". * @param array $line_stats * This structure tracks line numbers across multiple calls to DiffFormatter. @@ -621,3 +690,85 @@ function diff_build_attachments($jscript = FALSE) { } return $attachments; } + +/** + * Implements hook_entity_diff() on behalf of the Node module. + */ +function node_entity_diff($old_node, $new_node, $context) { + $result = array(); + if ($context['entity_type'] == 'node') { + module_load_include('inc', 'diff', 'includes/node'); + $options = variable_get('diff_additional_options_node', array('title' => 'title')); + foreach (node_entity_diff_options('node') as $key => $option_label) { + if (!empty($options[$key])) { + $func = '_node_entity_diff_additional_options_' . $key; + $result[$key] = $func($old_node, $new_node, $context); + } + } + } + return $result; +} + +/** + * Implements hook_entity_diff_options() on behalf of the Node module. + */ +function node_entity_diff_options($entity_type) { + if ($entity_type == 'node') { + $options = array( + 'title' => t('Title field'), + // Author field is either the owner or revision creator, neither capture + // a change in the author field. + 'author' => t('Author'), + 'revision_author' => t('Revision author'), + 'type' => t('Node type'), + 'publishing_flags' => t('Publishing options'), + // More fields that currently can not be tracked. + 'created' => t('Created date'), + 'changed' => t('Updated date'), + 'revision_timestamp' => t('Revision timestamp'), + ); + if (module_exists('comment')) { + $options['comment'] = t('Comment setting'); + } + return $options; + } +} + +/** + * Implements hook_entity_diff() on behalf of the User module. + */ +function user_entity_diff($old_user, $new_user, $context) { + $result = array(); + if ($context['entity_type'] == 'user') { + module_load_include('inc', 'diff', 'includes/user'); + $options = variable_get('diff_additional_options_user', array( + 'name' => 'name', + 'mail' => 'mail', + 'status' => 'status', + )); + foreach (user_entity_diff_options('user') as $key => $option_label) { + if (!empty($options[$key])) { + $func = '_user_entity_diff_additional_options_' . $key; + $result[$key] = $func($old_user, $new_user, $context); + } + } + } + return $result; +} + +/** + * Implements hook_entity_diff_options() on behalf of the User module. + */ +function user_entity_diff_options($entity_type) { + if ($entity_type == 'user') { + $options = array( + 'name' => t('Username'), + 'mail' => t('E-mail address'), + 'roles' => t('Roles'), + 'status' => t('Status'), + 'timezone' => t('Time zone'), + 'password' => t('Password Hash'), + ); + return $options; + } +} diff --git a/sites/all/modules/contrib/content/diff/diff.pages.inc b/sites/all/modules/contrib/content/diff/diff.pages.inc index 1cd14419..285eb1ed 100644 --- a/sites/all/modules/contrib/content/diff/diff.pages.inc +++ b/sites/all/modules/contrib/content/diff/diff.pages.inc @@ -10,6 +10,9 @@ */ function diff_latest($node) { $revisions = node_revision_list($node); + if (count($revisions) < 2 || !diff_node_revision_access($node, 'view')) { + drupal_goto('node/' . $node->nid); + } $new = array_shift($revisions); $old = array_shift($revisions); drupal_goto("node/{$node->nid}/revisions/view/{$old->vid}/{$new->vid}"); @@ -35,19 +38,20 @@ function diff_node_revisions($form, $form_state, $node) { '#value' => $node->nid, ); - $revision_list = node_revision_list($node); + $revision_list = diff_node_revision_list($node); + $revision_count = count($revision_list); - if (count($revision_list) > REVISION_LIST_SIZE) { + if ($revision_count > REVISION_LIST_SIZE) { // If the list of revisions is longer than the number shown on one page // split the array. $page = isset($_GET['page']) ? $_GET['page'] : '0'; - $revision_chunks = array_chunk(node_revision_list($node), REVISION_LIST_SIZE); + $revision_chunks = array_chunk($revision_list, REVISION_LIST_SIZE); $revisions = $revision_chunks[$page]; // Set up global pager variables as would 'pager_query' do. // These variables are then used in the theme('pager') call later. global $pager_page_array, $pager_total, $pager_total_items; - $pager_total_items[0] = count($revision_list); - $pager_total[0] = ceil(count($revision_list) / REVISION_LIST_SIZE); + $pager_total_items[0] = $revision_count; + $pager_total[0] = ceil($revision_count / REVISION_LIST_SIZE); $pager_page_array[0] = max(0, min($page, ((int) $pager_total[0]) - 1)); } else { @@ -73,6 +77,7 @@ function diff_node_revisions($form, $form_state, $node) { '#markup' => t('!date by !username', array( '!date' => l(format_date($revision->timestamp, 'small'), "node/$node->nid"), '!username' => theme('username', array('account' => $revision)))) . $revision_log, + '#revision' => $revision, ); } else { @@ -82,6 +87,7 @@ function diff_node_revisions($form, $form_state, $node) { '!date' => $diff_date, '!username' => theme('username', array('account' => $revision))) ) . $revision_log, + '#revision' => $revision, ); if ($revert_permission) { $operations[] = array( @@ -117,23 +123,13 @@ function diff_node_revisions($form, $form_state, $node) { $form['submit'] = array('#type' => 'submit', '#value' => t('Compare')); - if (count($revision_list) > REVISION_LIST_SIZE) { + if ($revision_count > REVISION_LIST_SIZE) { $form['#suffix'] = theme('pager'); } $form['#attached'] = diff_build_attachments(TRUE); return $form; } -/** - * Submit code for input form to select two revisions. - */ -function diff_node_revisions_submit($form, &$form_state) { - // The ids are ordered so the old revision is always on the left. - $old_vid = min($form_state['values']['old'], $form_state['values']['new']); - $new_vid = max($form_state['values']['old'], $form_state['values']['new']); - $form_state['redirect'] = 'node/' . $form_state['values']['nid'] . '/revisions/view/' . $old_vid . '/' . $new_vid; -} - /** * Validation for input form to select two revisions. */ @@ -145,14 +141,27 @@ function diff_node_revisions_validate($form, &$form_state) { } } +/** + * Submit code for input form to select two revisions. + */ +function diff_node_revisions_submit($form, &$form_state) { + // The ids are ordered so the old revision is always on the left. + $old_vid = min($form_state['values']['old'], $form_state['values']['new']); + $new_vid = max($form_state['values']['old'], $form_state['values']['new']); + if (isset($_GET['destination'])) { + unset($_GET['destination']); + } + $form_state['redirect'] = 'node/' . $form_state['values']['nid'] . '/revisions/view/' . $old_vid . '/' . $new_vid; +} + /** * Create a comparison for the node between versions 'old_vid' and 'new_vid'. * * @param object $node - * Node on which to perform comparison - * @param integer $old_vid + * Node on which to perform comparison. + * @param int $old_vid * Version ID of the old revision. - * @param integer $new_vid + * @param int $new_vid * Version ID of the new revision. */ function diff_diffs_show($node, $old_vid, $new_vid, $state = NULL) { @@ -161,7 +170,7 @@ function diff_diffs_show($node, $old_vid, $new_vid, $state = NULL) { $default_state = variable_get('diff_default_state_node', 'raw'); if (empty($state)) { - $state = $default_state; + $state = $default_state; } $state = str_replace('-', '_', $state); if (!array_key_exists($state, diff_available_states())) { @@ -279,7 +288,7 @@ function diff_diffs_show($node, $old_vid, $new_vid, $state = NULL) { } $build['diff_preview']['header']['#markup'] = $header; // Don't include node links or comments when viewing the diff. - $build['diff_preview']['content'] = node_view($new_node, $view_mode); + $build['diff_preview']['content'] = function_exists('entity_view') ? entity_view('node', array($new_node), $view_mode) : node_view($new_node, $view_mode); if (isset($build['diff_preview']['content']['links'])) { unset($build['diff_preview']['content']['links']); } @@ -291,33 +300,33 @@ function diff_diffs_show($node, $old_vid, $new_vid, $state = NULL) { } /** - * Creates an array of rows which represent the difference between nodes. + * Creates an array of rows which represent the difference between two entities. * - * @param object $old_node - * Node for comparison which will be displayed on the left side. - * @param object $new_node - * Node for comparison which will be displayed on the right side. - * @param boolean $state - * The state to render for the diff. + * @param object $left_entity + * Entity for comparison which will be displayed on the left side. + * @param object $right_entity + * Entity for comparison which will be displayed on the right side. + * @param array $context + * The context used to render the diff. */ -function _diff_body_rows($old_node, $new_node, $state = 'raw') { +function diff_entity_body_rows($entity_type, $left_entity, $right_entity, $context = array()) { // This is an unique index only, so no need for drupal_static(). static $table_row_counter = 0; if ($theme = variable_get('diff_theme', 'default')) { drupal_add_css(drupal_get_path('module', 'diff') . "/css/diff.{$theme}.css"); } - module_load_include('inc', 'diff', 'includes/node'); $rows = array(); $any_visible_change = FALSE; - $context = array( - 'entity_type' => 'node', - 'states' => array($state), + $context += array( + 'entity_type' => $entity_type, + 'states' => array('raw'), 'view_mode' => 'diff_standard', ); + $state = current($context['states']); - $node_diffs = diff_compare_entities($old_node, $new_node, $context); + $entity_diffs = diff_compare_entities($left_entity, $right_entity, $context); // Track line numbers between multiple diffs. $line_stats = array( @@ -326,19 +335,19 @@ function _diff_body_rows($old_node, $new_node, $state = 'raw') { ); // Render diffs for each. - foreach ($node_diffs as $node_diff) { - $show_header = !empty($node_diff['#name']); + foreach ($entity_diffs as $entity_diff) { + $show_header = !empty($entity_diff['#name']); // These are field level settings. - if ($show_header && isset($node_diff['#settings']['show_header'])) { - $show_header = $show_header && $node_diff['#settings']['show_header']; + if ($show_header && isset($entity_diff['#settings']['show_header'])) { + $show_header = $show_header && $entity_diff['#settings']['show_header']; } // Line counting and line header options. - if (empty($node_diff['#settings']['line_counter'])) { + if (empty($entity_diff['#settings']['line_counter'])) { $line_counter = FALSE; } else { - $line_counter = $node_diff['#settings']['line_counter']; + $line_counter = $entity_diff['#settings']['line_counter']; } // Every call to 'line' resets the counters. if ($line_counter) { @@ -354,8 +363,8 @@ function _diff_body_rows($old_node, $new_node, $state = 'raw') { $line_stats_ref = NULL; } - list($old, $new) = diff_extract_state($node_diff, $state); - if ($node_diff_rows = diff_get_rows($old, $new, $line_counter && $line_counter != 'hidden', $line_stats_ref)) { + list($left, $right) = diff_extract_state($entity_diff, $state); + if ($entity_diff_rows = diff_get_rows($left, $right, $line_counter && $line_counter != 'hidden', $line_stats_ref)) { if ($line_counter && $line_counter != 'line') { $line_stats['offset']['x'] += $line_stats_ref['counter']['x']; $line_stats['offset']['y'] += $line_stats_ref['counter']['y']; @@ -363,7 +372,7 @@ function _diff_body_rows($old_node, $new_node, $state = 'raw') { if ($show_header) { $rows['diff-header-' . $table_row_counter++] = array( array( - 'data' => t('Changes to %name', array('%name' => $node_diff['#name'])), + 'data' => t('Changes to %name', array('%name' => $entity_diff['#name'])), 'class' => 'diff-section-title', 'colspan' => 4, ), @@ -371,7 +380,7 @@ function _diff_body_rows($old_node, $new_node, $state = 'raw') { } // To avoid passing counter to the Diff engine, index rows manually here // to allow modules to interact with the table. i.e. no array_merge(). - foreach ($node_diff_rows as $row) { + foreach ($entity_diff_rows as $row) { $rows['diff-row-' . $table_row_counter++] = $row; } $any_visible_change = TRUE; @@ -385,19 +394,28 @@ function _diff_body_rows($old_node, $new_node, $state = 'raw') { 'colspan' => 4, ), ); - // @todo: revise this. - // Needed to keep safari happy. - $rows['diff-empty-' . $table_row_counter++] = array( - array('data' => ''), - array('data' => ''), - array('data' => ''), - array('data' => ''), - ); } - return $rows; } +/** + * Creates an array of rows which represent the difference between nodes. + * + * @param object $old_node + * Node for comparison which will be displayed on the left side. + * @param object $new_node + * Node for comparison which will be displayed on the right side. + * @param bool $state + * The state to render for the diff. + */ +function _diff_body_rows($old_node, $new_node, $state = 'raw') { + $context = array( + 'states' => array($state), + 'view_mode' => 'diff_standard', + ); + return diff_entity_body_rows('node', $old_node, $new_node, $context); +} + /** * Generic callback to compare two entities. */ @@ -460,6 +478,9 @@ function diff_compare_entities($left_entity, $right_entity, $context) { if (!isset($diff['#sorted'])) { uasort($diff, 'element_sort'); } + else { + unset($diff['#sorted']); + } // Process the array and get line counts per field. array_walk($diff, 'diff_process_state_lines'); @@ -467,6 +488,9 @@ function diff_compare_entities($left_entity, $right_entity, $context) { return $diff; } +/** + * Helper function to get line counts per field. + */ function diff_process_state_lines(&$diff, $key) { foreach ($diff['#states'] as $state => $data) { if (isset($data['#old'])) { @@ -509,20 +533,29 @@ function diff_markdown_state(&$diff, $state) { } if (!isset($plain_old) && isset($old)) { - if (is_array($old)) { - $diff['#states'][$state . '_plain']['#old'] = $markdown ? array_map($markdown, $old) : $old; - } - else { - $diff['#states'][$state . '_plain']['#old'] = $markdown ? $markdown($old) : $old; - } + $diff['#states'][$state . '_plain']['#old'] = _diff_apply_markdown($markdown, $old); } if (!isset($plain_new) && isset($new)) { - if (is_array($new)) { - $diff['#states'][$state . '_plain']['#new'] = $markdown ? array_map($markdown, $new) : $new; - } - else { - $diff['#states'][$state . '_plain']['#new'] = $markdown ? $markdown($new) : $new; + $diff['#states'][$state . '_plain']['#new'] = _diff_apply_markdown($markdown, $new); + } +} + +/** + * Helper function to clear newlines from the content. + */ +function _diff_apply_markdown($markdown, $items) { + if (!$markdown) { + return $items; + } + if (is_array($items)) { + $items = array_map($markdown, $items); + foreach ($items as &$item) { + $item = trim($item, "\n"); } + return $items; + } + else { + return trim($markdown($items), "\n"); } } @@ -534,7 +567,7 @@ function diff_markdown_state(&$diff, $state) { * @param int $vid * Version ID to look for. * - * @return boolean|integer + * @return bool|int * Returns FALSE if $vid is the last entry. */ function _diff_get_next_vid($node_revisions, $vid) { @@ -553,10 +586,10 @@ function _diff_get_next_vid($node_revisions, $vid) { * * @param array $node_revisions * Array of node revision IDs in descending order. - * @param integer $vid + * @param int $vid * Version ID to look for. * - * @return boolean|integer + * @return bool|int * Returns FALSE if $vid is the first entry. */ function _diff_get_previous_vid($node_revisions, $vid) { @@ -615,13 +648,13 @@ function _diff_default_header($old_header = '', $new_header = '') { * normally rendered content of the specified revision. */ function diff_inline_show($node, $vid = 0, $metadata = TRUE) { - $new_node = $vid ? node_load($node->nid, $vid, TRUE) : clone $node; + $new_node = $vid ? node_load($node->nid, $vid) : clone $node; node_build_content($new_node); $new = drupal_render($new_node->content); $old = $vid ? _diff_get_previous_vid(node_revision_list($node), $vid) : 0; if ($old) { - $old_node = node_load($node->nid, $old, TRUE); + $old_node = node_load($node->nid, $old); node_build_content($old_node); $old = drupal_render($old_node->content); $output = $metadata ? theme('diff_inline_metadata', array('node' => $new_node)) : ''; diff --git a/sites/all/modules/contrib/content/diff/diff.theme.inc b/sites/all/modules/contrib/content/diff/diff.theme.inc index 96d20b3a..aee2581c 100644 --- a/sites/all/modules/contrib/content/diff/diff.theme.inc +++ b/sites/all/modules/contrib/content/diff/diff.theme.inc @@ -48,14 +48,21 @@ function theme_diff_node_revisions($vars) { 'data' => drupal_render($form['diff']['new'][$key]), 'class' => array('revision-current'), ); + $revision = $form['info'][$key]['#revision']; + if ($revision && !empty($revision->status)) { + $message = t('This is the published revision.'); + } + else { + $message = t('This is the current revision.'); + } $row[] = array( - 'data' => t('current revision'), + 'data' => '' . $message . '', 'class' => array('revision-current'), 'colspan' => '2', ); $rows[] = array( 'data' => $row, - 'class' => array('error diff-revision'), + 'class' => array('revision-published diff-revision'), ); } } @@ -64,17 +71,13 @@ function theme_diff_node_revisions($vars) { 'header' => $header, 'rows' => $rows, 'sticky' => FALSE, - 'attributes' => array('class' => 'diff-revisions'), + 'attributes' => array('class' => array('diff-revisions')), )); $output .= drupal_render_children($form); return $output; } -/** - * Theme functions - */ - /** * Theme function for a header line in the diff. */ @@ -139,11 +142,15 @@ function theme_diff_inline_chunk($vars) { switch ($vars['type']) { case 'add': return "{$vars['text']}"; + case 'change': return "{$vars['text']}"; + case 'delete': return "{$vars['text']}"; + default: return $vars['text']; + } } diff --git a/sites/all/modules/contrib/content/diff/diff.tokens.inc b/sites/all/modules/contrib/content/diff/diff.tokens.inc index 96dbd80a..605d2e43 100644 --- a/sites/all/modules/contrib/content/diff/diff.tokens.inc +++ b/sites/all/modules/contrib/content/diff/diff.tokens.inc @@ -38,13 +38,13 @@ function diff_tokens($type, $tokens, array $data = array(), array $options = arr // Basic diff standard comparison information. case 'diff': case 'diff-markdown': - $revisons = node_revision_list($node); - if (count($revisons) == 1) { + $revisions = node_revision_list($node); + if (count($revisions) == 1) { $replacements[$original] = t('(No previous revision available.)'); } else { module_load_include('inc', 'diff', 'diff.pages'); - $old_vid = _diff_get_previous_vid($revisons, $node->vid); + $old_vid = _diff_get_previous_vid($revisions, $node->vid); $state = $name == 'diff' ? 'raw' : 'raw_plain'; $build = diff_diffs_show($node, $old_vid, $node->vid, $state); unset($build['diff_table']['#rows']['states']); @@ -52,7 +52,10 @@ function diff_tokens($type, $tokens, array $data = array(), array $options = arr unset($build['diff_preview']); $output = drupal_render_children($build); - $replacements[$original] = $sanitize ? check_plain($output) : $output; + if ($sanitize) { + $output = filter_xss($output, array('a', 'em', 'strong', 'cite', 'blockquote', 'code', 'ul', 'ol', 'li', 'dl', 'dt', 'dd', 'table', 'tr', 'th', 'td')); + } + $replacements[$original] = $output; } break; diff --git a/sites/all/modules/contrib/content/diff/includes/file.inc b/sites/all/modules/contrib/content/diff/includes/file.inc index 678ff466..575e8498 100644 --- a/sites/all/modules/contrib/content/diff/includes/file.inc +++ b/sites/all/modules/contrib/content/diff/includes/file.inc @@ -67,7 +67,8 @@ function file_field_diff_view($items, $context) { if ($settings['compare_display_field'] && !empty($field['settings']['display_field'])) { $output['display'] = $item['display'] ? t('Displayed') : t('Hidden'); } - $diff_items[$delta] = implode('; ', $output); + $separator = $settings['property_separator'] == 'nl' ? "\n" : $settings['property_separator']; + $diff_items[$delta] = implode($separator, $output); } } @@ -82,6 +83,7 @@ function file_field_diff_default_options($field_type) { 'show_id' => 0, 'compare_display_field' => 0, 'compare_description_field' => 0, + 'property_separator' => '; ', ); } @@ -107,5 +109,21 @@ function file_field_diff_options_form($field_type, $settings) { '#default_value' => $settings['compare_display_field'], '#description' => t('This is only used if the "Enable Display field" is checked in the field settings.'), ); + $options_form['property_separator'] = array( + '#type' => 'select', + '#title' => t('Property separator'), + '#default_value' => $settings['property_separator'], + '#description' => t('Provides the ability to show properties inline or across multiple lines.'), + '#options' => array( + ', ' => t('Comma (,)'), + '; ' => t('Semicolon (;)'), + ' ' => t('Space'), + 'nl' => t('New line'), + ), + ); + // Allow users to set their own separator using variable_set(). + if (!isset($options_form['#options'][$settings['property_separator']])) { + $options_form['#options'][$settings['property_separator']] = $settings['property_separator']; + } return $options_form; } diff --git a/sites/all/modules/contrib/content/diff/includes/image.inc b/sites/all/modules/contrib/content/diff/includes/image.inc index cb93616d..b41753e1 100644 --- a/sites/all/modules/contrib/content/diff/includes/image.inc +++ b/sites/all/modules/contrib/content/diff/includes/image.inc @@ -68,7 +68,8 @@ function image_field_diff_view($items, $context) { if ($settings['show_id']) { $output[] = t('File ID: !fid', $t_args); } - $diff_items[$delta] = implode('; ', $output); + $separator = $settings['property_separator'] == 'nl' ? "\n" : $settings['property_separator']; + $diff_items[$delta] = implode($separator, $output); } } @@ -83,6 +84,7 @@ function image_field_diff_default_options($field_type) { 'show_id' => 0, 'compare_alt_field' => 0, 'compare_title_field' => 0, + 'property_separator' => '; ', ); } @@ -108,5 +110,21 @@ function image_field_diff_options_form($field_type, $settings) { '#default_value' => $settings['compare_title_field'], '#description' => t('This is only used if the "Enable Title field" is checked in the instance settings.'), ); + $options_form['property_separator'] = array( + '#type' => 'select', + '#title' => t('Property separator'), + '#default_value' => $settings['property_separator'], + '#description' => t('Provides the ability to show properties inline or across multiple lines.'), + '#options' => array( + ', ' => t('Comma (,)'), + '; ' => t('Semicolon (;)'), + ' ' => t('Space'), + 'nl' => t('New line'), + ), + ); + // Allow users to set their own separator using variable_set(). + if (!isset($options_form['#options'][$settings['property_separator']])) { + $options_form['#options'][$settings['property_separator']] = $settings['property_separator']; + } return $options_form; } diff --git a/sites/all/modules/contrib/content/diff/includes/node.inc b/sites/all/modules/contrib/content/diff/includes/node.inc index 3f0bca33..9cab7a68 100644 --- a/sites/all/modules/contrib/content/diff/includes/node.inc +++ b/sites/all/modules/contrib/content/diff/includes/node.inc @@ -6,102 +6,199 @@ */ /** - * Implements hook_entity_diff(). - * - * This function compares core node properties. This is currently limited to: - * - title: The title of the node. - * - * @param object $old_node - * The older node revision. - * @param object $new_node - * The newer node revision. - * @param array $context - * An associative array containing: - * - entity_type: The entity type; e.g., 'node' or 'user'. - * - old_entity: The older entity. - * - new_entity: The newer entity. - * - view_mode: The view mode to use. Defaults to FALSE. If no view mode is - * given, the recommended fallback view mode is 'default'. - * - states: An array of view states. These could be one of: - * - raw: The raw value of the diff, the classic 7.x-2.x view. - * - rendered: The rendered HTML as determined by the view mode. Only - * return markup for this state if the value is normally shown - * by this view mode. The user will most likely be able to see - * the raw or raw_plain state, so this is optional. - * - * The rendering state is a work in progress. - * - * Conditionally, you can get these states, but setting these will override - * the user selectable markdown method. - * - * - raw_plain: As raw, but text should be markdowned. - * - rendered_plain: As rendered, but text should be markdowned. - * - * @return array - * An associative array of values keyed by the entity property. - * - * This is effectively an unnested Form API-like structure. - * - * States are returned as follows: - * - * $results['line'] = array( - * '#name' => t('Line'), - * '#states' => array( - * 'raw' => array( - * '#old' => 'This was the old line number [tag].
', - * '#new' => 'This is the new line [tag].
', - * ), - * 'rendered' => array( - * '#old' => 'This was the old line number 57.
', - * '#new' => 'This is the new line 57.
', - * ), - * ), - * ); - * - * For backwards compatability, no changes are required to support states, - * but it is recommended to provide a better UI for end users. - * - * For example, the following example is equivalent to returning the raw - * state from the example above. - * - * $results['line'] = array( - * '#name' => t('Line'), - * '#old' => 'This was the old line number [tag].
', - * '#new' => 'This is the new line [tag].
', - * ); + * Private callback function to render the title field. */ -function node_entity_diff($old_node, $new_node, $context) { - $result = array(); - if ($context['entity_type'] == 'node') { - $type = node_type_get_type($new_node); - $result['title'] = array( - '#name' => $type->title_label, - '#states' => array(), - '#weight' => -5, - '#settings' => array( - // Global setting - 'diff_show_header_' . $entity_type - 'show_header' => variable_get('diff_show_header_node', 1), - ), - ); - foreach ($context['states'] as $state) { - switch ($state) { - case 'rendered': - $result['title']['#states'][$state] = array( - '#old' => l($old_node->title, 'node/' . $old_node->title), - '#new' => l($new_node->title, 'node/' . $new_node->title), - ); - break; +function _node_entity_diff_additional_options_title($old_node, $new_node, $context) { + $type = node_type_get_type($new_node); + $row = array( + '#name' => $type->title_label, + '#states' => array(), + '#weight' => -5, + '#settings' => array( + 'show_header' => variable_get('diff_show_header_node', 1), + ), + ); + foreach ($context['states'] as $state) { + switch ($state) { + case 'rendered': + $row['#states'][$state] = array( + '#old' => l($old_node->title, 'node/' . $old_node->title), + '#new' => l($new_node->title, 'node/' . $new_node->title), + ); + break; - // We specify a default so that the title is allows compared. - case 'raw': - default: - $result['title']['#states'][$state] = array( - '#old' => array($old_node->title), - '#new' => array($new_node->title), - ); - break; - } + // We specify a default so that the title is allows compared. + case 'raw': + default: + $row['#states'][$state] = array( + '#old' => array($old_node->title), + '#new' => array($new_node->title), + ); + break; } } - return $result; + return $row; +} + +/** + * Private callback function to render the type field. + */ +function _node_entity_diff_additional_options_type($old_node, $new_node, $context) { + $row = array( + '#name' => t('Content type'), + '#states' => array(), + '#weight' => -4, + '#settings' => array(), + ); + $old_type = node_type_get_type($old_node); + $new_type = node_type_get_type($new_node); + + foreach ($context['states'] as $state) { + $row['#states'][$state] = array( + '#old' => array($old_type ? $old_type->name : t('Deleted type !type', array('!type' => $old_node->type))), + '#new' => array($new_type ? $new_type->name : t('Deleted type !type', array('!type' => $new_node->type))), + ); + } + return $row; +} + +/** + * Private callback function to render the author field. + */ +function _node_entity_diff_additional_options_author($old_node, $new_node, $context) { + $old_author = user_load($old_node->uid); + $new_author = user_load($new_node->uid); + return _node_entity_diff_additional_options_account(t('Author'), $old_author, $new_author, $context, -4); +} + +/** + * Private callback function to render the revision_author field. + */ +function _node_entity_diff_additional_options_revision_author($old_node, $new_node, $context) { + $old_author = user_load($old_node->revision_uid); + $new_author = user_load($new_node->revision_uid); + return _node_entity_diff_additional_options_account(t('Revision author'), $old_author, $new_author, $context, -3.9); +} + +/** + * Private callback function to render the author field. + */ +function _node_entity_diff_additional_options_account($label, $old_author, $new_author, $context, $weight = 0) { + $row = array( + '#name' => $label, + '#states' => array(), + '#weight' => $weight, + '#settings' => array(), + ); + foreach ($context['states'] as $state) { + $row['#states'][$state] = array( + '#old' => array($old_author ? format_username($old_author) : t('Deleted user')), + '#new' => array($new_author ? format_username($new_author) : t('Deleted user')), + ); + } + return $row; +} + +/** + * Private callback function to render the status, sticky and published field. + */ +function _node_entity_diff_additional_options_publishing_flags($old_node, $new_node, $context) { + $row = array( + '#name' => t('Publishing options'), + '#states' => array(), + '#weight' => -3, + '#settings' => array(), + ); + $old_options = array($old_node->status ? t('Published') : t('Unpublished')); + if ($old_node->promote) { + $old_options[] = t('Promoted to front page'); + } + if ($old_node->sticky) { + $old_options[] = t('Sticky at top of lists'); + } + + $new_options = array($new_node->status ? t('Published') : t('Unpublished')); + if ($new_node->promote) { + $new_options[] = t('Promoted to front page'); + } + if ($new_node->sticky) { + $new_options[] = t('Sticky at top of lists'); + } + + foreach ($context['states'] as $state) { + $row['#states'][$state] = array( + '#old' => $old_options, + '#new' => $new_options, + ); + } + return $row; +} + +/** + * Private callback function to render the created field. + */ +function _node_entity_diff_additional_options_created($old_node, $new_node, $context) { + return _node_entity_diff_additional_options_date_field(t('Created timestamp'), $old_node->created, $new_node->created, $context, -1); +} + +/** + * Private callback function to render the changed field. + */ +function _node_entity_diff_additional_options_changed($old_node, $new_node, $context) { + return _node_entity_diff_additional_options_date_field(t('Changed timestamp'), $old_node->changed, $new_node->changed, $context, -1); +} + +/** + * Private callback function to render the revision_timestamp field. + */ +function _node_entity_diff_additional_options_revision_timestamp($old_node, $new_node, $context) { + return _node_entity_diff_additional_options_date_field(t('Revision timestamp'), $old_node->revision_timestamp, $new_node->revision_timestamp, $context, -1); +} + +/** + * Helper function to render the date flags. + */ +function _node_entity_diff_additional_options_date_field($label, $old_date, $new_date, $context, $weight = 0) { + $row = array( + '#name' => $label, + '#states' => array(), + '#weight' => $weight, + '#settings' => array(), + ); + + foreach ($context['states'] as $state) { + $row['#states'][$state] = array( + '#old' => array(format_date($old_date)), + '#new' => array(format_date($new_date)), + ); + } + return $row; +} + +/** + * Private callback function to render the comment field. + */ +function _node_entity_diff_additional_options_comment($old_node, $new_node, $context) { + if (!module_exists('comment')) { + return array(); + } + $row = array( + '#name' => t('Comment setting'), + '#states' => array(), + '#weight' => -1, + '#settings' => array(), + ); + $options = array( + COMMENT_NODE_OPEN => t('Open'), + COMMENT_NODE_CLOSED => t('Closed'), + COMMENT_NODE_HIDDEN => t('Hidden'), + ); + + foreach ($context['states'] as $state) { + $row['#states'][$state] = array( + '#old' => array($options[$old_node->comment]), + '#new' => array($options[$new_node->comment]), + ); + } + return $row; } diff --git a/sites/all/modules/contrib/content/diff/includes/user.inc b/sites/all/modules/contrib/content/diff/includes/user.inc new file mode 100644 index 00000000..7ebd5664 --- /dev/null +++ b/sites/all/modules/contrib/content/diff/includes/user.inc @@ -0,0 +1,148 @@ + t('Username'), + '#states' => array(), + '#weight' => -5, + '#settings' => array( + 'show_header' => variable_get('diff_show_header_user', 1), + ), + ); + foreach ($context['states'] as $state) { + switch ($state) { + case 'rendered': + $row['#states'][$state] = array( + '#old' => theme('username', array('account' => $old_user)), + '#new' => theme('username', array('account' => $old_user)), + ); + break; + + // We specify a default so that the name is always compared. + case 'raw': + default: + $row['#states'][$state] = array( + '#old' => array($old_user->name), + '#new' => array($new_user->name), + ); + break; + } + } + return $row; +} + +/** + * Private callback function to render the mail field. + */ +function _user_entity_diff_additional_options_mail($old_user, $new_user, $context) { + $row = array( + '#name' => t('E-mail address'), + '#states' => array(), + '#weight' => -4, + '#settings' => array(), + ); + + foreach ($context['states'] as $state) { + $row['#states'][$state] = array( + '#old' => array($old_user->mail), + '#new' => array($new_user->mail), + ); + } + return $row; +} + +/** + * Private callback function to render the status field. + */ +function _user_entity_diff_additional_options_status($old_user, $new_user, $context) { + $row = array( + '#name' => t('Status'), + '#states' => array(), + '#weight' => -3, + '#settings' => array(), + ); + + foreach ($context['states'] as $state) { + $row['#states'][$state] = array( + '#old' => array($old_user->status ? t('Active') : t('Blocked')), + '#new' => array($new_user->status ? t('Active') : t('Blocked')), + ); + } + return $row; +} + +/** + * Private callback function to render the timezone field. + */ +function _user_entity_diff_additional_options_timezone($old_user, $new_user, $context) { + $row = array( + '#name' => t('Time zone'), + '#states' => array(), + '#weight' => -1, + '#settings' => array(), + ); + $system_time_zones = system_time_zones(TRUE); + $old_zone = isset($old_user->timezone) ? $old_user->timezone : ''; + $new_zone = isset($new_user->timezone) ? $new_user->timezone : ''; + + foreach ($context['states'] as $state) { + $row['#states'][$state] = array( + '#old' => array(isset($system_time_zones[$old_zone]) ? $system_time_zones[$old_zone] : t('- None selected -')), + '#new' => array(isset($system_time_zones[$new_zone]) ? $system_time_zones[$new_zone] : t('- None selected -')), + ); + } + return $row; +} + +/** + * Private callback function to render the password field. + */ +function _user_entity_diff_additional_options_password($old_user, $new_user, $context) { + $row = array( + '#name' => t('Password Hash'), + '#states' => array(), + '#weight' => -1, + '#settings' => array(), + ); + + foreach ($context['states'] as $state) { + $row['#states'][$state] = array( + '#old' => array($old_user->pass), + '#new' => array($new_user->pass), + ); + } + return $row; +} + +/** + * Private callback function to render the roles field. + */ +function _user_entity_diff_additional_options_roles($old_user, $new_user, $context) { + $row = array( + '#name' => t('Roles'), + '#states' => array(), + '#weight' => -1, + '#settings' => array(), + ); + + $roles = user_roles(TRUE); + unset($roles[DRUPAL_AUTHENTICATED_RID]); + foreach ($context['states'] as $state) { + $row['#states'][$state] = array( + '#old' => array(implode("\n", array_intersect_key($roles, $old_user->roles))), + '#new' => array(implode("\n", array_intersect_key($roles, $new_user->roles))), + ); + } + return $row; +} diff --git a/sites/all/modules/contrib/content/diff/js/diff.js b/sites/all/modules/contrib/content/diff/js/diff.js index 2c873e9f..5b63d7b1 100644 --- a/sites/all/modules/contrib/content/diff/js/diff.js +++ b/sites/all/modules/contrib/content/diff/js/diff.js @@ -1,58 +1,65 @@ (function ($) { -Drupal.behaviors.diffRevisions = { - attach: function (context, settings) { - var $rows = $('table.diff-revisions tbody tr'); - function updateDiffRadios() { - var newTd = false; - var oldTd = false; - if (!$rows.length) { - return true; - } - $rows.removeClass('selected').each(function() { - var $row = $(this); - $row.removeClass('selected'); - var $inputs = $row.find('input[type="radio"]'); - var $oldRadio = $inputs.filter('[name="old"]').eq(0); - var $newRadio = $inputs.filter('[name="new"]').eq(0); - if (!$oldRadio.length || !$newRadio.length) { + "use strict"; + + Drupal.behaviors.diffRevisions = { + attach: function (context, settings) { + var $rows = $('table.diff-revisions tbody tr'); + function updateDiffRadios() { + var newTd = false; + var oldTd = false; + if (!$rows.length) { return true; } - if ($oldRadio.attr('checked')) { - oldTd = true; - $row.addClass('selected'); - $oldRadio.css('visibility', 'visible'); - $newRadio.css('visibility', 'hidden'); - } else if ($newRadio.attr('checked')) { - newTd = true; - $row.addClass('selected'); - $oldRadio.css('visibility', 'hidden'); - $newRadio.css('visibility', 'visible'); - } else { - if (Drupal.settings.diffRevisionRadios == 'linear') { - if (newTd && oldTd) { - $oldRadio.css('visibility', 'visible'); - $newRadio.css('visibility', 'hidden'); - } else if (newTd) { - $newRadio.css('visibility', 'visible'); - $oldRadio.css('visibility', 'visible'); - } else { - $newRadio.css('visibility', 'visible'); - $oldRadio.css('visibility', 'hidden'); - } - } else { - $newRadio.css('visibility', 'visible'); - $oldRadio.css('visibility', 'visible'); + $rows.removeClass('selected').each(function() { + var $row = $(this); + $row.removeClass('selected'); + var $inputs = $row.find('input[type="radio"]'); + var $oldRadio = $inputs.filter('[name="old"]').eq(0); + var $newRadio = $inputs.filter('[name="new"]').eq(0); + if (!$oldRadio.length || !$newRadio.length) { + return true; } - } - }); - return true; + if ($oldRadio.attr('checked')) { + oldTd = true; + $row.addClass('selected'); + $oldRadio.css('visibility', 'visible'); + $newRadio.css('visibility', 'hidden'); + } + else if ($newRadio.attr('checked')) { + newTd = true; + $row.addClass('selected'); + $oldRadio.css('visibility', 'hidden'); + $newRadio.css('visibility', 'visible'); + } + else { + if (Drupal.settings.diffRevisionRadios == 'linear') { + if (newTd && oldTd) { + $oldRadio.css('visibility', 'visible'); + $newRadio.css('visibility', 'hidden'); + } + else if (newTd) { + $newRadio.css('visibility', 'visible'); + $oldRadio.css('visibility', 'visible'); + } + else { + $newRadio.css('visibility', 'visible'); + $oldRadio.css('visibility', 'hidden'); + } + } + else { + $newRadio.css('visibility', 'visible'); + $oldRadio.css('visibility', 'visible'); + } + } + }); + return true; + } + if (Drupal.settings.diffRevisionRadios) { + $rows.find('input[name="new"], input[name="old"]').click(updateDiffRadios); + updateDiffRadios(); + } } - if (Drupal.settings.diffRevisionRadios) { - $rows.find('input[name="new"], input[name="old"]').click(updateDiffRadios); - updateDiffRadios(); - } - } -}; + }; })(jQuery); diff --git a/sites/all/modules/contrib/content/diff/readme.txt b/sites/all/modules/contrib/content/diff/readme.txt index f82db821..f5164666 100644 --- a/sites/all/modules/contrib/content/diff/readme.txt +++ b/sites/all/modules/contrib/content/diff/readme.txt @@ -58,13 +58,16 @@ e.g. http://www.example.com/admin/structure/types/manage/page i) "Show View changes button on node edit form" adds a new "Preview" like submit button to node editing pages. This shows a diff preview. + + This can be conditionally restricted per role using the user permission + "Access View changes button". ii) "Enable the Revisions page for this content type" adds the revisioning tab to content. This allows users to compare between various revisions that they have access to. iii) "Standard comparison preview" option allows you to control how the most - current revision is show on the revision comparision page. + current revision is shown on the revision comparison page. b) Publishing options diff --git a/sites/all/modules/contrib/dev/ctools/bulk_export/bulk_export.info b/sites/all/modules/contrib/dev/ctools/bulk_export/bulk_export.info index d9e4dfc8..22dc566a 100644 --- a/sites/all/modules/contrib/dev/ctools/bulk_export/bulk_export.info +++ b/sites/all/modules/contrib/dev/ctools/bulk_export/bulk_export.info @@ -6,9 +6,9 @@ package = Chaos tool suite version = CTOOLS_MODULE_VERSION -; Information added by Drupal.org packaging script on 2016-10-16 -version = "7.x-1.11" +; Information added by Drupal.org packaging script on 2016-11-22 +version = "7.x-1.12" core = "7.x" project = "ctools" -datestamp = "1476581654" +datestamp = "1479787162" diff --git a/sites/all/modules/contrib/dev/ctools/css/button.css b/sites/all/modules/contrib/dev/ctools/css/button.css index 15e484be..ead8f8ef 100644 --- a/sites/all/modules/contrib/dev/ctools/css/button.css +++ b/sites/all/modules/contrib/dev/ctools/css/button.css @@ -19,6 +19,7 @@ .ctools-button-processed .ctools-content ul { list-style-image: none; list-style-type: none; + margin-left: 0; } .ctools-button-processed li { diff --git a/sites/all/modules/contrib/dev/ctools/ctools.api.php b/sites/all/modules/contrib/dev/ctools/ctools.api.php index a7ab7839..f328a7ca 100644 --- a/sites/all/modules/contrib/dev/ctools/ctools.api.php +++ b/sites/all/modules/contrib/dev/ctools/ctools.api.php @@ -199,7 +199,10 @@ function hook_ctools_render_alter(&$info, &$page, &$context) { * or categories or to rename content on specific sites. */ function hook_ctools_content_subtype_alter($subtype, $plugin) { - $subtype['render last'] = TRUE; + // Force a particular subtype of a particular plugin to render last. + if ($plugin['module'] == 'some_plugin_module' && $plugin['name'] == 'some_plugin_name' && $subtype['subtype_id'] == 'my_subtype_id') { + $subtype['render last'] = TRUE; + } } /** diff --git a/sites/all/modules/contrib/dev/ctools/ctools.info b/sites/all/modules/contrib/dev/ctools/ctools.info index bdd3794c..3a2d031e 100644 --- a/sites/all/modules/contrib/dev/ctools/ctools.info +++ b/sites/all/modules/contrib/dev/ctools/ctools.info @@ -6,11 +6,19 @@ files[] = includes/context.inc files[] = includes/css-cache.inc files[] = includes/math-expr.inc files[] = includes/stylizer.inc -files[] = tests/css_cache.test -; Information added by Drupal.org packaging script on 2016-10-16 -version = "7.x-1.11" +; Tests. +files[] = tests/context.test +files[] = tests/css.test +files[] = tests/css_cache.test +files[] = tests/ctools.plugins.test +files[] = tests/math_expression.test +files[] = tests/math_expression_stack.test +files[] = tests/object_cache.test + +; Information added by Drupal.org packaging script on 2016-11-22 +version = "7.x-1.12" core = "7.x" project = "ctools" -datestamp = "1476581654" +datestamp = "1479787162" diff --git a/sites/all/modules/contrib/dev/ctools/ctools_access_ruleset/ctools_access_ruleset.info b/sites/all/modules/contrib/dev/ctools/ctools_access_ruleset/ctools_access_ruleset.info index 8d5a77c4..bfa17834 100644 --- a/sites/all/modules/contrib/dev/ctools/ctools_access_ruleset/ctools_access_ruleset.info +++ b/sites/all/modules/contrib/dev/ctools/ctools_access_ruleset/ctools_access_ruleset.info @@ -5,9 +5,9 @@ package = Chaos tool suite version = CTOOLS_MODULE_VERSION dependencies[] = ctools -; Information added by Drupal.org packaging script on 2016-10-16 -version = "7.x-1.11" +; Information added by Drupal.org packaging script on 2016-11-22 +version = "7.x-1.12" core = "7.x" project = "ctools" -datestamp = "1476581654" +datestamp = "1479787162" diff --git a/sites/all/modules/contrib/dev/ctools/ctools_ajax_sample/ctools_ajax_sample.info b/sites/all/modules/contrib/dev/ctools/ctools_ajax_sample/ctools_ajax_sample.info index dcb634d7..52126d51 100644 --- a/sites/all/modules/contrib/dev/ctools/ctools_ajax_sample/ctools_ajax_sample.info +++ b/sites/all/modules/contrib/dev/ctools/ctools_ajax_sample/ctools_ajax_sample.info @@ -5,9 +5,9 @@ version = CTOOLS_MODULE_VERSION dependencies[] = ctools core = 7.x -; Information added by Drupal.org packaging script on 2016-10-16 -version = "7.x-1.11" +; Information added by Drupal.org packaging script on 2016-11-22 +version = "7.x-1.12" core = "7.x" project = "ctools" -datestamp = "1476581654" +datestamp = "1479787162" diff --git a/sites/all/modules/contrib/dev/ctools/ctools_custom_content/ctools_custom_content.info b/sites/all/modules/contrib/dev/ctools/ctools_custom_content/ctools_custom_content.info index 715e4539..ee2d2d1e 100644 --- a/sites/all/modules/contrib/dev/ctools/ctools_custom_content/ctools_custom_content.info +++ b/sites/all/modules/contrib/dev/ctools/ctools_custom_content/ctools_custom_content.info @@ -5,9 +5,9 @@ package = Chaos tool suite version = CTOOLS_MODULE_VERSION dependencies[] = ctools -; Information added by Drupal.org packaging script on 2016-10-16 -version = "7.x-1.11" +; Information added by Drupal.org packaging script on 2016-11-22 +version = "7.x-1.12" core = "7.x" project = "ctools" -datestamp = "1476581654" +datestamp = "1479787162" diff --git a/sites/all/modules/contrib/dev/ctools/ctools_plugin_example/ctools_plugin_example.info b/sites/all/modules/contrib/dev/ctools/ctools_plugin_example/ctools_plugin_example.info index 97b3ebfe..337e699d 100644 --- a/sites/all/modules/contrib/dev/ctools/ctools_plugin_example/ctools_plugin_example.info +++ b/sites/all/modules/contrib/dev/ctools/ctools_plugin_example/ctools_plugin_example.info @@ -8,9 +8,9 @@ dependencies[] = page_manager dependencies[] = advanced_help core = 7.x -; Information added by Drupal.org packaging script on 2016-10-16 -version = "7.x-1.11" +; Information added by Drupal.org packaging script on 2016-11-22 +version = "7.x-1.12" core = "7.x" project = "ctools" -datestamp = "1476581654" +datestamp = "1479787162" diff --git a/sites/all/modules/contrib/dev/ctools/drush/ctools.drush.inc b/sites/all/modules/contrib/dev/ctools/drush/ctools.drush.inc index 1862dbe9..0342c734 100644 --- a/sites/all/modules/contrib/dev/ctools/drush/ctools.drush.inc +++ b/sites/all/modules/contrib/dev/ctools/drush/ctools.drush.inc @@ -64,7 +64,7 @@ function ctools_drush_command() { 'machine names' => 'Space separated list of exportables you want to view.', ), 'options' => array( - 'indent' => 'The string to use for indentation when dispalying the exportable export code. Defaults to \'\'.', + 'indent' => 'The string to use for indentation when displaying the exportable export code. Defaults to \'\'.', 'no-colour' => 'Remove any colour formatting from export string output. Ideal if you are sending the output of this command to a file.', 'module' => $module_text, 'all' => $all_text, diff --git a/sites/all/modules/contrib/dev/ctools/includes/content.inc b/sites/all/modules/contrib/dev/ctools/includes/content.inc index ae1c6073..6490d8d5 100644 --- a/sites/all/modules/contrib/dev/ctools/includes/content.inc +++ b/sites/all/modules/contrib/dev/ctools/includes/content.inc @@ -155,6 +155,11 @@ function ctools_content_get_subtypes($type) { // Walk through the subtypes and ensure minimal settings are // retained. foreach ($subtypes as $id => $subtype) { + // Ensure that the 'subtype_id' value exists. + if (!isset($subtype['subtype_id'])) { + $subtype['subtype_id'] = $id; + } + // Use exact name since this is a modify by reference. ctools_content_prepare_subtype($subtypes[$id], $plugin); } @@ -217,6 +222,7 @@ function ctools_content_prepare_subtype(&$subtype, $plugin) { } } + // Trigger hook_ctools_content_subtype_alter(). drupal_alter('ctools_content_subtype', $subtype, $plugin); } @@ -241,8 +247,8 @@ function ctools_content_prepare_subtype(&$subtype, $plugin) { * Any incoming content, if this display is a wrapper. * * @return - * The content as rendered by the plugin. This content should be an array - * with the following possible keys: + * The content as rendered by the plugin, or NULL. + * This content should be an object with the following possible properties: * - title: The safe to render title of the content. * - title_heading: The title heading. * - content: The safe to render HTML content. diff --git a/sites/all/modules/contrib/dev/ctools/includes/context-access-admin.inc b/sites/all/modules/contrib/dev/ctools/includes/context-access-admin.inc index 76643cf6..ea2a7c81 100644 --- a/sites/all/modules/contrib/dev/ctools/includes/context-access-admin.inc +++ b/sites/all/modules/contrib/dev/ctools/includes/context-access-admin.inc @@ -367,7 +367,6 @@ function ctools_access_ajax_edit($fragment = NULL, $id = NULL) { 'contexts' => $contexts, 'title' => t('Edit criteria'), 'ajax' => TRUE, - 'ajax' => TRUE, 'modal' => TRUE, 'modal return' => TRUE, ); diff --git a/sites/all/modules/contrib/dev/ctools/includes/context.inc b/sites/all/modules/contrib/dev/ctools/includes/context.inc index 8b6d6032..a532f657 100644 --- a/sites/all/modules/contrib/dev/ctools/includes/context.inc +++ b/sites/all/modules/contrib/dev/ctools/includes/context.inc @@ -676,14 +676,19 @@ function ctools_context_keyword_substitute($string, $keywords, $contexts, $conve } } - if (empty($context_keywords[$context]) || !empty($context_keywords[$context]->empty)) { - $keywords['%' . $keyword] = ''; - } - else if (!empty($converter)) { - $keywords['%' . $keyword] = ctools_context_convert_context($context_keywords[$context], $converter, $converter_options); + if (!isset($context_keywords[$context])) { + $keywords['%' . $keyword] = '%' . $keyword; } else { - $keywords['%' . $keyword] = $context_keywords[$keyword]->title; + if (empty($context_keywords[$context]) || !empty($context_keywords[$context]->empty)) { + $keywords['%' . $keyword] = ''; + } + else if (!empty($converter)) { + $keywords['%' . $keyword] = ctools_context_convert_context($context_keywords[$context], $converter, $converter_options); + } + else { + $keywords['%' . $keyword] = $context_keywords[$keyword]->title; + } } } } diff --git a/sites/all/modules/contrib/dev/ctools/includes/plugins.inc b/sites/all/modules/contrib/dev/ctools/includes/plugins.inc index 65f36629..d524f746 100644 --- a/sites/all/modules/contrib/dev/ctools/includes/plugins.inc +++ b/sites/all/modules/contrib/dev/ctools/includes/plugins.inc @@ -200,18 +200,18 @@ function ctools_plugin_api_get_hook($owner, $api) { /** * Fetch a group of plugins by name. * - * @param $module - * The name of the module that utilizes this plugin system. It will be - * used to call hook_ctools_plugin_$plugin() to get more data about the plugin. - * @param $type + * @param string $module + * The name of the module that utilizes this plugin system. It will be used to + * get more data about the plugin as defined on hook_ctools_plugin_type(). + * @param string $type * The type identifier of the plugin. - * @param $id + * @param string $id * If specified, return only information about plugin with this identifier. * The system will do its utmost to load only plugins with this id. * - * @return - * An array of information arrays about the plugins received. The contents - * of the array are specific to the plugin. + * @return array + * An array of information arrays about the plugins received. The contents of + * the array are specific to the plugin. */ function ctools_get_plugins($module, $type, $id = NULL) { // Store local caches of plugins and plugin info so we don't have to do full @@ -224,10 +224,14 @@ function ctools_get_plugins($module, $type, $id = NULL) { $info = ctools_plugin_get_plugin_type_info(); - // Bail out noisily if an invalid module/type combination is requested. if (!isset($info[$module][$type])) { - watchdog('ctools', 'Invalid plugin module/type combination requested: module @module and type @type', array('@module' => $module, '@type' => $type), WATCHDOG_ERROR); - return array(); + // If we don't find the plugin we attempt a cache rebuild before bailing out + $info = ctools_plugin_get_plugin_type_info(TRUE); + // Bail out noisily if an invalid module/type combination is requested. + if (!isset($info[$module][$type])) { + watchdog('ctools', 'Invalid plugin module/type combination requested: module @module and type @type', array('@module' => $module, '@type' => $type), WATCHDOG_ERROR); + return array(); + } } // Make sure our plugins array is populated. @@ -235,8 +239,8 @@ function ctools_get_plugins($module, $type, $id = NULL) { $plugins[$module][$type] = array(); } - // Attempt to shortcut this whole piece of code if we already have - // the requested plugin: + // Attempt to shortcut this whole piece of code if we already have the + // requested plugin: if ($id && array_key_exists($id, $plugins[$module][$type])) { return $plugins[$module][$type][$id]; } @@ -271,8 +275,8 @@ function ctools_get_plugins($module, $type, $id = NULL) { $plugins[$module][$type] = ctools_plugin_load_hooks($info[$module][$type]); } - // Then see if we should load all files. We only do this if we - // want a list of all plugins or there was a cache miss. + // Then see if we should load all files. We only do this if we want a list of + // all plugins or there was a cache miss. if (empty($setup[$module][$type]) && ($build_cache || !$id)) { $setup[$module][$type] = TRUE; $plugins[$module][$type] = array_merge($plugins[$module][$type], ctools_plugin_load_includes($info[$module][$type])); @@ -296,8 +300,8 @@ function ctools_get_plugins($module, $type, $id = NULL) { } - // If we were told earlier that this is cacheable and the cache was - // empty, give something back. + // If we were told earlier that this is cacheable and the cache was empty, + // give something back. if ($build_cache) { cache_set("plugins:$module:$type", $plugins[$module][$type], $info[$module][$type]['cache table']); } diff --git a/sites/all/modules/contrib/dev/ctools/includes/uuid.inc b/sites/all/modules/contrib/dev/ctools/includes/uuid.inc index 6e4c42c3..13897f1f 100644 --- a/sites/all/modules/contrib/dev/ctools/includes/uuid.inc +++ b/sites/all/modules/contrib/dev/ctools/includes/uuid.inc @@ -9,7 +9,9 @@ /** * Pattern for detecting a valid UUID. */ -define('UUID_PATTERN', '[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}'); +if (!defined('UUID_PATTERN')) { + define('UUID_PATTERN', '[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}'); +} /** * Generates a UUID using the Windows internal GUID generator. diff --git a/sites/all/modules/contrib/dev/ctools/page_manager/help/getting-started.html b/sites/all/modules/contrib/dev/ctools/page_manager/help/getting-started.html index 4e4f24ae..6a75a370 100644 --- a/sites/all/modules/contrib/dev/ctools/page_manager/help/getting-started.html +++ b/sites/all/modules/contrib/dev/ctools/page_manager/help/getting-started.html @@ -4,7 +4,7 @@ Note: this page is currently very preliminary. Please visit path = $form_state['values']['path']; $handlers = !empty($form_state['values']['handlers']) ? $form_state['page']->handlers : FALSE; + // Ensure the handler uuids are re-generated. + if ($handlers) { + foreach ($handlers as &$handler) { + if (isset($handler->conf['display']) && method_exists($handler->conf['display'], 'clone_display')) { + $handler->conf['display'] = $handler->conf['display']->clone_display(); + } + } + } + // Export the handler, which is a fantastic way to clean database IDs out of it. $export = page_manager_page_export($original, $handlers); ob_start(); diff --git a/sites/all/modules/contrib/dev/ctools/plugins/arguments/terms.inc b/sites/all/modules/contrib/dev/ctools/plugins/arguments/terms.inc index 4298ea91..d31f28de 100644 --- a/sites/all/modules/contrib/dev/ctools/plugins/arguments/terms.inc +++ b/sites/all/modules/contrib/dev/ctools/plugins/arguments/terms.inc @@ -65,6 +65,7 @@ function ctools_terms_breadcrumb($conf, $context) { return; } + $current = new stdClass(); $current->tid = $context->tids[0]; $breadcrumb = array(); while ($parents = taxonomy_get_parents($current->tid)) { diff --git a/sites/all/modules/contrib/dev/ctools/plugins/content_types/block/block.inc b/sites/all/modules/contrib/dev/ctools/plugins/content_types/block/block.inc index 4d4c31c3..46b02e9e 100644 --- a/sites/all/modules/contrib/dev/ctools/plugins/content_types/block/block.inc +++ b/sites/all/modules/contrib/dev/ctools/plugins/content_types/block/block.inc @@ -372,9 +372,9 @@ function profile_ctools_block_info($module, $delta, &$info) { } function book_ctools_block_info($module, $delta, &$info) { - // Hide the book navigation block which isn't as rich as what we can - // do with context. - $info = NULL; + $info['title'] = t('Book navigation menu'); + $info['icon'] = 'icon_core_block_menu.png'; + $info['category'] = t('Node'); } function blog_ctools_block_info($module, $delta, &$info) { diff --git a/sites/all/modules/contrib/dev/ctools/plugins/content_types/node_context/node_book_menu.inc b/sites/all/modules/contrib/dev/ctools/plugins/content_types/node_context/node_book_menu.inc new file mode 100644 index 00000000..84497c85 --- /dev/null +++ b/sites/all/modules/contrib/dev/ctools/plugins/content_types/node_context/node_book_menu.inc @@ -0,0 +1,101 @@ + TRUE, + 'title' => t('Book navigation menu'), + 'icon' => '../block/icon_core_block_menu.png', + 'description' => t('The book menu belonging to the current book node.'), + 'required context' => new ctools_context_required(t('Node'), 'node'), + 'category' => t('Node'), + ); +} + +function ctools_node_book_menu_content_type_render($subtype, $conf, $panel_args, $context) { + $node = isset($context->data) ? clone($context->data) : NULL; + $block = new stdClass(); + $block->module = 'book_menu'; + + if ($conf['override_title']) { + $block->title = t($conf['override_title_text']); + } + else { + $block->title = t('Book navigation menu'); + } + if ($node) { + $block->delta = $node->nid; + // TODO: the value is not available somehow?!? + $book_block_mode = isset($conf['book_block_mode']) ? $conf['book_block_mode'] : 'book pages'; + + // Code below is taken from function book_block_view(). + $current_bid = empty($node->book['bid']) ? 0 : $node->book['bid']; + + if ($book_block_mode === 'all pages') { + $block->subject = t('Book navigation'); + $book_menus = array(); + $pseudo_tree = array(0 => array('below' => FALSE)); + foreach (book_get_books() as $book_id => $book) { + if ($book['bid'] === $current_bid) { + // If the current page is a node associated with a book, the menu + // needs to be retrieved. + $book_menus[$book_id] = menu_tree_output(menu_tree_all_data($node->book['menu_name'], $node->book)); + } + else { + // Since we know we will only display a link to the top node, there + // is no reason to run an additional menu tree query for each book. + $book['in_active_trail'] = FALSE; + // Check whether user can access the book link. + $book_node = node_load($book['nid']); + $book['access'] = node_access('view', $book_node); + $pseudo_tree[0]['link'] = $book; + $book_menus[$book_id] = menu_tree_output($pseudo_tree); + } + } + $book_menus['#theme'] = 'book_all_books_block'; + $block->content = $book_menus; + } + elseif ($current_bid) { + // Only display this block when the user is browsing a book. + $select = db_select('node', 'n') + ->fields('n', array('title')) + ->condition('n.nid', $node->book['bid']) + ->addTag('node_access'); + $title = $select->execute()->fetchField(); + // Only show the block if the user has view access for the top-level node. + if ($title) { + $tree = menu_tree_all_data($node->book['menu_name'], $node->book); + // There should only be one element at the top level. + $data = array_shift($tree); + // TODO: subject is not rendered + $block->subject = theme('book_title_link', array('link' => $data['link'])); + $block->content = ($data['below']) ? menu_tree_output($data['below']) : ''; + } + } + } + else { + $block->content = t('Book navigation pager goes here.'); + $block->delta = 'unknown'; + } + + return $block; +} + +function ctools_node_book_menu_content_type_admin_title($subtype, $conf, $context) { + return t('"@s" book navigation pager', array('@s' => $context->identifier)); +} + +function ctools_node_book_menu_content_type_edit_form($form, &$form_state) { + // Grab block form from the book module. + $block_form = book_block_configure($delta = ''); + // TODO: this does not work yet. + // See TODO in: ctools_node_book_menu_content_type_render + if (isset($form_state['input']['book_block_mode'])) { + $block_form['book_block_mode']['#default_value'] = $form_state['input']['book_block_mode']; + } + $form += $block_form; + return $form; +} diff --git a/sites/all/modules/contrib/dev/ctools/plugins/content_types/node_context/node_book_nav.inc b/sites/all/modules/contrib/dev/ctools/plugins/content_types/node_context/node_book_nav.inc index 403db8d1..f0529b43 100644 --- a/sites/all/modules/contrib/dev/ctools/plugins/content_types/node_context/node_book_nav.inc +++ b/sites/all/modules/contrib/dev/ctools/plugins/content_types/node_context/node_book_nav.inc @@ -7,9 +7,9 @@ if (module_exists('book')) { */ $plugin = array( 'single' => TRUE, - 'title' => t('Book navigation'), - 'icon' => 'icon_node.png', - 'description' => t('The navigation menu the book the node belongs to.'), + 'title' => t('Book navigation pager'), + 'icon' => '../block/icon_core_booknavigation.png', + 'description' => t('The navigational pager and sub pages of the current book node.'), 'required context' => new ctools_context_required(t('Node'), 'node'), 'category' => t('Node'), ); @@ -20,13 +20,13 @@ function ctools_node_book_nav_content_type_render($subtype, $conf, $panel_args, $block = new stdClass(); $block->module = 'book_nav'; - $block->title = t('Book navigation'); + $block->title = t('Book navigation pager'); if ($node) { $block->content = isset($node->book) ? theme('book_navigation', array('book_link' => $node->book)) : ''; $block->delta = $node->nid; } else { - $block->content = t('Book navigation goes here.'); + $block->content = t('Book navigation pager goes here.'); $block->delta = 'unknown'; } @@ -34,7 +34,7 @@ function ctools_node_book_nav_content_type_render($subtype, $conf, $panel_args, } function ctools_node_book_nav_content_type_admin_title($subtype, $conf, $context) { - return t('"@s" book navigation', array('@s' => $context->identifier)); + return t('"@s" book navigation pager', array('@s' => $context->identifier)); } function ctools_node_book_nav_content_type_edit_form($form, &$form_state) { diff --git a/sites/all/modules/contrib/dev/ctools/stylizer/stylizer.info b/sites/all/modules/contrib/dev/ctools/stylizer/stylizer.info index 66957648..79dc8929 100644 --- a/sites/all/modules/contrib/dev/ctools/stylizer/stylizer.info +++ b/sites/all/modules/contrib/dev/ctools/stylizer/stylizer.info @@ -6,9 +6,9 @@ version = CTOOLS_MODULE_VERSION dependencies[] = ctools dependencies[] = color -; Information added by Drupal.org packaging script on 2016-10-16 -version = "7.x-1.11" +; Information added by Drupal.org packaging script on 2016-11-22 +version = "7.x-1.12" core = "7.x" project = "ctools" -datestamp = "1476581654" +datestamp = "1479787162" diff --git a/sites/all/modules/contrib/dev/ctools/term_depth/term_depth.info b/sites/all/modules/contrib/dev/ctools/term_depth/term_depth.info index 91701667..885a5d0d 100644 --- a/sites/all/modules/contrib/dev/ctools/term_depth/term_depth.info +++ b/sites/all/modules/contrib/dev/ctools/term_depth/term_depth.info @@ -5,9 +5,9 @@ dependencies[] = ctools package = Chaos tool suite version = CTOOLS_MODULE_VERSION -; Information added by Drupal.org packaging script on 2016-10-16 -version = "7.x-1.11" +; Information added by Drupal.org packaging script on 2016-11-22 +version = "7.x-1.12" core = "7.x" project = "ctools" -datestamp = "1476581654" +datestamp = "1479787162" diff --git a/sites/all/modules/contrib/dev/ctools/tests/context.test b/sites/all/modules/contrib/dev/ctools/tests/context.test index bdf14e3f..2dd4f4d4 100644 --- a/sites/all/modules/contrib/dev/ctools/tests/context.test +++ b/sites/all/modules/contrib/dev/ctools/tests/context.test @@ -5,7 +5,7 @@ class CtoolsContextKeywordsSubstitutionTestCase extends DrupalWebTestCase { return array( 'name' => 'Keywords substitution', 'description' => 'Verify that keywords are properly replaced with data.', - 'group' => 'Chaos Tools Suite', + 'group' => 'ctools', ); } @@ -51,6 +51,30 @@ class CtoolsContextKeywordsSubstitutionTestCase extends DrupalWebTestCase { "%{$node->title}", t('Keyword after escaped and unescaped percent sign has been replaced.'), ), + '%%foo:bar' => array( + "%foo:bar", + t('Non-existant context ignored.'), + ), + 'There was about 20%-30% difference in price.' => array( + 'There was about 20%-30% difference in price.', + t('Non-keyword percent sign left untouched.'), + ), + 'href="my%20file%2dname.pdf"' => array( + 'href="my%20file%2dname.pdf"', + t('HTTP URL escape left untouched.'), + ), + 'href="my%a0file%fdname.pdf"' => array( + 'href="my%a0file%fdname.pdf"', + t('HTTP URL escape (high-chars) left untouched.'), + ), + 'Click here!' => array( + 'Click here!', + t('HTTP URL escape percent sign left untouched in HTML.'), + ), + 'SELECT * FROM {table} WHERE field = "%s"' => array( + 'SELECT * FROM {table} WHERE field = "%s"', + t('SQL percent sign left untouched.'), + ), ); foreach ($checks as $string => $expectations) { list($expected_result, $message) = $expectations; diff --git a/sites/all/modules/contrib/dev/ctools/tests/css.test b/sites/all/modules/contrib/dev/ctools/tests/css.test index 4a5200ca..3ffd42a5 100644 --- a/sites/all/modules/contrib/dev/ctools/tests/css.test +++ b/sites/all/modules/contrib/dev/ctools/tests/css.test @@ -12,7 +12,7 @@ class CtoolsCssTestCase extends DrupalWebTestCase { return array( 'name' => 'CSS Tools tests', 'description' => '...', - 'group' => 'Chaos Tools Suite', + 'group' => 'ctools', ); } diff --git a/sites/all/modules/contrib/dev/ctools/tests/css_cache.test b/sites/all/modules/contrib/dev/ctools/tests/css_cache.test index e289b42c..0b3528da 100644 --- a/sites/all/modules/contrib/dev/ctools/tests/css_cache.test +++ b/sites/all/modules/contrib/dev/ctools/tests/css_cache.test @@ -16,7 +16,7 @@ class CtoolsObjectCache extends DrupalWebTestCase { return array( 'name' => 'Ctools CSS cache', 'description' => 'Tests the custom CSS cache handler.', - 'group' => 'Chaos Tools Suite', + 'group' => 'ctools', ); } diff --git a/sites/all/modules/contrib/dev/ctools/tests/ctools.plugins.test b/sites/all/modules/contrib/dev/ctools/tests/ctools.plugins.test index fe1829cf..7e866b16 100644 --- a/sites/all/modules/contrib/dev/ctools/tests/ctools.plugins.test +++ b/sites/all/modules/contrib/dev/ctools/tests/ctools.plugins.test @@ -12,7 +12,7 @@ class CtoolsPluginsGetInfoTestCase extends DrupalWebTestCase { return array( 'name' => 'Get plugin info', 'description' => 'Verify that plugin type definitions can properly set and overide values.', - 'group' => 'Chaos Tools Suite', + 'group' => 'ctools', ); } diff --git a/sites/all/modules/contrib/dev/ctools/tests/ctools_export_test/ctools_export.test b/sites/all/modules/contrib/dev/ctools/tests/ctools_export_test/ctools_export.test index 1accfd74..6a062de7 100644 --- a/sites/all/modules/contrib/dev/ctools/tests/ctools_export_test/ctools_export.test +++ b/sites/all/modules/contrib/dev/ctools/tests/ctools_export_test/ctools_export.test @@ -14,7 +14,7 @@ class CtoolsExportCrudTestCase extends DrupalWebTestCase { return array( 'name' => 'CTools export CRUD tests', 'description' => 'Test the CRUD functionality for the ctools export system.', - 'group' => 'Chaos Tools Suite', + 'group' => 'ctools', ); } diff --git a/sites/all/modules/contrib/dev/ctools/tests/ctools_export_test/ctools_export_test.info b/sites/all/modules/contrib/dev/ctools/tests/ctools_export_test/ctools_export_test.info index f2d96edc..1f2612ee 100644 --- a/sites/all/modules/contrib/dev/ctools/tests/ctools_export_test/ctools_export_test.info +++ b/sites/all/modules/contrib/dev/ctools/tests/ctools_export_test/ctools_export_test.info @@ -8,9 +8,9 @@ hidden = TRUE files[] = ctools_export.test -; Information added by Drupal.org packaging script on 2016-10-16 -version = "7.x-1.11" +; Information added by Drupal.org packaging script on 2016-11-22 +version = "7.x-1.12" core = "7.x" project = "ctools" -datestamp = "1476581654" +datestamp = "1479787162" diff --git a/sites/all/modules/contrib/dev/ctools/tests/ctools_plugin_test.info b/sites/all/modules/contrib/dev/ctools/tests/ctools_plugin_test.info index bd906122..4a6d2766 100644 --- a/sites/all/modules/contrib/dev/ctools/tests/ctools_plugin_test.info +++ b/sites/all/modules/contrib/dev/ctools/tests/ctools_plugin_test.info @@ -12,9 +12,9 @@ files[] = math_expression.test files[] = math_expression_stack.test hidden = TRUE -; Information added by Drupal.org packaging script on 2016-10-16 -version = "7.x-1.11" +; Information added by Drupal.org packaging script on 2016-11-22 +version = "7.x-1.12" core = "7.x" project = "ctools" -datestamp = "1476581654" +datestamp = "1479787162" diff --git a/sites/all/modules/contrib/dev/ctools/tests/math_expression.test b/sites/all/modules/contrib/dev/ctools/tests/math_expression.test index 730e079a..8810e8c4 100644 --- a/sites/all/modules/contrib/dev/ctools/tests/math_expression.test +++ b/sites/all/modules/contrib/dev/ctools/tests/math_expression.test @@ -13,7 +13,7 @@ class CtoolsMathExpressionTestCase extends DrupalWebTestCase { return array( 'name' => 'CTools math expression tests', 'description' => 'Test the math expression library of ctools.', - 'group' => 'Chaos Tools Suite', + 'group' => 'ctools', ); } diff --git a/sites/all/modules/contrib/dev/ctools/tests/math_expression_stack.test b/sites/all/modules/contrib/dev/ctools/tests/math_expression_stack.test index 8143a55b..bdd46959 100644 --- a/sites/all/modules/contrib/dev/ctools/tests/math_expression_stack.test +++ b/sites/all/modules/contrib/dev/ctools/tests/math_expression_stack.test @@ -13,7 +13,7 @@ class CtoolsMathExpressionStackTestCase extends DrupalWebTestCase { return array( 'name' => 'CTools math expression stack tests', 'description' => 'Test the stack class of the math expression library.', - 'group' => 'Chaos Tools Suite', + 'group' => 'ctools', ); } diff --git a/sites/all/modules/contrib/dev/ctools/tests/object_cache.test b/sites/all/modules/contrib/dev/ctools/tests/object_cache.test index 8791d7e7..2e714d6b 100644 --- a/sites/all/modules/contrib/dev/ctools/tests/object_cache.test +++ b/sites/all/modules/contrib/dev/ctools/tests/object_cache.test @@ -12,7 +12,7 @@ class CtoolsObjectCache extends DrupalWebTestCase { return array( 'name' => 'Ctools object cache storage', 'description' => 'Verify that objects are written, readable and lockable.', - 'group' => 'Chaos Tools Suite', + 'group' => 'ctools', ); } diff --git a/sites/all/modules/contrib/dev/ctools/views_content/views_content.info b/sites/all/modules/contrib/dev/ctools/views_content/views_content.info index 84e2ae55..4f78dbdd 100644 --- a/sites/all/modules/contrib/dev/ctools/views_content/views_content.info +++ b/sites/all/modules/contrib/dev/ctools/views_content/views_content.info @@ -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 2016-10-16 -version = "7.x-1.11" +; Information added by Drupal.org packaging script on 2016-11-22 +version = "7.x-1.12" core = "7.x" project = "ctools" -datestamp = "1476581654" +datestamp = "1479787162" diff --git a/sites/all/modules/contrib/fields/date/date.field.inc b/sites/all/modules/contrib/fields/date/date.field.inc index fa311224..7aef97be 100644 --- a/sites/all/modules/contrib/fields/date/date.field.inc +++ b/sites/all/modules/contrib/fields/date/date.field.inc @@ -28,6 +28,7 @@ function date_field_formatter_info() { 'settings' => array( 'interval' => 2, 'interval_display' => 'time ago', + 'use_end_date' => false, ), ), 'date_plain' => array( @@ -207,7 +208,7 @@ function date_field_formatter_view($entity_type, $entity, $field, $instance, $la $variables['item'] = $item; $variables['dates'] = date_formatter_process($formatter, $entity_type, $entity, $field, $instance, $langcode, $item, $display); $variables['attributes'] = !empty($rdf_mapping) ? rdf_rdfa_attributes($rdf_mapping, $item['value']) : array(); - $variables['show_remaining_days'] = $display['settings']['show_remaining_days']; + $variables['show_remaining_days'] = isset($display['settings']['show_remaining_days']) ? $display['settings']['show_remaining_days'] : FALSE; $output = theme('date_display_combination', $variables); if (!empty($output)) { $element[$delta] = array('#markup' => $output); @@ -322,7 +323,7 @@ function date_field_widget_info() { } // The date text widget should use an increment of 1. - $info['date_text']['increment'] = 1; + $info['date_text']['settings']['increment'] = 1; return $info; } @@ -462,6 +463,14 @@ function date_field_instance_settings_form($field, $instance) { return _date_field_instance_settings_form($field, $instance); } +/** + * Form validation handler for _date_field_instance_settings_form(). + */ +function date_field_instance_settings_form_validate(&$form, &$form_state) { + module_load_include('inc', 'date', 'date_admin'); + return _date_field_instance_settings_form_validate($form, $form_state); +} + /** * Implements hook_field_widget_settings_form(). */ @@ -470,6 +479,14 @@ function date_field_widget_settings_form($field, $instance) { return _date_field_widget_settings_form($field, $instance); } +/** + * Form validation handler for _date_field_widget_settings_form(). + */ +function date_field_widget_settings_form_validate(&$form, &$form_state) { + module_load_include('inc', 'date', 'date_admin'); + return _date_field_widget_settings_form_validate($form, $form_state); +} + /** * Implements hook_field_settings_form(). */ @@ -478,6 +495,14 @@ function date_field_settings_form($field, $instance, $has_data) { return _date_field_settings_form($field, $instance, $has_data); } +/** + * Form validation handler for _date_field_settings_form(). + */ +function date_field_settings_validate(&$form, &$form_state) { + module_load_include('inc', 'date', 'date_admin'); + return _date_field_settings_validate($form, $form_state); +} + /** * Implements hook_content_migrate_field_alter(). * diff --git a/sites/all/modules/contrib/fields/date/date.info b/sites/all/modules/contrib/fields/date/date.info index c6fdde55..28263b42 100644 --- a/sites/all/modules/contrib/fields/date/date.info +++ b/sites/all/modules/contrib/fields/date/date.info @@ -13,10 +13,11 @@ files[] = tests/date_validation.test files[] = tests/date_timezone.test files[] = tests/date_views_pager.test files[] = tests/date_views_popup.test +files[] = tests/date_form.test -; Information added by Drupal.org packaging script on 2015-09-08 -version = "7.x-2.9" +; Information added by Drupal.org packaging script on 2017-04-07 +version = "7.x-2.10" core = "7.x" project = "date" -datestamp = "1441727353" +datestamp = "1491562090" diff --git a/sites/all/modules/contrib/fields/date/date.install b/sites/all/modules/contrib/fields/date/date.install index 9a9b6d35..765b90cf 100644 --- a/sites/all/modules/contrib/fields/date/date.install +++ b/sites/all/modules/contrib/fields/date/date.install @@ -204,3 +204,11 @@ function date_update_7004() { field_cache_clear(); drupal_set_message(t('Date text widgets have been updated to use an increment of 1.')); } + +/** + * Revisited: Date text widgets should always use an increment of 1. + */ +function date_update_7005() { + // @see https://www.drupal.org/node/1355256 + date_update_7004(); +} diff --git a/sites/all/modules/contrib/fields/date/date.migrate.inc b/sites/all/modules/contrib/fields/date/date.migrate.inc index ad2a5681..90c1ec51 100644 --- a/sites/all/modules/contrib/fields/date/date.migrate.inc +++ b/sites/all/modules/contrib/fields/date/date.migrate.inc @@ -1,10 +1,13 @@ ' . t('!start-date to !end-date', array( + $output = '' . t('!start-date to !end-date', array( '!start-date' => $start_date, '!end-date' => $end_date, - )) . ''; + )) . ''; // Add remaining message and return. return $output . $show_remaining_days; @@ -378,6 +378,8 @@ function theme_date_display_interval($variables) { 'end_date' => $dates['value2']['local']['object'], 'interval' => $options['interval'], 'interval_display' => $options['interval_display'], + 'use_end_date' => !empty($options['use_end_date']) ? + $options['use_end_date'] : FALSE, ); if ($return = theme('date_time_ago', $time_ago_vars)) { @@ -398,9 +400,9 @@ function theme_date_combo($variables) { // Group start/end items together in fieldset. $fieldset = array( - '#title' => field_filter_xss(t($element['#title'])) . ' ' . ($element['#delta'] > 0 ? intval($element['#delta'] + 1) : ''), + '#title' => field_filter_xss(t($element['#title'])) . ($element['#delta'] > 0 ? ' ' . intval($element['#delta'] + 1) : ''), '#value' => '', - '#description' => !empty($element['#fieldset_description']) ? $element['#fieldset_description'] : '', + '#description' => !empty($element['#description']) ? $element['#description'] : '', '#attributes' => array('class' => array('date-combo')), '#children' => $element['#children'], ); diff --git a/sites/all/modules/contrib/fields/date/date_admin.inc b/sites/all/modules/contrib/fields/date/date_admin.inc index 13da42ef..b800201e 100644 --- a/sites/all/modules/contrib/fields/date/date_admin.inc +++ b/sites/all/modules/contrib/fields/date/date_admin.inc @@ -14,15 +14,24 @@ function date_default_formatter_settings_form($field, $instance, $view_mode, $fo $formatter = $display['type']; $form = array(); + $date_formats = date_format_type_options(); $form['format_type'] = array( '#title' => t('Choose how users view dates and times:'), '#type' => 'select', - '#options' => date_format_type_options(), + '#options' => $date_formats + array('custom' => t('Custom')), '#default_value' => $settings['format_type'], '#description' => t('To add or edit options, visit Date and time settings.', array('@date-time-page' => url('admin/config/regional/date-time'))), '#weight' => 0, ); + $form['custom_date_format'] = array( + '#type' => 'textfield', + '#title' => t('Custom date format'), + '#description' => t('If "Custom", see the PHP manual for date formats. Otherwise, enter the number of different time units to display, which defaults to 2.', array('@url' => 'http://php.net/manual/function.date.php')), + '#default_value' => isset($settings['custom_date_format']) ? $settings['custom_date_format'] : '', + '#dependency' => array('edit-options-settings-format-type' => array('custom')), + ); + $form['fromto'] = array( '#title' => t('Display:'), '#type' => 'select', @@ -116,6 +125,14 @@ function date_interval_formatter_settings_form($field, $instance, $view_mode, $f '#default_value' => $settings['interval_display'], '#weight' => 0, ); + if (!empty($field['settings']['todate'])) { + $form['use_end_date'] = array( + '#title' => t('Use End date'), + '#description' => 'Use the End date, instead of the start date', + '#type' => 'checkbox', + '#default_value' => $settings['use_end_date'], + ); + } return $form; } @@ -186,7 +203,9 @@ function date_interval_formatter_settings_summary($field, $instance, $view_mode) $display = $instance['display'][$view_mode]; $settings = $display['settings']; $formatter = $display['type']; - $summary[] = t('Display time ago, showing @interval units.', array('@interval' => $settings['interval'])); + $field = ($settings['use_end_date'] == 1) ? 'End' : 'Start'; + $summary[] = t('Display time ago, showing @interval units. Using @field Date', + array('@interval' => $settings['interval'], '@field' => $field)); return $summary; } @@ -273,7 +292,7 @@ function _date_field_instance_settings_form($field, $instance) { /** * Form validation handler for _date_field_instance_settings_form(). */ -function date_field_instance_settings_form_validate(&$form, &$form_state) { +function _date_field_instance_settings_form_validate(&$form, &$form_state) { $settings = $form_state['values']['instance']['settings']; if ($settings['default_value'] == 'strtotime') { @@ -459,7 +478,7 @@ function _date_field_widget_settings_form($field, $instance) { /** * Form validation handler for _date_field_widget_settings_form(). */ -function date_field_widget_settings_form_validate(&$form, &$form_state) { +function _date_field_widget_settings_form_validate(&$form, &$form_state) { // The widget settings are in the wrong place in the form because of #tree on // the top level. $settings = $form_state['values']['instance']['widget']['settings']; @@ -561,7 +580,7 @@ function _date_field_settings_form($field, $instance, $has_data) { $form['cache_enabled'] = array( '#type' => 'checkbox', '#title' => t('Cache dates'), - '#description' => t('Date objects can be created and cached as date fields are loaded rather than when they are displayed to improve performance.'), + '#description' => t('Date objects can be created and cached as date fields are loaded, rather than when they are displayed, to improve performance.'), '#default_value' => !empty($settings['cache_enabled']), '#weight' => 10, ); @@ -594,7 +613,7 @@ function _date_field_settings_form($field, $instance, $has_data) { /** * Form validation handler for _date_field_settings_form(). */ -function date_field_settings_validate(&$form, &$form_state) { +function _date_field_settings_validate(&$form, &$form_state) { $field = &$form_state['values']['field']; if ($field['settings']['tz_handling'] == 'none') { diff --git a/sites/all/modules/contrib/fields/date/date_all_day/date_all_day.info b/sites/all/modules/contrib/fields/date/date_all_day/date_all_day.info index df773e41..fcdc673a 100644 --- a/sites/all/modules/contrib/fields/date/date_all_day/date_all_day.info +++ b/sites/all/modules/contrib/fields/date/date_all_day/date_all_day.info @@ -5,9 +5,9 @@ dependencies[] = date package = Date/Time core = 7.x -; Information added by Drupal.org packaging script on 2015-09-08 -version = "7.x-2.9" +; Information added by Drupal.org packaging script on 2017-04-07 +version = "7.x-2.10" core = "7.x" project = "date" -datestamp = "1441727353" +datestamp = "1491562090" diff --git a/sites/all/modules/contrib/fields/date/date_api/date_api.info b/sites/all/modules/contrib/fields/date/date_api/date_api.info index 40fbb056..c537ca04 100644 --- a/sites/all/modules/contrib/fields/date/date_api/date_api.info +++ b/sites/all/modules/contrib/fields/date/date_api/date_api.info @@ -9,9 +9,9 @@ stylesheets[all][] = date.css files[] = date_api.module files[] = date_api_sql.inc -; Information added by Drupal.org packaging script on 2015-09-08 -version = "7.x-2.9" +; Information added by Drupal.org packaging script on 2017-04-07 +version = "7.x-2.10" core = "7.x" project = "date" -datestamp = "1441727353" +datestamp = "1491562090" diff --git a/sites/all/modules/contrib/fields/date/date_api/date_api.module b/sites/all/modules/contrib/fields/date/date_api/date_api.module index 2a973ccf..160bc9fb 100644 --- a/sites/all/modules/contrib/fields/date/date_api/date_api.module +++ b/sites/all/modules/contrib/fields/date/date_api/date_api.module @@ -1833,9 +1833,10 @@ function date_format_interval($date, $granularity = 2, $display_ago = TRUE) { /** * A date object for the current time. * - * @param object $timezone - * (optional) Optionally force time to a specific timezone, defaults to user - * timezone, if set, otherwise site timezone. Defaults to NULL. + * @param object|string|null $timezone + * (optional) PHP DateTimeZone object, string or NULL allowed. Optionally + * force time to a specific timezone, defaults to user timezone, if set, + * otherwise site timezone. Defaults to NULL. * * @param bool $reset * (optional) Static cache reset. @@ -1844,11 +1845,16 @@ function date_format_interval($date, $granularity = 2, $display_ago = TRUE) { * The current time as a date object. */ function date_now($timezone = NULL, $reset = FALSE) { - if ($reset) { - drupal_static_reset(__FUNCTION__ . $timezone); + $static_var = __FUNCTION__ . $timezone; + if ($timezone instanceof DateTimeZone) { + $static_var = __FUNCTION__ . $timezone->getName(); } - $now = &drupal_static(__FUNCTION__ . $timezone); + if ($reset) { + drupal_static_reset($static_var); + } + + $now = &drupal_static($static_var); if (!isset($now)) { $now = new DateObject('now', $timezone); @@ -1920,7 +1926,12 @@ function date_days_in_month($year, $month) { // Pick a day in the middle of the month to avoid timezone shifts. $datetime = date_pad($year, 4) . '-' . date_pad($month) . '-15 00:00:00'; $date = new DateObject($datetime); - return $date->format('t'); + if ($date->errors) { + return FALSE; + } + else { + return $date->format('t'); + } } /** @@ -2075,6 +2086,9 @@ function date_iso_week_range($week, $year) { date_timezone_set($min_date, date_default_timezone_object()); // Find the first day of the first ISO week in the year. + // If it's already a Monday, date_modify won't add a Monday, + // it will remain the same day. So add a Sunday first, then a Monday. + date_modify($min_date, '+1 Sunday'); date_modify($min_date, '+1 Monday'); // Jump ahead to the desired week for the beginning of the week range. diff --git a/sites/all/modules/contrib/fields/date/date_api/date_api_elements.inc b/sites/all/modules/contrib/fields/date/date_api/date_api_elements.inc index fc91205c..638fcda5 100644 --- a/sites/all/modules/contrib/fields/date/date_api/date_api_elements.inc +++ b/sites/all/modules/contrib/fields/date/date_api/date_api_elements.inc @@ -111,7 +111,7 @@ function date_default_date($element) { $format = DATE_FORMAT_DATETIME; // The text and popup widgets might return less than a full datetime string. - if (strlen($element['#default_value']) < 19) { + if (is_string($element['#default_value']) && strlen($element['#default_value']) < 19) { switch (strlen($element['#default_value'])) { case 16: $format = 'Y-m-d H:i'; @@ -319,7 +319,7 @@ function date_text_element_process($element, &$form_state, $form) { $element['#tree'] = TRUE; $element['#theme_wrappers'] = array('date_text'); - $element['date']['#value'] = $element['#value']['date']; + $element['date']['#value'] = isset($element['#value']['date']) ? $element['#value']['date'] : ''; $element['date']['#type'] = 'textfield'; $element['date']['#weight'] = !empty($element['date']['#weight']) ? $element['date']['#weight'] : $element['#weight']; $element['date']['#attributes'] = array('class' => isset($element['#attributes']['class']) ? $element['#attributes']['class'] += array('date-date') : array('date-date')); diff --git a/sites/all/modules/contrib/fields/date/date_api/theme/theme.inc b/sites/all/modules/contrib/fields/date/date_api/theme/theme.inc index a6aef230..0a57ecd0 100644 --- a/sites/all/modules/contrib/fields/date/date_api/theme/theme.inc +++ b/sites/all/modules/contrib/fields/date/date_api/theme/theme.inc @@ -194,6 +194,7 @@ function theme_date_calendar_day($variables) { function theme_date_time_ago($variables) { $start_date = $variables['start_date']; $end_date = $variables['end_date']; + $use_end_date = isset($variables['use_end_date']) ? $variables['use_end_date'] : false; $interval = !empty($variables['interval']) ? $variables['interval'] : 2; $display = isset($variables['interval_display']) ? $variables['interval_display'] : 'time ago'; @@ -202,12 +203,20 @@ function theme_date_time_ago($variables) { return; } + // We use the end date only when the option is checked. + if ($use_end_date){ + $date = date_format($end_date, DATE_FORMAT_UNIX); + } + else { + $date = date_format($start_date, DATE_FORMAT_UNIX); + } + // Time to compare dates to. + $now = date_format(date_now(), DATE_FORMAT_UNIX); - $start = date_format($start_date, DATE_FORMAT_UNIX); // Will be positive for a datetime in the past (ago), and negative for a datetime in the future (hence). - $time_diff = $now - $start; + $time_diff = $now - $date; // Uses the same options used by Views format_interval. switch ($display) { diff --git a/sites/all/modules/contrib/fields/date/date_context/date_context.info b/sites/all/modules/contrib/fields/date/date_context/date_context.info index c521dd26..97cb8c9d 100644 --- a/sites/all/modules/contrib/fields/date/date_context/date_context.info +++ b/sites/all/modules/contrib/fields/date/date_context/date_context.info @@ -8,9 +8,9 @@ dependencies[] = context files[] = date_context.module files[] = plugins/date_context_date_condition.inc -; Information added by Drupal.org packaging script on 2015-09-08 -version = "7.x-2.9" +; Information added by Drupal.org packaging script on 2017-04-07 +version = "7.x-2.10" core = "7.x" project = "date" -datestamp = "1441727353" +datestamp = "1491562090" diff --git a/sites/all/modules/contrib/fields/date/date_elements.inc b/sites/all/modules/contrib/fields/date/date_elements.inc index 83697153..656d4998 100644 --- a/sites/all/modules/contrib/fields/date/date_elements.inc +++ b/sites/all/modules/contrib/fields/date/date_elements.inc @@ -74,7 +74,7 @@ function date_field_widget_form(&$form, &$form_state, $field, $instance, $langco // The repeating values will be re-generated when the repeat widget form is validated. // At this point we can't tell if this form element is going to be hidden by #access, and we're going to // lose all but the first value by doing this, so store the original values in case we need to replace them later. - if (!empty($field['settings']['repeat'])) { + if (!empty($field['settings']['repeat']) && module_exists('date_repeat_field')) { if ($delta == 0) { $form['#after_build'][] = 'date_repeat_after_build'; $form_state['storage']['repeat_fields'][$field_name] = array_merge($form['#parents'], array($field_name)); @@ -337,8 +337,11 @@ function date_combo_element_process($element, &$form_state, $form) { '#date_label_position' => $instance['widget']['settings']['label_position'], ); - $description = !empty($element['#description']) ? t($element['#description']) : ''; - unset($element['#description']); + // Date repeat is a multiple value field. So the description is removed from + // the single element earlier. Let's get it back. + if (isset($element['show_repeat_settings']) && !empty($element['value']['#instance']['description'])) { + $element['#description'] = $element['value']['#instance']['description']; + } // Give this element the right type, using a Date API // or a Date Popup element type. @@ -383,8 +386,7 @@ function date_combo_element_process($element, &$form_state, $form) { $element[$to_field]['#prefix'] = ''; // Users with JS enabled will never see initially blank values for the end // date (see Drupal.date.EndDateHandler()), so hide the message for them. - $description .= ' ' . t("Empty 'End date' values will use the 'Start date' values.") . ''; - $element['#fieldset_description'] = $description; + $element['#description'] .= ' ' . t("Empty 'End date' values will use the 'Start date' values.") . ''; if ($field['settings']['todate'] == 'optional') { $element[$to_field]['#states'] = array( 'visible' => array( @@ -395,9 +397,6 @@ function date_combo_element_process($element, &$form_state, $form) { ); } } - else { - $element[$from_field]['#description'] = $description; - } // Create label for error messages that make sense in multiple values // and when the title field is left blank. @@ -474,6 +473,12 @@ function date_combo_validate($element, &$form_state) { $form_values = drupal_array_get_nested_value($form_state['values'], $element['#field_parents']); $form_input = drupal_array_get_nested_value($form_state['input'], $element['#field_parents']); + // Programmatically calling drupal_submit_form() does not always add the date + // combo to $form_state['input']. + if (empty($form_input[$field_name]) && !empty($form_values[$field_name])) { + form_set_value($element, $element['#date_items'], $form_state); + return; + } // If the whole field is empty and that's OK, stop now. if (empty($form_input[$field_name]) && !$element['#required']) { return; @@ -546,11 +551,7 @@ function date_combo_validate($element, &$form_state) { return; } } - // Don't look for further errors if errors are already flagged - // because otherwise we'll show errors on the nested elements - // more than once. - elseif (!form_get_errors()) { - + else { $timezone = !empty($item[$tz_field]) ? $item[$tz_field] : $element['#date_timezone']; $timezone_db = date_get_timezone_db($field['settings']['tz_handling']); $element[$from_field]['#date_timezone'] = $timezone; @@ -625,7 +626,10 @@ function date_combo_validate($element, &$form_state) { } } } - if (!empty($errors)) { + // Don't show further errors if errors are already flagged + // because otherwise we'll show errors on the nested elements + // more than once. + if (!form_get_errors() && !empty($errors)) { if ($field['cardinality']) { form_error($element, t('There are errors in @field_name value #@delta:', array('@field_name' => $instance['label'], '@delta' => $delta + 1)) . theme('item_list', array('items' => $errors))); } diff --git a/sites/all/modules/contrib/fields/date/date_migrate/date_migrate.info b/sites/all/modules/contrib/fields/date/date_migrate/date_migrate.info index b3a6bba6..41e416a3 100644 --- a/sites/all/modules/contrib/fields/date/date_migrate/date_migrate.info +++ b/sites/all/modules/contrib/fields/date/date_migrate/date_migrate.info @@ -4,9 +4,9 @@ core = 7.x package = Date/Time hidden = TRUE -; Information added by Drupal.org packaging script on 2015-09-08 -version = "7.x-2.9" +; Information added by Drupal.org packaging script on 2017-04-07 +version = "7.x-2.10" core = "7.x" project = "date" -datestamp = "1441727353" +datestamp = "1491562090" diff --git a/sites/all/modules/contrib/fields/date/date_migrate/date_migrate_example/date_migrate_example.info b/sites/all/modules/contrib/fields/date/date_migrate/date_migrate_example/date_migrate_example.info index 6d79df40..ba07220d 100644 --- a/sites/all/modules/contrib/fields/date/date_migrate/date_migrate_example/date_migrate_example.info +++ b/sites/all/modules/contrib/fields/date/date_migrate/date_migrate_example/date_migrate_example.info @@ -20,9 +20,9 @@ package = "Features" project = "date_migrate_example" version = "7.x-2.0" -; Information added by Drupal.org packaging script on 2015-09-08 -version = "7.x-2.9" +; Information added by Drupal.org packaging script on 2017-04-07 +version = "7.x-2.10" core = "7.x" project = "date" -datestamp = "1441727353" +datestamp = "1491562090" diff --git a/sites/all/modules/contrib/fields/date/date_popup/date_popup.info b/sites/all/modules/contrib/fields/date/date_popup/date_popup.info index 500c7ffb..41945a63 100644 --- a/sites/all/modules/contrib/fields/date/date_popup/date_popup.info +++ b/sites/all/modules/contrib/fields/date/date_popup/date_popup.info @@ -7,9 +7,9 @@ configure = admin/config/date/date_popup stylesheets[all][] = themes/datepicker.1.7.css -; Information added by Drupal.org packaging script on 2015-09-08 -version = "7.x-2.9" +; Information added by Drupal.org packaging script on 2017-04-07 +version = "7.x-2.10" core = "7.x" project = "date" -datestamp = "1441727353" +datestamp = "1491562090" diff --git a/sites/all/modules/contrib/fields/date/date_popup/date_popup.js b/sites/all/modules/contrib/fields/date/date_popup/date_popup.js index bbf25e2d..f38dcb59 100644 --- a/sites/all/modules/contrib/fields/date/date_popup/date_popup.js +++ b/sites/all/modules/contrib/fields/date/date_popup/date_popup.js @@ -14,6 +14,14 @@ $(this).click(function(){ $(this).focus(); }); + if (datePopup.settings.syncEndDate) { + $('.start-date-wrapper').each(function(){ + var start_date_wrapper = this; + $(this).find('input:eq(0)').change(function(){ + $(start_date_wrapper).next('.end-date-wrapper').find('input:eq(0)').val($(this).val()); + }); + }); + } break; case 'timeEntry': diff --git a/sites/all/modules/contrib/fields/date/date_popup/date_popup.module b/sites/all/modules/contrib/fields/date/date_popup/date_popup.module index e91cc8a7..a03132e9 100644 --- a/sites/all/modules/contrib/fields/date/date_popup/date_popup.module +++ b/sites/all/modules/contrib/fields/date/date_popup/date_popup.module @@ -394,6 +394,10 @@ function date_popup_process_date_part(&$element) { 'fromTo' => isset($fromto), ); + if (!empty($element['#instance'])) { + $settings['syncEndDate'] = $element['#instance']['settings']['default_value2'] == 'sync'; + } + // Create a unique id for each set of custom settings. $id = date_popup_js_settings_id($element['#id'], 'datepicker', $settings); @@ -474,10 +478,11 @@ function date_popup_process_time_part(&$element) { $grans = array('hour', 'minute', 'second'); $time_granularity = array_intersect($granularity, $grans); $format = date_popup_format_to_popup_time(date_limit_format($element['#date_format'], $time_granularity), 'wvega'); + $default_value = isset($element['#default_value']) ? $element['#default_value'] : ''; // The first value in the dropdown list should be the same as the element // default_value, but it needs to be in JS format (i.e. milliseconds since // the epoch). - $start_time = new DateObject($element['#default_value'], $element['#date_timezone'], DATE_FORMAT_DATETIME); + $start_time = new DateObject($default_value, $element['#date_timezone'], DATE_FORMAT_DATETIME); date_increment_round($start_time, $element['#date_increment']); $start_time = $start_time->format(DATE_FORMAT_UNIX) * 1000; $settings = array( @@ -580,7 +585,7 @@ function date_popup_validate($element, &$form_state) { // If something was input but there is no date, the date is invalid. // If the field is empty and required, set error message and return. $error_field = implode('][', $element['#parents']); - if (empty($date) || !empty($date->errors)) { + if ((empty($element['#value']['date']) && empty($element['#value']['time'])) || !empty($date->errors)) { if (is_object($date) && !empty($date->errors)) { $message = t('The value input for field %field is invalid:', array('%field' => $label)); $message .= 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus at velit dolor. Donec egestas tellus sit amet urna rhoncus adipiscing. Proin nec porttitor sem. Maecenas aliquam, purus nec tempus dignissim, nulla arcu aliquam diam, non tincidunt massa ante vel dolor. Aliquam sapien sapien, tincidunt id tristique at, pretium sagittis libero.
- -Nulla facilisi. Curabitur lacinia, tellus sed tristique consequat, diam lorem scelerisque felis, at dictum purus augue facilisis lorem. Duis pharetra dignissim rutrum. Curabitur ac elit id dui dapibus tincidunt. Nulla eget sem quam, non eleifend eros. Cras porttitor tempus lectus ac scelerisque. Curabitur vehicula bibendum lorem, vitae ornare ligula venenatis ut.
- "; + return <<+ Nulla facilisi. Curabitur lacinia, tellus sed tristique consequat, diam + lorem scelerisque felis, at dictum purus augue facilisis lorem. Duis + pharetra dignissim rutrum. Curabitur ac elit id dui dapibus tincidunt. + Nulla eget sem quam, non eleifend eros. Cras porttitor tempus lectus ac + scelerisque. Curabitur vehicula bibendum lorem, vitae ornare ligula + venenatis ut. +
+LIPSUM; } /** @@ -515,7 +574,14 @@ function panels_stylizer_lipsum() { */ function panels_stylizer_region_preview($plugin, $settings) { ctools_stylizer_add_css($plugin, $settings); - return theme($plugin['theme'], array('settings' => $settings, 'class' => ctools_stylizer_get_css_class($plugin, $settings), 'content' => panels_stylizer_lipsum())); + return theme( + $plugin['theme'], + array( + 'settings' => $settings, + 'class' => ctools_stylizer_get_css_class($plugin, $settings), + 'content' => panels_stylizer_lipsum(), + ) + ); } /** @@ -525,7 +591,7 @@ function panels_stylizer_pane_preview($plugin, $settings) { ctools_stylizer_add_css($plugin, $settings); $pane = new stdClass(); - $content = new stdClass; + $content = new stdClass(); $content->title = t('Lorem ipsum'); $content->content = panels_stylizer_lipsum(); $content->type = 'dummy'; @@ -536,78 +602,103 @@ function panels_stylizer_pane_preview($plugin, $settings) { $display = new panels_display(); if (!empty($plugin['theme'])) { - return theme($plugin['theme'], array('settings' => $settings, 'content' => $content, 'pane' => $pane, 'display' => $display)); + return theme( + $plugin['theme'], + array( + 'settings' => $settings, + 'content' => $content, + 'pane' => $pane, + 'display' => $display, + ) + ); } else { - return theme('panels_pane', array('content' => $content, 'pane' => $pane, 'display' => $display)); + return theme( + 'panels_pane', + array( + 'content' => $content, + 'pane' => $pane, + 'display' => $display, + ) + ); } } -// --------------------------------------------------------------------------- -// Panels display editing +/** + * Panels display editing. + */ /** - * @defgroup mainapi Functions comprising the main panels API - * @{ + * @defgroup mainapi Functions comprising the main panels API. */ /** * Main API entry point to edit a panel display. * - * Sample implementations utiltizing the the complex $destination behavior can be found - * in panels_page_edit_content() and, in a separate contrib module, OG Blueprints - * (http://drupal.org/project/og_blueprints), og_blueprints_blueprint_edit(). + * Sample implementations utiltizing the the complex $destination behavior can + * be found in panels_page_edit_content() and, in a separate contrib module, + * OG Blueprints (http://drupal.org/project/og_blueprints), + * og_blueprints_blueprint_edit(). + * + * @param object $display + * Instanceof panels_display. + * + * A fully loaded panels $display object, as returned from + * panels_load_display(). Merely passing a did is NOT sufficient. + * Note that 'fully loaded' means the $display must already be loaded with + * any contexts the caller wishes to have set for the display. + * @param mixed $destination + * The redirect destination that the user should be taken to on form + * submission or cancellation. With panels_edit, $destination has complex + * effects on the return values of panels_edit() once the form has been + * submitted. See the explanation of the return value below to understand the + * different types of values returned by panels_edit() at different stages of + * FAPI. Under most circumstances, simply passing in drupal_get_destination() + * is all that's necessary. + * @param array $content_types + * An associative array of allowed content types, typically as returned from + * panels_common_get_allowed_types(). Note that context partially governs + * available content types, so you will want to create any relevant contexts + * using panels_create_context() or panels_create_context_empty() to make sure + * all the appropriate content types are available. + * + * @return mixed + * Because the functions called by panels_edit() invoke the form API, + * this function returns different values depending on the stage of form + * submission we're at. In Drupal 5, the phase of form submission is indicated + * by the contents of $_POST['op']. Here is what you'll get at different + * stages: + * - If !$_POST['op']: then we're on on the initial passthrough and the + * form is being rendered, so it's the $form itself that's being + * returned. Because negative margins, a common CSS technique, bork the + * display editor's ajax drag-and-drop, it's important that the $output + * be printed, not returned. Use this syntax in the caller function: + * print theme('page', panels_edit($display, $destination, $content_types), FALSE); + * - If $_POST['op'] == t('Cancel'): form submission has been cancelled. + * If empty($destination) == FALSE, then there is no return value and the + * panels API takes care of redirecting to $destination. + * If empty($destination) == TRUE, then there's still no return value, + * but the caller function has to take care of form redirection. + * - If $_POST['op'] == ('Save'): the form has been submitted successfully + * and has run through panels_edit_display_submit(). + * $output depends on the value of $destination: + * - If empty($destination) == TRUE: $output contains the modified $display + * object, and no redirection will occur. This option is useful if the + * caller needs to perform additional operations on or with the modified + * $display before the page request is complete. Using hook_form_alter() + * to add an additional submit handler is typically the preferred method + * for something like this, but there are certain use cases where that is + * infeasible and $destination = NULL should be used instead. If this + * method is employed, the caller will need to handle form redirection. + * Note that having $_REQUEST['destination'] set, whether via + * drupal_get_destination() or some other method, will NOT interfere with + * this functionality; consequently, you can use drupal_get_destination() + * to safely store your desired redirect in the caller function, then + * simply use drupal_goto() once panels_edit() has done its business. + * - If empty($destination) == FALSE: the form will redirect to the URL + * string given in $destination and NO value will be returned. * * @ingroup mainapi - * - * @param object $display instanceof panels_display \n - * A fully loaded panels $display object, as returned from panels_load_display(). - * Merely passing a did is NOT sufficient. \n - * Note that 'fully loaded' means the $display must already be loaded with any contexts - * the caller wishes to have set for the display. - * @param mixed $destination \n - * The redirect destination that the user should be taken to on form submission or - * cancellation. With panels_edit, $destination has complex effects on the return - * values of panels_edit() once the form has been submitted. See the explanation of - * the return value below to understand the different types of values returned by panels_edit() - * at different stages of FAPI. Under most circumstances, simply passing in - * drupal_get_destination() is all that's necessary. - * @param array $content_types \n - * An associative array of allowed content types, typically as returned from - * panels_common_get_allowed_types(). Note that context partially governs available content types, - * so you will want to create any relevant contexts using panels_create_context() or - * panels_create_context_empty() to make sure all the appropriate content types are available. - * - * @return - * Because the functions called by panels_edit() invoke the form API, this function - * returns different values depending on the stage of form submission we're at. In Drupal 5, - * the phase of form submission is indicated by the contents of $_POST['op']. Here's what you'll - * get at different stages: - * -# If !$_POST['op']: then we're on on the initial passthrough and the form is being - * rendered, so it's the $form itself that's being returned. Because negative margins, - * a common CSS technique, bork the display editor's ajax drag-and-drop, it's important - * that the $output be printed, not returned. Use this syntax in the caller function: \n - * print theme('page', panels_edit($display, $destination, $content_types), FALSE); \n - * -# If $_POST['op'] == t('Cancel'): form submission has been cancelled. If empty($destination) == FALSE, - * then there is no return value and the panels API takes care of redirecting to $destination. - * If empty($destination) == TRUE, then there's still no return value, but the caller function - * has to take care of form redirection. - * -# If $_POST['op'] == ('Save'): the form has been submitted successfully and has run through - * panels_edit_display_submit(). $output depends on the value of $destination: - * - If empty($destination) == TRUE: $output contains the modified $display - * object, and no redirection will occur. This option is useful if the caller - * needs to perform additional operations on or with the modified $display before - * the page request is complete. Using hook_form_alter() to add an additional submit - * handler is typically the preferred method for something like this, but there - * are certain use cases where that is infeasible and $destination = NULL should - * be used instead. If this method is employed, the caller will need to handle form - * redirection. Note that having $_REQUEST['destination'] set, whether via - * drupal_get_destination() or some other method, will NOT interfere with this - * functionality; consequently, you can use drupal_get_destination() to safely store - * your desired redirect in the caller function, then simply use drupal_goto() once - * panels_edit() has done its business. - * - If empty($destination) == FALSE: the form will redirect to the URL string - * given in $destination and NO value will be returned. */ function panels_edit($display, $destination = NULL, $content_types = NULL, $title = FALSE) { ctools_include('display-edit', 'panels'); @@ -619,40 +710,47 @@ function panels_edit($display, $destination = NULL, $content_types = NULL, $titl /** * API entry point for selecting a layout for a given display. * - * Layout selection is nothing more than a list of radio items encompassing the available - * layouts for this display, as defined by .inc files in the panels/layouts subdirectory. - * The only real complexity occurs when a user attempts to change the layout of a display - * that has some content in it. + * Layout selection is nothing more than a list of radio items encompassing the + * available layouts for this display, as defined by .inc files in the + * panels/layouts subdirectory. The only real complexity occurs when a user + * attempts to change the layout of a display that has some content in it. * - * @param object $display instanceof panels_display \n - * A fully loaded panels $display object, as returned from panels_load_display(). - * Merely passing a did is NOT sufficient. + * @param object $display + * A fully loaded panels $display object, as returned from + * panels_load_display(). Merely passing a did is NOT sufficient. * @param string $finish - * A string that will be used for the text of the form submission button. If no value is provided, - * then the form submission button will default to t('Save'). + * A string that will be used for the text of the form submission button. If + * no value is provided, then the form submission button will default to + * t('Save'). * @param mixed $destination - * Basic usage is a string containing the URL that the form should redirect to upon submission. - * For a discussion of advanced usages, see panels_edit(). + * Basic usage is a string containing the URL that the form should redirect to + * upon submission. For a discussion of advanced usages, see panels_edit(). * @param mixed $allowed_layouts - * Allowed layouts has three different behaviors that depend on which of three value types - * are passed in by the caller: - * #- if $allowed_layouts instanceof panels_allowed_layouts (includes subclasses): the most - * complex use of the API. The caller is passing in a loaded panels_allowed_layouts object - * that the client module previously created and stored somewhere using a custom storage - * mechanism. - * #- if is_string($allowed_layouts): the string will be used in a call to variable_get() which - * will call the $allowed_layouts . '_allowed_layouts' var. If the data was stored properly - * in the system var, the $allowed_layouts object will be unserialized and recreated. - * @see panels_common_set_allowed_layouts() - * #- if is_null($allowed_layouts): the default behavior, which also provides backwards - * compatibility for implementations of the Panels2 API written before beta4. In this case, - * a dummy panels_allowed_layouts object is created which does not restrict any layouts. - * Subsequent behavior is indistinguishable from pre-beta4 behavior. + * Allowed layouts has three different behaviors that depend on which of three + * value types are passed in by the caller: + * #- if $allowed_layouts instanceof panels_allowed_layouts + * (includes subclasses): the most complex use of the API. The caller is + * passing in a loaded panels_allowed_layouts object that the client + * module previously created and stored somewhere using a custom storage + * mechanism. + * #- if is_string($allowed_layouts): the string will be used in a call to + * variable_get() which will call the + * $allowed_layouts . '_allowed_layouts' var. If the data was stored + * properly in the system var, the $allowed_layouts object will be + * unserialized and recreated. + * #- if is_null($allowed_layouts): the default behavior, which also + * provides backwards compatibility for implementations of the Panels2 + * API written before beta4. In this case, a dummy panels_allowed_layouts + * object is created which does not restrict any layouts. Subsequent + * behavior is indistinguishable from pre-beta4 behavior. + * + * @return mixed + * Can return nothing, or a modified $display object, or a redirection string; + * return values for the panels_edit* family of functions are quite complex. + * See panels_edit() for detailed discussion. * - * @return - * Can return nothing, or a modified $display object, or a redirection string; return values for the - * panels_edit* family of functions are quite complex. See panels_edit() for detailed discussion. * @see panels_edit() + * @see panels_common_set_allowed_layouts() */ function panels_edit_layout($display, $finish, $destination = NULL, $allowed_layouts = NULL) { ctools_include('display-layout', 'panels'); @@ -660,23 +758,27 @@ function panels_edit_layout($display, $finish, $destination = NULL, $allowed_lay return _panels_edit_layout($display, $finish, $destination, $allowed_layouts); } -// --------------------------------------------------------------------------- -// Panels database functions +/** + * Panels database functions. + */ /** - * Forms the basis of a panel display + * Forms the basis of a panel display. */ class panels_display { - var $args = array(); - var $content = array(); - var $panels = array(); - var $incoming_content = NULL; - var $css_id = NULL; - var $context = array(); - var $did = 'new'; - var $renderer = 'standard'; + public $args = array(); + public $content = array(); + public $panels = array(); + public $incoming_content = NULL; + public $css_id = NULL; + public $context = array(); + public $did = 'new'; + public $renderer = 'standard'; - function add_pane(&$pane, $location = NULL) { + /** + * Add a pane. + */ + public function add_pane(&$pane, $location = NULL) { // If no location specified, use what's set in the pane. if (empty($location)) { $location = $pane->panel; @@ -690,33 +792,30 @@ class panels_display { $pane->uuid = ctools_uuid_generate(); $pane->pid = 'new-' . $pane->uuid; - // Add the pane to the approprate spots. + // Add the pane to the appropriate spots. $this->content[$pane->pid] = &$pane; $this->panels[$location][] = $pane->pid; } - function duplicate_pane($pid, $location = FALSE) { + /** + * Duplicate a pane. + */ + public function duplicate_pane($pid, $location = FALSE) { $pane = $this->clone_pane($pid); $this->add_pane($pane, $location); } - function clone_pane($pid) { - $pane = clone $this->content[$pid]; - $pane->uuid = ctools_uuid_generate(); - return $pane; - } - /** * Get the title from a display. * * The display must have already been rendered, or the setting to set the * display's title from a pane's title will not have worked. * - * @return - * The title to use. If NULL, this means to let any default title that may be in use - * pass through. i.e, do not actually set the title. + * @return mixed + * The title to use. If NULL, this means to let any default title that may + * be in use pass through. i.e, do not actually set the title. */ - function get_title() { + public function get_title() { switch ($this->hide_title) { case PANELS_TITLE_NONE: return ''; @@ -725,7 +824,8 @@ class panels_display { return isset($this->stored_pane_title) ? $this->stored_pane_title : ''; case PANELS_TITLE_FIXED: - case FALSE; // For old exported panels that are not in the database. + case FALSE; + // For old exported panels that are not in the database. if (!empty($this->title)) { return filter_xss_admin(ctools_context_keyword_substitute($this->title, array(), $this->context)); } @@ -743,8 +843,11 @@ class panels_display { * An instantiated display renderer object, or the name of a display * renderer plugin+class to be fetched. Defaults to NULL. When NULL, the * predesignated display renderer will be used. + * + * @return mixed + * NULL or output of render function. */ - function render($renderer = NULL) { + public function render($renderer = NULL) { $layout = panels_get_layout($this->layout); if (!$layout) { return NULL; @@ -788,7 +891,7 @@ class panels_display { * @return bool * TRUE if access is granted; otherwise FALSE. */ - function access($op, $account = NULL) { + public function access($op, $account = NULL) { global $user; if (!$account) { @@ -825,10 +928,11 @@ class panels_display { return $access_callback($this->storage_type, $this->storage_id, $op, $account); } + } /** - * }@ End of 'defgroup mainapi', although other functions are specifically added later + * End of 'defgroup mainapi', although other functions are specifically added later. */ /** @@ -869,10 +973,10 @@ function panels_new_pane($type, $subtype, $set_defaults = FALSE) { * Helper function primarily for for panels_load_display(). * * @param array $dids - * An indexed array of dids to be loaded from the database. + * An indexed array of dids to be loaded from the database. * - * @return $displays - * An array of displays, keyed by their display dids. + * @return array + * An array of displays, keyed by their display dids. * * @todo schema API can drasticly simplify this code. */ @@ -882,7 +986,10 @@ function panels_load_displays($dids) { return $displays; } - $result = db_query("SELECT * FROM {panels_display} WHERE did IN (:dids)", array(':dids' => $dids)); + $result = db_query( + "SELECT * FROM {panels_display} WHERE did IN (:dids)", + array(':dids' => $dids) + ); ctools_include('export'); foreach ($result as $obj) { @@ -890,28 +997,28 @@ function panels_load_displays($dids) { // Modify the hide_title field to go from a bool to an int if necessary. } - $result = db_query("SELECT * FROM {panels_pane} WHERE did IN (:dids) ORDER BY did, panel, position", array(':dids' => $dids)); + $result = db_query( + "SELECT * FROM {panels_pane} WHERE did IN (:dids) ORDER BY did, panel, position", + array(':dids' => $dids) + ); foreach ($result as $obj) { $pane = ctools_export_unpack_object('panels_pane', $obj); $displays[$pane->did]->panels[$pane->panel][] = $pane->pid; $displays[$pane->did]->content[$pane->pid] = $pane; } - return $displays; } /** * Load a single display. * - * @ingroup mainapi - * * @param int $did - * The display id (did) of the display to be loaded. + * The display id (did) of the display to be loaded. * - * @return object $display instanceof panels_display \n - * Returns a partially-loaded panels_display object. $display objects returned from - * from this function have only the following data: + * @return object $display + * Returns a partially-loaded panels_display object. $display objects returned + * from this function have only the following data: * - $display->did (the display id) * - $display->name (the 'name' of the display, where applicable - it often isn't) * - $display->layout (a string with the system name of the display's layout) @@ -923,9 +1030,10 @@ function panels_load_displays($dids) { * - $display->cache (any relevant data from panels_simple_cache) * - $display->args * - $display->incoming_content + * While all of these members are defined, $display->context is NEVER defined in the returned $display; + * it must be set using one of the ctools_context_create() functions. * - * While all of these members are defined, $display->context is NEVER defined in the returned $display; - * it must be set using one of the ctools_context_create() functions. + * @ingroup mainapi */ function panels_load_display($did) { $displays = panels_load_displays(array($did)); @@ -937,8 +1045,6 @@ function panels_load_display($did) { /** * Save a display object. * - * @ingroup mainapi - * * Note that a new $display only receives a real did once it is run through * this function, and likewise for the pid of any new pane. * @@ -947,11 +1053,14 @@ function panels_load_display($did) { * universally-unique identifier (which is stored permanently in the 'uuid' * field). This format is also used in place of the real pid for exports. * - * @param object $display instanceof panels_display \n - * The display object to be saved. Passed by reference so the caller need not use - * the return value for any reason except convenience. + * @param object $display + * The display object to be saved. Passed by reference so the caller need not + * use the return value for any reason except convenience. * - * @return object $display instanceof panels_display \n + * @return object $display + * This display panel display object to return. + * + * @ingroup mainapi */ function panels_save_display(&$display) { $update = (isset($display->did) && is_numeric($display->did)) ? array('did') : array(); @@ -962,15 +1071,19 @@ function panels_save_display(&$display) { $pids = array(); if ($update) { - // Get a list of all panes currently in the database for this display so we can know if there - // are panes that need to be deleted. (i.e, aren't currently in our list of panes). - $result = db_query("SELECT pid FROM {panels_pane} WHERE did = :did", array(':did' => $display->did)); + // Get a list of all panes currently in the database for this display so we + // can know if there are panes that need to be deleted. (i.e, aren't + // currently in our list of panes). + $result = db_query( + "SELECT pid FROM {panels_pane} WHERE did = :did", + array(':did' => $display->did) + ); foreach ($result as $pane) { $pids[$pane->pid] = $pane->pid; } } - // update all the panes + // Update all the panes. ctools_include('plugins', 'panels'); ctools_include('content'); @@ -1007,7 +1120,7 @@ function panels_save_display(&$display) { // Remove the old new-* entry from the displays content. unset($display->content[$pid]); - // and put it back so our pids and positions can be used. + // Put it back so our pids and positions can be used. $display->content[$pane->pid] = $pane; // If the title pane was one of our panes that just got its ID changed, @@ -1019,7 +1132,7 @@ function panels_save_display(&$display) { // because it was needed to get the did. Chicken, egg, more chicken. db_update('panels_display') ->fields(array( - 'title_pane' => $pane->pid + 'title_pane' => $pane->pid, )) ->condition('did', $display->did) ->execute(); @@ -1049,7 +1162,7 @@ function panels_save_display(&$display) { // Allow other modules to take action when a display is saved. module_invoke_all('panels_display_save', $display); - // Log the change to watchdog, using the same style as node.module + // Log the change to watchdog, using the same style as node.module. $watchdog_args = array('%did' => $display->did); if (!empty($display->title)) { $watchdog_args['%title'] = $display->title; @@ -1059,7 +1172,7 @@ function panels_save_display(&$display) { watchdog('content', 'Panels: saved display with id %did', $watchdog_args, WATCHDOG_NOTICE); } - // to be nice, even tho we have a reference. + // To be nice, even though we have a reference. return $display; } @@ -1089,23 +1202,25 @@ function panels_delete_display($display) { * Only once panels_save_display() is called on the code version of $display * will the exported display be written to the database and permanently saved. * - * @see panels_page_export() or _panels_page_fetch_display() for sample implementations. - * - * @ingroup mainapi - * - * @param object $display instanceof panels_display \n - * This export function does no loading of additional data about the provided - * display. Consequently, the caller should make sure that all the desired data - * has been loaded into the $display before calling this function. + * @param object $display + * This export function does no loading of additional data about the provided + * display. Consequently, the caller should make sure that all the desired + * data has been loaded into the $display before calling this function. * @param string $prefix - * A string prefix that is prepended to each line of exported code. This is primarily - * used for prepending a double space when exporting so that the code indents and lines up nicely. + * A string prefix that is prepended to each line of exported code. This is + * primarily used for prepending a double space when exporting so that the + * code indents and lines up nicely. * * @return string $output - * The passed-in $display expressed as code, ready to be imported. Import by running - * eval($output) in the caller function; doing so will create a new $display variable - * with all the exported values. Note that if you have already defined a $display variable in - * the same scope as where you eval(), your existing $display variable WILL be overwritten. + * The passed-in $display expressed as code, ready to be imported. Import by + * running eval($output) in the caller function; doing so will create a new + * $display variable with all the exported values. Note that if you have + * already defined a $display variable in the same scope as where you eval(), + * your existing $display variable WILL be overwritten. + * + * @see panels_page_export() or _panels_page_fetch_display() for samples. + * + * @ingroup mainapi */ function panels_export_display($display, $prefix = '') { ctools_include('export'); @@ -1139,7 +1254,7 @@ function panels_export_display($display, $prefix = '') { if (!isset($region_counters[$pane->panel])) { $region_counters[$pane->panel] = 0; } - $output .= $prefix . '$display->panels[\'' . $pane->panel . '\'][' . $region_counters[$pane->panel]++ .'] = \'' . $pane->pid . "';\n"; + $output .= $prefix . '$display->panels[\'' . $pane->panel . '\'][' . $region_counters[$pane->panel]++ . '] = \'' . $pane->pid . "';\n"; } } $output .= $prefix . '$display->hide_title = '; @@ -1147,9 +1262,11 @@ function panels_export_display($display, $prefix = '') { case PANELS_TITLE_FIXED: $output .= 'PANELS_TITLE_FIXED'; break; + case PANELS_TITLE_NONE: $output .= 'PANELS_TITLE_NONE'; break; + case PANELS_TITLE_PANE: $output .= 'PANELS_TITLE_PANE'; break; @@ -1161,11 +1278,14 @@ function panels_export_display($display, $prefix = '') { } /** + * Panels Render Display. + * * Render a display by loading the content into an appropriate * array and then passing through to panels_render_layout. * * if $incoming_content is NULL, default content will be applied. Use * an empty string to indicate no content. + * * @ingroup hook_invocations */ function panels_render_display(&$display, $renderer = NULL) { @@ -1176,7 +1296,7 @@ function panels_render_display(&$display, $renderer = NULL) { if ($form_context = ctools_context_get_form($display->context)) { $form_context->form['#theme'] = 'panels_render_display_form'; if (empty($form_context->form['#theme_wrappers']) || !in_array('form', $form_context->form['#theme_wrappers'])) { - $form_context['#theme_wrappers'][] = 'form'; + $form_context->form['#theme_wrappers'][] = 'form'; } $form_context->form['#display'] = &$display; return $form_context->form; @@ -1197,16 +1317,32 @@ function theme_panels_render_display_form($vars) { return $vars['element']['#display']->render(); } -// @layout +/** + * Panels layout icon function. + */ function panels_print_layout_icon($id, $layout, $title = NULL) { ctools_add_css('panels_admin', 'panels'); $file = $layout['path'] . '/' . $layout['icon']; - return theme('panels_layout_icon', array('id' => $id, 'image' => theme('image', array('path' => $file, 'alt' => strip_tags($layout['title']), 'title' => strip_tags($layout['description']))), 'title' => $title)); + return theme( + 'panels_layout_icon', + array( + 'id' => $id, + 'image' => theme( + 'image', + array( + 'path' => $file, + 'alt' => strip_tags($layout['title']), + 'title' => strip_tags($layout['description']), + ) + ), + 'title' => $title, + ) + ); } /** - * Theme the layout icon image - * @layout + * Theme the layout icon image. + * * @todo move to theme.inc */ function theme_panels_layout_icon($vars) { @@ -1224,18 +1360,15 @@ function theme_panels_layout_icon($vars) { } /** - * Theme the layout link image + * Theme the layout link image. + * * @layout * * @todo Why isn't this a template at this point? * @todo Why does this take 4 arguments but only makes use of two? */ function theme_panels_layout_link($vars) { - $title = $vars['title']; - $image = $vars['image']; - $class = $vars['class']; - - $output = '