Browse Source

updated elysia_cron, elfinder, metatag, libraries, email_registration, migrate, nodeform_cols

Bachir Soussi Chiadmi 5 years ago
parent
commit
58cd990c8c
100 changed files with 3701 additions and 2760 deletions
  1. 3 3
      sites/all/modules/contrib/admin/nodeformcols/nfcbiblio.info
  2. 3 3
      sites/all/modules/contrib/admin/nodeformcols/nfcbiblio.module
  3. 3 3
      sites/all/modules/contrib/admin/nodeformcols/nfccaptcha.info
  4. 18 2
      sites/all/modules/contrib/admin/nodeformcols/nodeformcols.admin.inc
  5. 3 3
      sites/all/modules/contrib/admin/nodeformcols/nodeformcols.info
  6. 3 3
      sites/all/modules/contrib/admin/nodeformcols/nodeformcols.module
  7. 14 12
      sites/all/modules/contrib/content/diff/DiffEngine.php
  8. 8 5
      sites/all/modules/contrib/content/diff/diff.admin.inc
  9. 16 0
      sites/all/modules/contrib/content/diff/diff.api.php
  10. 3 4
      sites/all/modules/contrib/content/diff/diff.info
  11. 8 3
      sites/all/modules/contrib/content/diff/diff.install
  12. 2 1
      sites/all/modules/contrib/content/diff/diff.module
  13. 2 0
      sites/all/modules/contrib/dev/elysia_cron/README.txt
  14. 27 20
      sites/all/modules/contrib/dev/elysia_cron/elysia_cron.admin.inc
  15. 14 12
      sites/all/modules/contrib/dev/elysia_cron/elysia_cron.ctools.inc
  16. 23 5
      sites/all/modules/contrib/dev/elysia_cron/elysia_cron.drush.inc
  17. 3 4
      sites/all/modules/contrib/dev/elysia_cron/elysia_cron.info
  18. 67 29
      sites/all/modules/contrib/dev/elysia_cron/elysia_cron.module
  19. 19 21
      sites/all/modules/contrib/dev/elysia_cron/elysia_cron_scheduler.inc
  20. 16 0
      sites/all/modules/contrib/dev/elysia_cron/js/elysia_cron.js
  21. 17 6
      sites/all/modules/contrib/dev/libraries/CHANGELOG.txt
  22. 3 0
      sites/all/modules/contrib/dev/libraries/css/libraries.admin.css
  23. 117 24
      sites/all/modules/contrib/dev/libraries/libraries.admin.inc
  24. 2 0
      sites/all/modules/contrib/dev/libraries/libraries.api.php
  25. 56 24
      sites/all/modules/contrib/dev/libraries/libraries.drush.inc
  26. 3 4
      sites/all/modules/contrib/dev/libraries/libraries.info
  27. 10 0
      sites/all/modules/contrib/dev/libraries/libraries.install
  28. 141 7
      sites/all/modules/contrib/dev/libraries/libraries.module
  29. 36 0
      sites/all/modules/contrib/dev/libraries/libraries.theme.inc
  30. 19 8
      sites/all/modules/contrib/dev/libraries/tests/LibrariesAdminWebTest.test
  31. 3 4
      sites/all/modules/contrib/dev/libraries/tests/libraries/example_info_file.libraries.info
  32. 3 4
      sites/all/modules/contrib/dev/libraries/tests/modules/libraries_test_module/libraries_test_module.info
  33. 3 4
      sites/all/modules/contrib/dev/libraries/tests/themes/libraries_test_theme/libraries_test_theme.info
  34. 4 1
      sites/all/modules/contrib/files/elfinder/CHANGELOG.txt
  35. 8 333
      sites/all/modules/contrib/files/elfinder/LICENSE.txt
  36. 79 83
      sites/all/modules/contrib/files/elfinder/README.txt
  37. 10 4
      sites/all/modules/contrib/files/elfinder/css/elfinder.admin.css
  38. 48 27
      sites/all/modules/contrib/files/elfinder/css/elfinder.common.css
  39. 10 5
      sites/all/modules/contrib/files/elfinder/css/elfinder.css
  40. 0 9
      sites/all/modules/contrib/files/elfinder/css/elfinder.d7.css
  41. 5 0
      sites/all/modules/contrib/files/elfinder/css/ui-themes/smoothness/jquery-ui.custom.css
  42. 2 2
      sites/all/modules/contrib/files/elfinder/css/ui-themes/smoothness/jquery-ui.min.css
  43. 0 0
      sites/all/modules/contrib/files/elfinder/editors/bueditor/bueditor.callback.js
  44. 19 13
      sites/all/modules/contrib/files/elfinder/editors/bueditor/bueditor.inc
  45. 9 3
      sites/all/modules/contrib/files/elfinder/editors/bueditor/bueditor.js
  46. 18 4
      sites/all/modules/contrib/files/elfinder/editors/ckeditor/ckeditor.callback.js
  47. 8 2
      sites/all/modules/contrib/files/elfinder/editors/ckeditor/ckeditor.inc
  48. 23 17
      sites/all/modules/contrib/files/elfinder/editors/ckeditor/ckeditor.upload.inc
  49. 7 2
      sites/all/modules/contrib/files/elfinder/editors/drupalnodeattach/drupalnodeattach.callback.js
  50. 10 1
      sites/all/modules/contrib/files/elfinder/editors/fckeditor/fckeditor.callback.js
  51. 30 24
      sites/all/modules/contrib/files/elfinder/editors/fckeditor/fckeditor.inc
  52. 24 18
      sites/all/modules/contrib/files/elfinder/editors/fckeditor/fckeditor.upload.inc
  53. 10 1
      sites/all/modules/contrib/files/elfinder/editors/jwysiwyg/jwysiwyg.callback.js
  54. 30 20
      sites/all/modules/contrib/files/elfinder/editors/jwysiwyg/jwysiwyg.inc
  55. 32 26
      sites/all/modules/contrib/files/elfinder/editors/jwysiwyg/jwysiwyg.js
  56. 0 0
      sites/all/modules/contrib/files/elfinder/editors/tinymce/tinymce.callback.js
  57. 21 15
      sites/all/modules/contrib/files/elfinder/editors/tinymce/tinymce.inc
  58. 42 23
      sites/all/modules/contrib/files/elfinder/editors/tinymce/tinymce.js
  59. 8 2
      sites/all/modules/contrib/files/elfinder/editors/wymeditor/wymeditor.callback.js
  60. 18 12
      sites/all/modules/contrib/files/elfinder/editors/wymeditor/wymeditor.inc
  61. 55 43
      sites/all/modules/contrib/files/elfinder/editors/wymeditor/wymeditor.js
  62. 9 3
      sites/all/modules/contrib/files/elfinder/editors/yui/yui.callback.js
  63. 20 12
      sites/all/modules/contrib/files/elfinder/editors/yui/yui.inc
  64. 34 26
      sites/all/modules/contrib/files/elfinder/editors/yui/yui.js
  65. 3 2
      sites/all/modules/contrib/files/elfinder/elfinder.info
  66. 71 68
      sites/all/modules/contrib/files/elfinder/elfinder.install
  67. 292 225
      sites/all/modules/contrib/files/elfinder/elfinder.module
  68. 79 28
      sites/all/modules/contrib/files/elfinder/inc/elfinder.admin.inc
  69. 197 192
      sites/all/modules/contrib/files/elfinder/inc/elfinder.admin.profiles.inc
  70. 285 265
      sites/all/modules/contrib/files/elfinder/inc/elfinder.drupal.inc
  71. 113 107
      sites/all/modules/contrib/files/elfinder/inc/elfinder.drupalfs.acl.inc
  72. 14 6
      sites/all/modules/contrib/files/elfinder/inc/elfinder.drupalfs.driver.inc
  73. 380 205
      sites/all/modules/contrib/files/elfinder/js/elfinder.callback.js
  74. 2 0
      sites/all/modules/contrib/files/elfinder/js/elfinder.jquery-ui.legacy.min.js
  75. 1 1
      sites/all/modules/contrib/files/elfinder/js/elfinder.jquery-ui.min.js
  76. 1 0
      sites/all/modules/contrib/files/elfinder/js/elfinder.jquery.legacy.min.js
  77. 0 1
      sites/all/modules/contrib/files/elfinder/js/elfinder.jquery.min.js
  78. 6 0
      sites/all/modules/contrib/files/elfinder/js/elfinder.wysiwyg.init.js
  79. 6 0
      sites/all/modules/contrib/files/elfinder/js/helper.js
  80. 260 254
      sites/all/modules/contrib/files/elfinder/js/info.js
  81. 4 2
      sites/all/modules/contrib/files/elfinder/modules/elfinder_bueditor/elfinder_bueditor.info
  82. 7 6
      sites/all/modules/contrib/files/elfinder/modules/elfinder_bueditor/elfinder_bueditor.module
  83. 4 2
      sites/all/modules/contrib/files/elfinder/modules/elfinder_ffsel/elfinder_ffsel.info
  84. 59 54
      sites/all/modules/contrib/files/elfinder/modules/elfinder_ffsel/elfinder_ffsel.module
  85. 31 18
      sites/all/modules/contrib/files/elfinder/modules/elfinder_ffsel/ffs.callback.js
  86. 14 0
      sites/all/modules/contrib/files/elfinder/modules/elfinder_tinymce/elfinder_tinymce.info
  87. 24 0
      sites/all/modules/contrib/files/elfinder/modules/elfinder_tinymce/elfinder_tinymce.module
  88. 9 9
      sites/all/modules/contrib/files/elfinder/tpl/elfinder-page-backend.tpl.php
  89. 17 17
      sites/all/modules/contrib/files/elfinder/tpl/elfinder-page.tpl.php
  90. 26 0
      sites/all/modules/contrib/migrate/migrate/CHANGELOG.txt
  91. 13 11
      sites/all/modules/contrib/migrate/migrate/README.txt
  92. 211 163
      sites/all/modules/contrib/migrate/migrate/includes/base.inc
  93. 17 9
      sites/all/modules/contrib/migrate/migrate/includes/destination.inc
  94. 4 0
      sites/all/modules/contrib/migrate/migrate/includes/exception.inc
  95. 35 5
      sites/all/modules/contrib/migrate/migrate/includes/field_mapping.inc
  96. 18 12
      sites/all/modules/contrib/migrate/migrate/includes/group.inc
  97. 5 1
      sites/all/modules/contrib/migrate/migrate/includes/handler.inc
  98. 20 7
      sites/all/modules/contrib/migrate/migrate/includes/map.inc
  99. 198 132
      sites/all/modules/contrib/migrate/migrate/includes/migration.inc
  100. 14 9
      sites/all/modules/contrib/migrate/migrate/includes/source.inc

+ 3 - 3
sites/all/modules/contrib/admin/nodeformcols/nfcbiblio.info

@@ -5,9 +5,9 @@ dependencies[] = biblio
 core = 7.x
 package = Node form columns
 
-; Information added by Drupal.org packaging script on 2014-01-15
-version = "7.x-1.0"
+; Information added by Drupal.org packaging script on 2016-09-16
+version = "7.x-1.1"
 core = "7.x"
 project = "nodeformcols"
-datestamp = "1389798806"
+datestamp = "1474036440"
 

+ 3 - 3
sites/all/modules/contrib/admin/nodeformcols/nfcbiblio.module

@@ -19,7 +19,7 @@ function nfcbiblio_nodeformcols_variants_alter(&$variants, $type) {
       WHERE tid >= :tid
         AND visible = :visible
       ORDER BY weight ASC', array(':tid' => 0, ':visible' => 1));
-    while ($option = db_fetch_object($res)) {
+    while ($option = $res->fetchObject()) {
       $variants[$option->tid] = $option->name;
     }
   }
@@ -35,8 +35,8 @@ function _nfcbiblio_top_visible_type() {
   return db_query_range("SELECT tid
     FROM {biblio_types}
     WHERE visible = :visible
-      AND tid> = :tid>
-    ORDER BY weight ASC", array(':visible' => 1, ':tid>' => 0))->fetchField();
+    AND tid >= :tid
+    ORDER BY weight ASC", 0, 1, array(':visible' => 1, ':tid' => 0))->fetchField();
 }
 
 /**

+ 3 - 3
sites/all/modules/contrib/admin/nodeformcols/nfccaptcha.info

@@ -5,9 +5,9 @@ dependencies[] = captcha
 core = 7.x
 package = Node form columns
 
-; Information added by Drupal.org packaging script on 2014-01-15
-version = "7.x-1.0"
+; Information added by Drupal.org packaging script on 2016-09-16
+version = "7.x-1.1"
 core = "7.x"
 project = "nodeformcols"
-datestamp = "1389798806"
+datestamp = "1474036440"
 

+ 18 - 2
sites/all/modules/contrib/admin/nodeformcols/nodeformcols.admin.inc

@@ -21,6 +21,20 @@ function _nodeformcols_get_node_type_form($type) {
   );
   $fs += form_state_defaults();
   $nf = drupal_retrieve_form($nfid, $fs);
+  // Add in field_groups if they exist.
+  if (module_exists('field_group') && !empty($nf['#groups'])) {
+    foreach ($nf['#groups'] as $group) {
+      $group_title = $group->label . ' (' . t('Field group') . ')';
+      $nf[$group->group_name] = array(
+        '#group'  =>  $group,
+        '#weight' =>  $group->weight,
+        '#title'  =>  $group_title,
+      );
+      foreach ($nf['#groups'][$group->group_name]->children as $group_field) {
+        unset($nf[$group_field]);
+      }
+    }
+  }
   drupal_prepare_form($nfid, $nf, $fs);
   drupal_process_form($nfid, $nf, $fs);
   return $nf;
@@ -35,8 +49,10 @@ function nodeformcols_update_placements($type, $variant, &$placements) {
     $field = $form[$key];
     if (
       substr($key, 0, 8) == 'section_' ||
+      // Exclude hidden fields.
       (isset($field['#type']) && in_array($field['#type'], array('value', 'hidden', 'token'))) ||
-      (isset($field['#type'], $field['#group']) && $field['#type'] === 'fieldset')
+      // Exclude the vertical tabs.
+      (isset($field['#group']) && $field['#group'] == 'additional_settings')
     ) {
       // Remove placements that meet exclusion rules.
       if (isset($placements[$key])) {
@@ -128,7 +144,7 @@ function nodeformcols_configuration_form($form, $form_state, $node_type, $varian
     $form['variant'] = array(
       '#type' => 'item',
       '#title' => t('Select a form variant'),
-      '#value' => theme('links', array('links' => $variant_links)),
+      '#markup' => theme('links', array('links' => $variant_links)),
     );
   }
 

+ 3 - 3
sites/all/modules/contrib/admin/nodeformcols/nodeformcols.info

@@ -3,9 +3,9 @@ description = Separates the node forms into two columns and a footer.
 core = 7.x
 package = Node form columns
 
-; Information added by Drupal.org packaging script on 2014-01-15
-version = "7.x-1.0"
+; Information added by Drupal.org packaging script on 2016-09-16
+version = "7.x-1.1"
 core = "7.x"
 project = "nodeformcols"
-datestamp = "1389798806"
+datestamp = "1474036440"
 

+ 3 - 3
sites/all/modules/contrib/admin/nodeformcols/nodeformcols.module

@@ -160,8 +160,8 @@ function template_preprocess_node_form(&$aVars) {
     }
   }
 
-  foreach ($has_elements as $name => $has) {
-    if ($has) {
+  foreach ($regions as $name => $data) {
+    if (!empty($has_elements[$name])) {
       $class[] = 'node-form-has-region-' . $name;
       $form['nodeformcols_region_' . $name] = $regions[$name];
     }
@@ -191,8 +191,8 @@ function nodeformcols_node_type_update($info) {
     $base = 'nodeformscols_field_placements_' . $info->old_type;
     $new_base = 'nodeformscols_field_placements_' . $info->type;
     $result = db_select('variable')
-      ->condition('name', $base . '%', 'LIKE')
       ->fields('variable', array('name'))
+      ->condition('name', $base . '%', 'LIKE')
       ->execute();
     foreach ($result as $row) {
       $value = variable_get($row->name, NULL);

+ 14 - 12
sites/all/modules/contrib/content/diff/DiffEngine.php

@@ -312,7 +312,8 @@ class _DiffEngine {
         }
         $matches = $ymatches[$line];
         reset($matches);
-        while (list ($junk, $y) = each($matches)) {
+        while ($y = current($matches)) {
+          next($matches);
           if (empty($this->in_seq[$y])) {
             $k = $this->_lcs_pos($y);
             USE_ASSERTS && assert($k > 0);
@@ -320,7 +321,8 @@ class _DiffEngine {
             break;
           }
         }
-        while (list ($junk, $y) = each($matches)) {
+        while ($y = current($matches)) {
+          next($matches);
           if ($y > $this->seq[$k-1]) {
             USE_ASSERTS && assert($y < $this->seq[$k]);
             // Optimization: this is a common case:
@@ -454,7 +456,7 @@ class _DiffEngine {
     $i = 0;
     $j = 0;
 
-    USE_ASSERTS && assert('sizeof($lines) == sizeof($changed)');
+    USE_ASSERTS && assert(sizeof($lines) == sizeof($changed));
     $len = sizeof($lines);
     $other_len = sizeof($other_changed);
 
@@ -474,7 +476,7 @@ class _DiffEngine {
         $j++;
       }
       while ($i < $len && ! $changed[$i]) {
-        USE_ASSERTS && assert('$j < $other_len && ! $other_changed[$j]');
+        USE_ASSERTS && assert($j < $other_len && ! $other_changed[$j]);
         $i++;
         $j++;
         while ($j < $other_len && $other_changed[$j]) {
@@ -510,11 +512,11 @@ class _DiffEngine {
           while ($start > 0 && $changed[$start - 1]) {
             $start--;
           }
-          USE_ASSERTS && assert('$j > 0');
+          USE_ASSERTS && assert($j > 0);
           while ($other_changed[--$j]) {
             continue;
           }
-          USE_ASSERTS && assert('$j >= 0 && !$other_changed[$j]');
+          USE_ASSERTS && assert($j >= 0 && !$other_changed[$j]);
         }
 
         /*
@@ -537,7 +539,7 @@ class _DiffEngine {
           while ($i < $len && $changed[$i]) {
             $i++;
           }
-          USE_ASSERTS && assert('$j < $other_len && ! $other_changed[$j]');
+          USE_ASSERTS && assert($j < $other_len && ! $other_changed[$j]);
           $j++;
           if ($j < $other_len && $other_changed[$j]) {
             $corresponding = $i;
@@ -555,11 +557,11 @@ class _DiffEngine {
       while ($corresponding < $i) {
         $changed[--$start] = 1;
         $changed[--$i] = 0;
-        USE_ASSERTS && assert('$j > 0');
+        USE_ASSERTS && assert($j > 0);
         while ($other_changed[--$j]) {
           continue;
         }
-        USE_ASSERTS && assert('$j >= 0 && !$other_changed[$j]');
+        USE_ASSERTS && assert($j >= 0 && !$other_changed[$j]);
       }
     }
   }
@@ -742,8 +744,8 @@ class MappedDiff extends Diff {
    *  have the same number of elements as $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));
+    USE_ASSERTS && assert(sizeof($from_lines) == sizeof($mapped_from_lines));
+    USE_ASSERTS && assert(sizeof($to_lines) == sizeof($mapped_to_lines));
 
     parent::__construct($mapped_from_lines, $mapped_to_lines);
 
@@ -1000,7 +1002,7 @@ class _HWLDF_WordAccumulator {
         $this->_flushLine($tag);
         $word = drupal_substr($word, 1);
       }
-      assert(!strstr($word, "\n"));
+      USE_ASSERTS && assert(!strstr($word, "\n"));
       $this->_group .= $word;
     }
   }

+ 8 - 5
sites/all/modules/contrib/content/diff/diff.admin.inc

@@ -112,7 +112,12 @@ function diff_admin_field_overview() {
     '#markup' => '<p>' . t('This table provides a summary of the field type support found on the system. It is recommended that you use global settings whenever possible to configure field comparison settings.') . '</p>',
   );
 
-  $header = array(t('Type'), t('Module'), t('Operations'));
+  $header = array(
+    t('Type'),
+    t('Machine name'),
+    t('Module'),
+    t('Operations'),
+  );
   $rows = array();
 
   // Skip field types which have no widget types.
@@ -129,10 +134,8 @@ function diff_admin_field_overview() {
   foreach ($field_types as $field_name => $field_type) {
     if (!empty($widgets[$field_name])) {
       $row = array();
-      $row[] = t('@field_label (%field_type)', array(
-        '@field_label' => $field_type['label'],
-        '%field_type' => $field_name,
-      ));
+      $row[] = $field_type['label'];
+      $row[] = $field_name;
       $row[] = $field_type['module'];
       $row[] = l(t('Global settings'), 'admin/config/content/diff/fields/' . $field_name);
       $rows[] = $row;

+ 16 - 0
sites/all/modules/contrib/content/diff/diff.api.php

@@ -108,6 +108,22 @@ function hook_entity_diff($old_entity, $new_entity, $context) {
  * @see hook_entity_diff()
  */
 function hook_entity_diff_alter(&$entity_diffs, $context) {
+  if ($context['entity_type'] == 'node') {
+    $old_entity = $context['old_entity'];
+    $new_entity = $context['new_entity'];
+    $entity_diffs['custom_vid'] = array(
+      '#name' => t('Second VID'),
+      '#old' => array($old_entity->vid),
+      '#new' => array($new_entity->vid),
+      '#weight' => 5,
+    );
+    $entity_diffs['custom_log'] = array(
+      '#name' => t('Second log'),
+      '#old' => array($old_entity->log),
+      '#new' => array($new_entity->log),
+      '#weight' => 6,
+    );
+  }
 }
 
 /**

+ 3 - 4
sites/all/modules/contrib/content/diff/diff.info

@@ -5,9 +5,8 @@ configure = admin/config/content/diff
 
 files[] = DiffEngine.php
 
-; Information added by Drupal.org packaging script on 2016-12-20
-version = "7.x-3.3"
+; Information added by Drupal.org packaging script on 2018-11-05
+version = "7.x-3.4"
 core = "7.x"
 project = "diff"
-datestamp = "1482211686"
-
+datestamp = "1541401388"

+ 8 - 3
sites/all/modules/contrib/content/diff/diff.install

@@ -133,9 +133,14 @@ function diff_update_7306() {
 }
 
 /**
- * Grants access to the Diff "View Changes" button permission to all users.
+ * Grants access to the Diff "View Changes" button permission to all users
+ * if the Diff module is enabled. You need to manually update the permissions
+ * if the module is currently disabled.
  */
 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'));
+  // The update hooks run even if disabled, and this throws an error.
+  if (module_exists('diff')) {
+    user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, array('diff view changes'));
+    user_role_grant_permissions(DRUPAL_AUTHENTICATED_RID, array('diff view changes'));
+  }
 }

+ 2 - 1
sites/all/modules/contrib/content/diff/diff.module

@@ -475,7 +475,8 @@ function diff_node_form_build_preview_changes($form, &$form_state) {
   $node = node_form_submit_build_node($form, $form_state);
 
   // Create diff of old node and edited node.
-  $rows = _diff_body_rows($old_node, $node);
+  $state = variable_get('diff_default_state_node', 'raw');
+  $rows = _diff_body_rows($old_node, $node, $state);
 
   $header = _diff_default_header(t('Original'), t('Changes'));
   $changes = theme('table__diff__preview', array(

+ 2 - 0
sites/all/modules/contrib/dev/elysia_cron/README.txt

@@ -153,6 +153,8 @@ Options:
                                            --verbose, but without enabling drush
                                            verbose mode)
  --ignore-disable                          run channels/tasks even if disabled
+ --ignore-maintenance                      run channels/tasks even if
+                                           maintenance mode is enabled
  --ignore-running                          run channels/tasks even
                                            if already running
  --ignore-time                             run channels/tasks even if not ready

+ 27 - 20
sites/all/modules/contrib/dev/elysia_cron/elysia_cron.admin.inc

@@ -10,6 +10,9 @@
  *
  * @return array
  *   Renderable array.
+ *
+ * @throws Exception
+ *   Exceptions from theme().
  */
 function elysia_cron_admin_page() {
   $aoutput = array();
@@ -151,10 +154,26 @@ function elysia_cron_admin_page() {
   $output .= '<br />';
 
   $legend_icons = array(
-    'idle' => theme('image', array('path' => $ipath . 'idle.png')),
-    'waiting' => theme('image', array('path' => $ipath . 'waiting.png')),
-    'running' => theme('image', array('path' => $ipath . 'running.png')),
-    'disabled' => theme('image', array('path' => $ipath . 'disabled.png')),
+    'idle' => theme('image', array(
+      'path' => $ipath . 'idle.png',
+      'alt' => t('Idle'),
+      'title' => t('Idle'),
+    )),
+    'waiting' => theme('image', array(
+      'path' => $ipath . 'waiting.png',
+      'alt' => t('Waiting for execution'),
+      'title' => t('Waiting for execution'),
+    )),
+    'running' => theme('image', array(
+      'path' => $ipath . 'running.png',
+      'alt' => t('Running'),
+      'title' => t('Running'),
+    )),
+    'disabled' => theme('image', array(
+      'path' => $ipath . 'disabled.png',
+      'alt' => t('Disabled'),
+      'title' => t('Disabled'),
+    )),
   );
   $output .= theme('table', array(
     'header' => array(t('Legend')),
@@ -187,6 +206,7 @@ function elysia_cron_settings_form() {
   elysia_cron_initialize();
 
   $form = array();
+  $form['#attached']['js'][] = drupal_get_path('module', 'elysia_cron') . '/js/elysia_cron.js';
 
   $form['prefix_1'] = array(
     '#type' => 'fieldset',
@@ -429,14 +449,6 @@ EOT
     '#collapsible' => TRUE,
   );
 
-  $jobchannels = array(
-    '#title' => t('Job channel associations'),
-    '#description' => t('Leave empty for default channel'),
-    '#type' => 'fieldset',
-    '#collapsible' => TRUE,
-    '#collapsed' => TRUE,
-  );
-
   foreach ($_elysia_cron_settings_by_channel as $channel => $cconf) {
     foreach ($cconf as $job => $conf) {
       if ($job != '#data' && empty($conf['expression'])) {
@@ -546,12 +558,6 @@ EOT
 function theme_elysia_cron_settings_form(array &$variables) {
   $form = &$variables['form'];
 
-  $output = '<script type="text/javascript"><!--' . "\n" .
-    'function _ec_select(key, select) { if (select.value == \'custom\') {' .
-      '$ = jQuery; $("#_ec_select_"+key).hide();$("#_ec_custom_"+key).show();$("#_ec_custom_"+key).focus();' .
-    '}}' .
-    "\n" . '--></script>';
-
   $coutput = '<table>';
 
   $i = 0;
@@ -579,7 +585,8 @@ function theme_elysia_cron_settings_form(array &$variables) {
     $form['single_job'][$c]['_elysia_cron_seljob_rule_' . $key]['#suffix'] = '</span>';
     $form['single_job'][$c]['_elysia_cron_seljob_rule_' . $key]['#title'] = NULL;
     $form['single_job'][$c]['_elysia_cron_seljob_rule_' . $key]['#description'] = NULL;
-    $form['single_job'][$c]['_elysia_cron_seljob_rule_' . $key]['#attributes']['onchange'] = '_ec_select(\'' . $key . '\', this)';
+    $form['single_job'][$c]['_elysia_cron_seljob_rule_' . $key]['#attributes']['class'][] = 'ec-select';
+    $form['single_job'][$c]['_elysia_cron_seljob_rule_' . $key]['#attributes']['data-key'] = $key;
 
     $form['single_job'][$c]['_elysia_cron_job_weight_' . $key]['#title'] = NULL;
     $form['single_job'][$c]['_elysia_cron_job_weight_' . $key]['#description'] = NULL;
@@ -631,7 +638,7 @@ function theme_elysia_cron_settings_form(array &$variables) {
 
   $form['channels']['#children'] = $coutput;
 
-  return $output . drupal_render_children($form);
+  return drupal_render_children($form);
 }
 
 /**

+ 14 - 12
sites/all/modules/contrib/dev/elysia_cron/elysia_cron.ctools.inc

@@ -5,6 +5,8 @@
  * Ctools integration.
  */
 
+define('ELYSIA_CRON_CTOOLS_LINEBREAK', "\n");
+
 /**
  * Get default cron jobs.
  *
@@ -203,13 +205,13 @@ function elysia_cron_ctools_export_callback($object, $indent) {
   $schema = ctools_export_get_schema($table);
   $identifier = $schema['export']['identifier'];
 
-  $output = $indent . '$' . $identifier . ' = new ' . get_class($object) . ';' . PHP_EOL;
+  $output = $indent . '$' . $identifier . ' = new ' . get_class($object) . '();' . ELYSIA_CRON_CTOOLS_LINEBREAK;
 
   if ($schema['export']['can disable']) {
-    $output .= $indent . '$' . $identifier . '->disabled = FALSE; /* Edit this to true to make a default ' . $identifier . ' disabled initially */' . PHP_EOL;
+    $output .= $indent . '$' . $identifier . '->disabled = FALSE; /* Edit this to true to make a default ' . $identifier . ' disabled initially */' . ELYSIA_CRON_CTOOLS_LINEBREAK;
   }
   if (!empty($schema['export']['api']['current_version'])) {
-    $output .= $indent . '$' . $identifier . '->api_version = ' . $schema['export']['api']['current_version'] . ';' . PHP_EOL;
+    $output .= $indent . '$' . $identifier . '->api_version = ' . $schema['export']['api']['current_version'] . ';' . ELYSIA_CRON_CTOOLS_LINEBREAK;
   }
 
   $fields = $schema['fields'];
@@ -222,7 +224,7 @@ function elysia_cron_ctools_export_callback($object, $indent) {
     if (!is_null($value) && $info['type'] == 'int') {
       $value = (isset($info['size']) && $info['size'] == 'tiny') ? (bool) $value : (int) $value;
     }
-    $output .= $indent . '$' . $identifier . '->' . $field . ' = ' . ctools_var_export($value, $indent) . ';' . PHP_EOL;
+    $output .= $indent . '$' . $identifier . '->' . $field . ' = ' . ctools_var_export($value, $indent) . ';' . ELYSIA_CRON_CTOOLS_LINEBREAK;
   }
 
   return $output;
@@ -253,19 +255,19 @@ function elysia_cron_ctools_to_hook_code(array $names, $name) {
   $objects = array_intersect_key($objects, array_flip($names));
 
   if ($objects) {
-    $output = '/**' . PHP_EOL;
-    $output .= " * Implementation of hook_{$export['default hook']}()" . PHP_EOL;
-    $output .= ' */' . PHP_EOL;
-    $output .= "function " . $name . "_{$export['default hook']}() {" . PHP_EOL;
-    $output .= "  \${$export['identifier']}s = array();" . PHP_EOL . PHP_EOL;
+    $output = '/**' . ELYSIA_CRON_CTOOLS_LINEBREAK;
+    $output .= " * Implementation of hook_{$export['default hook']}()" . ELYSIA_CRON_CTOOLS_LINEBREAK;
+    $output .= ' */' . ELYSIA_CRON_CTOOLS_LINEBREAK;
+    $output .= "function " . $name . "_{$export['default hook']}() {" . ELYSIA_CRON_CTOOLS_LINEBREAK;
+    $output .= "  \${$export['identifier']}s = array();" . ELYSIA_CRON_CTOOLS_LINEBREAK . ELYSIA_CRON_CTOOLS_LINEBREAK;
 
     foreach ($objects as $object) {
       $output .= ctools_export_crud_export($table, $object, '  ');
-      $output .= "  \${$export['identifier']}s['" . check_plain($object->{$export['key']}) . "'] = \${$export['identifier']};" . PHP_EOL . PHP_EOL;
+      $output .= "  \${$export['identifier']}s['" . check_plain($object->{$export['key']}) . "'] = \${$export['identifier']};" . ELYSIA_CRON_CTOOLS_LINEBREAK . ELYSIA_CRON_CTOOLS_LINEBREAK;
     }
 
-    $output .= "  return \${$export['identifier']}s;" . PHP_EOL;
-    $output .= '}' . PHP_EOL;
+    $output .= "  return \${$export['identifier']}s;" . ELYSIA_CRON_CTOOLS_LINEBREAK;
+    $output .= '}' . ELYSIA_CRON_CTOOLS_LINEBREAK;
   }
 
   return $output;

+ 23 - 5
sites/all/modules/contrib/dev/elysia_cron/elysia_cron.drush.inc

@@ -63,7 +63,9 @@ function elysia_cron_drush_command() {
       'quiet' => 'suppress all output',
       'verbose' => 'enable extended output',
       'elysia-cron-verbose' => 'enable extended output (the same as --verbose, but without enabling drush verbose mode)',
+      'force' => 'run channels/tasks even if it disabled/not ready for execution/already running',
       'ignore-disable' => 'run channels/tasks even if disabled',
+      'ignore-maintenance' => 'run channels/tasks even if maintenance mode is enabled',
       'ignore-time' => 'run channels/tasks even if not ready for execution',
       'ignore-running' => 'run channels/tasks even if already running',
     ),
@@ -79,8 +81,10 @@ function elysia_cron_drush_command() {
 function drush_elysia_cron_run_wrapper($op = FALSE, $target = FALSE) {
   global $_elysia_cron_drush;
 
+  $force = drush_get_option('force', FALSE);
   if (variable_get('maintenance_mode', FALSE)) {
-    if (!variable_get('elysia_cron_run_maintenance', FALSE)) {
+    $ignore_maintenance = $force || drush_get_option('ignore-maintenance', FALSE);
+    if (!$ignore_maintenance && !variable_get('elysia_cron_run_maintenance', FALSE)) {
       drush_set_error('Cron run is not allowed in maintenance mode');
       return;
     }
@@ -91,7 +95,16 @@ function drush_elysia_cron_run_wrapper($op = FALSE, $target = FALSE) {
   if (!$verbose) {
     $verbose = drush_get_option('elysia-cron-verbose', FALSE);
   }
-  $_elysia_cron_drush = $quiet ? 1 : !$verbose ? 2 : 3;
+
+  if ($quiet) {
+    $_elysia_cron_drush = 1;
+  }
+  elseif ($verbose) {
+    $_elysia_cron_drush = 3;
+  }
+  else {
+    $_elysia_cron_drush = 2;
+  }
 
   switch ($op) {
     case 'list':
@@ -140,13 +153,18 @@ function drush_elysia_cron_run_wrapper($op = FALSE, $target = FALSE) {
       break;
 
     case 'run':
+      // Collect options.
+      $ignore_disable = $force || drush_get_option('ignore-disable', FALSE);
+      $ignore_time = $force || drush_get_option('ignore-time', FALSE);
+      $ignore_running = $force || drush_get_option('ignore-running', FALSE);
+
       if (empty($target)) {
-        elysia_cron_run(FALSE, drush_get_option('ignore-disable', FALSE), drush_get_option('ignore-time', FALSE), drush_get_option('ignore-running', FALSE));
+        elysia_cron_run(FALSE, $ignore_disable, $ignore_time, $ignore_running);
       }
       elseif (strpos($target, '@') === 0) {
         elysia_cron_initialize();
         if (elysia_cron_channel_exists(substr($target, 1))) {
-          elysia_cron_run_channel(substr($target, 1), drush_get_option('ignore-disable', FALSE), drush_get_option('ignore-time', FALSE), drush_get_option('ignore-running', FALSE));
+          elysia_cron_run_channel(substr($target, 1), $ignore_disable, $ignore_time, $ignore_running);
         }
         else {
           drush_set_error('Channel ' . substr($target, 1) . ' does not exists');
@@ -155,7 +173,7 @@ function drush_elysia_cron_run_wrapper($op = FALSE, $target = FALSE) {
       else {
         elysia_cron_initialize();
         if (elysia_cron_job_exists($target)) {
-          elysia_cron_run_job($target, drush_get_option('ignore-disable', FALSE), drush_get_option('ignore-time', FALSE), drush_get_option('ignore-running', FALSE));
+          elysia_cron_run_job($target, $ignore_disable, $ignore_time, $ignore_running);
         }
         else {
           drush_set_error('Job ' . $target . ' does not exists');

+ 3 - 4
sites/all/modules/contrib/dev/elysia_cron/elysia_cron.info

@@ -4,9 +4,8 @@ core = 7.x
 
 configure = admin/config/system/cron
 
-; Information added by Drupal.org packaging script on 2016-11-23
-version = "7.x-2.4"
+; Information added by Drupal.org packaging script on 2019-04-24
+version = "7.x-2.7"
 core = "7.x"
 project = "elysia_cron"
-datestamp = "1479877741"
-
+datestamp = "1556076200"

+ 67 - 29
sites/all/modules/contrib/dev/elysia_cron/elysia_cron.module

@@ -64,14 +64,15 @@ function elysia_cron_menu() {
  */
 function elysia_cron_menu_alter(&$items) {
   // Override default cron page.
-  $items['admin/config/system/cron'] = array(
-    'title' => 'Cron Settings',
-    'description' => 'View and manage cron table',
-    'page callback' => 'elysia_cron_admin_page',
-    'access callback' => 'elysia_cron_access',
-    'access arguments' => array('view elysia_cron'),
-    'file' => NULL,
-  ) + $items['admin/config/system/cron'];
+  $items['admin/config/system/cron']['title'] = 'Cron Settings';
+  $items['admin/config/system/cron']['description'] = 'View and manage cron table';
+  $items['admin/config/system/cron']['page callback'] = 'elysia_cron_admin_page';
+  $items['admin/config/system/cron']['access callback'] = 'elysia_cron_access';
+  $items['admin/config/system/cron']['access arguments'] = array('view elysia_cron');
+  $items['admin/config/system/cron']['file'] = NULL;
+
+  $items['admin/reports/status/run-cron']['page callback'] = 'elysia_cron_run_manually';
+  $items['admin/reports/status/run-cron']['file'] = NULL;
 }
 
 /**
@@ -113,7 +114,7 @@ function elysia_cron_permission() {
     'administer elysia_cron' => array(
       'title' => t('Administer elysia cron'),
       'description' => t('Perform changes to cron jobs timings, disable cron or single jobs and access cron execution statistics'),
-      'restrict access' => TRUE,  
+      'restrict access' => TRUE,
     ),
     'execute elysia_cron' => array(
       'title' => t('Execute elysia cron jobs'),
@@ -143,6 +144,12 @@ function elysia_cron_exit() {
 function elysia_cron_cron() {
   global $_elysia_cron_exit_phase, $_elysia_cron_drush;
 
+  // First cron run is executed in standard drupal way.
+  // This is to enable the use of install profiles.
+  if (variable_get('cron_last', 0) <= variable_get('install_time', 0)) {
+    return;
+  }
+
   // If cron has been executed via "drush core-cron" or any other custom drush
   // command then we run internal cron handler which is designed to handle
   // cron executions from drush.
@@ -150,11 +157,6 @@ function elysia_cron_cron() {
     elysia_cron_drush_invoke();
   }
 
-  // First cron run is executed in standard drupal way.
-  // This is to enable the use of install profiles.
-  if (variable_get('cron_last', 0) <= variable_get('install_time', 0)) {
-    return;
-  }
   // If the path is 'admin/*', or if the user is not anonymous,
   // this is a manual cron run (probably by admin/logs/status),
   // but not if we are in the exit phase (= this a "poormanscron" run).
@@ -187,7 +189,7 @@ function elysia_cron_cron() {
     variable_set('cron_last', time());
   }
 
-  exit();
+  drupal_exit();
 }
 
 /**
@@ -238,8 +240,11 @@ $GLOBALS['_ec_variables_allowed'] = array(
  */
 function _ec_variable_init() {
   global $_ec_variables, $_ec_variables_allowed;
+
   $_ec_variables = array();
-  $_ec_variables = array_map('unserialize', db_query("SELECT name, value FROM {variable} where name like '" . implode("' or name like '", $_ec_variables_allowed) . "'")->fetchAllKeyed());
+  foreach ($_ec_variables_allowed as $name) {
+    $_ec_variables[$name] = variable_get($name);
+  }
 }
 
 /**
@@ -925,7 +930,7 @@ function elysia_cron_debug($message, $vars = array(), $type = WATCHDOG_NOTICE) {
   if ($type < WATCHDOG_NOTICE || variable_get('elysia_cron_debug_messages', 0)) {
     watchdog('cron', $message, $vars, $type);
   }
-  if (!empty($_elysia_cron_drush) && $_elysia_cron_drush >= 2 && ($type >= WATCHDOG_NOTICE || !drush_get_option("verbose", FALSE))) {
+  if (!empty($_elysia_cron_drush) && $_elysia_cron_drush >= 2 && ($type >= WATCHDOG_NOTICE || drush_get_option("verbose", FALSE))) {
     if ($type >= WATCHDOG_NOTICE) {
       drush_print(strip_tags(dt($message, $vars)));
     }
@@ -1143,7 +1148,7 @@ function elysia_cron_prepare_run($manual_run, $start = TRUE) {
 
     // Try to allocate enough time to run all the hook_cron implementations.
     if (!ini_get('safe_mode') && _elysia_cron_function_available('set_time_limit')) {
-      set_time_limit(variable_get('elysia_cron_time_limit', 240));
+      @set_time_limit(variable_get('elysia_cron_time_limit', 240));
     }
 
     // Prevent session information from being saved while cron is running.
@@ -1294,6 +1299,21 @@ function elysia_cron_run($manual_run = FALSE, $ignore_disable = FALSE, $ignore_t
   return $execute;
 }
 
+/**
+ * Menu callback: run cron manually.
+ */
+function elysia_cron_run_manually() {
+  // Run cron manually
+  if (elysia_cron_run(TRUE)) {
+    drupal_set_message(t('Cron ran successfully.'));
+  }
+  else {
+    drupal_set_message(t('Cron run failed.'), 'error');
+  }
+
+  drupal_goto('admin/reports/status');
+}
+
 /**
  * Public function to execute all jobs in a channel.
  *
@@ -1303,6 +1323,9 @@ function elysia_cron_run($manual_run = FALSE, $ignore_disable = FALSE, $ignore_t
  *   Run channel (and all it's jobs) job even if not ready.
  * @param bool $ignore_running
  *   Run the channel (and all it's jobs) even if already running.
+ *
+ * @return bool
+ *   Result of execution.
  */
 function elysia_cron_run_channel($channel, $ignore_disable = FALSE, $ignore_time = FALSE, $ignore_running = FALSE) {
   global $_elysia_cron_settings_by_channel;
@@ -1530,7 +1553,8 @@ function elysia_cron_check_run_job($job) {
 /**
  * Find an idle channel (not running, or stuck). If found one, set it as running and returns available jobs.
  *
- * @return if found returns array { 'name' => name of channel, 'jobs' => array of active jobs }, else return FALSE
+ * @return array|bool
+ *   If found returns array { 'name' => name of channel, 'jobs' => array of active jobs }, else return FALSE.
  */
 function elysia_cron_run_available_channel($ignore_disable = FALSE, $ignore_time = FALSE, $ignore_running = FALSE) {
   global $_elysia_cron_settings_by_channel;
@@ -1592,7 +1616,7 @@ function elysia_cron_execute_aborted($channel) {
  * Used for unexpected termination of code.
  */
 function elysia_cron_internal_execute_channel_cleanup() {
-  global $_elysia_cron_settings, $_elysia_cron_current_channel, $_cron_completed, $_cron_completed_time;
+  global $_elysia_cron_current_channel, $_cron_completed;
 
   if ($_cron_completed) {
     return;
@@ -1825,16 +1849,16 @@ function elysia_cron_ping_page() {
   $max_interval = variable_get('elysia_cron_alert_interval', 60) * 60;
 
   if ($diff > $max_interval) {
-    return drupal_not_found();
-  }
-  else {
-    $aoutput = array();
-    $aoutput[] = array(
-      '#type' => 'markup',
-      '#markup' => t('Cron has been called within maximum lapse time.'),
-    );
-    return $aoutput;
+    drupal_not_found();
+    drupal_exit();
   }
+
+  $aoutput = array();
+  $aoutput[] = array(
+    '#type' => 'markup',
+    '#markup' => t('Cron has been called within maximum lapse time.'),
+  );
+  return $aoutput;
 }
 
 /*******************************************************************************
@@ -1842,6 +1866,9 @@ function elysia_cron_ping_page() {
  * ONLY FOR D7
  ******************************************************************************/
 
+/**
+ * Implements hook_cronapi().
+ */
 function elysia_cron_cronapi($op, $job = FALSE) {
   $items = array();
 
@@ -1879,6 +1906,14 @@ function elysia_cron_cronapi($op, $job = FALSE) {
   return $items;
 }
 
+/**
+ * Callback for cronapi.
+ *
+ * @param string $queue_name
+ *   Queue name.
+ * @param array $info
+ *   Info about queue.
+ */
 function elysia_cron_queue_exec($queue_name, $info) {
   $function = $info['worker callback'];
   $end = time() + (isset($info['time']) ? $info['time'] : 15);
@@ -1908,6 +1943,9 @@ function elysia_cron_queue_exec($queue_name, $info) {
  *   Array of links under admin/* that were removed by
  *   admin_menu_adjust_items(). If one of these links is added back,
  *   it should be removed from the array.
+ *
+ * @return array
+ *   Links array.
  */
 function elysia_cron_admin_menu(&$deleted) {
   $links = array();

+ 19 - 21
sites/all/modules/contrib/dev/elysia_cron/elysia_cron_scheduler.inc

@@ -9,8 +9,6 @@
  * Function for cron run schedule.
  */
 function elysia_cron_should_run($conf, $now = -1, $ignore_disable = FALSE, $ignore_time = FALSE) {
-  // What time SHOULD the job be executed last time.
-  $prev_rule_run = 0;
   if (!$ignore_disable && $conf['disabled']) {
     return FALSE;
   }
@@ -53,17 +51,17 @@ function _elysia_cron_next_run($conf) {
 
   $rule = array($rules[1], $rules[2], array($rules[3], $rules[5]), $rules[4]);
   $ruledec = array();
-  $date = __cronDecodeDate($conf['last_run'], 1);
-  $expected_date = __cronDecodeDate(!empty($conf['last_run_expected']) ? $conf['last_run_expected'] : 0);
+  $date = _cronDecodeDate($conf['last_run'], 1);
+  $expected_date = _cronDecodeDate(!empty($conf['last_run_expected']) ? $conf['last_run_expected'] : 0);
 
   for ($i = 0; $i < 4; $i++) {
     if ($i != 2) {
       // Standard scheme for mins, hours, month.
-      $ruledec[$i] = __cronDecodeRule($rule[$i], $ranges[$i][0], $ranges[$i][1]);
+      $ruledec[$i] = _cronDecodeRule($rule[$i], $ranges[$i][0], $ranges[$i][1]);
     }
     else {
       // For mday+week we follow another scheme.
-      $ruledec[$i] = __cronDecodeRuleMday($rule[2], $date[3], $date[4]);
+      $ruledec[$i] = _cronDecodeRuleMday($rule[2], $date[3], $date[4]);
     }
     $r = $ruledec[$i];
     $new = $date[$i];
@@ -74,7 +72,7 @@ function _elysia_cron_next_run($conf) {
       $new = $expected_date[$i] + ceil(($date[$i] - $expected_date[$i]) / $r['d']) * $r['d'];
     }
     elseif ($r['n']) {
-      $new = __cronNextOrEqual($date[$i], $r['n'], $ranges[$i][0], $ranges[$i][1]);
+      $new = _cronNextOrEqual($date[$i], $r['n'], $ranges[$i][0], $ranges[$i][1]);
     }
     if ($new != $date[$i]) {
       $date[$i] = $new;
@@ -85,7 +83,7 @@ function _elysia_cron_next_run($conf) {
       for ($j = 0; $j < $i; $j++) {
         if ($j == 2) {
           // For mday+week decoded rule could be changed (by month+year)
-          $ruledec[$j] = __cronDecodeRuleMday($rule[2], $date[3], $date[4]);
+          $ruledec[$j] = _cronDecodeRuleMday($rule[2], $date[3], $date[4]);
         }
         $date[$j] = $ruledec[$j]['d'] ? ($ranges[$j][0] == 0 ? 0 : $ruledec[$j]['d']) : ($ruledec[$j]['n'] ? reset($ruledec[$j]['n']) : $ranges[$j][0]);
         $expected_date[$j] = 0;
@@ -93,13 +91,13 @@ function _elysia_cron_next_run($conf) {
     }
   }
 
-  return __cronEncodeDate($date);
+  return _cronEncodeDate($date);
 }
 
 /**
  * Helper function for _elysia_cron_next_run().
  */
-function __cronDecodeDate($timestamp, $min_diff = 0) {
+function _cronDecodeDate($timestamp, $min_diff = 0) {
   $time = floor($timestamp / 60);
   $time += $min_diff;
 
@@ -117,14 +115,14 @@ function __cronDecodeDate($timestamp, $min_diff = 0) {
 /**
  * Helper function for _elysia_cron_next_run().
  */
-function __cronEncodeDate($date) {
+function _cronEncodeDate($date) {
   return mktime($date[1], $date[0], 0, $date[3], $date[2], $date[4]);
 }
 
 /**
  * Helper function for _elysia_cron_next_run().
  */
-function __cronNextOrEqual($el, $arr, $range_start, $range_end) {
+function _cronNextOrEqual($el, $arr, $range_start, $range_end) {
   if (empty($arr)) {
     return $el;
   }
@@ -139,7 +137,7 @@ function __cronNextOrEqual($el, $arr, $range_start, $range_end) {
 /**
  * Helper function for _elysia_cron_next_run().
  */
-function __cronDecodeRule($rule, $min, $max) {
+function _cronDecodeRule($rule, $min, $max) {
   if ($rule == '*') {
     return array('n' => array(), 'd' => 0);
   }
@@ -163,11 +161,11 @@ function __cronDecodeRule($rule, $min, $max) {
 /**
  * Helper function for _elysia_cron_next_run().
  */
-function __cronDecodeRuleMday($rule, $month, $year) {
+function _cronDecodeRuleMday($rule, $month, $year) {
   $range_from = 1;
   $range_to = $month != 2 ? (in_array($month, array(4, 6, 9, 11)) ? 30 : 31) : ($year % 4 == 0 ? 29 : 28);
-  $r1 = __cronDecodeRule($rule[0], $range_from, $range_to);
-  $r2 = __cronDecodeRule($rule[1], $range_from, $range_to);
+  $r1 = _cronDecodeRule($rule[0], $range_from, $range_to);
+  $r2 = _cronDecodeRule($rule[1], $range_from, $range_to);
   if ($r2['d']) {
     for ($i = 0; $i < 7; $i++) {
       if ($i % $r2['d'] == 0) {
@@ -178,7 +176,7 @@ function __cronDecodeRuleMday($rule, $month, $year) {
   if ($r2['n']) {
     $r2['n'] = array_unique($r2['n']);
     // Use always "31" and not $range_to, see http://drupal.org/node/1668302.
-    $r1['n'] = array_merge($r1['n'], __cronMonDaysFromWeekDays($year, $month, $r2['n']), __cronMonDaysFromWeekDays($year, $month + 1, $r2['n'], 31));
+    $r1['n'] = array_merge($r1['n'], _cronMonDaysFromWeekDays($year, $month, $r2['n']), _cronMonDaysFromWeekDays($year, $month + 1, $r2['n'], 31));
   }
   return $r1;
 }
@@ -186,7 +184,7 @@ function __cronDecodeRuleMday($rule, $month, $year) {
 /**
  * Helper function for _elysia_cron_next_run().
  */
-function __cronMonDaysFromWeekDays($year, $mon, $weekdays, $offset = 0) {
+function _cronMonDaysFromWeekDays($year, $mon, $weekdays, $offset = 0) {
   if ($mon > 12) {
     $year++;
     $mon = $mon - 12;
@@ -350,15 +348,15 @@ function test_elysia_cron_should_run() {
     'last_run' => mktime(23, 59, 0, 2, 29, 2008),
   ), mktime(23, 59, 0, 2, 6, 2009))));
   dprint("34." . (TRUE == elysia_cron_should_run(array(
-    'rule' => '59 23 *' . '/10 * *',
+    'rule' => '59 23 */10 * *',
     'last_run' => mktime(23, 58, 0, 1, 10, 2008),
   ), mktime(23, 59, 0, 1, 10, 2008))));
   dprint("35." . (FALSE == elysia_cron_should_run(array(
-    'rule' => '59 23 *' . '/10 * *',
+    'rule' => '59 23 */10 * *',
     'last_run' => mktime(23, 59, 0, 1, 10, 2008),
   ), mktime(23, 59, 0, 1, 11, 2008))));
   dprint("36." . (TRUE == elysia_cron_should_run(array(
-    'rule' => '59 23 *' . '/10 * *',
+    'rule' => '59 23 */10 * *',
     'last_run' => mktime(23, 59, 0, 1, 10, 2008),
   ), mktime(23, 59, 0, 1, 20, 2008))));
   dprint("37." . (TRUE == elysia_cron_should_run(array(

+ 16 - 0
sites/all/modules/contrib/dev/elysia_cron/js/elysia_cron.js

@@ -0,0 +1,16 @@
+(function ($) {
+
+  Drupal.behaviors.elysiaCron = {
+    attach: function (context, settings) {
+      $('.ec-select').once().change(function () {
+        if (this.value === 'custom') {
+          var key = $(this).data('key');
+
+          $("#_ec_select_" + key).hide();
+          $("#_ec_custom_" + key).show();
+        }
+      });
+    }
+  }
+
+})(jQuery);

+ 17 - 6
sites/all/modules/contrib/dev/libraries/CHANGELOG.txt

@@ -1,4 +1,21 @@
 
+Libraries 7.x-2.5, 2018-10-5
+-----------------------------
+#2815965 by plach, Manav, tstoeckler, Proteo: Base theme is not loaded when checking for theme library info
+#2999116 by Anghelu, joshbrown81: Finds no library after update
+
+Libraries 7.x-2.4, 2018-09-10
+-----------------------------
+#2779591 by mark_fullmer, cglauren, improved PHP 7.x.x support.
+#2699799 by flaviovs, hanoii: Support reading version from package.json.
+#2816781 by joelstein: Add a 'access library reports' permission.
+#2823735 by amanaplan, tstoeckler: Add admin_menu cache clear integration.
+#2745763 by Albert Volkman, tstoeckler: Allow downloading all libraries at once.
+#2310753 by tstoeckler: Avoid libraries_get_libraries() scanning the root.
+#2341955 by sadashiv, tstoeckler: Clear library cache on library report.
+#819610 by tstoeckler: Show variants and dependencies in the UI.
+#2724925 by ron_s, tstoeckler: Separate installed from uninstalled libraries.
+
 Libraries 7.x-2.3, 2016-05-12
 -----------------------------
 #1884246 by BR0kEN, tstoeckler et al: Allow downloading libraries via Drush.
@@ -94,17 +111,11 @@ by sun: Fixed testbot breaks upon .info file without .module file.
 #719896 by tstoeckler, sun: Added starting point for hook_libraries_info().
 
 
-Libraries 7.x-1.x, xxxx-xx-xx
------------------------------
-
 Libraries 7.x-1.0, 2010-01-27
 -----------------------------
 #743522 by sun: Ported to D7.
 
 
-Libraries 6.x-1.x, xxxx-xx-xx
------------------------------
-
 Libraries 6.x-1.0, 2010-01-27
 -----------------------------
 #1028744 by tstoeckler: Code clean-up.

+ 3 - 0
sites/all/modules/contrib/dev/libraries/css/libraries.admin.css

@@ -0,0 +1,3 @@
+.libraries-table {
+  margin-bottom: 2em;
+}

+ 117 - 24
sites/all/modules/contrib/dev/libraries/libraries.admin.inc

@@ -20,41 +20,112 @@
  *   The form array for the overview form.
  */
 function libraries_admin_overview(array $form, array &$form_state) {
-  $header = array(t('Name'), t('Status'), t('Installed version'), t('Provider'), t('Links'));
-  $rows = array();
-
-  $libraries = libraries_detect();
-  uasort($libraries, 'libraries_admin_sort_title');
-
-  foreach ($libraries as $machine_name => $library) {
+  // Only show variants for installed libraries.
+  $header_installed = array(t('Name'), t('Version'), t('Variants'), t('Dependencies'), t('Provider'), t('Links'));
+  // Only show status for libraries with an error.
+  $header_error = array(t('Name'), t('Status'), t('Version'), t('Dependencies'), t('Provider'), t('Links'));
+  // For unregistered libraries the only information we can show is the path.
+  $header_unregistered = array(t('Name'), t('Path'));
+
+  $rows_installed = array();
+  $rows_error = array();
+  $rows_unregistered = array();
+
+  // Registered libraries: we prefer to use libraries_detect() since it provides
+  // library metadata.
+  $libraries_registered = libraries_detect();
+  uasort($libraries_registered, 'libraries_admin_sort_title');
+
+  // Unregistered libraries: modules can depend on Libraries API without sharing
+  // metadata by using libraries_get_path(). Libraries can also be placed in the
+  // filesystem that are incorrectly installed, a wrong version, or a standalone
+  // not connected to any module. In these cases, libraries_get_libraries()
+  // provides a full library list. Libraries found by libraries_get_libraries(),
+  // but not identified by libraries_detect, are displayed in a separate table.
+  $libraries_unregistered = libraries_get_libraries();
+  natcasesort($libraries_unregistered);
+
+  foreach ($libraries_registered as $machine_name => $library) {
     $actions = array();
+    $row = array();
 
     if ($library['vendor url']) {
-      $actions[] = l('Homepage', $library['vendor url']);
+      $actions[] = l(t('Homepage'), $library['vendor url']);
     }
     if ($library['download url']) {
-      $actions[] = l('Download', $library['download url']);
+      $actions[] = l(t('Download'), $library['download url']);
+    }
+
+    $row['data'][] = l($library['name'], 'admin/reports/libraries/' . $machine_name);
+    // Only show status for libraries with an error. See above.
+    if (!$library['installed']) {
+      $row['data'][] = drupal_ucfirst($library['error']);
+    }
+    $row['data'][] = isset($library['version']) ? $library['version'] : '';
+    if ($library['installed']) {
+      $row['data'][] = implode(', ', array_keys($library['variants']));
+    }
+    $row['data'][] = libraries_admin_get_dependencies($library);
+    $row['data'][] = libraries_admin_get_provider_with_type($library);
+    $row['data'][] = implode(' | ', $actions);
+    $row['class'] = $library['installed'] ? array('ok') : array('warning');
+
+    if ($library['installed']) {
+      $rows_installed[] = $row;
     }
+    else {
+      $rows_error[] = $row;
+    }
+
+    // Filter registered libraries from unregistered libraries.
+    unset($libraries_unregistered[$library['machine name']]);
+  }
+
+  // Build table of registered libraries with installed status.
+  $form['libraries']['installed'] = array(
+    '#theme' => 'libraries_table_with_title',
+    '#title' => t('Installed'),
+    '#header' => $header_installed,
+    '#rows' => $rows_installed,
+    '#description' => t('These libraries are registered and installed correctly.'),
+    '#empty' => t('There are currently no libraries that are registered and installed.'),
+  );
+
+  // Build table of registered libraries with error status.
+  $form['libraries']['error'] = array(
+    '#theme' => 'libraries_table_with_title',
+    '#title' => t('Uninstalled'),
+    '#header' => $header_error,
+    '#rows' => $rows_error,
+    '#description' => t('These libraries are registered but not installed. They may not need to be installed in case a module or theme provides optional integration with a library.'),
+    '#empty' => t('There are currently no libraries that are registered but not installed.'),
+  );
 
-    $rows[] = array(
+  // Build table of unregistered libraries.
+  foreach ($libraries_unregistered as $name => $path) {
+    $rows_unregistered[] = array(
       'data' => array(
-        l($library['name'], 'admin/reports/libraries/' . $machine_name),
-        ($library['installed'] ? t('OK') : drupal_ucfirst($library['error'])),
-        (isset($library['version']) ? $library['version'] : ''),
-        libraries_admin_get_provider_with_type($library),
-        implode(' | ', $actions),
+        $name,
+        $path,
       ),
-      'class' => ($library['installed'] ? array('ok') : array('error')),
     );
   }
-
-  $form['libraries']['list'] = array(
-    '#theme' => 'table',
-    '#header' => $header,
-    '#rows' => $rows,
-    '#empty' => t('There are currently no libraries installed'),
+  $form['libraries']['unregistered'] = array(
+    '#theme' => 'libraries_table_with_title',
+    '#title' => t('Unregistered'),
+    '#header' => $header_unregistered,
+    '#rows' => $rows_unregistered,
+    '#description' => t('These libraries were found in the filesystem but there is no metadata about them.'),
+    // Do not show the table at all, if there are no unregistered libraries.
+    '#access' => (bool) $libraries_unregistered,
   );
 
+  // Clear the cached library information so that the library can be loaded if
+  // it was just downloaded. Because these instructions use libraries_detect()
+  // directly, they will never use the cached information, but this avoids the
+  // overview showing a library as installed but it not being loadable.
+  libraries_cache_clear();
+
   return $form;
 }
 
@@ -99,11 +170,11 @@ function libraries_admin_library_status_form(array $form, array &$form_state, $l
         break;
 
       case 'missing dependency':
-        $form['instructions']['instruction']['#markup'] = t('There a missing dependency in your configuration that prevent this library to work properly.') . '<br>';
+        $form['instructions']['instruction']['#markup'] = t('There is a missing dependency in your configuration that prevents this library from working properly.') . '<br>';
         break;
 
       case 'incompatible dependency':
-        $form['instructions']['instruction']['#markup'] = t('There an incompatible dependency in your configuration that prevent this library to work properly.') . '<br>';
+        $form['instructions']['instruction']['#markup'] = t('There is an incompatible dependency in your configuration that prevents this library from working properly.') . '<br>';
         break;
     }
   }
@@ -483,6 +554,28 @@ function libraries_admin_sort_title(array $a, array $b) {
   return strnatcasecmp($a['name'], $b['name']);
 }
 
+/**
+ * Returns the library's dependencies, if any.
+ *
+ * @param array $library
+ *   A library information array.
+ *
+ * @return string
+ *   The dependencies.
+ */
+function libraries_admin_get_dependencies($library) {
+  $dependencies = array();
+  foreach ($library['dependencies'] as $dependency_name) {
+    if ($dependency = libraries_info($dependency_name)) {
+      $dependencies[] = $dependency['name'];
+    }
+    else {
+      $dependencies[] = $dependency_name;
+    }
+  }
+  return implode(', ', $dependencies);
+}
+
 /**
  * Returns the library's provider.
  *

+ 2 - 0
sites/all/modules/contrib/dev/libraries/libraries.api.php

@@ -47,6 +47,8 @@
  *     Unless 'version' is declared or libraries_get_version() is being used as
  *     a version callback, 'version callback' must be declared. In the latter
  *     case, however, 'version arguments' must be declared in the specified way.
+ *     For libraries that provide a package.json file, use
+ *     'libraries_get_package_json_version' as the version callback.
  *   - version arguments: (optional) A list of arguments to pass to the version
  *     callback. Version arguments can be declared either as an associative
  *     array whose keys are the argument names or as an indexed array without

+ 56 - 24
sites/all/modules/contrib/dev/libraries/libraries.drush.inc

@@ -23,7 +23,9 @@ function libraries_drush_command() {
     'arguments' => array(
       'libraries' => 'A comma delimited list of library machine names.',
     ),
-    'required-arguments' => TRUE,
+    'options' => array(
+      'all' => 'Download all registered libraries.',
+    ),
   );
 
   return $items;
@@ -42,10 +44,7 @@ function libraries_drush_cache_clear(array &$types) {
  * Clears the library cache.
  */
 function libraries_drush_invalidate_cache() {
-  // @see drupal_flush_all_caches()
-  foreach (libraries_flush_caches() as $table) {
-    cache_clear_all('*', $table, TRUE);
-  }
+  libraries_cache_clear();
 }
 
 /**
@@ -109,28 +108,61 @@ function drush_libraries_list() {
 function drush_libraries_download() {
   drush_command_include('pm-download');
 
-  $libraries = libraries_info();
+  $all_libraries = libraries_detect();
 
-  // @todo Consider supporting downloading all downloadable libraries.
-  // @todo Consider offering a selection if no library is specified.
-  foreach (pm_parse_arguments(func_get_args(), FALSE) as $machine_name) {
-    if (!isset($libraries[$machine_name])) {
-      $message = dt("The !library library is not registered with Libraries API.\n", array('!library' => $machine_name));
-      $message .= dt("Provide an info file for it or implement hook_libraries_info().\n");
-      $message .= dt("See hook_libraries_info() for more information.\n");
-      drush_set_error('DRUSH_LIBRARY_UKNOWN', $message);
-      continue;
+  // Prepare a list of names of downloadable libraries.
+  $downloadable_names = array();
+  foreach ($all_libraries as $machine_name => $library) {
+    // Skip libraries that are already installed.
+    // @todo Allow (optionally) re-downloading installing libraries.
+    if (!empty($library['download file url']) && !$library['installed']) {
+      $downloadable_names[] = $machine_name;
     }
-    $library = $libraries[$machine_name];
+  }
 
-    if (empty($library['download file url'])) {
-      $message = dt("The !library library cannot be downloaded.\n", array('!library' => $machine_name));
-      $message .= dt("Libraries need to specify a download file URL to support being downloaded via Drush.\n");
-      $message .= dt("See hook_libraries_info() for more information.\n");
-      drush_set_error('DRUSH_LIBRARY_NOT_DOWNLOADABLE', $message);
-      continue;
+  // Gather a list of libraries to download. If '--all' was specified, that
+  // takes precedence over any other arguments. Otherwise and if no arguments
+  // are specified, we present a choice of all downloadable libraries.
+  if (drush_get_option('all', FALSE) && $downloadable_names) {
+    $machine_names = $downloadable_names;
+  }
+  elseif (pm_parse_arguments(func_get_args(), FALSE)) {
+    $machine_names = array();
+    foreach (pm_parse_arguments(func_get_args(), FALSE) as $machine_name) {
+      // If there was an error with with one of the libraries, continue to try
+      // to install any remaining libraries.
+      if (!isset($all_libraries[$machine_name])) {
+        $message = dt("The !library library is not registered with Libraries API.\n", array('!library' => $machine_name));
+        $message .= dt("Provide an info file for it or implement hook_libraries_info().\n");
+        $message .= dt("See hook_libraries_info() for more information.\n");
+        drush_set_error('DRUSH_LIBRARY_UKNOWN', $message);
+        continue;
+      }
+      if (empty($all_libraries[$machine_name]['download file url'])) {
+        $message = dt("The !library library cannot be downloaded.\n", array('!library' => $machine_name));
+        $message .= dt("Libraries need to specify a download file URL to support being downloaded via Drush.\n");
+        $message .= dt("See hook_libraries_info() for more information.\n");
+        drush_set_error('DRUSH_LIBRARY_NOT_DOWNLOADABLE', $message);
+        continue;
+      }
+      $machine_names[] = $machine_name;
+    }
+  }
+  elseif ($downloadable_names) {
+    $machine_names = drush_choice_multiple(drupal_map_assoc($downloadable_names), FALSE, 'Select which libraries to download.');
+    // If the operation was cancelled by the user, or if no libraries were
+    // selected, bail out without any further error message.
+    if (!$machine_names) {
+      return;
     }
-    $download_url = $library['download file url'];
+  }
+  else {
+    drush_log(dt('There are no registered, uninstalled libraries that can be downloaded.'), 'warning');
+    return;
+  }
+
+  foreach ($machine_names as $machine_name) {
+    $download_url = $all_libraries[$machine_name]['download file url'];
 
     drush_log(dt('Downloading library !name ...', array('!name' => $machine_name)));
 
@@ -205,7 +237,7 @@ function drush_libraries_download() {
         drush_delete_dir($install_location, TRUE);
       }
       else {
-        drush_log(dt("Skip installation of !project to !dest.", array('!project' => $library['machine name'], '!dest' => $install_location)), 'warning');
+        drush_log(dt("Skip installation of !project to !dest.", array('!project' => $machine_name, '!dest' => $install_location)), 'warning');
         continue;
       }
     }

+ 3 - 4
sites/all/modules/contrib/dev/libraries/libraries.info

@@ -8,9 +8,8 @@ files[] = tests/LibrariesLoadWebTest.test
 files[] = tests/LibrariesUnitTest.test
 files[] = tests/LibrariesWebTestBase.test
 
-; Information added by Drupal.org packaging script on 2016-05-12
-version = "7.x-2.3"
+; Information added by Drupal.org packaging script on 2018-10-05
+version = "7.x-2.5"
 core = "7.x"
 project = "libraries"
-datestamp = "1463077450"
-
+datestamp = "1538770685"

+ 10 - 0
sites/all/modules/contrib/dev/libraries/libraries.install

@@ -34,3 +34,13 @@ function libraries_update_7201() {
   // during the 7.x-2.x cycle.
   registry_rebuild();
 }
+
+/**
+ * Grant the "View library reports" permission to roles with the "View site reports" permission.
+ */
+function libraries_update_7202() {
+  $rids = array_keys(user_roles(FALSE, 'access site reports'));
+  foreach ($rids as $rid) {
+    _update_7000_user_role_grant_permissions($rid, array('access library reports'), 'libraries');
+  }
+}

+ 141 - 7
sites/all/modules/contrib/dev/libraries/libraries.module

@@ -25,6 +25,29 @@ function libraries_flush_caches() {
   }
 }
 
+/**
+ * Implements hook_admin_menu_cache_info().
+ */
+function libraries_admin_menu_cache_info() {
+  $caches['libraries'] = array(
+    'title' => t('Libraries'),
+    'callback' => 'libraries_cache_clear',
+  );
+  return $caches;
+}
+
+/**
+ * Clears the cached library information.
+ */
+function libraries_cache_clear() {
+  foreach (libraries_flush_caches() as $bin) {
+    // Using the wildcard argument leads to DrupalDatabaseCache::clear()
+    // truncating the libraries cache table which is more performant that
+    // deleting the rows.
+    cache_clear_all('*', $bin, TRUE);
+  }
+}
+
 /**
  * Gets the path of a library.
  *
@@ -56,6 +79,52 @@ function libraries_get_path($name, $base_path = FALSE) {
   return $path;
 }
 
+/**
+ * Returns all enabled themes.
+ *
+ * Themes are sorted so that base themes always precede their child themes.
+ *
+ * @return array
+ *   An associative array of theme objects keyed by theme name.
+ */
+function libraries_get_enabled_themes() {
+  $themes = array();
+  foreach (list_themes() as $name => $theme) {
+    if ($theme->status) {
+      $themes[$name] = $theme;
+    }
+  }
+
+  return libraries_sort_themes($themes);
+}
+
+/**
+ * Sort a themes array.
+ *
+ * @param array $themes
+ *   Array of themes as objects, keyed by theme name.
+ * @param string $base
+ *   A base theme (internal use only).
+ *
+ * @return array
+ *   A similar array to $themes, but sorted in such a way that subthemes are
+ *   always located after its base theme.
+ */
+function libraries_sort_themes($themes, $base = '') {
+  $output = array();
+  foreach ($themes as $name => $theme) {
+    if (!isset($theme->base_theme) || $theme->base_theme == $base) {
+      $output[$name] = $theme;
+      unset($themes[$name]);
+      $subthemes = libraries_sort_themes($themes, $name);
+      foreach ($subthemes as $sub_name => $subtheme) {
+        $output[$sub_name] = $subtheme;
+      }
+    }
+  }
+  return $output;
+}
+
 /**
  * Returns an array of library directories.
  *
@@ -77,6 +146,13 @@ function libraries_get_libraries() {
   $profile = drupal_get_path('profile', drupal_get_profile());
   $config = conf_path();
 
+  // $config and $profile should never be empty in a proper Drupal setup.
+  // However, we should never search into the root filesystem under any
+  // circumstances, so just bail out in that case.
+  if (!$profile && !$config) {
+    return array();
+  }
+
   // Similar to 'modules' and 'themes' directories in the root directory,
   // certain distributions may want to place libraries into a 'libraries'
   // directory in Drupal's root directory.
@@ -358,10 +434,12 @@ function &libraries_info($name = NULL) {
       }
     }
 
-    // Gather information from hook_libraries_info() in enabled themes.
+    // Gather information from hook_libraries_info() in enabled themes. Themes
+    // are sorted to ensure that a base theme's template.php is included before
+    // its children's ones.
     $themes = array();
-    foreach (list_themes() as $theme_name => $theme_info) {
-      if ($theme_info->status && file_exists(drupal_get_path('theme', $theme_name) . '/template.php')) {
+    foreach (libraries_get_enabled_themes() as $theme_name => $theme_info) {
+      if (file_exists(drupal_get_path('theme', $theme_name) . '/template.php')) {
         // Collect a list of viable themes for re-use when calling the alter
         // hook.
         $themes[] = $theme_name;
@@ -546,7 +624,7 @@ function libraries_detect($name = NULL) {
       $library['version'] = call_user_func_array($library['version callback'], array_merge(array($library), $library['version arguments']));
     }
     else {
-      $library['version'] = call_user_func($library['version callback'], $library, $library['version arguments']);
+      $library['version'] = call_user_func_array($library['version callback'], array(&$library, $library['version arguments']));
     }
     if (empty($library['version'])) {
       $library['error'] = 'not detected';
@@ -887,16 +965,56 @@ function libraries_get_version($library, $options) {
   fclose($file);
 }
 
+/**
+ * Gets the version information from a library's package.json file.
+ *
+ * @param $library
+ *   An associative array containing all information about the library.
+ * @param $options
+ *   This callback expects no option.
+ * @return
+ *   A string containing the version of the library.
+ *
+ * @see libraries_get_path()
+ */
+function libraries_get_package_json_version($library, $options) {
+  $file = DRUPAL_ROOT . '/' . $library['library path'] . '/package.json';
+  if (!file_exists($file)) {
+    return;
+  }
+
+  $content = file_get_contents($file);
+  if (!$content) {
+    return;
+  }
+
+  $data = drupal_json_decode($content);
+  if (isset($data['version'])) {
+    return $data['version'];
+  }
+}
+
 /**
  * Implements hook_help().
  */
 function libraries_help($path, $arg) {
   switch ($path) {
     case 'admin/reports/libraries':
-      return t('Click on a library for a status report or detailed installation instructions in case the library is not installed correctly.');
+      return t('Click on a library for a status report or detailed installation instructions.');
   }
 }
 
+/**
+ * Implements hook_permission().
+ */
+function libraries_permission() {
+  return array(
+    'access library reports' => array(
+      'title' => t('View library reports'),
+    ),
+  );
+}
+
 /**
  * Implements hook_menu().
  */
@@ -907,7 +1025,7 @@ function libraries_menu() {
     'description' => 'An overview of libraries installed on this site.',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('libraries_admin_overview'),
-    'access arguments' => array('access site reports'),
+    'access arguments' => array('access library reports'),
     'file' => 'libraries.admin.inc'
   );
   $items['admin/reports/libraries/%libraries_ui'] = array(
@@ -915,7 +1033,7 @@ function libraries_menu() {
     'description' => 'Status overview for a single library',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('libraries_admin_library_status_form', 3),
-    'access arguments' => array('access site reports'),
+    'access arguments' => array('access library reports'),
     'file' => 'libraries.admin.inc'
   );
   return $items;
@@ -944,3 +1062,19 @@ function libraries_menu() {
 function libraries_ui_load($name) {
   return libraries_detect($name);
 }
+
+/**
+ * Implements hook_theme().
+ */
+function libraries_theme($existing, $type, $theme, $path) {
+  // Because we extend the 'table' theme function, fetch the respective
+  // variables dynamically.
+  $common_theme = drupal_common_theme();
+  $variables = $common_theme['table']['variables'] + array('title' => '', 'description' => '');
+  return array(
+    'libraries_table_with_title' => array(
+      'variables' => $variables,
+      'file' => 'libraries.theme.inc',
+    ),
+  );
+}

+ 36 - 0
sites/all/modules/contrib/dev/libraries/libraries.theme.inc

@@ -0,0 +1,36 @@
+<?php
+
+/**
+ * @file
+ * Provides theme and preprocess functions for Libraries API.
+ */
+
+/**
+ * Prepare variables for theming a table with a title.
+ * 
+ * @param array $variables
+ *   An array of theme variables, passed by reference.
+ */
+function template_preprocess_libraries_table_with_title(&$variables) {
+  drupal_add_css(drupal_get_path('module', 'libraries') . '/css/libraries.admin.css');
+
+  $variables['attributes'] += array('class' => array());
+  $variables['attributes']['class'][] = 'libraries-table';
+}
+
+/**
+ * Returns HTML for a table with a title.
+ * 
+ * @param array $variables
+ *   An array theme variables.
+ * 
+ * @return string
+ *   The HTML output for this table with a title.
+ */
+function theme_libraries_table_with_title(array $variables) {
+  $output = '';
+  $output .= '<h2>' . $variables['title'] . '</h2>';
+  $output .= '<div class="description">' . $variables['description'] . '</div>';
+  $output .= theme_table($variables);
+  return $output;
+}

+ 19 - 8
sites/all/modules/contrib/dev/libraries/tests/LibrariesAdminWebTest.test

@@ -40,8 +40,20 @@ class LibrariesAdminWebTest extends LibrariesWebTestBase {
    * Tests the libraries report at /admin/reports/libraries.
    */
   public function testLibrariesReportOverview() {
-    $this->getWithPermissions(array('access site reports'), 'admin/reports/libraries');
-    $this->assertRaw('Libraries');
+    $this->getWithPermissions(array('access library reports'), 'admin/reports/libraries');
+    // Assert the page title and table titles show up.
+    $this->assertText('Libraries');
+    $this->assertRaw('<h2>Installed</h2>');
+    $this->assertRaw('<h2>Uninstalled</h2>');
+
+    // Make sure the table headings show up.
+    $this->assertText('Name');
+    $this->assertText('Status');
+    $this->assertText('Version');
+    $this->assertText('Variants');
+    $this->assertText('Dependencies');
+    $this->assertText('Provider');
+    $this->assertText('Links');
 
     // Make sure that all the libraries are listed.
     $libraries = libraries_info();
@@ -51,8 +63,7 @@ class LibrariesAdminWebTest extends LibrariesWebTestBase {
       $this->assertLinkByHref('admin/reports/libraries/' . $library['machine name']);
     }
 
-    // Make sure that all possible statuses are displayed.
-    $this->assertText('OK');
+    // Make sure that all possible error statuses are displayed.
     $this->assertText('Not found');
     $this->assertText('Not detected');
     $this->assertText('Not supported');
@@ -73,7 +84,7 @@ class LibrariesAdminWebTest extends LibrariesWebTestBase {
    * Tests the libraries report for an installed library.
    */
   public function testLibrariesReportInstalled() {
-    $this->getWithPermissions(array('access site reports'), 'admin/reports/libraries/example_files');
+    $this->getWithPermissions(array('access library reports'), 'admin/reports/libraries/example_files');
     $this->assertRaw('Status report for library <em class="placeholder">Example files</em>');
     $this->assertRaw('The <em class="placeholder">Example files</em> library is installed correctly.');
     // Check that the information in the status report is displayed.
@@ -88,7 +99,7 @@ class LibrariesAdminWebTest extends LibrariesWebTestBase {
    * Tests the libraries report for a missing library.
    */
   public function testLibrariesReportMissing() {
-    $this->getWithPermissions(array('access site reports'), 'admin/reports/libraries/example_missing');
+    $this->getWithPermissions(array('access library reports'), 'admin/reports/libraries/example_missing');
     $this->assertRaw('Status report for library <em class="placeholder">Example missing</em>');
     $this->assertRaw('The <em class="placeholder">Example missing</em> library could not be found.');
     // Check that the download link is being displayed.
@@ -100,7 +111,7 @@ class LibrariesAdminWebTest extends LibrariesWebTestBase {
    * Tests the libraries report for a missing library.
    */
   public function testLibrariesReportNotDetected() {
-    $this->getWithPermissions(array('access site reports'), 'admin/reports/libraries/example_undetected_version');
+    $this->getWithPermissions(array('access library reports'), 'admin/reports/libraries/example_undetected_version');
     $this->assertRaw('Status report for library <em class="placeholder">Example undetected version</em>');
     $this->assertRaw('The version of the <em class="placeholder">Example undetected version</em> library could not be detected.');
   }
@@ -109,7 +120,7 @@ class LibrariesAdminWebTest extends LibrariesWebTestBase {
    * Tests the libraries report for a missing library.
    */
   public function testLibrariesReportNotSupported() {
-    $this->getWithPermissions(array('access site reports'), 'admin/reports/libraries/example_unsupported_version');
+    $this->getWithPermissions(array('access library reports'), 'admin/reports/libraries/example_unsupported_version');
     $this->assertRaw('Status report for library <em class="placeholder">Example unsupported version</em>');
     $this->assertRaw('The installed version <em class="placeholder">1</em> of the <em class="placeholder">Example unsupported version</em> library is not supported.');
     // Check that the download link is being displayed.

+ 3 - 4
sites/all/modules/contrib/dev/libraries/tests/libraries/example_info_file.libraries.info

@@ -2,9 +2,8 @@
 name = Example info file
 
 
-; Information added by Drupal.org packaging script on 2016-05-12
-version = "7.x-2.3"
+; Information added by Drupal.org packaging script on 2018-10-05
+version = "7.x-2.5"
 core = "7.x"
 project = "libraries"
-datestamp = "1463077450"
-
+datestamp = "1538770685"

+ 3 - 4
sites/all/modules/contrib/dev/libraries/tests/modules/libraries_test_module/libraries_test_module.info

@@ -5,9 +5,8 @@ package = Testing
 dependencies[] = libraries
 hidden = TRUE
 
-; Information added by Drupal.org packaging script on 2016-05-12
-version = "7.x-2.3"
+; Information added by Drupal.org packaging script on 2018-10-05
+version = "7.x-2.5"
 core = "7.x"
 project = "libraries"
-datestamp = "1463077450"
-
+datestamp = "1538770685"

+ 3 - 4
sites/all/modules/contrib/dev/libraries/tests/themes/libraries_test_theme/libraries_test_theme.info

@@ -3,9 +3,8 @@ description = Tests that themes can provide and alter library information.
 core = 7.x
 hidden = TRUE
 
-; Information added by Drupal.org packaging script on 2016-05-12
-version = "7.x-2.3"
+; Information added by Drupal.org packaging script on 2018-10-05
+version = "7.x-2.5"
 core = "7.x"
 project = "libraries"
-datestamp = "1463077450"
-
+datestamp = "1538770685"

+ 4 - 1
sites/all/modules/contrib/files/elfinder/CHANGELOG.txt

@@ -1,6 +1,6 @@
 2.x-dev
 -------
-  - Now requires elFinder 2.0.9+
+  - Now requires elFinder 2.0.9+ or 2.1.38+
   - Added multiple root directories support
   - Added Drupal file_managed table synchronization
   - Added per-role configurable profiles support
@@ -8,4 +8,7 @@
   - Added CKEditor and FCKeditor Upload tab support
   - New library search algoritm with install profiles and multiple sites support
   - Search support
+  - Inline preview support for PSD, md, html, office docs (by Google/Microsoft online tools), CAD (by sharecad.org online tools),  etc (disabled by default, be careful)
+  - Auto fit window
+  - File owner available in list view
 

+ 8 - 333
sites/all/modules/contrib/files/elfinder/LICENSE.txt

@@ -1,339 +1,14 @@
-                    GNU GENERAL PUBLIC LICENSE
-                       Version 2, June 1991
+elFinder Integration
 
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
+Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
 
-                            Preamble
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Lesser General Public License instead.)  You can apply it to
-your programs, too.
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
 
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
 
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
+3. Neither the name of the Alexey Sukhotin nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
 
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-                    GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-                            NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-                     END OF TERMS AND CONDITIONS
-
-            How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License along
-    with this program; if not, write to the Free Software Foundation, Inc.,
-    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) year name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  <signature of Ty Coon>, 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Lesser General
-Public License instead of this License.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL "ALEXEY SUKHOTIN" OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 79 - 83
sites/all/modules/contrib/files/elfinder/README.txt

@@ -1,83 +1,79 @@
-elFinder file manager integration module for Drupal
-===================================================
-
-System Requirements:
-
- - Drupal 7.x
- - elFinder 2.0.9+ 
-
-   Note: elFinder 2.0rc1 no more supported - use 2.x dev build from 
-         http://sourceforge.net/projects/drupal-elfinder/files/Library/ 
-         or use production version if it is available
-
-Optional:
- 
- - Wysiwyg module
- - Wysiwyg editor:
- 
-    - CKEditor
-    - FCKeditor
-    - TinyMCE 3
-    - BUEdtor
-    - jWYSIWYG (jWYSIWYG 0.93+, jquery 1.3+, jquery ui 1.7+)
-    - YUI Editor
-    - WYMeditor
-
-  
-Installation:
-
-  1. Unpack archive contents into modules/elfinder
-  2. Get latest elFinder at http://sourceforge.net/projects/drupal-elfinder/files/Library/ and it's contents to sites/all/libraries/elfinder
-  3. REMOVE following files from library directory if it exists to avoid security hole:
-
-     sites/all/libraries/elfinder/elfinder.php.html
-     sites/all/libraries/elfinder/connectors/php/connector.php
-     sites/all/libraries/elfinder/php/connector.php
-
-  4. Enable elFinder module in Modules > List menu
-  5. Add 'use file manager' permission to users who will be able to use elFinder at Modules > elFinder > Permissions menu
-  6. Enable elFinder checkbox in your editor Wysiwyg profile at Configuration > Wysiwyg profiles > <Editor Profile> Buttons and Plugins
-  
-Usage:
-
- 1. Administration backend
-  
-  a. Open /elfinder url (or ?q=elfinder if seo-capable urls disabled)
-  b. Go to Administer page. Click 'Files' under Content section.
-
- 2. Inside CKEditor (FCKeditor)
-  2.1. Open Image Properties dialog in editor
-  2.2. Click Browse Server button near image url
- 
- 3. Inside TinyMCE
-  3.1. Open Insert/edit image dialog
-  3.2. Click Browse button near image url
-  
- 4. Inside BUEditor
-  4.1. Click 'Insert/edit image'
-  4.2. Click 'Browse'
-  4.3. Select file
-  4.4. Enter alt text then click OK
- 
- 5. Inside jWYSIWYG
-  5.1. Make sure that you have jWYSYWIG 0.93+ (http://github.com/akzhan/jwysiwyg/), jQuery 1.3+ and jQuery UI 1.7+ installed
-  5.2. Click 'Insert image' button
-  5.3. Click 'Browse Server' button near image url
- 
- 6. Inside YUI Editor
-  6.1. Click 'Insert Image' button
-  6.2. Click 'Browse Server' button near image url
-
- 7. Inside WYMeditor
-  7.1. Click 'Image' button
-  7.2. Click 'Browse Server' button near image url
- 
-
-  
-Known Issues:
-
- - Not all editors supported
- - Conflicting with some devel module features
-
-
-
+elFinder file manager integration module for Drupal
+===================================================
+
+System Requirements:
+
+ - Drupal 7.x
+ - elFinder 2.0.9+ or 2.1.38+
+
+   Note: elFinder 2.0rc1 no more supported - use 2.0.9+ or 2.1.38+ dev build from 
+         http://elfinder.org 
+         or use production version if it is available
+
+Optional:
+ 
+ - Wysiwyg module
+ - Wysiwyg editor:
+ 
+    - CKEditor
+    - FCKeditor
+    - TinyMCE 3
+    - BUEdtor
+    - jWYSIWYG (jWYSIWYG 0.93+, jquery 1.3+, jquery ui 1.7+)
+    - YUI Editor
+    - WYMeditor
+
+  
+Installation:
+
+  1. Unpack archive contents into modules/elfinder
+  2. Get latest elFinder at http://elfinder.org and it's contents to sites/all/libraries/elfinder
+  3. REMOVE following files from library directory if it exists to avoid security hole:
+
+     sites/all/libraries/elfinder/connectors/php/connector.php
+     sites/all/libraries/elfinder/php/connector.php
+
+  4. Enable elFinder module in Modules > List menu
+  5. Add 'use file manager' permission to users who will be able to use elFinder at Modules > elFinder > Permissions menu
+  6. Enable elFinder checkbox in your editor Wysiwyg profile at Configuration > Wysiwyg profiles > <Editor Profile> Buttons and Plugins
+  
+Usage:
+
+ 1. Administration backend
+  a. Open /elfinder url (or ?q=elfinder if seo-capable urls disabled)
+  b. Go to Administer page. Click 'Files' under Content section.
+
+ 2. Inside CKEditor (FCKeditor)
+  2.1. Open Image Properties dialog in editor
+  2.2. Click Browse Server button near image url
+
+ 3. Inside TinyMCE
+  3.1. Open Insert/edit image dialog
+  3.2. Click Browse button near image url
+
+ 4. Inside BUEditor
+  4.1. Click 'Insert/edit image'
+  4.2. Click 'Browse'
+  4.3. Select file
+  4.4. Enter alt text then click OK
+ 
+ 5. Inside jWYSIWYG
+  5.1. Make sure that you have jWYSYWIG 0.93+ (http://github.com/akzhan/jwysiwyg/), jQuery 1.3+ and jQuery UI 1.7+ installed
+  5.2. Click 'Insert image' button
+  5.3. Click 'Browse Server' button near image url
+
+ 6. Inside YUI Editor
+  6.1. Click 'Insert Image' button
+  6.2. Click 'Browse Server' button near image url
+
+ 7. Inside WYMeditor
+  7.1. Click 'Image' button
+  7.2. Click 'Browse Server' button near image url
+
+
+Known Issues:
+
+ - Not all editors supported
+ - Conflicting with some devel module features
+
+

+ 10 - 4
sites/all/modules/contrib/files/elfinder/css/elfinder.admin.css

@@ -1,5 +1,11 @@
-.elfinder-field-wrapper-volume-path {
- float:left;
- width:300px;
- bborder:#f00 1px solid;
+/*
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
+ */
+
+.elfinder-field-wrapper-volume-path {
+    float: left;
+    width: 300px;
+    bborder: #f00 1px solid;
 }

+ 48 - 27
sites/all/modules/contrib/files/elfinder/css/elfinder.common.css

@@ -1,27 +1,48 @@
-
-.el-finder-nav ul li {
-	background:none;
-	padding:0;
-	margin:0;
-}
-.elfinder-cwd, .elfinder-navbar {
- font-size:13px!important;
-}
-
-.elfinder-cwd-view-icons .elfinder-cwd-file {
-    height: 150px;
-    width: 100px;
-}
-
-.elfinder-cwd-view-icons .elfinder-cwd-filename {
-  white-space: normal;
-  overflow:visible;
-}
-
-body.elfinder #finder {
-  border: none;
-}
-
-body.elfinder .elfinder-toolbar, body.elfinder .elfinder-statusbar {
-  border-radius: 0 !important;
-}
+/*
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
+ */
+
+#finder .elfinder-statusbar {
+    padding: .2em 1em;
+}
+
+#finder fieldset.elfinder-resize-preset-container {
+    padding: .5em;
+}
+
+#finder .ui-dialog input[type='text'] {
+    padding: 1px 2px;
+}
+
+#finder .ui-dialog tr td {
+    border-right: none;
+    vertical-align: top;
+}
+
+#finder .ui-dialog textarea#elfinder-fm-file-desc {
+    background: #FFF;
+}
+
+#finder .elfinder-cwd-view-icons .elfinder-cwd-icon.elfinder-cwd-bgurl:before {
+    font-family: inherit;
+}
+
+/* elfinder popup window */
+body.elfinder #finder {
+    border: none;
+}
+
+body.elfinder .elfinder-toolbar,
+body.elfinder .elfinder-statusbar {
+    border-radius: 0 !important;
+}
+
+#elfinder-messages {
+    display: none;
+}
+
+#elfinder-messages.legacy {
+    display: block;
+}

+ 10 - 5
sites/all/modules/contrib/files/elfinder/css/elfinder.css

@@ -1,6 +1,11 @@
-
-.el-finder-nav ul li {
-	background:none;
-	padding:0;
-	margin:0;
+/*
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
+ */
+
+.el-finder-nav ul li {
+    background: none;
+    padding: 0;
+    margin: 0;
 }

+ 0 - 9
sites/all/modules/contrib/files/elfinder/css/elfinder.d7.css

@@ -1,9 +0,0 @@
-
-.el-finder-nav ul {
-  list-style-type:none!important;
-}
-
-.el-finder-cwd label {
-  font-weight:normal!important;
-  overflow:visible!important;
-}

+ 5 - 0
sites/all/modules/contrib/files/elfinder/css/ui-themes/smoothness/jquery-ui.custom.css

@@ -1,3 +1,8 @@
+/*
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
+ */
 @import url('jquery-ui.min.css');
 @import url('jquery-ui.structure.min.css');
 @import url('jquery-ui.theme.min.css');

File diff suppressed because it is too large
+ 2 - 2
sites/all/modules/contrib/files/elfinder/css/ui-themes/smoothness/jquery-ui.min.css


File diff suppressed because it is too large
+ 0 - 0
sites/all/modules/contrib/files/elfinder/editors/bueditor/bueditor.callback.js


+ 19 - 13
sites/all/modules/contrib/files/elfinder/editors/bueditor/bueditor.inc

@@ -1,23 +1,29 @@
 <?php
+/**
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
+ */
+
 /**
  * @file
  * BUEditor integration plugin
  */
 
 /**
-  * Pseudo-hook for elfinder hook_wysiwyg_plugin implementation
-  */
+ * Pseudo-hook for elfinder hook_wysiwyg_plugin implementation
+ */
 function elfinder_bueditor_elfinder_editor_plugin($options) {
-      drupal_add_js(array('elfinder' => array('moduleUrl' => url('elfinder'))), 'setting');
-      drupal_add_js(array('elfinder' => array('moduleUrl' => url('elfinder'))), 'setting');
-      drupal_add_js($options['plugin_url_base'] . '/bueditor.js');
+  drupal_add_js(array('elfinder' => array('moduleUrl' => url('elfinder'))), 'setting');
+  drupal_add_js(array('elfinder' => array('moduleUrl' => url('elfinder'))), 'setting');
+  drupal_add_js($options['plugin_url_base'] . '/bueditor.js');
 
-      return array(
-        'elfinder' => array(
-          'extensions' => array('elfinder' => t('elFinder')),
-          'url' => $options['homepage_url'],
-          'options' => array(),
-          'load' => FALSE,
-        ),
-      );
+  return array(
+    'elfinder' => array(
+      'extensions' => array('elfinder' => t('elFinder')),
+      'url' => $options['homepage_url'],
+      'options' => array(),
+      'load' => FALSE,
+    ),
+  );
 }

+ 9 - 3
sites/all/modules/contrib/files/elfinder/editors/bueditor/bueditor.js

@@ -1,12 +1,18 @@
+/*
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
+ */
+
 // $Id: elfinder.bueditor.js,v 1.1 2010/10/06 09:44:51 ph0enix Exp $
 
 Drupal.elfinder.editor.bueditor = {
-  fn : { 
+  fn: {
     attach: Drupal.wysiwyg.editor.attach.bueditor
   }
 }
 
 Drupal.wysiwyg.editor.attach.bueditor = function(context, params, settings) {
-  Drupal.settings.BUE.imceURL = Drupal.settings.elfinder.moduleUrl;  
-  Drupal.elfinder.editor.bueditor.fn.attach.apply(this, arguments); 
+  Drupal.settings.BUE.imceURL = Drupal.settings.elfinder.moduleUrl;
+  Drupal.elfinder.editor.bueditor.fn.attach.apply(this, arguments);
 }

+ 18 - 4
sites/all/modules/contrib/files/elfinder/editors/ckeditor/ckeditor.callback.js

@@ -1,4 +1,8 @@
-
+/*
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2019, Alexey Sukhotin. All rights reserved.
+ */
 
 function elfinder_ckeditor_callback(arg1) {
 
@@ -7,13 +11,23 @@ function elfinder_ckeditor_callback(arg1) {
   if (typeof arg1 == 'object') {
     url = arg1.url;
   }
+
   funcNum = window.location.search.replace(/^.*CKEditorFuncNum=(\d+).*$/, "$1");
+
   window.opener.CKEDITOR.tools.callFunction(funcNum, url, function() {
     // adapted from http://docs.ckeditor.com/#!/guide/dev_file_browser_api
+
     var dialog = this.getDialog();
-    if (dialog.getName() == 'link' ) {
+
+    if (dialog.getName() == 'link') {
+
       var element = dialog.getContentElement('info', 'linkDisplayText');
-      var display_text = element.getValue();
+      var display_text = null;
+
+      if (element) {
+        display_text = element.getValue();
+      }
+
       // If display text is blank, insert the filename.
       if (element && !display_text) {
         element.setValue(arg1.name);
@@ -24,7 +38,7 @@ function elfinder_ckeditor_callback(arg1) {
   // Avoid beforeunload event when selecting an image.
   // See https://github.com/Studio-42/elFinder/issues/1340
   // Maybe remove this when elfinder js library gets updated.
-  $(window).off('beforeunload');
+  jQuery(window).off('beforeunload');
 
   window.close();
 }

+ 8 - 2
sites/all/modules/contrib/files/elfinder/editors/ckeditor/ckeditor.inc

@@ -1,4 +1,9 @@
 <?php
+/**
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
+ */
 
 /**
  * @file
@@ -6,8 +11,8 @@
  */
 
 /**
-  * Pseudo-hook for elfinder hook_wysiwyg_plugin implementation
-  */
+ * Pseudo-hook for elfinder hook_wysiwyg_plugin implementation
+ */
 function elfinder_ckeditor_elfinder_editor_plugin($options) {
   return array(
     'elfinder' => array(
@@ -18,6 +23,7 @@ function elfinder_ckeditor_elfinder_editor_plugin($options) {
         'filebrowserUploadUrl' => url('elfinder/upload/ckeditor'),
         'filebrowserImageUploadUrl' => url('elfinder/upload/ckeditor'),
         'filebrowserFlashUploadUrl' => url('elfinder/upload/ckeditor'),
+        //'filebrowserBrowseUrl' => 'javascript:alert(12345);return false;//',
       ),
       'load' => FALSE,
     ),

+ 23 - 17
sites/all/modules/contrib/files/elfinder/editors/ckeditor/ckeditor.upload.inc

@@ -1,36 +1,42 @@
 <?php
+/**
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
+ */
+
 /**
  * @file
- *  
+ *
  * CKeditor Upload tab support
  */
 
 function elfinder_editor_upload_ckeditor() {
-    
+
   $p = elfinder_get_user_profile();
 
   $dest = file_build_uri('');
 
-	if (!strpos($p->settings['ckeditor_upload_directory'], '://')) {
-		$dest .= $p->settings['ckeditor_upload_directory'];
-	} else {
-	  $dest = $p->settings['ckeditor_upload_directory'];
-	}
-	
-	$dest = elfinder_parse_path_tokens($dest);
-	
-	$destabs = drupal_realpath($dest);	
-	
-	if (!file_prepare_directory($destabs, FILE_CREATE_DIRECTORY)) {
+  if (!strpos($p->settings['ckeditor_upload_directory'], '://')) {
+    $dest .= $p->settings['ckeditor_upload_directory'];
+  } else {
+    $dest = $p->settings['ckeditor_upload_directory'];
+  }
+
+  $dest = elfinder_parse_path_tokens($dest);
+
+  $destabs = drupal_realpath($dest);
+
+  if (!file_prepare_directory($destabs, FILE_CREATE_DIRECTORY)) {
     drupal_set_message(t('Error. Cannot initialize directory %dir', array('%dir' => $destabs)), 'error');
   }
-  
+
   $tmpf = $_FILES;
- 
+
   foreach (array_keys($_FILES['upload']) as $key) {
     $tmpf['files'][$key]['upload'] = $_FILES['upload'][$key];
   }
- 
+
   $_FILES = $tmpf;
 
   $file = file_save_upload('upload', array(), $dest);
@@ -38,7 +44,7 @@ function elfinder_editor_upload_ckeditor() {
   file_save($file);
 
   header('Content-Type: text/html');
-  
+
   print '<script type="text/javascript">';
 
   if ($file) {

+ 7 - 2
sites/all/modules/contrib/files/elfinder/editors/drupalnodeattach/drupalnodeattach.callback.js

@@ -1,5 +1,10 @@
-// $Id$
+/*
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
+ */
 
 function elfinder_drupalnodeattach_callback(url) {
-          parent.jQuery('input#edit-attach-url').val(url);
+  parent.jQuery('input#edit-attach-url').val(url);
+  alert(url);
 }

+ 10 - 1
sites/all/modules/contrib/files/elfinder/editors/fckeditor/fckeditor.callback.js

@@ -1 +1,10 @@
-// $Id$

function elfinder_fckeditor_callback(url) {
          window.opener.SetUrl(url) ;
          window.close();
}
+/*
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
+ */
+
+function elfinder_fckeditor_callback(url) {
+  window.opener.SetUrl(url);
+  window.close();
+}

+ 30 - 24
sites/all/modules/contrib/files/elfinder/editors/fckeditor/fckeditor.inc

@@ -1,34 +1,40 @@
 <?php
+/**
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
+ */
+
 /**
  * @file
  * FCKeditor integration plugin
  */
 
 /**
-  * Pseudo-hook for elfinder hook_wysiwyg_plugin implementation
-  */
+ * Pseudo-hook for elfinder hook_wysiwyg_plugin implementation
+ */
 function elfinder_fckeditor_elfinder_editor_plugin($options) {
-      return array(
-        'elfinder' => array(
-          'extensions' => array('elfinder' => t('elFinder')),
-          'url' => $options['homepage_url'],
-          'options' => array(
-            'LinkBrowser' => TRUE,
-            'LinkBrowserURL' => $options['elfinder_url'],
-            'ImageBrowser' => TRUE,
-            'ImageBrowserURL' => $options['elfinder_url'],
-            'FlashBrowser' => TRUE,
-            'FlashBrowserURL' => $options['elfinder_url'],
-            'ImageUpload' => TRUE,
-            'ImageUploadURL' => url('elfinder/upload/fckeditor'),
-            'FlashUpload' => TRUE,
-          //  'FlashUploadURL' => $options['elfinder_connector_url'],
-            'LinkUpload' => TRUE,
-          //  'LinkUploadURL' => $options['elfinder_connector_url'],
-            
+  return array(
+    'elfinder' => array(
+      'extensions' => array('elfinder' => t('elFinder')),
+      'url' => $options['homepage_url'],
+      'options' => array(
+        'LinkBrowser' => TRUE,
+        'LinkBrowserURL' => $options['elfinder_url'],
+        'ImageBrowser' => TRUE,
+        'ImageBrowserURL' => $options['elfinder_url'],
+        'FlashBrowser' => TRUE,
+        'FlashBrowserURL' => $options['elfinder_url'],
+        'ImageUpload' => TRUE,
+        'ImageUploadURL' => url('elfinder/upload/fckeditor'),
+        'FlashUpload' => TRUE,
+        //  'FlashUploadURL' => $options['elfinder_connector_url'],
+        'LinkUpload' => TRUE,
+        //  'LinkUploadURL' => $options['elfinder_connector_url'],
+
 
-          ),
-          'load' => FALSE,
-        ),
-      );
+      ),
+      'load' => FALSE,
+    ),
+  );
 }

+ 24 - 18
sites/all/modules/contrib/files/elfinder/editors/fckeditor/fckeditor.upload.inc

@@ -1,53 +1,59 @@
 <?php
+/**
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
+ */
+
 /**
  * @file
- *  
+ *
  * FCKeditor Upload tab support
  */
 
 function elfinder_editor_upload_fckeditor() {
-    
+
   $p = elfinder_get_user_profile();
 
   $dest = file_build_uri('');
 
-	if (!strpos($p->settings['ckeditor_upload_directory'], '://')) {
-		$dest .= $p->settings['ckeditor_upload_directory'];
-	} else {
-	  $dest = $p->settings['ckeditor_upload_directory'];
-	}
-	
-	$dest = elfinder_parse_path_tokens($dest);
-	
-	$destabs = drupal_realpath($dest);	
-	
-	if (!file_prepare_directory($destabs, FILE_CREATE_DIRECTORY)) {
+  if (!strpos($p->settings['ckeditor_upload_directory'], '://')) {
+    $dest .= $p->settings['ckeditor_upload_directory'];
+  } else {
+    $dest = $p->settings['ckeditor_upload_directory'];
+  }
+
+  $dest = elfinder_parse_path_tokens($dest);
+
+  $destabs = drupal_realpath($dest);
+
+  if (!file_prepare_directory($destabs, FILE_CREATE_DIRECTORY)) {
     drupal_set_message(t('Error. Cannot initialize directory %dir', array('%dir' => $destabs)), 'error');
   }
 
   $tmpf = $_FILES;
- 
+
   foreach (array_keys($_FILES['NewFile']) as $key) {
     $tmpf['files'][$key]['NewFile'] = $_FILES['NewFile'][$key];
   }
- 
+
   $_FILES = $tmpf;
 
   $file = file_save_upload('NewFile', array(), $dest);
   $file->status = FILE_STATUS_PERMANENT;
   file_save($file);
-  
+
 
   header('Content-Type: text/html');
 
   print '<script type="text/javascript">';
-  
+
   if ($file) {
     print "window.parent.OnUploadCompleted(0, '" . file_create_url($file->uri) . "', '" . $file->filename . "', '') ;";
   } else {
     print 'window.parent.OnUploadCompleted(1,"","", "' . t('Error uploading file!') . '") ;';
   }
-  
+
   print '</script>';
 
   exit();

+ 10 - 1
sites/all/modules/contrib/files/elfinder/editors/jwysiwyg/jwysiwyg.callback.js

@@ -1 +1,10 @@
-// $Id$

function elfinder_jwysiwyg_callback(url) {
          window.opener.jQuery('.ui-dialog input[type=text][name=url]').val(url);
          window.close();
}
+/*
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
+ */
+
+function elfinder_jwysiwyg_callback(url) {
+  window.opener.jQuery('.ui-dialog input[type=text][name=url]').val(url);
+  window.close();
+}

+ 30 - 20
sites/all/modules/contrib/files/elfinder/editors/jwysiwyg/jwysiwyg.inc

@@ -1,29 +1,39 @@
 <?php
+/**
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
+ */
+
+// $Id$
+
 /**
  * @file
  * jWYSIWYG integration plugin
  */
 
 /**
-  * Pseudo-hook for elfinder hook_wysiwyg_plugin implementation
-  */
+ * Pseudo-hook for elfinder hook_wysiwyg_plugin implementation
+ */
 function elfinder_jwysiwyg_elfinder_editor_plugin($options) {
-        if (module_exists('jquery_update') && module_exists('jquery_ui')) {
-          drupal_add_css(JQUERY_UI_PATH . '/themes/base/ui.all.css');
-          jquery_ui_add(array('ui.dialog', 'ui.accordion', 'ui.draggable', 'ui.droppable', 'ui.selectable'));
-  } else {
-          drupal_set_message(t('elFinder requires jQuery 1.3+ and jQuery UI 1.7+ for jWYSIWYG support. Please install and enable <a href="http://drupal.org/project/jquery_update">jquery_update</a> and <a href="http://drupal.org/project/jquery_ui">jquery_ui</a> modules.'), 'error');
-        }
-      
-      drupal_add_js(array('elfinder' => array('file_browser_url' => $options['elfinder_url'])), 'setting');
-      drupal_add_js($options['plugin_url_base'] . '/jwysiwyg.js');
-      
-      return array(
-        'elfinder' => array(
-          'extensions' => array('elfinder' => t('elFinder')),
-          'url' => $options['homepage_url'],
-          'options' => array(),
-          'load' => FALSE,
-        ),
-      );
+  if (VERSION < 7) {
+    if (module_exists('jquery_update') && module_exists('jquery_ui')) {
+      drupal_add_css(JQUERY_UI_PATH . '/themes/base/ui.all.css');
+      jquery_ui_add(array('ui.dialog', 'ui.accordion', 'ui.draggable', 'ui.droppable', 'ui.selectable'));
+    } else {
+      drupal_set_message(t('elFinder requires jQuery 1.3+ and jQuery UI 1.7+ for jWYSIWYG support. Please install and enable <a href="http://drupal.org/project/jquery_update">jquery_update</a> and <a href="http://drupal.org/project/jquery_ui">jquery_ui</a> modules.'), 'error');
+    }
+  }
+
+  drupal_add_js(array('elfinder' => array('file_browser_url' => $options['elfinder_url'])), 'setting');
+  drupal_add_js($options['plugin_url_base'] . '/jwysiwyg.js');
+
+  return array(
+    'elfinder' => array(
+      'extensions' => array('elfinder' => t('elFinder')),
+      'url' => $options['homepage_url'],
+      'options' => array(),
+      'load' => FALSE,
+    ),
+  );
 }

+ 32 - 26
sites/all/modules/contrib/files/elfinder/editors/jwysiwyg/jwysiwyg.js

@@ -1,34 +1,40 @@
+/*
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
+ */
+
 // $Id: elfinder.jwysiwyg.js,v 1.1 2010/10/06 09:44:51 ph0enix Exp $
 
 (function($) {
 
-Drupal.elfinder.editor.jwysiwyg = {
-  fn : { 
-    attach: Drupal.wysiwyg.editor.attach.jwysiwyg
-  }
-}
-
-Drupal.wysiwyg.editor.attach.jwysiwyg = function(context, params, settings) {
-  
-  var imgHtml = null;
-  
-  if (jQuery.fn.wysiwyg.defaults) {
-    imgHtml = jQuery.fn.wysiwyg.defaults.formImageHtml;
-  }
-  
-  var oImgHtml = $('<div>'+imgHtml+'</div>');
-  var oUrl = $("input[name=url]", oImgHtml);
-  var browsebutton = $('<input type="button">');
-
-  browsebutton.attr('value', Drupal.t('Browse Server'));
-  browsebutton.attr('onclick', 'var w = window; w.open("' + Drupal.settings.elfinder.file_browser_url + '","","toolbar=no,menubar=no,width=600,height=600")');
-  browsebutton.insertAfter(oUrl);
-  
-  if (jQuery.fn.wysiwyg.defaults) {
-    jQuery.fn.wysiwyg.defaults.formImageHtml = oImgHtml.html();
+  Drupal.elfinder.editor.jwysiwyg = {
+    fn: {
+      attach: Drupal.wysiwyg.editor.attach.jwysiwyg
+    }
   }
 
-  Drupal.elfinder.editor.jwysiwyg.fn.attach.apply(this, arguments); 
-}
+  Drupal.wysiwyg.editor.attach.jwysiwyg = function(context, params, settings) {
+
+    var imgHtml = null;
+
+    if (jQuery.fn.wysiwyg.defaults) {
+      imgHtml = jQuery.fn.wysiwyg.defaults.formImageHtml;
+    }
+
+    var oImgHtml = $('<div>' + imgHtml + '</div>');
+    var oUrl = $("input[name=url]", oImgHtml);
+    var browsebutton = $('<input type="button">');
+
+    browsebutton.attr('value', Drupal.t('Browse Server'));
+    browsebutton.attr('onclick', 'var w = window; w.open("' + Drupal.settings.elfinder.file_browser_url + '","","toolbar=no,menubar=no,width=600,height=600")');
+    browsebutton.insertAfter(oUrl);
+
+    if (jQuery.fn.wysiwyg.defaults) {
+      jQuery.fn.wysiwyg.defaults.formImageHtml = oImgHtml.html();
+    }
+
+    Drupal.elfinder.editor.jwysiwyg.fn.attach.apply(this, arguments);
+  }
 
 })(jQuery);

File diff suppressed because it is too large
+ 0 - 0
sites/all/modules/contrib/files/elfinder/editors/tinymce/tinymce.callback.js


+ 21 - 15
sites/all/modules/contrib/files/elfinder/editors/tinymce/tinymce.inc

@@ -1,24 +1,30 @@
 <?php
+/**
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
+ */
+
 /**
  * @file
  * TinyMCE integration plugin
  */
 
 /**
-  * Pseudo-hook for elfinder hook_wysiwyg_plugin implementation
-  */
+ * Pseudo-hook for elfinder hook_wysiwyg_plugin implementation
+ */
 function elfinder_tinymce_elfinder_editor_plugin($options) {
-      drupal_add_js($options['plugin_url_base'] . '/tinymce.js');
-      return array(
-        'elfinder' => array(
-          'extensions' => array('elfinder' => t('elFinder')),
-          'url' => $options['homepage_url'],
-          'options' => array(
-            'file_browser_callback' => 'elfinder_tinymce_browse_callback',
-            'file_browser_url' => $options['elfinder_url'], // non standard TinyMCE configuration variable to pass source application to elFinder
-            'inline_styles' => TRUE,
-          ),
-          'load' => FALSE,
-        ),
-      );
+  drupal_add_js($options['plugin_url_base'] . '/tinymce.js');
+  return array(
+    'elfinder' => array(
+      'extensions' => array('elfinder' => t('elFinder')),
+      'url' => $options['homepage_url'],
+      'options' => array(
+        'file_browser_callback' => 'elfinder_tinymce_browse_callback',
+        'file_browser_url' => $options['elfinder_url'], // non standard TinyMCE configuration variable to pass source application to elFinder
+        'inline_styles' => TRUE,
+      ),
+      'load' => FALSE,
+    ),
+  );
 }

+ 42 - 23
sites/all/modules/contrib/files/elfinder/editors/tinymce/tinymce.js

@@ -1,27 +1,46 @@
+/*
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
+ */
+
+// $Id$
+
+/*function elfinder_tinymce_browse_callback(field_name, url, type, win) {
+ var w = window.open(tinymce.settings.file_browser_url, null, 'toolbar=yes,menubar=yes,width=600,height=500, inline=yes');
+ w.tinymceFileField = field_name;
+ w.tinymceFileWin = win;
+ }*/
+
+// MAKE INLINE POPUP WORK
+
 function elfinder_tinymce_browse_callback(field_name, url, type, win) {
+  /*var w = window.open(tinymce.settings.file_browser_url, null, 'toolbar=yes,menubar=yes,width=600,height=500, inline=yes');
+   w.tinymceFileField = field_name;
+   w.tinymceFileWin = win;*/
 
-    var cmsURL = tinymce.settings.file_browser_url;    // script URL - use an absolute path!
-    if (cmsURL.indexOf("?") < 0) {
-        //add the type as the only query parameter
-        cmsURL = cmsURL + "?type=" + type;
-    } else {
-        //add the type as an additional query parameter
-        // (PHP session ID is now included if there is one at all)
-        cmsURL = cmsURL + "&type=" + type;
-    }
+  var cmsURL = tinymce.settings.file_browser_url;    // script URL - use an absolute path!
+  if (cmsURL.indexOf("?") < 0) {
+    //add the type as the only query parameter
+    cmsURL = cmsURL + "?type=" + type;
+  } else {
+    //add the type as an additional query parameter
+    // (PHP session ID is now included if there is one at all)
+    cmsURL = cmsURL + "&type=" + type;
+  }
 
-    tinyMCE.activeEditor.windowManager.open({
-        file: cmsURL,
-        title: 'File Manager',
-        width: 900,
-        height: 450,
-        resizable: "yes",
-        inline: "yes", // This parameter only has an effect if you use the inlinepopups plugin!
-        popup_css: false, // Disable TinyMCE's default popup CSS
-        close_previous: "no"
-    }, {
-        window: win,
-        input: field_name
-    });
-    return false;
+  tinyMCE.activeEditor.windowManager.open({
+    file: cmsURL,
+    title: 'File Manager',
+    width: 900,
+    height: 450,
+    resizable: "yes",
+    inline: "yes", // This parameter only has an effect if you use the inlinepopups plugin!
+    popup_css: false, // Disable TinyMCE's default popup CSS
+    close_previous: "no"
+  }, {
+    window: win,
+    input: field_name
+  });
+  return false;
 }

+ 8 - 2
sites/all/modules/contrib/files/elfinder/editors/wymeditor/wymeditor.callback.js

@@ -1,4 +1,10 @@
+/*
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
+ */
+
 function elfinder_wymeditor_callback(url) {
-          window.opener.jQuery('input.wym_src').val(url);
-          window.close();
+  window.opener.jQuery('input.wym_src').val(url);
+  window.close();
 }

+ 18 - 12
sites/all/modules/contrib/files/elfinder/editors/wymeditor/wymeditor.inc

@@ -1,4 +1,10 @@
 <?php
+/**
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
+ */
+
 // $Id$
 
 /**
@@ -7,17 +13,17 @@
  */
 
 /**
-  * Pseudo-hook for elfinder hook_wysiwyg_plugin implementation
-  */
+ * Pseudo-hook for elfinder hook_wysiwyg_plugin implementation
+ */
 function elfinder_wymeditor_elfinder_editor_plugin($options) {
-      drupal_add_js($options['plugin_url_base'] . '/wymeditor.js');
-      drupal_add_js(array('elfinder' => array('file_browser_url' => $options['elfinder_url'])), 'setting');
-      return array(
-        'elfinder' => array(
-          'extensions' => array('elfinder' => t('elFinder')),
-          'url' => $options['homepage_url'],
-          'options' => array(),
-          'load' => FALSE,
-        ),
-      );
+  drupal_add_js($options['plugin_url_base'] . '/wymeditor.js');
+  drupal_add_js(array('elfinder' => array('file_browser_url' => $options['elfinder_url'])), 'setting');
+  return array(
+    'elfinder' => array(
+      'extensions' => array('elfinder' => t('elFinder')),
+      'url' => $options['homepage_url'],
+      'options' => array(),
+      'load' => FALSE,
+    ),
+  );
 }

+ 55 - 43
sites/all/modules/contrib/files/elfinder/editors/wymeditor/wymeditor.js

@@ -1,52 +1,64 @@
+/*
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
+ */
+
 // $Id: elfinder.wymeditor.js,v 1.1.2.2 2010/12/11 11:53:49 ph0enix Exp $
 
 (function($) {
 
-Drupal.elfinder.editor.wymeditor = {
-  fn : { 
-    attach: Drupal.wysiwyg.editor.attach.wymeditor
-  }
-}
-
-Drupal.wysiwyg.editor.attach.wymeditor = function(context, params, settings) {
-
-  Drupal.elfinder.editor.wymeditor.fn.attach.apply(this, arguments); 
-
-  var $field = $('#' + params.field);
-  var index = $field.data(WYMeditor.WYM_INDEX);
-  
-  if (typeof index != 'undefined') {
-    var instance = WYMeditor.INSTANCES[index];
-
-    var imgHtml = instance._options.dialogImageHtml;
-    
-    var oImgHtml = $('<div>'+imgHtml+'</div>');
-    
-    var oUrl = $("input.wym_src", oImgHtml);
-    var browsebutton = $('<input type="button">');
-    browsebutton.attr('value', Drupal.t('Browse Server'));
-
-    /* FIXME: url parameters duplicates for some reason */
-    var tmp = Drupal.settings.elfinder.file_browser_url;
-    var bugpos = tmp.indexOf(",");
-    
-    var elfinderUrl = '';
-    
-    if (bugpos != -1) {
-      elfinderUrl = tmp.slice(0, bugpos);
-    }
-    else {
-      elfinderUrl = tmp;
+  Drupal.elfinder.editor.wymeditor = {
+    fn: {
+      attach: Drupal.wysiwyg.editor.attach.wymeditor
     }
+  }
+
+  Drupal.wysiwyg.editor.attach.wymeditor = function(context, params, settings) {
+
+    Drupal.elfinder.editor.wymeditor.fn.attach.apply(this, arguments);
+
+    var $field = $('#' + params.field);
+    var index = $field.data(WYMeditor.WYM_INDEX);
+
+    if (typeof index != 'undefined') {
+      var instance = WYMeditor.INSTANCES[index];
+
+      var imgHtml = instance._options.dialogImageHtml;
+
+      var oImgHtml = $('<div>' + imgHtml + '</div>');
+
 
-    browsebutton.attr('onclick', 'var w = window; w.open("' + elfinderUrl + '","","toolbar=no,menubar=no,width=600,height=600")');
-    browsebutton.insertAfter(oUrl);
-    
-    
-    ImgHtml = '<body class="wym_dialog wym_dialog_image" onload="WYMeditor.INIT_DIALOG(' + index + ')">' + oImgHtml.html() + '</body>';
-    
-    instance._options.dialogImageHtml = ImgHtml;
+      //$('body', oImgHtml).addClass('wym_dialog wym_dialog_image');
+      //$('body', oImgHtml).attr('omload', 'WYMeditor.INIT_DIALOG(' + index + ')');
+
+      var oUrl = $("input.wym_src", oImgHtml);
+      var browsebutton = $('<input type="button">');
+      browsebutton.attr('value', Drupal.t('Browse Server'));
+
+      /* FIXME: url parameters duplicates for some reason */
+      var tmp = Drupal.settings.elfinder.file_browser_url;
+      var bugpos = tmp.indexOf(",");
+
+      var elfinderUrl = '';
+
+      if (bugpos != -1) {
+        elfinderUrl = tmp.slice(0, bugpos);
+      }
+      else {
+        elfinderUrl = tmp;
+      }
+
+      /*  */
+
+      browsebutton.attr('onclick', 'var w = window; w.open("' + elfinderUrl + '","","toolbar=no,menubar=no,width=600,height=600")');
+      browsebutton.insertAfter(oUrl);
+
+
+      ImgHtml = '<body class="wym_dialog wym_dialog_image" onload="WYMeditor.INIT_DIALOG(' + index + ')">' + oImgHtml.html() + '</body>';
+
+      instance._options.dialogImageHtml = ImgHtml;
+    }
   }
-}
 
 })(jQuery);

+ 9 - 3
sites/all/modules/contrib/files/elfinder/editors/yui/yui.callback.js

@@ -1,5 +1,11 @@
+/*
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
+ */
+
 function elfinder_yui_callback(url) {
-          var editorId = window.opener.Drupal.wysiwyg.activeId;
-          window.opener.jQuery('input#' + editorId + '_insertimage_url').val(url);
-          window.close();
+  var editorId = window.opener.Drupal.wysiwyg.activeId;
+  window.opener.jQuery('input#' + editorId + '_insertimage_url').val(url);
+  window.close();
 }

+ 20 - 12
sites/all/modules/contrib/files/elfinder/editors/yui/yui.inc

@@ -1,21 +1,29 @@
 <?php
+/**
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
+ */
+
+// $Id$
+
 /**
  * @file
  * YUI editor integration plugin
  */
 
 /**
-  * Pseudo-hook for elfinder hook_wysiwyg_plugin implementation
-  */
+ * Pseudo-hook for elfinder hook_wysiwyg_plugin implementation
+ */
 function elfinder_yui_elfinder_editor_plugin($options) {
-      drupal_add_js($options['plugin_url_base'] . '/yui.js');
-      drupal_add_js(array('elfinder' => array('file_browser_url' => $options['elfinder_url'])), 'setting');
-      return array(
-        'elfinder' => array(
-          'extensions' => array('elfinder' => t('elFinder')),
-          'url' => $options['homepage_url'],
-          'options' => array(),
-          'load' => FALSE,
-        ),
-      );
+  drupal_add_js($options['plugin_url_base'] . '/yui.js');
+  drupal_add_js(array('elfinder' => array('file_browser_url' => $options['elfinder_url'])), 'setting');
+  return array(
+    'elfinder' => array(
+      'extensions' => array('elfinder' => t('elFinder')),
+      'url' => $options['homepage_url'],
+      'options' => array(),
+      'load' => FALSE,
+    ),
+  );
 }

+ 34 - 26
sites/all/modules/contrib/files/elfinder/editors/yui/yui.js

@@ -1,33 +1,41 @@
+/*
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
+ */
+
 // $Id: elfinder.yui.js,v 1.1 2010/10/06 09:44:51 ph0enix Exp $
 
 (function($) {
 
-Drupal.elfinder.editor.yui = {
-  fn : { 
-    attach: Drupal.wysiwyg.editor.attach.yui
+  Drupal.elfinder.editor.yui = {
+    fn: {
+      attach: Drupal.wysiwyg.editor.attach.yui
+    }
+  }
+
+  Drupal.wysiwyg.editor.attach.yui = function(context, params, settings) {
+
+    $('#' + params.field).parent().addClass('yui-skin-' + settings.theme);
+    // Attach editor.
+    var editor = new YAHOO.widget.Editor(params.field, settings);
+
+    editor.on('windowInsertImageRender', function(e) {
+
+      var dialogcode = $('#' + params.field + '-panel');
+
+
+      //var oImgHtml = $('<div>'+imgHtml+'</div>');
+      var oUrl = $('input#' + params.field + '_insertimage_url');
+      var browsebutton = $('<input type="button">');
+
+      browsebutton.attr('value', Drupal.t('Browse Server'));
+      browsebutton.attr('onclick', 'var w = window; w.open("' + Drupal.settings.elfinder.file_browser_url + '","","toolbar=no,menubar=no,width=600,height=600")');
+      browsebutton.insertAfter(oUrl);
+
+    }, editor, true);
+
+    editor.render();
   }
-}
-
-Drupal.wysiwyg.editor.attach.yui = function(context, params, settings) {
-  
-  $('#' + params.field).parent().addClass('yui-skin-' + settings.theme);
-  // Attach editor.
-  var editor = new YAHOO.widget.Editor(params.field, settings);
-  
-  editor.on('windowInsertImageRender', function(e) {
-	
-	var dialogcode = $('#' + params.field + '-panel');
-	
-	var oUrl = $('input#' + params.field + '_insertimage_url');
-	var browsebutton = $('<input type="button">');
-
-	browsebutton.attr('value', Drupal.t('Browse Server'));
-	browsebutton.attr('onclick', 'var w = window; w.open("' + Drupal.settings.elfinder.file_browser_url + '","","toolbar=no,menubar=no,width=600,height=600")');
-	browsebutton.insertAfter(oUrl);
-
-  }, editor, true);
-  
-  editor.render();
-}
 
 })(jQuery);

+ 3 - 2
sites/all/modules/contrib/files/elfinder/elfinder.info

@@ -6,8 +6,9 @@ configure = "admin/config/media/elfinder"
 core = 7.x
 project status url = https://drupal-elfinder.sourceforge.io/release-history.php
 
-; Information added by Drupal.org packaging script on 2018-12-03
+; Information added by Drupal.org packaging script on 2017-11-16
 version = "7.x-2.x-dev"
 core = "7.x"
 project = "elfinder"
-datestamp = "1543843700"
+datestamp = "1555577224"
+

+ 71 - 68
sites/all/modules/contrib/files/elfinder/elfinder.install

@@ -1,4 +1,10 @@
 <?php
+/**
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2019, Alexey Sukhotin. All rights reserved.
+ */
+
 /**
  * @file
  * Installation file for elfinder.
@@ -11,77 +17,74 @@ function elfinder_requirements($phase) {
   require_once drupal_get_path('module', 'elfinder') . "/elfinder.module";
 
   $requirements = array();
-	
-	$ver_major = 0;
-	$ver_minor = 0;
-    $ver_release = 0;
-	$min_major = 2;
-	$min_minor = 0;
-	
-	$min_ver = "$min_major.$min_minor";
+
+  $ver_major = 0;
+  $ver_minor = 0;
+  $ver_release = 0;
+  $min_major = 2;
+  $min_minor = 0;
+
+  $min_ver = "$min_major.$min_minor";
 
   $libpath = elfinder_lib_path();
-    $ver = '';
-	
-	
-	$install_t = t('Please download it from <a href="@url">@url</a> and install to @libpath.', array('@url' => 'http://elfinder.org', '@libpath' => $libpath));
+  $ver = '';
+
+
+  $install_t = t('Please download it from <a href="@url">@url</a> and install to @libpath.', array('@url' => elfinder_download_url(), '@libpath' => $libpath));
 
   if ($phase == 'runtime' || $phase == 'install' || $phase == 'update') {
     $description = t('elFinder library was not found.') . ' ' . $install_t;
 
     $severity = '';
     $value = t('Not found');
-		
-    if ( (is_readable($libpath . '/connectors/php/elFinder.class.php') || is_readable($libpath . '/php/elFinder.class.php') ) && is_readable($libpath . '/js/elfinder.min.js') ) {
 
-			$editor_file_content = file_get_contents($libpath . '/js/elfinder.min.js');
+    if ((is_readable($libpath . '/connectors/php/elFinder.class.php') || is_readable($libpath . '/php/elFinder.class.php')) && is_readable($libpath . '/js/elfinder.min.js')) {
+
+      $editor_file_content = file_get_contents($libpath . '/js/elfinder.min.js');
 
       $value = t('Exists');
 
       if (preg_match("/(?:this|elFinder\.prototype|\.prototype)\.version\s*=\s*[\"\']([^\"\']+)[\"\']/", $editor_file_content, $matches)) {
-				$ver = $matches[1];
+        $ver = $matches[1];
         $value = t('@ver', array('@ver' => $ver));
       }
 
       $description = '';
-			
-			if (preg_match("/^(\d+)\.(\d+|x)(\.(\d+))?/", $ver, $matches)) {
-				$ver_major = (int)$matches[1];
-				$ver_minor = $matches[2];
-                $ver = "$ver_major.$ver_minor";
-                if (count($matches) == 5) {
-                    $ver_release = (int)$matches[4];
-                    $ver = "$ver_major.$ver_minor.$ver_release";
-                }
-			}	
-				
-		
-        
-			
-			if (($ver_major < $min_major) || ($ver_major == 2 && $ver_minor == '1' && $ver_release < 38)) {
-				$description = t('Not supported elFinder library. Please upgrade to @minver.', array('@ver' => $ver, '@minver' => $min_ver)) . ' ' . $install_t;
-				$severity = REQUIREMENT_ERROR;
-			} else {
-				$severity = REQUIREMENT_OK;
-			}
-    
-            $badpaths_check = elfinder_check_badpaths();
-            
-            if ($badpaths_check['result'] == FALSE) {
-                $severity = REQUIREMENT_ERROR;
-                $description = $badpaths_check['message'];
-            }
-      
-    }
-		else {
+
+      if (preg_match("/^(\d+)\.(\d+|x)(\.(\d+))?/", $ver, $matches)) {
+        $ver_major = (int)$matches[1];
+        $ver_minor = $matches[2];
+        $ver = "$ver_major.$ver_minor";
+        if (count($matches) == 5) {
+          $ver_release = (int)$matches[4];
+          $ver = "$ver_major.$ver_minor.$ver_release";
+        }
+      }
+
+
+      if (($ver_major < $min_major) || ($ver_major == 2 && $ver_minor == '1' && $ver_release < 38)) {
+        $description = t('Not supported elFinder library. Please upgrade to @minver.', array('@ver' => $ver, '@minver' => $min_ver)) . ' ' . $install_t;
+        $severity = REQUIREMENT_ERROR;
+      } else {
+        $severity = REQUIREMENT_OK;
+      }
+
+      $badpaths_check = elfinder_check_badpaths();
+
+      if ($badpaths_check['result'] == FALSE) {
+        $severity = REQUIREMENT_ERROR;
+        $description = $badpaths_check['message'];
+      }
+
+    } else {
       $severity = REQUIREMENT_ERROR;
     }
 
     $requirements['elfinder'] = array(
-        'title' => 'elFinder',
-        'description' => $description,
-        'value' => $value,
-        'severity' => $severity
+      'title' => 'elFinder',
+      'description' => $description,
+      'value' => $value,
+      'severity' => $severity
     );
   }
 
@@ -102,47 +105,48 @@ function elfinder_schema() {
   $schema['elfinder_file_extinfo'] = array(
     'description' => 'Stores additional filesystem attributes',
     'fields' => array(
-      'extid'        => array('type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE),
-      'fid'        => array('type' => 'int', 'unsigned' => TRUE, 'not null' => FALSE),
-      'description'       => array('type' => 'varchar', 'length' => 255, 'not null' => FALSE, 'default' => ''),
+      'extid' => array('type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE),
+      'fid' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => FALSE),
+      'description' => array('type' => 'varchar', 'length' => 255, 'not null' => FALSE, 'default' => ''),
     ),
     'primary key' => array('extid'),
   );
-  
+
   $schema['elfinder_profile'] = array(
     'description' => 'Stores configuration profiles',
     'fields' => array(
-      'pid'        => array('type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE),
-      'name'        => array('type' => 'varchar', 'length' => 255, 'not null' => FALSE, 'default' => ''),
-      'description'       => array('type' => 'varchar', 'length' => 255, 'not null' => FALSE, 'default' => ''),
-      'settings'    => array('type' => 'text', 'not null' => FALSE),
+      'pid' => array('type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE),
+      'name' => array('type' => 'varchar', 'length' => 255, 'not null' => FALSE, 'default' => ''),
+      'description' => array('type' => 'varchar', 'length' => 255, 'not null' => FALSE, 'default' => ''),
+      'settings' => array('type' => 'text', 'not null' => FALSE),
     ),
     'primary key' => array('pid'),
   );
-  
+
   return $schema;
-     
+
 }
 
 function elfinder_update_7101() {
+  // drupal_install_schema('elfinder');
 }
 
 function elfinder_update_7102() {
   $ret = array();
 
   if (db_table_exists('elfinder_profile') == FALSE) {
-      drupal_install_schema('elfinder');
+    drupal_install_schema('elfinder');
   }
-  
+
   if (!db_field_exists('elfinder_profile', 'settings')) {
-      db_add_field($ret, 'elfinder_profile', 'settings', array('type' => 'text', 'not null' => FALSE));
+    db_add_field($ret, 'elfinder_profile', 'settings', array('type' => 'text', 'not null' => FALSE));
   }
-  
+
   return $ret;
 }
 
 function elfinder_update_7103() {
- drupal_flush_all_caches();
+  drupal_flush_all_caches();
 }
 
 /**
@@ -150,13 +154,12 @@ function elfinder_update_7103() {
  */
 function elfinder_update_7104() {
   $results = db_query("SELECT pid, name, description, settings from {elfinder_profile}");
-  foreach($results as $row) {
+  foreach ($results as $row) {
     $settings = unserialize($row->settings);
     if (!is_array($settings['profile_role'])) {
       if (isset($settings['profile_role']) && $settings['profile_role'] > 0) {
         $settings['profile_role'] = array($settings['profile_role'] => $settings['profile_role']);
-      }
-      else {
+      } else {
         $settings['profile_role'] = array();
       }
       db_update('elfinder_profile')

File diff suppressed because it is too large
+ 292 - 225
sites/all/modules/contrib/files/elfinder/elfinder.module


+ 79 - 28
sites/all/modules/contrib/files/elfinder/inc/elfinder.admin.inc

@@ -1,4 +1,9 @@
 <?php
+/**
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
+ */
 
 /**
  * @file
@@ -28,30 +33,29 @@ function elfinder_admin_profile_links($profile_name) {
 }
 
 
-
 /**
  * Settings form definition
  */
 function elfinder_admin_form(&$form_state) {
   global $user, $language;
   $path = drupal_get_path('module', 'elfinder');
- // require_once $path .'/inc/' . 'elfinder.admin.profiles.inc';
+  // require_once $path .'/inc/' . 'elfinder.admin.profiles.inc';
 
   $langCode = isset($language->language) ? $language->language : 'en';
- 
+
   $form['profiles'] = array(
     '#type' => 'fieldset',
     '#title' => t('Profiles'),
     '#collapsible' => TRUE,
     '#collapsed' => FALSE,
   );
-  
+
   $profiles = elfinder_admin_profile_get();
-  
+
   $roles = user_roles();
-  
+
   $rows = array();
-  
+
   if ($profiles) {
     if (is_array($profiles)) {
       foreach ($profiles as $profile) {
@@ -61,21 +65,21 @@ function elfinder_admin_form(&$form_state) {
       $profile = $profiles;
       $rows[] = array($profile->pid, $profile->name, $profile->description, implode(', ', array_intersect_key($roles, $profile->settings['profile_role'])), elfinder_admin_profile_links($profile->name));
     }
-  
+
   }
 
-  $profile_table =  theme('table', array(
+  $profile_table = theme('table', array(
     'header' => array(t('Id'), t('Name'), t('Description'), t('Role'), ''),
     'rows' => $rows
   ));
-  
+
   $addprofile = l(t('Add profile'), 'admin/config/media/elfinder/profile');
-  
+
   $form['profiles']['profile_list'] = array(
     '#type' => 'markup',
     '#markup' => "$profile_table<br/>$addprofile",
   );
-  
+
   $form['filesystem_settings'] = array(
     '#type' => 'fieldset',
     '#title' => t('File system settings'),
@@ -110,7 +114,7 @@ function elfinder_admin_form(&$form_state) {
     '#default_value' => variable_get('elfinder_settings_filesystem_unmanaged_root_label', ''),
     '#description' => t('Root directory label in directory tree'),
   );
-  
+
   $form['filesystem_settings']['filesystem_root_custom'] = array(
     '#prefix' => '<div class="custom-container">',
     '#suffix' => '</div>',
@@ -137,7 +141,7 @@ function elfinder_admin_form(&$form_state) {
       'auto' => t('Automatical detection'),
     ),
   );
-  
+
   $form['filesystem_settings']['filesystem_allowed_extensions'] = array(
     '#prefix' => '<div class="custom-container">',
     '#suffix' => '</div>',
@@ -147,7 +151,7 @@ function elfinder_admin_form(&$form_state) {
     '#default_value' => variable_get('elfinder_settings_filesystem_allowed_extensions', ''),
     '#description' => t('Separate extensions with a space or comma and do not include the leading dot.'),
   );
-  
+
   if (function_exists('finfo_open')) {
     $form['filesystem_settings']['mime_detect']['#options']['finfo'] = t('php finfo');
   }
@@ -160,8 +164,41 @@ function elfinder_admin_form(&$form_state) {
   $form['filesystem_settings']['mime_detect']['#options']['bsd'] = t('file -Ib (bsd)');
   $form['filesystem_settings']['mime_detect']['#options']['internal'] = t('By file extension (built-in)');
   $form['filesystem_settings']['mime_detect']['#options']['drupal'] = t('Drupal API');
-  
-  
+
+
+  $form['filesystem_settings']['filesystem_inline_preview'] = array(
+    '#type' => 'radios',
+    '#title' => t('Preview'),
+    '#default_value' => variable_get('elfinder_settings_filesystem_inline_preview', 'default'),
+    '#description' => t('File types allowed to display in preview'),
+    '#options' => array(
+      'default' => t('Default - images, video, audio, pdf, text'),
+      'all' => t('All supported for preview files - additional: md, psd, html, archives, swf, sharecad.org, MS Office Online, Google Docs - be careful'),
+      'custom' => t('Custom regex'),
+      'disabled' => t('Disabled'),
+    ),
+  );
+
+  $form['filesystem_settings']['filesystem_inline_preview_custom'] = array(
+    '#prefix' => '<div class="custom-container">',
+    '#suffix' => '</div>',
+    '#type' => 'textfield',
+    '#title' => t('Custom preview match regex'),
+    '#default_value' => variable_get('elfinder_settings_filesystem_inlinepreviewcustom', '^(?:(?:image|video|audio)|application/(?:x-mpegURL|dash\\+xml)|(?:text/plain|application/pdf)$)'),
+    '#description' => t('Custom mime type match regex for preview'),
+  );
+
+  $form['filesystem_settings']['filesystem_external_preview'] = array(
+    '#type' => 'radios',
+    '#title' => t('External Service Preview'),
+    '#default_value' => variable_get('elfinder_settings_filesystem_external_preview', 'disabled'),
+    '#description' => t('Use Microsoft, Google and other online services to preview some office documents. <b>Warning!</b> By previewing document with external services <b>YOU ARE ULOADING</b> the document to them. Google, Microsoft and other service owners usually <b>TRACK</b> your activity and <b>share it with Sales, CIA, FSB (KGB), FBI, governors, etc.</b>'),
+    '#options' => array(
+      'default' => t('Use Microsoft Office and Google Docs for preview'),
+      'disabled' => t('Disabled'),
+    ),
+  );
+
   $form['filesystem_settings']['file_url_type'] = array(
     '#type' => 'radios',
     '#title' => t('Selected file url type'),
@@ -170,7 +207,7 @@ function elfinder_admin_form(&$form_state) {
       'true' => t('Absolute'),
       'false' => t('Relative'),
     ),
-  );  
+  );
 
   $form['filesystem_settings']['file_perm'] = array(
     '#type' => 'textfield',
@@ -195,7 +232,7 @@ function elfinder_admin_form(&$form_state) {
     '#size' => 10,
     '#weight' => 5,
   );
-  
+
   $form['filesystem_settings']['max_filecount'] = array(
     '#type' => 'textfield',
     '#title' => t('Maximum folder size'),
@@ -204,7 +241,7 @@ function elfinder_admin_form(&$form_state) {
     '#size' => 10,
     '#weight' => 5,
   );
-  
+
   $form['filesystem_settings']['handleprivate'] = array(
     '#type' => 'radios',
     '#title' => t('Handle private downloads'),
@@ -222,7 +259,7 @@ function elfinder_admin_form(&$form_state) {
     '#collapsible' => TRUE,
     '#collapsed' => FALSE,
   );
-  
+
   $form['thumbnail_settings']['tmbsize'] = array(
     '#type' => 'textfield',
     '#title' => t('Thumbnail size'),
@@ -244,7 +281,7 @@ function elfinder_admin_form(&$form_state) {
     '#options' => array(
       'auto' => t('Automatical detection'),
       'imagick' => t('Image Magick'),
-      'gd'  => t('GD'),
+      'gd' => t('GD'),
     ),
   );
 
@@ -265,7 +302,7 @@ function elfinder_admin_form(&$form_state) {
     '#collapsible' => TRUE,
     '#collapsed' => FALSE,
   );
-  
+
   $form['misc_settings']['rememberlastdir'] = array(
     '#type' => 'radios',
     '#title' => t('Remember last opened directory'),
@@ -312,7 +349,7 @@ function elfinder_admin_form(&$form_state) {
 
   $form['submit'] = array('#type' => 'submit', '#value' => t('Save configuration'));
   $form['#submit'][] = 'elfinder_admin_submit';
-  
+
   return $form;
 }
 
@@ -344,11 +381,25 @@ function elfinder_admin_submit($form, &$form_state) {
   variable_set('elfinder_settings_filesystem_public_root_label', $form_state['values']['filesystem_public_root_label']);
   variable_set('elfinder_settings_filesystem_private_root_label', $form_state['values']['filesystem_private_root_label']);
   variable_set('elfinder_settings_filesystem_unmanaged_root_label', $form_state['values']['filesystem_unmanaged_root_label']);
-  variable_set('elfinder_settings_misc_manager_width', $form_state['values']['manager_width']);  
-  variable_set('elfinder_settings_misc_manager_height', $form_state['values']['manager_height']);  
+  variable_set('elfinder_settings_misc_manager_width', $form_state['values']['manager_width']);
+  variable_set('elfinder_settings_misc_manager_height', $form_state['values']['manager_height']);
   variable_set('elfinder_settings_misc_hidden_folders', $form_state['values']['hidden_folders']);
   variable_set('elfinder_settings_filesystem_allowed_extensions', $form_state['values']['filesystem_allowed_extensions']);
-  
+
+  if ($form_state['values']['filesystem_inline_preview'] == 'default') {
+    variable_set('elfinder_settings_filesystem_inlinepreviewregex', '^(?:(?:image|video|audio)|application/(?:x-mpegURL|dash\\+xml)|(?:text/plain|application/pdf)$)');
+  } else if ($form_state['values']['filesystem_inline_preview'] == 'all') {
+    variable_set('elfinder_settings_filesystem_inlinepreviewregex', '.');
+  } else if ($form_state['values']['filesystem_inline_preview'] == 'custom') {
+    variable_set('elfinder_settings_filesystem_inlinepreviewregex', variable_get('elfinder_settings_filesystem_inlinepreviewcustom', '^$'));
+  } else {
+    variable_set('elfinder_settings_filesystem_inlinepreviewregex', '^$');
+  }
+
+  variable_set('elfinder_settings_filesystem_inline_preview', $form_state['values']['filesystem_inline_preview']);
+  variable_set('elfinder_settings_filesystem_inlinepreviewcustom', $form_state['values']['filesystem_inline_preview_custom']);
+  variable_set('elfinder_settings_filesystem_external_preview', $form_state['values']['filesystem_external_preview']);
+
   drupal_set_message(t('Changes have been saved.'));
 }
 
@@ -398,4 +449,4 @@ function elfinder_admin_form_validate($form, &$form_state) {
   if ($tmbsize && !is_numeric($tmbsize)) {
     form_set_error('tmbsize', t('Thumbnail size should be a number'));
   }
-}
+}

+ 197 - 192
sites/all/modules/contrib/files/elfinder/inc/elfinder.admin.profiles.inc

@@ -1,4 +1,9 @@
 <?php
+/**
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
+ */
 
 /**
  * @file
@@ -31,69 +36,69 @@ function elfinder_admin_profile($form, &$form_state) {
 
   if ($action == 'profile_add') {
     $form['profile_name'] = array(
-        '#type' => 'textfield',
-        '#title' => t('Profile Name'),
-        '#default_value' => '',
-        '#size' => 14,
+      '#type' => 'textfield',
+      '#title' => t('Profile Name'),
+      '#default_value' => '',
+      '#size' => 14,
     );
   } else {
     $form['profile_name_label'] = array(
-        '#title' => t('Profile Name'),
-        '#markup' => $profile_name,
-        '#size' => 14,
-        '#type' => 'item',
+      '#title' => t('Profile Name'),
+      '#markup' => $profile_name,
+      '#size' => 14,
+      '#type' => 'item',
     );
 
     $form['profile_name'] = array(
-        '#default_value' => $profile_name,
-        '#type' => 'hidden',
+      '#default_value' => $profile_name,
+      '#type' => 'hidden',
     );
   }
 
   $form['profile_description'] = array(
-      '#type' => 'textarea',
-      '#title' => t('Description'),
-      '#default_value' => isset($p->description) ? $p->description : '',
+    '#type' => 'textarea',
+    '#title' => t('Description'),
+    '#default_value' => isset($p->description) ? $p->description : '',
   );
 
   $form['profile_role'] = array(
-      '#type' => 'checkboxes',
-      '#title' => t('Roles'),
-      '#default_value' => isset($profile['profile_role']) ? array_keys($profile['profile_role']) : array(),
-      '#options' => user_roles(),
-      '#description' => t('Roles for which profile settings will be applied'),
+    '#type' => 'checkboxes',
+    '#title' => t('Roles'),
+    '#default_value' => isset($profile['profile_role']) ? array_keys($profile['profile_role']) : array(),
+    '#options' => user_roles(),
+    '#description' => t('Roles for which profile settings will be applied'),
   );
 
   $form['profile_action'] = array(
-      '#default_value' => $action,
-      '#type' => 'hidden',
+    '#default_value' => $action,
+    '#type' => 'hidden',
   );
 
   $form['filesystem_settings'] = array(
-      '#type' => 'fieldset',
-      '#title' => t('File system'),
-      '#collapsible' => TRUE,
-      '#collapsed' => TRUE,
+    '#type' => 'fieldset',
+    '#title' => t('File system'),
+    '#collapsible' => TRUE,
+    '#collapsed' => TRUE,
   );
 
   $form['volumes'] = array(
-      '#type' => 'fieldset',
-      '#title' => t('Volumes'),
-      '#collapsible' => TRUE,
-      '#collapsed' => FALSE,
+    '#type' => 'fieldset',
+    '#title' => t('Volumes'),
+    '#collapsible' => TRUE,
+    '#collapsed' => FALSE,
   );
 
   $form['volumes']['volumes_wrapper'] = array(
-      '#weight' => -4,
-      '#prefix' => '<div class="clear-block" id="poll-choice-wrapper">',
-      '#suffix' => '</div>',
+    '#weight' => -4,
+    '#prefix' => '<div class="clear-block" id="poll-choice-wrapper">',
+    '#suffix' => '</div>',
   );
 
   $form['volumes']['volumes_wrapper']['volume'] = array(
-      '#prefix' => '<div id="profile-volumes">',
-      '#suffix' => '</div>',
-      '#type' => 'markup',
-      '#value' => '&nbsp;',
+    '#prefix' => '<div id="profile-volumes">',
+    '#suffix' => '</div>',
+    '#type' => 'markup',
+    '#value' => '&nbsp;',
   );
 
 
@@ -129,35 +134,35 @@ function elfinder_admin_profile($form, &$form_state) {
   foreach ($form['volumes']['volumes_wrapper']['volume'] as $volume) {
     if (is_array($volume) && isset($volume['volume_settings'])) {
       $ckeditor_volumes[] = t('Volume @i (@path)', array(
-          '@i' => $i,
-          '@path' => $volume['volume_settings']['path']['#default_value'],
-              ));
+        '@i' => $i,
+        '@path' => $volume['volume_settings']['path']['#default_value'],
+      ));
       $i++;
     }
   }
 
   $form['volumes']['volumes_wrapper']['volume_add'] = array(
-      '#type' => 'submit',
-      '#value' => t('Add volume'),
-      '#weight' => 1,
-      '#name' => 'addfield',
-      '#submit' => array('elfinder_admin_profile_change_volume'),
-      '#ajax' => array(
-          'wrapper' => 'profile-volumes',
-          'callback' => 'elfinder_admin_profile_callback',
-          'method' => 'replace',
-          'effect' => 'fade',
-      ),
+    '#type' => 'submit',
+    '#value' => t('Add volume'),
+    '#weight' => 1,
+    '#name' => 'addfield',
+    '#submit' => array('elfinder_admin_profile_change_volume'),
+    '#ajax' => array(
+      'wrapper' => 'profile-volumes',
+      'callback' => 'elfinder_admin_profile_callback',
+      'method' => 'replace',
+      'effect' => 'fade',
+    ),
   );
 
 
   $form['filesystem_settings']['mime_detect'] = array(
-      '#type' => 'radios',
-      '#title' => t('File type detection'),
-      '#default_value' => isset($profile['mimedetect']) ? $profile['mimedetect'] : 'auto',
-      '#options' => array(
-          'auto' => t('Automatical detection'),
-      ),
+    '#type' => 'radios',
+    '#title' => t('File type detection'),
+    '#default_value' => isset($profile['mimedetect']) ? $profile['mimedetect'] : 'auto',
+    '#options' => array(
+      'auto' => t('Automatical detection'),
+    ),
   );
 
   if (function_exists('finfo_open')) {
@@ -175,144 +180,144 @@ function elfinder_admin_profile($form, &$form_state) {
 
 
   $form['filesystem_settings']['file_url_type'] = array(
-      '#type' => 'radios',
-      '#title' => t('Selected file url type'),
-      '#default_value' => $profile['file_url_type'] == 'true' ? 'true' : 'false',
-      '#options' => array(
-          'true' => t('Absolute'),
-          'false' => t('Relative'),
-      ),
+    '#type' => 'radios',
+    '#title' => t('Selected file url type'),
+    '#default_value' => $profile['file_url_type'] == 'true' ? 'true' : 'false',
+    '#options' => array(
+      'true' => t('Absolute'),
+      'false' => t('Relative'),
+    ),
   );
 
   $form['filesystem_settings']['file_perm'] = array(
-      '#type' => 'textfield',
-      '#title' => t('Created file permissions'),
-      '#default_value' => isset($profile['file_perm']) ? $profile['file_perm'] : '0666',
-      '#size' => 4,
+    '#type' => 'textfield',
+    '#title' => t('Created file permissions'),
+    '#default_value' => isset($profile['file_perm']) ? $profile['file_perm'] : '0666',
+    '#size' => 4,
   );
 
   $form['filesystem_settings']['dir_perm'] = array(
-      '#type' => 'textfield',
-      '#title' => t('Created directory permissions'),
-      '#default_value' => isset($profile['dir_perm']) ? $profile['dir_perm'] : '0777',
-      '#size' => 4,
+    '#type' => 'textfield',
+    '#title' => t('Created directory permissions'),
+    '#default_value' => isset($profile['dir_perm']) ? $profile['dir_perm'] : '0777',
+    '#size' => 4,
   );
 
 
   $form['filesystem_settings']['max_filesize'] = array(
-      '#type' => 'textfield',
-      '#title' => t('Maximum upload size'),
-      '#default_value' => isset($profile['max_filesize']) ? $profile['max_filesize'] : '',
-      '#description' => t('Enter a value like "512" (bytes), "80 KB" (kilobytes) or "50 MB" (megabytes) in order to restrict the allowed file size. If left empty the file sizes will be limited only by PHP\'s maximum post and file upload sizes (current limit <strong>%limit</strong>).', array('%limit' => format_size(file_upload_max_size()))),
-      '#size' => 10,
-      '#weight' => 5,
+    '#type' => 'textfield',
+    '#title' => t('Maximum upload size'),
+    '#default_value' => isset($profile['max_filesize']) ? $profile['max_filesize'] : '',
+    '#description' => t('Enter a value like "512" (bytes), "80 KB" (kilobytes) or "50 MB" (megabytes) in order to restrict the allowed file size. If left empty the file sizes will be limited only by PHP\'s maximum post and file upload sizes (current limit <strong>%limit</strong>).', array('%limit' => format_size(file_upload_max_size()))),
+    '#size' => 10,
+    '#weight' => 5,
   );
 
   $form['filesystem_settings']['user_quota'] = array(
-      '#type' => 'textfield',
-      '#title' => t('User quota'),
-      '#default_value' => isset($profile['user_quota']) ? $profile['user_quota'] : '',
-      '#description' => t('Enter a value like "512" (bytes), "80 KB" (kilobytes) or "50 MB" (megabytes) in order to restrict the allowed file size. If left empty the file sizes will be unlimited.'),
-      '#size' => 10,
-      '#weight' => 5,
+    '#type' => 'textfield',
+    '#title' => t('User quota'),
+    '#default_value' => isset($profile['user_quota']) ? $profile['user_quota'] : '',
+    '#description' => t('Enter a value like "512" (bytes), "80 KB" (kilobytes) or "50 MB" (megabytes) in order to restrict the allowed file size. If left empty the file sizes will be unlimited.'),
+    '#size' => 10,
+    '#weight' => 5,
   );
 
   $form['thumbnail_settings'] = array(
-      '#type' => 'fieldset',
-      '#title' => t('Thumbnails'),
-      '#collapsible' => TRUE,
-      '#collapsed' => TRUE,
+    '#type' => 'fieldset',
+    '#title' => t('Thumbnails'),
+    '#collapsible' => TRUE,
+    '#collapsed' => TRUE,
   );
 
   $form['thumbnail_settings']['tmbsize'] = array(
-      '#type' => 'textfield',
-      '#title' => t('Thumbnail size'),
-      '#default_value' => isset($profile['tmbsize']) ? $profile['tmbsize'] : '48',
-      '#size' => 4,
+    '#type' => 'textfield',
+    '#title' => t('Thumbnail size'),
+    '#default_value' => isset($profile['tmbsize']) ? $profile['tmbsize'] : '48',
+    '#size' => 4,
   );
 
   $form['thumbnail_settings']['tmbdirname'] = array(
-      '#type' => 'textfield',
-      '#title' => t('Thumbnail directory name'),
-      '#default_value' => isset($profile['tmbdirname']) ? $profile['tmbdirname'] : 'tmb',
-      '#size' => 10,
+    '#type' => 'textfield',
+    '#title' => t('Thumbnail directory name'),
+    '#default_value' => isset($profile['tmbdirname']) ? $profile['tmbdirname'] : 'tmb',
+    '#size' => 10,
   );
 
   $form['thumbnail_settings']['imglib'] = array(
-      '#type' => 'radios',
-      '#title' => t('Image manipulation library'),
-      '#default_value' => isset($profile['imglib']) ? $profile['imglib'] : 'auto',
-      '#options' => array(
-          'auto' => t('Automatical detection'),
-          'imagick' => t('Image Magick'),
-          'gd' => t('GD'),
-      ),
+    '#type' => 'radios',
+    '#title' => t('Image manipulation library'),
+    '#default_value' => isset($profile['imglib']) ? $profile['imglib'] : 'auto',
+    '#options' => array(
+      'auto' => t('Automatical detection'),
+      'imagick' => t('Image Magick'),
+      'gd' => t('GD'),
+    ),
   );
 
   $form['thumbnail_settings']['tmbcrop'] = array(
-      '#type' => 'radios',
-      '#title' => t('Image crop'),
-      '#default_value' => $profile['tmbcrop'] == 'true' ? 'true' : 'false',
-      '#options' => array(
-          'true' => t('Yes'),
-          'false' => t('No'),
-      ),
-      '#description' => t('Crop image to fit thumbnail size. Yes - crop, No - scale image to fit thumbnail size.'),
+    '#type' => 'radios',
+    '#title' => t('Image crop'),
+    '#default_value' => $profile['tmbcrop'] == 'true' ? 'true' : 'false',
+    '#options' => array(
+      'true' => t('Yes'),
+      'false' => t('No'),
+    ),
+    '#description' => t('Crop image to fit thumbnail size. Yes - crop, No - scale image to fit thumbnail size.'),
   );
 
   $form['misc_settings'] = array(
-      '#type' => 'fieldset',
-      '#title' => t('Miscellaneous'),
-      '#collapsible' => TRUE,
-      '#collapsed' => TRUE,
+    '#type' => 'fieldset',
+    '#title' => t('Miscellaneous'),
+    '#collapsible' => TRUE,
+    '#collapsed' => TRUE,
   );
 
   $form['misc_settings']['rememberlastdir'] = array(
-      '#type' => 'radios',
-      '#title' => t('Remember last opened directory'),
-      '#default_value' => $profile['rememberlastdir'] == 'true' ? 'true' : 'false',
-      '#options' => array(
-          'true' => t('Yes'),
-          'false' => t('No'),
-      ),
-      '#description' => t('Creates a cookie. Disable if you have issues with caching.'),
+    '#type' => 'radios',
+    '#title' => t('Remember last opened directory'),
+    '#default_value' => $profile['rememberlastdir'] == 'true' ? 'true' : 'false',
+    '#options' => array(
+      'true' => t('Yes'),
+      'false' => t('No'),
+    ),
+    '#description' => t('Creates a cookie. Disable if you have issues with caching.'),
   );
 
 
   $form['misc_settings']['manager_width'] = array(
-      '#type' => 'textfield',
-      '#title' => t('File manager width'),
-      '#default_value' => isset($profile['manager_width']) ? $profile['manager_width'] : '',
-      '#size' => 4,
+    '#type' => 'textfield',
+    '#title' => t('File manager width'),
+    '#default_value' => isset($profile['manager_width']) ? $profile['manager_width'] : '',
+    '#size' => 4,
   );
 
   $form['misc_settings']['manager_height'] = array(
-      '#type' => 'textfield',
-      '#title' => t('File manager height'),
-      '#default_value' => isset($profile['manager_height']) ? $profile['manager_height'] : '',
-      '#size' => 4,
+    '#type' => 'textfield',
+    '#title' => t('File manager height'),
+    '#default_value' => isset($profile['manager_height']) ? $profile['manager_height'] : '',
+    '#size' => 4,
   );
 
   $form['misc_settings']['ckeditor_upload_settings'] = array(
-      '#type' => 'fieldset',
-      '#title' => t('CKEditor/FCKeditor Upload Settings'),
-      '#collapsible' => TRUE,
-      '#collapsed' => TRUE,
-      '#description' => t('CKEditor and FCKeditor allowing to upload and insert image files directly from Insert Image dialog.'),
+    '#type' => 'fieldset',
+    '#title' => t('CKEditor/FCKeditor Upload Settings'),
+    '#collapsible' => TRUE,
+    '#collapsed' => TRUE,
+    '#description' => t('CKEditor and FCKeditor allowing to upload and insert image files directly from Insert Image dialog.'),
   );
 
   $form['misc_settings']['ckeditor_upload_settings']['ckeditor_upload_directory'] = array(
-      '#type' => 'textfield',
-      '#title' => t('Path'),
-      '#default_value' => isset($profile['ckeditor_upload_directory']) ? $profile['ckeditor_upload_directory'] : '',
-      '#size' => 40,
-      '#description' => t('Image upload path. Default file uri is used if no uri prefix specified. Examples: public://ckeditor - image will be uploaded into public://ckeditor; images/ckeditor - image will be uploaded to :uriimages/ckeditor', array(':uri' => file_build_uri(''))),
+    '#type' => 'textfield',
+    '#title' => t('Path'),
+    '#default_value' => isset($profile['ckeditor_upload_directory']) ? $profile['ckeditor_upload_directory'] : '',
+    '#size' => 40,
+    '#description' => t('Image upload path. Default file uri is used if no uri prefix specified. Examples: public://ckeditor - image will be uploaded into public://ckeditor; images/ckeditor - image will be uploaded to :uriimages/ckeditor', array(':uri' => file_build_uri(''))),
   );
 
   $form['submit'] = array(
-      '#type' => 'submit',
-      '#name' => 'save_profile',
-      '#value' => t('Save configuration')
+    '#type' => 'submit',
+    '#name' => 'save_profile',
+    '#value' => t('Save configuration')
   );
 
   $form['#submit'][] = 'elfinder_admin_submit';
@@ -343,8 +348,8 @@ function elfinder_admin_profiles($action = '', $profile_name = '') {
 function elfinder_admin_profiles_delete_form($form_id, &$form_state, $action, $profile_name) {
   $form = array();
   $form['profile_name'] = array(
-      '#type' => 'hidden',
-      '#default_value' => $profile_name,
+    '#type' => 'hidden',
+    '#default_value' => $profile_name,
   );
 
 
@@ -381,53 +386,53 @@ function elfinder_admin_dir_form($delta, $values = array(), $votes = 0) {
 
 
   $form['volume_settings'] = array(
-      '#type' => 'fieldset',
-      '#title' => t('Volume @n (@p)', array('@n' => ($delta + 1), '@p' => $values['path'])),
-      '#collapsible' => TRUE,
-      '#collapsed' => FALSE,
+    '#type' => 'fieldset',
+    '#title' => t('Volume @n (@p)', array('@n' => ($delta + 1), '@p' => isset($values['path']) ? $values['path'] : '')),
+    '#collapsible' => TRUE,
+    '#collapsed' => FALSE,
   );
 
   $form['volume_settings']['path'] = array(
-      '#type' => 'textfield',
-      '#title' => t('Path'),
-      '#default_value' => isset($values['path']) ? $values['path'] : '',
-      '#parents' => array('volume', $delta, 'path'),
-      '#prefix' => '<div class="elfinder-field-wrapper-volume-path">',
-      '#suffix' => '</div>',
-      '#size' => 40,
+    '#type' => 'textfield',
+    '#title' => t('Path'),
+    '#default_value' => isset($values['path']) ? $values['path'] : '',
+    '#parents' => array('volume', $delta, 'path'),
+    '#prefix' => '<div class="elfinder-field-wrapper-volume-path">',
+    '#suffix' => '</div>',
+    '#size' => 40,
   );
 
   $form['volume_settings']['label'] = array(
-      '#type' => 'textfield',
-      '#title' => t('Label'),
-      '#size' => 15,
-      '#default_value' => isset($values['label']) ? $values['label'] : '',
-      '#description' => t('Root directory label in directory tree'),
-      '#parents' => array('volume', $delta, 'label'),
+    '#type' => 'textfield',
+    '#title' => t('Label'),
+    '#size' => 15,
+    '#default_value' => isset($values['label']) ? $values['label'] : '',
+    '#description' => t('Root directory label in directory tree'),
+    '#parents' => array('volume', $delta, 'label'),
   );
 
   $form['volume_settings']['url'] = array(
-      '#type' => 'textfield',
-      '#title' => t('URL'),
-      '#default_value' => isset($values['url']) ? $values['url'] : '',
-      '#parents' => array('volume', $delta, 'url'),
-      '#prefix' => '<div class="elfinder-field-wrapper-volume-path">',
-      '#suffix' => '</div>',
-      '#description' => t('Custom URL prefix (default %def)', array('%def' => $defaulturl)),
-      '#size' => 40,
+    '#type' => 'textfield',
+    '#title' => t('URL'),
+    '#default_value' => isset($values['url']) ? $values['url'] : '',
+    '#parents' => array('volume', $delta, 'url'),
+    '#prefix' => '<div class="elfinder-field-wrapper-volume-path">',
+    '#suffix' => '</div>',
+    '#description' => t('Custom URL prefix (default %def)', array('%def' => $defaulturl)),
+    '#size' => 40,
   );
 
   $form['volume_settings']['delete'] = array(
-      '#type' => 'submit',
-      '#value' => t('Delete'),
-      '#name' => 'rmfield-' . $delta,
-      '#submit' => array('elfinder_admin_profile_change_volume'),
-      '#ajax' => array(
-          'callback' => 'elfinder_admin_profile_callback',
-          'wrapper' => 'profile-volumes',
-          'method' => 'replace',
-          'effect' => 'fade',
-      ),
+    '#type' => 'submit',
+    '#value' => t('Delete'),
+    '#name' => 'rmfield-' . $delta,
+    '#submit' => array('elfinder_admin_profile_change_volume'),
+    '#ajax' => array(
+      'callback' => 'elfinder_admin_profile_callback',
+      'wrapper' => 'profile-volumes',
+      'method' => 'replace',
+      'effect' => 'fade',
+    ),
   );
 
   return $form;
@@ -466,28 +471,28 @@ function elfinder_admin_submit($form, &$form_state) {
 
   foreach ($settings as $setting) {
     if (isset($form_state['values'][$setting])) {
-      
+
       /* Excluding empty volumes */
-	    if ($setting == 'volume') {
-		    for ($i = 0; $i < count($form_state['values']['volume']); $i++) {
-			    if (empty($form_state['values']['volume'][$i]['path'])) {
-				    unset($form_state['values']['volume'][$i]);
-			    }
-		    }
-	    }
-      
+      if ($setting == 'volume') {
+        for ($i = 0; $i < count($form_state['values']['volume']); $i++) {
+          if (empty($form_state['values']['volume'][$i]['path'])) {
+            unset($form_state['values']['volume'][$i]);
+          }
+        }
+      }
+
       $profile_settings[$setting] = $form_state['values'][$setting];
     }
   }
-  
+
   // Save roles.
   $profile_settings['profile_role'] = array();
-  foreach($form_state['values']['profile_role'] as $rid) {
+  foreach ($form_state['values']['profile_role'] as $rid) {
     if ($rid != 0) {
       $profile_settings['profile_role'][$rid] = $rid;
     }
   }
-  
+
   $profile_name = $form_state['values']['profile_name'];
   $profile_description = $form_state['values']['profile_description'];
 

+ 285 - 265
sites/all/modules/contrib/files/elfinder/inc/elfinder.drupal.inc

@@ -1,265 +1,285 @@
-<?php
-/**
- * @file
- * 
- * elFinder conenctor class 
- */
-
-class elFinderDrupal extends elFinder {
-	public function __construct($opts) {
-        if (is_callable(array($this, 'version'))) {
-            
-            $ver = floatval($this->version());
-            
-            if (isset(elFinder::$ApiVersion)) {
-                $ver = elFinder::$ApiVersion;
-            }
-            
-            if ($ver == 2.1 && is_callable(array($this, 'revision')) && $this->revision() < 37) {
-                $this->connector_unsupported_error();
-            }
-
-            parent::__construct($opts);
-            
-            $this->commands['desc'] = array('target' => TRUE, 'content' => FALSE);
-            $this->commands['owner'] = array('target' => TRUE, 'content' => FALSE);
-            $this->commands['downloadcount'] = array('target' => TRUE);
-            
-        } else {
-            $this->connector_unsupported_error();
-        }
-        
-	}
-
-
-  public function connector_unsupported_error() {
-      $this->connector_error(t('Unsupported elFinder library version. Please upgrade.'));   
-  }
-    
-  public function connector_error($message) {
-    exit(drupal_json_encode(array('error' => array(strip_tags($message)))));   
-  }
-
-  /* Overriding search query argument name 'q' since it's already used in Drupal */
-
-  public function commandArgsList($cmd) {
-    $this->commands['search']['elfinder_search_q'] = TRUE;
-    return $this->commandExists($cmd) ? $this->commands[$cmd] : array();
-  }
-
-  protected function search($args) {
-    $q = trim($args['elfinder_search_q']);
-    $mimes = !empty($args['mimes']) && is_array($args['mimes']) ? $args['mimes'] : array();
-    $target = !empty($args['target']) ? $args['target'] : null;
-    $result = array();
-    $errors = array();
-
-    if ($target) {
-      if ($volume = $this->volume($target)) {
-        $result = $volume->search($q, $mimes, $target);
-        $errors = array_merge($errors, $volume->error());
-      }
-    } else {
-    foreach ($this->volumes as $volume) {
-      $result = array_merge($result, $volume->search($q, $mimes));
-        $errors = array_merge($errors, $volume->error());
-    }
-    }
-
-    // Exclude hidden folders from search results.
-    $hidden_folders = variable_get('elfinder_settings_misc_hidden_folders', '');
-    if($hidden_folders) {
-      $hidden_folders = explode(',', $hidden_folders);
-      foreach($result AS $key => $file) {
-        $parts = explode('/', $file['path']);
-        if(in_array($parts[1], $hidden_folders)) {
-          unset($result[$key]);
-        }
-      }
-    }
-
-    $result = array('files' => $result);
-    if ($errors) {
-      $result['warning'] = $errors;
-    }
-    return $result;
-  }
-
-  protected function desc($args) {
-    $target = $args['target'];
-    $desc = $args['content'];
-    $error = array(self::ERROR_UNKNOWN, '#' . $target);
-
-    if (($volume = $this->volume($target)) == FALSE
-            || ($file = $volume->file($target)) == FALSE) {
-      return array('error' => $this->error($error, self::ERROR_FILE_NOT_FOUND));
-    }
-
-    $error[1] = $file['name'];
-    
- 		if ($volume->driverId() == 'f') {
-			return array('desc' => '');
-		}
-
-    if ($volume->commandDisabled('desc')) {
-      return array('error' => $this->error($error, self::ERROR_ACCESS_DENIED));
-    }
-
-    if (($desc = $volume->desc($target, $desc)) == -1) {
-      return array('error' => $this->error($error, $volume->error()));
-    }
-
-    return array('desc' => $desc);
-  }
-
-  protected function owner($args) {
-    $target = $args['target'];
-
-    $error = array(self::ERROR_UNKNOWN, '#' . $target);
-
-    if (($volume = $this->volume($target)) == FALSE
-            || ($file = $volume->file($target)) == FALSE) {
-      return array('error' => $this->error($error, self::ERROR_FILE_NOT_FOUND));
-    }
-
-    $error[1] = $file['name'];
-    
- 		if ($volume->driverId() == 'f') {
-			return array('owner' => '');
-		}
-
-    if ($volume->commandDisabled('owner')) {
-      return array('error' => $this->error($error, self::ERROR_ACCESS_DENIED));
-    }
-
-    if (($owner = $volume->owner($target)) == FALSE) {
-      return array('error' => $this->error($error, $volume->error()));
-    }
-
-    return array('owner' => $owner);
-  }
-
-  protected function downloadcount($args) {
-    $target = $args['target'];
-
-    $error = array(self::ERROR_UNKNOWN, '#' . $target);
-
-    if (($volume = $this->volume($target)) == FALSE
-            || ($file = $volume->file($target)) == FALSE) {
-      return array('error' => $this->error($error, self::ERROR_FILE_NOT_FOUND));
-    }
-
-    $error[1] = $file['name'];
-    
- 		if ($volume->driverId() == 'f') {
-			return array('downloadcount' => '');
-		}
-
-    if ($volume->commandDisabled('downloadcount')) {
-      return array('error' => $this->error($error, self::ERROR_ACCESS_DENIED));
-    }
-
-    if (($downloadcount = $volume->downloadcount($target)) == FALSE) {
-      return array('error' => $this->error($error, $volume->error()));
-    }
-
-    return array('downloadcount' => $downloadcount);
-  }
-
-  /**
-   * Required to output file in browser when volume URL is not set 
-   * Return array contains opened file pointer, root itself and required headers
-   *
-   * @param  array  command arguments
-   * @return array
-   * @author Dmitry (dio) Levashov
-   * */
-  protected function file($args) {
-    $target = $args['target'];
-    $download = !empty($args['download']);
-    $h403 = 'HTTP/1.x 403 Access Denied';
-    $h404 = 'HTTP/1.x 404 Not Found';
-
-    if (($volume = $this->volume($target)) == FALSE) {
-      return array('error' => self::$errors[self::ERROR_FILE_NOT_FOUND], 'header' => $h404, 'raw' => TRUE);
-    }
-
-    if (($file = $volume->file($target)) == FALSE) {
-      return array('error' => self::$errors[self::ERROR_FILE_NOT_FOUND], 'header' => $h404, 'raw' => TRUE);
-    }
-
-    if (!$file['read']) {
-      return array('error' => self::$errors[self::ERROR_ACCESS_DENIED], 'header' => $h403, 'raw' => TRUE);
-    }
-
-    if ($volume->driverId() != 'f' && (($fp = $volume->open($target)) == FALSE)) {
-      return array('error' => self::$errors[self::ERROR_FILE_NOT_FOUND], 'header' => $h404, 'raw' => TRUE);
-    }
-
-    $mime = ($download) ? 'application/octet-stream' : $file['mime'];
-
-    $result = array(
-        'volume' => $volume,
-        'pointer' => $fp,
-        'info' => $file,
-        'header' => array(
-            "Content-Type: " . $mime,
-            "Content-Disposition: " . $this->GetContentDisposition($file['name'], $mime, $download),
-            "Content-Location: " . $file['name'],
-            'Content-Transfer-Encoding: binary',
-            "Content-Length: " . $file['size'],
-            "Connection: close"
-        )
-    );
-    
-    $real_path = $this->realpath($target);
-    module_invoke_all('file_download', $volume->drupalpathtouri($real_path));
-    
-    return $result;
-  }
-
-  /**
-   * Generating Content-Disposition HTTP header
-   *
-   * @param  string  $file     Filename
-   * @param  string  $filemime MIME Type
-   * @param  bool    $download Disposition type (true = download file, false = open file in browser)
-   * @return string
-   * @author Dmitry (dio) Levashov, Alexey Sukhotin
-   * */
-  public static function GetContentDisposition($file, $filemime, $download = FALSE) {
-
-    $disp = '';
-    $filename = $file;
-    $ua = $_SERVER["HTTP_USER_AGENT"];
-    $mime = $filemime;
-
-    if ($download) {
-      $disp = 'attachment';
-      $mime = 'application/octet-stream';
-    } else {
-      $disp = preg_match('/^(image|text)/i', $mime)
-              || $mime == 'application/x-shockwave-flash' ? 'inline' : 'attachment';
-    }
-
-    $disp .= '; ';
-
-    if (preg_match("/MSIE ([0-9]{1,}[\.0-9]{0,})/", $ua)) {
-      $filename = rawurlencode($filename);
-      $filename = str_replace("+", "%20", $filename);
-      //$filename = str_replace(" ", "%20", $filename);
-      $disp .= "filename=" . $filename;
-    } elseif (preg_match("/Firefox\/(\d+)/", $ua, $m)) {
-      if ($m[1] >= 8) {
-        $disp .= "filename*=?UTF-8''" . rawurlencode($filename);
-      } else {
-        $disp .= "filename*=\"?UTF-8''" . rawurlencode($filename) . "\";";
-      }
-    } else {
-      $disp .= "filename=" . $filename;
-    }
-
-    return $disp;
-  }
-
-}
+<?php
+/**
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2019, Alexey Sukhotin. All rights reserved.
+ */
+
+/**
+ * @file
+ *
+ * elFinder conenctor class
+ */
+class elFinderDrupal extends elFinder {
+
+  protected $elFinderDrupalLibVersion;
+  protected $elFinderDrupalLibRevision;
+
+  public function __construct($opts) {
+    if (is_callable(array($this, 'version'))) {
+
+      $this->elFinderDrupalLibVersion = floatval($this->version());
+
+      if (isset(elFinder::$ApiVersion)) {
+        $this->elFinderDrupalLibVersion = elFinder::$ApiVersion;
+      }
+
+      if (is_callable(array($this, 'revision'))) {
+        $this->elFinderDrupalLibRevision = $this->revision();
+      }
+
+      if ($this->elFinderDrupalLibVersion == 2.1 && is_callable(array($this, 'revision')) && $this->revision() < 37) {
+        $this->connector_unsupported_error();
+      }
+
+      parent::__construct($opts);
+
+      $this->commands['desc'] = array('target' => TRUE, 'content' => FALSE);
+      $this->commands['owner'] = array('target' => TRUE, 'content' => FALSE);
+      $this->commands['downloadcount'] = array('target' => TRUE);
+
+    } else {
+      $this->connector_unsupported_error();
+    }
+
+  }
+
+  public function connector_unsupported_error() {
+    $this->connector_error(t('Unsupported elFinder library version. Please upgrade.'));
+  }
+
+  public function connector_error($message) {
+    exit(drupal_json_encode(array('error' => array(strip_tags($message)))));
+  }
+
+  /* Overriding search query argument name 'q' since it's already used in Drupal */
+
+  public function commandArgsList($cmd) {
+    $this->commands['search']['elfinder_search_q'] = TRUE;
+    return $this->commandExists($cmd) ? $this->commands[$cmd] : array();
+  }
+
+  protected function search($args) {
+    $q = trim($args['elfinder_search_q']);
+    $mimes = !empty($args['mimes']) && is_array($args['mimes']) ? $args['mimes'] : array();
+    $target = !empty($args['target']) ? $args['target'] : null;
+    $result = array();
+    $errors = array();
+
+    if ($target) {
+      if ($volume = $this->volume($target)) {
+        $result = $volume->search($q, $mimes, $target);
+        $errors = array_merge($errors, $volume->error());
+      }
+    } else {
+      foreach ($this->volumes as $volume) {
+        $result = array_merge($result, $volume->search($q, $mimes));
+        $errors = array_merge($errors, $volume->error());
+      }
+    }
+
+    // Exclude hidden folders from search results.
+    $hidden_folders = variable_get('elfinder_settings_misc_hidden_folders', '');
+    if($hidden_folders) {
+      $hidden_folders = explode(',', $hidden_folders);
+      foreach($result AS $key => $file) {
+        $parts = explode('/', $file['path']);
+        if(in_array($parts[1], $hidden_folders)) {
+          unset($result[$key]);
+        }
+      }
+    }
+
+    $result = array('files' => $result);
+    if ($errors) {
+      $result['warning'] = $errors;
+    }
+    return $result;
+  }
+
+  protected function desc($args) {
+    $target = $args['target'];
+    $desc = $args['content'];
+    $error = array(self::ERROR_UNKNOWN, '#' . $target);
+
+    if (($volume = $this->volume($target)) == FALSE
+      || ($file = $volume->file($target)) == FALSE) {
+      return array('error' => $this->error($error, self::ERROR_FILE_NOT_FOUND));
+    }
+
+    $error[1] = $file['name'];
+
+    if ($volume->driverId() == 'f') {
+      return array('desc' => '');
+    }
+
+    if ($volume->commandDisabled('desc')) {
+      return array('error' => $this->error($error, self::ERROR_ACCESS_DENIED));
+    }
+
+    if (($desc = $volume->desc($target, $desc)) == -1) {
+      return array('error' => $this->error($error, $volume->error()));
+    }
+
+    return array('desc' => $desc);
+  }
+
+  protected function owner($args) {
+    $target = $args['target'];
+
+    $error = array(self::ERROR_UNKNOWN, '#' . $target);
+
+    if (($volume = $this->volume($target)) == FALSE
+      || ($file = $volume->file($target)) == FALSE) {
+      return array('error' => $this->error($error, self::ERROR_FILE_NOT_FOUND));
+    }
+
+    $error[1] = $file['name'];
+
+    if ($volume->driverId() == 'f') {
+      return array('owner' => '');
+    }
+
+    if ($volume->commandDisabled('owner')) {
+      return array('error' => $this->error($error, self::ERROR_ACCESS_DENIED));
+    }
+
+    if (($owner = $volume->owner($target)) == FALSE) {
+      return array('error' => $this->error($error, $volume->error()));
+    }
+
+    return array('owner' => $owner);
+  }
+
+  protected function downloadcount($args) {
+    $target = $args['target'];
+
+    $error = array(self::ERROR_UNKNOWN, '#' . $target);
+
+    if (($volume = $this->volume($target)) == FALSE
+      || ($file = $volume->file($target)) == FALSE) {
+      return array('error' => $this->error($error, self::ERROR_FILE_NOT_FOUND));
+    }
+
+    $error[1] = $file['name'];
+
+    if ($volume->driverId() == 'f') {
+      return array('downloadcount' => '');
+    }
+
+    if ($volume->commandDisabled('downloadcount')) {
+      return array('error' => $this->error($error, self::ERROR_ACCESS_DENIED));
+    }
+
+    if (($downloadcount = $volume->downloadcount($target)) == FALSE) {
+      return array('error' => $this->error($error, $volume->error()));
+    }
+
+    return array('downloadcount' => $downloadcount);
+  }
+
+  /**
+   * Required to output file in browser when volume URL is not set
+   * Return array contains opened file pointer, root itself and required headers
+   *
+   * @param  array  command arguments
+   * @return array
+   * @author Dmitry (dio) Levashov
+   * */
+  protected function file($args) {
+
+    if ($this->elFinderDrupalLibVersion >= 2.1 && $this->elFinderDrupalLibRevision > 38) {
+      return parent::file($args);
+    }
+
+    $target = $args['target'];
+    $download = !empty($args['download']);
+    $h403 = 'HTTP/1.x 403 Access Denied';
+    $h404 = 'HTTP/1.x 404 Not Found';
+
+    if (($volume = $this->volume($target)) == FALSE) {
+      return array('error' => self::$errors[self::ERROR_FILE_NOT_FOUND], 'header' => $h404, 'raw' => TRUE);
+    }
+
+    if (($file = $volume->file($target)) == FALSE) {
+      return array('error' => self::$errors[self::ERROR_FILE_NOT_FOUND], 'header' => $h404, 'raw' => TRUE);
+    }
+
+    if (!$file['read']) {
+      return array('error' => self::$errors[self::ERROR_ACCESS_DENIED], 'header' => $h403, 'raw' => TRUE);
+    }
+
+    if ($volume->driverId() != 'f' && (($fp = $volume->open($target)) == FALSE)) {
+      return array('error' => self::$errors[self::ERROR_FILE_NOT_FOUND], 'header' => $h404, 'raw' => TRUE);
+    }
+
+    $mime = ($download) ? 'application/octet-stream' : $file['mime'];
+
+    $result = array(
+      'volume' => $volume,
+      'pointer' => $fp,
+      'info' => $file,
+      'header' => array(
+        "Content-Type: " . $mime,
+        "Content-Disposition: " . $this->GetContentDisposition($file['name'], $mime, $download),
+        "Content-Location: " . $file['name'],
+        'Content-Transfer-Encoding: binary',
+        "Content-Length: " . $file['size'],
+        "Connection: close"
+      )
+    );
+
+    $real_path = $this->realpath($target);
+    module_invoke_all('file_download', $volume->drupalpathtouri($real_path));
+
+    return $result;
+  }
+
+  /**
+   * Generating Content-Disposition HTTP header
+   *
+   * @param  string $file Filename
+   * @param  string $filemime MIME Type
+   * @param  bool $download Disposition type (true = download file, false = open file in browser)
+   * @return string
+   * @author Dmitry (dio) Levashov, Alexey Sukhotin
+   * */
+  public static function GetContentDisposition($file, $filemime, $download = FALSE) {
+
+    $disp = '';
+    $filename = $file;
+    $ua = $_SERVER["HTTP_USER_AGENT"];
+    $mime = $filemime;
+
+    if ($download) {
+      $disp = 'attachment';
+      $mime = 'application/octet-stream';
+    } else {
+      $disp = preg_match('/^(image|text)/i', $mime)
+      || $mime == 'application/x-shockwave-flash' ? 'inline' : 'attachment';
+    }
+
+    $disp .= '; ';
+
+    if (preg_match("/MSIE ([0-9]{1,}[\.0-9]{0,})/", $ua)) {
+      $filename = rawurlencode($filename);
+      $filename = str_replace("+", "%20", $filename);
+      //$filename = str_replace(" ", "%20", $filename);
+      $disp .= "filename=" . $filename;
+    } elseif (preg_match("/Firefox\/(\d+)/", $ua, $m)) {
+      if ($m[1] >= 8) {
+        $disp .= "filename*=?UTF-8''" . rawurlencode($filename);
+      } else {
+        $disp .= "filename*=\"?UTF-8''" . rawurlencode($filename) . "\";";
+      }
+    } elseif (preg_match("/Chrome\/(\d+)/", $ua, $m)) {
+      $disp .= "filename=\"" . $filename . "\"";
+    } else {
+      $disp .= "filename=" . $filename;
+    }
+
+    return $disp;
+  }
+
+}
+

+ 113 - 107
sites/all/modules/contrib/files/elfinder/inc/elfinder.drupalfs.acl.inc

@@ -1,108 +1,114 @@
-<?php
-/**
- * @file
- * elfinder ACL class
- */
-class elFinderDrupalACL {
-
-  public function fsAccessPublic($attr, $path, $data, $volume) {
-
-    if (strpos(basename($path), '.') === 0 && $attr == 'hidden') {
-      return TRUE;
-    }
-
-    /* Hiding thumbnail folder */
-    if (strstr($path, DIRECTORY_SEPARATOR . variable_get('elfinder_settings_thumbnail_dirname', 'tmb')) && $attr == 'hidden') {
-      return TRUE;
-    }
-
-    // Hide folders hidden by config settings.
-    $f = drupal_realpath("public://") . "/";
-    $folder = str_replace($f, "", $path);
-    $hidden_folder = preg_split("/[\s,]+/", variable_get('elfinder_settings_misc_hidden_folders', ''));
-    if (in_array($folder, $hidden_folder) && $attr == 'hidden') {
-      return TRUE;
-    }
-
-    if (strstr($path, DIRECTORY_SEPARATOR . '.quarantine') && $attr == 'hidden') {
-      return TRUE;
-    }
-
-    if ($attr == 'read') {
-      return TRUE;
-    }
-
-    if ($attr == 'write') {
-      return TRUE;
-    }
-
-    /* if ($attr == 'write' && user_access('write public files')) {
-      return TRUE;
-      }
-
-      if ($attr == 'locked' && !user_access('write public files')) {
-      return TRUE;
-      } */
-
-    return FALSE;
-  }
-
-  public function fsAccessPrivate($attr, $path, $data, $volume) {
-
-    if (strpos(basename($path), '.') === 0 && $attr == 'hidden') {
-      return TRUE;
-    }
-
-    /* Hiding thumbnail folder */
-    if (strstr($path, DIRECTORY_SEPARATOR . variable_get('elfinder_settings_thumbnail_dirname', 'tmb')) && $attr == 'hidden') {
-      return TRUE;
-    }
-
-    if (strstr($path, DIRECTORY_SEPARATOR . '.quarantine') && $attr == 'hidden') {
-      return TRUE;
-    }
-
-    if ($attr == 'read') {
-      return TRUE;
-    }
-
-
-    if ($attr == 'write') {
-      return TRUE;
-    }
-
-    /* if ($attr == 'write' && user_access('write public files')) {
-      return TRUE;
-      }
-
-      if ($attr == 'locked' && !user_access('write public files')) {
-      return TRUE;
-      } */
-
-
-    return FALSE;
-  }
-
-  public function fsAccessUnmanaged($attr, $path, $data, $volume) {
-
-    if (strpos(basename($path), '.') === 0 && $attr == 'hidden') {
-      return TRUE;
-    }
-
-    /* Hiding thumbnail folder */
-    if (strstr($path, DIRECTORY_SEPARATOR . variable_get('elfinder_settings_thumbnail_dirname', 'tmb')) && $attr == 'hidden') {
-      return TRUE;
-    }
-
-    if (strstr($path, DIRECTORY_SEPARATOR . '.quarantine') && $attr == 'hidden') {
-      return TRUE;
-    }
-
-    if ($attr == 'read') {
-      return TRUE;
-    }
-
-    return FALSE;
-  }
-
+<?php
+/**
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
+ */
+
+/**
+ * @file
+ * elfinder ACL class
+ */
+class elFinderDrupalACL {
+
+  public function fsAccessPublic($attr, $path, $data, $volume) {
+
+    if (strpos(basename($path), '.') === 0 && $attr == 'hidden') {
+      return TRUE;
+    }
+
+    /* Hiding thumbnail folder */
+    if (strstr($path, DIRECTORY_SEPARATOR . variable_get('elfinder_settings_thumbnail_dirname', 'tmb')) && $attr == 'hidden') {
+      return TRUE;
+    }
+
+    // Hide folders hidden by config settings.
+    $f = drupal_realpath("public://") . "/";
+    $folder = str_replace($f, "", $path);
+    $hidden_folder = preg_split("/[\s,]+/", variable_get('elfinder_settings_misc_hidden_folders', ''));
+    if (in_array($folder, $hidden_folder) && $attr == 'hidden') {
+      return TRUE;
+    }
+
+    if (strstr($path, DIRECTORY_SEPARATOR . '.quarantine') && $attr == 'hidden') {
+      return TRUE;
+    }
+
+    if ($attr == 'read') {
+      return TRUE;
+    }
+
+    if ($attr == 'write') {
+      return TRUE;
+    }
+
+    /* if ($attr == 'write' && user_access('write public files')) {
+      return TRUE;
+      }
+
+      if ($attr == 'locked' && !user_access('write public files')) {
+      return TRUE;
+      } */
+
+    return FALSE;
+  }
+
+  public function fsAccessPrivate($attr, $path, $data, $volume) {
+
+    if (strpos(basename($path), '.') === 0 && $attr == 'hidden') {
+      return TRUE;
+    }
+
+    /* Hiding thumbnail folder */
+    if (strstr($path, DIRECTORY_SEPARATOR . variable_get('elfinder_settings_thumbnail_dirname', 'tmb')) && $attr == 'hidden') {
+      return TRUE;
+    }
+
+    if (strstr($path, DIRECTORY_SEPARATOR . '.quarantine') && $attr == 'hidden') {
+      return TRUE;
+    }
+
+    if ($attr == 'read') {
+      return TRUE;
+    }
+
+
+    if ($attr == 'write') {
+      return TRUE;
+    }
+
+    /* if ($attr == 'write' && user_access('write public files')) {
+      return TRUE;
+      }
+
+      if ($attr == 'locked' && !user_access('write public files')) {
+      return TRUE;
+      } */
+
+
+    return FALSE;
+  }
+
+  public function fsAccessUnmanaged($attr, $path, $data, $volume) {
+
+    if (strpos(basename($path), '.') === 0 && $attr == 'hidden') {
+      return TRUE;
+    }
+
+    /* Hiding thumbnail folder */
+    if (strstr($path, DIRECTORY_SEPARATOR . variable_get('elfinder_settings_thumbnail_dirname', 'tmb')) && $attr == 'hidden') {
+      return TRUE;
+    }
+
+    if (strstr($path, DIRECTORY_SEPARATOR . '.quarantine') && $attr == 'hidden') {
+      return TRUE;
+    }
+
+    if ($attr == 'read') {
+      return TRUE;
+    }
+
+    return FALSE;
+  }
+
 }

+ 14 - 6
sites/all/modules/contrib/files/elfinder/inc/elfinder.drupalfs.driver.inc

@@ -40,15 +40,16 @@ class elFinderVolumeDrupal extends elFinderVolumeLocalFileSystem {
     $pvtpath = drupal_realpath('private://');
     $pubpath = drupal_realpath('public://');
     $tmppath = drupal_realpath('temporary://');
+    $final_path = DIRECTORY_SEPARATOR !== '/' ? str_replace(DIRECTORY_SEPARATOR, '/', $path) : $path;
 
     $uri = '';
 
-    if (strpos($path, $pvtpath) === 0) {
-      $uri = 'private://' . substr($path, strlen($pvtpath) + 1);
-    } elseif (strpos($path, $tmppath) === 0) {
-      $uri = 'temporary://' . substr($path, strlen($tmppath) + 1);
+    if (strpos($final_path, $pvtpath) === 0) {
+      $uri = 'private://' . substr($final_path, strlen($pvtpath) + 1);
+    } elseif (strpos($final_path, $tmppath) === 0) {
+      $uri = 'temporary://' . substr($final_path, strlen($tmppath) + 1);
     } else {
-      $uri = 'public://' . substr($path, strlen($pubpath) + 1);
+      $uri = 'public://' . substr($final_path, strlen($pubpath) + 1);
     }
 
     return @file_stream_wrapper_uri_normalize($uri);
@@ -357,7 +358,8 @@ class elFinderVolumeDrupal extends elFinderVolumeLocalFileSystem {
         $this->setError(strip_tags(implode(' ', $validation_errors)));
         return FALSE;
       }
-    } else {
+    }
+    else {
       watchdog('elfinder', 'File upload "' . $name . '" not found in $_FILES');
     }
     return TRUE;
@@ -405,6 +407,12 @@ class elFinderVolumeDrupal extends elFinderVolumeLocalFileSystem {
     return FALSE;
   }
 
+  public static function stat_corrector(&$stat, $path, $statOwner, $volumeDriveInstance) {
+    if (method_exists($volumeDriveInstance, 'owner')) {
+      $stat['owner'] = $volumeDriveInstance->owner($volumeDriveInstance->encode($path));
+    }
+  }
+
   public function desc($target, $newdesc = NULL) {
     $path = $this->decode($target);
 

+ 380 - 205
sites/all/modules/contrib/files/elfinder/js/elfinder.callback.js

@@ -1,239 +1,414 @@
+/*
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
+ */
+
 // $Id: elfinder.callback.js 106 2011-02-26 08:19:56Z ph0enix $
 
 (function($) {
 
-/**
- * @class  elFinder command "search"
- * Find files
- *
- * @author Dmitry (dio) Levashov
- **/
-elFinder.prototype.commands.search = function() {
-	this.title          = 'Find files';
-	this.options        = {ui : 'searchbutton'}
-	this.alwaysEnabled  = true;
-	this.updateOnSelect = false;
-	
-	/**
-	 * Return command status.
-	 * Search does not support old api.
-	 *
-	 * @return Number
-	 **/
-	this.getstate = function() {
-		return 0;
-	}
-	
-	/**
-	 * Send search request to backend.
-	 *
-	 * @param  String  search string
-	 * @return $.Deferred
-	 **/
-	this.exec = function(q) {
-		var fm = this.fm;
-		
-		if (typeof(q) == 'string' && q) {
-			return fm.request({
-				data   : {cmd : 'search', elfinder_search_q : q},
-				notify : {type : 'search', cnt : 1, hideCnt : true}
-			});
-		}
-		fm.getUI('toolbar').find('.'+fm.res('class', 'searchbtn')+' :text').focus();
-		return $.Deferred().reject();
-	}
-
-}
-
-elFinder.prototype.commands.test134 = function() {
-	this.title          = 'Test Command';
-	//this.options        = {ui : 'uploadbutton'}
-	this.alwaysEnabled  = true;
-	this.updateOnSelect = false;
-	this.state = 0;
-	
-	this.getstate = function() {
-		return 0;
-	}
-	
-	/**
-	 * Send search request to backend.
-	 *
-	 * @param  String  search string
-	 * @return $.Deferred
-	 **/
-	this.exec = function(q) {
-		var fm = this.fm;
-    
-    alert(Drupal.t('test command. arg=') + q);
-		
-		return $.Deferred().reject();
-	}
-
-}
-
-
-$().ready(function() {
-  var uiopts = elFinder.prototype._options.uiOptions.toolbar;
-
-  var newOpts = new Array();
-
-  var disabledCommands = Drupal.settings.elfinder.disabledCommands;
-  
-  
-  for (var i in uiopts) {
-    var optsGroup = uiopts[i];
-    var newOptsGroup = Array();
-
-    for (var j in optsGroup) {
-      var found = false;
-      for (var k in disabledCommands) {
-        if (disabledCommands[k] == optsGroup[j]) {
-          found = true;
-        }
-      }
-    
-      if (found == false) {
-        newOptsGroup.push(optsGroup[j]);
-      }
-  
-    }
-    
-    if (i == 0) {
-      newOptsGroup.push('up');
-    }
-    
-    if (newOptsGroup.length >= 1) {
-      newOpts.push(newOptsGroup);
+  /**
+   * @class  elFinder command "search"
+   * Find files
+   *
+   * @author Dmitry (dio) Levashov
+   **/
+  elFinder.prototype.commands.search = function() {
+    this.title = 'Find files';
+    this.options = {ui: 'searchbutton'}
+    this.alwaysEnabled = true;
+    this.updateOnSelect = false;
+
+    /**
+     * Return command status.
+     * Search does not support old api.
+     *
+     * @return Number
+     **/
+    this.getstate = function() {
+      return 0;
     }
-  }
-  
-  var contextMenuCwd = elFinder.prototype._options.contextmenu.cwd;
-  var contextMenuFiles = elFinder.prototype._options.contextmenu.files;
-  var contextMenuNavbar = elFinder.prototype._options.contextmenu.navbar;
-  
-  var newContextMenuCwd = Array();
-  var newContextMenuFiles = Array();
-  var newContextMenuNavbar = Array();
-  
-  for (var i in contextMenuCwd) {
-    var found = false;
-    for (var k in disabledCommands) {
-      if (disabledCommands[k] == contextMenuCwd[i]) {
-       found = true;
+
+    /**
+     * Send search request to backend.
+     *
+     * @param  String  search string
+     * @return $.Deferred
+     **/
+    this.exec = function(q) {
+      var fm = this.fm;
+
+      if (typeof(q) == 'string' && q) {
+        return fm.request({
+          data: {cmd: 'search', elfinder_search_q: q},
+          notify: {type: 'search', cnt: 1, hideCnt: true}
+        });
       }
+      fm.getUI('toolbar').find('.' + fm.res('class', 'searchbtn') + ' :text').focus();
+      return $.Deferred().reject();
     }
-    
-    if (found == false && contextMenuCwd[i] != '|') {
-      newContextMenuCwd.push(contextMenuCwd[i]);
-    }
+
   }
-  
-  for (var i in contextMenuFiles) {
-    var found = false;
-    for (var k in disabledCommands) {
-      if (disabledCommands[k] == contextMenuFiles[i]) {
-       found = true;
-      }
+
+  elFinder.prototype.commands.test134 = function() {
+    this.title = 'Test Command';
+    //this.options        = {ui : 'uploadbutton'}
+    this.alwaysEnabled = true;
+    this.updateOnSelect = false;
+    this.state = 0;
+
+    this.getstate = function() {
+      return 0;
     }
-    
-    if (found == false && contextMenuFiles[i] != '|') {
-      newContextMenuFiles.push(contextMenuFiles[i]);
+
+    /**
+     * Send search request to backend.
+     *
+     * @param  String  search string
+     * @return $.Deferred
+     **/
+    this.exec = function(q) {
+      var fm = this.fm;
+
+      alert(Drupal.t('test command. arg=') + q);
+
+      return $.Deferred().reject();
     }
+
   }
-  
-  for (var i in contextMenuNavbar) {
-    var found = false;
-    for (var k in disabledCommands) {
-      if (disabledCommands[k] == contextMenuNavbar[i]) {
-       found = true;
+
+
+  $().ready(function() {
+    var uiopts = elFinder.prototype._options.uiOptions.toolbar;
+
+    var newOpts = new Array();
+
+    var disabledCommands = Drupal.settings.elfinder.disabledCommands;
+
+
+    for (var i in uiopts) {
+      var optsGroup = uiopts[i];
+      var newOptsGroup = Array();
+
+
+      for (var j in optsGroup) {
+        var found = false;
+        for (var k in disabledCommands) {
+          if (disabledCommands[k] == optsGroup[j]) {
+            found = true;
+          }
+        }
+
+        if (found == false) {
+          newOptsGroup.push(optsGroup[j]);
+        }
+
+      }
+
+      if (i == 0) {
+        newOptsGroup.push('up');
+      }
+
+      if (newOptsGroup.length >= 1) {
+        newOpts.push(newOptsGroup);
       }
     }
-    
-    if (found == false && contextMenuNavbar[i] != '|') {
-      newContextMenuNavbar.push(contextMenuNavbar[i]);
-    }
-  }
-  elFinder.prototype._options.uiOptions.toolbar = newOpts;
-  elFinder.prototype._options.contextmenu.cwd = newContextMenuCwd;
-  elFinder.prototype._options.contextmenu.files = newContextMenuFiles;
-  elFinder.prototype._options.contextmenu.navbar = newContextMenuNavbar;
 
-});
+    /*elFinder.prototype._options.contextmenu.files.push('|');
+    elFinder.prototype._options.contextmenu.files.push('rename');  */
 
+    var contextMenuCwd = elFinder.prototype._options.contextmenu.cwd;
+    var contextMenuFiles = elFinder.prototype._options.contextmenu.files;
+    var contextMenuNavbar = elFinder.prototype._options.contextmenu.navbar;
 
+    var newContextMenuCwd = Array();
+    var newContextMenuFiles = Array();
+    var newContextMenuNavbar = Array();
 
-$().ready(function() {
-  if (Drupal.settings.elfinder) {
-    var editorApp = Drupal.settings.elfinder.editorApp;
+    for (var i in contextMenuCwd) {
+      var found = false;
+      for (var k in disabledCommands) {
+        if (disabledCommands[k] == contextMenuCwd[i]) {
+          found = true;
+        }
+      }
 
-    var elfinderOpts = {
-      url : Drupal.settings.elfinder.connectorUrl,
-      lang : Drupal.settings.elfinder.langCode,
-      rememberLastDir : Drupal.settings.elfinder.rememberLastDir,
-      closeOnEditorCallback : false,
-      customData : {token: Drupal.settings.elfinder.token}
+      if (found == false && contextMenuCwd[i] != '|') {
+        newContextMenuCwd.push(contextMenuCwd[i]);
+      }
     }
-	
-    /* Pushing all settings to elFinder */
-    $.extend(elfinderOpts, Drupal.settings.elfinder);
-    
-    if (editorApp && typeof window[Drupal.settings.elfinder.editorCallback] == 'function') {
-      elfinderOpts.editorCallback = window[Drupal.settings.elfinder.editorCallback];
+
+    for (var i in contextMenuFiles) {
+      var found = false;
+      for (var k in disabledCommands) {
+        if (disabledCommands[k] == contextMenuFiles[i]) {
+          found = true;
+        }
+      }
+
+      if (found == false && contextMenuFiles[i] != '|') {
+        newContextMenuFiles.push(contextMenuFiles[i]);
+      }
     }
 
-    if (editorApp && typeof window[Drupal.settings.elfinder.editorCallback] == 'function') {
-      elfinderOpts.getFileCallback = window[Drupal.settings.elfinder.editorCallback];
+    for (var i in contextMenuNavbar) {
+      var found = false;
+      for (var k in disabledCommands) {
+        if (disabledCommands[k] == contextMenuNavbar[i]) {
+          found = true;
+        }
+      }
+
+      if (found == false && contextMenuNavbar[i] != '|') {
+        newContextMenuNavbar.push(contextMenuNavbar[i]);
+      }
     }
-    
-    if (elfinderOpts.api21) {
-        //alert('api21');
+    elFinder.prototype._options.uiOptions.toolbar = newOpts;
+    elFinder.prototype._options.contextmenu.cwd = newContextMenuCwd;
+    elFinder.prototype._options.contextmenu.files = newContextMenuFiles;
+    elFinder.prototype._options.contextmenu.navbar = newContextMenuNavbar;
+
+    //elFinder.prototype._options.ui.push('mouseover');
+  });
+
+
+  $().ready(function() {
+    if (Drupal.settings.elfinder) {
+      var editorApp = Drupal.settings.elfinder.editorApp;
+
+      var elfinderOpts = {
+        url: Drupal.settings.elfinder.connectorUrl,
+        lang: Drupal.settings.elfinder.langCode,
+        rememberLastDir: Drupal.settings.elfinder.rememberLastDir,
+        closeOnEditorCallback: false,
+        customData: {token: Drupal.settings.elfinder.token},
+        commandsOptions_: {}
+      }
+
+      // help tab rendering issues in admin theme
+      if (Drupal.settings.elfinder.browserMode != 'default' && elFinder.prototype._options.commandsOptions.help) {
+        final_options = [];
+
+        for (var i in elFinder.prototype._options.commandsOptions.help.view) {
+          var option = elFinder.prototype._options.commandsOptions.help.view[i];
+          if (option != 'help') {
+            final_options.push(option);
+          }
+        }
+
+        elFinder.prototype._options.commandsOptions.help['view'] = final_options;
+      }
+
+      /* Pushing all settings to elFinder */
+      $.extend(elfinderOpts, Drupal.settings.elfinder);
+
+      if (editorApp && typeof window[Drupal.settings.elfinder.editorCallback] == 'function') {
+        elfinderOpts.editorCallback = window[Drupal.settings.elfinder.editorCallback];
+      }
+
+      if (editorApp && typeof window[Drupal.settings.elfinder.editorCallback] == 'function') {
+        elfinderOpts.getFileCallback = window[Drupal.settings.elfinder.editorCallback];
+      }
+
+      if (elfinderOpts.api21) {
         console.log('2.1 api');
-      elfinderOpts['commandsOptions'] = {
-              info: {
-        // Key is the same as your command name
-      	desc : {
-          // Field label
-          label : 'Description1',
-          
-          // HTML Template
-          tpl : '<div class="elfinder-info-desc"><span class="elfinder-info-spinner"></span></div>',
-          
-          // Action that sends the request to the server and get the description
-          action : function(file, filemanager, dialog) {
-            // Use the @filemanager object to issue a request
-            filemanager.request({
-              // Issuing the custom 'desc' command, targetting the selected file
-              data : { cmd: 'desc', target: file.hash, },
-              preventDefault: true,
-            })
-            // If the request fails, populate the field with 'Unknown'
-            .fail(function() {
-              dialog.find('.elfinder-info-desc').html(filemanager.i18n('unknown'));
-            })
-            // When the request is successful, show the description
-            .done(function(data) {
-              dialog.find('.elfinder-info-desc').html(data.desc);
+        elfinderOpts['commandsOptions']['info'] = {
+          custom: {}
+
+        };
+        
+/*        elfinderOpts['commandsOptions']['quicklook'] = {
+          officeOnlineMimes : ['application/msword', 'application/vnd.ms-word', 'application/vnd.ms-excel', 'application/vnd.ms-powerpoint', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'],
+        }*/
+
+        var disabledCommands = Drupal.settings.elfinder.disabledCommands,
+          viewDesc = $.inArray('desc', disabledCommands) == -1 ? true : false,
+          editDesc = $.inArray('editdesc', disabledCommands) == -1 ? true : false,
+          viewOwner = $.inArray('owner', disabledCommands) == -1 ? true : false,
+          viewDownloads = $.inArray('downloadcount', disabledCommands) == -1 ? true : false;
+
+
+        if (viewDesc || editDesc) {
+
+          // Key is the same as your command name
+          elfinderOpts['commandsOptions']['info']['custom']['desc'] = {
+            // Field label
+            label: Drupal.t('Description'),
+
+            // HTML Template
+            tpl: '<div class="elfinder-info-desc"><span class="elfinder-info-spinner"></span></div><div class="elfinder-info-save"></div>',
+
+            // Action that sends the request to the server and get the description
+            action: function(file, filemanager, dialog) {
+              console.log('desc action');
+
+              console.log('fm');
+              console.log(file.mime);
+
+              // Use the @filemanager object to issue a request
+              filemanager.request({
+                // Issuing the custom 'desc' command, targetting the selected file
+                data: {cmd: 'desc', target: file.hash,},
+                preventDefault: true,
+              })
+              // If the request fails, populate the field with 'Unknown'
+                .fail(function() {
+                  console.log('desc fail');
+                  dialog.find('.elfinder-info-desc').html(filemanager.i18n('unknown'));
+                })
+                // When the request is successful, show the description
+                .done(function(data) {
+                  console.log('desc done');
+                  dialog.find('.elfinder-info-desc').html(data.desc);
+
+                  if (editDesc) {
+                    //filemanager.lockfiles({files : [file.hash]})
+                    dialog.find('.elfinder-info-desc').html('<textarea cols="20" rows="5" id="elfinder-fm-file-desc" class="ui-widget ui-widget-content">' + data.desc + '</textarea>');
+
+                    $('.elfinder-info-save').append('<input type="button" id="elfinder-fm-file-desc-btn-save" class="ui-widget ui-button" value="' + filemanager.i18n('btnSave') + '" />');
+
+                    var btnSave = $('#elfinder-fm-file-desc-btn-save', dialog).button();
+                    console.log(btnSave);
+
+                    btnSave.click(function() {
+                      filemanager.lockfiles({files: [file.hash]});
+                      filemanager.request({
+                        data: {cmd: 'desc', target: file.hash, content: $('#elfinder-fm-file-desc').val()},
+                        notify: {type: 'desc', cnt: 1}
+                      })
+                        .always(function() {
+                          filemanager.unlockfiles({files: [file.hash]});
+                        });
+                    });
+
+                  }
+
+
+                });
+            }
+          };
+
+        }
+
+
+        if (viewOwner) {
+          // Key is the same as your command name
+          elfinderOpts['commandsOptions']['info']['custom']['owner'] = {
+            // Field label
+            label: Drupal.t('Owner'),
+
+            // HTML Template
+            tpl: '<div class="elfinder-info-owner"><span class="elfinder-info-spinner"></span></div>',
+
+            // Action that sends the request to the server and get the description
+            action: function(file, filemanager, dialog) {
+              console.log('owner action');
+
+              // Use the @filemanager object to issue a request
+              filemanager.request({
+                // Issuing the custom 'desc' command, targetting the selected file
+                data: {cmd: 'owner', target: file.hash,},
+                preventDefault: true,
+              })
+              // If the request fails, populate the field with 'Unknown'
+                .fail(function() {
+                  console.log('owner fail');
+                  dialog.find('.elfinder-info-owner').html(filemanager.i18n('unknown'));
+                })
+                // When the request is successful, show the description
+                .done(function(data) {
+                  console.log('owner done');
+                  dialog.find('.elfinder-info-owner').html(data.owner);
+                });
+            }
+          };
+
+          elFinder.prototype._options.uiOptions.cwd.listView.columns.push('owner');
+          elFinder.prototype._options.uiOptions.cwd.listView.columnsCustomName['owner'] = Drupal.t('Owner');
+
+        }
+
+        if (viewDownloads) {
+          elfinderOpts['commandsOptions']['info']['custom']['downloadcount'] = {
+            // Field label
+            label: Drupal.t('Downloads'),
+
+            // HTML Template
+            tpl: '<div class="elfinder-info-downloadcount"><span class="elfinder-info-spinner"></span></div>',
+
+            // Action that sends the request to the server and get the description
+            action: function(file, filemanager, dialog) {
+              // Use the @filemanager object to issue a request
+              filemanager.request({
+                // Issuing the custom 'desc' command, targetting the selected file
+                data: {cmd: 'downloadcount', target: file.hash,},
+                preventDefault: true,
+              })
+              // If the request fails, populate the field with 'Unknown'
+                .fail(function() {
+                  dialog.find('.elfinder-info-downloadcount').html(0);
+                })
+                // When the request is successful, show the description
+                .done(function(data) {
+                  dialog.find('.elfinder-info-downloadcount').html(data.desc);
+                });
+            }
+          };
+
+        }
+
+//        console.log(elfinderOpts);
+      }
+
+      var fm = $('#finder').elfinder(elfinderOpts);
+
+      var instance = fm.elfinder('instance');
+
+//    console.log(typeof instance == 'object' && typeof instance.toast == 'function');
+
+      if (typeof instance == 'object' && typeof instance.toast == 'function') {
+        instance.bind('load', function(event) {
+          var messages = '#elfinder-messages .messages';
+          $(messages).each(function(index, value) {
+            var mode = 'info';
+            if ($(value).hasClass('warning')) {
+              mode = 'warning';
+            } else if ($(value).hasClass('error')) {
+              mode = 'error';
+            }
+
+            instance.toast({
+              msg: $(value).html(),
+              hideDuration: 500,
+              showDuration: 300,
+              timeOut: 1000,
+              mode: mode
             });
-          },
-        },
+
+          });
+        });
+      } else {
+        $('#elfinder-messages').addClass('legacy');
       }
-      };
+      //$('#finder').toast({msg: '123'});
 
-    }
-      
-    $('#finder').elfinder(elfinderOpts);
+      var h;
+
+      if (elfinderOpts.browserMode != 'backend') {
+        h = ($(window).height());
+      } else {
+        h = ($('#page').height());
+      }
 
-    if(elfinderOpts.browserMode != 'backend') {
-      // If this is a popup, add an event so that elfinder fills the window.
       $(window).resize(function() {
-        var h = ($(window).height());
-        if($('#finder').height() != h) {
+        if ($('#finder').height() != h) {
           $('#finder').height(h).resize();
         }
       });
+
+      $(window).trigger('resize');
     }
-  }
-});
+  });
 
 })(jQuery);

File diff suppressed because it is too large
+ 2 - 0
sites/all/modules/contrib/files/elfinder/js/elfinder.jquery-ui.legacy.min.js


File diff suppressed because it is too large
+ 1 - 1
sites/all/modules/contrib/files/elfinder/js/elfinder.jquery-ui.min.js


File diff suppressed because it is too large
+ 1 - 0
sites/all/modules/contrib/files/elfinder/js/elfinder.jquery.legacy.min.js


File diff suppressed because it is too large
+ 0 - 1
sites/all/modules/contrib/files/elfinder/js/elfinder.jquery.min.js


+ 6 - 0
sites/all/modules/contrib/files/elfinder/js/elfinder.wysiwyg.init.js

@@ -1,3 +1,9 @@
+/*
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
+ */
+
 Drupal.elfinder = {
   editor: {}
 

+ 6 - 0
sites/all/modules/contrib/files/elfinder/js/helper.js

@@ -1,3 +1,9 @@
+/*
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
+ */
+
 // $Id: helper.js 100 2011-02-20 19:14:25Z ph0enix $
 
 Drupal.elfinder = {

+ 260 - 254
sites/all/modules/contrib/files/elfinder/js/info.js

@@ -1,84 +1,90 @@
+/*
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
+ */
+
 "use strict";
 /**
- * @class elFinder command "info". 
+ * @class elFinder command "info".
  * Display dialog with file properties.
  *
  * @author Dmitry (dio) Levashov, dio@std42.ru
  **/
- 
+
 (function($) {
 
-elFinder.prototype.commands.info = function() {
-	var m   = 'msg',
-		fm  = this.fm,
-		spclass = 'elfinder-info-spinner',
-		msg = {
-			calc     : fm.i18n('calc'),
-			size     : fm.i18n('size'),
-			unknown  : fm.i18n('unknown'),
-			path     : fm.i18n('path'),
-			aliasfor : fm.i18n('aliasfor'),
-			modify   : fm.i18n('modify'),
-			perms    : fm.i18n('perms'),
-			locked   : fm.i18n('locked'),
-			dim      : fm.i18n('dim'),
-			kind     : fm.i18n('kind'),
-			files    : fm.i18n('files'),
-			folders  : fm.i18n('folders'),
-			items    : fm.i18n('items'),
-			yes      : fm.i18n('yes'),
-			no       : fm.i18n('no'),
-			link     : fm.i18n('link'),
-      owner    : fm.i18n('owner'),
-      desc     : fm.i18n('description'),
-      downloads: fm.i18n('downloads')
-		};
-		
-	this.tpl = {
-		main       : '<div class="ui-helper-clearfix elfinder-info-title"><span class="elfinder-cwd-icon {class} ui-corner-all"/>{title}</div><table class="elfinder-info-tb">{content}</table>',
-		itemTitle  : '<strong>{name}</strong><span class="elfinder-info-kind">{kind}</span>',
-		groupTitle : '<strong>{items}: {num}</strong>',
-		row        : '<tr><td>{label} : </td><td>{value}</td></tr>',
-		spinner    : '<span>{text}</span> <span class="'+spclass+' '+spclass+'-'+'{id}"/>'
-	}
-	
-	this.alwaysEnabled = true;
-	this.updateOnSelect = false;
-	this.shortcuts = [{
-		pattern     : 'ctrl+i'
-	}];
-	
-	this.init = function() {
-		$.each(msg, function(k, v) {
-			msg[k] = fm.i18n(v);
-		});
-	}
-	
-	this.getstate = function() {
-		return 0;
-	}
-	
-	this.exec = function(hashes) {
-
-		var self    = this,
-			fm      = this.fm,
-			tpl     = this.tpl,
-			row     = tpl.row,
-			files   = this.files(hashes),
-			cnt     = files.length,
-			content = [],
-			view    = tpl.main,
-			l       = '{label}',
-			v       = '{value}',
-			opts    = {
-				title : this.title,
-				width : 'auto',
-        modal : true,
+  elFinder.prototype.commands.info = function() {
+    var m = 'msg',
+      fm = this.fm,
+      spclass = 'elfinder-info-spinner',
+      msg = {
+        calc: fm.i18n('calc'),
+        size: fm.i18n('size'),
+        unknown: fm.i18n('unknown'),
+        path: fm.i18n('path'),
+        aliasfor: fm.i18n('aliasfor'),
+        modify: fm.i18n('modify'),
+        perms: fm.i18n('perms'),
+        locked: fm.i18n('locked'),
+        dim: fm.i18n('dim'),
+        kind: fm.i18n('kind'),
+        files: fm.i18n('files'),
+        folders: fm.i18n('folders'),
+        items: fm.i18n('items'),
+        yes: fm.i18n('yes'),
+        no: fm.i18n('no'),
+        link: fm.i18n('link'),
+        owner: fm.i18n('owner'),
+        desc: fm.i18n('description'),
+        downloads: fm.i18n('downloads')
+      };
+
+    this.tpl = {
+      main: '<div class="ui-helper-clearfix elfinder-info-title"><span class="elfinder-cwd-icon {class} ui-corner-all"/>{title}</div><table class="elfinder-info-tb">{content}</table>',
+      itemTitle: '<strong>{name}</strong><span class="elfinder-info-kind">{kind}</span>',
+      groupTitle: '<strong>{items}: {num}</strong>',
+      row: '<tr><td>{label} : </td><td>{value}</td></tr>',
+      spinner: '<span>{text}</span> <span class="' + spclass + ' ' + spclass + '-' + '{id}"/>'
+    }
+
+    this.alwaysEnabled = true;
+    this.updateOnSelect = false;
+    this.shortcuts = [{
+      pattern: 'ctrl+i'
+    }];
+
+    this.init = function() {
+      $.each(msg, function(k, v) {
+        msg[k] = fm.i18n(v);
+      });
+    }
+
+    this.getstate = function() {
+      return 0;
+    }
+
+    this.exec = function(hashes) {
+
+      var self = this,
+        fm = this.fm,
+        tpl = this.tpl,
+        row = tpl.row,
+        files = this.files(hashes),
+        cnt = files.length,
+        content = [],
+        view = tpl.main,
+        l = '{label}',
+        v = '{value}',
+        opts = {
+          title: this.title,
+          width: 'auto',
+          modal: true,
           close: function() {
             $(this).elfinderdialog('destroy');
           }
-			},
-			count = [],
+        },
+        count = [],
         replSpinner = function(msg) {
           dialog.find('.' + spclass).parent().text(msg);
         },
@@ -88,208 +94,208 @@ elFinder.prototype.commands.info = function() {
         id = fm.namespace + '-info-' + $.map(files, function(f) {
           return f.hash
         }).join('-'),
-			dialog = fm.getUI().find('#'+id), 
-			size, tmb, file, title, dcnt;
-      
-    var disabledCommands = Drupal.settings.elfinder.disabledCommands,
+        dialog = fm.getUI().find('#' + id),
+        size, tmb, file, title, dcnt;
+
+      var disabledCommands = Drupal.settings.elfinder.disabledCommands,
         viewDesc = $.inArray('desc', disabledCommands) == -1 ? true : false,
         editDesc = $.inArray('editdesc', disabledCommands) == -1 ? true : false,
         viewOwner = $.inArray('owner', disabledCommands) == -1 ? true : false,
         viewDownloads = $.inArray('downloadcount', disabledCommands) == -1 ? true : false;
-			
-		if (!cnt) {
-			return $.Deferred().reject();
-		}
-			
-		if (dialog.length) {
-			dialog.elfinderdialog('toTop');
-			return $.Deferred().resolve();
-		}
-		
-			
-		if (cnt == 1) {
-			file  = files[0];
-			view  = view.replace('{class}', fm.mime2class(file.mime));
-			title = tpl.itemTitle.replace('{name}', file.name).replace('{kind}', fm.mime2kind(file));
-
-			if (file.tmb) {
-				tmb = fm.option('tmbUrl')+file.tmb;
-			}
-			
-			if (!file.read) {
-				size = msg.unknown;
-			} else if (file.mime != 'directory' || file.alias) {
-				size = fm.formatSize(file.size);
-			} else {
-        /* adding spinner id to separate field updates */
-				size = tpl.spinner.replace('{text}', msg.calc).replace('{id}', 'size');
-				count.push(file.hash);
-			}
-			
-			content.push(row.replace(l, msg.size).replace(v, size));
-			file.alias && content.push(row.replace(l, msg.aliasfor).replace(v, file.alias));
-			content.push(row.replace(l, msg.path).replace(v, fm.escape(fm.path(file.hash))));
-			file.read && content.push(row.replace(l, msg.link).replace(v,  '<a href="'+fm.url(file.hash)+'" target="_blank">'+file.name+'</a>'));
-			
-			if (file.dim) { // old api
-				content.push(row.replace(l, msg.dim).replace(v, file.dim));
-			} else if (file.mime.indexOf('image') !== -1) {
-				content.push(row.replace(l, msg.dim).replace(v, tpl.spinner.replace('{text}', msg.calc).replace('{id}', 'dim')));
-				fm.request({
-					data : {cmd : 'dim', target : file.hash},
-					preventDefault : true
-				})
-				.fail(function() {
-					replSpinnerById(msg.unknown, 'dim');
-				})
-				.done(function(data) {
-					replSpinnerById(data.dim || msg.unknown, 'dim');
-				});
-			}
-			
-			content.push(row.replace(l, msg.modify).replace(v, fm.formatDate(file)));
-			content.push(row.replace(l, msg.perms).replace(v, fm.formatPermissions(file)));
-			content.push(row.replace(l, msg.locked).replace(v, file.locked ? msg.yes : msg.no));
-      
-      /* Don't show fields if command not allowed */
-      if (viewOwner) {
-				content.push(row.replace(l, Drupal.t('Owner')).replace(v, tpl.spinner.replace('{text}', msg.calc).replace('{id}', 'owner')));
-        
-				fm.request({
-					data : {cmd : 'owner', target : file.hash},
-					preventDefault : true
-				})
-				.fail(function() {
-					replSpinnerById(msg.unknown, 'owner');
-				})
-				.done(function(data) {
-					replSpinnerById(data.owner || msg.unknown, 'owner');
-				});
+
+      if (!cnt) {
+        return $.Deferred().reject();
       }
-      
-      /* Don't show fields if command not allowed */
-      if (viewDownloads) {
-        content.push(row.replace(l, Drupal.t('Downloads')).replace(v, tpl.spinner.replace('{text}', msg.calc).replace('{id}', 'downloads')));
-        
-				fm.request({
-					data : {cmd : 'downloadcount', target : file.hash},
-					preventDefault : true
-				})
-				.fail(function() {
-					replSpinnerById(msg.unknown, 'downloads');
-				})
-				.done(function(data) {
-					replSpinnerById(data.downloadcount || msg.unknown, 'downloads');
-				});
+
+      if (dialog.length) {
+        dialog.elfinderdialog('toTop');
+        return $.Deferred().resolve();
       }
-      
-      /* Don't show fields if command not allowed */
-      if (viewDesc || editDesc) {
-      
-        var desc = '<div id="elfinder-fm-file-desc">' + msg.calc + '</div>';
-        
-        if (editDesc)  {
-      
-          desc  = '<textarea cols="20" rows="5" id="elfinder-fm-file-desc" class="ui-widget ui-widget-content" disabled="true" >' + msg.calc + '</textarea><input type="button" id="elfinder-fm-file-desc-btn-save" value="' + fm.i18n('btnSave') + '" />';
+
+
+      if (cnt == 1) {
+        file = files[0];
+        view = view.replace('{class}', fm.mime2class(file.mime));
+        title = tpl.itemTitle.replace('{name}', file.name).replace('{kind}', fm.mime2kind(file));
+
+        if (file.tmb) {
+          tmb = fm.option('tmbUrl') + file.tmb;
         }
 
-        content.push(row.replace(l, Drupal.t('Description')).replace(v , desc));
-        
-				fm.request({
-					data : {cmd : 'desc', target : file.hash},
-					preventDefault : true
-				})
-				.done(function(data) {
-          var fieldDesc = dialog.find('#elfinder-fm-file-desc');
-          
-           if (editDesc)  {
-            fieldDesc.val(data.desc || '');
-            fieldDesc.removeAttr('disabled');
-           } else {
-            fieldDesc.empty();
-            fieldDesc.html(data.desc || '');
-           }
-				});
-        
-      }
-      
-		} else {
-			view  = view.replace('{class}', 'elfinder-cwd-icon-group');
-			title = tpl.groupTitle.replace('{items}', msg.items).replace('{num}', cnt);
+        if (!file.read) {
+          size = msg.unknown;
+        } else if (file.mime != 'directory' || file.alias) {
+          size = fm.formatSize(file.size);
+        } else {
+          /* adding spinner id to separate field updates */
+          size = tpl.spinner.replace('{text}', msg.calc).replace('{id}', 'size');
+          count.push(file.hash);
+        }
+
+        content.push(row.replace(l, msg.size).replace(v, size));
+        file.alias && content.push(row.replace(l, msg.aliasfor).replace(v, file.alias));
+        content.push(row.replace(l, msg.path).replace(v, fm.escape(fm.path(file.hash))));
+        file.read && content.push(row.replace(l, msg.link).replace(v, '<a href="' + fm.url(file.hash) + '" target="_blank">' + file.name + '</a>'));
+
+        if (file.dim) { // old api
+          content.push(row.replace(l, msg.dim).replace(v, file.dim));
+        } else if (file.mime.indexOf('image') !== -1) {
+          content.push(row.replace(l, msg.dim).replace(v, tpl.spinner.replace('{text}', msg.calc).replace('{id}', 'dim')));
+          fm.request({
+            data: {cmd: 'dim', target: file.hash},
+            preventDefault: true
+          })
+            .fail(function() {
+              replSpinnerById(msg.unknown, 'dim');
+            })
+            .done(function(data) {
+              replSpinnerById(data.dim || msg.unknown, 'dim');
+            });
+        }
+
+        content.push(row.replace(l, msg.modify).replace(v, fm.formatDate(file)));
+        content.push(row.replace(l, msg.perms).replace(v, fm.formatPermissions(file)));
+        content.push(row.replace(l, msg.locked).replace(v, file.locked ? msg.yes : msg.no));
+
+        /* Don't show fields if command not allowed */
+        if (viewOwner) {
+          content.push(row.replace(l, Drupal.t('Owner')).replace(v, tpl.spinner.replace('{text}', msg.calc).replace('{id}', 'owner')));
+
+          fm.request({
+            data: {cmd: 'owner', target: file.hash},
+            preventDefault: true
+          })
+            .fail(function() {
+              replSpinnerById(msg.unknown, 'owner');
+            })
+            .done(function(data) {
+              replSpinnerById(data.owner || msg.unknown, 'owner');
+            });
+        }
+
+        /* Don't show fields if command not allowed */
+        if (viewDownloads) {
+          content.push(row.replace(l, Drupal.t('Downloads')).replace(v, tpl.spinner.replace('{text}', msg.calc).replace('{id}', 'downloads')));
+
+          fm.request({
+            data: {cmd: 'downloadcount', target: file.hash},
+            preventDefault: true
+          })
+            .fail(function() {
+              replSpinnerById(msg.unknown, 'downloads');
+            })
+            .done(function(data) {
+              replSpinnerById(data.downloadcount || msg.unknown, 'downloads');
+            });
+        }
+
+        /* Don't show fields if command not allowed */
+        if (viewDesc || editDesc) {
+
+          var desc = '<div id="elfinder-fm-file-desc">' + msg.calc + '</div>';
+
+          if (editDesc) {
+
+            desc = '<textarea cols="20" rows="5" id="elfinder-fm-file-desc" class="ui-widget ui-widget-content" disabled="true" >' + msg.calc + '</textarea><input type="button" id="elfinder-fm-file-desc-btn-save" value="' + fm.i18n('btnSave') + '" />';
+          }
+
+          content.push(row.replace(l, Drupal.t('Description')).replace(v, desc));
+
+          fm.request({
+            data: {cmd: 'desc', target: file.hash},
+            preventDefault: true
+          })
+            .done(function(data) {
+              var fieldDesc = dialog.find('#elfinder-fm-file-desc');
+
+              if (editDesc) {
+                fieldDesc.val(data.desc || '');
+                fieldDesc.removeAttr('disabled');
+              } else {
+                fieldDesc.empty();
+                fieldDesc.html(data.desc || '');
+              }
+            });
+
+        }
+
+      } else {
+        view = view.replace('{class}', 'elfinder-cwd-icon-group');
+        title = tpl.groupTitle.replace('{items}', msg.items).replace('{num}', cnt);
         dcnt = $.map(files, function(f) {
           return f.mime == 'directory' ? 1 : null
         }).length;
-			if (!dcnt) {
-				size = 0;
-				$.each(files, function(h, f) { 
-					var s = parseInt(f.size);
-					
-					if (s >= 0 && size >= 0) {
-						size += s;
-					} else {
-						size = 'unknown';
-					}
-				});
-				content.push(row.replace(l, msg.kind).replace(v, msg.files));
-				content.push(row.replace(l, msg.size).replace(v, fm.formatSize(size)));
-			} else {
-				content.push(row.replace(l, msg.kind).replace(v, dcnt == cnt ? msg.folders : msg.folders+' '+dcnt+', '+msg.files+' '+(cnt-dcnt)))
-				content.push(row.replace(l, msg.size).replace(v, tpl.spinner.replace('{text}', msg.calc).replace('{id}', 'size')));
+        if (!dcnt) {
+          size = 0;
+          $.each(files, function(h, f) {
+            var s = parseInt(f.size);
+
+            if (s >= 0 && size >= 0) {
+              size += s;
+            } else {
+              size = 'unknown';
+            }
+          });
+          content.push(row.replace(l, msg.kind).replace(v, msg.files));
+          content.push(row.replace(l, msg.size).replace(v, fm.formatSize(size)));
+        } else {
+          content.push(row.replace(l, msg.kind).replace(v, dcnt == cnt ? msg.folders : msg.folders + ' ' + dcnt + ', ' + msg.files + ' ' + (cnt - dcnt)))
+          content.push(row.replace(l, msg.size).replace(v, tpl.spinner.replace('{text}', msg.calc).replace('{id}', 'size')));
           count = $.map(files, function(f) {
             return f.hash
           });
-				
-			}
-		}
-		
-		view = view.replace('{title}', title).replace('{content}', content.join(''));
-		
-		dialog = fm.dialog(view, opts);
-		dialog.attr('id', id);
-    
-    if (editDesc) {
-      var inputDesc = $('#elfinder-fm-file-desc', dialog);
-      var btnSave = $('#elfinder-fm-file-desc-btn-save', dialog).button();
-      
-      btnSave.click(function() {
-        fm.lockfiles({files : [file.hash]});
-        fm.request({
-          data   : {cmd : 'desc', target : file.hash, content : inputDesc.val()},
-          notify : {type : 'desc', cnt : 1}
+
+        }
+      }
+
+      view = view.replace('{title}', title).replace('{content}', content.join(''));
+
+      dialog = fm.dialog(view, opts);
+      dialog.attr('id', id);
+
+      if (editDesc) {
+        var inputDesc = $('#elfinder-fm-file-desc', dialog);
+        var btnSave = $('#elfinder-fm-file-desc-btn-save', dialog).button();
+
+        btnSave.click(function() {
+          fm.lockfiles({files: [file.hash]});
+          fm.request({
+            data: {cmd: 'desc', target: file.hash, content: inputDesc.val()},
+            notify: {type: 'desc', cnt: 1}
           })
-					.always(function() {
-						fm.unlockfiles({files : [file.hash]})
-					});
-      });
-    }
-		// load thumbnail
-		if (tmb) {
-			$('<img/>')
+            .always(function() {
+              fm.unlockfiles({files: [file.hash]})
+            });
+        });
+      }
+      // load thumbnail
+      if (tmb) {
+        $('<img/>')
           .load(function() {
             dialog.find('.elfinder-cwd-icon').css('background', 'url("' + tmb + '") center center no-repeat');
           })
-				.attr('src', tmb);
-		}
-		
-		// send request to count total size
-		if (count.length) {
-			fm.request({
-					data : {cmd : 'size', targets : count},
-					preventDefault : true
-				})
-				.fail(function() {
-					replSpinnerById(msg.unknown, 'size');
-				})
-				.done(function(data) {
-					var size = parseInt(data.size);
-					fm.log(data.size)
-					replSpinnerById(size >= 0 ? fm.formatSize(size) : msg.unknown, 'size');
-				});
-		}
-		
-	}
-	
-}
+          .attr('src', tmb);
+      }
+
+      // send request to count total size
+      if (count.length) {
+        fm.request({
+          data: {cmd: 'size', targets: count},
+          preventDefault: true
+        })
+          .fail(function() {
+            replSpinnerById(msg.unknown, 'size');
+          })
+          .done(function(data) {
+            var size = parseInt(data.size);
+            fm.log(data.size)
+            replSpinnerById(size >= 0 ? fm.formatSize(size) : msg.unknown, 'size');
+          });
+      }
+
+    }
+
+  }
 
 
 })(jQuery);

+ 4 - 2
sites/all/modules/contrib/files/elfinder/modules/elfinder_bueditor/elfinder_bueditor.info

@@ -3,12 +3,14 @@ name = elFinder BUEditor integration
 description = Adding elFinder to BUEditor Insert Image dialog
 package = User interface
 core = 7.x
+project status url = https://drupal-elfinder.sourceforge.io/release-history.php
 
 dependencies[] = bueditor
 dependencies[] = elfinder
 
-; Information added by Drupal.org packaging script on 2018-12-03
+; Information added by Drupal.org packaging script on 2017-11-16
 version = "7.x-2.x-dev"
 core = "7.x"
 project = "elfinder"
-datestamp = "1543843700"
+datestamp = "1555577224"
+

+ 7 - 6
sites/all/modules/contrib/files/elfinder/modules/elfinder_bueditor/elfinder_bueditor.module

@@ -1,15 +1,16 @@
 <?php
-// $Id: elfinder.module 102 2011-02-20 20:11:52Z ph0enix $
-
 /**
- * BUEditor support for elFinder
- * Copyright (c) 2011, Alexey Sukhotin
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
  */
 
+// $Id: elfinder.module 102 2011-02-20 20:11:52Z ph0enix $
+
 function elfinder_bueditor_elfinder_js_settings($settings) {
 
   $newsettings['editorCallback'] = 'elfinder_bue_callback';
-  
+
   $newsettings['browserscripts'][] = drupal_get_path('module', 'elfinder') . '/editors/bueditor/bueditor.callback.js';
 
   return array('bue' => $newsettings, 'bueditor' => $newsettings);
@@ -18,7 +19,7 @@ function elfinder_bueditor_elfinder_js_settings($settings) {
 /* D7 Support */
 function elfinder_bueditor_init() {
   $settings = array();
-  $settings['BUE']['imceURL'] = url('elfinder', array('query' => array('app' => 'bueditor' ))); 
+  $settings['BUE']['imceURL'] = url('elfinder', array('query' => array('app' => 'bueditor')));
   drupal_add_js($settings, 'setting');
 }
 

+ 4 - 2
sites/all/modules/contrib/files/elfinder/modules/elfinder_ffsel/elfinder_ffsel.info

@@ -2,12 +2,14 @@ name = elFinder File Field Source
 description = File Field Sources elFinder connector
 package = User interface
 core = 7.x
+project status url = https://drupal-elfinder.sourceforge.io/release-history.php
 
 dependencies[] = filefield_sources
 dependencies[] = elfinder
 
-; Information added by Drupal.org packaging script on 2018-12-03
+; Information added by Drupal.org packaging script on 2017-11-16
 version = "7.x-2.x-dev"
 core = "7.x"
 project = "elfinder"
-datestamp = "1543843700"
+datestamp = "1555577224"
+

+ 59 - 54
sites/all/modules/contrib/files/elfinder/modules/elfinder_ffsel/elfinder_ffsel.module

@@ -1,4 +1,9 @@
 <?php
+/**
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
+ */
 
 // Main hooks to tell FielField Sources about our source
 function elfinder_ffsel_filefield_sources_info() {
@@ -52,11 +57,11 @@ function filefield_source_elfinder_info() {
 function filefield_source_elfinder_menu() {
   $items = array();
   $items['filefield/elfinder/%/%'] = array(
-      'page callback' => 'filefield_source_elfinder_page',
-      'page arguments' => array(2, 3),
-      'access callback' => 'filefield_edit_access',
-      'access arguments' => array(2, 3),
-      'type' => MENU_CALLBACK,
+    'page callback' => 'filefield_source_elfinder_page',
+    'page arguments' => array(2, 3),
+    'access callback' => 'filefield_edit_access',
+    'access arguments' => array(2, 3),
+    'type' => MENU_CALLBACK,
   );
   return $items;
 }
@@ -66,9 +71,9 @@ function filefield_source_elfinder_menu() {
  */
 function elfinder_ffsel_theme() {
   return array(
-      'filefield_source_elfinder_element' => array(
-          'render element' => 'element',
-      ),
+    'filefield_source_elfinder_element' => array(
+      'render element' => 'element',
+    ),
   );
 }
 
@@ -90,58 +95,58 @@ function filefield_source_elfinder_process($element, &$form_state, $form) {
   $instance = field_widget_instance($element, $form_state);
 
   $element['filefield_elfinder'] = array(
-      '#weight' => 100.5,
-      '#theme' => 'filefield_source_elfinder_element',
-      '#filefield_source' => TRUE, // Required for proper theming.
-      '#description' => filefield_sources_element_validation_help($element['#upload_validators']),
+    '#weight' => 100.5,
+    '#theme' => 'filefield_source_elfinder_element',
+    '#filefield_source' => TRUE, // Required for proper theming.
+    '#description' => filefield_sources_element_validation_help($element['#upload_validators']),
   );
 
   $filepath_id = $element['#id'] . '-elfinder-path';
   $display_id = $element['#id'] . '-elfinder-display';
   $select_id = $element['#id'] . '-elfinder-select';
   $element['filefield_elfinder']['file_path'] = array(
-      '#type' => 'hidden',
-      '#attributes' => array(
-          'id' => $filepath_id,
-          'onchange' => "if (!jQuery('#$select_id').attr('disabled')) { jQuery('#$select_id').mousedown().attr('disabled', true); jQuery('#$display_id').html(this.value); }",
-      ),
-      '#value_callback' => 'elfinder_ffsel_element_value',
-      '#upload_validators' => $element['#upload_validators'],
-      '#maxlength' => NULL,
+    '#type' => 'hidden',
+    '#attributes' => array(
+      'id' => $filepath_id,
+      'onchange' => "if (!jQuery('#$select_id').attr('disabled')) { jQuery('#$select_id').mousedown().attr('disabled', true); jQuery('#$display_id').html(this.value); }",
+    ),
+    '#value_callback' => 'elfinder_ffsel_element_value',
+    '#upload_validators' => $element['#upload_validators'],
+    '#maxlength' => NULL,
   );
 
   $width = variable_get('elfinder_settings_misc_manager_width', '');
-  if(!$width) {
+  if (!$width) {
     $width = ELFINDER_POPUP_WIDTH;
   }
   $height = variable_get('elfinder_settings_misc_manager_height', '');
-  if(!$height) {
+  if (!$height) {
     $height = ELFINDER_POPUP_HEIGHT;
   }
 
   $elfinder_function = 'var left = window.screenX + (window.innerWidth / 2) - (' . $width . ' / 2); var top = window.screenY + (window.innerHeight / 2) - (' . $height . ' / 2); window.open(\'' . url('elfinder', array('query' => array('app' => 'ffs', 'field_name' => $element['#field_name'], 'filepath_id' => $filepath_id, 'select_id' => $select_id))) . '\', \'\', \'width=' . $width . ',height=' . $height . ',top=\'+top+\',left=\'+left+\',resizable=1\'); return false;';
 
   $element['filefield_elfinder']['display_path'] = array(
-      '#type' => 'markup',
-      '#markup' => '<span id="' . $display_id . '" class="filefield-sources-elfinder-display">' . t('No file selected') . '</span> (<a class="filefield-sources-elfinder-browse" href="#" onclick="' . $elfinder_function . '">' . t('browse') . '</a>)',
+    '#type' => 'markup',
+    '#markup' => '<span id="' . $display_id . '" class="filefield-sources-elfinder-display">' . t('No file selected') . '</span> (<a class="filefield-sources-elfinder-browse" href="#" onclick="' . $elfinder_function . '">' . t('browse') . '</a>)',
   );
 
   $element['filefield_elfinder']['upload_button'] = array(
-      '#name' => implode('_', $element['#array_parents']) . '_elfinder_select',
-      '#type' => 'submit',
-      '#value' => t('Select'),
-      '#validate' => array(),
-      '#submit' => array('filefield_sources_field_submit'),
-      '#limit_validation_errors' => array($element['#parents']),
-      '#name' => $element['#name'] . '[filefield_elfinder][button]',
-      '#id' => $select_id,
-      '#attributes' => array('style' => 'display: none;'),
-      '#ajax' => array(
-          'path' => 'file/ajax/' . implode('/', $element['#array_parents']) . '/' . $form['form_build_id']['#value'],
-          'wrapper' => $element['upload_button']['#ajax']['wrapper'],
-          'method' => 'replace',
-          'effect' => 'fade',
-      ),
+    '#name' => implode('_', $element['#array_parents']) . '_elfinder_select',
+    '#type' => 'submit',
+    '#value' => t('Select'),
+    '#validate' => array(),
+    '#submit' => array('filefield_sources_field_submit'),
+    '#limit_validation_errors' => array($element['#parents']),
+    '#name' => $element['#name'] . '[filefield_elfinder][button]',
+    '#id' => $select_id,
+    '#attributes' => array('style' => 'display: none;'),
+    '#ajax' => array(
+      'path' => 'file/ajax/' . implode('/', $element['#array_parents']) . '/' . $form['form_build_id']['#value'],
+      'wrapper' => $element['upload_button']['#ajax']['wrapper'],
+      'method' => 'replace',
+      'effect' => 'fade',
+    ),
   );
 
   return $element;
@@ -163,21 +168,21 @@ function filefield_source_elfinder_value($element, &$item) {
 
     // Resolve the file path to an FID.
     $fid = db_select('file_managed', 'f')
-            ->condition('uri', rawurldecode($uri))
-            ->fields('f', array('fid'))
-            ->execute()
-            ->fetchField();
+      ->condition('uri', rawurldecode($uri))
+      ->fields('f', array('fid'))
+      ->execute()
+      ->fetchField();
     if ($fid) {
       $file = file_load($fid);
       if (filefield_sources_element_validate($element, $file)) {
-        $item = array_merge($item, (array) $file);
+        $item = array_merge($item, (array)$file);
       }
     } else {
       $local_root = elfinder_document_root() . '/' . $file_directory_prefix . '/';
       $file_path = preg_replace('/.*(' . preg_quote('/' . $file_directory_prefix . '/', '/') . ')/', $local_root, $item['filefield_elfinder']['file_path']);
 
       if ($file = filefield_sources_save_file($file_path, $element['#upload_validators'], $element['#upload_location'], FILE_EXISTS_REPLACE)) {
-        $item = array_merge($item, (array) $file);
+        $item = array_merge($item, (array)$file);
         drupal_set_message(t('File created'));
       } else {
         form_error($element, t('The selected file could not be used because the file does not exist in the database.'));
@@ -237,7 +242,7 @@ function elfinder_ffsel_elfinder_js_settings($settings) {
  */
 function elfinder_ffsel_element_value($element, $input = FALSE, &$form_state = NULL) {
 
-  if(empty($input)) {
+  if (empty($input)) {
     return array();
   }
 
@@ -265,22 +270,22 @@ function elfinder_ffsel_element_value($element, $input = FALSE, &$form_state = N
 
   $files = explode('%%', $input);
 
-  foreach($files AS $delta => $file) {
+  foreach ($files AS $delta => $file) {
     // Respect the field's count limit.
-    if($upload_delta == $field['cardinality']) {
+    if ($upload_delta == $field['cardinality']) {
       break;
     }
     $uri = preg_replace('/.*(' . preg_quote('/' . $file_directory_prefix . '/', '/') . ')/', $scheme . '://', $file);
     // Resolve the file path to an FID.
     $fid = db_select('file_managed', 'f')
-            ->condition('uri', rawurldecode($uri))
-            ->fields('f', array('fid'))
-            ->execute()
-            ->fetchField();
+      ->condition('uri', rawurldecode($uri))
+      ->fields('f', array('fid'))
+      ->execute()
+      ->fetchField();
     if ($fid) {
       $file = file_load($fid);
       if (filefield_sources_element_validate($element, $file)) {
-        $items[$upload_delta] = (array) $file;
+        $items[$upload_delta] = (array)$file;
         $items[$upload_delta]['_weight'] = $upload_delta;
         $upload_delta++;
       }
@@ -289,7 +294,7 @@ function elfinder_ffsel_element_value($element, $input = FALSE, &$form_state = N
       $file_path = preg_replace('/.*(' . preg_quote('/' . $file_directory_prefix . '/', '/') . ')/', $local_root, $file);
 
       if ($file = filefield_sources_save_file($file_path, $element['#upload_validators'], $element['#upload_location'], FILE_EXISTS_REPLACE)) {
-        $items[$upload_delta] = (array) $file;
+        $items[$upload_delta] = (array)$file;
         $items[$upload_delta]['_weight'] = $upload_delta;
         $upload_delta++;
         drupal_set_message(t('File created'));

+ 31 - 18
sites/all/modules/contrib/files/elfinder/modules/elfinder_ffsel/ffs.callback.js

@@ -1,26 +1,39 @@
+/*
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
+ */
+
 function elfinder_ffs_callback(arg1) {
+  var fieldName = Drupal.settings.elfinder.field_name;
+  var fieldId = Drupal.settings.elfinder.filepath_id;
+
+  var url = arg1;
+
+  if (typeof arg1 == 'object') {
+    if ($.isArray(arg1)) {
+      url = arg1[0];
+    } else {
+      url = arg1.url;
+    }
+  } 
 
-          var fieldName = Drupal.settings.elfinder.field_name;
-          var fieldId = Drupal.settings.elfinder.filepath_id;
+  var filePath = url;
 
-          var url = arg1;
+  /* Needs rework: must support both classic single file selection and multiple selection */
+  //var filePath =  arg1.join('%%');
 
-          if (typeof arg1 == 'object') {
-            url = arg1.url;
-          }
-          
-          var filePath = url;
-          
-          /* Needs rework: must support both classic single file selection and multiple selection */
-          //var filePath =  arg1.join('%%');
+  if (typeof filePath == 'undefined') {
+    console.log('Undefined filePath, please check integration');
+  }
 
-          window.opener.jQuery('input#'+fieldId).val(filePath).change();
-          window.opener.focus();
+  window.opener.jQuery('input#' + fieldId).val(filePath).change();
+  window.opener.focus();
 
-          // Avoid beforeunload event when selecting an image.
-          // https://github.com/Studio-42/elFinder/issues/1340
-          // Maybe remove this when elfinder js library gets updated.
-          //$(window).off('beforeunload');
+  // Avoid beforeunload event when selecting an image.
+  // https://github.com/Studio-42/elFinder/issues/1340
+  // Maybe remove this when elfinder js library gets updated.
+  //$(window).off('beforeunload');
 
-          window.close();
+  window.close();
 }

+ 14 - 0
sites/all/modules/contrib/files/elfinder/modules/elfinder_tinymce/elfinder_tinymce.info

@@ -0,0 +1,14 @@
+name = elFinder TinyMCE integration
+description = Extended tinyMCE integration
+package = User interface
+core = 7.x
+project status url = https://drupal-elfinder.sourceforge.io/release-history.php
+
+dependencies[] = elfinder
+
+; Information added by Drupal.org packaging script on 2017-11-16
+version = "7.x-2.x-dev"
+core = "7.x"
+project = "elfinder"
+datestamp = "1555577224"
+

+ 24 - 0
sites/all/modules/contrib/files/elfinder/modules/elfinder_tinymce/elfinder_tinymce.module

@@ -0,0 +1,24 @@
+<?php
+/**
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
+ */
+
+// $Id: elfinder.module 102 2011-02-20 20:11:52Z ph0enix $
+
+function elfinder_tinymce_elfinder_js_settings($settings) {
+
+//  $newsettings['editorCallback'] = 'elfinder_bue_callback';
+
+  $newsettings['browserscripts'][] = drupal_get_path('module', 'elfinder') . '/editors/bueditor/bueditor.callback.js';
+
+  return array('bue' => $newsettings, 'bueditor' => $newsettings);
+}
+
+/* D7 Support */
+function elfinder_tinymce_init() {
+  $settings = array();
+  drupal_add_js($settings, 'setting');
+}
+

+ 9 - 9
sites/all/modules/contrib/files/elfinder/tpl/elfinder-page-backend.tpl.php

@@ -1,9 +1,9 @@
-<?php
-
-/**
- * @file
- * elFinder file browser page template
- * Copyright (c) 2010, Alexey Sukhotin
- */
-?>
-<div id="finder"></div>
+<?php
+
+/**
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
+ */
+?>
+<div id="finder"></div>

+ 17 - 17
sites/all/modules/contrib/files/elfinder/tpl/elfinder-page.tpl.php

@@ -1,26 +1,26 @@
 <?php
 /**
- * @file
- * elFinder file browser page template
- * Copyright (c) 2010, Alexey Sukhotin
+ * elFinder Integration
+ *
+ * Copyright (c) 2010-2018, Alexey Sukhotin. All rights reserved.
  */
 ?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml"
       lang="<?php print isset($language->language) ? $language->language : 'en'; ?>"
       xml:lang="<?php print isset($language->language) ? $language->language : 'en'; ?>">
-    <head>
-        <title><?php print t('File Browser'); ?></title>
+<head>
+    <title><?php print t('File Browser'); ?></title>
 
-        <?php
-        print drupal_get_html_head();
-        print elfinder_browser_css();
-        print elfinder_browser_js();
-        ?>
-        <!-- make inline popup WORK  -->
-    </head>
-    <body class="elfinder">
-        <div id="elfinder-messages"><?php print theme('status_messages'); ?></div>
-        <div id="finder"></div>
-        <?php print drupal_get_js('footer'); ?>
-    </body>
+  <?php
+  print drupal_get_html_head();
+  print elfinder_browser_css();
+  print elfinder_browser_js();
+  ?>
+    <!-- make inline popup WORK  -->
+</head>
+<body class="elfinder">
+<div id="elfinder-messages"><?php print theme('status_messages'); ?></div>
+<div id="finder"></div>
+<?php print drupal_get_js('footer'); ?>
+</body>
 </html>

+ 26 - 0
sites/all/modules/contrib/migrate/migrate/CHANGELOG.txt

@@ -1,3 +1,29 @@
+Next release
+============
+
+Features and enhancements
+- #2552189 - Return migration status from drush migrate-import.
+- #2550793 - Option to always use chunk IDs in MigrateContentParser.
+- #2505683 - Pass item ID to MigrateContentParser implementations.
+- #2532222 - Allow spreadsheet source data on a row different that 1.
+- #1406802 - Add callback() field mapping method, to pass additional arguments
+             to callbacks.
+- #2516828 - Add mdreg alias for migrate-deregister.
+- #2504517 - Add timezone handling to timestamp().
+
+Bug fixes
+- #2612110 - Notice when units omitted on --limit.
+- #2597606 - Escape MySQL database names.
+- #2577091 - Do strict type-check on XML ids.
+- #2537206 - copy() return not checked.
+- #2536616 - Improve message when sourceMigration not found.
+- #2578391 - Improve message when class not found.
+- #2565043 - Handle empty idlist in MigrateSourceMultiItems.
+- #2510010 - Stop stripping group name prefixes from migration names.
+- #2542520 - Fallback for missing source key description.
+- #2499861 - Properly save/disable/restore mail system.
+- #2541996 - Prevent NULL file_mask being passed to file_scan_directory().
+
 Migrate 2.8
 ===========
 

+ 13 - 11
sites/all/modules/contrib/migrate/migrate/README.txt

@@ -1,15 +1,17 @@
-
-The Migrate module provides a flexible framework for migrating content into Drupal 
-from other sources (e.g., when converting a web site from another CMS to Drupal). 
+The Migrate module provides a flexible framework for migrating content into
+Drupal from other sources
+(e.g., when converting a web site from another CMS to Drupal).
 Out-of-the-box, support for creating Drupal nodes, taxonomy terms, comments, and 
 users are included. Plugins permit migration of other types of content.
 
 Usage
 -----
 Documentation is at http://drupal.org/migrate. To get started, enable the
-migrate_example module and browse to admin/content/migrate to see its dashboard.
-The code for this migration is in migrate_example/beer.inc (advanced examples are
-in wine.inc). Mimic that file in order to specify your own migrations. 
+migrate_example module, enable migrate_ui, and then browse to
+admin/content/migrate to see its dashboard.
+The code for this migration is in migrate_example/beer.inc
+(advanced examples are in wine.inc). Mimic that file in order to specify your
+own migrations. 
 
 The Migrate module itself has support for migration into core objects. Support
 for migration involving contrib modules is in the migrate_extras module. 
@@ -17,8 +19,8 @@ for migration involving contrib modules is in the migrate_extras module.
 Known issues
 ------------
 A user migration with systemOfRecord == DESTINATION will drop pictures from user
-records due to core bug http://drupal.org/node/935592 - the simpletests report an
-error reflecting this. We have not developed a work-around.
+records due to core bug http://drupal.org/node/935592 - the simpletests report
+an error reflecting this. We have not developed a work-around.
 
 Upgrading
 ---------
@@ -30,9 +32,9 @@ projects.
 
 Acknowledgements 
 ----------------
-Much of the Migrate module functionality was sponsored by Cyrve, for its clients GenomeWeb 
-(http://www.genomeweb.com), The Economist (http://www.economist.com), and Examiner.com 
-(http://www.examiner.com). 
+Much of the Migrate module functionality was sponsored by Cyrve, for its clients
+GenomeWeb (http://www.genomeweb.com), The Economist (http://www.economist.com),
+and Examiner.com (http://www.examiner.com).
 
 Authors
 -------

+ 211 - 163
sites/all/modules/contrib/migrate/migrate/includes/base.inc

@@ -8,11 +8,12 @@
 /**
  * The base class for all objects representing distinct steps in a migration
  * process. Most commonly these will be Migration objects which actually import
- * data from a source into a Drupal destination, but by deriving classes directly
- * from MigrationBase one can have other sorts of tasks (e.g., enabling/disabling
- * of modules) occur during the migration process.
+ * data from a source into a Drupal destination, but by deriving classes
+ * directly from MigrationBase one can have other sorts of tasks (e.g.,
+ * enabling/disabling of modules) occur during the migration process.
  */
 abstract class MigrationBase {
+
   /**
    * Track the migration currently running, so handlers can easily determine it
    * without having to pass a Migration object everywhere.
@@ -20,18 +21,21 @@ abstract class MigrationBase {
    * @var Migration
    */
   protected static $currentMigration;
+
   public static function currentMigration() {
     return self::$currentMigration;
   }
 
   /**
-   * The machine name of this Migration object, derived by removing the 'Migration'
-   * suffix from the class name. Used to construct default map/message table names,
-   * displayed in drush migrate-status, key to migrate_status table...
+   * The machine name of this Migration object, derived by removing the
+   * 'Migration' suffix from the class name. Used to construct default
+   * map/message table names, displayed in drush migrate-status, key to
+   * migrate_status table...
    *
    * @var string
    */
   protected $machineName;
+
   public function getMachineName() {
     return $this->machineName;
   }
@@ -42,6 +46,7 @@ abstract class MigrationBase {
    * @var MigrateGroup
    */
   protected $group;
+
   public function getGroup() {
     return $this->group;
   }
@@ -52,18 +57,22 @@ abstract class MigrationBase {
    * @var string
    */
   protected $description;
+
   public function getDescription() {
     return $this->description;
   }
+
   public function setDescription($description) {
     $this->description = $description;
   }
 
   /**
    * Save options passed to current operation
+   *
    * @var array
    */
   protected $options;
+
   public function getOption($option_name) {
     if (isset($this->options[$option_name])) {
       return $this->options[$option_name];
@@ -72,18 +81,20 @@ abstract class MigrationBase {
       return NULL;
     }
   }
+
   public function getItemLimit() {
     if (isset($this->options['limit']) &&
-        ($this->options['limit']['unit'] == 'items' || $this->options['limit']['unit'] == 'item')) {
+      ($this->options['limit']['unit'] == 'items' || $this->options['limit']['unit'] == 'item')) {
       return $this->options['limit']['value'];
     }
     else {
       return NULL;
     }
   }
+
   public function getTimeLimit() {
     if (isset($this->options['limit']) &&
-        ($this->options['limit']['unit'] == 'seconds' || $this->options['limit']['unit'] == 'second')) {
+      ($this->options['limit']['unit'] == 'seconds' || $this->options['limit']['unit'] == 'second')) {
       return $this->options['limit']['value'];
     }
     else {
@@ -108,6 +119,7 @@ abstract class MigrationBase {
 
   /**
    * When the current operation started.
+   *
    * @var int
    */
   protected $starttime;
@@ -137,41 +149,51 @@ abstract class MigrationBase {
 
   /**
    * List of other Migration classes which should be imported before this one.
-   * E.g., a comment migration class would typically have node and user migrations
-   * as dependencies.
+   * E.g., a comment migration class would typically have node and user
+   * migrations as dependencies.
    *
    * @var array
    */
   protected $dependencies = array(), $softDependencies = array();
+
   public function getHardDependencies() {
     return $this->dependencies;
   }
+
   public function setHardDependencies(array $dependencies) {
     $this->dependencies = $dependencies;
   }
+
   public function addHardDependencies(array $dependencies) {
     $this->dependencies = array_merge($this->dependencies, $dependencies);
   }
+
   public function getSoftDependencies() {
     return $this->softDependencies;
   }
+
   public function setSoftDependencies(array $dependencies) {
     $this->softDependencies = $dependencies;
   }
+
   public function addSoftDependencies(array $dependencies) {
     $this->softDependencies = array_merge($this->softDependencies, $dependencies);
   }
+
   public function getDependencies() {
     return array_merge($this->dependencies, $this->softDependencies);
   }
 
   /**
-   * Name of a function for displaying feedback. It must take the message to display
-   * as its first argument, and a (string) message type as its second argument
+   * Name of a function for displaying feedback. It must take the message to
+   * display as its first argument, and a (string) message type as its second
+   * argument
    * (see drush_log()).
+   *
    * @var string
    */
   protected static $displayFunction;
+
   public static function setDisplayFunction($display_function) {
     self::$displayFunction = $display_function;
   }
@@ -230,9 +252,11 @@ abstract class MigrationBase {
    * @var array
    */
   protected $team = array();
+
   public function getTeam() {
     return $this->team;
   }
+
   public function setTeam(array $team) {
     $this->team = $team;
   }
@@ -244,9 +268,11 @@ abstract class MigrationBase {
    * @var string
    */
   protected $issuePattern;
+
   public function getIssuePattern() {
     return $this->issuePattern;
   }
+
   public function setIssuePattern($issue_pattern) {
     $this->issuePattern = $issue_pattern;
   }
@@ -265,12 +291,15 @@ abstract class MigrationBase {
    * @var array
    */
   protected $arguments = array();
+
   public function getArguments() {
     return $this->arguments;
   }
+
   public function setArguments(array $arguments) {
     $this->arguments = $arguments;
   }
+
   public function addArguments(array $arguments) {
     $this->arguments = array_merge($this->arguments, $arguments);
   }
@@ -282,9 +311,11 @@ abstract class MigrationBase {
    * @var boolean
    */
   protected $enabled = TRUE;
+
   public function getEnabled() {
     return $this->enabled;
   }
+
   public function setEnabled($enabled) {
     $this->enabled = $enabled;
   }
@@ -294,9 +325,11 @@ abstract class MigrationBase {
    *
    * @var array
    *  Key: Hook name (e.g., 'node_insert')
-   *  Value: Array of modules for which to disable this hook (e.g., array('pathauto')).
+   *  Value: Array of modules for which to disable this hook (e.g.,
+   *   array('pathauto')).
    */
   protected $disableHooks = array();
+
   public function getDisableHooks() {
     return $this->disableHooks;
   }
@@ -304,26 +337,33 @@ abstract class MigrationBase {
   /**
    * An array to track 'mail_system' variable if disabled.
    */
-  protected $mailSystem = array();
+  protected $mailSystem;
 
   /**
-   * Have we already warned about obsolete constructor argumentss on this request?
+   * Have we already warned about obsolete constructor argumentss on this
+   * request?
    *
    * @var bool
    */
   static protected $groupArgumentWarning = FALSE;
+
   static protected $emptyArgumentsWarning = FALSE;
 
   /**
    * Codes representing the result of a rollback or import process.
    */
   const RESULT_COMPLETED = 1;   // All records have been processed
+
   const RESULT_INCOMPLETE = 2;  // The process has interrupted itself (e.g., the
-                                // memory limit is approaching)
+
+  // memory limit is approaching)
   const RESULT_STOPPED = 3;     // The process was stopped externally (e.g., via
-                                // drush migrate-stop)
+
+  // drush migrate-stop)
   const RESULT_FAILED = 4;      // The process had a fatal error
+
   const RESULT_SKIPPED = 5;     // Dependencies are unfulfilled - skip the process
+
   const RESULT_DISABLED = 6;    // This migration is disabled, skipping
 
   /**
@@ -331,20 +371,27 @@ abstract class MigrationBase {
    * migrate_status table.
    */
   const STATUS_IDLE = 0;
+
   const STATUS_IMPORTING = 1;
+
   const STATUS_ROLLING_BACK = 2;
+
   const STATUS_STOPPING = 3;
+
   const STATUS_DISABLED = 4;
 
   /**
    * Message types to be passed to saveMessage() and saved in message tables.
-   * MESSAGE_INFORMATIONAL represents a condition that did not prevent the operation
-   * from succeeding - all others represent different severities of conditions
-   * resulting in a source record not being imported.
+   * MESSAGE_INFORMATIONAL represents a condition that did not prevent the
+   * operation from succeeding - all others represent different severities of
+   * conditions resulting in a source record not being imported.
    */
   const MESSAGE_ERROR = 1;
+
   const MESSAGE_WARNING = 2;
+
   const MESSAGE_NOTICE = 3;
+
   const MESSAGE_INFORMATIONAL = 4;
 
   /**
@@ -374,7 +421,7 @@ abstract class MigrationBase {
       $this->group = $arguments;
       $this->arguments['group_name'] = $arguments->getName();
       if (!self::$groupArgumentWarning &&
-          variable_get('migrate_deprecation_warnings', 1)) {
+        variable_get('migrate_deprecation_warnings', 1)) {
         self::displayMessage(t('Passing a group object to a migration constructor is now deprecated - pass through the arguments array passed to the leaf class instead.'));
         self::$groupArgumentWarning = TRUE;
       }
@@ -383,7 +430,7 @@ abstract class MigrationBase {
       if (empty($arguments)) {
         $this->arguments = array();
         if (!self::$emptyArgumentsWarning &&
-            variable_get('migrate_deprecation_warnings', 1)) {
+          variable_get('migrate_deprecation_warnings', 1)) {
           self::displayMessage(t('Passing an empty first parameter to a migration constructor is now deprecated - pass through the arguments array passed to the leaf class instead.'));
           self::$emptyArgumentsWarning = TRUE;
         }
@@ -417,7 +464,8 @@ abstract class MigrationBase {
     }
     else {
       if (!is_numeric($limit)) {
-        $last = drupal_strtolower($limit[strlen($limit)-1]);
+        $last = drupal_strtolower($limit[strlen($limit) - 1]);
+        $limit = substr($limit, 0, -1);
         switch ($last) {
           case 'g':
             $limit *= 1024;
@@ -437,18 +485,12 @@ abstract class MigrationBase {
     // Record the time limit
     $this->timeLimit = ini_get('max_execution_time');
 
-    // Save the current mail system, prior to disabling emails.
-    $this->saveMailSystem();
-
-    // Prevent emails from being sent out during migrations.
-    $this->disableMailSystem();
-
     // Make sure we clear our semaphores in case of abrupt exit
     drupal_register_shutdown_function(array($this, 'endProcess'));
 
     // Save any hook disablement information.
     if (isset($this->arguments['disable_hooks']) &&
-        is_array($this->arguments['disable_hooks'])) {
+      is_array($this->arguments['disable_hooks'])) {
       $this->disableHooks = $this->arguments['disable_hooks'];
     }
   }
@@ -477,7 +519,7 @@ abstract class MigrationBase {
    * @param array $arguments
    */
   static public function registerMigration($class_name, $machine_name = NULL,
-      array $arguments = array()) {
+                                           array $arguments = array()) {
     // Support for legacy migration code - in later releases, the machine_name
     // should always be explicit.
     if (!$machine_name) {
@@ -486,7 +528,7 @@ abstract class MigrationBase {
 
     if (!preg_match('|^[a-z0-9_]+$|i', $machine_name)) {
       throw new Exception(t('!name is not a valid Migration machine name. Use only alphanumeric or underscore characters.',
-                          array('!name' => $machine_name)));
+        array('!name' => $machine_name)));
     }
 
     // We no longer have any need to store the machine_name in the arguments.
@@ -509,10 +551,10 @@ abstract class MigrationBase {
     db_merge('migrate_status')
       ->key(array('machine_name' => $machine_name))
       ->fields(array(
-                'class_name' => $class_name,
-                'group_name' => $group_name,
-                'arguments' => serialize($arguments)
-        ))
+        'class_name' => $class_name,
+        'group_name' => $group_name,
+        'arguments' => serialize($arguments),
+      ))
       ->execute();
   }
 
@@ -524,8 +566,8 @@ abstract class MigrationBase {
    */
   static public function deregisterMigration($machine_name) {
     $rows_deleted = db_delete('migrate_status')
-                    ->condition('machine_name', $machine_name)
-                    ->execute();
+      ->condition('machine_name', $machine_name)
+      ->execute();
     // Make sure the group gets deleted if we were the only member.
     MigrateGroup::deleteOrphans();
   }
@@ -583,10 +625,10 @@ abstract class MigrationBase {
     if (!isset($migrations[$machine_name_key])) {
       // See if we know about this migration
       $row = db_select('migrate_status', 'ms')
-             ->fields('ms', array('class_name', 'group_name', 'arguments'))
-             ->condition('machine_name', $machine_name)
-             ->execute()
-             ->fetchObject();
+        ->fields('ms', array('class_name', 'group_name', 'arguments'))
+        ->condition('machine_name', $machine_name)
+        ->execute()
+        ->fetchObject();
       if ($row) {
         $class_name = $row->class_name;
         $arguments = unserialize($row->arguments);
@@ -603,8 +645,7 @@ abstract class MigrationBase {
       if (class_exists($class_name)) {
         try {
           $migrations[$machine_name_key] = new $class_name($arguments);
-        }
-        catch (Exception $e) {
+        } catch (Exception $e) {
           self::displayMessage(t('Migration !machine could not be constructed.',
             array('!machine' => $machine_name)));
           self::displayMessage($e->getMessage());
@@ -665,12 +706,14 @@ abstract class MigrationBase {
   }
 
   /**
-   * Output the given message appropriately (drush_print/drupal_set_message/etc.)
+   * Output the given message appropriately
+   * (drush_print/drupal_set_message/etc.)
    *
    * @param string $message
    *  The message to output.
    * @param int $level
-   *  Optional message severity as understood by drupal_set_message and drush_log
+   *  Optional message severity as understood by drupal_set_message and
+   *   drush_log
    *  (defaults to 'error').
    */
   static public function displayMessage($message, $level = 'error') {
@@ -690,12 +733,13 @@ abstract class MigrationBase {
    * @param $line
    *   The line number the error was raised at.
    * @param $context
-   *   An array that points to the active symbol table at the point the error occurred.
+   *   An array that points to the active symbol table at the point the error
+   *   occurred.
    */
   public function errorHandler($error_level, $message, $filename, $line, $context) {
     if ($error_level & error_reporting()) {
       $message .= "\n" . t('File !file, line !line',
-        array('!line' => $line, '!file' => $filename));
+          array('!line' => $line, '!file' => $filename));
       // Record notices and continue
       if ($error_level == E_NOTICE || $error_level == E_USER_NOTICE) {
         $this->saveMessage($message . "(file: $filename, line $line)", MigrationBase::MESSAGE_INFORMATIONAL);
@@ -703,20 +747,21 @@ abstract class MigrationBase {
       // Simply ignore strict and deprecated errors
       // Note DEPRECATED constants introduced in PHP 5.3
       elseif (!($error_level == E_STRICT || $error_level == 8192 ||
-                $error_level == 16384)) {
+        $error_level == 16384)) {
         throw new MigrateException($message, MigrationBase::MESSAGE_ERROR);
       }
     }
   }
 
   /**
-   * Takes an Exception object and both saves and displays it, pulling additional
-   * information on the location triggering the exception.
+   * Takes an Exception object and both saves and displays it, pulling
+   * additional information on the location triggering the exception.
    *
    * @param Exception $exception
    *  Object representing the exception.
    * @param boolean $save
-   *  Whether to save the message in the migration's mapping table. Set to FALSE
+   *  Whether to save the message in the migration's mapping table. Set to
+   *   FALSE
    *  in contexts where this doesn't make sense.
    */
   public function handleException($exception, $save = TRUE) {
@@ -730,6 +775,7 @@ abstract class MigrationBase {
 
   /**
    * Check the current status of a migration.
+   *
    * @return int
    *  One of the MigrationBase::STATUS_* constants
    */
@@ -738,10 +784,10 @@ abstract class MigrationBase {
       return MigrationBase::STATUS_DISABLED;
     }
     $status = db_select('migrate_status', 'ms')
-              ->fields('ms', array('status'))
-              ->condition('machine_name', $this->machineName)
-              ->execute()
-              ->fetchField();
+      ->fields('ms', array('status'))
+      ->condition('machine_name', $this->machineName)
+      ->execute()
+      ->fetchField();
     if (!isset($status)) {
       $status = MigrationBase::STATUS_IDLE;
     }
@@ -750,19 +796,20 @@ abstract class MigrationBase {
 
   /**
    * Retrieve the last time an import operation completed successfully.
+   *
    * @return string
    *  Date/time string, formatted... How? Default DB server format?
    */
   public function getLastImported() {
     $last_imported = db_select('migrate_log', 'ml')
-              ->fields('ml', array('endtime'))
-              ->condition('machine_name', $this->machineName)
-              ->isNotNull('endtime')
-              ->orderBy('endtime', 'DESC')
-              ->execute()
-              ->fetchField();
+      ->fields('ml', array('endtime'))
+      ->condition('machine_name', $this->machineName)
+      ->isNotNull('endtime')
+      ->orderBy('endtime', 'DESC')
+      ->execute()
+      ->fetchField();
     if ($last_imported) {
-      $last_imported = date('Y-m-d H:i:s', $last_imported/1000);
+      $last_imported = date('Y-m-d H:i:s', $last_imported / 1000);
     }
     else {
       $last_imported = '';
@@ -778,10 +825,10 @@ abstract class MigrationBase {
    */
   public function getHighwater() {
     $highwater = db_select('migrate_status', 'ms')
-              ->fields('ms', array('highwater'))
-              ->condition('machine_name', $this->machineName)
-              ->execute()
-              ->fetchField();
+      ->fields('ms', array('highwater'))
+      ->condition('machine_name', $this->machineName)
+      ->execute()
+      ->fetchField();
     return $highwater;
   }
 
@@ -796,8 +843,8 @@ abstract class MigrationBase {
   protected function saveHighwater($highwater, $force = FALSE) {
     if (!isset($this->options['idlist'])) {
       $query = db_update('migrate_status')
-               ->fields(array('highwater' => $highwater))
-               ->condition('machine_name', $this->machineName);
+        ->fields(array('highwater' => $highwater))
+        ->condition('machine_name', $this->machineName);
       if (!$force) {
         if (!empty($this->highwaterField['type']) && $this->highwaterField['type'] == 'int') {
           // If the highwater is an integer type, we need to force the DB server
@@ -808,9 +855,8 @@ abstract class MigrationBase {
               $query->where('(CASE WHEN highwater=\'\' THEN 0 ELSE CAST(highwater AS INTEGER) END) < :highwater', array(':highwater' => intval($highwater)));
               break;
             default:
-              // CAST(highwater AS INTEGER) would be ideal, but won't
-              // work in MySQL. This hack is thought to be portable.
-              $query->where('(highwater+0) < :highwater', array(':highwater' => $highwater));
+              // MySQL casts as integers as SIGNED or UNSIGNED.
+              $query->where('(CASE WHEN highwater=\'\' THEN 0 ELSE CAST(highwater AS SIGNED) END) < :highwater', array(':highwater' => intval($highwater)));
           }
         }
         else {
@@ -823,20 +869,21 @@ abstract class MigrationBase {
 
   /**
    * Retrieve the last throughput for current Migration (items / minute).
+   *
    * @return integer
    */
   public function getLastThroughput() {
     $last_throughput = 0;
     $row = db_select('migrate_log', 'ml')
-              ->fields('ml', array('starttime', 'endtime', 'numprocessed'))
-              ->condition('machine_name', $this->machineName)
-              ->condition('process_type', 1)
-              ->isNotNull('endtime')
-              ->orderBy('starttime', 'DESC')
-              ->execute()
-              ->fetchObject();
+      ->fields('ml', array('starttime', 'endtime', 'numprocessed'))
+      ->condition('machine_name', $this->machineName)
+      ->condition('process_type', 1)
+      ->isNotNull('endtime')
+      ->orderBy('starttime', 'DESC')
+      ->execute()
+      ->fetchObject();
     if ($row) {
-      $elapsed = ($row->endtime - $row->starttime)/1000;
+      $elapsed = ($row->endtime - $row->starttime) / 1000;
       if ($elapsed > 0) {
         $last_throughput = round(($row->numprocessed / $elapsed) * 60);
       }
@@ -846,8 +893,9 @@ abstract class MigrationBase {
 
   /**
    * Reports whether this migration process is complete. For a Migration, for
-   * example, this would be whether all available source rows have been processed.
-   * Other MigrationBase classes will need to return TRUE/FALSE appropriately.
+   * example, this would be whether all available source rows have been
+   * processed. Other MigrationBase classes will need to return TRUE/FALSE
+   * appropriately.
    */
   abstract public function isComplete();
 
@@ -904,6 +952,12 @@ abstract class MigrationBase {
     // Try to make the semaphore handling atomic (depends on DB support)
     $transaction = db_transaction();
 
+    // Save the current mail system, prior to disabling emails.
+    $this->saveMailSystem();
+
+    // Prevent emails from being sent out during migrations.
+    $this->disableMailSystem();
+
     $this->starttime = microtime(TRUE);
 
     // Check to make sure there's no process already running for this migration
@@ -922,19 +976,22 @@ abstract class MigrationBase {
 
     // Set an error handler for imports
     if ($newStatus == MigrationBase::STATUS_IMPORTING) {
-      $this->previousErrorHandler = set_error_handler(array($this, 'errorHandler'));
+      $this->previousErrorHandler = set_error_handler(array(
+        $this,
+        'errorHandler',
+      ));
     }
 
     // Save the initial history record
     if ($this->logHistory) {
       $this->logID = db_insert('migrate_log')
-                     ->fields(array(
-                       'machine_name' => $this->machineName,
-                       'process_type' => $newStatus,
-                       'starttime' => round(microtime(TRUE) * 1000),
-                       'initialHighwater' => $this->getHighwater(),
-                       ))
-                     ->execute();
+        ->fields(array(
+          'machine_name' => $this->machineName,
+          'process_type' => $newStatus,
+          'starttime' => round(microtime(TRUE) * 1000),
+          'initialHighwater' => $this->getHighwater(),
+        ))
+        ->execute();
     }
 
     // If we're disabling any hooks, reset the static module_implements cache so
@@ -950,8 +1007,8 @@ abstract class MigrationBase {
   }
 
   /**
-   * End a rollback or import process, releasing the semaphore. Note that it must
-   * be public to be callable as the shutdown function.
+   * End a rollback or import process, releasing the semaphore. Note that it
+   * must be public to be callable as the shutdown function.
    */
   public function endProcess() {
     if ($this->previousErrorHandler) {
@@ -960,7 +1017,14 @@ abstract class MigrationBase {
     }
     if ($this->processing) {
       $this->status = MigrationBase::STATUS_IDLE;
-      $fields = array('class_name' => get_class($this), 'status' => MigrationBase::STATUS_IDLE);
+
+      // Restore the previous mail handler.
+      $this->restoreMailSystem();
+
+      $fields = array(
+        'class_name' => get_class($this),
+        'status' => MigrationBase::STATUS_IDLE,
+      );
       db_merge('migrate_status')
         ->key(array('machine_name' => $this->machineName))
         ->fields($fields)
@@ -977,10 +1041,9 @@ abstract class MigrationBase {
               'numprocessed' => $this->total_processed,
             ))
             ->execute();
-        }
-        catch (PDOException $e) {
+        } catch (PDOException $e) {
           Migration::displayMessage(t('Could not log operation on migration !name - possibly MigrationBase::beginProcess() was not called',
-                                    array('!name' => $this->machineName)));
+            array('!name' => $this->machineName)));
         }
       }
 
@@ -1035,8 +1098,7 @@ abstract class MigrationBase {
         $this->beginProcess(MigrationBase::STATUS_ROLLING_BACK);
         try {
           $return = $this->rollback();
-        }
-        catch (Exception $exception) {
+        } catch (Exception $exception) {
           // If something bad happened, make sure we clear the semaphore
           $this->endProcess();
           throw $exception;
@@ -1071,8 +1133,7 @@ abstract class MigrationBase {
         $this->beginProcess(MigrationBase::STATUS_IMPORTING);
         try {
           $return = $this->import();
-        }
-        catch (Exception $exception) {
+        } catch (Exception $exception) {
           // If something bad happened, make sure we clear the semaphore
           $this->endProcess();
           throw $exception;
@@ -1117,43 +1178,50 @@ abstract class MigrationBase {
    */
 
   /**
-   * Test whether we've exceeded the desired memory threshold. If so, output a message.
+   * Test whether we've exceeded the desired memory threshold. If so, output a
+   * message.
    *
    * @return boolean
    *  TRUE if the threshold is exceeded, FALSE if not.
    */
   protected function memoryExceeded() {
     $usage = memory_get_usage();
-    $pct_memory = $usage/$this->memoryLimit;
+    $pct_memory = $usage / $this->memoryLimit;
     if ($pct_memory > $this->memoryThreshold) {
       self::displayMessage(
         t('Memory usage is !usage (!pct% of limit !limit), resetting statics',
-          array('!pct' => round($pct_memory*100),
-                '!usage' => format_size($usage),
-                '!limit' => format_size($this->memoryLimit))),
+          array(
+            '!pct' => round($pct_memory * 100),
+            '!usage' => format_size($usage),
+            '!limit' => format_size($this->memoryLimit),
+          )),
         'warning');
       // First, try resetting Drupal's static storage - this frequently releases
       // plenty of memory to continue
       drupal_static_reset();
       $usage = memory_get_usage();
-      $pct_memory = $usage/$this->memoryLimit;
+      $pct_memory = $usage / $this->memoryLimit;
       // Use a lower threshold - we don't want to be in a situation where we keep
       // coming back here and trimming a tiny amount
       if ($pct_memory > (.90 * $this->memoryThreshold)) {
         self::displayMessage(
           t('Memory usage is now !usage (!pct% of limit !limit), not enough reclaimed, starting new batch',
-            array('!pct' => round($pct_memory*100),
-                  '!usage' => format_size($usage),
-                  '!limit' => format_size($this->memoryLimit))),
+            array(
+              '!pct' => round($pct_memory * 100),
+              '!usage' => format_size($usage),
+              '!limit' => format_size($this->memoryLimit),
+            )),
           'warning');
         return TRUE;
       }
       else {
         self::displayMessage(
           t('Memory usage is now !usage (!pct% of limit !limit), reclaimed enough, continuing',
-            array('!pct' => round($pct_memory*100),
-                  '!usage' => format_size($usage),
-                  '!limit' => format_size($this->memoryLimit))),
+            array(
+              '!pct' => round($pct_memory * 100),
+              '!usage' => format_size($usage),
+              '!limit' => format_size($this->memoryLimit),
+            )),
           'warning');
         return FALSE;
       }
@@ -1204,37 +1272,23 @@ abstract class MigrationBase {
 
   /**
    * Encrypt an incoming value. Detects for existence of the Drupal 'Encrypt'
-   *  module or the mcrypt PHP extension.
+   *  module.
    *
    * @param string $value
+   *
    * @return string The encrypted value.
    */
   static public function encrypt($value) {
     if (module_exists('encrypt')) {
       $value = encrypt($value);
     }
-    else if (extension_loaded('mcrypt')) {
-      // Mimic encrypt module to ensure compatibility
-      $key = drupal_substr(variable_get('drupal_private_key', 'no_key'), 0, 32);
-      $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
-      $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
-      $value = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $value,
-                              MCRYPT_MODE_ECB, $iv);
-
-      $encryption_array['text'] = $value;
-      // For forward compatibility with the encrypt module.
-      $encryption_array['method'] = 'mcrypt_rij_256';
-      $encryption_array['key_name'] = 'drupal_private_key';
-      $value = serialize($encryption_array);
-    }
     else {
       if (self::$showEncryptionWarning) {
-        MigrationBase::displayMessage(t('Encryption of secure migration information is not supported. Ensure the <a href="@encrypt">Encrypt module</a> or <a href="mcrypt">mcrypt PHP extension</a> is installed for this functionality.',
-            array(
-              '@encrypt' => 'http://drupal.org/project/encrypt',
-              '@mcrypt' => 'http://php.net/manual/en/book.mcrypt.php',
-            )
-          ),
+        MigrationBase::displayMessage(t('Encryption of secure migration information is not supported. Ensure the <a href="@encrypt">Encrypt module</a> is installed for this functionality.',
+          array(
+            '@encrypt' => 'http://drupal.org/project/encrypt',
+          )
+        ),
           'warning');
         self::$showEncryptionWarning = FALSE;
       }
@@ -1246,33 +1300,20 @@ abstract class MigrationBase {
    * Decrypt an incoming value.
    *
    * @param string $value
+   *
    * @return string The encrypted value
    */
   static public function decrypt($value) {
     if (module_exists('encrypt')) {
       $value = decrypt($value);
     }
-    else if (extension_loaded('mcrypt')) {
-      // Mimic encrypt module to ensure compatibility
-      $encryption_array = unserialize($value);
-      $method = $encryption_array['method']; // Not used right now
-      $text = $encryption_array['text'];
-      $key_name = $encryption_array['key_name']; // Not used right now
-
-      $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
-      $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
-      $key = drupal_substr(variable_get('drupal_private_key', 'no_key'), 0, 32);
-      $value = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $text,
-                              MCRYPT_MODE_ECB, $iv);
-    }
     else {
       if (self::$showEncryptionWarning) {
-        MigrationBase::displayMessage(t('Encryption of secure migration information is not supported. Ensure the <a href="@encrypt">Encrypt module</a> or <a href="mcrypt">mcrypt PHP extension</a> is installed for this functionality.',
-            array(
-              '@encrypt' => 'http://drupal.org/project/encrypt',
-              '@mcrypt' => 'http://php.net/manual/en/book.mcrypt.php',
-            )
-          ),
+        MigrationBase::displayMessage(t('Encryption of secure migration information is not supported. Ensure the <a href="@encrypt">Encrypt module</a> is installed for this functionality.',
+          array(
+            '@encrypt' => 'http://drupal.org/project/encrypt',
+          )
+        ),
           'warning');
         self::$showEncryptionWarning = FALSE;
       }
@@ -1329,12 +1370,18 @@ abstract class MigrationBase {
   }
 
   /**
-   * Convert an incoming string (which may be a UNIX timestamp, or an arbitrarily-formatted
-   * date/time string) to a UNIX timestamp.
+   * Convert an incoming string (which may be a UNIX timestamp, or an
+   * arbitrarily-formatted date/time string) to a UNIX timestamp.
    *
    * @param string $value
+   *   The time string to convert.
+   * @param string $timezone
+   *   Optional timezone for the time string. NULL to leave the timezone unset.
+   *
+   * @return string
+   *   The UNIX timestamp.
    */
-  static public function timestamp($value) {
+  static public function timestamp($value, $timezone = NULL) {
     // Does it look like it's already a timestamp? Just return it
     if (is_numeric($value)) {
       return $value;
@@ -1345,7 +1392,10 @@ abstract class MigrationBase {
       return time();
     }
 
-    $date = new DateTime($value);
+    if (isset($timezone)) {
+      $timezone = new DateTimeZone($timezone);
+    }
+    $date = new DateTime($value, $timezone);
     $time = $date->format('U');
     if ($time == FALSE) {
       // Handles form YYYY-MM-DD HH:MM:SS.garbage
@@ -1359,14 +1409,9 @@ abstract class MigrationBase {
   /**
    * Saves the current mail system, or set a system default if there is none.
    */
-  protected function saveMailSystem() {
+  public function saveMailSystem() {
     global $conf;
-    if (empty($conf['mail_system'])) {
-      $conf['mail_system']['default-system'] = 'MigrateMailIgnore';
-    }
-    else {
-      $this->mailSystem = $conf['mail_system'];
-    }
+    $this->mailSystem = empty($conf['mail_system']) ? NULL : $conf['mail_system'];
   }
 
   /**
@@ -1379,6 +1424,9 @@ abstract class MigrationBase {
         $conf['mail_system'][$system] = 'MigrateMailIgnore';
       }
     }
+    else {
+      $conf['mail_system'] = array('default-system' => 'MigrateMailIgnore');
+    }
   }
 
   /**

+ 17 - 9
sites/all/modules/contrib/migrate/migrate/includes/destination.inc

@@ -13,11 +13,12 @@
  * MigrateDestinationEntity for an example.
  */
 abstract class MigrateDestination {
+
   /**
    * To support MigrateSQLMap maps, derived destination classes should return
-   * schema field definition(s) corresponding to the primary key of the destination
-   * being implemented. These are used to construct the destination key fields
-   * of the map table for a migration using this destination.
+   * schema field definition(s) corresponding to the primary key of the
+   * destination being implemented. These are used to construct the destination
+   * key fields of the map table for a migration using this destination.
    *
    * abstract static public function getKeySchema()
    */
@@ -36,6 +37,7 @@ abstract class MigrateDestination {
    *
    * @param Migration $migration
    *  Optionally, the migration containing this destination.
+   *
    * @return array
    *  Keys: machine names of the fields (to be passed to addFieldMapping)
    *  Values: Human-friendly descriptions of the fields.
@@ -43,9 +45,9 @@ abstract class MigrateDestination {
   abstract public function fields();
 
   /**
-   * Derived classes must implement either bulkRollback or rollback() according to
-   * the signatures below, to rollback (usually by deletion) previously-migrated
-   * items.
+   * Derived classes must implement either bulkRollback or rollback() according
+   * to the signatures below, to rollback (usually by deletion)
+   * previously-migrated items.
    *
    * $ids is an array of single-field keys to be deleted
    * abstract public function bulkRollback(array $ids);
@@ -55,9 +57,10 @@ abstract class MigrateDestination {
    */
 
   /**
-   * Derived classes must implement import(), to construct one new object (pre-pppulated
-   * using field mappings in the Migration). It is expected to call prepare and
-   * complete handlers, passing them $row (the raw data from the source).
+   * Derived classes must implement import(), to construct one new object
+   * (pre-pppulated using field mappings in the Migration). It is expected to
+   * call prepare and complete handlers, passing them $row (the raw data from
+   * the source).
    */
   abstract public function import(stdClass $object, stdClass $row);
 
@@ -78,10 +81,13 @@ abstract class MigrateDestination {
    * @var int
    */
   protected $numCreated = 0;
+
   public function getCreated() {
     return $this->numCreated;
   }
+
   protected $numUpdated = 0;
+
   public function getUpdated() {
     return $this->numUpdated;
   }
@@ -105,6 +111,7 @@ abstract class MigrateDestination {
  * All destination handlers should be derived from MigrateDestinationHandler
  */
 abstract class MigrateDestinationHandler extends MigrateHandler {
+
   // Any one or more of these methods may be implemented
 
   /**
@@ -116,6 +123,7 @@ abstract class MigrateDestinationHandler extends MigrateHandler {
    *  The bundle (article, blog, etc.), if any, for which to list fields.
    * @param Migration $migration
    *  Optionally, the migration providing the context.
+   *
    * @return array
    *  An array keyed by field name, with field descriptions as values.
    */

+ 4 - 0
sites/all/modules/contrib/migrate/migrate/includes/exception.inc

@@ -6,11 +6,14 @@
  */
 
 class MigrateException extends Exception {
+
   /**
    * The level of the error being reported (a Migration::MESSAGE_* constant)
+   *
    * @var int
    */
   protected $level;
+
   public function getLevel() {
     return $this->level;
   }
@@ -22,6 +25,7 @@ class MigrateException extends Exception {
    * @var int
    */
   protected $status;
+
   public function getStatus() {
     return $this->status;
   }

+ 35 - 5
sites/all/modules/contrib/migrate/migrate/includes/field_mapping.inc

@@ -7,6 +7,7 @@
  */
 
 class MigrateFieldMapping {
+
   /**
    * Destination field name for the mapping. If empty, the mapping is just a
    * stub for annotating the source field.
@@ -14,6 +15,7 @@ class MigrateFieldMapping {
    * @var string
    */
   protected $destinationField;
+
   public function getDestinationField() {
     return $this->destinationField;
   }
@@ -25,6 +27,7 @@ class MigrateFieldMapping {
    * @var string
    */
   protected $sourceField;
+
   public function getSourceField() {
     return $this->sourceField;
   }
@@ -33,11 +36,15 @@ class MigrateFieldMapping {
    * @var int
    */
   const MAPPING_SOURCE_CODE = 1;
+
   const MAPPING_SOURCE_DB = 2;
+
   protected $mappingSource = self::MAPPING_SOURCE_CODE;
+
   public function getMappingSource() {
     return $this->mappingSource;
   }
+
   public function setMappingSource($mapping_source) {
     $this->mappingSource = $mapping_source;
   }
@@ -50,6 +57,7 @@ class MigrateFieldMapping {
    * @var mixed
    */
   protected $defaultValue;
+
   public function getDefaultValue() {
     return $this->defaultValue;
   }
@@ -61,6 +69,7 @@ class MigrateFieldMapping {
    * @var string
    */
   protected $separator;
+
   public function getSeparator() {
     return $this->separator;
   }
@@ -74,6 +83,7 @@ class MigrateFieldMapping {
    *   An array of source migrations, or string for a single migration.
    */
   protected $sourceMigration;
+
   public function getSourceMigration() {
     return $this->sourceMigration;
   }
@@ -84,6 +94,7 @@ class MigrateFieldMapping {
    * @var string
    */
   protected $callbacks = array();
+
   public function getCallbacks() {
     return $this->callbacks;
   }
@@ -99,6 +110,7 @@ class MigrateFieldMapping {
    * @var string
    */
   protected $dedupe;
+
   public function getDedupe() {
     return $this->dedupe;
   }
@@ -106,41 +118,49 @@ class MigrateFieldMapping {
   /**
    * Argument overrides. If present this will be an array, keyed by
    * a field API array key, with one or both of these entries:
-   * 'source_field' - Name of the source field in the incoming row containing the
-   *  value to be assigned
-   * 'default_value' - A constant value to be assigned in the absence of source_field
-   * Deprecated - subfield notation is now preferred.
+   * 'source_field' - Name of the source field in the incoming row containing
+   * the value to be assigned
+   * 'default_value' - A constant value to be assigned in the absence of
+   * source_field Deprecated - subfield notation is now preferred.
    *
    * @var array
    */
   protected $arguments;
+
   public function getArguments() {
     return $this->arguments;
   }
 
   protected $description = '';
+
   public function getDescription() {
     return $this->description;
   }
 
   protected $issueGroup;
+
   public function getIssueGroup() {
     return $this->issueGroup;
   }
 
   protected $issueNumber;
+
   public function getIssueNumber() {
     return $this->issueNumber;
   }
 
   protected $issuePriority = self::ISSUE_PRIORITY_OK;
+
   public function getIssuePriority() {
     return $this->issuePriority;
   }
 
   const ISSUE_PRIORITY_OK = 1;
+
   const ISSUE_PRIORITY_LOW = 2;
+
   const ISSUE_PRIORITY_MEDIUM = 3;
+
   const ISSUE_PRIORITY_BLOCKER = 4;
 
   public static $priorities = array();
@@ -177,7 +197,17 @@ class MigrateFieldMapping {
   }
 
   public function callbacks($callbacks) {
-    $this->callbacks = func_get_args();
+    foreach (func_get_args() as $callback) {
+      $this->callback($callback);
+    }
+    return $this;
+  }
+
+  public function callback($callback) {
+    $this->callbacks[] = array(
+      'callback' => $callback,
+      'params' => array_slice(func_get_args(), 1),
+    );
     return $this;
   }
 

+ 18 - 12
sites/all/modules/contrib/migrate/migrate/includes/group.inc

@@ -6,12 +6,14 @@
  */
 
 class MigrateGroup {
+
   /**
    * The machine name of the group - used to identify it in drush commands.
    *
    * @var string
    */
   protected $name;
+
   public function getName() {
     return $this->name;
   }
@@ -22,6 +24,7 @@ class MigrateGroup {
    * @var string
    */
   protected $title;
+
   public function getTitle() {
     return $this->title;
   }
@@ -33,6 +36,7 @@ class MigrateGroup {
    * @var array
    */
   protected $arguments = array();
+
   public function getArguments() {
     return $this->arguments;
   }
@@ -43,6 +47,7 @@ class MigrateGroup {
    * @var array
    */
   protected $dependencies = array();
+
   public function getDependencies() {
     return $this->dependencies;
   }
@@ -53,6 +58,7 @@ class MigrateGroup {
    * @var array
    */
   static protected $groupList = array();
+
   static public function groups() {
     $groups = array();
     $dependent_groups = array();
@@ -110,10 +116,10 @@ class MigrateGroup {
   static public function getInstance($name, $dependencies = array()) {
     if (empty(self::$groupList[$name])) {
       $row = db_select('migrate_group', 'mg')
-             ->fields('mg')
-             ->condition('name', $name)
-             ->execute()
-             ->fetchObject();
+        ->fields('mg')
+        ->condition('name', $name)
+        ->execute()
+        ->fetchObject();
       if ($row) {
         $arguments = unserialize($row->arguments);
         $arguments = MigrationBase::decryptArguments($arguments);
@@ -141,8 +147,8 @@ class MigrateGroup {
    *  A user-visible title for the group. Defaults to the machine name.
    *
    * @param array $arguments
-   *  An array of group arguments - generally data that applies to all migrations
-   *  in the group.
+   *  An array of group arguments - generally data that applies to all
+   *   migrations in the group.
    */
   static public function register($name, $title = NULL, array $arguments = array()) {
     if (!$title) {
@@ -156,9 +162,9 @@ class MigrateGroup {
     db_merge('migrate_group')
       ->key(array('name' => $name))
       ->fields(array(
-                'title' => $title,
-                'arguments' => serialize($arguments)
-        ))
+        'title' => $title,
+        'arguments' => serialize($arguments),
+      ))
       ->execute();
   }
 
@@ -172,9 +178,9 @@ class MigrateGroup {
    */
   static public function deregister($name) {
     $result = db_select('migrate_status', 'ms')
-              ->fields('ms', array('machine_name'))
-              ->condition('group_name', $name)
-              ->execute();
+      ->fields('ms', array('machine_name'))
+      ->condition('group_name', $name)
+      ->execute();
     foreach ($result as $row) {
       Migration::deregisterMigration($row->machine_name);
     }

+ 5 - 1
sites/all/modules/contrib/migrate/migrate/includes/handler.inc

@@ -10,12 +10,15 @@
  * to implement appropriate methods (e.g., prepare, complete, or fields).
  */
 abstract class MigrateHandler {
+
   /**
-   * List of other handler classes which should be invoked before the current one.
+   * List of other handler classes which should be invoked before the current
+   * one.
    *
    * @var array
    */
   protected $dependencies = array();
+
   public function getDependencies() {
     return $this->dependencies;
   }
@@ -27,6 +30,7 @@ abstract class MigrateHandler {
    * @var array
    */
   protected $typesHandled = array();
+
   public function getTypesHandled() {
     return $this->typesHandled;
   }

+ 20 - 7
sites/all/modules/contrib/migrate/migrate/includes/map.inc

@@ -10,12 +10,16 @@
  * for the purpose of rollback.
  */
 abstract class MigrateMap implements Iterator {
+
   /**
    * Codes reflecting the current status of a map row.
    */
   const STATUS_IMPORTED = 0;
+
   const STATUS_NEEDS_UPDATE = 1;
+
   const STATUS_IGNORED = 2;
+
   const STATUS_FAILED = 3;
 
   /**
@@ -23,6 +27,7 @@ abstract class MigrateMap implements Iterator {
    *
    */
   const ROLLBACK_DELETE = 0;
+
   const ROLLBACK_PRESERVE = 1;
 
   /**
@@ -32,7 +37,9 @@ abstract class MigrateMap implements Iterator {
    * @var array
    */
   protected $sourceKey, $destinationKey;
+
   abstract public function getSourceKey();
+
   abstract public function getDestinationKey();
 
   /**
@@ -56,9 +63,11 @@ abstract class MigrateMap implements Iterator {
    * @var boolean
    */
   protected $trackLastImported = FALSE;
+
   public function getTrackLastImported() {
     return $this->trackLastImported;
   }
+
   public function setTrackLastImported($trackLastImported) {
     if (is_bool($trackLastImported)) {
       $this->trackLastImported = $trackLastImported;
@@ -76,8 +85,8 @@ abstract class MigrateMap implements Iterator {
    * @param $hash
    */
   abstract public function saveIDMapping(stdClass $source_row, array $dest_ids,
-    $status = MigrateMap::STATUS_IMPORTED,
-    $rollback_action = MigrateMap::ROLLBACK_DELETE, $hash = NULL);
+                                         $status = MigrateMap::STATUS_IMPORTED,
+                                         $rollback_action = MigrateMap::ROLLBACK_DELETE, $hash = NULL);
 
   /**
    * Record a message related to a source record
@@ -147,6 +156,7 @@ abstract class MigrateMap implements Iterator {
    * Retrieve map data for a given source or destination item
    */
   abstract public function getRowBySource(array $source_id);
+
   abstract public function getRowByDestination(array $destination_id);
 
   /**
@@ -155,29 +165,32 @@ abstract class MigrateMap implements Iterator {
   abstract public function getRowsNeedingUpdate($count);
 
   /**
-   * Given a (possibly multi-field) destination key, return the (possibly multi-field)
-   * source key mapped to it.
+   * Given a (possibly multi-field) destination key, return the (possibly
+   * multi-field) source key mapped to it.
    *
    * @param array $destination_id
    *  Array of destination key values.
+   *
    * @return array
    *  Array of source key values, or NULL on failure.
    */
   abstract public function lookupSourceID(array $destination_id);
 
   /**
-   * Given a (possibly multi-field) source key, return the (possibly multi-field)
-   * destination key it is mapped to.
+   * Given a (possibly multi-field) source key, return the (possibly
+   * multi-field) destination key it is mapped to.
    *
    * @param array $source_id
    *  Array of source key values.
+   *
    * @return array
    *  Array of destination key values, or NULL on failure.
    */
   abstract public function lookupDestinationID(array $source_id);
 
   /**
-   * Remove any persistent storage used by this map (e.g., map and message tables)
+   * Remove any persistent storage used by this map (e.g., map and message
+   * tables)
    */
   abstract public function destroy();
 }

+ 198 - 132
sites/all/modules/contrib/migrate/migrate/includes/migration.inc

@@ -8,20 +8,24 @@
 /**
  * The base class for all import objects. This is where most of the smarts
  * of the migrate module resides. Migrations are created by deriving from this
- * class, and in the constructor (after calling parent::__construct()) initializing
- * at a minimum the name, description, source, and destination properties. The constructor
- * will also usually make several calls to addFieldMapping().
+ * class, and in the constructor (after calling parent::__construct())
+ * initializing at a minimum the name, description, source, and destination
+ * properties. The constructor will also usually make several calls to
+ * addFieldMapping().
  */
 abstract class Migration extends MigrationBase {
+
   /**
    * Source object for the migration, derived from MigrateSource.
    *
    * @var MigrateSource
    */
   protected $source;
+
   public function getSource() {
     return $this->source;
   }
+
   public function setSource(MigrateSource $source) {
     $this->source = $source;
   }
@@ -32,9 +36,11 @@ abstract class Migration extends MigrationBase {
    * @var MigrateDestination
    */
   protected $destination;
+
   public function getDestination() {
     return $this->destination;
   }
+
   public function setDestination(MigrateDestination $destination) {
     $this->destination = $destination;
   }
@@ -45,9 +51,11 @@ abstract class Migration extends MigrationBase {
    * @var MigrateMap
    */
   protected $map;
+
   public function getMap() {
     return $this->map;
   }
+
   public function setMap(MigrateMap $map) {
     $this->map = $map;
   }
@@ -63,11 +71,15 @@ abstract class Migration extends MigrationBase {
    * @var int
    */
   const SOURCE = 1;
+
   const DESTINATION = 2;
+
   protected $systemOfRecord = Migration::SOURCE;
+
   public function getSystemOfRecord() {
     return $this->systemOfRecord;
   }
+
   public function setSystemOfRecord($system_of_record) {
     $this->systemOfRecord = $system_of_record;
   }
@@ -87,9 +99,11 @@ abstract class Migration extends MigrationBase {
    * @var int
    */
   protected $defaultRollbackAction = MigrateMap::ROLLBACK_DELETE;
+
   public function getDefaultRollbackAction() {
     return $this->defaultRollbackAction;
   }
+
   public function setDefaultRollbackAction($rollback_action) {
     $this->defaultRollbackAction = $rollback_action;
   }
@@ -107,7 +121,9 @@ abstract class Migration extends MigrationBase {
    * @var array
    */
   protected $storedFieldMappings = array();
+
   protected $storedFieldMappingsRetrieved = FALSE;
+
   public function getStoredFieldMappings() {
     if (!$this->storedFieldMappingsRetrieved) {
       $this->loadFieldMappings();
@@ -122,6 +138,7 @@ abstract class Migration extends MigrationBase {
    * @var array
    */
   protected $codedFieldMappings = array();
+
   public function getCodedFieldMappings() {
     return $this->codedFieldMappings;
   }
@@ -133,10 +150,11 @@ abstract class Migration extends MigrationBase {
    * @var array
    */
   protected $allFieldMappings = array();
+
   public function getFieldMappings() {
     if (empty($allFieldMappings)) {
       $this->allFieldMappings = array_merge($this->getCodedFieldMappings(),
-                                            $this->getStoredFieldMappings());
+        $this->getStoredFieldMappings());
       // If there are multiple mappings of a given source field to no
       // destination field, keep only the last (so the UI can override a source
       // field DNM that was defined in code).
@@ -193,21 +211,25 @@ abstract class Migration extends MigrationBase {
    * @var array
    */
   protected $highwaterField = array();
+
   public function getHighwaterField() {
     return $this->highwaterField;
   }
+
   public function setHighwaterField(array $highwater_field) {
     $this->highwaterField = $highwater_field;
   }
 
   /**
    * The object currently being constructed
+   *
    * @var stdClass
    */
   protected $destinationValues;
 
   /**
    * The current data row retrieved from the source.
+   *
    * @var stdClass
    */
   protected $sourceValues;
@@ -238,7 +260,7 @@ abstract class Migration extends MigrationBase {
    * @param array $arguments
    */
   static public function registerMigration($class_name, $machine_name = NULL,
-      array $arguments = array()) {
+                                           array $arguments = array()) {
     // Record any field mappings provided via arguments.
     if (isset($arguments['field_mappings'])) {
       self::saveFieldMappings($machine_name, $arguments['field_mappings']);
@@ -270,14 +292,13 @@ abstract class Migration extends MigrationBase {
 
       // Remove stored field mappings for this migration
       $rows_deleted = db_delete('migrate_field_mapping')
-                      ->condition('machine_name', $machine_name)
-                      ->execute();
+        ->condition('machine_name', $machine_name)
+        ->execute();
 
       // Call the parent deregistration (which clears migrate_status) last, the
       // above will reference it.
       parent::deregisterMigration($machine_name);
-    }
-    catch (Exception $e) {
+    } catch (Exception $e) {
       // Fail silently if it's already gone
     }
   }
@@ -298,11 +319,11 @@ abstract class Migration extends MigrationBase {
       $source_field = $field_mapping->getSourceField();
       db_insert('migrate_field_mapping')
         ->fields(array(
-            'machine_name' => $machine_name,
-            'destination_field' => is_null($destination_field) ? '' : $destination_field,
-            'source_field' => is_null($source_field) ? '' : $source_field,
-            'options' => serialize($field_mapping)
-          ))
+          'machine_name' => $machine_name,
+          'destination_field' => is_null($destination_field) ? '' : $destination_field,
+          'source_field' => is_null($source_field) ? '' : $source_field,
+          'options' => serialize($field_mapping),
+        ))
         ->execute();
     }
   }
@@ -312,9 +333,9 @@ abstract class Migration extends MigrationBase {
    */
   public function loadFieldMappings() {
     $result = db_select('migrate_field_mapping', 'mfm')
-              ->fields('mfm', array('destination_field', 'source_field', 'options'))
-              ->condition('machine_name', $this->machineName)
-              ->execute();
+      ->fields('mfm', array('destination_field', 'source_field', 'options'))
+      ->condition('machine_name', $this->machineName)
+      ->execute();
     foreach ($result as $row) {
       $field_mapping = unserialize($row->options);
       $field_mapping->setMappingSource(MigrateFieldMapping::MAPPING_SOURCE_DB);
@@ -346,11 +367,14 @@ abstract class Migration extends MigrationBase {
                                   $warn_on_override = TRUE) {
     // Warn of duplicate mappings
     if ($warn_on_override && !is_null($destination_field) &&
-        isset($this->codedFieldMappings[$destination_field])) {
+      isset($this->codedFieldMappings[$destination_field])) {
       self::displayMessage(
         t('!name addFieldMapping: !dest was previously mapped from !source, overridden',
-          array('!name' => $this->machineName, '!dest' => $destination_field,
-                '!source' => $this->codedFieldMappings[$destination_field]->getSourceField())),
+          array(
+            '!name' => $this->machineName,
+            '!dest' => $destination_field,
+            '!source' => $this->codedFieldMappings[$destination_field]->getSourceField(),
+          )),
         'warning');
     }
     $mapping = new MigrateFieldMapping($destination_field, $source_field);
@@ -413,7 +437,7 @@ abstract class Migration extends MigrationBase {
     }
     foreach ($fields as $field) {
       $this->addFieldMapping($field, NULL, $warn_on_override)
-           ->issueGroup($issue_group);
+        ->issueGroup($issue_group);
     }
   }
 
@@ -433,7 +457,7 @@ abstract class Migration extends MigrationBase {
     }
     foreach ($fields as $field) {
       $this->addFieldMapping(NULL, $field, $warn_on_override)
-           ->issueGroup($issue_group);
+        ->issueGroup($issue_group);
     }
   }
 
@@ -464,7 +488,7 @@ abstract class Migration extends MigrationBase {
 
     // Do some standard setup
     if (isset($this->options['feedback']) && isset($this->options['feedback']['value']) &&
-        isset($this->options['feedback']['unit'])) {
+      isset($this->options['feedback']['unit'])) {
       $this->feedback = $this->options['feedback']['value'];
       $this->feedback_unit = $this->options['feedback']['unit'];
       if ($this->feedback_unit == 'item') {
@@ -477,7 +501,7 @@ abstract class Migration extends MigrationBase {
     $this->lastfeedback = $this->starttime;
 
     $this->total_processed = $this->total_successes =
-      $this->processed_since_feedback = $this->successes_since_feedback = 0;
+    $this->processed_since_feedback = $this->successes_since_feedback = 0;
 
     // Call pre-process methods
     if ($this->status == Migration::STATUS_IMPORTING) {
@@ -572,7 +596,7 @@ abstract class Migration extends MigrationBase {
         // Note that bulk rollback is only supported for single-column keys
         $sourceids[] = $current_source_key;
         if (!empty($destination_key->destid1)) {
-          $map_row = $this->map->getRowByDestination((array)$destination_key);
+          $map_row = $this->map->getRowByDestination((array) $destination_key);
           if ($map_row['rollback_action'] == MigrateMap::ROLLBACK_DELETE) {
             $destids[] = $destination_key->destid1;
           }
@@ -594,8 +618,7 @@ abstract class Migration extends MigrationBase {
             migrate_instrument_stop('rollback map/message update');
             $this->total_successes += $batch_count;
             $this->successes_since_feedback += $batch_count;
-          }
-          catch (Exception $e) {
+          } catch (Exception $e) {
             $this->handleException($e, FALSE);
             migrate_instrument_stop('bulkRollback');
             migrate_instrument_stop('rollback map/message update');
@@ -656,10 +679,10 @@ abstract class Migration extends MigrationBase {
               }
             }
             if (!$skip) {
-              $map_row = $this->map->getRowByDestination((array)$destination_key);
+              $map_row = $this->map->getRowByDestination((array) $destination_key);
               if ($map_row['rollback_action'] == MigrateMap::ROLLBACK_DELETE) {
                 migrate_instrument_start('destination rollback');
-                $this->destination->rollback((array)$destination_key);
+                $this->destination->rollback((array) $destination_key);
                 migrate_instrument_stop('destination rollback');
               }
             }
@@ -670,8 +693,7 @@ abstract class Migration extends MigrationBase {
           migrate_instrument_stop('rollback map/message update');
           $this->total_successes++;
           $this->successes_since_feedback++;
-        }
-        catch (Exception $e) {
+        } catch (Exception $e) {
           // TODO: At least count failures
           continue;
         }
@@ -701,11 +723,15 @@ abstract class Migration extends MigrationBase {
 
     try {
       $this->source->rewind();
-    }
-    catch (Exception $e) {
+    } catch (Exception $e) {
       self::displayMessage(
-        t('Migration failed with source plugin exception: %e, in %file:%line',
-          array('%e' => $e->getMessage(), '%file' => $e->getFile(), '%line' => $e->getLine())));
+        t('Migration for %class failed with source plugin exception: %e, in %file:%line',
+          array(
+            '%class' => get_class($this),
+            '%e' => $e->getMessage(),
+            '%file' => $e->getFile(),
+            '%line' => $e->getLine(),
+          )));
       return MigrationBase::RESULT_FAILED;
     }
     while ($this->source->valid()) {
@@ -732,24 +758,22 @@ abstract class Migration extends MigrationBase {
         else {
           $this->map->saveIDMapping($this->sourceValues, array(),
             MigrateMap::STATUS_FAILED, $this->rollbackAction,
-            $data_row->migrate_map_hash);
+            NULL);
           if ($this->map->messageCount() == 0) {
             $message = t('New object was not saved, no error provided');
             $this->saveMessage($message);
             self::displayMessage($message);
           }
         }
-      }
-      catch (MigrateException $e) {
+      } catch (MigrateException $e) {
         $this->map->saveIDMapping($this->sourceValues, array(),
           $e->getStatus(), $this->rollbackAction, $data_row->migrate_map_hash);
         $this->saveMessage($e->getMessage(), $e->getLevel());
         self::displayMessage($e->getMessage());
-      }
-      catch (Exception $e) {
+      } catch (Exception $e) {
         $this->map->saveIDMapping($this->sourceValues, array(),
           MigrateMap::STATUS_FAILED, $this->rollbackAction,
-          $data_row->migrate_map_hash);
+          NULL);
         $this->handleException($e);
       }
       $this->total_processed++;
@@ -779,11 +803,15 @@ abstract class Migration extends MigrationBase {
       }
       try {
         $this->source->next();
-      }
-      catch (Exception $e) {
+      } catch (Exception $e) {
         self::displayMessage(
-          t('Migration failed with source plugin exception: %e, in %file:%line',
-            array('%e' => $e->getMessage(), '%file' => $e->getFile(), '%line' => $e->getLine())));
+          t('Migration for %class failed with source plugin exception: %e, in %file:%line',
+            array(
+              '%class' => get_class($this),
+              '%e' => $e->getMessage(),
+              '%file' => $e->getFile(),
+              '%line' => $e->getLine(),
+            )));
         return MigrationBase::RESULT_FAILED;
       }
     }
@@ -805,8 +833,7 @@ abstract class Migration extends MigrationBase {
     self::$currentMigration = $this;
     try {
       $this->source->rewind();
-    }
-    catch (Exception $e) {
+    } catch (Exception $e) {
       self::displayMessage(
         t('Migration analysis failed with source plugin exception: !e',
           array('!e' => $e->getMessage())));
@@ -901,8 +928,7 @@ abstract class Migration extends MigrationBase {
 
       try {
         $this->source->next();
-      }
-      catch (Exception $e) {
+      } catch (Exception $e) {
         self::displayMessage(
           t('Migration analysis failed with source plugin exception: !e. Partial results follow:',
             array('!e' => $e->getMessage())));
@@ -940,17 +966,18 @@ abstract class Migration extends MigrationBase {
   public function prepareKey($source_key, $row) {
     $key = array();
     foreach ($source_key as $field_name => $field_schema) {
-      $key[$field_name] = $row->$field_name;
+      $key[$field_name] = $row->{$field_name};
     }
     return $key;
   }
 
   /**
-   * Default implementation of prepareRow(). This method is called from the source
-   * plugin upon first pulling the raw data from the source.
+   * Default implementation of prepareRow(). This method is called from the
+   * source plugin upon first pulling the raw data from the source.
    *
    * @param $row
    *  Object containing raw source data.
+   *
    * @return bool
    *  TRUE to process this row, FALSE to have the source skip it.
    */
@@ -971,8 +998,7 @@ abstract class Migration extends MigrationBase {
   public function sourceCount($refresh = FALSE) {
     try {
       $count = $this->source->count($refresh);
-    }
-    catch (Exception $e) {
+    } catch (Exception $e) {
       $count = t('N/A');
       self::displayMessage($e->getMessage());
     }
@@ -981,14 +1007,14 @@ abstract class Migration extends MigrationBase {
 
   /**
    * Get the number of source records processed.
+   *
    * @return int
    *  Number of processed records.
    */
   public function processedCount() {
     try {
       $count = $this->map->processedCount();
-    }
-    catch (Exception $e) {
+    } catch (Exception $e) {
       $count = t('N/A');
       self::displayMessage($e->getMessage());
     }
@@ -997,14 +1023,14 @@ abstract class Migration extends MigrationBase {
 
   /**
    * Get the number of records successfully imported.
+   *
    * @return int
    *  Number of imported records.
    */
   public function importedCount() {
     try {
       $count = $this->map->importedCount();
-    }
-    catch (Exception $e) {
+    } catch (Exception $e) {
       $count = t('N/A');
       self::displayMessage($e->getMessage());
     }
@@ -1013,13 +1039,13 @@ abstract class Migration extends MigrationBase {
 
   /**
    * Get the number of records marked as needing update.
+   *
    * @return int
    */
   public function updateCount() {
     try {
       $count = $this->map->updateCount();
-    }
-    catch (Exception $e) {
+    } catch (Exception $e) {
       $count = t('N/A');
       self::displayMessage($e->getMessage());
     }
@@ -1072,15 +1098,17 @@ abstract class Migration extends MigrationBase {
   }
 
   /**
-   * Outputs a progress message, reflecting the current status of a migration process.
+   * Outputs a progress message, reflecting the current status of a migration
+   * process.
    *
    * @param int $result
-   *  Status of the process, represented by one of the Migration::RESULT_* constants.
+   *  Status of the process, represented by one of the Migration::RESULT_*
+   *   constants.
    */
   protected function progressMessage($result) {
     $time = microtime(TRUE) - $this->lastfeedback;
     if ($time > 0) {
-      $perminute = round(60*$this->processed_since_feedback/$time);
+      $perminute = round(60 * $this->processed_since_feedback / $time);
       $time = round($time, 1);
     }
     else {
@@ -1129,31 +1157,37 @@ abstract class Migration extends MigrationBase {
     }
     $numitems = $this->processed_since_feedback + $this->source->getIgnored();
     $message = t($basetext,
-        array('!numitems' => $numitems,
-              '!successes' => $this->successes_since_feedback,
-              '!failed' => $this->processed_since_feedback - $this->successes_since_feedback,
-              '!created' => $this->destination->getCreated(),
-              '!updated' => $this->destination->getUpdated(),
-              '!ignored' => $this->source->getIgnored(),
-              '!time' => $time,
-              '!perminute' => $perminute,
-              '!name' => $this->machineName));
+      array(
+        '!numitems' => $numitems,
+        '!successes' => $this->successes_since_feedback,
+        '!failed' => $this->processed_since_feedback - $this->successes_since_feedback,
+        '!created' => $this->destination->getCreated(),
+        '!updated' => $this->destination->getUpdated(),
+        '!ignored' => $this->source->getIgnored(),
+        '!time' => $time,
+        '!perminute' => $perminute,
+        '!name' => $this->machineName,
+      ));
     self::displayMessage($message, $type);
 
     // Report on lookup_cache hit rate. Only visible at 'debug' level.
     if ($result != Migration::RESULT_INCOMPLETE && !empty($this->counts['lookup_cache'])) {
       foreach ($this->counts['lookup_cache'] as $name => $tallies) {
-        $tallies += array('hit' => 0, 'miss_hit' => 0, 'miss_miss' => 0); // Set defaults to avoid NOTICE.
-        $sum = $tallies['hit']+$tallies['miss_hit']+$tallies['miss_miss'];
+        $tallies += array(
+          'hit' => 0,
+          'miss_hit' => 0,
+          'miss_miss' => 0,
+        ); // Set defaults to avoid NOTICE.
+        $sum = $tallies['hit'] + $tallies['miss_hit'] + $tallies['miss_miss'];
         self::displayMessage(
           t('Lookup cache: !mn SM=!name !hit hit, !miss_hit miss_hit, !miss_miss miss_miss (!total total).', array(
-                '!mn' => $this->machineName,
-                '!name' => $name,
-                '!hit' => round((100*$tallies['hit'])/$sum) . '%',
-                '!miss_hit' => round((100*$tallies['miss_hit'])/$sum) . '%',
-                '!miss_miss' => round((100*$tallies['miss_miss'])/$sum) . '%',
-                '!total' => $sum
-        )), 'debug');
+            '!mn' => $this->machineName,
+            '!name' => $name,
+            '!hit' => round((100 * $tallies['hit']) / $sum) . '%',
+            '!miss_hit' => round((100 * $tallies['miss_hit']) / $sum) . '%',
+            '!miss_miss' => round((100 * $tallies['miss_miss']) / $sum) . '%',
+            '!total' => $sum,
+          )), 'debug');
       }
       $this->counts['lookup_cache'] = array();
     }
@@ -1182,7 +1216,7 @@ abstract class Migration extends MigrationBase {
     // If feedback is requested, produce a progress message at the proper time
     if (isset($this->feedback)) {
       if (($this->feedback_unit == 'seconds' && time() - $this->lastfeedback >= $this->feedback) ||
-          ($this->feedback_unit == 'items' && $this->processed_since_feedback >= $this->feedback)) {
+        ($this->feedback_unit == 'items' && $this->processed_since_feedback >= $this->feedback)) {
         $this->progressMessage(MigrationBase::RESULT_INCOMPLETE);
       }
     }
@@ -1214,7 +1248,7 @@ abstract class Migration extends MigrationBase {
         // If there's a source mapping, and a source value in the data row, copy
         // to the destination
         if ($source && isset($this->sourceValues->{$source})) {
-          $destination_values = $this->sourceValues->$source;
+          $destination_values = $this->sourceValues->{$source};
         }
         // Otherwise, apply the default value (if any)
         elseif (!is_null($default)) {
@@ -1225,7 +1259,25 @@ abstract class Migration extends MigrationBase {
         // will be populated as an array exploded from the source value
         $separator = $mapping->getSeparator();
         if ($separator && isset($destination_values)) {
-          $destination_values = explode($separator, $destination_values);
+          if (is_array($separator)) {
+            if (isset($separator['group separator'])) {
+              $destination_values = explode($separator['group separator'], $destination_values);
+            }
+            else {
+              $destination_values = array($destination_values);
+            }
+            foreach ($destination_values as $group => $value) {
+              if (isset($separator['key separator'])) {
+                $destination_values[$group] = explode($separator['key separator'], $value);
+              }
+              else {
+                $destination_values[$group] = array($value);
+              }
+            }
+          }
+          else {
+            $destination_values = explode($separator, $destination_values);
+          }
         }
 
         // If a source migration is supplied, use the current value for this field
@@ -1239,7 +1291,7 @@ abstract class Migration extends MigrationBase {
         $callbacks = $mapping->getCallbacks();
         foreach ($callbacks as $callback) {
           if (isset($destination_values)) {
-            $destination_values = call_user_func($callback, $destination_values);
+            $destination_values = call_user_func_array($callback['callback'], array_merge(array($destination_values), $callback['params']));
           }
         }
 
@@ -1262,7 +1314,7 @@ abstract class Migration extends MigrationBase {
             $destination_values['arguments'] = array();
             foreach ($arguments as $argname => $destarg) {
               if (is_array($destarg) && isset($destarg['source_field']) && property_exists($this->sourceValues, $destarg['source_field'])) {
-                $destination_values['arguments'][$argname] = $this->sourceValues->$destarg['source_field'];
+                $destination_values['arguments'][$argname] = $this->sourceValues->{$destarg['source_field']};
               }
               elseif (is_array($destarg) && isset($destarg['default_value'])) {
                 $destination_values['arguments'][$argname] = $destarg['default_value'];
@@ -1281,47 +1333,47 @@ abstract class Migration extends MigrationBase {
         // last one.
         $destination_count = count($destination);
         $destination_field = $destination[0];
-	      if ($destination_count == 2) {
+        if ($destination_count == 2) {
           $subfield = $destination[1];
           // We're processing the subfield before the primary value, initialize it
           if (!property_exists($this->destinationValues, $destination_field)) {
-            $this->destinationValues->$destination_field = array();
+            $this->destinationValues->{$destination_field} = array();
           }
           // We have a value, and need to convert to an array so we can add
           // arguments.
-          elseif (!is_array($this->destinationValues->$destination_field)) {
-            $this->destinationValues->$destination_field = array($this->destinationValues->$destination_field);
+          elseif (!is_array($this->destinationValues->{$destination_field})) {
+            $this->destinationValues->{$destination_field} = array($this->destinationValues->{$destination_field});
           }
           // Add the subfield value to the arguments array.
           $this->destinationValues->{$destination_field}['arguments'][$subfield] = $destination_values;
         }
         elseif ($destination_count == 3) {
-	        $subfield2 = $destination[2];
-	        // We're processing the subfield before the primary value, initialize it
-	        if (!property_exists($this->destinationValues, $destination_field)) {
-		        $this->destinationValues->$destination_field = array();
-	        }
-	        // We have a value, and need to convert to an array so we can add
-	        // arguments.
-	        elseif (!is_array($this->destinationValues->$destination_field)) {
-		        $this->destinationValues->$destination_field = array($this->destinationValues->$destination_field);
-	        }
-	        if (!is_array($this->destinationValues->{$destination_field}['arguments'][$destination[1]])) {
-		        // Convert first subfield level to an array so we can add to it.
-		        $this->destinationValues->{$destination_field}['arguments'][$destination[1]] = array( $this->destinationValues->{$destination_field}['arguments'][$destination[1]] );
-	        }
-	        // Add the subfield value to the arguments array.
-	        $this->destinationValues->{$destination_field}['arguments'][$destination[1]]['arguments'][$subfield2] = $destination_values;
+          $subfield2 = $destination[2];
+          // We're processing the subfield before the primary value, initialize it
+          if (!property_exists($this->destinationValues, $destination_field)) {
+            $this->destinationValues->{$destination_field} = array();
+          }
+          // We have a value, and need to convert to an array so we can add
+          // arguments.
+          elseif (!is_array($this->destinationValues->{$destination_field})) {
+            $this->destinationValues->{$destination_field} = array($this->destinationValues->{$destination_field});
+          }
+          if (!is_array($this->destinationValues->{$destination_field}['arguments'][$destination[1]])) {
+            // Convert first subfield level to an array so we can add to it.
+            $this->destinationValues->{$destination_field}['arguments'][$destination[1]] = array($this->destinationValues->{$destination_field}['arguments'][$destination[1]]);
+          }
+          // Add the subfield value to the arguments array.
+          $this->destinationValues->{$destination_field}['arguments'][$destination[1]]['arguments'][$subfield2] = $destination_values;
         }
         // Just the primary value, the first time through for this field, simply
         // set it.
         elseif (!property_exists($this->destinationValues, $destination_field)) {
-          $this->destinationValues->$destination_field = $destination_values;
+          $this->destinationValues->{$destination_field} = $destination_values;
         }
         // We've seen a subfield, so add as an array value.
         else {
           $this->destinationValues->{$destination_field} = array_merge(
-            (array)$destination_values, $this->destinationValues->{$destination_field});
+            (array) $destination_values, $this->destinationValues->{$destination_field});
         }
       }
     }
@@ -1333,14 +1385,15 @@ abstract class Migration extends MigrationBase {
    * @param mixed $source_migrations
    *   An array of source migrations, or string for a single migration.
    * @param mixed $source_keys
-   *   Key(s) to be looked up against the source migration(s). This may be a simple
-   *   value (one single-field key), an array of values (multiple single-field keys
-   *   to each be looked up), or an array of arrays (multiple multi-field keys to
-   *   each be looked up).
+   *   Key(s) to be looked up against the source migration(s). This may be a
+   *   simple value (one single-field key), an array of values (multiple
+   *   single-field keys to each be looked up), or an array of arrays (multiple
+   *   multi-field keys to each be looked up).
    * @param mixed $default
    *   The default value, if no ID was found.
    * @param $migration
    *   The implementing migration.
+   *
    * @return
    *   Destination value(s) from the source migration(s), as a single value if
    *   a single key was passed in, or an array of values if there were multiple
@@ -1377,6 +1430,11 @@ abstract class Migration extends MigrationBase {
     // Instantiate each migration, and store back in the array.
     foreach ($source_migrations as $key => $source_migration) {
       $source_migrations[$key] = Migration::getInstance($source_migration);
+      if (!isset($source_migrations[$key])) {
+        MigrationBase::displayMessage(t('The @source cannot be resolved to a migration instance.',
+          array('@source' => $source_migration)));
+        unset($source_migrations[$key]);
+      }
     }
 
     $results = array();
@@ -1398,7 +1456,8 @@ abstract class Migration extends MigrationBase {
       // Loop through each source migration, checking for an existing dest ID.
       foreach ($source_migrations as $source_migration) {
         // Break out of the loop as soon as a destination ID is found.
-        if ($destids = $source_migration->getMap()->lookupDestinationID($source_key)) {
+        if ($destids = $source_migration->getMap()
+          ->lookupDestinationID($source_key)) {
           if (!empty($destids['destid1'])) {
             break;
           }
@@ -1448,16 +1507,18 @@ abstract class Migration extends MigrationBase {
   }
 
   /**
-   * For fields which require uniqueness, assign a new unique value if necessary.
+   * For fields which require uniqueness, assign a new unique value if
+   * necessary.
    *
    * @param array $dedupe
    *  An array with two keys, 'table' the name of the Drupal table and 'column'
    *  the column within that table where uniqueness must be maintained.
    * @param $original
    *  The value coming in, which must be checked for uniqueness.
+   *
    * @return string
-   *  The value to use - either the original, or a variation created by appending
-   *  a sequence number.
+   *  The value to use - either the original, or a variation created by
+   *   appending a sequence number.
    */
   protected function handleDedupe($dedupe, $original) {
     // If we're remigrating a previously-existing value, simply running through
@@ -1468,11 +1529,11 @@ abstract class Migration extends MigrationBase {
     if (isset($this->sourceValues->migrate_map_destid1)) {
       $key_field = key($this->destination->getKeySchema());
       $existing_value = db_select($dedupe['table'], 't')
-                        ->fields('t', array($dedupe['column']))
-                        ->range(0, 1)
-                        ->condition($key_field, $this->sourceValues->migrate_map_destid1)
-                        ->execute()
-                        ->fetchField();
+        ->fields('t', array($dedupe['column']))
+        ->range(0, 1)
+        ->condition($key_field, $this->sourceValues->migrate_map_destid1)
+        ->execute()
+        ->fetchField();
       // Note that if, for some reason, we don't find a value, fall through
       // to the normal deduping process
       if ($existing_value) {
@@ -1481,12 +1542,12 @@ abstract class Migration extends MigrationBase {
     }
     $i = 1;
     $candidate = $original;
-    while ($candidate_found = db_select($dedupe['table'], 't')
-                      ->fields('t', array($dedupe['column']))
-                      ->range(0, 1)
-                      ->condition('t.' . $dedupe['column'], $candidate)
-                      ->execute()
-                      ->fetchField()) {
+    while (db_select($dedupe['table'], 't')
+      ->fields('t', array($dedupe['column']))
+      ->range(0, 1)
+      ->condition('t.' . $dedupe['column'], $candidate)
+      ->execute()
+      ->rowCount() > 0) {
       // We already have the candidate value. Find a non-existing value.
       $i++;
       // @TODO: support custom replacement pattern instead of just append.
@@ -1494,9 +1555,11 @@ abstract class Migration extends MigrationBase {
     }
     if ($i > 1) {
       $message = t('Replacing !column !original with !candidate',
-                   array('!column' => $dedupe['column'],
-                         '!original' => $original,
-                         '!candidate' => $candidate));
+        array(
+          '!column' => $dedupe['column'],
+          '!original' => $original,
+          '!candidate' => $candidate,
+        ));
       $migration = Migration::currentMigration();
       $migration->saveMessage($message, Migration::MESSAGE_INFORMATIONAL);
     }
@@ -1515,7 +1578,7 @@ abstract class Migration extends MigrationBase {
         $data_row = new stdClass;
         $i = 0;
         foreach ($map_source_key as $key => $definition) {
-          $data_row->$key = $source_key[$i++];
+          $data_row->{$key} = $source_key[$i++];
         }
         $this->map->saveIDMapping($data_row, $destids,
           MigrateMap::STATUS_NEEDS_UPDATE, $this->defaultRollbackAction);
@@ -1577,15 +1640,18 @@ abstract class Migration extends MigrationBase {
  *  Migration instead.
  */
 abstract class DynamicMigration extends Migration {
+
   static $deprecationWarning = FALSE;
+
   public function __construct($arguments) {
     parent::__construct($arguments);
     if (variable_get('migrate_deprecation_warnings', 1) &&
-        !self::$deprecationWarning) {
+      !self::$deprecationWarning) {
       self::displayMessage(t('The DynamicMigration class is no longer necessary and is now deprecated - please derive your migration classes directly from Migration.'));
       self::$deprecationWarning = TRUE;
     }
   }
+
   /**
    * Overrides default of FALSE
    */

+ 14 - 9
sites/all/modules/contrib/migrate/migrate/includes/source.inc

@@ -13,6 +13,7 @@
  * MigrateSourceSQL for an example.
  */
 abstract class MigrateSource implements Iterator {
+
   /**
    * The current row from the quey
    *
@@ -26,6 +27,7 @@ abstract class MigrateSource implements Iterator {
    * @var array
    */
   protected $currentKey;
+
   public function getCurrentKey() {
     return $this->currentKey;
   }
@@ -50,6 +52,7 @@ abstract class MigrateSource implements Iterator {
    * @var int
    */
   protected $numIgnored = 0;
+
   public function getIgnored() {
     return $this->numIgnored;
   }
@@ -60,6 +63,7 @@ abstract class MigrateSource implements Iterator {
    * @var int
    */
   protected $numProcessed = 0;
+
   public function getProcessed() {
     return $this->numProcessed;
   }
@@ -160,7 +164,7 @@ abstract class MigrateSource implements Iterator {
     }
 
     if (!isset($this->cacheKey)) {
-      $this->cacheKey = md5((string)$this);
+      $this->cacheKey = md5((string) $this);
     }
 
     // If a refresh is requested, or we're not caching counts, ask the derived
@@ -227,17 +231,18 @@ abstract class MigrateSource implements Iterator {
   }
 
   /**
-   * Implementation of Iterator::key - called when entering a loop iteration, returning
-   * the key of the current row. It must be a scalar - we will serialize
-   * to fulfill the requirement, but using getCurrentKey() is preferable.
+   * Implementation of Iterator::key - called when entering a loop iteration,
+   * returning the key of the current row. It must be a scalar - we will
+   * serialize to fulfill the requirement, but using getCurrentKey() is
+   * preferable.
    */
   public function key() {
     return serialize($this->currentKey);
   }
 
   /**
-   * Implementation of Iterator::valid() - called at the top of the loop, returning
-   * TRUE to process the loop and FALSE to terminate it
+   * Implementation of Iterator::valid() - called at the top of the loop,
+   * returning TRUE to process the loop and FALSE to terminate it
    */
   public function valid() {
     return !is_null($this->currentRow);
@@ -292,7 +297,7 @@ abstract class MigrateSource implements Iterator {
         if ($map_row) {
           foreach ($map_row as $field => $value) {
             $field = 'migrate_map_' . $field;
-            $row->$field = $value;
+            $row->{$field} = $value;
           }
         }
       }
@@ -422,12 +427,12 @@ abstract class MigrateSource implements Iterator {
       // so we need to provide them with the necessary information (before and
       // after hashes).
       if ($this->trackChanges) {
-        $unhashed_row = clone ($row);
+        $unhashed_row = clone $row;
         // Remove all map data, otherwise we'll have a false positive on the
         // second import (attempt) on a row.
         foreach ($unhashed_row as $field => $data) {
           if (strpos($field, 'migrate_map_') === 0) {
-            unset($unhashed_row->$field);
+            unset($unhashed_row->{$field});
           }
         }
         $row->migrate_map_original_hash = isset($row->migrate_map_hash) ?

Some files were not shown because too many files changed in this diff