kolab.org/www
Torsten Grote
grote at kolabsys.com
Mon Oct 15 12:43:00 CEST 2012
kolab.org/www/drupal-7.15/sites/all/modules/feeds/README.txt | 5
kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.api.php | 66 +
kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.info | 9
kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.install | 27
kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.module | 156 ++
kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.pages.inc | 59
kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.plugins.inc | 2
kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.rules.inc | 16
kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.tokens.inc | 25
kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds_import/feeds_import.info | 6
kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds_import/feeds_import.module | 5
kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds_news/feeds_news.info | 6
kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds_news/feeds_news.module | 5
kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds_ui/feeds_ui.admin.inc | 290 ++++
kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds_ui/feeds_ui.info | 6
kolab.org/www/drupal-7.15/sites/all/modules/feeds/includes/FeedsConfigurable.inc | 48
kolab.org/www/drupal-7.15/sites/all/modules/feeds/includes/FeedsSource.inc | 26
kolab.org/www/drupal-7.15/sites/all/modules/feeds/libraries/ParserCSV.inc | 4
kolab.org/www/drupal-7.15/sites/all/modules/feeds/libraries/common_syndication_parser.inc | 4
kolab.org/www/drupal-7.15/sites/all/modules/feeds/libraries/http_request.inc | 85 -
kolab.org/www/drupal-7.15/sites/all/modules/feeds/mappers/date.inc | 1
kolab.org/www/drupal-7.15/sites/all/modules/feeds/mappers/field.inc | 127 --
kolab.org/www/drupal-7.15/sites/all/modules/feeds/mappers/file.inc | 10
kolab.org/www/drupal-7.15/sites/all/modules/feeds/mappers/link.inc | 49
kolab.org/www/drupal-7.15/sites/all/modules/feeds/mappers/number.inc | 74 +
kolab.org/www/drupal-7.15/sites/all/modules/feeds/mappers/path.inc | 120 +
kolab.org/www/drupal-7.15/sites/all/modules/feeds/mappers/profile.inc | 35
kolab.org/www/drupal-7.15/sites/all/modules/feeds/mappers/text.inc | 78 +
kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsCSVParser.inc | 5
kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsFetcher.inc | 5
kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsFileFetcher.inc | 2
kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsHTTPFetcher.inc | 4
kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsNodeProcessor.inc | 67 +
kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsParser.inc | 44
kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsPlugin.inc | 2
kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsProcessor.inc | 159 +-
kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsSimplePieParser.inc | 19
kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsSitemapParser.inc | 5
kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsSyndicationParser.inc | 7
kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsTermProcessor.inc | 72 -
kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsUserProcessor.inc | 19
kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/common_syndication_parser.test | 5
kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds.test | 208 +++
kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds/path_alias.csv | 10
kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds/profile.csv | 3
kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_date_time.test | 7
kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_config.test | 115 +
kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_date.test | 8
kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_field.test | 14
kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_file.test | 31
kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_link.test | 18
kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_path.test | 240 +++
kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_profile.test | 102 +
kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_taxonomy.test | 29
kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_parser_sitemap.test | 10
kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_processor_node.test | 97 +
kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_processor_term.test | 10
kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_processor_user.test | 45
kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_scheduler.test | 14
kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_tests.info | 6
kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_tests.module | 111 +
kolab.org/www/drupal-7.15/sites/all/modules/feeds/views/feeds.views.inc | 4
kolab.org/www/drupal-7.15/sites/all/modules/redirect/redirect.admin.inc | 13
kolab.org/www/drupal-7.15/sites/all/modules/redirect/redirect.admin.js | 28
kolab.org/www/drupal-7.15/sites/all/modules/redirect/redirect.info | 6
kolab.org/www/drupal-7.15/sites/all/modules/redirect/redirect.install | 166 ++
kolab.org/www/drupal-7.15/sites/all/modules/redirect/redirect.module | 127 +-
kolab.org/www/drupal-7.15/sites/all/modules/redirect/views/redirects.view | 106 -
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/CHANGELOG.txt | 19
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/LICENSE.txt | 601 +++++-----
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/README.txt | 3
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/ckeditor.inc | 141 ++
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/epiceditor.inc | 102 +
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/fckeditor.inc | 4
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/ckeditor-3.0.js | 37
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/epiceditor.js | 38
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/fckeditor-2.6.js | 17
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/fckeditor.config.js | 13
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/jwysiwyg.js | 24
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/markitup.js | 19
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/nicedit.js | 32
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/none.js | 26
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/openwysiwyg.js | 87 +
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/tinymce-2.js | 12
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/tinymce-3.js | 65 -
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/whizzywig-56.js | 62 -
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/whizzywig-60.js | 64 -
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/whizzywig.js | 72 -
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/wymeditor.js | 38
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/yui.js | 118 +
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/nicedit.inc | 6
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/openwysiwyg.inc | 4
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/tinymce.inc | 124 +-
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/whizzywig.inc | 6
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/wymeditor.inc | 43
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/yui.inc | 52
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/tests/wysiwyg_test.info | 6
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/tests/wysiwyg_test.module | 43
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg-dialog-page.tpl.php | 92 -
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.admin.inc | 75 -
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.api.php | 77 +
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.dialog.inc | 168 ++
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.features.inc | 92 +
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.info | 6
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.install | 1
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.js | 44
kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.module | 88 +
107 files changed, 4494 insertions(+), 1314 deletions(-)
New commits:
commit 6325dcbb75c8b5d682a26115285556a7d813e72f
Author: Torsten Grote <grote at kolabsys.com>
Date: Mon Oct 15 12:41:50 2012 +0200
feeds, redirect, wysiwyg
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/README.txt b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/README.txt
index f932d94..5c137a2 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/README.txt
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/README.txt
@@ -49,8 +49,9 @@ Installation
Feeds News, Feeds Import, Feeds Fast News (more info below).
- Make sure cron is correctly configured http://drupal.org/cron
- Go to import/ to import data.
-- To use SimplePie parser, download SimplePie and place simplepie.inc into
- feeds/libraries. Recommended version: 1.2.
+- To use SimplePie parser, download either the compiled or minified SimplePie
+ and place simplepie_[version].compiled.php into feeds/libraries as
+ simplepie.compiled.php. Recommended version: 1.3.
http://simplepie.org/
Feature modules
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.api.php b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.api.php
index 389da82..0154e90 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.api.php
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.api.php
@@ -104,8 +104,10 @@ function hook_feeds_after_parse(FeedsSource $source, FeedsParserResult $result)
* FeedsSource object that describes the source that is being imported.
* @param $entity
* The entity object.
+ * @param $item
+ * The parser result for this entity.
*/
-function hook_feeds_presave(FeedsSource $source, $entity) {
+function hook_feeds_presave(FeedsSource $source, $entity, $item) {
if ($entity->feeds_item->entity_type == 'node') {
// Skip saving this entity.
$entity->feeds_item->skip = TRUE;
@@ -205,6 +207,11 @@ function hook_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_nam
'name' => t('My custom node field'),
'description' => t('Description of what my custom node field does.'),
'callback' => 'my_module_set_target',
+
+ // Specify both summary_callback and form_callback to add a per mapping
+ // configuration form.
+ 'summary_callback' => 'my_module_summary_callback',
+ 'form_callback' => 'my_module_form_callback',
);
$targets['my_node_field2'] = array(
'name' => t('My Second custom node field'),
@@ -226,9 +233,11 @@ function hook_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_nam
* A string identifying the target on the node.
* @param $value
* The value to populate the target with.
- *
+ * @param $mapping
+ * Associative array of the mapping settings from the per mapping
+ * configuration form.
*/
-function my_module_set_target($source, $entity, $target, $value) {
+function my_module_set_target($source, $entity, $target, $value, $mapping) {
$entity->{$target}[$entity->language][0]['value'] = $value;
if (isset($source->importer->processor->config['input_format'])) {
$entity->{$target}[$entity->language][0]['format'] =
@@ -237,5 +246,56 @@ function my_module_set_target($source, $entity, $target, $value) {
}
/**
+ * Example of the summary_callback specified in
+ * hook_feeds_processor_targets_alter().
+ *
+ * @param $mapping
+ * Associative array of the mapping settings.
+ * @param $target
+ * Array of target settings, as defined by the processor or
+ * hook_feeds_processor_targets_alter().
+ * @param $form
+ * The whole mapping form.
+ * @param $form_state
+ * The form state of the mapping form.
+ *
+ * @return
+ * Returns, as a string that may contain HTML, the summary to display while
+ * the full form isn't visible.
+ * If the return value is empty, no summary and no option to view the form
+ * will be displayed.
+ */
+function my_module_summary_callback($mapping, $target, $form, $form_state) {
+ if (empty($mapping['my_setting'])) {
+ return t('My setting <strong>not</strong> active');
+ }
+ else {
+ return t('My setting <strong>active</strong>');
+ }
+}
+
+/**
+ * Example of the form_callback specified in
+ * hook_feeds_processor_targets_alter().
+ *
+ * The arguments are the same that my_module_summary_callback() gets.
+ *
+ * @see my_module_summary_callback()
+ *
+ * @return
+ * The per mapping configuration form. Once the form is saved, $mapping will
+ * be populated with the form values.
+ */
+function my_module_form_callback($mapping, $target, $form, $form_state) {
+ return array(
+ 'my_setting' => array(
+ '#type' => 'checkbox',
+ '#title' => t('My setting checkbox'),
+ '#default_value' => !empty($mapping['my_setting']),
+ ),
+ );
+}
+
+/**
* @}
*/
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.info b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.info
index 4844f36..c5d164d 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.info
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.info
@@ -16,7 +16,10 @@ files[] = tests/feeds_date_time.test
files[] = tests/feeds_mapper_date.test
files[] = tests/feeds_mapper_field.test
files[] = tests/feeds_mapper_file.test
+files[] = tests/feeds_mapper_path.test
+files[] = tests/feeds_mapper_profile.test
files[] = tests/feeds_mapper.test
+files[] = tests/feeds_mapper_config.test
files[] = tests/feeds_fetcher_file.test
files[] = tests/feeds_processor_node.test
files[] = tests/feeds_processor_term.test
@@ -32,9 +35,9 @@ files[] = views/feeds_views_handler_field_severity.inc
files[] = views/feeds_views_handler_field_source.inc
files[] = views/feeds_views_handler_filter_severity.inc
-; Information added by drupal.org packaging script on 2012-05-28
-version = "7.x-2.0-alpha5"
+; Information added by drupal.org packaging script on 2012-10-10
+version = "7.x-2.0-alpha6"
core = "7.x"
project = "feeds"
-datestamp = "1338228956"
+datestamp = "1349851321"
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.install b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.install
index 7a3322e..7584f4e 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.install
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.install
@@ -33,7 +33,8 @@ function feeds_schema() {
'description' => 'Id of the fields object.',
),
'config' => array(
- 'type' => 'text',
+ 'type' => 'blob',
+ 'size' => 'big',
'not null' => FALSE,
'description' => 'Configuration of the feeds object.',
'serialize' => TRUE,
@@ -59,7 +60,8 @@ function feeds_schema() {
'description' => 'Node nid if this particular source is attached to a feed node.',
),
'config' => array(
- 'type' => 'text',
+ 'type' => 'blob',
+ 'size' => 'big',
'not null' => FALSE,
'description' => 'Configuration of the source.',
'serialize' => TRUE,
@@ -538,3 +540,24 @@ function feeds_update_7206() {
'serialize' => TRUE,
));
}
+
+/**
+ * Change config fields from text to big blobs.
+ */
+function feeds_update_7207() {
+ db_change_field('feeds_importer', 'config', 'config', array(
+ 'type' => 'blob',
+ 'size' => 'big',
+ 'not null' => FALSE,
+ 'description' => 'Configuration of the feeds object.',
+ 'serialize' => TRUE,
+ ));
+
+ db_change_field('feeds_source', 'config', 'config', array(
+ 'type' => 'blob',
+ 'size' => 'big',
+ 'not null' => FALSE,
+ 'description' => 'Configuration of the feeds object.',
+ 'serialize' => TRUE,
+ ));
+}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.module b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.module
index 769fe42..0e1bda4 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.module
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.module
@@ -235,6 +235,10 @@ function feeds_permission() {
$perms["clear $importer->id feeds"] = array(
'title' => t('Delete items from @name feeds', array('@name' => $importer->config['name'])),
);
+ $perms["unlock $importer->id feeds"] = array(
+ 'title' => t('Unlock imports from @name feeds', array('@name' => $importer->config['name'])),
+ 'description' => t('If a feed importation breaks for some reason, users with this permission can unlock them.')
+ );
}
return $perms;
}
@@ -288,6 +292,15 @@ function feeds_menu() {
'file' => 'feeds.pages.inc',
'type' => MENU_LOCAL_TASK,
);
+ $items['import/%/unlock'] = array(
+ 'title' => 'Unlock',
+ 'page callback' => 'drupal_get_form',
+ 'page arguments' => array('feeds_unlock_tab_form', 1),
+ 'access callback' => 'feeds_access',
+ 'access arguments' => array('unlock', 1),
+ 'file' => 'feeds.pages.inc',
+ 'type' => MENU_LOCAL_TASK,
+ );
$items['import/%/template'] = array(
'page callback' => 'feeds_importer_template',
'page arguments' => array(1),
@@ -316,6 +329,16 @@ function feeds_menu() {
'type' => MENU_LOCAL_TASK,
'weight' => 11,
);
+ $items['node/%node/unlock'] = array(
+ 'title' => 'Unlock',
+ 'page callback' => 'drupal_get_form',
+ 'page arguments' => array('feeds_unlock_tab_form', NULL, 1),
+ 'access callback' => 'feeds_access',
+ 'access arguments' => array('unlock', 1),
+ 'file' => 'feeds.pages.inc',
+ 'type' => MENU_LOCAL_TASK,
+ 'weight' => 11,
+ );
// @todo Eliminate this step and thus eliminate clearing menu cache when
// manipulating importers.
foreach (feeds_importer_load_all() as $importer) {
@@ -367,11 +390,12 @@ function feeds_theme() {
* The action to be performed. Possible values are:
* - import
* - clear
+ * - unlock
* @param $param
* Node object or FeedsImporter id.
*/
function feeds_access($action, $param) {
- if (!in_array($action, array('import', 'clear'))) {
+ if (!in_array($action, array('import', 'clear', 'unlock'))) {
// If $action is not one of the supported actions, we return access denied.
return FALSE;
}
@@ -466,19 +490,19 @@ function feeds_feeds_plugins() {
}
/**
- * Implements hook_entity_load().
+ * Gets the feed_nid for a single entity.
+ *
+ * @param int $entity_id
+ * The entity id.
+ * @param string $entity_type
+ * The type of entity.
+ *
+ * @return int|bool
+ * The feed_nid of the entity, or FALSE if the entity doesn't belong to a
+ * feed.
*/
-function feeds_entity_load($entities, $type) {
- try {
- $feed_nids = db_query("SELECT entity_id, feed_nid FROM {feeds_item} WHERE entity_type = :type AND entity_id IN (:ids)", array(':type' => $type, ':ids' => array_keys($entities)))->fetchAllKeyed();
- foreach ($feed_nids as $id => $feed_nid) {
- $entities[$id]->feed_nid = $feed_nid;
- }
- }
- catch (Exception $e) {
- watchdog_exception('feeds', $e);
- // Do not re-throw $e.
- }
+function feeds_get_feed_nid($entity_id, $entity_type) {
+ return db_query("SELECT feed_nid FROM {feeds_item} WHERE entity_type = :type AND entity_id = :id", array(':type' => $entity_type, ':id' => $entity_id))->fetchField();
}
/**
@@ -897,10 +921,10 @@ function feeds_plugin($plugin, $id) {
$args = array('%plugin' => $plugin, '@id' => $id);
if (user_access('administer feeds')) {
$args['@link'] = url('admin/structure/feeds/' . $id);
- drupal_set_message(t('Missing Feeds plugin %plugin. See <a href="@link">@id</a>. Check whether all required libraries and modules are installed properly.', $args), 'warning');
+ drupal_set_message(t('Missing Feeds plugin %plugin. See <a href="@link">@id</a>. Check whether all required libraries and modules are installed properly.', $args), 'warning', FALSE);
}
else {
- drupal_set_message(t('Missing Feeds plugin %plugin. Please contact your site administrator.', $args), 'warning');
+ drupal_set_message(t('Missing Feeds plugin %plugin. Please contact your site administrator.', $args), 'warning', FALSE);
}
$class = ctools_plugin_load_class('feeds', 'plugins', 'FeedsMissingPlugin', 'handler');
return FeedsConfigurable::instance($class, $id);
@@ -928,29 +952,43 @@ function feeds_plugin($plugin, $id) {
function feeds_include_library($file, $library) {
static $included = array();
static $ignore_deprecated = array('simplepie');
+
if (!isset($included[$file])) {
// Disable deprecated warning for libraries known for throwing them
if (in_array($library, $ignore_deprecated)) {
$level = error_reporting();
// We can safely use E_DEPRECATED since Drupal 7 requires PHP 5.3+
- error_reporting($level & ~E_DEPRECATED);
+ error_reporting($level ^ E_DEPRECATED ^ E_STRICT);
}
+
+ $library_dir = variable_get('feeds_library_dir', FALSE);
+ $feeds_library_path = DRUPAL_ROOT . '/' . drupal_get_path('module', 'feeds') . "/libraries/$file";
+
// Try first whether libraries module is present and load the file from
// there. If this fails, require the library from the local path.
if (module_exists('libraries') && file_exists(libraries_get_path($library) . "/$file")) {
require libraries_get_path($library) . "/$file";
+ $included[$file] = TRUE;
}
- else {
+ elseif ($library_dir && file_exists("$library_dir/$library/$file")) {
+ require "$library_dir/$library/$file";
+ $included[$file] = TRUE;
+ }
+ elseif (file_exists($feeds_library_path)) {
// @todo: Throws "Deprecated function: Assigning the return value of new
// by reference is deprecated."
- require DRUPAL_ROOT . '/' . drupal_get_path('module', 'feeds') . "/libraries/$file";
+ require $feeds_library_path;
+ $included[$file] = TRUE;
}
// Restore error reporting level
if (isset($level)) {
error_reporting($level);
}
}
- $included[$file] = TRUE;
+ if (isset($included[$file])) {
+ return TRUE;
+ }
+ return FALSE;
}
/**
@@ -964,16 +1002,51 @@ function feeds_include_library($file, $library) {
* libraries module.
*/
function feeds_library_exists($file, $library) {
+
if (module_exists('libraries') && file_exists(libraries_get_path($library) . "/$file")) {
return TRUE;
}
+
elseif (file_exists(DRUPAL_ROOT . '/' . drupal_get_path('module', 'feeds') . "/libraries/$file")) {
return TRUE;
}
+
+ elseif ($library_dir = variable_get('feeds_library_dir', FALSE)) {
+ if (file_exists("$library_dir/$library/$file")) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+ /**
+ * Checks whether simplepie exists.
+ */
+function feeds_simplepie_exists() {
+ return (feeds_library_exists('simplepie.compiled.php', 'simplepie') ||
+ feeds_library_exists('simplepie.mini.php', 'simplepie') ||
+ feeds_library_exists('simplepie.inc', 'simplepie')
+ );
+}
+
+/**
+ * Includes the simplepie library.
+ */
+function feeds_include_simplepie() {
+ $files = array('simplepie.mini.php', 'simplepie.compiled.php', 'simplepie.inc');
+
+ foreach ($files as $file) {
+ if (feeds_include_library($file, 'simplepie')) {
+ return TRUE;
+ }
+ }
return FALSE;
}
/**
+ * @deprecated
+ *
* Simplified drupal_alter().
*
* - None of that 'multiple parameters by ref' crazyness.
@@ -1006,7 +1079,7 @@ function feeds_alter($type, &$data) {
*
* @see valid_url().
*
- * @todo Replace with valid_url() when http://drupal.org/node/1191252 is fixed.
+ * @todo Replace with valid_url() when http://drupal.org/node/295021 is fixed.
*/
function feeds_valid_url($url, $absolute = FALSE) {
if ($absolute) {
@@ -1023,7 +1096,7 @@ function feeds_valid_url($url, $absolute = FALSE) {
)
(?::[0-9]+)? # Server port number (optional)
(?:[\/|\?]
- (?:[\w#!:\.\?\+=&@$'~*,;\/\(\)\[\]\-]|%[0-9a-f]{2}) # The path and query (optional)
+ (?:[|\w#!:\.\?\+=&@$'~*,;\/\(\)\[\]\-]|%[0-9a-f]{2}) # The path and query (optional)
*)?
$/xi", $url);
}
@@ -1064,3 +1137,44 @@ function feeds_set_subscription_job(array $job = NULL) {
function feeds_get_subscription_jobs() {
return feeds_set_subscription_job();
}
+
+/**
+ * Implements hook_entity_property_info_alter().
+ */
+function feeds_entity_property_info_alter(&$info) {
+ // Gather entities supported by Feeds processors.
+ $processors = FeedsPlugin::byType('processor');
+ $supported_entities = array();
+ foreach ($processors as $processor) {
+ $instance = feeds_plugin($processor['handler']['class'], '__none__');
+ if (method_exists($instance, 'entityType')) {
+ $supported_entities[] = $instance->entityType();
+ }
+ }
+ // Feeds processors can fake the entity info. Only set the property for
+ // defined entities.
+ $supported_entities = array_intersect(array_keys($info), $supported_entities);
+
+ foreach ($supported_entities as $entity_type) {
+ $info[$entity_type]['properties']['feed_nid'] = array(
+ 'label' => 'Feed NID',
+ 'type' => 'integer',
+ 'description' => t('Nid of the Feed Node that imported this entity.'),
+ 'getter callback' => 'feeds_get_feed_nid_entity_callback',
+ );
+ }
+}
+
+/**
+ * Gets the feed_nid for an entity for use in entity metadata.
+ */
+function feeds_get_feed_nid_entity_callback($entity, array $options, $name, $entity_type) {
+ list($entity_id, , ) = entity_extract_ids($entity_type, $entity);
+
+ $feed_nid = feeds_get_feed_nid($entity_id, $entity_type);
+
+ if ($feed_nid === FALSE) {
+ return NULL;
+ }
+ return $feed_nid;
+}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.pages.inc b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.pages.inc
index b57955d..6f1481e 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.pages.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.pages.inc
@@ -194,6 +194,65 @@ function feeds_delete_tab_form_submit($form, &$form_state) {
}
/**
+ * Render a feeds unlock form.
+ *
+ * Used on both node pages and configuration pages.
+ * Therefore $node may be missing.
+ */
+function feeds_unlock_tab_form($form, &$form_state, $importer_id, $node = NULL) {
+ if (empty($node)) {
+ $source = feeds_source($importer_id);
+ $form['#redirect'] = 'import/' . $source->id;
+ }
+ else {
+ $importer_id = feeds_get_importer_id($node->type);
+ $source = feeds_source($importer_id, $node->nid);
+ $form['#redirect'] = 'node/' . $source->feed_nid;
+ }
+ // Form cannot pass on source object.
+ $form['#importer_id'] = $source->id;
+ $form['#feed_nid'] = $source->feed_nid;
+ $form['source_status'] = array(
+ '#type' => 'fieldset',
+ '#title' => t('Status'),
+ '#tree' => TRUE,
+ '#value' => feeds_source_status($source),
+ );
+ $form = confirm_form($form, t('Unlock this importer?'), $form['#redirect'], '', t('Delete'), t('Cancel'), 'confirm feeds update');
+ if ($source->progressImporting() == FEEDS_BATCH_COMPLETE && $source->progressClearing() == FEEDS_BATCH_COMPLETE) {
+ $form['source_locked'] = array(
+ '#type' => 'markup',
+ '#title' => t('Not Locked'),
+ '#tree' => TRUE,
+ '#markup' => t('This importer is not locked, therefore it cannot be unlocked.'),
+ );
+ $form['actions']['submit']['#disabled'] = TRUE;
+ $form['actions']['submit']['#value'] = t('Unlock (disabled)');
+ }
+ else {
+ $form['actions']['submit']['#value'] = t('Unlock');
+ }
+ return $form;
+}
+
+/**
+ * Form submit handler. Resets all feeds state.
+ */
+function feeds_unlock_tab_form_submit($form, &$form_state) {
+ drupal_set_message(t('Import Unlocked'));
+ $form_state['redirect'] = $form['#redirect'];
+ $feed_nid = empty($form['#feed_nid']) ? 0 : $form['#feed_nid'];
+ $importer_id = $form['#importer_id'];
+
+ //Is there a more API-friendly way to set the state?
+ db_update('feeds_source')
+ ->condition('id', $importer_id)
+ ->condition('feed_nid', $feed_nid)
+ ->fields(array('state' => FALSE))
+ ->execute();
+}
+
+/**
* Handle a fetcher callback.
*/
function feeds_fetcher_callback($importer, $feed_nid = 0) {
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.plugins.inc b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.plugins.inc
index 26d9bff..3f23cb8 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.plugins.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.plugins.inc
@@ -106,7 +106,7 @@ function _feeds_feeds_plugins() {
'path' => $path,
),
);
- if (feeds_library_exists('simplepie.inc', 'simplepie')) {
+ if (feeds_simplepie_exists()) {
$info['FeedsSimplePieParser'] = array(
'name' => 'SimplePie parser',
'description' => 'Parse RSS and Atom feeds.',
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.rules.inc b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.rules.inc
index 4dd583a..84b4685 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.rules.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.rules.inc
@@ -11,16 +11,26 @@
function feeds_rules_event_info() {
$info = array();
$entity_info = entity_get_info();
+
foreach (feeds_importer_load_all() as $importer) {
$config = $importer->getConfig();
$processor = feeds_plugin($config['processor']['plugin_key'], $importer->id);
+
+ // It's possible to get FeedsMissingPlugin here which will break things
+ // since it doesn't implement FeedsProcessor::entityType().
+ if (!$processor instanceof FeedsProcessor) {
+ continue;
+ }
+
$entity_type = $processor->entityType();
+ $label = isset($entity_info[$entity_type]['label']) ? $entity_info[$entity_type]['label'] : $entity_type;
+
$info['feeds_import_'. $importer->id] = array(
'label' => t('Before saving an item imported via @name.', array('@name' => $importer->config['name'])),
'group' => t('Feeds'),
'variables' => array(
$entity_type => array(
- 'label' => t('Imported @label', array('@label' => $entity_info[$entity_type]['label'])),
+ 'label' => t('Imported @label', array('@label' => $label)),
'type' => $entity_type,
// Saving is handled by feeds anyway (unless the skip action is used).
'skip save' => TRUE,
@@ -59,8 +69,8 @@ function feeds_rules_action_info() {
*/
function feeds_action_skip_item($entity_wrapper) {
$entity = $entity_wrapper->value();
- if(isset($entity->feeds_item)) {
- $entity->feeds_item->skip = TRUE;
+ if (isset($entity->feeds_item)) {
+ $entity->feeds_item->skip = TRUE;
}
}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.tokens.inc b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.tokens.inc
index 2078d47..cb7dc4c 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.tokens.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds.tokens.inc
@@ -25,24 +25,23 @@ function feeds_token_info() {
function feeds_tokens($type, $tokens, array $data, array $options) {
$replacements = array();
- $sanitize = !empty($options['sanitize']);
-
if ($type == 'node' && !empty($data['node'])) {
- $node = $data['node'];
- foreach ($tokens as $name => $original) {
- switch ($name) {
- case 'feed-source':
- if (!empty($node->feed_nid) && $feed_source = node_load($node->feed_nid)) {
+ $sanitize = !empty($options['sanitize']);
+
+ $feed_nid = feeds_get_feed_nid($data['node']->nid, 'node');
+
+ if ($feed_nid && $feed_source = node_load($feed_nid)) {
+ foreach ($tokens as $name => $original) {
+ switch ($name) {
+ case 'feed-source':
$replacements[$original] = $sanitize ? check_plain($feed_source->title) : $feed_source->title;
- }
- break;
+ break;
+ }
}
- }
- // Chained node token relationships.
- if ($feed_source_tokens = token_find_with_prefix($tokens, 'feed-source')) {
- if (!empty($node->feed_nid) && $feed_source = node_load($node->feed_nid)) {
+ // Chained node token relationships.
+ if ($feed_source_tokens = token_find_with_prefix($tokens, 'feed-source')) {
$replacements += token_generate('node', $feed_source_tokens, array('node' => $feed_source), $options);
}
}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds_import/feeds_import.info b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds_import/feeds_import.info
index 7781942..4d507eb 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds_import/feeds_import.info
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds_import/feeds_import.info
@@ -9,9 +9,9 @@ name = "Feeds Import"
package = "Feeds"
php = "5.2.4"
-; Information added by drupal.org packaging script on 2012-05-28
-version = "7.x-2.0-alpha5"
+; Information added by drupal.org packaging script on 2012-10-10
+version = "7.x-2.0-alpha6"
core = "7.x"
project = "feeds"
-datestamp = "1338228956"
+datestamp = "1349851321"
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds_import/feeds_import.module b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds_import/feeds_import.module
index a7b4753..044a4f1 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds_import/feeds_import.module
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds_import/feeds_import.module
@@ -1,3 +1,8 @@
<?php
+/**
+ * @file
+ * Empty module file.
+ */
+
include_once('feeds_import.features.inc');
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds_news/feeds_news.info b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds_news/feeds_news.info
index 70679ec..6e3e7e7 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds_news/feeds_news.info
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds_news/feeds_news.info
@@ -17,9 +17,9 @@ name = "Feeds News"
package = "Feeds"
php = "5.2.4"
-; Information added by drupal.org packaging script on 2012-05-28
-version = "7.x-2.0-alpha5"
+; Information added by drupal.org packaging script on 2012-10-10
+version = "7.x-2.0-alpha6"
core = "7.x"
project = "feeds"
-datestamp = "1338228956"
+datestamp = "1349851321"
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds_news/feeds_news.module b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds_news/feeds_news.module
index 5c4fce3..1310976 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds_news/feeds_news.module
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds_news/feeds_news.module
@@ -1,3 +1,8 @@
<?php
+/**
+ * @file
+ * Empty module file.
+ */
+
include_once('feeds_news.features.inc');
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds_ui/feeds_ui.admin.inc b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds_ui/feeds_ui.admin.inc
index b66f963..ee3f15e 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds_ui/feeds_ui.admin.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds_ui/feeds_ui.admin.inc
@@ -232,7 +232,7 @@ function feeds_ui_create_form_submit($form, &$form_state) {
* Delete configuration form.
*/
function feeds_ui_delete_form($form, &$form_state, $importer) {
- $form['#importer'] = $importer;
+ $form['#importer'] = $importer->id;
if ($importer->export_type & EXPORT_IN_CODE) {
$title = t('Would you really like to revert the importer @importer?', array('@importer' => $importer->config['name']));
$button_label = t('Revert');
@@ -257,7 +257,7 @@ function feeds_ui_delete_form_submit($form, &$form_state) {
$form_state['redirect'] = 'admin/structure/feeds';
// Remove importer.
- $form['#importer']->delete();
+ feeds_importer($form['#importer'])->delete();
// Clear cache, deleting a configuration may have an affect on menu tree.
feeds_cache_clear();
@@ -428,7 +428,7 @@ function feeds_ui_plugin_form($form, &$form_state, $importer, $type) {
$plugins = FeedsPlugin::byType($type);
$form = array();
- $form['#importer'] = $importer;
+ $form['#importer'] = $importer->id;
$form['#plugin_type'] = $type;
foreach ($plugins as $key => $plugin) {
@@ -454,8 +454,9 @@ function feeds_ui_plugin_form($form, &$form_state, $importer, $type) {
*/
function feeds_ui_plugin_form_submit($form, &$form_state) {
// Set the plugin and save feed.
- $form['#importer']->setPlugin($form_state['values']['plugin_key']);
- $form['#importer']->save();
+ $importer = feeds_importer($form['#importer']);
+ $importer->setPlugin($form_state['values']['plugin_key']);
+ $importer->save();
drupal_set_message(t('Changed @type plugin.', array('@type' => $form['#plugin_type'])));
}
@@ -497,9 +498,11 @@ function feeds_ui_mapping_form($form, &$form_state, $importer) {
drupal_add_js(drupal_get_path('module', 'feeds_ui') . '/feeds_ui.js');
$form = array();
- $form['#importer'] = $importer;
+ $form['#importer'] = $importer->id;
$form['#mappings'] = $mappings = $importer->processor->getMappings();
$form['help']['#markup'] = feeds_ui_mapping_help();
+ $form['#prefix'] = '<div id="feeds-ui-mapping-form-wrapper">';
+ $form['#suffix'] = '</div>';
// Get mapping sources from parsers and targets from processor, format them
// for output.
@@ -531,29 +534,37 @@ function feeds_ui_mapping_form($form, &$form_state, $importer) {
);
$form['legendset']['legend'] = $legend;
- // Add unique and remove forms to mappings.
- $form['unique_flags'] = $form['remove_flags'] = array(
+ // Add config forms and remove flags to mappings.
+ $form['config'] = $form['remove_flags'] = $form['mapping_weight'] = array(
'#tree' => TRUE,
);
if (is_array($mappings)) {
+
+ $delta = count($mappings) + 2;
+
foreach ($mappings as $i => $mapping) {
- $param = array(
- 'processor' => $importer->processor,
- 'mapping' => $mapping,
- );
- if (isset($targets[$mapping['target']]['optional_unique']) && $targets[$mapping['target']]['optional_unique'] === TRUE) {
- $form['unique_flags'][$i] = array(
- '#type' => 'checkbox',
- '#default_value' => !empty($mapping['unique']),
- '#attributes' => array('class' => array('feeds-ui-trigger-submit')),
- );
+ if (isset($targets[$mapping['target']])) {
+ $form['config'][$i] = feeds_ui_mapping_settings_form($form, $form_state, $i, $mapping, $targets[$mapping['target']]);
}
+
$form['remove_flags'][$i] = array(
'#type' => 'checkbox',
'#title' => t('Remove'),
'#prefix' => '<div class="feeds-ui-checkbox-link">',
'#suffix' => '</div>',
);
+
+ $form['mapping_weight'][$i] = array(
+ '#type' => 'weight',
+ '#title' => '',
+ '#default_value' => $i,
+ '#delta' => $delta,
+ '#attributes' => array(
+ 'class' => array(
+ 'feeds-ui-mapping-weight'
+ ),
+ ),
+ );
}
}
@@ -579,6 +590,7 @@ function feeds_ui_mapping_form($form, &$form_state, $importer) {
'#type' => 'submit',
'#value' => t('Add'),
'#submit' => array('feeds_ui_mapping_form_add_submit'),
+ '#validate' => array('feeds_ui_mapping_form_add_validate'),
);
$form['save'] = array(
'#type' => 'submit',
@@ -589,10 +601,141 @@ function feeds_ui_mapping_form($form, &$form_state, $importer) {
}
/**
+ * Per mapper configuration form that is a part of feeds_ui_mapping_form().
+ */
+function feeds_ui_mapping_settings_form($form, $form_state, $i, $mapping, $target) {
+ $form_state += array(
+ 'mapping_settings_edit' => NULL,
+ 'mapping_settings' => array(),
+ );
+
+ $base_button = array(
+ '#submit' => array('feeds_ui_mapping_form_multistep_submit'),
+ '#ajax' => array(
+ 'callback' => 'feeds_ui_mapping_settings_form_callback',
+ 'wrapper' => 'feeds-ui-mapping-form-wrapper',
+ 'effect' => 'fade',
+ 'progress' => 'none',
+ ),
+ '#i' => $i,
+ );
+
+ if (isset($form_state['mapping_settings'][$i])) {
+ $mapping = $form_state['mapping_settings'][$i] + $mapping;
+ }
+
+ if ($form_state['mapping_settings_edit'] === $i) {
+ // Build the form.
+ if (isset($target['form_callback'])) {
+ $settings_form = call_user_func($target['form_callback'], $mapping, $target, $form, $form_state);
+ }
+ else {
+ $settings_form = array();
+ }
+
+ // Merge in the optional unique form.
+ $settings_form += feeds_ui_mapping_settings_optional_unique_form($mapping, $target, $form, $form_state);
+
+ return array(
+ '#type' => 'container',
+ 'settings' => $settings_form,
+ 'save_settings' => $base_button + array(
+ '#type' => 'submit',
+ '#name' => 'mapping_settings_update_' . $i,
+ '#value' => t('Update'),
+ '#op' => 'update',
+ ),
+ 'cancel_settings' => $base_button + array(
+ '#type' => 'submit',
+ '#name' => 'mapping_settings_cancel_' . $i,
+ '#value' => t('Cancel'),
+ '#op' => 'cancel',
+ ),
+ );
+ }
+ else {
+ // Build the summary.
+ if (isset($target['summary_callback'])) {
+ $summary = call_user_func($target['summary_callback'], $mapping, $target, $form, $form_state);
+ }
+ else {
+ $summary = '';
+ }
+
+ // Append the optional unique summary.
+ if ($optional_unique_summary = feeds_ui_mapping_settings_optional_unique_summary($mapping, $target, $form, $form_state)) {
+ $summary .= ' ' . $optional_unique_summary;
+ }
+
+ if ($summary) {
+ return array(
+ 'summary' => array(
+ '#prefix' => '<div>',
+ '#markup' => $summary,
+ '#suffix' => '</div>',
+ ),
+ 'edit_settings' => $base_button + array(
+ '#type' => 'image_button',
+ '#name' => 'mapping_settings_edit_' . $i,
+ '#src' => 'misc/configure.png',
+ '#attributes' => array('alt' => t('Edit')),
+ '#op' => 'edit',
+ ),
+ );
+ }
+ }
+}
+
+/**
+ * Submit callback for a per mapper configuration form. Switches between edit
+ * and summary mode.
+ */
+function feeds_ui_mapping_form_multistep_submit($form, &$form_state) {
+ $trigger = $form_state['triggering_element'];
+
+ switch ($trigger['#op']) {
+ case 'edit':
+ $form_state['mapping_settings_edit'] = $trigger['#i'];
+ break;
+
+ case 'update':
+ $values = $form_state['values']['config'][$trigger['#i']]['settings'];
+ $form_state['mapping_settings'][$trigger['#i']] = $values;
+ unset($form_state['mapping_settings_edit']);
+ break;
+
+ case 'cancel':
+ unset($form_state['mapping_settings_edit']);
+ break;
+ }
+
+ $form_state['rebuild'] = TRUE;
+}
+
+/**
+ * AJAX callback that returns the whole feeds_ui_mapping_form().
+ */
+function feeds_ui_mapping_settings_form_callback($form, $form_state) {
+ return $form;
+}
+
+/**
+ * Validation for source and target selection.
+ */
+function feeds_ui_mapping_form_add_validate($form, &$form_state) {
+ if ($form_state['values']['source'] == '') {
+ form_set_error('source', t('You must select a mapping source.'));
+ }
+ if ($form_state['values']['target'] == '') {
+ form_set_error('target', t('You must select a mapping target.'));
+ }
+}
+
+/**
* Submit handler for add button on feeds_ui_mapping_form().
*/
function feeds_ui_mapping_form_add_submit($form, &$form_state) {
- $importer = $form['#importer'];
+ $importer = feeds_importer($form['#importer']);
try {
$mappings = $form['#mappings'];
$mappings[] = array(
@@ -601,7 +744,7 @@ function feeds_ui_mapping_form_add_submit($form, &$form_state) {
'unique' => FALSE,
);
$importer->processor->addConfig(array('mappings' => $mappings));
- $importer->processor->save();
+ $importer->save();
drupal_set_message(t('Mapping has been added.'));
}
catch (Exception $e) {
@@ -613,27 +756,48 @@ function feeds_ui_mapping_form_add_submit($form, &$form_state) {
* Submit handler for save button on feeds_ui_mapping_form().
*/
function feeds_ui_mapping_form_submit($form, &$form_state) {
- $processor = $form['#importer']->processor;
- // We may set some unique flags to mappings that we remove in the subsequent
- // step, that's fine.
+ $importer = feeds_importer($form['#importer']);
+ $processor = $importer->processor;
+
+ $form_state += array(
+ 'mapping_settings' => array(),
+ 'mapping_settings_edit' => NULL,
+ );
+
+ // If an item is in edit mode, prepare it for saving.
+ if ($form_state['mapping_settings_edit'] !== NULL) {
+ $values = $form_state['values']['config'][$form_state['mapping_settings_edit']]['settings'];
+ $form_state['mapping_settings'][$form_state['mapping_settings_edit']] = $values;
+ }
+
+ // We may set some settings to mappings that we remove in the subsequent step,
+ // that's fine.
$mappings = $form['#mappings'];
- if (isset($form_state['values']['unique_flags'])) {
- foreach ($form_state['values']['unique_flags'] as $k => $v) {
- $mappings[$k]['unique'] = $v;
- }
+ foreach ($form_state['mapping_settings'] as $k => $v) {
+ $mappings[$k] = array(
+ 'source' => $mappings[$k]['source'],
+ 'target' => $mappings[$k]['target'],
+ ) + $v;
}
if (!empty($form_state['values']['remove_flags'])) {
- foreach ($form_state['values']['remove_flags'] as $k => $v) {
- if ($v) {
- unset($mappings[$k]);
- }
+ $remove_flags = array_keys(array_filter($form_state['values']['remove_flags']));
+
+ foreach ($remove_flags as $k) {
+ unset($mappings[$k]);
+ unset($form_state['values']['mapping_weight'][$k]);
}
- // Keep our keys clean.
- $mappings = array_values($mappings);
}
+
+ // Keep our keys clean.
+ $mappings = array_values($mappings);
+
+ if (!empty($mappings)) {
+ array_multisort($form_state['values']['mapping_weight'], $mappings);
+ }
+
$processor->addConfig(array('mappings' => $mappings));
- $processor->save();
+ $importer->save();
drupal_set_message(t('Your changes have been saved.'));
}
@@ -660,6 +824,39 @@ function _feeds_ui_format_options($options) {
}
/**
+ * Per mapping settings summary callback. Shows whether a mapping is used as
+ * unique or not.
+ */
+function feeds_ui_mapping_settings_optional_unique_summary($mapping, $target, $form, $form_state) {
+ if (!empty($target['optional_unique'])) {
+ if ($mapping['unique']) {
+ return t('Used as <strong>unique</strong>.');
+ }
+ else {
+ return t('Not used as unique.');
+ }
+ }
+}
+
+/**
+ * Per mapping settings form callback. Lets the user choose if a target is as
+ * unique or not.
+ */
+function feeds_ui_mapping_settings_optional_unique_form($mapping, $target, $form, $form_state) {
+ $settings_form = array();
+
+ if (!empty($target['optional_unique'])) {
+ $settings_form['unique'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Unique'),
+ '#default_value' => !empty($mapping['unique']),
+ );
+ }
+
+ return $settings_form;
+}
+
+/**
* Theme feeds_ui_overview_form().
*/
function theme_feeds_ui_overview_form($variables) {
@@ -801,8 +998,9 @@ function theme_feeds_ui_mapping_form($variables) {
$header = array(
t('Source'),
t('Target'),
- t('Unique target'),
+ t('Target configuration'),
' ',
+ t('Weight'),
);
$rows = array();
if (is_array($form['#mappings'])) {
@@ -811,17 +1009,21 @@ function theme_feeds_ui_mapping_form($variables) {
$source = isset($form['source']['#options'][$mapping['source']]) ? $form['source']['#options'][$mapping['source']] : $mapping['source'];
$target = isset($form['target']['#options'][$mapping['target']]) ? check_plain($form['target']['#options'][$mapping['target']]) : '<em>' . t('Missing') . '</em>';
$rows[] = array(
- check_plain($source),
- $target,
- drupal_render($form['unique_flags'][$i]),
- drupal_render($form['remove_flags'][$i]),
+ 'data' => array(
+ check_plain($source),
+ $target,
+ drupal_render($form['config'][$i]),
+ drupal_render($form['remove_flags'][$i]),
+ drupal_render($form['mapping_weight'][$i]),
+ ),
+ 'class' => array('draggable', 'tabledrag-leaf'),
);
}
}
if (!count($rows)) {
$rows[] = array(
array(
- 'colspan' => 4,
+ 'colspan' => 5,
'data' => t('No mappings defined.'),
),
);
@@ -831,9 +1033,10 @@ function theme_feeds_ui_mapping_form($variables) {
drupal_render($form['target']),
'',
drupal_render($form['add']),
+ '',
);
- $output = '<div class="help feeds-admin-ui""' . drupal_render($form['help']) . '</div>';
- $output .= theme('table', array('header' => $header, 'rows' => $rows));
+ $output = '<div class="help feeds-admin-ui">' . drupal_render($form['help']) . '</div>';
+ $output .= theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('id' => 'feeds-ui-mapping-overview')));
// Build the help table that explains available sources.
$legend = '';
@@ -866,7 +1069,8 @@ function theme_feeds_ui_mapping_form($variables) {
);
$output .= drupal_render($form['legendset']);
-
$output .= drupal_render_children($form);
+
+ drupal_add_tabledrag('feeds-ui-mapping-overview', 'order', 'sibling', 'feeds-ui-mapping-weight');
return $output;
}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds_ui/feeds_ui.info b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds_ui/feeds_ui.info
index 2d282af..c75c154 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds_ui/feeds_ui.info
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/feeds_ui/feeds_ui.info
@@ -7,9 +7,9 @@ configure = admin/structure/feeds
files[] = feeds_ui.test
-; Information added by drupal.org packaging script on 2012-05-28
-version = "7.x-2.0-alpha5"
+; Information added by drupal.org packaging script on 2012-10-10
+version = "7.x-2.0-alpha6"
core = "7.x"
project = "feeds"
-datestamp = "1338228956"
+datestamp = "1349851321"
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/includes/FeedsConfigurable.inc b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/includes/FeedsConfigurable.inc
index 0b9b620..0f3b013 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/includes/FeedsConfigurable.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/includes/FeedsConfigurable.inc
@@ -76,6 +76,13 @@ abstract class FeedsConfigurable {
}
/**
+ * Override magic method __isset(). This is needed due to overriding __get().
+ */
+ public function __isset($name) {
+ return isset($this->$name) ? TRUE : FALSE;
+ }
+
+ /**
* Determine whether this object is persistent and enabled. I. e. it is
* defined either in code or in the database and it is enabled.
*/
@@ -129,8 +136,8 @@ abstract class FeedsConfigurable {
}
/**
- * Override magic method __get(). Make sure that $this->config goes
- * through getConfig()
+ * Override magic method __get(). Make sure that $this->config goes through
+ * getConfig().
*/
public function __get($name) {
if ($name == 'config') {
@@ -246,18 +253,39 @@ function feeds_form($form, &$form_state, $configurable, $form_method) {
* Validation handler for feeds_form().
*/
function feeds_form_validate($form, &$form_state) {
- $validate_method = $form['#feeds_form_method'] . 'Validate';
- if (method_exists($form['#configurable'], $validate_method)) {
- $form['#configurable']->$validate_method($form_state['values']);
- }
+ _feeds_form_helper($form, $form_state, 'Validate');
}
/**
- * Submit handler for feeds_config_form().
+ * Submit handler for feeds_form().
*/
function feeds_form_submit($form, &$form_state) {
- $submit_method = $form['#feeds_form_method'] . 'Submit';
- if (method_exists($form['#configurable'], $submit_method)) {
- $form['#configurable']->$submit_method($form_state['values']);
+ _feeds_form_helper($form, $form_state, 'Submit');
+}
+
+/**
+ * Helper for Feeds validate and submit callbacks.
+ */
+function _feeds_form_helper($form, &$form_state, $action) {
+ $method = $form['#feeds_form_method'] . $action;
+ $class = get_class($form['#configurable']);
+ $id = $form['#configurable']->id;
+
+ // Re-initialize the configurable object. Using feeds_importer() and
+ // feeds_plugin() will ensure that we're using the same instance. We can't
+ // reuse the previous form instance because feeds_importer() is used to save.
+ // This will re-initialize all of the plugins anyway, causing some tricky
+ // saving issues in certain cases.
+ // See http://drupal.org/node/1672880.
+
+ if ($class == variable_get('feeds_importer_class', 'FeedsImporter')) {
+ $form['#configurable'] = feeds_importer($id);
+ }
+ else {
+ $form['#configurable'] = feeds_plugin($class, $id);
+ }
+
+ if (method_exists($form['#configurable'], $method)) {
+ $form['#configurable']->$method($form_state['values']);
}
}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/includes/FeedsSource.inc b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/includes/FeedsSource.inc
index b272b7f..7133842 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/includes/FeedsSource.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/includes/FeedsSource.inc
@@ -305,18 +305,19 @@ class FeedsSource extends FeedsConfigurable {
* Schedule background clearing tasks.
*/
public function scheduleClear() {
- // Schedule as soon as possible if batch is not complete.
- if ($this->progressClearing() !== FEEDS_BATCH_COMPLETE) {
- $job = array(
- 'type' => $this->id,
- 'id' => $this->feed_nid,
- 'period' => 0,
- 'periodic' => TRUE,
- );
- JobScheduler::get('feeds_source_clear')->set($job);
+ $job = array(
+ 'type' => $this->id,
+ 'id' => $this->feed_nid,
+ 'period' => 0,
+ 'periodic' => TRUE,
+ );
+ // Remove job if batch is complete.
+ if ($this->progressClearing() === FEEDS_BATCH_COMPLETE) {
+ JobScheduler::get('feeds_source_clear')->remove($job);
}
+ // Schedule as soon as possible if batch is not complete.
else {
- JobScheduler::get('feeds_source_clear')->remove($job);
+ JobScheduler::get('feeds_source_clear')->set($job);
}
}
@@ -363,9 +364,9 @@ class FeedsSource extends FeedsConfigurable {
// Clean up.
$result = $this->progressImporting();
if ($result == FEEDS_BATCH_COMPLETE || isset($e)) {
- module_invoke_all('feeds_after_import', $this);
$this->imported = time();
$this->log('import', 'Imported in !s s', array('!s' => $this->imported - $this->state[FEEDS_START]), WATCHDOG_INFO);
+ module_invoke_all('feeds_after_import', $this);
unset($this->fetcher_result, $this->state);
}
$this->save();
@@ -581,7 +582,8 @@ class FeedsSource extends FeedsConfigurable {
* An array stored for $client.
*/
public function getConfigFor(FeedsSourceInterface $client) {
- return $this->config[get_class($client)];
+ $class = get_class($client);
+ return isset($this->config[$class]) ? $this->config[$class] : $client->sourceDefaults();
}
/**
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/libraries/ParserCSV.inc b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/libraries/ParserCSV.inc
index 0850753..6a3ff70 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/libraries/ParserCSV.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/libraries/ParserCSV.inc
@@ -1,7 +1,9 @@
<?php
/**
+ * @file
* Contains CSV Parser.
+ *
* Functions in this file are independent of the Feeds specific implementation.
* Thanks to jpetso http://drupal.org/user/56020 for most of the code in this
* file.
@@ -155,7 +157,7 @@ class ParserCSV {
* reached the timeout set with setTimeout() or the line limit set with
* setLineLimit().
*
- * @see ParserCSV::setStartByte($start);
+ * @see ParserCSV::setStartByte()
*/
public function lastLinePos() {
return $this->lastLinePos;
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/libraries/common_syndication_parser.inc b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/libraries/common_syndication_parser.inc
index a7b55ec..1b7ef61 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/libraries/common_syndication_parser.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/libraries/common_syndication_parser.inc
@@ -583,8 +583,8 @@ function _parser_common_syndication_link($links) {
function _parser_common_syndication_title($title, $body = FALSE) {
if (empty($title) && !empty($body)) {
// Explode to words and use the first 3 words.
- $words = preg_split("/[\s,]+/", strip_tags($body));
- $title = $words[0] . ' ' . $words[1] . ' ' . $words[2];
+ $words = preg_split('/[\s,]+/', strip_tags($body));
+ $title = implode(' ', array_slice($words, 0, 3));
}
return $title;
}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/libraries/http_request.inc b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/libraries/http_request.inc
index e400999..44f4fb5 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/libraries/http_request.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/libraries/http_request.inc
@@ -4,7 +4,8 @@
* @file
* Download via HTTP.
*
- * Support caching, HTTP Basic Authentication, detection of RSS/Atom feeds, redirects.
+ * Support caching, HTTP Basic Authentication, detection of RSS/Atom feeds,
+ * redirects.
*/
/**
@@ -26,23 +27,19 @@ class HRCurlException extends Exception {}
* Discover RSS or atom feeds at the given URL. If document in given URL is an
* HTML document, function attempts to discover RSS or Atom feeds.
*
- * @param $url
- * @param null $settings
- * @return bool|string string - the discovered feed, FALSE - if the URL is not reachable or there
+ * @param string $url
+ * The url of the feed to retrieve.
+ * @param array $settings
+ * An optional array of settings. Valid options are: accept_invalid_cert.
+ *
+ * @return bool|string
+ * The discovered feed, or FALSE if the URL is not reachable or there was an
+ * error.
*/
function http_request_get_common_syndication($url, $settings = NULL) {
- $password = $username = NULL;
- if (feeds_valid_url($url, TRUE)) {
- // Handle password protected feeds.
- $url_parts = parse_url($url);
- if (!empty($url_parts['user'])) {
- $password = $url_parts['pass'];
- $username = $url_parts['user'];
- }
- }
$accept_invalid_cert = isset($settings['accept_invalid_cert']) ? $settings['accept_invalid_cert'] : FALSE;
- $download = http_request_get($url, $username, $password, $accept_invalid_cert);
+ $download = http_request_get($url, NULL, NULL, $accept_invalid_cert);
// Cannot get the feed, return.
// http_request_get() always returns 200 even if its 304.
@@ -72,22 +69,35 @@ function http_request_get_common_syndication($url, $settings = NULL) {
/**
* Get the content from the given URL.
*
- * @param $url
- * A valid URL (not only web URLs).
- * @param $username
- * If the URL use authentication, here you can supply the username for this.
- * @param $password
- * If the URL use authentication, here you can supply the password for this.
+ * @param string $url
+ * A valid URL (not only web URLs).
+ * @param string $username
+ * If the URL uses authentication, supply the username.
+ * @param string $password
+ * If the URL uses authentication, supply the password.
* @param bool $accept_invalid_cert
- * @return object A stdClass object that describes the data downloaded from $url. The object's
+ * Whether to accept invalid certificates.
+
+ * @return stdClass
+ * An object that describes the data downloaded from $url.
*/
function http_request_get($url, $username = NULL, $password = NULL, $accept_invalid_cert = FALSE) {
- // Intra-pagedownload cache, avoid to download the same content twice within one page download
- // (it's possible, compatible and parse calls).
+ // Intra-pagedownload cache, avoid to download the same content twice within
+ // one page download (it's possible, compatible and parse calls).
static $download_cache = array();
if (isset($download_cache[$url])) {
return $download_cache[$url];
}
+
+ if (!$username && valid_url($url, TRUE)) {
+ // Handle password protected feeds.
+ $url_parts = parse_url($url);
+ if (!empty($url_parts['user'])) {
+ $password = $url_parts['pass'];
+ $username = $url_parts['user'];
+ }
+ }
+
$curl = http_request_use_curl();
// Only download and parse data if really needs refresh.
@@ -152,12 +162,13 @@ function http_request_get($url, $username = NULL, $password = NULL, $accept_inva
curl_setopt($download, CURLOPT_FOLLOWLOCATION, TRUE);
if (!empty($username)) {
curl_setopt($download, CURLOPT_USERPWD, "{$username}:{$password}");
+ curl_setopt($download, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
}
curl_setopt($download, CURLOPT_HTTPHEADER, $headers);
curl_setopt($download, CURLOPT_HEADER, TRUE);
curl_setopt($download, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($download, CURLOPT_ENCODING, '');
- curl_setopt($download, CURLOPT_TIMEOUT, variable_get('http_request_timeout', 15));
+ curl_setopt($download, CURLOPT_TIMEOUT, variable_get('http_request_timeout', 30));
if ($accept_invalid_cert) {
curl_setopt($download, CURLOPT_SSL_VERIFYPEER, 0);
}
@@ -201,7 +212,7 @@ function http_request_get($url, $username = NULL, $password = NULL, $accept_inva
}
}
else {
- $result = drupal_http_request($url, array('headers' => $headers));
+ $result = drupal_http_request($url, array('headers' => $headers, 'timeout' => variable_get('http_request_timeout', 30)));
}
$result->code = isset($result->code) ? $result->code : 200;
@@ -231,7 +242,7 @@ function http_request_get($url, $username = NULL, $password = NULL, $accept_inva
/**
* Decides if it's possible to use cURL or not.
*
- * @return
+ * @return bool
* TRUE if curl is available, FALSE otherwise.
*/
function http_request_use_curl() {
@@ -261,7 +272,7 @@ function http_request_clear_cache($url) {
* @param string $data
* The actual data from the http request.
*
- * @return boolean
+ * @return bool
* Returns TRUE if this is a parsable feed.
*/
function http_request_is_feed($content_type, $data) {
@@ -274,7 +285,8 @@ function http_request_is_feed($content_type, $data) {
return TRUE;
}
- // @TODO: Sometimes the content-type can be text/html but still be a valid feed.
+ // @TODO: Sometimes the content-type can be text/html but still be a valid
+ // feed.
return FALSE;
}
@@ -284,7 +296,7 @@ function http_request_is_feed($content_type, $data) {
* @param string $html
* The html string to search.
*
- * @return array()
+ * @return array
* An array of href to feeds.
*/
function http_request_find_feeds($html) {
@@ -300,7 +312,8 @@ function http_request_find_feeds($html) {
preg_match_all(HTTP_REQUEST_PCRE_TAG_ATTRIBUTES, $link_tag, $attributes, PREG_SET_ORDER);
foreach ($attributes as $attribute) {
- // Find the key value pairs, attribute[1] is key and attribute[2] is the value.
+ // Find the key value pairs, attribute[1] is key and attribute[2] is the
+ // value.
if (!empty($attribute[1]) && !empty($attribute[2])) {
$candidate[drupal_strtolower($attribute[1])] = drupal_strtolower(decode_entities($attribute[2]));
}
@@ -323,13 +336,12 @@ function http_request_find_feeds($html) {
* Create an absolute url.
*
* @param string $url
- * The href to transform.
- *
- * @param $base_url
- * The url to be used as the base for a relative $url.
+ * The href to transform.
+ * @param string $base_url
+ * The url to be used as the base for a relative $url.
*
* @return string
- * an absolute url
+ * An absolute url
*/
function http_request_create_absolute_url($url, $base_url) {
$url = trim($url);
@@ -340,7 +352,8 @@ function http_request_create_absolute_url($url, $base_url) {
// Turn relative url into absolute.
if (valid_url($url, FALSE)) {
- // Produces variables $scheme, $host, $user, $pass, $path, $query and $fragment.
+ // Produces variables $scheme, $host, $user, $pass, $path, $query and
+ // $fragment.
$parsed_url = parse_url($base_url);
$path = dirname($parsed_url['path']);
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/mappers/date.inc b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/mappers/date.inc
index 6cc5bca..3de6a69 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/mappers/date.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/mappers/date.inc
@@ -59,5 +59,4 @@ function date_feeds_set_target($source, $entity, $target, $feed_element) {
}
}
$feed_element->buildDateField($entity, $field_name);
-
}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/mappers/field.inc b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/mappers/field.inc
deleted file mode 100644
index 43d62c4..0000000
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/mappers/field.inc
+++ /dev/null
@@ -1,127 +0,0 @@
-<?php
-
-/**
- * @file
- * On behalf implementation of Feeds mapping API for field.module.
- *
- * Does actually not include mappers for field types defined in fields module
- * (because there aren't any) but mappers for all fields that contain their
- * value simply in $entity->fieldname['und'][$i]['value'].
- */
-
-/**
- * Implements hook_feeds_processor_targets_alter().
- *
- * @see FeedsNodeProcessor::getMappingTargets().
- */
-function field_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_name) {
- $numeric_types = array(
- 'list_integer',
- 'list_float',
- 'list_boolean',
- 'number_integer',
- 'number_decimal',
- 'number_float',
- );
- $string_types = array(
- 'list_text',
- 'text',
- 'text_long',
- 'text_with_summary',
- );
- foreach (field_info_instances($entity_type, $bundle_name) as $name => $instance) {
- $info = field_info_field($name);
- unset($callback);
- if (in_array($info['type'], $numeric_types)) {
- $callback = 'field_feeds_set_target_numeric';
- }
- if (in_array($info['type'], $string_types)) {
- $callback = 'field_feeds_set_target_text';
- }
- if (isset($callback)) {
- $targets[$name] = array(
- 'name' => check_plain($instance['label']),
- 'callback' => $callback,
- 'description' => t('The @label field of the node.', array('@label' => $instance['label'])),
- );
- }
- }
-}
-
-/**
- * Callback for mapping numerics.
- *
- * Ensure that $value is a numeric to avoid database errors.
- */
-function field_feeds_set_target_numeric($source, $entity, $target, $value) {
- if (!is_array($value)) {
- $value = array($value);
- }
- foreach ($value as $k => $v) {
- if (!is_numeric($v)) {
- unset($value[$k]);
- }
- }
- _field_feeds_set_target($source, $entity, $target, $value, FALSE);
-}
-
-/**
- * Callback for mapping text fields.
- */
-function field_feeds_set_target_text($source, $entity, $target, $value) {
- if (!is_array($value)) {
- $value = array($value);
- }
- _field_feeds_set_target($source, $entity, $target, $value, TRUE);
-}
-
-/**
- * Helper for mapping.
- *
- * When the callback is invoked, $target contains the name of the field the
- * user has decided to map to and $value contains the value of the feed item
- * element the user has picked as a source.
- *
- * @param $source
- * A FeedsSource object.
- * @param $entity
- * The entity to map to.
- * @param $target
- * The target key on $entity to map to.
- * @param $value
- * The value to map. MUST be an array.
- * @param $input_format
- * TRUE if an input format should be applied.
- */
-function _field_feeds_set_target($source, $entity, $target, $value, $input_format = FALSE) {
- if (empty($value)) {
- return;
- }
-
- if ($input_format) {
- if (isset($source->importer->processor->config['input_format'])) {
- $format = $source->importer->processor->config['input_format'];
- }
- }
-
- $info = field_info_field($target);
-
- // Iterate over all values.
- $i = 0;
- $field = isset($entity->$target) ? $entity->$target : array();
- foreach ($value as $v) {
- if (!is_array($v) && !is_object($v)) {
- $field['und'][$i]['value'] = $v;
- }
- if ($input_format) {
- if (isset($format)) {
- $field['und'][$i]['format'] = $format;
- }
- }
- if ($info['cardinality'] == 1) {
- break;
- }
- $i++;
- }
- $entity->{$target} = $field;
-}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/mappers/file.inc b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/mappers/file.inc
index 63c1e2d..2cc5dc3 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/mappers/file.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/mappers/file.inc
@@ -49,7 +49,7 @@ function file_feeds_set_target($source, $entity, $target, $value) {
foreach ($value as $k => $v) {
if (!($v instanceof FeedsEnclosure)) {
if (is_string($v)) {
- $value[$k] = new FeedsEnclosure($v, 'application/octet-stream');
+ $value[$k] = new FeedsEnclosure($v, file_get_mimetype($v));
}
else {
unset($value[$k]);
@@ -75,7 +75,13 @@ function file_feeds_set_target($source, $entity, $target, $value) {
$i = 0;
$field = isset($entity->$target) ? $entity->$target : array();
foreach ($value as $v) {
- if ($file = $v->getFile($destination)) {
+ try {
+ $file = $v->getFile($destination);
+ }
+ catch (Exception $e) {
+ watchdog_exception('Feeds', $e, nl2br(check_plain($e)));
+ }
+ if ($file) {
$field['und'][$i] = (array)$file;
$field['und'][$i]['display'] = 1; // @todo: Figure out how to properly populate this field.
if ($info['cardinality'] == 1) {
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/mappers/link.inc b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/mappers/link.inc
index 029b795..45a86f7 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/mappers/link.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/mappers/link.inc
@@ -8,7 +8,7 @@
/**
* Implements hook_feeds_processor_targets_alter().
*
- * @see FeedsNodeProcessor::getMappingTargets().
+ * @see FeedsProcessor::getMappingTargets()
*/
function link_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_name) {
foreach (field_info_instances($entity_type, $bundle_name) as $name => $instance) {
@@ -16,16 +16,18 @@ function link_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_nam
if ($info['type'] == 'link_field') {
if (array_key_exists('url', $info['columns'])) {
$targets[$name . ':url'] = array(
- 'name' => t('@name URL', array('@name' => $instance['label'])),
+ 'name' => t('@name: URL', array('@name' => $instance['label'])),
'callback' => 'link_feeds_set_target',
- 'description' => t('The @label field of the node.', array('@label' => $instance['label'])),
+ 'description' => t('The @label field of the entity.', array('@label' => $instance['label'])),
+ 'real_target' => $name,
);
}
if (array_key_exists('title', $info['columns'])) {
$targets[$name . ':title'] = array(
- 'name' => t('@name Title', array('@name' => $instance['label'])),
+ 'name' => t('@name: Title', array('@name' => $instance['label'])),
'callback' => 'link_feeds_set_target',
- 'description' => t('The @label field of the node.', array('@label' => $instance['label'])),
+ 'description' => t('The @label field of the entity.', array('@label' => $instance['label'])),
+ 'real_target' => $name,
);
}
}
@@ -50,28 +52,25 @@ function link_feeds_set_target($source, $entity, $target, $value) {
}
// Iterate over all values.
- $i = 0;
- $info = field_info_field($target);
- list($field_name, $sub_field) = explode(':', $target);
+ list($field_name, $column) = explode(':', $target);
+ $info = field_info_field($field_name);
+
+ $field = isset($entity->$field_name) ? $entity->$field_name : array();
+ $delta = 0;
+
foreach ($value as $v) {
- if (!is_array($v) && !is_object($v)) {
- if (strstr($target, 'url')) {
- if (isset($entity->{$field_name}['und'][$i]['title'])) {
- $field['und'][$i]['title'] = $entity->{$field_name}['und'][$i]['title'];
- }
- $field['und'][$i]['url'] = $v;
- }
- elseif (strstr($target, 'title')) {
- if (isset($entity->{$field_name}['und'][$i]['url'])) {
- $field['und'][$i]['url'] = $entity->{$field_name}['und'][$i]['url'];
- }
- $field['und'][$i]['title'] = $v;
- }
- }
- if ($info['cardinality'] == 1) {
+ if ($info['cardinality'] == $delta) {
break;
}
- $i++;
+
+ if (is_object($v) && ($v instanceof FeedsElement)) {
+ $v = $v->getValue();
+ }
+
+ if (is_scalar($v)) {
+ $field['und'][$delta][$column] = $v;
+ $delta++;
+ }
}
- $entity->{$field_name} = $field;
+ $entity->$field_name = $field;
}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/mappers/number.inc b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/mappers/number.inc
new file mode 100644
index 0000000..b64c4ee
--- /dev/null
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/mappers/number.inc
@@ -0,0 +1,74 @@
+<?php
+
+/**
+ * @file
+ * On behalf implementation of Feeds mapping API for number.module.
+ */
+
+/**
+ * Implements hook_feeds_processor_targets_alter().
+ *
+ * @see FeedsProcessor::getMappingTargets()
+ */
+function number_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_name) {
+ $numeric_types = array(
+ 'list_integer',
+ 'list_float',
+ 'list_boolean',
+ 'number_integer',
+ 'number_decimal',
+ 'number_float',
+ );
+ foreach (field_info_instances($entity_type, $bundle_name) as $name => $instance) {
+ $info = field_info_field($name);
+
+ if (in_array($info['type'], $numeric_types)) {
+ $targets[$name] = array(
+ 'name' => check_plain($instance['label']),
+ 'callback' => 'number_feeds_set_target',
+ 'description' => t('The @label field of the entity.', array('@label' => $instance['label'])),
+ );
+ }
+ }
+}
+
+/**
+ * Callback for mapping numerics.
+ *
+ * Ensure that $value is a numeric to avoid database errors.
+ */
+function number_feeds_set_target($source, $entity, $target, $value) {
+
+ // Do not perform the regular empty() check here. 0 is a valid value. That's
+ // really just a performance thing anyway.
+
+ if (!is_array($value)) {
+ $value = array($value);
+ }
+
+ $info = field_info_field($target);
+
+ // Iterate over all values.
+ $field = isset($entity->$target) ? $entity->$target : array('und' => array());
+
+ // Allow for multiple mappings to the same target.
+ $delta = count($field['und']);
+
+ foreach ($value as $v) {
+
+ if ($info['cardinality'] == $delta) {
+ break;
+ }
+
+ if (is_object($v) && ($v instanceof FeedsElement)) {
+ $v = $v->getValue();
+ }
+
+ if (is_numeric($v)) {
+ $field['und'][$delta]['value'] = $v;
+ $delta++;
+ }
+ }
+
+ $entity->$target = $field;
+}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/mappers/path.inc b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/mappers/path.inc
new file mode 100644
index 0000000..47ae0fc
--- /dev/null
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/mappers/path.inc
@@ -0,0 +1,120 @@
+<?php
+
+/**
+ * @file
+ * On behalf implementation of Feeds mapping API for path.module.
+ */
+
+/**
+ * Implements hook_feeds_processor_targets_alter().
+ *
+ * @see FeedsNodeProcessor::getMappingTargets().
+ */
+function path_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_name) {
+ switch ($entity_type) {
+ case 'node':
+ case 'taxonomy_term':
+ case 'user':
+ $targets['path_alias'] = array(
+ 'name' => t('Path alias'),
+ 'description' => t('URL path alias of the node.'),
+ 'callback' => 'path_feeds_set_target',
+ 'summary_callback' => 'path_feeds_summary_callback',
+ 'form_callback' => 'path_feeds_form_callback',
+ );
+ break;
+ }
+}
+
+/**
+ * Callback for mapping. Here is where the actual mapping happens.
+ *
+ * When the callback is invoked, $target contains the name of the field the
+ * user has decided to map to and $value contains the value of the feed item
+ * element the user has picked as a source.
+ */
+function path_feeds_set_target($source, $entity, $target, $value, $mapping) {
+ if (empty($value)) {
+ $value = '';
+ }
+
+ // Path alias cannot be multi-valued, so use the first value.
+ if (is_array($value)) {
+ $value = $value[0];
+ }
+
+ $entity->path = array();
+
+ $entity_type = $source->importer->processor->entityType();
+
+ list($id, , ) = entity_extract_ids($entity_type, $entity);
+
+ if ($id) {
+ $uri = entity_uri($entity_type, $entity);
+
+ // Check for existing aliases.
+ if ($path = path_load($uri['path'])) {
+ $entity->path = $path;
+ }
+ }
+
+ $entity->path['pathauto'] = FALSE;
+ // Allow pathauto to set the path alias if the option is set, and this value
+ // is empty.
+ if (!empty($mapping['pathauto_override']) && !$value) {
+ $entity->path['pathauto'] = TRUE;
+ }
+ else {
+ $entity->path['alias'] = ltrim($value, '/');
+ }
+}
+
+/**
+ * Mapping configuration summary for path.module.
+ *
+ * @param $mapping
+ * Associative array of the mapping settings.
+ * @param $target
+ * Array of target settings, as defined by the processor or
+ * hook_feeds_processor_targets_alter().
+ * @param $form
+ * The whole mapping form.
+ * @param $form_state
+ * The form state of the mapping form.
+ *
+ * @return
+ * Returns, as a string that may contain HTML, the summary to display while
+ * the full form isn't visible.
+ * If the return value is empty, no summary and no option to view the form
+ * will be displayed.
+ */
+function path_feeds_summary_callback($mapping, $target, $form, $form_state) {
+ if (!module_exists('pathauto')) {
+ return;
+ }
+
+ if (empty($mapping['pathauto_override'])) {
+ return t('Do not allow Pathauto if empty.');
+ }
+
+ else {
+ return t('Allow Pathauto if empty.');
+ }
+}
+
+/**
+ * Settings form callback.
+ *
+ * @return
+ * The per mapping configuration form. Once the form is saved, $mapping will
+ * be populated with the form values.
+ */
+function path_feeds_form_callback($mapping, $target, $form, $form_state) {
+ return array(
+ 'pathauto_override' => array(
+ '#type' => 'checkbox',
+ '#title' => t('Allow Pathauto to set the alias if the value is empty.'),
+ '#default_value' => !empty($mapping['pathauto_override']),
+ ),
+ );
+}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/mappers/profile.inc b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/mappers/profile.inc
new file mode 100644
index 0000000..0dd62de
--- /dev/null
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/mappers/profile.inc
@@ -0,0 +1,35 @@
+<?php
+
+/**
+ * @file
+ * On behalf implementation of Feeds mapping API for user profiles.
+ */
+
+/**
+ * Implements hook_feeds_processor_target_alter().
+ */
+function profile_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_name) {
+
+ if ($entity_type != 'user') {
+ return;
+ }
+
+ $categories = profile_user_categories();
+
+ foreach ($categories as $category) {
+ foreach (_profile_get_fields($category['name']) as $record) {
+ $targets[$record->name] = array(
+ 'name' => t('Profile: @name', array('@name' => $record->title)),
+ 'description' => t('Profile: @name', array('@name' => $record->title)),
+ 'callback' => 'profile_feeds_set_target',
+ );
+ }
+ }
+}
+
+/**
+ * Set the user profile target after import.
+ */
+function profile_feeds_set_target($source, $entity, $target, $value, $mapping) {
+ $entity->$target = $value;
+}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/mappers/text.inc b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/mappers/text.inc
new file mode 100644
index 0000000..3e51ffc
--- /dev/null
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/mappers/text.inc
@@ -0,0 +1,78 @@
+<?php
+
+/**
+ * @file
+ * On behalf implementation of Feeds mapping API for text.module.
+ */
+
+/**
+ * Implements hook_feeds_processor_targets_alter().
+ *
+ * @see FeedsProcessor::getMappingTargets()
+ */
+function text_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_name) {
+ $text_types = array(
+ 'list_text',
+ 'text',
+ 'text_long',
+ 'text_with_summary',
+ );
+ foreach (field_info_instances($entity_type, $bundle_name) as $name => $instance) {
+ $info = field_info_field($name);
+
+ if (in_array($info['type'], $text_types)) {
+ $targets[$name] = array(
+ 'name' => check_plain($instance['label']),
+ 'callback' => 'text_feeds_set_target',
+ 'description' => t('The @label field of the entity.', array('@label' => $instance['label'])),
+ );
+ }
+ }
+}
+
+/**
+ * Callback for mapping text fields.
+ */
+function text_feeds_set_target($source, $entity, $target, $value) {
+ if (empty($value)) {
+ return;
+ }
+
+ if (!is_array($value)) {
+ $value = array($value);
+ }
+
+ if (isset($source->importer->processor->config['input_format'])) {
+ $format = $source->importer->processor->config['input_format'];
+ }
+
+ $info = field_info_field($target);
+
+ // Iterate over all values.
+ $field = isset($entity->$target) ? $entity->$target : array('und' => array());
+
+ // Allow for multiple mappings to the same target.
+ $delta = count($field['und']);
+
+ foreach ($value as $v) {
+
+ if ($info['cardinality'] == $delta) {
+ break;
+ }
+
+ if (is_object($v) && ($v instanceof FeedsElement)) {
+ $v = $v->getValue();
+ }
+
+ if (is_scalar($v)) {
+ $field['und'][$delta]['value'] = $v;
+ $delta++;
+
+ if (isset($format)) {
+ $field['und'][$delta]['format'] = $format;
+ }
+ }
+ }
+
+ $entity->$target = $field;
+}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsCSVParser.inc b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsCSVParser.inc
index 8f4f67f..337dd68 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsCSVParser.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsCSVParser.inc
@@ -1,6 +1,11 @@
<?php
/**
+ * @file
+ * Contains the FeedsCSVParser class.
+ */
+
+/**
* Parses a given file as a CSV file.
*/
class FeedsCSVParser extends FeedsParser {
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsFetcher.inc b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsFetcher.inc
index 9cafd20..4bba44d 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsFetcher.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsFetcher.inc
@@ -1,6 +1,11 @@
<?php
/**
+ * @file
+ * Contains the FeedsFetcher and related classes.
+ */
+
+/**
* Base class for all fetcher results.
*/
class FeedsFetcherResult extends FeedsResult {
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsFileFetcher.inc b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsFileFetcher.inc
index 5d11129..03ef72a 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsFileFetcher.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsFileFetcher.inc
@@ -129,6 +129,8 @@ class FeedsFileFetcher extends FeedsFetcher {
* Override parent::sourceFormValidate().
*/
public function sourceFormValidate(&$values) {
+ $values['source'] = trim($values['source']);
+
$feed_dir = 'public://feeds';
file_prepare_directory($feed_dir, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsHTTPFetcher.inc b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsHTTPFetcher.inc
index 1b00395..119c0bf 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsHTTPFetcher.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsHTTPFetcher.inc
@@ -147,6 +147,8 @@ class FeedsHTTPFetcher extends FeedsFetcher {
* Override parent::sourceFormValidate().
*/
public function sourceFormValidate(&$values) {
+ $values['source'] = trim($values['source']);
+
if (!feeds_valid_url($values['source'], TRUE)) {
$form_key = 'feeds][' . get_class($this) . '][source';
form_set_error($form_key, t('The URL %source is invalid.', array('%source' => $values['source'])));
@@ -306,7 +308,7 @@ class PuSHEnvironment implements PuSHSubscriberEnvironmentInterface {
* Implements PuSHSubscriberEnvironmentInterface::msg().
*/
public function msg($msg, $level = 'status') {
- drupal_set_message($msg, $level);
+ drupal_set_message(check_plain($msg), $level);
}
/**
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsNodeProcessor.inc b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsNodeProcessor.inc
index 2df4b35..d208047 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsNodeProcessor.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsNodeProcessor.inc
@@ -55,7 +55,7 @@ class FeedsNodeProcessor extends FeedsProcessor {
}
else {
// We're replacing the existing node. Only save the absolutely necessary.
- $node = db_query("SELECT created, nid, vid, type FROM {node} WHERE nid = :nid", array(':nid' => $nid))->fetchObject();
+ $node = db_query("SELECT created, nid, vid, type, status FROM {node} WHERE nid = :nid", array(':nid' => $nid))->fetchObject();
$node->uid = $this->config['author'];
}
node_object_prepare($node);
@@ -78,6 +78,39 @@ class FeedsNodeProcessor extends FeedsProcessor {
}
/**
+ * Check that the user has permission to save a node.
+ */
+ protected function entitySaveAccess($entity) {
+
+ // The check will be skipped for anonymous nodes.
+ if ($this->config['authorize'] && !empty($entity->uid)) {
+
+ $author = user_load($entity->uid);
+
+ // If the uid was mapped directly, rather than by email or username, it
+ // could be invalid.
+ if (!$author) {
+ $message = 'User %uid is not a valid user.';
+ throw new FeedsAccessException(t($message, array('%uid' => $entity->uid)));
+ }
+
+ if (empty($entity->nid) || !empty($entity->is_new)) {
+ $op = 'create';
+ $access = node_access($op, $entity->type, $author);
+ }
+ else {
+ $op = 'update';
+ $access = node_access($op, $entity, $author);
+ }
+
+ if (!$access) {
+ $message = 'User %name is not authorized to %op content type %content_type.';
+ throw new FeedsAccessException(t($message, array('%name' => $author->name, '%op' => $op, '%content_type' => $entity->type)));
+ }
+ }
+ }
+
+ /**
* Save a node.
*/
public function entitySave($entity) {
@@ -137,6 +170,7 @@ class FeedsNodeProcessor extends FeedsProcessor {
'content_type' => $type,
'expire' => FEEDS_EXPIRE_NEVER,
'author' => 0,
+ 'authorize' => TRUE,
) + parent::configDefaults();
}
@@ -162,6 +196,12 @@ class FeedsNodeProcessor extends FeedsProcessor {
'#autocomplete_path' => 'user/autocomplete',
'#default_value' => empty($author->name) ? 'anonymous' : check_plain($author->name),
);
+ $form['authorize'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Authorize'),
+ '#description' => t('Check that the author has permission to create the node.'),
+ '#default_value' => $this->config['authorize'],
+ );
$period = drupal_map_assoc(array(FEEDS_EXPIRE_NEVER, 3600, 10800, 21600, 43200, 86400, 259200, 604800, 2592000, 2592000 * 3, 2592000 * 6, 31536000), 'feeds_format_expire');
$form['expire'] = array(
'#type' => 'select',
@@ -219,6 +259,16 @@ class FeedsNodeProcessor extends FeedsProcessor {
$target_node->feeds['suppress_import'] = TRUE;
}
break;
+ case 'user_name':
+ if ($user = user_load_by_name($value)) {
+ $target_node->uid = $user->uid;
+ }
+ break;
+ case 'user_mail':
+ if ($user = user_load_by_mail($value)) {
+ $target_node->uid = $user->uid;
+ }
+ break;
default:
parent::setTargetElement($source, $target_node, $target_element, $value);
break;
@@ -247,6 +297,14 @@ class FeedsNodeProcessor extends FeedsProcessor {
'name' => t('User ID'),
'description' => t('The Drupal user ID of the node author.'),
);
+ $targets['user_name'] = array(
+ 'name' => t('Username'),
+ 'description' => t('The Drupal username of the node author.'),
+ );
+ $targets['user_mail'] = array(
+ 'name' => t('User email'),
+ 'description' => t('The email address of the node author.'),
+ );
$targets['status'] = array(
'name' => t('Published status'),
'description' => t('Whether a node is published or not. 1 stands for published, 0 for not published.'),
@@ -280,7 +338,6 @@ class FeedsNodeProcessor extends FeedsProcessor {
);
}
-
// If the target content type is a Feed node, expose its source field.
if ($id = feeds_get_importer_id($this->config['content_type'])) {
$name = feeds_importer($id)->config['name'];
@@ -293,7 +350,9 @@ class FeedsNodeProcessor extends FeedsProcessor {
// Let other modules expose mapping targets.
self::loadMappers();
- feeds_alter('feeds_processor_targets', $targets, 'node', $this->config['content_type']);
+ $entity_type = $this->entityType();
+ $bundle = $this->config['content_type'];
+ drupal_alter('feeds_processor_targets', $targets, $entity_type, $bundle);
return $targets;
}
@@ -314,7 +373,7 @@ class FeedsNodeProcessor extends FeedsProcessor {
$nid = db_query("SELECT nid FROM {node} WHERE nid = :nid", array(':nid' => $value))->fetchField();
break;
case 'title':
- $nid = db_query("SELECT nid FROM {node} WHERE title = :title", array(':title' => $value))->fetchField();
+ $nid = db_query("SELECT nid FROM {node} WHERE title = :title AND type = :type", array(':title' => $value, ':type' => $this->config['content_type']))->fetchField();
break;
case 'feeds_source':
if ($id = feeds_get_importer_id($this->config['content_type'])) {
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsParser.inc b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsParser.inc
index 23bc591..c492317 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsParser.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsParser.inc
@@ -1,6 +1,11 @@
<?php
/**
+ * @file
+ * Contains FeedsParser and related classes.
+ */
+
+/**
* A result of a parsing stage.
*/
class FeedsParserResult extends FeedsResult {
@@ -91,7 +96,8 @@ abstract class FeedsParser extends FeedsPlugin {
public function getMappingSources() {
self::loadMappers();
$sources = array();
- feeds_alter('feeds_parser_sources', $sources, feeds_importer($this->id)->config['content_type']);
+ $content_type = feeds_importer($this->id)->config['content_type'];
+ drupal_alter('feeds_parser_sources', $sources, $content_type);
if (!feeds_importer($this->id)->config['content_type']) {
return $sources;
}
@@ -99,6 +105,10 @@ abstract class FeedsParser extends FeedsPlugin {
'name' => t('Feed node: User ID'),
'description' => t('The feed node author uid.'),
);
+ $sources['parent:nid'] = array(
+ 'name' => t('Feed node: Node ID'),
+ 'description' => t('The feed node nid.'),
+ );
return $sources;
}
@@ -121,14 +131,21 @@ abstract class FeedsParser extends FeedsPlugin {
* The source element from $item identified by $element_key.
*
* @see FeedsProcessor::map()
- * @see FeedsCSVParser::getSourceElement().
+ * @see FeedsCSVParser::getSourceElement()
*/
public function getSourceElement(FeedsSource $source, FeedsParserResult $result, $element_key) {
- if ($element_key == 'parent:uid' &&
- $source->feed_nid &&
- ($node = node_load($source->feed_nid))) {
- return $node->uid;
+
+ switch ($element_key) {
+
+ case 'parent:uid':
+ if ($source->feed_nid && $node = node_load($source->feed_nid)) {
+ return $node->uid;
+ }
+ break;
+ case 'parent:nid':
+ return $source->feed_nid;
}
+
$item = $result->currentItem();
return isset($item[$element_key]) ? $item[$element_key] : '';
}
@@ -349,10 +366,15 @@ class FeedsEnclosure extends FeedsElement {
require_once drupal_get_path('module', 'transliteration') . '/transliteration.inc';
$filename = transliteration_clean_filename($filename);
}
- if(file_uri_target($destination)) {
- $destination .= trim($destination, '/') . '/';
+ if (file_uri_target($destination)) {
+ $destination = trim($destination, '/') . '/';
+ }
+ try {
+ $file = file_save_data($this->getContent(), $destination . $filename);
+ }
+ catch (Exception $e) {
+ watchdog_exception('Feeds', $e, nl2br(check_plain($e)));
}
- $file = file_save_data($this->getContent(), $destination . $filename);
}
// We couldn't make sense of this enclosure, throw an exception.
@@ -523,7 +545,7 @@ class FeedsDateTimeElement extends FeedsElement {
* This class is a Drupal independent extension of the >= PHP 5.2 DateTime
* class.
*
- * @see FeedsDateTimeElement class
+ * @see FeedsDateTimeElement
*/
class FeedsDateTime extends DateTime {
public $granularity = array();
@@ -724,7 +746,7 @@ function feeds_to_unixtime($date, $default_value) {
if (is_numeric($date)) {
return $date;
}
- elseif (is_string($date)) {
+ elseif (is_string($date) && !empty($date)) {
$date = new FeedsDateTimeElement($date);
return $date->getValue();
}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsPlugin.inc b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsPlugin.inc
index fa1746b..be83393 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsPlugin.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsPlugin.inc
@@ -97,7 +97,7 @@ abstract class FeedsPlugin extends FeedsConfigurable implements FeedsSourceInter
$files = drupal_system_listing('/.*\.inc$/', $path, 'name', 0);
foreach ($files as $file) {
if (strstr($file->uri, '/mappers/')) {
- require_once("./$file->uri");
+ require_once(DRUPAL_ROOT . '/' . $file->uri);
}
}
}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsProcessor.inc b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsProcessor.inc
old mode 100644
new mode 100755
index 029f9f4..80e54d5
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsProcessor.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsProcessor.inc
@@ -1,5 +1,9 @@
<?php
+/**
+ * @file
+ * Contains FeedsProcessor and related classes.
+ */
// Update mode for existing items.
define('FEEDS_SKIP_EXISTING', 0);
@@ -16,6 +20,11 @@ define('FEEDS_PROCESS_LIMIT', 50);
class FeedsValidationException extends Exception {}
/**
+ * Thrown if a an access check fails.
+ */
+class FeedsAccessException extends Exception {}
+
+/**
* Abstract class, defines interface for processors.
*/
abstract class FeedsProcessor extends FeedsPlugin {
@@ -61,10 +70,21 @@ abstract class FeedsProcessor extends FeedsPlugin {
protected function entityValidate($entity) {}
/**
+ * Access check for saving an enity.
+ *
+ * @param $entity
+ * Entity to be saved.
+ *
+ * @throws FeedsAccessException $e
+ * If the access check fails.
+ */
+ protected function entitySaveAccess($entity) {}
+
+ /**
* Save an entity.
*
* @param $entity
- * Entity to b saved.
+ * Entity to be saved.
*/
protected abstract function entitySave($entity);
@@ -102,60 +122,83 @@ abstract class FeedsProcessor extends FeedsPlugin {
$state = $source->state(FEEDS_PROCESS);
while ($item = $parser_result->shiftItem()) {
- if (!($entity_id = $this->existingEntityId($source, $parser_result)) ||
- ($this->config['update_existing'] != FEEDS_SKIP_EXISTING)) {
- // Only proceed if item has actually changed.
- $hash = $this->hash($item);
- if (!empty($entity_id) && $hash == $this->getHash($entity_id)) {
+ // Check if this item already exists.
+ $entity_id = $this->existingEntityId($source, $parser_result);
+ $skip_existing = $this->config['update_existing'] == FEEDS_SKIP_EXISTING;
+
+ // If it exists, and we are not updating, pass onto the next item.
+ if ($entity_id && $skip_existing) {
+ continue;
+ }
+
+ $hash = $this->hash($item);
+ $changed = ($hash !== $this->getHash($entity_id));
+ $force_update = $this->config['skip_hash_check'];
+
+ // Do not proceed if the item exists, has not changed, and we're not
+ // forcing the update.
+ if ($entity_id && !$changed && !$force_update) {
+ continue;
+ }
+
+ try {
+
+ // Build a new entity.
+ if (empty($entity_id)) {
+ $entity = $this->newEntity($source);
+ $this->newItemInfo($entity, $source->feed_nid, $hash);
+ }
+
+ // Load an existing entity.
+ else {
+ $entity = $this->entityLoad($source, $entity_id);
+
+ // The feeds_item table is always updated with the info for the most recently processed entity.
+ // The only carryover is the entity_id.
+ $this->newItemInfo($entity, $source->feed_nid, $hash);
+ $entity->feeds_item->entity_id = $entity_id;
+ }
+
+ // Set property and field values.
+ $this->map($source, $parser_result, $entity);
+ $this->entityValidate($entity);
+
+ // Allow modules to alter the entity before saving.
+ module_invoke_all('feeds_presave', $source, $entity, $item);
+ if (module_exists('rules')) {
+ rules_invoke_event('feeds_import_'. $source->importer()->id, $entity);
+ }
+
+ // Enable modules to skip saving at all.
+ if (!empty($entity->feeds_item->skip)) {
continue;
}
- try {
- // Assemble node, map item to it, save.
- if (empty($entity_id)) {
- $entity = $this->newEntity($source);
- $this->newItemInfo($entity, $source->feed_nid, $hash);
- }
- else {
- $entity = $this->entityLoad($source, $entity_id);
- // The feeds_item table is always updated with the info for the most recently processed entity.
- // The only carryover is the entity_id.
- $this->newItemInfo($entity, $source->feed_nid, $hash);
- $entity->feeds_item->entity_id = $entity_id;
- }
- $this->map($source, $parser_result, $entity);
- $this->entityValidate($entity);
-
- // Allow modules to alter the entity before saving.
- module_invoke_all('feeds_presave', $source, $entity);
- if (module_exists('rules')) {
- rules_invoke_event('feeds_import_'. $source->importer()->id, $entity);
- }
-
- // Enable modules to skip saving at all.
- if (empty($entity->feeds_item->skip)) {
- $this->entitySave($entity);
- // Track progress.
- if (empty($entity_id)) {
- $state->created++;
- }
- else {
- $state->updated++;
- }
- }
+ // This will throw an exception on failure.
+ $this->entitySaveAccess($entity);
+ $this->entitySave($entity);
+
+ // Track progress.
+ if (empty($entity_id)) {
+ $state->created++;
}
- catch (Exception $e) {
- $state->failed++;
- drupal_set_message($e->getMessage(), 'warning');
- $message = $e->getMessage();
- $message .= '<h3>Original item</h3>';
- $message .= '<pre>' . var_export($item, TRUE) . '</pre>';
- $message .= '<h3>Entity</h3>';
- $message .= '<pre>' . var_export($entity, TRUE) . '</pre>';
- $source->log('import', $message, array(), WATCHDOG_ERROR);
+ else {
+ $state->updated++;
}
}
+
+ // Something bad happened, log it.
+ catch (Exception $e) {
+ $state->failed++;
+ drupal_set_message($e->getMessage(), 'warning');
+ $message = $e->getMessage();
+ $message .= '<h3>Original item</h3>';
+ $message .= '<pre>' . var_export($item, TRUE) . '</pre>';
+ $message .= '<h3>Entity</h3>';
+ $message .= '<pre>' . var_export($entity, TRUE) . '</pre>';
+ $source->log('import', $message, array(), WATCHDOG_ERROR);
+ }
}
// Set messages if we're done.
@@ -404,10 +447,10 @@ abstract class FeedsProcessor extends FeedsPlugin {
isset($targets[$this->id][$mapping['target']]['callback']) &&
function_exists($targets[$this->id][$mapping['target']]['callback'])) {
$callback = $targets[$this->id][$mapping['target']]['callback'];
- $callback($source, $target_item, $mapping['target'], $value);
+ $callback($source, $target_item, $mapping['target'], $value, $mapping);
}
else {
- $this->setTargetElement($source, $target_item, $mapping['target'], $value);
+ $this->setTargetElement($source, $target_item, $mapping['target'], $value, $mapping);
}
}
return $target_item;
@@ -428,7 +471,8 @@ abstract class FeedsProcessor extends FeedsPlugin {
return array(
'mappings' => array(),
'update_existing' => FEEDS_SKIP_EXISTING,
- 'input_format' => NULL
+ 'input_format' => NULL,
+ 'skip_hash_check' => FALSE,
);
}
@@ -455,6 +499,12 @@ abstract class FeedsProcessor extends FeedsPlugin {
foreach ($formats as $format) {
$format_options[$format->format] = $format->name;
}
+ $form['skip_hash_check'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Skip hash check'),
+ '#description' => t('Force update of items even if item source data did not change.'),
+ '#default_value' => $this->config['skip_hash_check'],
+ );
$form['input_format'] = array(
'#type' => 'select',
'#title' => t('Text format'),
@@ -639,10 +689,13 @@ abstract class FeedsProcessor extends FeedsPlugin {
}
/**
- * Retrieve MD5 hash of $entity_id from DB.
- * @return Empty string if no item is found, hash otherwise.
+ * Retrieves the MD5 hash of $entity_id from the database.
+ *
+ * @return string
+ * Empty string if no item is found, hash otherwise.
*/
protected function getHash($entity_id) {
+
if ($hash = db_query("SELECT hash FROM {feeds_item} WHERE entity_type = :type AND entity_id = :id", array(':type' => $this->entityType(), ':id' => $entity_id))->fetchField()) {
// Return with the hash.
return $hash;
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsSimplePieParser.inc b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsSimplePieParser.inc
index 6d963a0..cadb6b8 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsSimplePieParser.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsSimplePieParser.inc
@@ -1,6 +1,11 @@
<?php
/**
+ * @file
+ * Contains FeedsSimplePieParser and related classes.
+ */
+
+/**
* Adapter to present SimplePie_Enclosure as FeedsEnclosure object.
*/
class FeedsSimplePieEnclosure extends FeedsEnclosure {
@@ -30,8 +35,8 @@ class FeedsSimplePieEnclosure extends FeedsEnclosure {
* Ensure that the simplepie class definitions are loaded for the enclosure when unserializing.
*/
public function __wakeup() {
- feeds_include_library('simplepie.inc', 'simplepie');
- $this->simplepie_enclosure = unserialize($this->_serialized_simplepie_enclosure);
+ feeds_include_simplepie();
+ $this->simplepie_enclosure = unserialize($this->_serialized_simplepie_enclosure);
}
/**
@@ -60,7 +65,11 @@ class FeedsSimplePieParser extends FeedsParser {
* Implements FeedsParser::parse().
*/
public function parse(FeedsSource $source, FeedsFetcherResult $fetcher_result) {
- feeds_include_library('simplepie.inc', 'simplepie');
+ feeds_include_simplepie();
+
+ // Please be quiet SimplePie.
+ $level = error_reporting();
+ error_reporting($level ^ E_DEPRECATED ^ E_STRICT);
// Initialize SimplePie.
$parser = new SimplePie();
@@ -140,6 +149,8 @@ class FeedsSimplePieParser extends FeedsParser {
}
// Release parser.
unset($parser);
+ // Set error reporting back to its previous value.
+ error_reporting($level);
return $result;
}
@@ -205,7 +216,7 @@ class FeedsSimplePieParser extends FeedsParser {
'name' => t('Enclosures'),
'description' => t('An array of enclosures attached to the feed item.'),
),
- ) + parent::getMappingSources();
+ ) + parent::getMappingSources();
}
/**
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsSitemapParser.inc b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsSitemapParser.inc
index 836bb2d..9288593 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsSitemapParser.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsSitemapParser.inc
@@ -1,6 +1,11 @@
<?php
/**
+ * @file
+ * Contains FeedsSitemapParser and related classes.
+ */
+
+/**
* A parser for the Sitemap specification http://www.sitemaps.org/protocol.php
*/
class FeedsSitemapParser extends FeedsParser {
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsSyndicationParser.inc b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsSyndicationParser.inc
index 64e55a4..09b0cb3 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsSyndicationParser.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsSyndicationParser.inc
@@ -1,6 +1,11 @@
<?php
/**
+ * @file
+ * Contains FeedsSyndicationParser and related classes.
+ */
+
+/**
* Class definition for Common Syndication Parser.
*
* Parses RSS and Atom feeds.
@@ -71,6 +76,6 @@ class FeedsSyndicationParser extends FeedsParser {
'name' => t('Geo Locations'),
'description' => t('An array of geographic locations with a name and a position.'),
),
- ) + parent::getMappingSources();
+ ) + parent::getMappingSources();
}
}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsTermProcessor.inc b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsTermProcessor.inc
index 83183b0..7721ff0 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsTermProcessor.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsTermProcessor.inc
@@ -33,6 +33,7 @@ class FeedsTermProcessor extends FeedsProcessor {
$term = new stdClass();
$term->vid = $vocabulary->vid;
$term->vocabulary_machine_name = $vocabulary->machine_name;
+ $term->format = isset($this->config['input_format']) ? $this->config['input_format'] : filter_fallback_format();
return $term;
}
@@ -85,7 +86,6 @@ class FeedsTermProcessor extends FeedsProcessor {
public function configDefaults() {
return array(
'vocabulary' => 0,
- 'force_update' => TRUE,
) + parent::configDefaults();
}
@@ -105,12 +105,6 @@ class FeedsTermProcessor extends FeedsProcessor {
'#options' => $options,
'#default_value' => $this->config['vocabulary'],
);
- $form['force_update'] = array(
- '#type' => 'checkbox',
- '#title' => t('Force update'),
- '#description' => t('Force update of imported terms even if no data change. For import of <strong>term parents</strong> you need to import twice and set this in the second pass.'),
- '#default_value' => $this->config['force_update'],
- );
return $form;
}
@@ -123,31 +117,29 @@ class FeedsTermProcessor extends FeedsProcessor {
}
}
-
- /**
- * Override setTargetElement to operate on a target item that is a term.
- */
- public function setTargetElement(FeedsSource $source, $target_node, $target_element, $value) {
-
+ /**
+ * Override setTargetElement to operate on a target item that is a taxonomy term.
+ */
+ public function setTargetElement(FeedsSource $source, $target_term, $target_element, $value) {
switch ($target_element) {
case 'parent':
if (!empty($value)) {
$terms = taxonomy_get_term_by_name($value);
$parent_tid = '';
foreach ($terms as $term) {
- if ($term->vid == $target_node->vid) {
+ if ($term->vid == $target_term->vid) {
$parent_tid = $term->tid;
}
}
if (!empty($parent_tid)) {
- $target_node->parent[] = $parent_tid;
+ $target_term->parent[] = $parent_tid;
}
else {
- $target_node->parent[] = 0;
+ $target_term->parent[] = 0;
}
}
else {
- $target_node->parent[] = 0;
+ $target_term->parent[] = 0;
}
break;
case 'parentguid':
@@ -156,7 +148,7 @@ class FeedsTermProcessor extends FeedsProcessor {
->fields('feeds_item', array('entity_id'))
->condition('entity_type', $this->entityType());
$parent_tid = $query->condition('guid', $value)->execute()->fetchField();
- $target_node->parent[] = ($parent_tid) ? $parent_tid : 0;
+ $target_term->parent[] = ($parent_tid) ? $parent_tid : 0;
break;
case 'weight':
@@ -166,10 +158,10 @@ class FeedsTermProcessor extends FeedsProcessor {
else {
$weight = 0;
}
- $target_node->weight = $weight;
+ $target_term->weight = $weight;
break;
default:
- parent::setTargetElement($source, $target_node, $target_element, $value);
+ parent::setTargetElement($source, $target_term, $target_element, $value);
break;
}
}
@@ -184,31 +176,34 @@ class FeedsTermProcessor extends FeedsProcessor {
'name' => t('Term name'),
'description' => t('Name of the taxonomy term.'),
'optional_unique' => TRUE,
- ),
+ ),
'parent' => array(
- 'name' => t('Parent Term Name'),
- 'description' => t('Name of the Parent Term.'),
+ 'name' => t('Parent: Term name'),
+ 'description' => t('The name of the parent taxonomy term.'),
'optional_unique' => TRUE,
),
'parentguid' => array(
- 'name' => t('Parent GUID'),
- 'description' => t('The globally unique identifier of the item\'s parent term.'),
+ 'name' => t('Parent: GUID'),
+ 'description' => t('The GUID of the parent taxonomy term.'),
'optional_unique' => TRUE,
),
'weight' => array(
- 'name' => t('Term Weight'),
- 'description' => t('Weight of the Term.'),
+ 'name' => t('Term weight'),
+ 'description' => t('Weight of the taxonomy term.'),
'optional_unique' => TRUE,
),
'description' => array(
'name' => t('Term description'),
'description' => t('Description of the taxonomy term.'),
- ),
+ ),
);
+
// Let implementers of hook_feeds_term_processor_targets() add their targets.
try {
self::loadMappers();
- feeds_alter('feeds_processor_targets', $targets, 'taxonomy_term', $this->vocabulary()->machine_name);
+ $entity_type = $this->entityType();
+ $bundle = $this->vocabulary()->machine_name;
+ drupal_alter('feeds_processor_targets', $targets, $entity_type, $bundle);
}
catch (Exception $e) {
// Do nothing.
@@ -231,12 +226,6 @@ class FeedsTermProcessor extends FeedsProcessor {
if ($tid = db_query("SELECT tid FROM {taxonomy_term_data} WHERE name = :name AND vid = :vid", array(':name' => $value, ':vid' => $vocabulary->vid))->fetchField()) {
return $tid;
}
- } else if($target == 'guid') {
- $query = db_select('feeds_item')
- ->fields('feeds_item', array('entity_id'))
- ->condition('entity_type', 'taxonomy_term');
- $tid = $query->condition('guid', $value)->execute()->fetchField();
- return ($tid) ? $tid : 0;
}
}
return 0;
@@ -253,17 +242,4 @@ class FeedsTermProcessor extends FeedsProcessor {
}
throw new Exception(t('No vocabulary defined for Taxonomy Term processor.'));
}
-
- /**
- * Override getHash()
- *
- * @return string
- */
- protected function getHash($entity_id) {
- if($this->config['force_update']) {
- return ''; // dummy to always update
- } else {
- return parent::getHash($entity_id);
- }
- }
}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsUserProcessor.inc b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsUserProcessor.inc
index c8a1fa4..b067c41 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsUserProcessor.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/plugins/FeedsUserProcessor.inc
@@ -40,7 +40,10 @@ class FeedsUserProcessor extends FeedsProcessor {
* Loads an existing user.
*/
protected function entityLoad(FeedsSource $source, $uid) {
- return user_load($uid);
+ // Copy the password so that we can compare it again at save.
+ $user = user_load($uid);
+ $user->feeds_original_pass = $user->pass;
+ return $user;
}
/**
@@ -59,7 +62,15 @@ class FeedsUserProcessor extends FeedsProcessor {
if ($this->config['defuse_mail']) {
$account->mail = $account->mail . '_test';
}
- user_save($account, (array) $account);
+
+ $edit = (array) $account;
+
+ // Remove pass from $edit if the password is unchanged.
+ if (isset($account->feeds_original_pass) && $account->pass == $account->feeds_original_pass) {
+ unset($edit['pass']);
+ }
+
+ user_save($account, $edit);
if ($account->uid && !empty($account->openid)) {
$authmap = array(
'uid' => $account->uid,
@@ -192,7 +203,9 @@ class FeedsUserProcessor extends FeedsProcessor {
// Let other modules expose mapping targets.
self::loadMappers();
- feeds_alter('feeds_processor_targets', $targets, 'user', 'user');
+ $entity_type = $this->entityType();
+ $bundle = $this->entityType();
+ drupal_alter('feeds_processor_targets', $targets, $entity_type, $bundle);
return $targets;
}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/common_syndication_parser.test b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/common_syndication_parser.test
index a08e3fe..d61baad 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/common_syndication_parser.test
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/common_syndication_parser.test
@@ -1,6 +1,11 @@
<?php
/**
+ * @file
+ * Tests for the common syndication parser.
+ */
+
+/**
* Test cases for common syndication parser library.
*
* @todo Break out into Drupal independent test framework.
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds.test b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds.test
index 3710e1c..4bcb20c 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds.test
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds.test
@@ -148,7 +148,7 @@ class FeedsWebTestCase extends DrupalWebTestCase {
<body>
<outline text="Feeds test group" >
<outline title="Development Seed - Technological Solutions for Progressive Organizations" text="" xmlUrl="' . $path . 'developmentseed.rss2" type="rss" />
- <outline title="Magyar Nemzet Online - Hrek" text="" xmlUrl="' . $path . 'feed_without_guid.rss2" type="rss" />
+ <outline title="Magyar Nemzet Online - H\'rek" text="" xmlUrl="' . $path . 'feed_without_guid.rss2" type="rss" />
<outline title="Drupal planet" text="" type="rss" xmlUrl="' . $path . 'drupalplanet.rss2" />
</outline>
</body>
@@ -377,36 +377,148 @@ class FeedsWebTestCase extends DrupalWebTestCase {
$this->assertEqual($config['processor']['plugin_key'], $processor, 'Correct processor');
}
+ /**
+ * Adds mappings to a given configuration.
+ *
+ * @param string $id
+ * ID of the importer.
+ * @param array $mappings
+ * An array of mapping arrays. Each mapping array must have a source and
+ * an target key and can have a unique key.
+ * @param bool $test_mappings
+ * (optional) TRUE to automatically test mapping configs. Defaults to TRUE.
+ */
+ public function addMappings($id, $mappings, $test_mappings = TRUE) {
+
+ $path = "admin/structure/feeds/$id/mapping";
+
+ // Iterate through all mappings and add the mapping via the form.
+ foreach ($mappings as $i => $mapping) {
+
+ if ($test_mappings) {
+ $current_mapping_key = $this->mappingExists($id, $i, $mapping['source'], $mapping['target']);
+ $this->assertEqual($current_mapping_key, -1, 'Mapping does not exist before addition.');
+ }
+
+ // Get unique flag and unset it. Otherwise, drupalPost will complain that
+ // Split up config and mapping.
+ $config = $mapping;
+ unset($config['source'], $config['target']);
+ $mapping = array('source' => $mapping['source'], 'target' => $mapping['target']);
+
+ // Add mapping.
+ $this->drupalPost($path, $mapping, t('Add'));
+
+ // If there are other configuration options, set them.
+ if ($config) {
+ $this->drupalPostAJAX(NULL, array(), 'mapping_settings_edit_' . $i);
+
+ // Set some settings.
+ $edit = array();
+ foreach ($config as $key => $value) {
+ $edit["config[$i][settings][$key]"] = $value;
+ }
+ $this->drupalPostAJAX(NULL, $edit, 'mapping_settings_update_' . $i);
+ $this->drupalPost(NULL, array(), t('Save'));
+ }
+
+ if ($test_mappings) {
+ $current_mapping_key = $this->mappingExists($id, $i, $mapping['source'], $mapping['target']);
+ $this->assertTrue($current_mapping_key >= 0, 'Mapping exists after addition.');
+ }
+ }
+ }
+
/**
- * Add mappings to a given configuration.
+ * Remove mappings from a given configuration.
*
- * @param $mappings
- * An array of mapping arrays. Each mapping array must have a source and
- * an target key and can have a unique key.
+ * This function mimicks the Javascript behavior in feeds_ui.js
*
- * @see FeedsRSStoDataTest class.
+ * @param array $mappings
+ * An array of mapping arrays. Each mapping array must have a source and
+ * a target key and can have a unique key.
+ * @param bool $test_mappings
+ * (optional) TRUE to automatically test mapping configs. Defaults to TRUE.
*/
- public function addMappings($id, $mappings) {
+ public function removeMappings($id, $mappings, $test_mappings = TRUE) {
+ $path = "admin/structure/feeds/$id/mapping";
- $path = 'admin/structure/feeds/' . $id . '/mapping';
+ $current_mappings = $this->getCurrentMappings($id);
- // Iterate through all mappings and add the via the form.
+ // Iterate through all mappings and remove via the form.
foreach ($mappings as $i => $mapping) {
- // Get unique flag and unset it - otherwise drupalPost will complain that
- // there is no form element named "unique".
- $unique = !empty($mapping['unique']);
- unset($mapping['unique']);
- $this->drupalPost($path, $mapping, t('Add'));
+ if ($test_mappings) {
+ $current_mapping_key = $this->mappingExists($id, $i, $mapping['source'], $mapping['target']);
+ $this->assertEqual($current_mapping_key, $i, 'Mapping exists before removal.');
+ }
+
+ $remove_mapping = array("remove_flags[$i]" => 1);
+
+ $this->drupalPost($path, $remove_mapping, t('Save'));
+
+ $this->assertText('Your changes have been saved.');
+
+ if ($test_mappings) {
+ $current_mapping_key = $this->mappingExists($id, $i, $mapping['source'], $mapping['target']);
+ $this->assertEqual($current_mapping_key, -1, 'Mapping does not exist after removal.');
+ }
+ }
+ }
+
+ /**
+ * Gets an array of current mappings from the feeds_importer config.
+ *
+ * @param string $id
+ * ID of the importer.
+ *
+ * @return bool|array
+ * FALSE if the importer has no mappings, or an an array of mappings.
+ */
+ public function getCurrentMappings($id) {
+ $config = db_query("SELECT config FROM {feeds_importer} WHERE id = :id", array(':id' => $id))->fetchField();
+
+ $config = unserialize($config);
+
+ // We are very specific here. 'mappings' can either be an array or not
+ // exist.
+ if (array_key_exists('mappings', $config['processor']['config'])) {
+ $this->assertTrue(is_array($config['processor']['config']['mappings']), 'Mappings is an array.');
+
+ return $config['processor']['config']['mappings'];
+ }
+
+ return FALSE;
+ }
+
+ /**
+ * Determines if a mapping exists for a given importer.
+ *
+ * @param string $id
+ * ID of the importer.
+ * @param integer $i
+ * The key of the mapping.
+ * @param string $source
+ * The source field.
+ * @param string $target
+ * The target field.
+ *
+ * @return integer
+ * -1 if the mapping doesn't exist, the key of the mapping otherwise.
+ */
+ public function mappingExists($id, $i, $source, $target) {
- // If unique was set, set the last mapping's unique flag.
- if ($unique) {
- $edit = array(
- 'unique_flags[' . $i . ']' => 1,
- );
- $this->drupalPost($path, $edit, t('Save'));
+ $current_mappings = $this->getCurrentMappings($id);
+
+ if ($current_mappings) {
+ foreach ($current_mappings as $key => $mapping) {
+ if ($mapping['source'] == $source && $mapping['target'] == $target && $key == $i) {
+ return $key;
+ }
}
}
+
+ return -1;
}
/**
@@ -416,9 +528,10 @@ class FeedsWebTestCase extends DrupalWebTestCase {
$matches = array();
preg_match('/node\/(\d+?)$/', $url, $matches);
$nid = $matches[1];
- if (!is_numeric($nid)) {
- $this->error(t('Could not find node id, found @nid instead.', array('@nid' => $nid)));
- }
+
+ // Test for actual integerness.
+ $this->assertTrue($nid === (string) (int) $nid, 'Node id is an integer.');
+
return $nid;
}
@@ -433,6 +546,54 @@ class FeedsWebTestCase extends DrupalWebTestCase {
}
}
}
+
+ /**
+ * Download and extract SimplePIE.
+ *
+ * Sets the 'feeds_simplepie_library_dir' variable to the directory where
+ * SimplePie is downloaded.
+ */
+ function downloadExtractSimplePie($version) {
+ $url = "http://simplepie.org/downloads/simplepie_$version.mini.php";
+ $filename = 'simplepie.mini.php';
+
+ // Avoid downloading the file dozens of times
+ $library_dir = DRUPAL_ROOT . '/' . $this->originalFileDirectory . '/simpletest/feeds';
+ $simplepie_library_dir = $library_dir . '/simplepie';
+
+ if (!file_exists($library_dir)) {
+ drupal_mkdir($library_dir);
+ }
+
+ if (!file_exists($simplepie_library_dir)) {
+ drupal_mkdir($simplepie_library_dir);
+ }
+
+ // Local file name.
+ $local_file = $simplepie_library_dir . '/' . $filename;
+
+ // Begin single threaded code.
+ if (function_exists('sem_get')) {
+ $semaphore = sem_get(ftok(__FILE__, 1));
+ sem_acquire($semaphore);
+ }
+
+ // Download and extact the archive, but only in one thread.
+ if (!file_exists($local_file)) {
+ $local_file = system_retrieve_file($url, $local_file, FALSE, FILE_EXISTS_REPLACE);
+ }
+
+ if (function_exists('sem_get')) {
+ sem_release($semaphore);
+ }
+ // End single threaded code.
+
+ // Verify that files were successfully extracted.
+ $this->assertTrue(file_exists($local_file), t('@file found.', array('@file' => $local_file)));
+
+ // Set the simpletest library directory.
+ variable_set('feeds_library_dir', $library_dir);
+ }
}
/**
@@ -485,6 +646,7 @@ class FeedsUnitTestCase extends FeedsUnitTestHelper {
'example.org/~,$\'*;',
'caf%C3%A9.example.org',
'[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html',
+ 'graph.asfdasdfasdf.com/blarg/feed?access_token=133283760145143|tGew8jbxi1ctfVlYh35CPYij1eE',
);
foreach ($url_schemes as $scheme) {
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds/path_alias.csv b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds/path_alias.csv
new file mode 100644
index 0000000..a3b8ac2
--- /dev/null
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds/path_alias.csv
@@ -0,0 +1,10 @@
+Title,GUID,path
+pathauto1,1,path1
+pathauto2,2,path2
+pathauto3,3,path3
+pathauto4,4,path4
+pathauto5,5,path5
+pathauto6,6,path6
+pathauto7,7,path7
+pathauto8,8,path8
+pathauto9,9,path9
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds/profile.csv b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds/profile.csv
new file mode 100644
index 0000000..1e3ab6c
--- /dev/null
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds/profile.csv
@@ -0,0 +1,3 @@
+name,mail,color,letter
+magna,auctor at tortor.com,red,alpha
+rhoncus,rhoncus at habitasse.org,blue,beta
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_date_time.test b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_date_time.test
index f742d86..eac3d9f 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_date_time.test
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_date_time.test
@@ -12,7 +12,7 @@
* Not inheriting from Feeds base class as ParserCSV should be moved out of
* Feeds at some time.
*/
-class FeedsDateTimeTest extends FeedsWebTestCase {
+class FeedsDateTimeTest extends FeedsUnitTestHelper {
protected $profile = 'testing';
public static function getInfo() {
@@ -23,6 +23,11 @@ class FeedsDateTimeTest extends FeedsWebTestCase {
);
}
+ public function setUp() {
+ parent::setUp();
+ module_load_include('inc', 'feeds' , 'plugins/FeedsParser');
+ }
+
/**
* Dispatch tests, only use one entry point method testX to save time.
*/
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_config.test b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_config.test
new file mode 100644
index 0000000..b5fd92d
--- /dev/null
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_config.test
@@ -0,0 +1,115 @@
+<?php
+
+/**
+ * @file
+ * Test cases for Feeds mapping configuration form.
+ */
+
+/**
+ * Class for testing basic Feeds ajax mapping configurtaion form behavior.
+ */
+class FeedsMapperConfigTestCase extends FeedsMapperTestCase {
+ public static function getInfo() {
+ return array(
+ 'name' => 'Mapper: Config',
+ 'description' => 'Test the mapper configuration UI.',
+ 'group' => 'Feeds',
+ );
+ }
+
+ public function setUp() {
+ parent::setUp(array('feeds_tests'));
+ }
+
+ /**
+ * Basic test of mapping configuration.
+ */
+ public function test() {
+ // Create importer configuration.
+ $this->createImporterConfiguration();
+ $this->addMappings('syndication', array(
+ array(
+ 'source' => 'url',
+ 'target' => 'test_target',
+ ),
+ ));
+
+ // Click gear to get form.
+ $this->drupalPostAJAX(NULL, array(), 'mapping_settings_edit_0');
+
+ // Set some settings.
+ $edit = array(
+ 'config[0][settings][checkbox]' => 1,
+ 'config[0][settings][textfield]' => 'Some text',
+ 'config[0][settings][textarea]' => 'Textarea value: Didery dofffffffffffffffffffffffffffffffffffff',
+ 'config[0][settings][radios]' => 'option1',
+ 'config[0][settings][select]' => 'option4',
+ );
+ $this->drupalPostAJAX(NULL, $edit, 'mapping_settings_update_0');
+
+ // Click Save.
+ $this->drupalPost(NULL, array(), t('Save'));
+
+ // Reload.
+ $this->drupalGet('admin/structure/feeds/syndication/mapping');
+
+ // See if our settings were saved.
+ $this->assertText('Checkbox active.');
+ $this->assertText('Textfield value: Some text');
+ $this->assertText('Textarea value: Didery dofffffffffffffffffffffffffffffffffffff');
+ $this->assertText('Radios value: Option 1');
+ $this->assertText('Select value: Another One');
+
+ // Check that settings are in db.
+ $config = unserialize(db_query("SELECT config FROM {feeds_importer} WHERE id='syndication'")->fetchField());
+
+ $settings = $config['processor']['config']['mappings'][0];
+ $this->assertEqual($settings['checkbox'], 1);
+ $this->assertEqual($settings['textfield'], 'Some text');
+ $this->assertEqual($settings['textarea'], 'Textarea value: Didery dofffffffffffffffffffffffffffffffffffff');
+ $this->assertEqual($settings['radios'], 'option1');
+ $this->assertEqual($settings['select'], 'option4');
+
+
+ // Check that form validation works.
+ // Click gear to get form.
+ $this->drupalPostAJAX(NULL, array(), 'mapping_settings_edit_0');
+
+ // Set some settings.
+ $edit = array(
+ // Required form item.
+ 'config[0][settings][textfield]' => '',
+ );
+ $this->drupalPostAJAX(NULL, $edit, 'mapping_settings_update_0');
+ $this->assertText('A text field field is required.');
+ $this->drupalPost(NULL, array(), t('Save'));
+ // Reload.
+ $this->drupalGet('admin/structure/feeds/syndication/mapping');
+ // Value has not changed.
+ $this->assertText('Textfield value: Some text');
+
+ // Check that multiple mappings work.
+ $this->addMappings('syndication', array(
+ 1 => array(
+ 'source' => 'url',
+ 'target' => 'test_target',
+ ),
+ ));
+ $this->assertText('Checkbox active.');
+ $this->assertText('Checkbox inactive.');
+ // Click gear to get form.
+ $this->drupalPostAJAX(NULL, array(), 'mapping_settings_edit_1');
+ // Set some settings.
+ $edit = array(
+ 'config[1][settings][textfield]' => 'Second mapping text',
+ );
+ $this->drupalPostAJAX(NULL, $edit, 'mapping_settings_update_1');
+ // Click Save.
+ $this->drupalPost(NULL, array(), t('Save'));
+ // Reload.
+ $this->drupalGet('admin/structure/feeds/syndication/mapping');
+ $this->assertText('Checkbox active.');
+ $this->assertText('Checkbox inactive.');
+ $this->assertText('Second mapping text');
+ }
+}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_date.test b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_date.test
index f9020e0..60fb383 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_date.test
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_date.test
@@ -46,19 +46,19 @@ class FeedsMapperDateTestCase extends FeedsMapperTestCase {
$this->setPlugin('daterss', 'FeedsSyndicationParser');
$this->setSettings('daterss', 'FeedsNodeProcessor', array('content_type' => $typename));
$this->addMappings('daterss', array(
- array(
+ 0 => array(
'source' => 'title',
'target' => 'title',
),
- array(
+ 1 => array(
'source' => 'description',
'target' => 'body',
),
- array(
+ 2 => array(
'source' => 'timestamp',
'target' => 'field_date:start',
),
- array(
+ 3 => array(
'source' => 'timestamp',
'target' => 'field_datestamp:start',
),
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_field.test b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_field.test
index f0684da..130d0af 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_field.test
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_field.test
@@ -40,31 +40,31 @@ class FeedsMapperFieldTestCase extends FeedsMapperTestCase {
$this->setPlugin('csv', 'FeedsCSVParser');
$this->setSettings('csv', 'FeedsNodeProcessor', array('content_type' => $typename));
$this->addMappings('csv', array(
- array(
+ 0 => array(
'source' => 'title',
'target' => 'title',
),
- array(
+ 1 => array(
'source' => 'created',
'target' => 'created',
),
- array(
+ 2 => array(
'source' => 'body',
'target' => 'body',
),
- array(
+ 3 => array(
'source' => 'alpha',
'target' => 'field_alpha',
),
- array(
+ 4 => array(
'source' => 'beta',
'target' => 'field_beta',
),
- array(
+ 5 => array(
'source' => 'gamma',
'target' => 'field_gamma',
),
- array(
+ 6 => array(
'source' => 'delta',
'target' => 'field_delta',
),
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_file.test b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_file.test
index d642e94..909e47e 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_file.test
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_file.test
@@ -30,7 +30,16 @@ class FeedsMapperFileTestCase extends FeedsMapperTestCase {
// site before running the test, it will work fine. Since it is truly screwy, lets just
// force it to use drupal_http_request for this test case.
variable_set('feeds_never_use_curl', TRUE);
-
+ variable_set('clean_url', TRUE);
+
+ // Only download simplepie if the plugin doesn't already exist somewhere.
+ // People running tests locally might have it.
+ if (!feeds_simplepie_exists()) {
+ $this->downloadExtractSimplePie('1.3');
+ $this->assertTrue(feeds_simplepie_exists());
+ // Reset all the caches!
+ $this->resetAll();
+ }
$typename = $this->createContentType(array(), array('files' => 'file'));
// 1) Test mapping remote resources to file field.
@@ -40,15 +49,15 @@ class FeedsMapperFileTestCase extends FeedsMapperTestCase {
$this->setPlugin('syndication', 'FeedsSimplePieParser');
$this->setSettings('syndication', 'FeedsNodeProcessor', array('content_type' => $typename));
$this->addMappings('syndication', array(
- array(
+ 0 => array(
'source' => 'title',
'target' => 'title'
),
- array(
+ 1 => array(
'source' => 'timestamp',
'target' => 'created'
),
- array(
+ 2 => array(
'source' => 'enclosures',
'target' => 'field_files'
),
@@ -56,7 +65,7 @@ class FeedsMapperFileTestCase extends FeedsMapperTestCase {
$nid = $this->createFeedNode('syndication', $GLOBALS['base_url'] . '/testing/feeds/flickr.xml');
$this->assertText('Created 5 nodes');
- $files = $this->testFiles();
+ $files = $this->_testFiles();
$entities = db_select('feeds_item')
->fields('feeds_item', array('entity_id'))
->condition('id', 'syndication')
@@ -83,11 +92,11 @@ class FeedsMapperFileTestCase extends FeedsMapperTestCase {
$this->setPlugin('node', 'FeedsCSVParser');
$this->setSettings('node', 'FeedsNodeProcessor', array('content_type' => $typename));
$this->addMappings('node', array(
- array(
+ 0 => array(
'source' => 'title',
'target' => 'title'
),
- array(
+ 1 => array(
'source' => 'file',
'target' => 'field_files'
),
@@ -105,7 +114,7 @@ class FeedsMapperFileTestCase extends FeedsMapperTestCase {
$this->assertText('Created 5 nodes');
// Assert: files should be in resources/.
- $files = $this->testFiles();
+ $files = $this->_testFiles();
$entities = db_select('feeds_item')
->fields('feeds_item', array('entity_id'))
->condition('id', 'node')
@@ -131,7 +140,7 @@ class FeedsMapperFileTestCase extends FeedsMapperTestCase {
$this->assertText('Created 5 nodes');
// Assert: files should be in images/ now.
- $files = $this->testFiles();
+ $files = $this->_testFiles();
$entities = db_select('feeds_item')
->fields('feeds_item', array('entity_id'))
->condition('id', 'node')
@@ -145,7 +154,7 @@ class FeedsMapperFileTestCase extends FeedsMapperTestCase {
// Deleting all imported items will delete the files from the images/ dir.
// @todo: for some reason the first file does not get deleted.
// $this->drupalPost('import/node/delete-items', array(), 'Delete');
-// foreach ($this->testFiles() as $file) {
+// foreach ($this->_testFiles() as $file) {
// $this->assertFalse(is_file("public://images/$file"));
// }
}
@@ -153,7 +162,7 @@ class FeedsMapperFileTestCase extends FeedsMapperTestCase {
/**
* Lists test files.
*/
- public function testFiles() {
+ public function _testFiles() {
return array('tubing.jpeg', 'foosball.jpeg', 'attersee.jpeg', 'hstreet.jpeg', 'la fayette.jpeg');
}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_link.test b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_link.test
index 7724dd8..5fddbb1 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_link.test
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_link.test
@@ -61,39 +61,39 @@ class FeedsMapperLinkTestCase extends FeedsMapperTestCase {
$this->createImporterConfiguration(); //Create a default importer configuration
$this->setSettings('syndication', 'FeedsNodeProcessor', array('content_type' => $typename)); //Processor settings
$this->addMappings('syndication', array(
- array(
+ 0 => array(
'source' => 'title',
'target' => 'title'
),
- array(
+ 1 => array(
'source' => 'timestamp',
'target' => 'created'
),
- array(
+ 2 => array(
'source' => 'description',
'target' => 'body'
),
- array(
+ 3 => array(
'source' => 'url',
'target' => 'field_alpha:url'
),
- array(
+ 4 => array(
'source' => 'title',
'target' => 'field_alpha:title'
),
- array(
+ 5 => array(
'source' => 'url',
'target' => 'field_beta:url'
),
- array(
+ 6 => array(
'source' => 'url',
'target' => 'field_gamma:url'
),
- array(
+ 7 => array(
'source' => 'title',
'target' => 'field_gamma:title'
),
- array(
+ 8 => array(
'source' => 'url',
'target' => 'field_omega:url'
),
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_path.test b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_path.test
new file mode 100644
index 0000000..55f75b0
--- /dev/null
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_path.test
@@ -0,0 +1,240 @@
+<?php
+
+/**
+ * @file
+ * Test case for path alias mapper path.inc.
+ */
+
+/**
+ * Class for testing Feeds <em>path</em> mapper.
+ */
+class FeedsMapperPathTestCase extends FeedsMapperTestCase {
+ public static function getInfo() {
+ return array(
+ 'name' => 'Mapper: Path',
+ 'description' => 'Test Feeds Mapper support for path aliases.',
+ 'group' => 'Feeds',
+ );
+ }
+
+ public function setUp() {
+ parent::setUp(array('path'));
+ }
+
+ /**
+ * Basic test loading a single entry CSV file.
+ */
+ public function testNodeAlias() {
+
+ // Create importer configuration.
+ $this->createImporterConfiguration($this->randomName(), 'path_test');
+ $this->setPlugin('path_test', 'FeedsFileFetcher');
+ $this->setPlugin('path_test', 'FeedsCSVParser');
+ $this->addMappings('path_test', array(
+ 0 => array(
+ 'source' => 'Title',
+ 'target' => 'title',
+ ),
+ 1 => array(
+ 'source' => 'path',
+ 'target' => 'path_alias',
+ ),
+ 2 => array(
+ 'source' => 'GUID',
+ 'target' => 'guid',
+ 'unique' => TRUE,
+ ),
+ ));
+
+ // Turn on update existing.
+ $this->setSettings('path_test', 'FeedsNodeProcessor', array('update_existing' => 2));
+
+ // Import RSS file.
+ $this->importFile('path_test', $this->absolutePath() . '/tests/feeds/path_alias.csv');
+ $this->assertText('Created 9 nodes');
+
+ $aliases = array();
+
+ for ($i = 1; $i <= 9; $i++) {
+ $aliases[] = "path$i";
+ }
+
+ $this->assertAliasCount($aliases);
+
+ // Adding a mapping will force update.
+ $this->addMappings('path_test', array(
+ 3 => array(
+ 'source' => 'fake',
+ 'target' => 'body',
+ ),
+ ));
+ // Import RSS file.
+ $this->importFile('path_test', $this->absolutePath() . '/tests/feeds/path_alias.csv');
+ $this->assertText('Updated 9 nodes');
+
+ // Check that duplicate aliases are not created.
+ $this->assertAliasCount($aliases);
+ }
+
+ /**
+ * Test support for term aliases.
+ */
+ public function testTermAlias() {
+
+ // Create importer configuration.
+ $this->createImporterConfiguration($this->randomName(), 'path_test');
+ $this->setPlugin('path_test', 'FeedsFileFetcher');
+ $this->setPlugin('path_test', 'FeedsCSVParser');
+ $this->setPlugin('path_test', 'FeedsTermProcessor');
+
+ // Create vocabulary.
+ $edit = array(
+ 'name' => 'Addams vocabulary',
+ 'machine_name' => 'addams',
+ );
+ $this->drupalPost('admin/structure/taxonomy/add', $edit, t('Save'));
+
+ $this->setSettings('path_test', 'FeedsTermProcessor', array('vocabulary' => 'addams'));
+
+ // Turn on update existing.
+ $this->setSettings('path_test', 'FeedsTermProcessor', array('update_existing' => 2));
+
+ // Add mappings.
+ $this->addMappings('path_test', array(
+ 0 => array(
+ 'source' => 'Title',
+ 'target' => 'name',
+ ),
+ 1 => array(
+ 'source' => 'path',
+ 'target' => 'path_alias',
+ ),
+ 2 => array(
+ 'source' => 'GUID',
+ 'target' => 'guid',
+ 'unique' => TRUE,
+ ),
+ ));
+
+ // Import RSS file.
+ $this->importFile('path_test', $this->absolutePath() . '/tests/feeds/path_alias.csv');
+ $this->assertText('Created 9 terms');
+
+ $aliases = array();
+
+ for ($i = 1; $i <= 9; $i++) {
+ $aliases[] = "path$i";
+ }
+
+ $this->assertAliasCount($aliases);
+
+ // Adding a mapping will force update.
+ $this->addMappings('path_test', array(
+ 3 => array(
+ 'source' => 'fake',
+ 'target' => 'description',
+ ),
+ ));
+ // Import RSS file.
+ $this->importFile('path_test', $this->absolutePath() . '/tests/feeds/path_alias.csv');
+ $this->assertText('Updated 9 terms');
+
+ // Check that duplicate aliases are not created.
+ $this->assertAliasCount($aliases);
+ }
+
+ public function assertAliasCount($aliases) {
+ $in_db = db_select('url_alias', 'a')
+ ->fields('a')
+ ->condition('a.alias', $aliases)
+ ->execute()
+ ->fetchAll();
+
+ $this->assertEqual(count($in_db), count($aliases), 'Correct number of aliases in db.');
+ }
+}
+
+/**
+ * Class for testing Feeds <em>path</em> mapper with pathauto.module.
+ */
+class FeedsMapperPathPathautoTestCase extends FeedsMapperTestCase {
+ public static function getInfo() {
+ return array(
+ 'name' => 'Mapper: Path with pathauto',
+ 'description' => 'Test Feeds Mapper support for path aliases and pathauto.',
+ 'group' => 'Feeds',
+ 'dependencies' => array('pathauto'),
+ );
+ }
+
+ public function setUp() {
+ parent::setUp(array('pathauto'));
+ }
+
+ /**
+ * Basic for allowing pathauto to override the alias.
+ */
+ public function test() {
+
+ // Create importer configuration.
+ $this->createImporterConfiguration($this->randomName(), 'path_test');
+ $this->setPlugin('path_test', 'FeedsFileFetcher');
+ $this->setPlugin('path_test', 'FeedsCSVParser');
+ $this->addMappings('path_test', array(
+ 0 => array(
+ 'source' => 'Title',
+ 'target' => 'title',
+ 'unique' => FALSE,
+ ),
+ 1 => array(
+ 'source' => 'does_not_exist',
+ 'target' => 'path_alias',
+ 'pathauto_override' => TRUE,
+ ),
+ 2 => array(
+ 'source' => 'GUID',
+ 'target' => 'guid',
+ 'unique' => TRUE,
+ ),
+ ));
+
+ // Turn on update existing.
+ $this->setSettings('path_test', 'FeedsNodeProcessor', array('update_existing' => 2));
+
+ // Import RSS file.
+ $this->importFile('path_test', $this->absolutePath() . '/tests/feeds/path_alias.csv');
+ $this->assertText('Created 9 nodes');
+
+ $aliases = array();
+
+ for ($i = 1; $i <= 9; $i++) {
+ $aliases[] = "path$i";
+ }
+
+ $this->assertAliasCount($aliases);
+
+ // Adding a mapping will force update.
+ $this->addMappings('path_test', array(
+ 3 => array(
+ 'source' => 'fake',
+ 'target' => 'body',
+ ),
+ ));
+ // Import RSS file.
+ $this->importFile('path_test', $this->absolutePath() . '/tests/feeds/path_alias.csv');
+ $this->assertText('Updated 9 nodes');
+
+ // Check that duplicate aliases are not created.
+ $this->assertAliasCount($aliases);
+ }
+
+ public function assertAliasCount($aliases) {
+ $in_db = db_select('url_alias', 'a')
+ ->fields('a')
+ ->condition('a.alias', $aliases)
+ ->execute()
+ ->fetchAll();
+
+ $this->assertEqual(count($in_db), count($aliases), 'Correct number of aliases in db.');
+ }
+}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_profile.test b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_profile.test
new file mode 100644
index 0000000..9ced5db
--- /dev/null
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_profile.test
@@ -0,0 +1,102 @@
+<?php
+
+/**
+ * @file
+ * Test suite for profile mapper mappers/profile.inc.
+ */
+
+/**
+ * Class for testing Feeds profile mapper.
+ */
+class FeedsMapperProfileTestCase extends FeedsMapperTestCase {
+ public static function getInfo() {
+ return array(
+ 'name' => 'Mapper: Profile',
+ 'description' => 'Test Feeds Mapper support for profile fields.',
+ 'group' => 'Feeds',
+ );
+ }
+
+ function setUp() {
+ // Call parent setup with required modules.
+ parent::setUp(array('profile'));
+ }
+
+ /**
+ * Basic test loading a doulbe entry CSV file.
+ */
+ function test() {
+
+ // Create profile fields.
+ $edit = array(
+ 'category' => 'test',
+ 'title' => 'color',
+ 'name' => 'profile_textfield_test',
+ 'register' => 1,
+ );
+ $name = $this->drupalPost('admin/config/people/profile/add/textfield', $edit, t('Save field'));
+ $edit = array(
+ 'category' => 'test',
+ 'title' => 'letter',
+ 'name' => 'profile_select_test',
+ 'options' => 'alpha' . "\n" . 'beta' . "\n" . 'gamma',
+ 'register' => 1,
+ );
+ $name = $this->drupalPost('admin/config/people/profile/add/selection', $edit, t('Save field'));
+
+ // Create an importer.
+ $this->createImporterConfiguration('Profile import', 'profile_import');
+
+ // Set and configure plugins.
+ $this->setPlugin('profile_import', 'FeedsFileFetcher');
+ $this->setPlugin('profile_import', 'FeedsCSVParser');
+ $this->setPlugin('profile_import', 'FeedsUserProcessor');
+
+ // Go to mapping page and create a couple of mappings.
+ $mappings = array(
+ '0' => array(
+ 'source' => 'name',
+ 'target' => 'name',
+ 'unique' => 0,
+ ),
+ '1' => array(
+ 'source' => 'mail',
+ 'target' => 'mail',
+ 'unique' => 1,
+ ),
+ '2' => array(
+ 'source' => 'color',
+ 'target' => 'profile_textfield_test',
+ ),
+ '3' => array(
+ 'source' => 'letter',
+ 'target' => 'profile_select_test',
+ ),
+ );
+ $this->addMappings('profile_import', $mappings);
+
+ // Change some of the basic configuration.
+ $edit = array(
+ 'content_type' => '',
+ 'import_period' => FEEDS_SCHEDULE_NEVER,
+ );
+ $this->drupalPost('admin/structure/feeds/profile_import/settings', $edit, 'Save');
+
+ // Import CSV file.
+ $this->importFile('profile_import', $this->absolutePath() .'/tests/feeds/profile.csv');
+ $this->assertText('Created 2 users.');
+
+ // Check the two imported users.
+ $this->drupalGet('admin/people');
+ $this->assertText('magna');
+ $this->assertText('rhoncus');
+
+ $account = user_load_by_name('magna');
+ $this->assertEqual($account->profile_textfield_test, 'red', 'User profile_textfield_test is correct');
+ $this->assertEqual($account->profile_select_test, 'alpha', 'User profile_select_test is correct');
+
+ $account = user_load_by_name('rhoncus');
+ $this->assertEqual($account->profile_textfield_test, 'blue', 'User profile_textfield_test is correct');
+ $this->assertEqual($account->profile_select_test, 'beta', 'User profile_select_test is correct');
+ }
+}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_taxonomy.test b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_taxonomy.test
index 4ee4277..94dd188 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_taxonomy.test
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_mapper_taxonomy.test
@@ -85,27 +85,24 @@ class FeedsMapperTaxonomyTestCase extends FeedsMapperTestCase {
$this->createImporterConfiguration('Syndication', 'syndication');
$this->addMappings('syndication',
array(
- array(
+ 0 => array(
'source' => 'title',
'target' => 'title',
- 'unique' => FALSE,
),
- array(
+ 1 => array(
'source' => 'description',
'target' => 'body',
- 'unique' => FALSE,
),
- array(
+ 2 => array(
'source' => 'timestamp',
'target' => 'created',
- 'unique' => FALSE,
),
- array(
+ 3 => array(
'source' => 'url',
'target' => 'url',
'unique' => TRUE,
),
- array(
+ 4 => array(
'source' => 'guid',
'target' => 'guid',
'unique' => TRUE,
@@ -125,15 +122,13 @@ class FeedsMapperTaxonomyTestCase extends FeedsMapperTestCase {
$this->assertText('Do not import on submission');
// Map feed node's taxonomy to feed item node's taxonomy.
- $this->addMappings('syndication',
- array(
- array(
- 'source' => 'parent:taxonomy:tags',
- 'target' => 'field_tags',
- 'unique' => FALSE,
- ),
- )
+ $mappings = array(
+ 5 => array(
+ 'source' => 'parent:taxonomy:tags',
+ 'target' => 'field_tags',
+ ),
);
+ $this->addMappings('syndication', $mappings);
// Create feed node and add term term1.
$langcode = LANGUAGE_NONE;
@@ -271,6 +266,6 @@ class FeedsMapperTaxonomyTestCase extends FeedsMapperTestCase {
*/
public function assertTaxonomyTerm($term) {
$term = check_plain($term);
- $this->assertPattern('/<a href="(.*?)\/taxonomy\/term\/([0-9]*?)"(.*)>' . $term . '<\/a>/', 'Found ' . $term);
+ $this->assertPattern('/<a href="\/.*taxonomy\/term\/[0-9]+">' . $term . '<\/a>/', 'Found ' . $term);
}
}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_parser_sitemap.test b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_parser_sitemap.test
index 6b79804..0607d89 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_parser_sitemap.test
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_parser_sitemap.test
@@ -26,27 +26,27 @@ class FeedsSitemapParserTestCase extends FeedsWebTestCase {
$this->addMappings('sitemap',
array(
- array(
+ 0 => array(
'source' => 'changefreq',
'target' => 'title',
'unique' => FALSE,
),
- array(
+ 1 => array(
'source' => 'priority',
'target' => 'body',
'unique' => FALSE,
),
- array(
+ 2 => array(
'source' => 'lastmod',
'target' => 'created',
'unique' => FALSE,
),
- array(
+ 3 => array(
'source' => 'url',
'target' => 'url',
'unique' => TRUE,
),
- array(
+ 4 => array(
'source' => 'url',
'target' => 'guid',
'unique' => TRUE,
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_processor_node.test b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_processor_node.test
index 4db78aa..677bd95 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_processor_node.test
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_processor_node.test
@@ -36,27 +36,25 @@ class FeedsRSStoNodesTest extends FeedsWebTestCase {
$this->createImporterConfiguration('Syndication', 'syndication');
$this->addMappings('syndication',
array(
- array(
+ 0 => array(
'source' => 'title',
'target' => 'title',
'unique' => FALSE,
),
- array(
+ 1 => array(
'source' => 'description',
'target' => 'body',
- 'unique' => FALSE,
),
- array(
+ 2 => array(
'source' => 'timestamp',
'target' => 'created',
- 'unique' => FALSE,
),
- array(
+ 3 => array(
'source' => 'url',
'target' => 'url',
'unique' => TRUE,
),
- array(
+ 4 => array(
'source' => 'guid',
'target' => 'guid',
'unique' => TRUE,
@@ -91,11 +89,10 @@ class FeedsRSStoNodesTest extends FeedsWebTestCase {
$this->assertEqual($count, 10, 'Accurate number of items in database.');
// Assert default input format on first imported feed node.
-/*
-// NEEDS update.
- $format = db_query_range("SELECT nr.format FROM {feeds_node_item} fi JOIN {node} n ON fi.nid = n.nid JOIN {node_revision} nr ON n.vid = nr.vid", 0, 1)->fetchField();
- $this->assertEqual($format, filter_fallback_format(), 'Using default Input format.');
-*/
+
+ // NEEDS update.
+ // $format = db_query_range("SELECT nr.format FROM {feeds_node_item} fi JOIN {node} n ON fi.nid = n.nid JOIN {node_revision} nr ON n.vid = nr.vid", 0, 1)->fetchField();
+ // $this->assertEqual($format, filter_fallback_format(), 'Using default Input format.');
// Import again.
$this->drupalPost("node/$nid/import", array(), 'Import');
@@ -147,9 +144,9 @@ class FeedsRSStoNodesTest extends FeedsWebTestCase {
$this->assertText('Deleted 10 nodes');
$this->assertFeedItemCount(0);
- // Change author.
+ // Change author and turn off authorization.
$this->auth_user = $this->drupalCreateUser(array('access content'));
- $this->setSettings('syndication', 'FeedsNodeProcessor', array('author' => $this->auth_user->name));
+ $this->setSettings('syndication', 'FeedsNodeProcessor', array('author' => $this->auth_user->name, 'authorize' => FALSE));
// Change input format.
$this->setSettings('syndication', 'FeedsNodeProcessor', array('input_format' => 'plain_text'));
@@ -165,11 +162,10 @@ class FeedsRSStoNodesTest extends FeedsWebTestCase {
$this->assertEqual($count, 10, 'Accurate number of items in database.');
// Assert input format.
-/*
-// NEEDS update.
- $format = db_query_range("SELECT nr.format FROM {feeds_node_item} fi JOIN {node} n ON fi.nid = n.nid JOIN {node_revision} nr ON n.vid = nr.vid", 0, 1)->fetchField();
- $this->assertEqual($format, filter_fallback_format() + 1, 'Set non-default Input format.');
-*/
+
+ // NEEDS update.
+ // $format = db_query_range("SELECT nr.format FROM {feeds_node_item} fi JOIN {node} n ON fi.nid = n.nid JOIN {node_revision} nr ON n.vid = nr.vid", 0, 1)->fetchField();
+ // $this->assertEqual($format, filter_fallback_format() + 1, 'Set non-default Input format.');
// Set to update existing, remove authorship of above nodes and import again.
$this->setSettings('syndication', 'FeedsNodeProcessor', array('update_existing' => 2));
@@ -193,7 +189,7 @@ class FeedsRSStoNodesTest extends FeedsWebTestCase {
// should now be assigned to feed node author.
$this->addMappings('syndication',
array(
- array(
+ 5 => array(
'source' => 'parent:uid',
'target' => 'uid',
),
@@ -230,27 +226,25 @@ class FeedsRSStoNodesTest extends FeedsWebTestCase {
$this->drupalPost('admin/structure/feeds/syndication_standalone/settings', $edit, 'Save');
$this->addMappings('syndication_standalone',
array(
- array(
+ 0 => array(
'source' => 'title',
'target' => 'title',
'unique' => FALSE,
),
- array(
+ 1 => array(
'source' => 'description',
'target' => 'body',
- 'unique' => FALSE,
),
- array(
+ 2 => array(
'source' => 'timestamp',
'target' => 'created',
- 'unique' => FALSE,
),
- array(
+ 3 => array(
'source' => 'url',
'target' => 'url',
'unique' => TRUE,
),
- array(
+ 4 => array(
'source' => 'guid',
'target' => 'guid',
'unique' => TRUE,
@@ -412,4 +406,53 @@ class FeedsRSStoNodesTest extends FeedsWebTestCase {
$this->drupalGet('node/add/article');
$this->assertNoFieldByName('feeds[FeedsHTTPFetcher][source]');
}
+
+ /**
+ * Test that nodes will not be created if the user is unauthorized to create
+ * them.
+ */
+ public function testAuthorize() {
+
+ // Create a user with limited permissions. We can't use
+ // $this->drupalCreateUser here because we need to to set a specific user
+ // name.
+ $edit = array(
+ 'name' => 'Development Seed',
+ 'mail' => 'devseed at example.com',
+ 'pass' => user_password(),
+ 'status' => 1,
+ );
+
+ $account = user_save(drupal_anonymous_user(), $edit);
+
+ // Adding a mapping to the user_name will invoke authorization.
+ $this->addMappings('syndication',
+ array(
+ 5 => array(
+ 'source' => 'author_name',
+ 'target' => 'user_name',
+ ),
+ )
+ );
+
+ $nid = $this->createFeedNode();
+
+ $this->assertText('Failed importing 10 nodes.');
+ $this->assertText('User ' . $account->name . ' is not authorized to create content type article.');
+ $node_count = db_query("SELECT COUNT(*) FROM {node}")->fetchField();
+
+ // We should have 1 node, the feed node.
+ $this->assertEqual($node_count, 1, t('Correct number of nodes in the database.'));
+
+ // Give the user our admin powers.
+ $edit = array(
+ 'roles' => $this->admin_user->roles,
+ );
+ $account = user_save($account, $edit);
+
+ $this->drupalPost("node/$nid/import", array(), 'Import');
+ $this->assertText('Created 10 nodes.');
+ $node_count = db_query("SELECT COUNT(*) FROM {node}")->fetchField();
+ $this->assertEqual($node_count, 11, t('Correct number of nodes in the database.'));
+ }
}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_processor_term.test b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_processor_term.test
index ac8aa55..4adcd08 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_processor_term.test
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_processor_term.test
@@ -30,7 +30,7 @@ class FeedsCSVtoTermsTest extends FeedsWebTestCase {
$this->setPlugin('term_import', 'FeedsCSVParser');
$this->setPlugin('term_import', 'FeedsTermProcessor');
$mappings = array(
- '0' => array(
+ 0 => array(
'source' => 'name',
'target' => 'name',
'unique' => 1,
@@ -68,6 +68,14 @@ class FeedsCSVtoTermsTest extends FeedsWebTestCase {
$this->importFile('term_import', $this->absolutePath() . '/tests/feeds/users.csv');
$this->assertText('There are no new terms.');
+ // Force update.
+ $this->setSettings('term_import', 'FeedsTermProcessor', array(
+ 'skip_hash_check' => TRUE,
+ 'update_existing' => 2,
+ ));
+ $this->importFile('term_import', $this->absolutePath() . '/tests/feeds/users.csv');
+ $this->assertText('Updated 5 terms.');
+
// Add a term manually, delete all terms, this term should still stand.
$edit = array(
'name' => 'Cousin Itt',
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_processor_user.test b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_processor_user.test
index bec9dd0..73f8d06 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_processor_user.test
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_processor_user.test
@@ -31,25 +31,23 @@ class FeedsCSVtoUsersTest extends FeedsWebTestCase {
// Go to mapping page and create a couple of mappings.
$mappings = array(
- '0' => array(
+ 0 => array(
'source' => 'name',
'target' => 'name',
- 'unique' => 0,
+ 'unique' => FALSE,
),
- '1' => array(
+ 1 => array(
'source' => 'mail',
'target' => 'mail',
- 'unique' => 1,
+ 'unique' => TRUE,
),
- '2' => array(
+ 2 => array(
'source' => 'since',
'target' => 'created',
- 'unique' => FALSE,
),
- '3' => array(
+ 3 => array(
'source' => 'password',
'target' => 'pass',
- 'unique' => 0,
),
);
$this->addMappings('user_import', $mappings);
@@ -76,7 +74,7 @@ class FeedsCSVtoUsersTest extends FeedsWebTestCase {
$this->assertText('Created 3 users');
// 1 user has an invalid email address, all users should be assigned
// the manager role.
- $this->assertText('Failed importing 2 user');
+ $this->assertText('Failed importing 2 users.');
$this->drupalGet('admin/people');
$this->assertText('Morticia');
$this->assertText('Fester');
@@ -86,12 +84,39 @@ class FeedsCSVtoUsersTest extends FeedsWebTestCase {
$count = db_query("SELECT count(*) FROM {users_roles} WHERE rid = :rid", array(':rid' => $admin_rid))->fetchField();
$this->assertEqual($count, 0, t('No imported user was assigned the administrator role.'));
- // @todo Test status setting, update existing and role settings.
+ // Run import again, verify no new users.
+ $this->importFile('user_import', $this->absolutePath() . '/tests/feeds/users.csv');
+ $this->assertText('Failed importing 2 users.');
// Attempt to log in as one of the imported users.
$account = user_load_by_name('Morticia');
$this->assertTrue($account, 'Imported user account loaded.');
$account->pass_raw = 'mort';
$this->drupalLogin($account);
+
+ // Login as admin.
+ $this->drupalLogin($this->admin_user);
+
+ // Removing a mapping forces updating without needing a different file.
+ // We are also testing that if we don't map anything to the user's password
+ // that it will keep its existing one.
+ $mappings = array(
+ 3 => array(
+ 'source' => 'password',
+ 'target' => 'pass',
+ ),
+ );
+ $this->removeMappings('user_import', $mappings);
+ $this->setSettings('user_import', 'FeedsUserProcessor', array('update_existing' => 2));
+ $this->importFile('user_import', $this->absolutePath() . '/tests/feeds/users.csv');
+ // Assert result.
+ $this->assertText('Updated 3 users');
+ $this->assertText('Failed importing 2 user');
+
+ // Attempt to log in as one of the imported users.
+ $account = user_load_by_name('Fester');
+ $this->assertTrue($account, 'Imported user account loaded.');
+ $account->pass_raw = 'fest';
+ $this->drupalLogin($account);
}
}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_scheduler.test b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_scheduler.test
index c60c461..861e8c9 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_scheduler.test
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_scheduler.test
@@ -26,27 +26,25 @@ class FeedsSchedulerTestCase extends FeedsWebTestCase {
$this->createImporterConfiguration();
$this->addMappings('syndication',
array(
- array(
+ 0 => array(
'source' => 'title',
'target' => 'title',
'unique' => FALSE,
),
- array(
+ 1 => array(
'source' => 'description',
'target' => 'body',
- 'unique' => FALSE,
),
- array(
+ 2 => array(
'source' => 'timestamp',
'target' => 'created',
- 'unique' => FALSE,
),
- array(
+ 3 => array(
'source' => 'url',
'target' => 'url',
'unique' => TRUE,
),
- array(
+ 4 => array(
'source' => 'guid',
'target' => 'guid',
'unique' => TRUE,
@@ -210,7 +208,7 @@ class FeedsSchedulerTestCase extends FeedsWebTestCase {
$this->setPlugin('node', 'FeedsFileFetcher');
$this->setPlugin('node', 'FeedsCSVParser');
$mappings = array(
- '0' => array(
+ 0 => array(
'source' => 'title',
'target' => 'title',
),
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_tests.info b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_tests.info
index 354ec12..deff209 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_tests.info
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_tests.info
@@ -6,9 +6,9 @@ core = 7.x
files[] = feeds_test.module
hidden = TRUE
-; Information added by drupal.org packaging script on 2012-05-28
-version = "7.x-2.0-alpha5"
+; Information added by drupal.org packaging script on 2012-10-10
+version = "7.x-2.0-alpha6"
core = "7.x"
project = "feeds"
-datestamp = "1338228956"
+datestamp = "1349851321"
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_tests.module b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_tests.module
index e1e5f97..ade38b2 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_tests.module
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/tests/feeds_tests.module
@@ -1,6 +1,11 @@
<?php
/**
+ * @file
+ * Helper module for Feeds tests.
+ */
+
+/**
* Implements hook_menu().
*/
function feeds_tests_menu() {
@@ -71,3 +76,109 @@ function feeds_tests_files() {
drupal_add_http_header('Content-Type', 'text/plain; charset=utf-8');
print theme('feeds_tests_files', array('files' => $images));
}
+
+/**
+ * Implements hook_feeds_processor_targets_alter()
+ */
+function feeds_tests_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_name) {
+ $targets['test_target'] = array(
+ 'name' => t('Test Target'),
+ 'description' => t('This is a test target.'),
+ 'callback' => 'feeds_tests_mapper_set_target',
+ 'summary_callback' => 'feeds_tests_mapper_summary',
+ 'form_callback' => 'feeds_tests_mapper_form',
+ );
+}
+
+/**
+ * Set target value on entity.
+ *
+ * @see my_module_set_target()
+ */
+function feeds_tests_mapper_set_target($source, $entity, $target, $value, $mapping) {
+ $entity->body['und'][0]['value'] = serialize($mapping);
+}
+
+/**
+ * Provides setting summary for the mapper.
+ *
+ * @see my_module_summary_callback()
+ */
+function feeds_tests_mapper_summary($mapping, $target, $form, $form_state) {
+ $options = array(
+ 'option1' => t('Option 1'),
+ 'option2' => t('Another Option'),
+ 'option3' => t('Option for select'),
+ 'option4' => t('Another One')
+ );
+
+ $items = array();
+ if (!empty($mapping['checkbox']) && $mapping['checkbox']) {
+ $items[] = t('Checkbox active.');
+ }
+ else {
+ $items[] = t('Checkbox inactive.');
+ }
+ if (!empty($mapping['textfield'])) {
+ $items[] = t('<strong>Textfield value</strong>: %textfield', array('%textfield' => $mapping['textfield']));
+ }
+ if (!empty($mapping['textarea'])) {
+ $items[] = t('<strong>Textarea value</strong>: %textarea', array('%textarea' => $mapping['textarea']));
+ }
+ if (!empty($mapping['radios'])) {
+ $items[] = t('<strong>Radios value</strong>: %radios', array('%radios' => $options[$mapping['radios']]));
+ }
+ if (!empty($mapping['select'])) {
+ $items[] = t('<strong>Select value</strong>: %select', array('%select' => $options[$mapping['select']]));
+ }
+ $list = array(
+ '#type' => 'ul',
+ '#theme' => 'item_list',
+ '#items' => $items,
+ );
+ return drupal_render($list);
+}
+
+/*
+ * Provides the form with mapper settings.
+ */
+function feeds_tests_mapper_form($mapping, $target, $form, $form_state) {
+ $mapping += array(
+ 'checkbox' => FALSE,
+ 'textfield' => '',
+ 'textarea' => '',
+ 'radios' => NULL,
+ 'select' => NULL,
+ );
+ return array(
+ 'checkbox' => array(
+ '#type' => 'checkbox',
+ '#title' => t('A checkbox'),
+ '#default_value' => !empty($mapping['checkbox']),
+ ),
+ 'textfield' => array(
+ '#type' => 'textfield',
+ '#title' => t('A text field'),
+ '#default_value' => $mapping['textfield'],
+ '#required' => TRUE,
+ ),
+ 'textarea' => array(
+ '#type' => 'textarea',
+ '#title' => t('A textarea'),
+ '#default_value' => $mapping['textarea'],
+ ),
+ 'radios' => array(
+ '#type' => 'radios',
+ '#title' => t('Some radios'),
+ '#options' => array('option1' => t('Option 1'), 'option2' => t('Another Option')),
+ '#default_value' => $mapping['radios'],
+ ),
+ 'select' => array(
+ '#type' => 'select',
+ '#title' => t('A select list'),
+ '#options' => array('option3' => t('Option for select'), 'option4' => t('Another One')),
+ '#default_value' => $mapping['select'],
+ ),
+ );
+}
+
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/views/feeds.views.inc b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/views/feeds.views.inc
index e1d715f..01ba7d4 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/feeds/views/feeds.views.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/feeds/views/feeds.views.inc
@@ -198,7 +198,7 @@ function feeds_views_data() {
'title' => 'Importer id',
'help' => 'The id of an importer.',
'field' => array(
- 'handler' => 'feeds_views_handler_field',
+ 'handler' => 'views_handler_field',
'click sortable' => TRUE,
),
'filter' => array(
@@ -234,7 +234,7 @@ function feeds_views_data() {
'title' => 'Feed node id',
'help' => 'Contains the node id of a feed node if the feed\'s configuration is attached to a content type, otherwise contains 0.',
'field' => array(
- 'handler' => 'feeds_views_handler_field_numeric',
+ 'handler' => 'views_handler_field_numeric',
'click sortable' => TRUE,
),
'filter' => array(
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/redirect/redirect.admin.inc b/kolab.org/www/drupal-7.15/sites/all/modules/redirect/redirect.admin.inc
index 820e626..3d70ebf 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/redirect/redirect.admin.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/redirect/redirect.admin.inc
@@ -42,6 +42,9 @@ function redirect_list_form($form, &$form_state) {
'#title' => t('Update options'),
'#prefix' => '<div class="container-inline">',
'#suffix' => '</div>',
+ '#attributes' => array(
+ 'class' => array('redirect-list-operations'),
+ ),
);
$operations = array();
foreach ($form['#operations'] as $key => $operation) {
@@ -131,6 +134,14 @@ function redirect_list_form($form, &$form_state) {
'#header' => $header,
'#options' => $rows,
'#empty' => t('No URL redirects available.'),
+ '#attributes' => array(
+ 'class' => array('redirect-list-tableselect'),
+ ),
+ '#attached' => array(
+ 'js' => array(
+ drupal_get_path('module', 'redirect') . '/redirect.admin.js',
+ ),
+ ),
);
if (redirect_access('create', 'redirect')) {
$form['rids']['#empty'] .= ' ' . l(t('Add URL redirect.'), 'admin/config/search/redirect/add', array('query' => $destination));
@@ -329,7 +340,7 @@ function redirect_edit_form($form, &$form_state, $redirect = NULL) {
$form['source'] = array(
'#type' => 'textfield',
'#title' => t('From'),
- '#description' => t("Enter an interal Drupal path or path alias to redirect (e.g. %example1 or %example2). Fragment anchors (e.g. %anchor) are <strong>not</strong> allowed.", array('%example1' => 'node/123', '%example2' => 'taxonomy/term/123', '%anchor' => '#anchor')),
+ '#description' => t("Enter an internal Drupal path or path alias to redirect (e.g. %example1 or %example2). Fragment anchors (e.g. %anchor) are <strong>not</strong> allowed.", array('%example1' => 'node/123', '%example2' => 'taxonomy/term/123', '%anchor' => '#anchor')),
'#maxlength' => 560,
'#default_value' => $redirect->rid || $redirect->source ? redirect_url($redirect->source, $redirect->source_options + array('alter' => FALSE)) : '',
'#required' => TRUE,
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/redirect/redirect.admin.js b/kolab.org/www/drupal-7.15/sites/all/modules/redirect/redirect.admin.js
new file mode 100644
index 0000000..d169d4b
--- /dev/null
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/redirect/redirect.admin.js
@@ -0,0 +1,28 @@
+
+(function ($) {
+
+Drupal.behaviors.redirectAdmin = {
+ attach: function (context) {
+ $('table.redirect-list-tableselect tbody input:checkbox').bind('change', function(context) {
+ var checked = $('table.redirect-list-tableselect input:checkbox:checked').length;
+ if (checked) {
+ $('fieldset.redirect-list-operations').slideDown();
+ }
+ else {
+ $('fieldset.redirect-list-operations').slideUp();
+ }
+ });
+ $('table.redirect-list-tableselect th.select-all input:checkbox').bind('change', function(context) {
+ var checked = $(this, context).attr('checked');
+ if (checked) {
+ $('fieldset.redirect-list-operations').slideDown();
+ }
+ else {
+ $('fieldset.redirect-list-operations').slideUp();
+ }
+ });
+ $('fieldset.redirect-list-operations').hide();
+ }
+};
+
+})(jQuery);
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/redirect/redirect.info b/kolab.org/www/drupal-7.15/sites/all/modules/redirect/redirect.info
index b249ce1..b87b4e8 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/redirect/redirect.info
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/redirect/redirect.info
@@ -15,9 +15,9 @@ files[] = views/redirect_handler_field_redirect_link_edit.inc
files[] = views/redirect_handler_field_redirect_link_delete.inc
configure = admin/config/search/redirect/settings
-; Information added by drupal.org packaging script on 2011-12-08
-version = "7.x-1.0-beta4"
+; Information added by drupal.org packaging script on 2012-09-18
+version = "7.x-1.0-rc1"
core = "7.x"
project = "redirect"
-datestamp = "1323364843"
+datestamp = "1347989995"
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/redirect/redirect.install b/kolab.org/www/drupal-7.15/sites/all/modules/redirect/redirect.install
index 0a67212..fa67aaa 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/redirect/redirect.install
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/redirect/redirect.install
@@ -103,6 +103,17 @@ function redirect_schema() {
}
/**
+ * Implements hook_install().
+ */
+function redirect_install() {
+ // If the path redirect table exists, then set the schema to run the
+ // migration update function.
+ if (db_table_exists('path_redirect')) {
+ drupal_set_installed_schema_version('redirect', 6999);
+ }
+}
+
+/**
* Implements hook_uninstall().
*/
function redirect_uninstall() {
@@ -190,3 +201,158 @@ function redirect_update_6() {
db_add_index('redirect', 'source_language', array('source', 'language'));
}
}
+
+/**
+ * Migrate data and variables from the Drupal 6 path_redirect module.
+ */
+function redirect_update_7000(&$sandbox) {
+ if (!isset($sandbox['progress']) && db_table_exists('path_redirect')) {
+ $sandbox['progress'] = 0;
+ $sandbox['current_rid'] = 0;
+ $sandbox['max'] = db_query('SELECT COUNT(rid) FROM {path_redirect}')->fetchField();
+ $sandbox['skipped'] = array();
+ }
+
+ if (empty($sandbox['max'])) {
+ $sandbox['#finished'] = 1;
+ return t('No redirects to migrate.');
+ }
+
+ // Ensure the redirect module is loaded since we need to use its functions.
+ drupal_load('module', 'redirect');
+
+ $query = db_query_range("SELECT * FROM {path_redirect} WHERE rid > :rid ORDER BY rid", 0, 25, array(':rid' => $sandbox['current_rid']));
+ foreach ($query as $old_redirect) {
+ $redirect = _redirect_migrate_path_redirect_redirect($old_redirect);
+
+ if (empty($redirect->success)) {
+ $sandbox['skipped'][$old_redirect->rid] = t('RID @rid: @from to @to', array(
+ '@rid' => $old_redirect->rid,
+ '@from' => redirect_url($redirect->source, $redirect->source_options),
+ '@to' => redirect_url($redirect->redirect, $redirect->redirect_options),
+ ));
+ }
+ $sandbox['progress']++;
+ $sandbox['current_rid'] = $old_redirect->rid;
+ }
+
+ $sandbox['#finished'] = $sandbox['progress'] / $sandbox['max'];
+
+ if ($sandbox['#finished'] >= 1) {
+ // Once finished, drop the old table.
+ db_drop_table('path_redirect');
+
+ // Migrate variables.
+ _redirect_migrate_path_redirect_variables();
+
+ // Remove the path_redirect entry from the system table.
+ db_delete('system')
+ ->condition('name', 'path_redirect')
+ ->execute();
+
+ // Show a message about how many redirects were migrated, and how many
+ // were skipped.
+ $skipped = count($sandbox['skipped']);
+ $migrated = $sandbox['progress'] - $skipped;
+ // @todo The following strings should be using t().
+ $return = "Migrated $migrated redirects.";
+ if (!empty($sandbox['skipped'])) {
+ $return .= " The following $skipped redirects were not migrated since there were already existing redirects for the path and language combination:" . theme('item_list', array('items' => $sandbox['skipped']));
+ }
+ return $return;
+ }
+}
+
+/**
+ * Migrate a path redirect redirect to a redirect redirect.
+ */
+function _redirect_migrate_path_redirect_redirect($old_redirect) {
+ $redirect = new stdClass();
+ redirect_object_prepare($redirect);
+
+ $source_parsed = redirect_parse_url($old_redirect->source);
+ $redirect->source = $source_parsed['url'];
+ if (!empty($source_parsed['query'])) {
+ $redirect->source_options['query'] = $source_parsed['query'];
+ }
+
+ $redirect_parsed = redirect_parse_url($old_redirect->redirect) + array('query' => drupal_get_query_array($old_redirect->query), 'fragment' => $old_redirect->fragment);
+ $redirect->redirect = $redirect_parsed['url'];
+ if (!empty($redirect_parsed['query'])) {
+ $redirect->redirect_options['query'] = $redirect_parsed['query'];
+ }
+ if (!empty($redirect_parsed['fragment'])) {
+ $redirect->redirect_options['fragment'] = $redirect_parsed['fragment'];
+ }
+ if (!empty($redirect_parsed['https'])) {
+ $redirect->redirect_options['https'] = TRUE;
+ }
+
+ // Make sure empty language codes get migrated to use the new constant.
+ $redirect->language = empty($old_redirect->language) ? LANGUAGE_NONE : $old_redirect->language;
+
+ // Default status codes get a value of 0.
+ if ($old_redirect->type != variable_get('redirect_default_status_code', 301)) {
+ $redirect->status_code = (int) $old_redirect->type;
+ }
+
+ redirect_hash($redirect);
+ if (redirect_load_by_hash($redirect->hash)) {
+ // If a redirect with the same hash already exists, then it needs to be
+ // skipped.
+ $redirect->success = FALSE;
+ }
+ else {
+ // Add the redirect to the database.
+ db_insert('redirect')
+ ->fields(array(
+ 'hash' => $redirect->hash,
+ 'type' => 'redirect',
+ 'uid' => 1,
+ 'source' => $redirect->source,
+ 'source_options' => serialize($redirect->source_options),
+ 'redirect' => $redirect->redirect,
+ 'redirect_options' => serialize($redirect->redirect_options),
+ 'language' => $redirect->language,
+ 'status_code' => $redirect->status_code,
+ 'count' => 0,
+ 'access' => $old_redirect->last_used,
+ ))
+ ->execute();
+
+ // Migrating this redirect succeeded.
+ $redirect->success = TRUE;
+ }
+
+ return $redirect;
+}
+
+/**
+ * Migrate path redirect variables to redirect variables.
+ */
+function _redirect_migrate_path_redirect_variables() {
+ // Port path_redirect variables.
+ $variables = array(
+ 'path_redirect_default_status' => 'redirect_default_status_code',
+ 'path_redirect_purge_inactive' => 'redirect_purge_inactive',
+ 'path_redirect_retain_query_string' => 'redirect_passthrough_querystring',
+ 'path_redirect_auto_redirect' => 'redirect_auto_redirect',
+ 'path_redirect_redirect_warning' => 'redirect_warning',
+ 'path_redirect_allow_bypass' => NULL,
+ );
+ foreach ($variables as $old_variable => $new_variable) {
+ if (!empty($new_variable)) {
+ $old_value = variable_get($old_variable);
+ $new_value = variable_get($new_variable);
+
+ // Only if the old variable exists, and the new variable hasn't been set
+ // yet, do we set the new variable with the old value.
+ if (isset($old_value) && !isset($new_value)) {
+ variable_set($new_variable, $old_value);
+ }
+ }
+
+ // Delete the old path redirect variable.
+ variable_del($old_variable);
+ }
+}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/redirect/redirect.module b/kolab.org/www/drupal-7.15/sites/all/modules/redirect/redirect.module
index b14709b..9f7a256 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/redirect/redirect.module
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/redirect/redirect.module
@@ -40,6 +40,7 @@ function redirect_entity_info() {
),
'fieldable' => FALSE,
'uuid' => FALSE,
+ 'redirect' => FALSE,
);
return $info;
@@ -80,11 +81,7 @@ function redirect_hook_info() {
'redirect_alter',
);
- $hooks = array_combine($hooks, $hooks);
- foreach ($hooks as $hook => $info) {
- $hooks[$hook] = array('group' => 'redirect');
- }
- return $hooks;
+ return array_fill_keys($hooks, array('group' => 'redirect'));
}
/**
@@ -202,10 +199,51 @@ function redirect_menu() {
return $items;
}
+function redirect_set_current_redirect($redirect) {
+ $static = &drupal_static(__FUNCTION__);
+ $static = $redirect;
+}
+
+function redirect_get_current_redirect() {
+ $redirect = drupal_static('redirect_set_current_redirect', NULL);
+
+ // If a redirect has not been set with redirect_set_current_redirect(), then
+ // attempt to find a redirect matching the current path, query string, and
+ // language code.
+ if (!isset($redirect)) {
+ $redirect = redirect_load_by_source(current_path(), $GLOBALS['language']->language, drupal_get_query_parameters());
+ }
+
+ // @todo Add an alter hook here?
+ return $redirect;
+}
+
/**
* Implements hook_url_inbound_alter().
*/
function redirect_url_inbound_alter(&$path, $original_path, $path_language) {
+ // If the current path global does not exist, then drupal_get_path_alias()
+ // will fail. This condition only happens when $path is the front page.
+ // @todo Remove when http://drupal.org/node/1329914 is fixed in core.
+ if (empty($_GET['q'])) {
+ $_GET['q'] = variable_get('site_frontpage', 'node');
+ return;
+ }
+
+ // If the inbound path has been changed, then attempt to find a redirect
+ // matching the original path and save it for processing later in
+ // redirect_init(). For example, if the Sub-pathauto module changes the path
+ // 'foo/redirect' to 'node/1/redirect', and there is a redirect enabled for
+ // the path 'foo/redirect', then redirect_init() would normally fail since it
+ // would not find a match.
+ if ($path != $original_path && $original_path == current_path()) {
+ $current_langcode = !empty($path_language) ? $path_language : $GLOBALS['language']->language;
+ $current_query = drupal_get_query_parameters();
+ if ($redirect = redirect_load_by_source($original_path, $current_langcode, $current_query)) {
+ redirect_set_current_redirect($redirect);
+ }
+ }
+
// Redirect to canonical URLs.
if ($path && variable_get('redirect_canonical', 1)) {
$alias = drupal_get_path_alias($path, $path_language);
@@ -214,13 +252,13 @@ function redirect_url_inbound_alter(&$path, $original_path, $path_language) {
}
// Redirect from default entity paths to the proper entity path.
- if ($path_entity = redirect_load_entity_from_path($path)) {
- if ($uri = entity_uri($path_entity['entity_type'], $path_entity['entity'])) {
- if ($path != $uri['path']) {
- //return redirect_redirect(array('redirect' => $uri['path'], 'redirect_options' => $uri['options'], 'type' => 'global'));
- }
- }
- }
+ //if ($path_entity = redirect_load_entity_from_path($path)) {
+ // if ($uri = entity_uri($path_entity['entity_type'], $path_entity['entity'])) {
+ // if ($path != $uri['path']) {
+ // return redirect_redirect(array('redirect' => $uri['path'], 'redirect_options' => $uri['options'], 'type' => 'global'));
+ // }
+ // }
+ //}
}
}
@@ -239,6 +277,40 @@ function redirect_entity_info_alter(&$info) {
$info[$entity_type]['default path'] = $default_path;
}
}
+
+ // Disable support for some entity types that cause problems.
+ $unsupported_entity_types = array(
+ 'comment',
+ 'media',
+ );
+ foreach ($unsupported_entity_types as $unsupported_entity_type) {
+ if (isset($info[$unsupported_entity_type])) {
+ $info[$unsupported_entity_type]['redirect'] = FALSE;
+ }
+ }
+}
+
+/**
+ * Check if an entity type supports redirects.
+ *
+ * @param $entity_type
+ * An entity type.
+ *
+ * @return
+ * TRUE if the entity type has an uri callback and supports redirects, or
+ * FALSE otherwise.
+ */
+function redirect_entity_type_supports_redirects($entity_type) {
+ $types = &drupal_static(__FUNCTION__);
+
+ if (!isset($types)) {
+ $types = array();
+ foreach (entity_get_info() as $type => $entity_info) {
+ $types[$type] = !empty($entity_info['uri callback']) && (!isset($entity_info['redirect']) || !empty($entity_info['redirect']));
+ }
+ }
+
+ return isset($types[$entity_type]) ? $types[$entity_type] : FALSE;
}
/**
@@ -249,10 +321,8 @@ function redirect_init() {
return;
}
- $current_path = current_path();
- $current_langcode = $GLOBALS['language']->language;
- $current_query = drupal_get_query_parameters();
- if ($redirect = redirect_load_by_source($current_path, $current_langcode, $current_query)) {
+ // Fetch the current redirect.
+ if ($redirect = redirect_get_current_redirect()) {
redirect_redirect($redirect);
}
@@ -307,10 +377,9 @@ function redirect_exit($destination = NULL) {
* Implements hook_entity_delete().
*/
function redirect_entity_delete($entity, $entity_type) {
- if ($entity_type == 'redirect') {
- return;
+ if (redirect_entity_type_supports_redirects($entity_type)) {
+ redirect_delete_by_entity_path($entity_type, $entity);
}
- redirect_delete_by_entity_path($entity_type, $entity);
}
/**
@@ -390,10 +459,15 @@ function redirect_page_build(&$page) {
'#weight' => -100,
);
}
+ // We cannot simply use current_path() because if a 404 path is set, then
+ // that value overrides whatever is in $_GET['q']. The
+ // drupal_deliver_html_page() function thankfully puts the original current
+ // path into $_GET['destination'].
+ $destination = drupal_get_destination();
$page['content']['system_main']['actions']['#links']['add_redirect'] = array(
'title' => t('Add URL redirect from this page to another location'),
'href' => 'admin/config/search/redirect/add',
- 'query' => array('source' => current_path()) + drupal_get_destination(),
+ 'query' => array('source' => $destination['destination']) + drupal_get_destination(),
);
}
}
@@ -977,7 +1051,12 @@ function redirect_goto($redirect) {
if (variable_get('cache', 0)) {
// We must output something to allow the request to be cached.
echo ' ';
- drupal_page_set_cache();
+ if ($cache = drupal_page_set_cache()) {
+ // When caching this redirect for the first time we still need to ensure
+ // that the correct cache headers are sent.
+ // @see drupal_page_footer()
+ drupal_serve_page_from_cache($cache);
+ }
}
}
@@ -1368,12 +1447,12 @@ function locale_form_redirect_edit_form_alter(&$form, &$form_state) {
*/
function redirect_field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode) {
list($id) = entity_extract_ids($entity_type, $entity);
- if (!empty($form['redirect']) || empty($id) || $entity_type == 'comment') {
+ if (!empty($form['redirect']) || empty($id)) {
return;
}
- // @todo Remove when http://drupal.org/node/1057242 is fixed.
- if ($entity_type == 'file') {
+ // Check if this entity type supports redirects.
+ if (!redirect_entity_type_supports_redirects($entity_type)) {
return;
}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/redirect/views/redirects.view b/kolab.org/www/drupal-7.15/sites/all/modules/redirect/views/redirects.view
index 008e28d..fd9e777 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/redirect/views/redirects.view
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/redirect/views/redirects.view
@@ -1,15 +1,18 @@
<?php
-$view = new view;
+$view = new view();
$view->name = 'redirects';
-$view->description = 'Redirects';
+$view->description = 'Displays a list of redirects on user and admin pages.';
$view->tag = '';
$view->base_table = 'redirect';
-$view->api_version = '3.0-alpha1';
+$view->human_name = 'Redirects';
+$view->core = 0;
+$view->api_version = '3.0';
$view->disabled = TRUE; /* Edit this to true to make a default view disabled initially */
/* Display: Defaults */
$handler = $view->new_display('default', 'Defaults', 'default');
+$handler->display->display_options['use_more_always'] = FALSE;
$handler->display->display_options['access']['type'] = 'perm';
$handler->display->display_options['access']['perm'] = 'administer redirects';
$handler->display->display_options['cache']['type'] = 'none';
@@ -65,13 +68,11 @@ $handler->display->display_options['style_options']['info'] = array(
'separator' => '',
),
);
-$handler->display->display_options['style_options']['override'] = 1;
-$handler->display->display_options['style_options']['sticky'] = 1;
-/* Empty text: Global: Text area */
+$handler->display->display_options['style_options']['sticky'] = TRUE;
+/* No results behavior: Global: Text area */
$handler->display->display_options['empty']['area']['id'] = 'area';
$handler->display->display_options['empty']['area']['table'] = 'views';
$handler->display->display_options['empty']['area']['field'] = 'area';
-$handler->display->display_options['empty']['area']['empty'] = FALSE;
$handler->display->display_options['empty']['area']['content'] = 'No URL redirects found.';
$handler->display->display_options['empty']['area']['format'] = '1';
/* Field: Redirect: Redirect ID */
@@ -79,110 +80,40 @@ $handler->display->display_options['fields']['rid']['id'] = 'rid';
$handler->display->display_options['fields']['rid']['table'] = 'redirect';
$handler->display->display_options['fields']['rid']['field'] = 'rid';
$handler->display->display_options['fields']['rid']['exclude'] = TRUE;
-$handler->display->display_options['fields']['rid']['alter']['alter_text'] = 0;
-$handler->display->display_options['fields']['rid']['alter']['make_link'] = 0;
-$handler->display->display_options['fields']['rid']['alter']['absolute'] = 0;
-$handler->display->display_options['fields']['rid']['alter']['trim'] = 0;
-$handler->display->display_options['fields']['rid']['alter']['word_boundary'] = 1;
-$handler->display->display_options['fields']['rid']['alter']['ellipsis'] = 1;
-$handler->display->display_options['fields']['rid']['alter']['strip_tags'] = 0;
-$handler->display->display_options['fields']['rid']['alter']['html'] = 0;
-$handler->display->display_options['fields']['rid']['hide_empty'] = 0;
-$handler->display->display_options['fields']['rid']['empty_zero'] = 0;
/* Field: Redirect: Source URL */
$handler->display->display_options['fields']['source']['id'] = 'source';
$handler->display->display_options['fields']['source']['table'] = 'redirect';
$handler->display->display_options['fields']['source']['field'] = 'source';
-$handler->display->display_options['fields']['source']['alter']['alter_text'] = 0;
-$handler->display->display_options['fields']['source']['alter']['make_link'] = 1;
-$handler->display->display_options['fields']['source']['alter']['absolute'] = 0;
-$handler->display->display_options['fields']['source']['alter']['trim'] = 0;
-$handler->display->display_options['fields']['source']['alter']['word_boundary'] = 1;
-$handler->display->display_options['fields']['source']['alter']['ellipsis'] = 1;
-$handler->display->display_options['fields']['source']['alter']['strip_tags'] = 0;
-$handler->display->display_options['fields']['source']['alter']['html'] = 0;
$handler->display->display_options['fields']['source']['absolute'] = 0;
/* Field: Redirect: Redirect URL */
$handler->display->display_options['fields']['redirect']['id'] = 'redirect';
$handler->display->display_options['fields']['redirect']['table'] = 'redirect';
$handler->display->display_options['fields']['redirect']['field'] = 'redirect';
-$handler->display->display_options['fields']['redirect']['alter']['alter_text'] = 0;
-$handler->display->display_options['fields']['redirect']['alter']['make_link'] = 1;
$handler->display->display_options['fields']['redirect']['alter']['path'] = 'node';
-$handler->display->display_options['fields']['redirect']['alter']['absolute'] = 1;
-$handler->display->display_options['fields']['redirect']['alter']['trim'] = 0;
-$handler->display->display_options['fields']['redirect']['alter']['word_boundary'] = 1;
-$handler->display->display_options['fields']['redirect']['alter']['ellipsis'] = 1;
-$handler->display->display_options['fields']['redirect']['alter']['strip_tags'] = 0;
-$handler->display->display_options['fields']['redirect']['alter']['html'] = 0;
+$handler->display->display_options['fields']['redirect']['alter']['absolute'] = TRUE;
$handler->display->display_options['fields']['redirect']['absolute'] = 0;
/* Field: Redirect: Language */
$handler->display->display_options['fields']['language']['id'] = 'language';
$handler->display->display_options['fields']['language']['table'] = 'redirect';
$handler->display->display_options['fields']['language']['field'] = 'language';
-$handler->display->display_options['fields']['language']['alter']['alter_text'] = 0;
-$handler->display->display_options['fields']['language']['alter']['make_link'] = 0;
-$handler->display->display_options['fields']['language']['alter']['absolute'] = 0;
-$handler->display->display_options['fields']['language']['alter']['trim'] = 0;
-$handler->display->display_options['fields']['language']['alter']['word_boundary'] = 1;
-$handler->display->display_options['fields']['language']['alter']['ellipsis'] = 1;
-$handler->display->display_options['fields']['language']['alter']['strip_tags'] = 0;
-$handler->display->display_options['fields']['language']['alter']['html'] = 0;
-$handler->display->display_options['fields']['language']['element_label_colon'] = 1;
-$handler->display->display_options['fields']['language']['element_default_classes'] = 1;
$handler->display->display_options['fields']['language']['empty'] = 'All';
-$handler->display->display_options['fields']['language']['hide_empty'] = 0;
-$handler->display->display_options['fields']['language']['empty_zero'] = 0;
/* Field: Redirect: Clicks */
$handler->display->display_options['fields']['count']['id'] = 'count';
$handler->display->display_options['fields']['count']['table'] = 'redirect';
$handler->display->display_options['fields']['count']['field'] = 'count';
-$handler->display->display_options['fields']['count']['alter']['alter_text'] = 0;
-$handler->display->display_options['fields']['count']['alter']['make_link'] = 0;
-$handler->display->display_options['fields']['count']['alter']['absolute'] = 0;
-$handler->display->display_options['fields']['count']['alter']['trim'] = 0;
-$handler->display->display_options['fields']['count']['alter']['word_boundary'] = 1;
-$handler->display->display_options['fields']['count']['alter']['ellipsis'] = 1;
-$handler->display->display_options['fields']['count']['alter']['strip_tags'] = 0;
-$handler->display->display_options['fields']['count']['alter']['html'] = 0;
-$handler->display->display_options['fields']['count']['hide_empty'] = 0;
-$handler->display->display_options['fields']['count']['empty_zero'] = 0;
/* Field: Redirect: Last accessed date */
$handler->display->display_options['fields']['access']['id'] = 'access';
$handler->display->display_options['fields']['access']['table'] = 'redirect';
$handler->display->display_options['fields']['access']['field'] = 'access';
$handler->display->display_options['fields']['access']['label'] = 'Last accessed';
-$handler->display->display_options['fields']['access']['alter']['alter_text'] = 0;
-$handler->display->display_options['fields']['access']['alter']['make_link'] = 0;
-$handler->display->display_options['fields']['access']['alter']['absolute'] = 0;
-$handler->display->display_options['fields']['access']['alter']['trim'] = 0;
-$handler->display->display_options['fields']['access']['alter']['word_boundary'] = 1;
-$handler->display->display_options['fields']['access']['alter']['ellipsis'] = 1;
-$handler->display->display_options['fields']['access']['alter']['strip_tags'] = 0;
-$handler->display->display_options['fields']['access']['alter']['html'] = 0;
-$handler->display->display_options['fields']['access']['element_label_colon'] = 1;
-$handler->display->display_options['fields']['access']['element_default_classes'] = 1;
$handler->display->display_options['fields']['access']['empty'] = 'Never';
-$handler->display->display_options['fields']['access']['hide_empty'] = 0;
-$handler->display->display_options['fields']['access']['empty_zero'] = 1;
+$handler->display->display_options['fields']['access']['empty_zero'] = TRUE;
$handler->display->display_options['fields']['access']['date_format'] = 'time ago';
/* Field: Redirect: Operations */
$handler->display->display_options['fields']['operations']['id'] = 'operations';
$handler->display->display_options['fields']['operations']['table'] = 'redirect';
$handler->display->display_options['fields']['operations']['field'] = 'operations';
-$handler->display->display_options['fields']['operations']['alter']['alter_text'] = 0;
-$handler->display->display_options['fields']['operations']['alter']['make_link'] = 0;
-$handler->display->display_options['fields']['operations']['alter']['absolute'] = 0;
-$handler->display->display_options['fields']['operations']['alter']['trim'] = 0;
-$handler->display->display_options['fields']['operations']['alter']['word_boundary'] = 1;
-$handler->display->display_options['fields']['operations']['alter']['ellipsis'] = 1;
-$handler->display->display_options['fields']['operations']['alter']['strip_tags'] = 0;
-$handler->display->display_options['fields']['operations']['alter']['html'] = 0;
-$handler->display->display_options['fields']['operations']['element_label_colon'] = 1;
-$handler->display->display_options['fields']['operations']['element_default_classes'] = 1;
-$handler->display->display_options['fields']['operations']['hide_empty'] = 0;
-$handler->display->display_options['fields']['operations']['empty_zero'] = 0;
-/* Filter: Redirect: Type */
+/* Filter criterion: Redirect: Type */
$handler->display->display_options['filters']['type']['id'] = 'type';
$handler->display->display_options['filters']['type']['table'] = 'redirect';
$handler->display->display_options['filters']['type']['field'] = 'type';
@@ -192,17 +123,16 @@ $handler->display->display_options['filters']['type']['value'] = array(
/* Display: Page: User redirects */
$handler = $view->new_display('page', 'Page: User redirects', 'page_user');
+$handler->display->display_options['defaults']['hide_admin_links'] = FALSE;
$handler->display->display_options['defaults']['arguments'] = FALSE;
-/* Argument: Redirect: User ID */
+/* Contextual filter: Redirect: User ID */
$handler->display->display_options['arguments']['uid']['id'] = 'uid';
$handler->display->display_options['arguments']['uid']['table'] = 'redirect';
$handler->display->display_options['arguments']['uid']['field'] = 'uid';
$handler->display->display_options['arguments']['uid']['default_action'] = 'default';
-$handler->display->display_options['arguments']['uid']['style_plugin'] = 'default_summary';
$handler->display->display_options['arguments']['uid']['default_argument_type'] = 'user';
$handler->display->display_options['arguments']['uid']['default_argument_options']['user'] = FALSE;
-$handler->display->display_options['arguments']['uid']['break_phrase'] = 0;
-$handler->display->display_options['arguments']['uid']['not'] = 0;
+$handler->display->display_options['arguments']['uid']['summary']['format'] = 'default_summary';
$handler->display->display_options['path'] = 'user/%/redirects';
$handler->display->display_options['menu']['type'] = 'tab';
$handler->display->display_options['menu']['title'] = 'Redirects';
@@ -210,6 +140,7 @@ $handler->display->display_options['menu']['weight'] = '0';
/* Display: Page: Admin redirects */
$handler = $view->new_display('page', 'Page: Admin redirects', 'page_admin');
+$handler->display->display_options['defaults']['hide_admin_links'] = FALSE;
$handler->display->display_options['path'] = 'admin/config/search/redirect/list';
$handler->display->display_options['menu']['type'] = 'default tab';
$handler->display->display_options['menu']['title'] = 'List';
@@ -221,17 +152,20 @@ $translatables['redirects'] = array(
t('more'),
t('Apply'),
t('Reset'),
- t('Sort By'),
+ t('Sort by'),
t('Asc'),
t('Desc'),
t('Items per page'),
t('- All -'),
t('Offset'),
+ t('« first'),
+ t('â¹ previous'),
+ t('next âº'),
+ t('last »'),
t('No URL redirects found.'),
t('Redirect ID'),
t('Source URL'),
t('Redirect URL'),
- t('node'),
t('Language'),
t('All'),
t('Clicks'),
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/CHANGELOG.txt b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/CHANGELOG.txt
index 2b79f35..2072654 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/CHANGELOG.txt
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/CHANGELOG.txt
@@ -1,6 +1,25 @@
Wysiwyg 7.x-2.x, xxxx-xx-xx
---------------------------
+#1388224 by ksenzee, sun, TwoD: Fixed editors detaching on form submissions.
+#682160 by n_vashenko, TwoD: Fixed lists plugin support for TinyMCE.
+#1414354 by Merco: Fixed none.js breaks if textarea.js is not loaded.
+#1064600 by TwoD: Fixed maximized editors hidden under Drupal's toolbar.
+#1405786 by logaritmisk: Fixed CKEditor being wider than parent elements.
+#1531896 by Chi: Fixed strict warning for WYMeditor.
+#1442226 by robertom: Fixed inverted list button names for WYMeditor.
+#1352426 by TwoD, sun: Added install notes (CKEditor edition clarification).
+#1112212 by timdiacon, TwoD: Added language direction buttons for CKEditor.
+#1398560 by markwittens: Fixed TinyMCE removing the longdesc attribute.
+#970452 by smk-ka, sun, TwoD, drzraf: Fixed outdated TinyMCE plugin info.
+#1155678 by james.elliott, Jody Lynn, sun: Add Drupal.detachBehaviors support.
+#624018 by smk-ka, quartsize, dagmar, nedjo, rickvug, catch, sun: Added Features support.
+#1238766 by Dave Reid: Fixed Missing cells in profile plugins table.
+#1073106 by scottrouse: Fixed 'Input Format' should be 'Text Format'.
+#1153458 by TwoD: Fixed TinyMCE 'Verify HTML' setting ignored.
+#1125582 by TwoD: Fixed TinyMCE fullscreen plugin deletes content.
+#1078834 by sun: Fixed coding standards errors.
+#1173476 by jim0203, sun: Fixed installation instructions in README.txt.
Wysiwyg 7.x-2.1, 2011-06-19
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/LICENSE.txt b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/LICENSE.txt
index 2c095c8..d159169 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/LICENSE.txt
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/LICENSE.txt
@@ -1,274 +1,339 @@
-GNU GENERAL PUBLIC LICENSE
-
- Version 2, June 1991
-
-Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave,
-Cambridge, MA 02139, USA. Everyone is permitted to copy and distribute
-verbatim copies of this license document, but changing it is not allowed.
-
- Preamble
-
-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 Library General Public License
-instead.) You can apply it to your programs, too.
-
-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.
-
-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.
-
-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.
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ 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.
+
+ Preamble
+
+ 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.
+
+ 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.
+
+ 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.
+
+ 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.)
+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
+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
+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.
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/README.txt b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/README.txt
index cc81447..75d2b14 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/README.txt
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/README.txt
@@ -18,7 +18,8 @@ To submit bug reports and feature suggestions, or to track changes:
-- INSTALLATION --
-* Install as usual, see http://drupal.org/node/70151 for further information.
+* Install as usual, see
+ http://drupal.org/documentation/install/modules-themes/modules-7
* Go to Administration » Configuration » Content authoring » Wysiwyg,
and follow the displayed installation instructions to download and install one
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/ckeditor.inc b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/ckeditor.inc
index 0a56fe0..fcf168e 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/ckeditor.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/ckeditor.inc
@@ -27,8 +27,11 @@ function wysiwyg_ckeditor_editor() {
),
),
),
+ 'install note callback' => 'wysiwyg_ckeditor_install_note',
'version callback' => 'wysiwyg_ckeditor_version',
'themes callback' => 'wysiwyg_ckeditor_themes',
+ 'settings form callback' => 'wysiwyg_ckeditor_settings_form',
+ 'init callback' => 'wysiwyg_ckeditor_init',
'settings callback' => 'wysiwyg_ckeditor_settings',
'plugin callback' => 'wysiwyg_ckeditor_plugins',
'plugin settings callback' => 'wysiwyg_ckeditor_plugin_settings',
@@ -49,6 +52,13 @@ function wysiwyg_ckeditor_editor() {
}
/**
+ * Return an install note.
+ */
+function wysiwyg_ckeditor_install_note() {
+ return '<p class="warning">' . t('Do NOT download the "CKEditor for Drupal" edition.') . '</p>';
+}
+
+/**
* Detect editor version.
*
* @param $editor
@@ -112,6 +122,69 @@ function wysiwyg_ckeditor_themes($editor, $profile) {
}
/**
+ * Enhances the editor profile settings form for CKEditor.
+ *
+ * Adds support for CKEditor's advanced stylesSets, which are a more advanced
+ * implementation and combination of block formats and font styles that allow
+ * to adjust the HTML element, attributes, and CSS styles at once.
+ *
+ * @see http://docs.cksource.com/CKEditor_3.x/Developers_Guide/Styles
+ * @see http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.config.html#.stylesSet
+ */
+function wysiwyg_ckeditor_settings_form(&$form, &$form_state) {
+ if (version_compare($form_state['wysiwyg']['editor']['installed version'], '3.2.1', '>=')) {
+ // Replace CSS classes element description to explain the advanced syntax.
+ $form['css']['css_classes']['#description'] = t('Optionally define CSS classes for the "Font style" dropdown list.<br />Enter one class on each line in the format: !format. Example: !example<br />If left blank, CSS classes are automatically imported from loaded stylesheet(s).', array(
+ '!format' => '<code>[label]=[element].[class]</code>',
+ '!example' => '<code>Title=h1.title</code>',
+ ));
+ $form['css']['css_classes']['#element_validate'][] = 'wysiwyg_ckeditor_settings_form_validate_css_classes';
+ }
+ else {
+ // Versions below 3.2.1 do not support Font styles at all.
+ $form['css']['css_classes']['#access'] = FALSE;
+ }
+}
+
+/**
+ * #element_validate handler for CSS classes element altered by wysiwyg_ckeditor_settings_form().
+ */
+function wysiwyg_ckeditor_settings_form_validate_css_classes($element, &$form_state) {
+ if (wysiwyg_ckeditor_settings_parse_styles($element['#value']) === FALSE) {
+ form_error($element, t('The specified CSS classes are syntactically incorrect.'));
+ }
+}
+
+/**
+ * Returns an initialization JavaScript for this editor library.
+ *
+ * @param array $editor
+ * The editor library definition.
+ * @param string $library
+ * The library variant key from $editor['libraries'].
+ * @param object $profile
+ * The (first) wysiwyg editor profile.
+ *
+ * @return string
+ * A string containing inline JavaScript to execute before the editor library
+ * script is loaded.
+ */
+function wysiwyg_ckeditor_init($editor) {
+ // CKEditor unconditionally searches for its library filename in SCRIPT tags
+ // on the page upon loading the library in order to determine the base path to
+ // itself. When JavaScript aggregation is enabled, this search fails and all
+ // relative constructed paths within CKEditor are broken. The library has a
+ // CKEditor.basePath property, but it is not publicly documented and thus not
+ // reliable. The official documentation suggests to solve the issue through
+ // the global window variable.
+ // @see http://docs.cksource.com/CKEditor_3.x/Developers_Guide/Specifying_the_Editor_Path
+ $library_path = base_path() . $editor['library path'] . '/';
+ return <<<EOL
+window.CKEDITOR_BASEPATH = '$library_path';
+EOL;
+}
+
+/**
* Return runtime editor settings for a given wysiwyg profile.
*
* @param $editor
@@ -127,8 +200,7 @@ function wysiwyg_ckeditor_themes($editor, $profile) {
*/
function wysiwyg_ckeditor_settings($editor, $config, $theme) {
$settings = array(
- 'baseHref' => $GLOBALS['base_url'] . '/',
- 'width' => '100%',
+ 'width' => 'auto',
// For better compatibility with smaller textareas.
'resize_minWidth' => 450,
'height' => 420,
@@ -167,7 +239,7 @@ function wysiwyg_ckeditor_settings($editor, $config, $theme) {
$settings['contentsCss'] = reset(wysiwyg_get_css());
}
elseif ($config['css_setting'] == 'self' && isset($config['css_path'])) {
- $settings['contentsCss'] = strtr($config['css_path'], array('%b' => base_path(), '%t' => path_to_theme()));
+ $settings['contentsCss'] = strtr($config['css_path'], array('%b' => base_path(), '%t' => drupal_get_path('theme', variable_get('theme_default', NULL))));
}
}
else {
@@ -175,16 +247,25 @@ function wysiwyg_ckeditor_settings($editor, $config, $theme) {
$settings['contentsCss'] = wysiwyg_get_css();
}
elseif ($config['css_setting'] == 'self' && isset($config['css_path'])) {
- $settings['contentsCss'] = explode(',', strtr($config['css_path'], array('%b' => base_path(), '%t' => path_to_theme())));
+ $settings['contentsCss'] = explode(',', strtr($config['css_path'], array('%b' => base_path(), '%t' => drupal_get_path('theme', variable_get('theme_default', NULL)))));
}
}
}
+ // Parse and define the styles set for the Styles plugin (3.2.1+).
+ // @todo This should be a plugin setting, but Wysiwyg does not support
+ // plugin-specific settings yet.
+ if (!empty($config['buttons']['default']['Styles']) && version_compare($editor['installed version'], '3.2.1', '>=')) {
+ if ($styles = wysiwyg_ckeditor_settings_parse_styles($config['css_classes'])) {
+ $settings['stylesSet'] = $styles;
+ }
+ }
+
if (isset($config['language'])) {
$settings['language'] = $config['language'];
}
if (isset($config['resizing'])) {
- // CKEditor tests "!== false", so ensure it is a Boolean.
+ // CKEditor performs a type-agnostic comparison on this particular setting.
$settings['resize_enabled'] = (bool) $config['resizing'];
}
if (isset($config['toolbar_loc'])) {
@@ -241,6 +322,51 @@ function wysiwyg_ckeditor_settings($editor, $config, $theme) {
}
/**
+ * Parses CSS classes settings string into a stylesSet JavaScript settings array.
+ *
+ * @param string $css_classes
+ * A string containing CSS class definitions to add to the Style dropdown
+ * list, separated by newlines.
+ *
+ * @return array|false
+ * An array containing the parsed stylesSet definition, or FALSE on parse
+ * error.
+ *
+ * @see wysiwyg_ckeditor_settings_form()
+ * @see wysiwyg_ckeditor_settings_form_validate_css_classes()
+ *
+ * @todo This should be a plugin setting, but Wysiwyg does not support
+ * plugin-specific settings yet.
+ */
+function wysiwyg_ckeditor_settings_parse_styles($css_classes) {
+ $set = array();
+ $input = trim($css_classes);
+ if (empty($input)) {
+ return $set;
+ }
+ // Handle both Unix and Windows line-endings.
+ foreach (explode("\n", str_replace("\r", '', $input)) as $line) {
+ $line = trim($line);
+ // [label]=[element].[class][.[class]][...] pattern expected.
+ if (!preg_match('@^.+= *[a-zA-Z0-9]+(\.[a-zA-Z0-9_ -]+)*$@', $line)) {
+ return FALSE;
+ }
+ list($label, $selector) = explode('=', $line, 2);
+ $classes = explode('.', $selector);
+ $element = array_shift($classes);
+
+ $style = array();
+ $style['name'] = trim($label);
+ $style['element'] = trim($element);
+ if (!empty($classes)) {
+ $style['attributes']['class'] = implode(' ', array_map('trim', $classes));
+ }
+ $set[] = $style;
+ }
+ return $set;
+}
+
+/**
* Build a JS settings array of native external plugins that need to be loaded separately.
*/
function wysiwyg_ckeditor_plugin_settings($editor, $profile, $plugins) {
@@ -294,6 +420,7 @@ function wysiwyg_ckeditor_plugins($editor) {
'Bold' => t('Bold'), 'Italic' => t('Italic'), 'Underline' => t('Underline'),
'Strike' => t('Strike-through'),
'JustifyLeft' => t('Align left'), 'JustifyCenter' => t('Align center'), 'JustifyRight' => t('Align right'), 'JustifyBlock' => t('Justify'),
+ 'BidiLtr' => t('Left-to-right'), 'BidiRtl' => t('Right-to-left'),
'BulletedList' => t('Bullet list'), 'NumberedList' => t('Numbered list'),
'Outdent' => t('Outdent'), 'Indent' => t('Indent'),
'Undo' => t('Undo'), 'Redo' => t('Redo'),
@@ -325,6 +452,10 @@ function wysiwyg_ckeditor_plugins($editor) {
if (version_compare($editor['installed version'], '3.1.0.4885', '<')) {
unset($plugins['default']['buttons']['CreateDiv']);
}
+ if (version_compare($editor['installed version'], '3.4.0.5808', '<')) {
+ unset($plugins['default']['buttons']['BidiLtr']);
+ unset($plugins['default']['buttons']['BidiRtl']);
+ }
if (version_compare($editor['installed version'], '3.5.0.6260', '<')) {
unset($plugins['default']['buttons']['Iframe']);
}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/epiceditor.inc b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/epiceditor.inc
new file mode 100644
index 0000000..7c89768
--- /dev/null
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/epiceditor.inc
@@ -0,0 +1,102 @@
+<?php
+
+/**
+ * @file
+ * Editor integration functions for EpicEditor.
+ */
+
+/**
+ * Plugin implementation of hook_editor().
+ */
+function wysiwyg_epiceditor_editor() {
+ $editor['epiceditor'] = array(
+ 'title' => 'EpicEditor',
+ 'vendor url' => 'http://oscargodson.github.com/EpicEditor',
+ 'download url' => 'http://oscargodson.github.com/EpicEditor/docs/downloads/EpicEditor-v0.1.1.zip',
+ 'libraries' => array(
+ '' => array(
+ 'title' => 'Minified',
+ 'files' => array('js/epiceditor.min.js'),
+ ),
+ 'src' => array(
+ 'title' => 'Source',
+ 'files' => array('js/epiceditor.js'),
+ ),
+ ),
+ 'version callback' => 'wysiwyg_epiceditor_version',
+ 'themes callback' => 'wysiwyg_epiceditor_themes',
+ 'settings callback' => 'wysiwyg_epiceditor_settings',
+ 'versions' => array(
+ '0.1.1' => array(
+ 'js files' => array('epiceditor.js'),
+ ),
+ ),
+ );
+ return $editor;
+}
+
+/**
+ * Detect editor version.
+ *
+ * @param $editor
+ * An array containing editor properties as returned from hook_editor().
+ *
+ * @return
+ * The installed editor version.
+ */
+function wysiwyg_epiceditor_version($editor) {
+ $library = $editor['library path'] . '/js/epiceditor.js';
+ if (!file_exists($library)) {
+ return;
+ }
+ // @todo Do not load the entire file; use fgets() instead.
+ $library = file_get_contents($library, 'r');
+ $version = preg_match('%EpicEditor\.version = \'(.*)\'\;%', $library, $matches);
+ if (!isset($matches[1])) {
+ return;
+ }
+ return $matches[1];
+}
+
+/**
+ * Determine available editor themes or check/reset a given one.
+ *
+ * @param $editor
+ * A processed hook_editor() array of editor properties.
+ * @param $profile
+ * A wysiwyg editor profile.
+ *
+ * @return
+ * An array of theme names. The first returned name should be the default
+ * theme name.
+ */
+function wysiwyg_epiceditor_themes($editor, $profile) {
+ return array('epic-dark', 'epic-light');
+ // @todo Use the preview themes somewhere.
+ //return array('preview-dark', 'github');
+}
+
+/**
+ * Return runtime editor settings for a given wysiwyg profile.
+ *
+ * @param $editor
+ * A processed hook_editor() array of editor properties.
+ * @param $config
+ * An array containing wysiwyg editor profile settings.
+ * @param $theme
+ * The name of a theme/GUI/skin to use.
+ *
+ * @return
+ * A settings array to be populated in
+ * Drupal.settings.wysiwyg.configs.{editor}
+ */
+function wysiwyg_epiceditor_settings($editor, $config, $theme) {
+ $settings = array(
+ 'basePath' => base_path() . $editor['library path'],
+ 'clientSideStorage' => FALSE,
+ 'theme' => $theme,
+ //'preview_theme' => '',
+ );
+ return $settings;
+}
+
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/fckeditor.inc b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/fckeditor.inc
index 70954da..27bcb7b 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/fckeditor.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/fckeditor.inc
@@ -131,8 +131,8 @@ function wysiwyg_fckeditor_settings($editor, $config, $theme) {
if ($config['css_setting'] == 'theme') {
$settings['EditorAreaCSS'] = implode(',', wysiwyg_get_css());
}
- else if ($config['css_setting'] == 'self' && isset($config['css_path'])) {
- $settings['EditorAreaCSS'] = strtr($config['css_path'], array('%b' => base_path(), '%t' => path_to_theme()));
+ elseif ($config['css_setting'] == 'self' && isset($config['css_path'])) {
+ $settings['EditorAreaCSS'] = strtr($config['css_path'], array('%b' => base_path(), '%t' => drupal_get_path('theme', variable_get('theme_default', NULL))));
}
}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/ckeditor-3.0.js b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/ckeditor-3.0.js
index d2cf300..f288928 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/ckeditor-3.0.js
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/ckeditor-3.0.js
@@ -23,6 +23,10 @@ Drupal.wysiwyg.editor.init.ckeditor = function(settings) {
}
}
}
+ // Register Font styles (versions 3.2.1 and above).
+ if (Drupal.settings.wysiwyg.configs.ckeditor[format].stylesSet) {
+ CKEDITOR.stylesSet.add(format, Drupal.settings.wysiwyg.configs.ckeditor[format].stylesSet);
+ }
}
};
@@ -34,6 +38,8 @@ Drupal.wysiwyg.editor.attach.ckeditor = function(context, params, settings) {
// Apply editor instance settings.
CKEDITOR.config.customConfig = '';
+ var $drupalToolbar = $('#toolbar', Drupal.overlayChild ? window.parent.document : document);
+
settings.on = {
instanceReady: function(ev) {
var editor = ev.editor;
@@ -125,6 +131,19 @@ Drupal.wysiwyg.editor.attach.ckeditor = function(context, params, settings) {
focus: function(ev) {
Drupal.wysiwyg.activeId = ev.editor.name;
+ },
+
+ afterCommandExec: function(ev) {
+ // Fix Drupal toolbar obscuring editor toolbar in fullscreen mode.
+ if (ev.data.name != 'maximize') {
+ return;
+ }
+ if (ev.data.command.state == CKEDITOR.TRISTATE_ON) {
+ $drupalToolbar.hide();
+ }
+ else {
+ $drupalToolbar.show();
+ }
}
};
@@ -139,16 +158,19 @@ Drupal.wysiwyg.editor.attach.ckeditor = function(context, params, settings) {
* containing all instances or the passed in params.field instance, but
* always return an array to simplify all detach functions.
*/
-Drupal.wysiwyg.editor.detach.ckeditor = function(context, params) {
+Drupal.wysiwyg.editor.detach.ckeditor = function (context, params, trigger) {
+ var method = (trigger == 'serialize') ? 'updateElement' : 'destroy';
if (typeof params != 'undefined') {
var instance = CKEDITOR.instances[params.field];
if (instance) {
- instance.destroy();
+ instance[method]();
}
}
else {
for (var instanceName in CKEDITOR.instances) {
- CKEDITOR.instances[instanceName].destroy();
+ if (CKEDITOR.instances.hasOwnProperty(instanceName)) {
+ CKEDITOR.instances[instanceName][method]();
+ }
}
}
};
@@ -208,9 +230,18 @@ Drupal.wysiwyg.editor.instance.ckeditor = {
// @todo Don't know if we need this yet.
return content;
},
+
insert: function(content) {
content = this.prepareContent(content);
CKEDITOR.instances[this.field].insertHtml(content);
+ },
+
+ setContent: function (content) {
+ CKEDITOR.instances[this.field].setData(content);
+ },
+
+ getContent: function () {
+ return CKEDITOR.instances[this.field].getData();
}
};
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/epiceditor.js b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/epiceditor.js
new file mode 100644
index 0000000..03c4801
--- /dev/null
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/epiceditor.js
@@ -0,0 +1,38 @@
+(function($) {
+
+/**
+ * Attach this editor to a target element.
+ */
+Drupal.wysiwyg.editor.attach.epiceditor = function (context, params, settings) {
+ var $target = $('#' + params.field);
+ var containerId = params.field + '-epiceditor';
+ var defaultContent = $target.val();
+ $target.hide().after('<div id="' + containerId + '" />');
+
+ settings.container = containerId;
+ settings.file = {
+ defaultContent: defaultContent
+ };
+ settings.theme = {
+ preview: '/themes/preview/preview-dark.css',
+ editor: '/themes/editor/' + settings.theme + '.css'
+ }
+ var editor = new EpicEditor(settings).load();
+ $target.data('epiceditor', editor);
+};
+
+/**
+ * Detach a single or all editors.
+ */
+Drupal.wysiwyg.editor.detach.epiceditor = function (context, params, trigger) {
+ var $target = $('#' + params.field);
+ var editor = $target.data('epiceditor');
+
+ $target.val(editor.exportFile());
+
+ editor.unload(function () {
+ $target.show();
+ });
+};
+
+})(jQuery);
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/fckeditor-2.6.js b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/fckeditor-2.6.js
index 4ee2cff..fd915e3 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/fckeditor-2.6.js
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/fckeditor-2.6.js
@@ -21,7 +21,7 @@ Drupal.wysiwyg.editor.attach.fckeditor = function(context, params, settings) {
/**
* Detach a single or all editors.
*/
-Drupal.wysiwyg.editor.detach.fckeditor = function(context, params) {
+Drupal.wysiwyg.editor.detach.fckeditor = function (context, params, trigger) {
var instances = [];
if (typeof params != 'undefined' && typeof FCKeditorAPI != 'undefined') {
var instance = FCKeditorAPI.GetInstance(params.field);
@@ -36,6 +36,11 @@ Drupal.wysiwyg.editor.detach.fckeditor = function(context, params) {
for (var instanceName in instances) {
var instance = instances[instanceName];
instance.UpdateLinkedField();
+ if (trigger == 'serialize') {
+ // The editor is not being removed from the DOM, so updating the linked
+ // field is the only action necessary.
+ continue;
+ }
// Since we already detach the editor and update the textarea, the submit
// event handler needs to be removed to prevent data loss (in IE).
// FCKeditor uses 2 nested iFrames; instance.EditingArea.Window is the
@@ -175,6 +180,16 @@ Drupal.wysiwyg.editor.instance.fckeditor = {
var instance = FCKeditorAPI.GetInstance(this.field);
// @see FCK.InsertHtml(), FCK.InsertElement()
instance.InsertHtml(content);
+ },
+
+ getContent: function () {
+ var instance = FCKeditorAPI.GetInstance(this.field);
+ return instance.GetData();
+ },
+
+ setContent: function (content) {
+ var instance = FCKeditorAPI.GetInstance(this.field);
+ instance.SetHTML(content);
}
};
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/fckeditor.config.js b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/fckeditor.config.js
index d3fbc2f..42efc32 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/fckeditor.config.js
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/fckeditor.config.js
@@ -40,6 +40,19 @@ for (var setting in wysiwygSettings) {
}
}
+// Fix Drupal toolbar obscuring editor toolbar in fullscreen mode.
+var oldFitWindowExecute = FCKFitWindow.prototype.Execute;
+var $drupalToolbar = window.parent.jQuery('#toolbar', Drupal.overlayChild ? window.parent.window.parent.document : window.parent.document);
+FCKFitWindow.prototype.Execute = function() {
+ oldFitWindowExecute.apply(this, arguments);
+ if (this.IsMaximized) {
+ $drupalToolbar.hide();
+ }
+ else {
+ $drupalToolbar.show();
+ }
+}
+
/**
* Initialize this editor instance.
*/
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/jwysiwyg.js b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/jwysiwyg.js
index ae47853..d3e7490 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/jwysiwyg.js
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/jwysiwyg.js
@@ -11,15 +11,33 @@ Drupal.wysiwyg.editor.attach.jwysiwyg = function(context, params, settings) {
/**
* Detach a single or all editors.
*/
-Drupal.wysiwyg.editor.detach.jwysiwyg = function(context, params) {
+Drupal.wysiwyg.editor.detach.jwysiwyg = function (context, params, trigger) {
var $field = $('#' + params.field);
var editor = $field.data('wysiwyg');
if (typeof editor != 'undefined') {
editor.saveContent();
- editor.element.remove();
+ if (trigger != 'serialize') {
+ editor.element.remove();
+ }
}
$field.removeData('wysiwyg');
- $field.show();
+ if (trigger != 'serialize') {
+ $field.show();
+ }
+};
+
+Drupal.wysiwyg.editor.instance.jwysiwyg = {
+ insert: function (content) {
+ $('#' + this.field).wysiwyg('insertHtml', content);
+ },
+
+ setContent: function (content) {
+ $('#' + this.field).wysiwyg('setContent', content);
+ },
+
+ getContent: function () {
+ return $('#' + this.field).wysiwyg('getContent');
+ }
};
})(jQuery);
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/markitup.js b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/markitup.js
index 6691811..00e10b9 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/markitup.js
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/markitup.js
@@ -17,7 +17,10 @@ Drupal.wysiwyg.editor.attach.markitup = function(context, params, settings) {
/**
* Detach a single or all editors.
*/
-Drupal.wysiwyg.editor.detach.markitup = function(context, params) {
+Drupal.wysiwyg.editor.detach.markitup = function (context, params, trigger) {
+ if (trigger == 'serialize') {
+ return;
+ }
if (typeof params != 'undefined') {
$('#' + params.field, context).markItUpRemove();
}
@@ -26,4 +29,18 @@ Drupal.wysiwyg.editor.detach.markitup = function(context, params) {
}
};
+Drupal.wysiwyg.editor.instance.markitup = {
+ insert: function (content) {
+ $.markItUp({ replaceWith: content });
+ },
+
+ setContent: function (content) {
+ $('#' + this.field).val(content);
+ },
+
+ getContent: function () {
+ return $('#' + this.field).val();
+ }
+};
+
})(jQuery);
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/nicedit.js b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/nicedit.js
index d5d9795..10b7809 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/nicedit.js
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/nicedit.js
@@ -30,12 +30,17 @@ Drupal.wysiwyg.editor.attach.nicedit = function(context, params, settings) {
*
* See Drupal.wysiwyg.editor.detach.none() for a full description of this hook.
*/
-Drupal.wysiwyg.editor.detach.nicedit = function(context, params) {
+Drupal.wysiwyg.editor.detach.nicedit = function (context, params, trigger) {
if (typeof params != 'undefined') {
var instance = nicEditors.findEditor(params.field);
if (instance) {
- instance.ne.removeInstance(params.field);
- instance.ne.removePanel();
+ if (trigger == 'serialize') {
+ instance.saveContent();
+ }
+ else {
+ instance.ne.removeInstance(params.field);
+ instance.ne.removePanel();
+ }
}
}
else {
@@ -43,10 +48,17 @@ Drupal.wysiwyg.editor.detach.nicedit = function(context, params) {
// Save contents of all editors back into textareas.
var instances = nicEditors.editors[e].nicInstances;
for (var i = 0; i < instances.length; i++) {
- instances[i].remove();
+ if (trigger == 'serialize') {
+ instances[i].saveContent();
+ }
+ else {
+ instances[i].remove();
+ }
}
// Remove all editor instances.
- nicEditors.editors[e].nicInstances = [];
+ if (trigger != 'serialize') {
+ nicEditors.editors[e].nicInstances = [];
+ }
}
}
};
@@ -62,7 +74,7 @@ Drupal.wysiwyg.editor.instance.nicedit = {
// IE.
if (document.selection) {
editingArea.focus();
- sel.createRange().text = content;
+ sel.createRange().pasteHTML(content);
}
else {
// Convert selection to a range.
@@ -89,6 +101,14 @@ Drupal.wysiwyg.editor.instance.nicedit = {
// Only fragment children are inserted.
range.insertNode(fragment);
}
+ },
+
+ setContent: function (content) {
+ nicEditors.findEditor(this.field).setContent(content);
+ },
+
+ getContent: function () {
+ return nicEditors.findEditor(this.field).getContent();
}
};
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/none.js b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/none.js
index 3402024..762f7fb 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/none.js
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/none.js
@@ -17,7 +17,7 @@ Drupal.wysiwyg.editor.attach.none = function(context, params, settings) {
if (params.resizable) {
var $wrapper = $('#' + params.field).parents('.form-textarea-wrapper:first');
$wrapper.addClass('resizable');
- if (Drupal.behaviors.textarea.attach) {
+ if (Drupal.behaviors.textarea) {
Drupal.behaviors.textarea.attach();
}
}
@@ -26,6 +26,9 @@ Drupal.wysiwyg.editor.attach.none = function(context, params, settings) {
/**
* Detach a single or all editors.
*
+ * The editor syncs its contents back to the original field before its instance
+ * is removed.
+ *
* @param context
* A DOM element, supplied by Drupal.attachBehaviors().
* @param params
@@ -33,9 +36,18 @@ Drupal.wysiwyg.editor.attach.none = function(context, params, settings) {
* only the editor instance in params.field should be detached. Otherwise,
* all editors should be detached and saved, so they can be submitted in
* AJAX/AHAH applications.
+ * @param trigger
+ * A string describing why the editor is being detached.
+ * Possible triggers are:
+ * - unload: (default) Another or no editor is about to take its place.
+ * - move: Currently expected to produce the same result as unload.
+ * - serialize: The form is about to be serialized before an AJAX request or
+ * a normal form submission. If possible, perform a quick detach and leave
+ * the editor's GUI elements in place to avoid flashes or scrolling issues.
+ * @see Drupal.detachBehaviors
*/
-Drupal.wysiwyg.editor.detach.none = function(context, params) {
- if (typeof params != 'undefined') {
+Drupal.wysiwyg.editor.detach.none = function (context, params, trigger) {
+ if (typeof params != 'undefined' && (trigger != 'serialize')) {
var $wrapper = $('#' + params.field).parents('.form-textarea-wrapper:first');
$wrapper.removeOnce('textarea').removeClass('.resizable-textarea')
.find('.grippie').remove();
@@ -65,6 +77,14 @@ Drupal.wysiwyg.editor.instance.none = {
else {
editor.value += content;
}
+ },
+
+ setContent: function (content) {
+ $('#' + this.field).val(content);
+ },
+
+ getContent: function () {
+ return $('#' + this.field).val();
}
};
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/openwysiwyg.js b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/openwysiwyg.js
index 89a5337..a01e8a0 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/openwysiwyg.js
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/openwysiwyg.js
@@ -23,6 +23,19 @@ WYSIWYG.getEditor = function (n) {
(function($) {
+// Fix Drupal toolbar obscuring editor toolbar in fullscreen mode.
+var oldMaximize = WYSIWYG.maximize;
+WYSIWYG.maximize = function (n) {
+var $drupalToolbar = $('#toolbar', Drupal.overlayChild ? window.parent.document : document);
+ oldMaximize.apply(this, arguments);
+ if (this.maximized[n]) {
+ $drupalToolbar.hide();
+ }
+ else {
+ $drupalToolbar.show();
+ }
+}
+
/**
* Attach this editor to a target element.
*/
@@ -45,24 +58,84 @@ Drupal.wysiwyg.editor.attach.openwysiwyg = function(context, params, settings) {
/**
* Detach a single or all editors.
*/
-Drupal.wysiwyg.editor.detach.openwysiwyg = function(context, params) {
+Drupal.wysiwyg.editor.detach.openwysiwyg = function (context, params, trigger) {
if (typeof params != 'undefined') {
var instance = WYSIWYG.config[params.field];
if (typeof instance != 'undefined') {
WYSIWYG.updateTextArea(params.field);
- jQuery('#wysiwyg_div_' + params.field).remove();
- delete instance;
+ if (trigger != 'serialize') {
+ jQuery('#wysiwyg_div_' + params.field).remove();
+ delete instance;
+ }
+ }
+ if (trigger != 'serialize') {
+ jQuery('#' + params.field).show();
}
- jQuery('#' + params.field).show();
}
else {
jQuery.each(WYSIWYG.config, function(field) {
WYSIWYG.updateTextArea(field);
- jQuery('#wysiwyg_div_' + field).remove();
- delete this;
- jQuery('#' + field).show();
+ if (trigger != 'serialize') {
+ jQuery('#wysiwyg_div_' + field).remove();
+ delete this;
+ jQuery('#' + field).show();
+ }
});
}
};
+/**
+ * Instance methods for openWYSIWYG.
+ */
+Drupal.wysiwyg.editor.instance.openwysiwyg = {
+ insert: function (content) {
+ // If IE has dropped focus content will be inserted at the top of the page.
+ $('#wysiwyg' + this.field).contents().find('body').focus();
+ WYSIWYG.insertHTML(content, this.field);
+ },
+
+ setContent: function (content) {
+ // Based on openWYSIWYG's _generate() method.
+ var doc = WYSIWYG.getEditorWindow(this.field).document;
+ if (WYSIWYG.config[this.field].ReplaceLineBreaks) {
+ content = content.replace(/\n\r|\n/ig, '<br />');
+ }
+ if (WYSIWYG.viewTextMode[this.field]) {
+ var html = document.createTextNode(content);
+ doc.body.innerHTML = '';
+ doc.body.appendChild(html);
+ }
+ else {
+ doc.open();
+ doc.write(content);
+ doc.close();
+ }
+ },
+
+ getContent: function () {
+ // Based on openWYSIWYG's updateTextarea() method.
+ var content = '';
+ var doc = WYSIWYG.getEditorWindow(this.field).document;
+ if (WYSIWYG.viewTextMode[this.field]) {
+ if (WYSIWYG_Core.isMSIE) {
+ content = doc.body.innerText;
+ }
+ else {
+ var range = doc.body.ownerDocument.createRange();
+ range.selectNodeContents(doc.body);
+ content = range.toString();
+ }
+ }
+ else {
+ content = doc.body.innerHTML;
+ }
+ content = WYSIWYG.stripURLPath(this.field, content);
+ content = WYSIWYG_Core.replaceRGBWithHexColor(content);
+ if (WYSIWYG.config[this.field].ReplaceLineBreaks) {
+ content = content.replace(/(\r\n)|(\n)/ig, '');
+ }
+ return content;
+ }
+};
+
})(jQuery);
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/tinymce-2.js b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/tinymce-2.js
index 088021f..61a60ad 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/tinymce-2.js
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/tinymce-2.js
@@ -10,18 +10,8 @@
* An object containing editor settings for each input format.
*/
Drupal.wysiwyg.editor.init.tinymce = function(settings) {
- // If JS compression is enabled, TinyMCE is unable to autodetect its global
- // settinge, hence we need to define them manually.
- // @todo Move global library settings somewhere else.
- tinyMCE.baseURL = settings.global.editorBasePath;
- tinyMCE.srcMode = (settings.global.execMode == 'src' ? '_src' : '');
- tinyMCE.gzipMode = (settings.global.execMode == 'gzip');
-
// Initialize editor configurations.
for (var format in settings) {
- if (format == 'global') {
- continue;
- }
tinyMCE.init(settings[format]);
if (Drupal.settings.wysiwyg.plugins[format]) {
// Load native external plugins.
@@ -67,7 +57,7 @@ Drupal.wysiwyg.editor.attach.tinymce = function(context, params, settings) {
*
* See Drupal.wysiwyg.editor.detach.none() for a full desciption of this hook.
*/
-Drupal.wysiwyg.editor.detach.tinymce = function(context, params) {
+Drupal.wysiwyg.editor.detach.tinymce = function (context, params, trigger) {
if (typeof params != 'undefined') {
tinyMCE.removeMCEControl(tinyMCE.getEditorId(params.field));
$('#' + params.field).removeAttr('style');
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/tinymce-3.js b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/tinymce-3.js
index b38f523..83bae13 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/tinymce-3.js
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/tinymce-3.js
@@ -11,19 +11,21 @@
* An object containing editor settings for each input format.
*/
Drupal.wysiwyg.editor.init.tinymce = function(settings) {
- // If JS compression is enabled, TinyMCE is unable to autodetect its global
- // settinge, hence we need to define them manually.
- // @todo Move global library settings somewhere else.
- tinyMCE.baseURL = settings.global.editorBasePath;
- tinyMCE.srcMode = (settings.global.execMode == 'src' ? '_src' : '');
- tinyMCE.gzipMode = (settings.global.execMode == 'gzip');
+ // Fix Drupal toolbar obscuring editor toolbar in fullscreen mode.
+ var $drupalToolbar = $('#toolbar', Drupal.overlayChild ? window.parent.document : document);
+ tinyMCE.onAddEditor.add(function (mgr, ed) {
+ if (ed.id == 'mce_fullscreen') {
+ $drupalToolbar.hide();
+ }
+ });
+ tinyMCE.onRemoveEditor.add(function (mgr, ed) {
+ if (ed.id == 'mce_fullscreen') {
+ $drupalToolbar.show();
+ }
+ });
// Initialize editor configurations.
for (var format in settings) {
- if (format == 'global') {
- continue;
- };
- tinyMCE.init(settings[format]);
if (Drupal.settings.wysiwyg.plugins[format]) {
// Load native external plugins.
// Array syntax required; 'native' is a predefined token in JavaScript.
@@ -50,6 +52,8 @@ Drupal.wysiwyg.editor.attach.tinymce = function(context, params, settings) {
ed.onEvent.add(function(ed, e) {
Drupal.wysiwyg.activeId = ed.id;
});
+ // Indicate that the DOM has been loaded (in case of Ajax).
+ tinymce.dom.Event.domLoaded = true;
// Make toolbar buttons wrappable (required for IE).
ed.onPostRender.add(function (ed) {
var $toolbar = $('<div class="wysiwygToolbar"></div>');
@@ -79,20 +83,24 @@ Drupal.wysiwyg.editor.attach.tinymce = function(context, params, settings) {
*
* See Drupal.wysiwyg.editor.detach.none() for a full desciption of this hook.
*/
-Drupal.wysiwyg.editor.detach.tinymce = function(context, params) {
+Drupal.wysiwyg.editor.detach.tinymce = function (context, params, trigger) {
if (typeof params != 'undefined') {
var instance = tinyMCE.get(params.field);
if (instance) {
instance.save();
- instance.remove();
+ if (trigger != 'serialize') {
+ instance.remove();
+ }
}
}
else {
// Save contents of all editors back into textareas.
tinyMCE.triggerSave();
- // Remove all editor instances.
- for (var instance in tinyMCE.editors) {
- tinyMCE.editors[instance].remove();
+ if (trigger != 'serialize') {
+ // Remove all editor instances.
+ for (var instance in tinyMCE.editors) {
+ tinyMCE.editors[instance].remove();
+ }
}
}
};
@@ -138,16 +146,18 @@ Drupal.wysiwyg.editor.instance.tinymce = {
// Attach: Replace plain text with HTML representations.
ed.onBeforeSetContent.add(function(ed, data) {
+ var editorId = (ed.id == 'mce_fullscreen' ? ed.getParam('fullscreen_editor_id') : ed.id);
if (typeof Drupal.wysiwyg.plugins[plugin].attach == 'function') {
- data.content = Drupal.wysiwyg.plugins[plugin].attach(data.content, pluginSettings, ed.id);
+ data.content = Drupal.wysiwyg.plugins[plugin].attach(data.content, pluginSettings, editorId);
data.content = Drupal.wysiwyg.editor.instance.tinymce.prepareContent(data.content);
}
});
// Detach: Replace HTML representations with plain text.
ed.onGetContent.add(function(ed, data) {
+ var editorId = (ed.id == 'mce_fullscreen' ? ed.getParam('fullscreen_editor_id') : ed.id);
if (typeof Drupal.wysiwyg.plugins[plugin].detach == 'function') {
- data.content = Drupal.wysiwyg.plugins[plugin].detach(data.content, pluginSettings, ed.id);
+ data.content = Drupal.wysiwyg.plugins[plugin].detach(data.content, pluginSettings, editorId);
}
});
@@ -175,7 +185,7 @@ Drupal.wysiwyg.editor.instance.tinymce = {
},
openDialog: function(dialog, params) {
- var instanceId = this.isFullscreen() ? 'mce_fullscreen' : this.field;
+ var instanceId = this.getInstanceId();
var editor = tinyMCE.get(instanceId);
editor.windowManager.open({
file: dialog.url + '/' + instanceId,
@@ -186,8 +196,7 @@ Drupal.wysiwyg.editor.instance.tinymce = {
},
closeDialog: function(dialog) {
- var instanceId = this.isFullscreen() ? 'mce_fullscreen' : this.field;
- var editor = tinyMCE.get(instanceId);
+ var editor = tinyMCE.get(this.getInstanceId());
editor.windowManager.close(dialog);
},
@@ -222,13 +231,25 @@ Drupal.wysiwyg.editor.instance.tinymce = {
insert: function(content) {
content = this.prepareContent(content);
- var instanceId = this.isFullscreen() ? 'mce_fullscreen' : this.field;
- tinyMCE.execInstanceCommand(instanceId, 'mceInsertContent', false, content);
+ tinyMCE.execInstanceCommand(this.getInstanceId(), 'mceInsertContent', false, content);
+ },
+
+ setContent: function (content) {
+ content = this.prepareContent(content);
+ tinyMCE.execInstanceCommand(this.getInstanceId(), 'mceSetContent', false, content);
+ },
+
+ getContent: function () {
+ return tinyMCE.get(this.getInstanceId()).getContent();
},
isFullscreen: function() {
// TinyMCE creates a completely new instance for fullscreen mode.
return tinyMCE.activeEditor.id == 'mce_fullscreen' && tinyMCE.activeEditor.getParam('fullscreen_editor_id') == this.field;
+ },
+
+ getInstanceId: function () {
+ return this.isFullscreen() ? 'mce_fullscreen' : this.field;
}
};
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/whizzywig-56.js b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/whizzywig-56.js
index 229a70b..3fc2fe5 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/whizzywig-56.js
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/whizzywig-56.js
@@ -80,39 +80,28 @@ Drupal.wysiwyg.editor.attach.whizzywig = function(context, params, settings) {
// Attach editor.
makeWhizzyWig(params.field, (settings.buttons ? settings.buttons : 'all'));
// Whizzywig fails to detect and set initial textarea contents.
- var instance = $('#whizzy' + params.field).get(0);
- if (instance) {
- instance.contentWindow.document.body.innerHTML = tidyD($field.val());
- }
+ $('#whizzy' + params.field).contents().find('body').html(tidyD($field.val()));
};
/**
* Detach a single or all editors.
*/
-Drupal.wysiwyg.editor.detach.whizzywig = function(context, params) {
+Drupal.wysiwyg.editor.detach.whizzywig = function (context, params, trigger) {
var detach = function (index) {
- var id = whizzies[index];
- var instance = $('#whizzy' + id).get(0);
- if (!instance) {
- return;
- }
- var editingArea = instance.contentWindow.document;
- var $field = $('#' + id);
- // Whizzywig shows the original textarea in source mode.
- if ($field.css('display') == 'block') {
- editingArea.body.innerHTML = $field.val();
- }
+ var id = whizzies[index], $field = $('#' + id), instance = Drupal.wysiwyg.instances[id];
// Save contents of editor back into textarea.
- $field.val(tidyH(editingArea));
+ $field.val(instance.getContent());
+ // If the editor is just being serialized (not detached), our work is done.
+ if (trigger == 'serialize') {
+ return;
+ }
// Remove editor instance.
$('#' + id + '-whizzywig').remove();
whizzies.splice(index, 1);
// Restore original textarea styling.
- var originalValues = Drupal.wysiwyg.instances[id];
- $field.removeAttr('style');
- $field.attr('style', originalValues.originalStyle);
+ $field.removeAttr('style').attr('style', instance.originalStyle);
};
if (typeof params != 'undefined') {
@@ -130,4 +119,37 @@ Drupal.wysiwyg.editor.detach.whizzywig = function(context, params) {
}
};
+/**
+ * Instance methods for Whizzywig.
+ */
+Drupal.wysiwyg.editor.instance.whizzywig = {
+ insert: function (content) {
+ // Whizzywig executes any string beginning with 'js:'.
+ insHTML(content.replace(/^js:/, 'js:'));
+ },
+
+ setContent: function (content) {
+ // Whizzywig shows the original textarea in source mode.
+ if ($field.css('display') == 'block') {
+ $('#' + this.field).val(content);
+ }
+ else {
+ var doc = $('#whizzy' + this.field).contents()[0];
+ doc.open();
+ doc.write(content);
+ doc.close();
+ }
+ },
+
+ getContent: function () {
+ // Whizzywig's tidyH() expects a document node. Clone the editing iframe's
+ // document so tidyH() won't mess with it if this gets called while editing.
+ var clone = $($('#whizzy' + this.field).contents()[0].documentElement).clone()[0].ownerDocument;
+ // Whizzywig shows the original textarea in source mode so update the body.
+ if ($field.css('display') == 'block') {
+ clone.body.innerHTML = $('#' + this.field).val();
+ }
+ return tidyH(clone);
+ }
+};
})(jQuery);
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/whizzywig-60.js b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/whizzywig-60.js
index dc995f6..bbc6e64 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/whizzywig-60.js
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/whizzywig-60.js
@@ -29,42 +29,31 @@ Drupal.wysiwyg.editor.attach.whizzywig = function(context, params, settings) {
// Attach editor.
makeWhizzyWig(params.field, (settings.buttons ? settings.buttons : 'all'));
// Whizzywig fails to detect and set initial textarea contents.
- var instance = $('#whizzy' + params.field).get(0);
- if (instance) {
- instance.contentWindow.document.body.innerHTML = tidyD($field.val());
- }
+ $('#whizzy' + params.field).contents().find('body').html(tidyD($field.val()));
};
/**
* Detach a single or all editors.
*/
-Drupal.wysiwyg.editor.detach.whizzywig = function(context, params) {
+Drupal.wysiwyg.editor.detach.whizzywig = function (context, params, trigger) {
var detach = function (index) {
- var id = whizzies[index];
- var instance = $('#whizzy' + id).get(0);
- if (!instance) {
- return;
- }
- var editingArea = instance.contentWindow.document;
- var $field = $('#' + id);
- // Whizzywig shows the original textarea in source mode.
- if ($field.css('display') == 'block') {
- editingArea.body.innerHTML = $field.val();
- }
+ var id = whizzies[index], $field = $('#' + id), instance = Drupal.wysiwyg.instances[id];
// Save contents of editor back into textarea.
- $field.val(tidyH(editingArea));
+ $field.val(instance.getContent());
+ // If the editor is just being serialized (not detached), our work is done.
+ if (trigger == 'serialize') {
+ return;
+ }
// Move original textarea back to its previous location.
- $container = $('#CONTAINER' + id);
+ var $container = $('#CONTAINER' + id);
$field.insertBefore($container);
// Remove editor instance.
$container.remove();
whizzies.splice(index, 1);
// Restore original textarea styling.
- var originalValues = Drupal.wysiwyg.instances[id];
- $field.removeAttr('style');
- $field.attr('style', originalValues.originalStyle);
+ $field.removeAttr('style').attr('style', instance.originalStyle);
}
if (typeof params != 'undefined') {
@@ -82,4 +71,37 @@ Drupal.wysiwyg.editor.detach.whizzywig = function(context, params) {
}
};
+/**
+ * Instance methods for Whizzywig.
+ */
+Drupal.wysiwyg.editor.instance.whizzywig = {
+ insert: function (content) {
+ // Whizzywig executes any string beginning with 'js:'.
+ insHTML(content.replace(/^js:/, 'js:'));
+ },
+
+ setContent: function (content) {
+ // Whizzywig shows the original textarea in source mode.
+ if ($field.css('display') == 'block') {
+ $('#' + this.field).val(content);
+ }
+ else {
+ var doc = $('#whizzy' + this.field).contents()[0];
+ doc.open();
+ doc.write(content);
+ doc.close();
+ }
+ },
+
+ getContent: function () {
+ // Whizzywig's tidyH() expects a document node. Clone the editing iframe's
+ // document so tidyH() won't mess with it if this gets called while editing.
+ var clone = $($('#whizzy' + this.field).contents()[0].documentElement).clone()[0].ownerDocument;
+ // Whizzywig shows the original textarea in source mode so update the body.
+ if ($field.css('display') == 'block') {
+ clone.body.innerHTML = $('#' + this.field).val();
+ }
+ return tidyH(clone);
+ }
+};
})(jQuery);
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/whizzywig.js b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/whizzywig.js
index e98bc4d..e89ac5f 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/whizzywig.js
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/whizzywig.js
@@ -71,41 +71,28 @@ Drupal.wysiwyg.editor.attach.whizzywig = function(context, params, settings) {
// Attach editor.
makeWhizzyWig(params.field, (settings.buttons ? settings.buttons : 'all'));
// Whizzywig fails to detect and set initial textarea contents.
- var instance = $('#whizzy' + params.field).get(0);
- if (instance) {
- instance.contentWindow.document.body.innerHTML = tidyD($field.val());
- }
+ $('#whizzy' + params.field).contents().find('body').html(tidyD($field.val()));
};
/**
* Detach a single or all editors.
*/
-Drupal.wysiwyg.editor.detach.whizzywig = function(context, params) {
+Drupal.wysiwyg.editor.detach.whizzywig = function (context, params, trigger) {
var detach = function (index) {
- var id = whizzies[index];
- var instance = $('#whizzy' + id).get(0);
- if (!instance) {
- return;
- }
- var body = instance.contentWindow.document.body;
- var $field = $('#' + id);
- // Whizzywig shows the original textarea in source mode.
- if ($field.css('display') == 'block') {
- body.innerHTML = $field.val();
- }
- body.innerHTML = tidyH(body.innerHTML);
+ var id = whizzies[index], $field = $('#' + id), instance = Drupal.wysiwyg.instances[id];
// Save contents of editor back into textarea.
- $field.val(window.get_xhtml ? get_xhtml(body) : body.innerHTML);
- $field.val($field.val().replace(location.href + '#', '#'));
+ $field.val(instance.getContent());
+ // If the editor is just being serialized (not detached), our work is done.
+ if (trigger == 'serialize') {
+ return;
+ }
// Remove editor instance.
$('#' + id + '-whizzywig').remove();
whizzies.splice(index, 1);
// Restore original textarea styling.
- var originalValues = Drupal.wysiwyg.instances[id];
- $field.removeAttr('style');
- $field.attr('style', originalValues.originalStyle);
+ $field.removeAttr('style').attr('style', instance.originalStyle);
};
if (typeof params != 'undefined') {
@@ -123,4 +110,45 @@ Drupal.wysiwyg.editor.detach.whizzywig = function(context, params) {
}
};
+/**
+ * Instance methods for Whizzywig.
+ */
+Drupal.wysiwyg.editor.instance.whizzywig = {
+ insert: function (content) {
+ // Whizzywig executes any string beginning with 'js:'.
+ insHTML(content.replace(/^js:/, 'js:'));
+ },
+
+ setContent: function (content) {
+ var $field = $('#' + this.field);
+ // Whizzywig shows the original textarea in source mode.
+ if ($field.css('display') == 'block') {
+ $field.val(content);
+ }
+ else {
+ var doc = $('#whizzy' + this.field).contents()[0];
+ doc.open();
+ doc.write(content);
+ doc.close();
+ }
+ },
+
+ getContent: function () {
+ var $field = $('#' + this.field),
+ // Whizzywig shows the original textarea in source mode.
+ content = ($field.css('display') == 'block' ?
+ $field.val() : $('#whizzy' + this.field).contents().find('body').html()
+ );
+
+ content = tidyH(content);
+ // Whizzywig's get_xhtml() addon, if defined, expects a DOM node.
+ if ($.isFunction(window.get_xhtml)) {
+ var pre = document.createElement('pre');
+ pre.innerHTML = content;
+ content = get_xhtml(pre);
+ }
+ return content.replace(location.href + '#', '#');
+ }
+};
+
})(jQuery);
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/wymeditor.js b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/wymeditor.js
index ed66784..4989dc6 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/wymeditor.js
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/wymeditor.js
@@ -19,37 +19,55 @@ Drupal.wysiwyg.editor.attach.wymeditor = function (context, params, settings) {
/**
* Detach a single or all editors.
*/
-Drupal.wysiwyg.editor.detach.wymeditor = function (context, params) {
+Drupal.wysiwyg.editor.detach.wymeditor = function (context, params, trigger) {
if (typeof params != 'undefined') {
var $field = $('#' + params.field);
var index = $field.data(WYMeditor.WYM_INDEX);
if (typeof index != 'undefined') {
var instance = WYMeditor.INSTANCES[index];
instance.update();
- $(instance._box).remove();
- $(instance._element).show();
- delete instance;
+ if (trigger != 'serialize') {
+ $(instance._box).remove();
+ $(instance._element).show();
+ delete instance;
+ }
+ }
+ if (trigger != 'serialize') {
+ $field.show();
}
- $field.show();
}
else {
jQuery.each(WYMeditor.INSTANCES, function () {
this.update();
- $(this._box).remove();
- $(this._element).show();
- delete this;
+ if (trigger != 'serialize') {
+ $(this._box).remove();
+ $(this._element).show();
+ delete this;
+ }
});
}
};
Drupal.wysiwyg.editor.instance.wymeditor = {
insert: function (content) {
+ this.getInstance().insert(content);
+ },
+
+ setContent: function (content) {
+ this.getInstance().html(content);
+ },
+
+ getContent: function () {
+ return this.getInstance().xhtml();
+ },
+
+ getInstance: function () {
var $field = $('#' + this.field);
var index = $field.data(WYMeditor.WYM_INDEX);
if (typeof index != 'undefined') {
- var instance = WYMeditor.INSTANCES[index];
- instance.insert(content);
+ return WYMeditor.INSTANCES[index];
}
+ return null;
}
};
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/yui.js b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/yui.js
index ad8be36..3f4e7c6 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/yui.js
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/js/yui.js
@@ -2,12 +2,70 @@
/**
* Attach this editor to a target element.
+ *
+ * Since buttons must be added before the editor is rendered, we add plugins
+ * buttons on attach event rather than in init.
*/
Drupal.wysiwyg.editor.attach.yui = function(context, params, settings) {
// Apply theme.
$('#' + params.field).parent().addClass('yui-skin-' + settings.theme);
+
+ // Load plugins stylesheet.
+ for (var plugin in Drupal.settings.wysiwyg.plugins[params.format].drupal) {
+ settings.extracss += settings.extracss+' @import "'+Drupal.settings.wysiwyg.plugins[params.format].drupal[plugin].css+'"; ';
+ }
+
// Attach editor.
var editor = new YAHOO.widget.Editor(params.field, settings);
+
+ editor.on('toolbarLoaded', function() {
+ // Load Drupal plugins.
+ for (var plugin in Drupal.settings.wysiwyg.plugins[params.format].drupal) {
+ Drupal.wysiwyg.instances[params.field].addPlugin(plugin, Drupal.settings.wysiwyg.plugins[params.format].drupal[plugin], Drupal.settings.wysiwyg.plugins.drupal[plugin]);
+ }
+ });
+
+ // Allow plugins to act on setEditorHTML.
+ var oldSetEditorHTML = editor.setEditorHTML;
+ editor.setEditorHTML = function (content) {
+ for (var plugin in Drupal.settings.wysiwyg.plugins[params.format].drupal) {
+ var pluginSettings = Drupal.settings.wysiwyg.plugins.drupal[plugin];
+ if (typeof Drupal.wysiwyg.plugins[plugin].attach == 'function') {
+ content = Drupal.wysiwyg.plugins[plugin].attach(content, pluginSettings, params.field);
+ content = Drupal.wysiwyg.instances[params.field].prepareContent(content);
+ }
+ }
+ oldSetEditorHTML.call(this, content);
+ };
+
+ // Allow plugins to act on getEditorHTML.
+ var oldGetEditorHTML = editor.getEditorHTML;
+ editor.getEditorHTML = function () {
+ var content = oldGetEditorHTML.call(this);
+ for (var plugin in Drupal.settings.wysiwyg.plugins[params.format].drupal) {
+ var pluginSettings = Drupal.settings.wysiwyg.plugins.drupal[plugin];
+ if (typeof Drupal.wysiwyg.plugins[plugin].detach == 'function') {
+ content = Drupal.wysiwyg.plugins[plugin].detach(content, pluginSettings, params.field);
+ }
+ }
+ return content;
+ }
+
+ // Reload the editor contents to give Drupal plugins a chance to act.
+ editor.on('editorContentLoaded', function (e) {
+ e.target.setEditorHTML(oldGetEditorHTML.call(e.target));
+ });
+
+ editor.on('afterNodeChange', function (e) {
+ for (var plugin in Drupal.settings.wysiwyg.plugins[params.format].drupal) {
+ if (typeof Drupal.wysiwyg.plugins[plugin].isNode == 'function') {
+ if (Drupal.wysiwyg.plugins[plugin].isNode(e.target._getSelectedElement())) {
+ this.toolbar.selectButton(plugin);
+ }
+ }
+ }
+ });
+
editor.render();
};
@@ -16,19 +74,71 @@ Drupal.wysiwyg.editor.attach.yui = function(context, params, settings) {
*
* See Drupal.wysiwyg.editor.detach.none() for a full desciption of this hook.
*/
-Drupal.wysiwyg.editor.detach.yui = function(context, params) {
+Drupal.wysiwyg.editor.detach.yui = function (context, params, trigger) {
+ var method = (trigger && trigger == 'serialize') ? 'saveHTML' : 'destroy';
if (typeof params != 'undefined') {
- var instance = YAHOO.widget.EditorInfo.getEditorById(params.field);
+ var instance = YAHOO.widget.EditorInfo._instances[params.field];
if (instance) {
- instance.destroy();
+ instance[method]();
+ if (method == 'destroy') {
+ delete YAHOO.widget.EditorInfo._instances[params.field];
+ }
}
}
else {
for (var e in YAHOO.widget.EditorInfo._instances) {
// Save contents of all editors back into textareas.
var instance = YAHOO.widget.EditorInfo._instances[e];
- instance.destroy();
+ instance[method]();
+ if (method == 'destroy') {
+ delete YAHOO.widget.EditorInfo._instances[e];
+ }
+ }
+ }
+};
+
+/**
+ * Instance methods for YUI Editor.
+ */
+Drupal.wysiwyg.editor.instance.yui = {
+ addPlugin: function (plugin, settings, pluginSettings) {
+ if (typeof Drupal.wysiwyg.plugins[plugin] != 'object') {
+ return;
}
+ var editor = YAHOO.widget.EditorInfo.getEditorById(this.field);
+ var button = editor.toolbar.getButtonByValue(plugin);
+ $(button._button).parent().css('background', 'transparent url(' + settings.icon + ') no-repeat center');
+ // 'this' will reference the toolbar while inside the event handler.
+ var instanceId = this.field;
+ editor.toolbar.on(plugin + 'Click', function (e) {
+ var selectedElement = editor._getSelectedElement();
+ // @todo Using .html() will cause XTHML vs HTML conflicts.
+ var data = {
+ format: 'html',
+ node: selectedElement,
+ content: $(selectedElement).html()
+ };
+ Drupal.wysiwyg.plugins[plugin].invoke(data, pluginSettings, instanceId);
+ });
+ },
+
+ prepareContent: function (content) {
+ var editor = YAHOO.widget.EditorInfo.getEditorById(this.field);
+ content = editor.cleanHTML(content);
+ return content;
+ },
+
+ insert: function (content) {
+ YAHOO.widget.EditorInfo.getEditorById(this.field).cmd_inserthtml(content);
+ },
+
+ setContent: function (content) {
+ YAHOO.widget.EditorInfo.getEditorById(this.field).setEditorHTML(content);
+ },
+
+ getContent: function () {
+ var instance = YAHOO.widget.EditorInfo.getEditorById(this.field);
+ return instance.cleanHTML(instance.getEditorHTML(content));
}
};
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/nicedit.inc b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/nicedit.inc
index 779660c..6acc800 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/nicedit.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/nicedit.inc
@@ -77,13 +77,13 @@ function wysiwyg_nicedit_settings($editor, $config, $theme) {
// Add editor content stylesheet.
if (isset($config['css_setting'])) {
if ($config['css_setting'] == 'theme') {
- $css = path_to_theme() . '/style.css';
+ $css = drupal_get_path('theme', variable_get('theme_default', NULL)) . '/style.css';
if (file_exists($css)) {
$settings['externalCSS'] = base_path() . $css;
}
}
- else if ($config['css_setting'] == 'self' && isset($config['css_path'])) {
- $settings['externalCSS'] = strtr($config['css_path'], array('%b' => base_path(), '%t' => path_to_theme()));
+ elseif ($config['css_setting'] == 'self' && isset($config['css_path'])) {
+ $settings['externalCSS'] = strtr($config['css_path'], array('%b' => base_path(), '%t' => drupal_get_path('theme', variable_get('theme_default', NULL))));
}
}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/openwysiwyg.inc b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/openwysiwyg.inc
index f521da5..b3ad84d 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/openwysiwyg.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/openwysiwyg.inc
@@ -102,8 +102,8 @@ function wysiwyg_openwysiwyg_settings($editor, $config, $theme) {
if ($config['css_setting'] == 'theme') {
$settings['CSSFile'] = reset(wysiwyg_get_css());
}
- else if ($config['css_setting'] == 'self' && isset($config['css_path'])) {
- $settings['CSSFile'] = strtr($config['css_path'], array('%b' => base_path(), '%t' => path_to_theme()));
+ elseif ($config['css_setting'] == 'self' && isset($config['css_path'])) {
+ $settings['CSSFile'] = strtr($config['css_path'], array('%b' => base_path(), '%t' => drupal_get_path('theme', variable_get('theme_default', NULL))));
}
}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/tinymce.inc b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/tinymce.inc
index a7250f3..f3a92dd 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/tinymce.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/tinymce.inc
@@ -28,6 +28,7 @@ function wysiwyg_tinymce_editor() {
),
'version callback' => 'wysiwyg_tinymce_version',
'themes callback' => 'wysiwyg_tinymce_themes',
+ 'init callback' => 'wysiwyg_tinymce_init',
'settings callback' => 'wysiwyg_tinymce_settings',
'plugin callback' => 'wysiwyg_tinymce_plugins',
'plugin settings callback' => 'wysiwyg_tinymce_plugin_settings',
@@ -126,6 +127,40 @@ function wysiwyg_tinymce_themes($editor, $profile) {
}
/**
+ * Returns an initialization JavaScript for this editor library.
+ *
+ * @param array $editor
+ * The editor library definition.
+ * @param string $library
+ * The library variant key from $editor['libraries'].
+ * @param object $profile
+ * The (first) wysiwyg editor profile.
+ *
+ * @return string
+ * A string containing inline JavaScript to execute before the editor library
+ * script is loaded.
+ */
+function wysiwyg_tinymce_init($editor, $library) {
+ // TinyMCE unconditionally searches for its library filename in SCRIPT tags on
+ // on the page upon loading the library in order to determine the base path to
+ // itself. When JavaScript aggregation is enabled, this search fails and all
+ // relative constructed paths within TinyMCE are broken. The library has a
+ // tinyMCE.baseURL property, but it is not publicly documented and thus not
+ // reliable. The official support forum suggests to solve the issue through
+ // the global window.tinyMCEPreInit variable also used by various serverside
+ // compressor scrips available from the official website.
+ // @see http://www.tinymce.com/forum/viewtopic.php?id=23286
+ $settings = drupal_json_encode(array(
+ 'base' => base_path() . $editor['library path'],
+ 'suffix' => (strpos($library, 'src') !== FALSE || strpos($library, 'dev') !== FALSE ? '_src' : ''),
+ 'query' => '',
+ ));
+ return <<<EOL
+window.tinyMCEPreInit = $settings;
+EOL;
+}
+
+/**
* Return runtime editor settings for a given wysiwyg profile.
*
* @param $editor
@@ -178,6 +213,7 @@ function wysiwyg_tinymce_settings($editor, $config, $theme) {
$settings['remove_linebreaks'] = $config['remove_linebreaks'];
}
if (isset($config['verify_html'])) {
+ // TinyMCE performs a type-agnostic comparison on this particular setting.
$settings['verify_html'] = (bool) $config['verify_html'];
}
@@ -189,8 +225,8 @@ function wysiwyg_tinymce_settings($editor, $config, $theme) {
if ($config['css_setting'] == 'theme') {
$settings['content_css'] = implode(',', wysiwyg_get_css());
}
- else if ($config['css_setting'] == 'self' && isset($config['css_path'])) {
- $settings['content_css'] = strtr($config['css_path'], array('%b' => base_path(), '%t' => path_to_theme()));
+ elseif ($config['css_setting'] == 'self' && isset($config['css_path'])) {
+ $settings['content_css'] = strtr($config['css_path'], array('%b' => base_path(), '%t' => drupal_get_path('theme', variable_get('theme_default', NULL))));
}
}
@@ -229,15 +265,15 @@ function wysiwyg_tinymce_settings($editor, $config, $theme) {
$settings['extensions'][_wysiwyg_tinymce_plugin_name('add', $button)] = 1;
}
// Add external plugins to the list of extensions.
- else if ($type == 'buttons' && empty($plugins[$plugin]['internal'])) {
+ elseif ($type == 'buttons' && empty($plugins[$plugin]['internal'])) {
$settings['extensions'][_wysiwyg_tinymce_plugin_name('add', $plugin)] = 1;
}
// Add internal buttons that also need to be loaded as extension.
- else if ($type == 'buttons' && !empty($plugins[$plugin]['load'])) {
+ elseif ($type == 'buttons' && !empty($plugins[$plugin]['load'])) {
$settings['extensions'][$plugin] = 1;
}
// Add plain extensions.
- else if ($type == 'extensions' && !empty($plugins[$plugin]['load'])) {
+ elseif ($type == 'extensions' && !empty($plugins[$plugin]['load'])) {
$settings['extensions'][$plugin] = 1;
}
// Allow plugins to add valid HTML elements.
@@ -265,7 +301,7 @@ function wysiwyg_tinymce_settings($editor, $config, $theme) {
$settings += array(
'theme_advanced_resize_horizontal' => FALSE,
'theme_advanced_resizing_use_cookie' => FALSE,
- 'theme_advanced_path_location' => isset($config['path_loc']) ? $config['path_loc'] : 'bottom',
+ 'theme_advanced_statusbar_location' => isset($config['path_loc']) ? $config['path_loc'] : 'bottom',
'theme_advanced_resizing' => isset($config['resizing']) ? $config['resizing'] : 1,
'theme_advanced_toolbar_location' => isset($config['toolbar_loc']) ? $config['toolbar_loc'] : 'top',
'theme_advanced_toolbar_align' => isset($config['toolbar_align']) ? $config['toolbar_align'] : 'left',
@@ -358,7 +394,7 @@ function _wysiwyg_tinymce_plugin_name($op, $name) {
}
return $name;
}
- else if ($op == 'remove') {
+ elseif ($op == 'remove') {
if (strpos($name, '-') === 0) {
return substr($name, 1);
}
@@ -383,6 +419,8 @@ function wysiwyg_tinymce_plugins($editor) {
'link' => t('Link'), 'unlink' => t('Unlink'), 'anchor' => t('Anchor'),
'image' => t('Image'),
'cleanup' => t('Clean-up'),
+ 'formatselect' => t('Block format'), 'styleselect' => t('Styles'),
+ 'fontselect' => t('Font'), 'fontsizeselect' => t('Font size'),
'forecolor' => t('Forecolor'), 'backcolor' => t('Backcolor'),
'sup' => t('Superscript'), 'sub' => t('Subscript'),
'blockquote' => t('Blockquote'), 'code' => t('Source code'),
@@ -399,15 +437,15 @@ function wysiwyg_tinymce_plugins($editor) {
'path' => $editor['library path'] . '/plugins/advhr',
'buttons' => array('advhr' => t('Advanced horizontal rule')),
'extended_valid_elements' => array('hr[class|width|size|noshade]'),
- 'url' => 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advhr',
+ 'url' => 'http://www.tinymce.com/wiki.php/Plugin:advhr',
'internal' => TRUE,
'load' => TRUE,
),
'advimage' => array(
'path' => $editor['library path'] . '/plugins/advimage',
'extensions' => array('advimage' => t('Advanced image')),
- 'extended_valid_elements' => array('img[src|alt|title|align|width|height|usemap|hspace|vspace|border|style|class|onmouseover|onmouseout|id|name]'),
- 'url' => 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advimage',
+ 'extended_valid_elements' => array('img[src|alt|title|align|width|height|usemap|hspace|vspace|border|style|class|onmouseover|onmouseout|id|name|longdesc]'),
+ 'url' => 'http://www.tinymce.com/wiki.php/Plugin:advimage',
'internal' => TRUE,
'load' => TRUE,
),
@@ -415,49 +453,42 @@ function wysiwyg_tinymce_plugins($editor) {
'path' => $editor['library path'] . '/plugins/advlink',
'extensions' => array('advlink' => t('Advanced link')),
'extended_valid_elements' => array('a[name|href|target|title|class|onfocus|onblur|onclick|ondlbclick|onmousedown|onmouseup|onmouseover|onmouseout|onkeypress|onkeydown|onkeyup|id|style|rel]'),
- 'url' => 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advlink',
+ 'url' => 'http://www.tinymce.com/wiki.php/Plugin:advlink',
'internal' => TRUE,
'load' => TRUE,
),
'autosave' => array(
'path' => $editor['library path'] . '/plugins/autosave',
'extensions' => array('autosave' => t('Auto save')),
- 'url' => 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/autosave',
+ 'url' => 'http://www.tinymce.com/wiki.php/Plugin:autosave',
'internal' => TRUE,
'load' => TRUE,
),
'contextmenu' => array(
'path' => $editor['library path'] . '/plugins/contextmenu',
'extensions' => array('contextmenu' => t('Context menu')),
- 'url' => 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/contextmenu',
+ 'url' => 'http://www.tinymce.com/wiki.php/Plugin:contextmenu',
'internal' => TRUE,
'load' => TRUE,
),
'directionality' => array(
'path' => $editor['library path'] . '/plugins/directionality',
'buttons' => array('ltr' => t('Left-to-right'), 'rtl' => t('Right-to-left')),
- 'url' => 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/directionality',
+ 'url' => 'http://www.tinymce.com/wiki.php/Plugin:directionality',
'internal' => TRUE,
'load' => TRUE,
),
'emotions' => array(
'path' => $editor['library path'] . '/plugins/emotions',
'buttons' => array('emotions' => t('Emotions')),
- 'url' => 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/emotions',
+ 'url' => 'http://www.tinymce.com/wiki.php/Plugin:emotions',
'internal' => TRUE,
'load' => TRUE,
),
- 'font' => array(
- 'path' => $editor['library path'] . '/plugins/font',
- 'buttons' => array('formatselect' => t('HTML block format'), 'fontselect' => t('Font'), 'fontsizeselect' => t('Font size'), 'styleselect' => t('Font style')),
- 'extended_valid_elements' => array('font[face|size|color|style],span[class|align|style]'),
- 'url' => 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/font',
- 'internal' => TRUE,
- ),
'fullscreen' => array(
'path' => $editor['library path'] . '/plugins/fullscreen',
'buttons' => array('fullscreen' => t('Fullscreen')),
- 'url' => 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/fullscreen',
+ 'url' => 'http://www.tinymce.com/wiki.php/Plugin:fullscreen',
'internal' => TRUE,
'load' => TRUE,
),
@@ -467,7 +498,7 @@ function wysiwyg_tinymce_plugins($editor) {
'options' => array(
'dialog_type' => array('modal'),
),
- 'url' => 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/inlinepopups',
+ 'url' => 'http://www.tinymce.com/wiki.php/Plugin:inlinepopups',
'internal' => TRUE,
'load' => TRUE,
),
@@ -478,56 +509,56 @@ function wysiwyg_tinymce_plugins($editor) {
'plugin_insertdate_dateFormat' => '%Y-%m-%d',
'plugin_insertdate_timeFormat' => '%H:%M:%S',
),
- 'url' => 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/insertdatetime',
+ 'url' => 'http://www.tinymce.com/wiki.php/Plugin:insertdatetime',
'internal' => TRUE,
'load' => TRUE,
),
'layer' => array(
'path' => $editor['library path'] . '/plugins/layer',
'buttons' => array('insertlayer' => t('Insert layer'), 'moveforward' => t('Move forward'), 'movebackward' => t('Move backward'), 'absolute' => t('Absolute')),
- 'url' => 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/layer',
+ 'url' => 'http://www.tinymce.com/wiki.php/Plugin:layer',
'internal' => TRUE,
'load' => TRUE,
),
'paste' => array(
'path' => $editor['library path'] . '/plugins/paste',
'buttons' => array('pastetext' => t('Paste text'), 'pasteword' => t('Paste from Word'), 'selectall' => t('Select all')),
- 'url' => 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/paste',
+ 'url' => 'http://www.tinymce.com/wiki.php/Plugin:paste',
'internal' => TRUE,
'load' => TRUE,
),
'preview' => array(
'path' => $editor['library path'] . '/plugins/preview',
'buttons' => array('preview' => t('Preview')),
- 'url' => 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/preview',
+ 'url' => 'http://www.tinymce.com/wiki.php/Plugin:preview',
'internal' => TRUE,
'load' => TRUE,
),
'print' => array(
'path' => $editor['library path'] . '/plugins/print',
'buttons' => array('print' => t('Print')),
- 'url' => 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/print',
+ 'url' => 'http://www.tinymce.com/wiki.php/Plugin:print',
'internal' => TRUE,
'load' => TRUE,
),
'searchreplace' => array(
'path' => $editor['library path'] . '/plugins/searchreplace',
'buttons' => array('search' => t('Search'), 'replace' => t('Replace')),
- 'url' => 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/searchreplace',
+ 'url' => 'http://www.tinymce.com/wiki.php/Plugin:searchreplace',
'internal' => TRUE,
'load' => TRUE,
),
'style' => array(
'path' => $editor['library path'] . '/plugins/style',
- 'buttons' => array('styleprops' => t('Style properties')),
- 'url' => 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/style',
+ 'buttons' => array('styleprops' => t('Advanced CSS styles')),
+ 'url' => 'http://www.tinymce.com/wiki.php/Plugin:style',
'internal' => TRUE,
'load' => TRUE,
),
'table' => array(
'path' => $editor['library path'] . '/plugins/table',
'buttons' => array('tablecontrols' => t('Table')),
- 'url' => 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/table',
+ 'url' => 'http://www.tinymce.com/wiki.php/Plugin:table',
'internal' => TRUE,
'load' => TRUE,
),
@@ -537,7 +568,6 @@ function wysiwyg_tinymce_plugins($editor) {
'path' => $editor['library path'] . '/plugins/flash',
'buttons' => array('flash' => t('Flash')),
'extended_valid_elements' => array('img[class|src|alt|title|hspace|vspace|width|height|align|onmouseover|onmouseout|name|obj|param|embed]'),
- 'url' => 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/flash',
'internal' => TRUE,
'load' => TRUE,
);
@@ -546,14 +576,14 @@ function wysiwyg_tinymce_plugins($editor) {
$plugins['media'] = array(
'path' => $editor['library path'] . '/plugins/media',
'buttons' => array('media' => t('Media')),
- 'url' => 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/media',
+ 'url' => 'http://www.tinymce.com/wiki.php/Plugin:media',
'internal' => TRUE,
'load' => TRUE,
);
$plugins['xhtmlxtras'] = array(
'path' => $editor['library path'] . '/plugins/xhtmlxtras',
'buttons' => array('cite' => t('Citation'), 'del' => t('Deleted'), 'abbr' => t('Abbreviation'), 'acronym' => t('Acronym'), 'ins' => t('Inserted'), 'attribs' => t('HTML attributes')),
- 'url' => 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/xhtmlxtras',
+ 'url' => 'http://www.tinymce.com/wiki.php/Plugin:xhtmlxtras',
'internal' => TRUE,
'load' => TRUE,
);
@@ -562,7 +592,7 @@ function wysiwyg_tinymce_plugins($editor) {
$plugins['bbcode'] = array(
'path' => $editor['library path'] . '/plugins/bbcode',
'extensions' => array('bbcode' => t('BBCode')),
- 'url' => 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/bbcode',
+ 'url' => 'http://www.tinymce.com/wiki.php/Plugin:bbcode',
'internal' => TRUE,
'load' => TRUE,
);
@@ -570,7 +600,6 @@ function wysiwyg_tinymce_plugins($editor) {
$plugins['safari'] = array(
'path' => $editor['library path'] . '/plugins/safari',
'extensions' => array('safari' => t('Safari compatibility')),
- 'url' => 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/safari',
'internal' => TRUE,
'load' => TRUE,
);
@@ -580,7 +609,7 @@ function wysiwyg_tinymce_plugins($editor) {
$plugins['autoresize'] = array(
'path' => $editor['library path'] . '/plugins/autoresize',
'extensions' => array('autoresize' => t('Auto resize')),
- 'url' => 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/autoresize',
+ 'url' => 'http://www.tinymce.com/wiki.php/Plugin:autoresize',
'internal' => TRUE,
'load' => TRUE,
);
@@ -589,7 +618,7 @@ function wysiwyg_tinymce_plugins($editor) {
$plugins['advlist'] = array(
'path' => $editor['library path'] . '/plugins/advlist',
'extensions' => array('advlist' => t('Advanced list')),
- 'url' => 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advlist',
+ 'url' => 'http://www.tinymce.com/wiki.php/Plugin:advlist',
'internal' => TRUE,
'load' => TRUE,
);
@@ -598,11 +627,24 @@ function wysiwyg_tinymce_plugins($editor) {
$plugins['wordcount'] = array(
'path' => $editor['library path'] . '/plugins/wordcount',
'extensions' => array('wordcount' => t('Word count')),
- 'url' => 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/wordcount',
'internal' => TRUE,
'load' => TRUE,
);
}
+ if (version_compare($editor['installed version'], '3.4.1', '>=')) {
+ $plugins['lists'] = array(
+ 'path' => $editor['library path'] . 'plugins/lists',
+ 'extensions' => array('lists' => t('List normalizer')),
+ 'url' => 'http://www.tinymce.com/wiki.php/Plugin:lists',
+ 'internal' => TRUE,
+ 'load' => TRUE,
+ 'extended_valid_elements' => array(
+ 'li[class|dir|id|lang|onclick|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style|title|type|value]',
+ 'ol[class|compact|dir|id|lang|onclick|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|start|style|title|type]',
+ 'ul[class|compact|dir|id|lang|onclick|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style|title|type]',
+ ),
+ );
+ }
return $plugins;
}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/whizzywig.inc b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/whizzywig.inc
index d82cc0f..acfc7de 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/whizzywig.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/whizzywig.inc
@@ -104,13 +104,13 @@ function wysiwyg_whizzywig_settings($editor, $config, $theme) {
// Add editor content stylesheet.
if (isset($config['css_setting'])) {
if ($config['css_setting'] == 'theme') {
- $css = path_to_theme() . '/style.css';
+ $css = drupal_get_path('theme', variable_get('theme_default', NULL)) . '/style.css';
if (file_exists($css)) {
$settings['externalCSS'] = base_path() . $css;
}
}
- else if ($config['css_setting'] == 'self' && isset($config['css_path'])) {
- $settings['externalCSS'] = strtr($config['css_path'], array('%b' => base_path(), '%t' => path_to_theme()));
+ elseif ($config['css_setting'] == 'self' && isset($config['css_path'])) {
+ $settings['externalCSS'] = strtr($config['css_path'], array('%b' => base_path(), '%t' => drupal_get_path('theme', variable_get('theme_default', NULL))));
}
}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/wymeditor.inc b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/wymeditor.inc
index 3e8ffd2..5f44d64 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/wymeditor.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/wymeditor.inc
@@ -172,10 +172,11 @@ function wysiwyg_wymeditor_settings($editor, $config, $theme) {
if (isset($config['css_setting'])) {
if ($config['css_setting'] == 'theme') {
// WYMeditor only supports one CSS file currently.
- $settings['stylesheet'] = reset(wysiwyg_get_css());
+ $css = wysiwyg_get_css();
+ $settings['stylesheet'] = reset($css);
}
- else if ($config['css_setting'] == 'self' && isset($config['css_path'])) {
- $settings['stylesheet'] = strtr($config['css_path'], array('%b' => base_path(), '%t' => path_to_theme()));
+ elseif ($config['css_setting'] == 'self' && isset($config['css_path'])) {
+ $settings['stylesheet'] = strtr($config['css_path'], array('%b' => base_path(), '%t' => drupal_get_path('theme', variable_get('theme_default', NULL))));
}
}
@@ -190,7 +191,7 @@ function wysiwyg_wymeditor_plugins($editor) {
'default' => array(
'buttons' => array(
'Bold' => t('Bold'), 'Italic' => t('Italic'),
- 'InsertOrderedList' => t('Bullet list'), 'InsertUnorderedList' => t('Numbered list'),
+ 'InsertOrderedList' => t('Numbered list'), 'InsertUnorderedList' => t('Bullet list'),
'Outdent' => t('Outdent'), 'Indent' => t('Indent'),
'Undo' => t('Undo'), 'Redo' => t('Redo'),
'CreateLink' => t('Link'), 'Unlink' => t('Unlink'),
@@ -212,22 +213,22 @@ function wysiwyg_wymeditor_plugins($editor) {
*/
function _wysiwyg_wymeditor_button_info() {
return array(
- 'Bold' => array('title'=> 'Strong', 'css'=> 'wym_tools_strong'),
- 'Italic' => array('title'=> 'Emphasis', 'css'=> 'wym_tools_emphasis'),
- 'Superscript' => array('title'=> 'Superscript', 'css'=> 'wym_tools_superscript'),
- 'Subscript' => array('title'=> 'Subscript', 'css'=> 'wym_tools_subscript'),
- 'InsertOrderedList' => array('title'=> 'Ordered_List', 'css'=> 'wym_tools_ordered_list'),
- 'InsertUnorderedList' => array('title'=> 'Unordered_List', 'css'=> 'wym_tools_unordered_list'),
- 'Indent' => array('title'=> 'Indent', 'css'=> 'wym_tools_indent'),
- 'Outdent' => array('title'=> 'Outdent', 'css'=> 'wym_tools_outdent'),
- 'Undo' => array('title'=> 'Undo', 'css'=> 'wym_tools_undo'),
- 'Redo' => array('title'=> 'Redo', 'css'=> 'wym_tools_redo'),
- 'CreateLink' => array('title'=> 'Link', 'css'=> 'wym_tools_link'),
- 'Unlink' => array('title'=> 'Unlink', 'css'=> 'wym_tools_unlink'),
- 'InsertImage' => array('title'=> 'Image', 'css'=> 'wym_tools_image'),
- 'InsertTable' => array('title'=> 'Table', 'css'=> 'wym_tools_table'),
- 'Paste' => array('title'=> 'Paste_From_Word', 'css'=> 'wym_tools_paste'),
- 'ToggleHtml' => array('title'=> 'HTML', 'css'=> 'wym_tools_html'),
- 'Preview' => array('title'=> 'Preview', 'css'=> 'wym_tools_preview'),
+ 'Bold' => array('title' => 'Strong', 'css' => 'wym_tools_strong'),
+ 'Italic' => array('title' => 'Emphasis', 'css' => 'wym_tools_emphasis'),
+ 'Superscript' => array('title' => 'Superscript', 'css' => 'wym_tools_superscript'),
+ 'Subscript' => array('title' => 'Subscript', 'css' => 'wym_tools_subscript'),
+ 'InsertOrderedList' => array('title' => 'Ordered_List', 'css' => 'wym_tools_ordered_list'),
+ 'InsertUnorderedList' => array('title' => 'Unordered_List', 'css' => 'wym_tools_unordered_list'),
+ 'Indent' => array('title' => 'Indent', 'css' => 'wym_tools_indent'),
+ 'Outdent' => array('title' => 'Outdent', 'css' => 'wym_tools_outdent'),
+ 'Undo' => array('title' => 'Undo', 'css' => 'wym_tools_undo'),
+ 'Redo' => array('title' => 'Redo', 'css' => 'wym_tools_redo'),
+ 'CreateLink' => array('title' => 'Link', 'css' => 'wym_tools_link'),
+ 'Unlink' => array('title' => 'Unlink', 'css' => 'wym_tools_unlink'),
+ 'InsertImage' => array('title' => 'Image', 'css' => 'wym_tools_image'),
+ 'InsertTable' => array('title' => 'Table', 'css' => 'wym_tools_table'),
+ 'Paste' => array('title' => 'Paste_From_Word', 'css' => 'wym_tools_paste'),
+ 'ToggleHtml' => array('title' => 'HTML', 'css' => 'wym_tools_html'),
+ 'Preview' => array('title' => 'Preview', 'css' => 'wym_tools_preview'),
);
}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/yui.inc b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/yui.inc
index 7e3c697..36d0a59 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/yui.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/editors/yui.inc
@@ -45,6 +45,14 @@ function wysiwyg_yui_editor() {
'load callback' => 'wysiwyg_yui_load',
'settings callback' => 'wysiwyg_yui_settings',
'plugin callback' => 'wysiwyg_yui_plugins',
+ 'plugin settings callback' => 'wysiwyg_yui_plugin_settings',
+ 'proxy plugin' => array(
+ 'drupal' => array(
+ 'load' => TRUE,
+ 'proxy' => TRUE,
+ ),
+ ),
+ 'proxy plugin settings callback' => 'wysiwyg_yui_proxy_plugin_settings',
'versions' => array(
'2.7.0' => array(
'js files' => array('yui.js'),
@@ -177,7 +185,7 @@ function wysiwyg_yui_settings($editor, $config, $theme) {
}
}
}
- else if ($button == 'fontname') {
+ elseif ($button == 'fontname') {
$extra = array('menu' => array(
array('text' => 'Arial', 'checked' => TRUE),
array('text' => 'Arial Black'),
@@ -202,8 +210,8 @@ function wysiwyg_yui_settings($editor, $config, $theme) {
if ($config['css_setting'] == 'theme') {
$settings['extracss'] = wysiwyg_get_css();
}
- else if ($config['css_setting'] == 'self' && isset($config['css_path'])) {
- $settings['extracss'] = strtr($config['css_path'], array('%b' => base_path(), '%t' => path_to_theme()));
+ elseif ($config['css_setting'] == 'self' && isset($config['css_path'])) {
+ $settings['extracss'] = strtr($config['css_path'], array('%b' => base_path(), '%t' => drupal_get_path('theme', variable_get('theme_default', NULL))));
$settings['extracss'] = explode(',', $settings['extracss']);
}
// YUI only supports inline CSS, so we need to use @import directives.
@@ -233,8 +241,7 @@ function wysiwyg_yui_button_setting($editor, $plugin, $button, $extra = array())
static $plugins;
if (!isset($plugins)) {
- // @todo Invoke all enabled plugins, not just internals.
- $plugins = wysiwyg_yui_plugins($editor);
+ $plugins = wysiwyg_get_plugins($editor['name']);
}
// Return a simple separator.
@@ -270,6 +277,41 @@ function wysiwyg_yui_button_setting($editor, $plugin, $button, $extra = array())
}
/**
+ * Build a JS settings array of native external plugins that need to be loaded separately.
+ */
+function wysiwyg_yui_plugin_settings($editor, $profile, $plugins) {
+ $settings = array();
+ foreach ($plugins as $name => $plugin) {
+ if (!empty($plugin['load'])) {
+ // Add path for native external plugins; internal ones are loaded
+ // automatically.
+ if (empty($plugin['internal']) && isset($plugin['path'])) {
+ $settings[$name] = base_path() . $plugin['path'];
+ }
+ }
+ }
+ return $settings;
+}
+
+/**
+ * Build a JS settings array for Drupal plugins loaded via the proxy plugin.
+ */
+function wysiwyg_yui_proxy_plugin_settings($editor, $profile, $plugins) {
+ $settings = array();
+ foreach ($plugins as $name => $plugin) {
+ // Populate required plugin settings.
+ $settings[$name] = $plugin['dialog settings'] + array(
+ 'title' => $plugin['title'],
+ 'icon' => base_path() . $plugin['icon path'] . '/' . $plugin['icon file'],
+ 'iconTitle' => $plugin['icon title'],
+ // @todo These should only be set if the plugin defined them.
+ 'css' => base_path() . $plugin['css path'] . '/' . $plugin['css file'],
+ );
+ }
+ return $settings;
+}
+
+/**
* Return internal plugins for this editor; semi-implementation of hook_wysiwyg_plugin().
*/
function wysiwyg_yui_plugins($editor) {
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/tests/wysiwyg_test.info b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/tests/wysiwyg_test.info
index 1314897..feee124 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/tests/wysiwyg_test.info
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/tests/wysiwyg_test.info
@@ -6,9 +6,9 @@ hidden = TRUE
dependencies[] = wysiwyg
files[] = wysiwyg_test.module
-; Information added by drupal.org packaging script on 2011-06-19
-version = "7.x-2.1"
+; Information added by drupal.org packaging script on 2012-10-02
+version = "7.x-2.2"
core = "7.x"
project = "wysiwyg"
-datestamp = "1308450722"
+datestamp = "1349213776"
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/tests/wysiwyg_test.module b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/tests/wysiwyg_test.module
index c908e29..c2dd9a9 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/tests/wysiwyg_test.module
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/tests/wysiwyg_test.module
@@ -5,3 +5,46 @@
* Testing functionality for Wysiwyg module.
*/
+/**
+ * Implements hook_menu().
+ */
+function wysiwyg_test_menu() {
+ $items['wysiwyg-test/ajax'] = array(
+ 'title' => 'Ajaxified form',
+ 'page callback' => 'drupal_get_form',
+ 'page arguments' => array('wysiwyg_test_ajax_form'),
+ 'access callback' => TRUE,
+ );
+ return $items;
+}
+
+/**
+ * Form constructor for an ajaxified form lazy-loading a textarea.
+ */
+function wysiwyg_test_ajax_form($form, &$form_state) {
+ $form['enable'] = array(
+ '#type' => 'checkbox',
+ '#title' => 'Load textarea',
+ '#ajax' => array(
+ 'callback' => 'wysiwyg_test_ajax_form_callback',
+ 'wrapper' => 'ajax-wrapper',
+ ),
+ );
+ $form['wrapper'] = array(
+ '#type' => 'container',
+ '#id' => 'ajax-wrapper',
+ );
+ return $form;
+}
+
+/**
+ * #ajax callback for wysiwyg_test_ajax_form().
+ */
+function wysiwyg_test_ajax_form_callback($form, &$form_state) {
+ $form['body'] = array(
+ '#type' => 'text_format',
+ '#default_value' => '',
+ );
+ form_builder($form['form_id']['#value'], $form, $form_state);
+ return $form['body'];
+}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg-dialog-page.tpl.php b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg-dialog-page.tpl.php
index 0811ae7..3e77d79 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg-dialog-page.tpl.php
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg-dialog-page.tpl.php
@@ -2,83 +2,27 @@
/**
* @file
- * Theme template to display a single Wysiwyg (plugin) dialog page.
- *
- * Available variables:
- *
- * General utility variables:
- * - $base_path: The base URL path of the Drupal installation. At the very
- * least, this will always default to /.
- * - $css: An array of CSS files for the current page.
- * - $directory: The directory the theme is located in, e.g. themes/garland or
- * themes/garland/minelli.
- * - $logged_in: TRUE if the user is registered and signed in.
- * - $is_admin: TRUE if the user has permission to access administration pages.
- *
- * Page metadata:
- * - $language: (object) The language the site is being displayed in.
- * $language->language contains its textual representation.
- * $language->dir contains the language direction. It will either be 'ltr' or 'rtl'.
- * - $head_title: A modified version of the page title, for use in the TITLE tag.
- * - $head: Markup for the HEAD section (including meta tags, keyword tags, and
- * so on).
- * - $styles: Style tags necessary to import all CSS files for the page.
- * - $scripts: Script tags necessary to load the JavaScript files and settings
- * for the page.
- *
- * Site identity:
- * - $site_name: The name of the site, empty when display has been disabled
- * in theme settings.
- *
- * Page content (in order of occurrance in the default page.tpl.php):
- * - $breadcrumb: The breadcrumb trail for the current page.
- * - $title: The page title, for use in the actual HTML content.
- * - $help: Dynamic help text, mostly for admin pages.
- * - $messages: HTML for status and error messages. Should be displayed prominently.
- * - $tabs: Tabs linking to any sub-pages beneath the current page (e.g., the view
- * and edit tabs when displaying a node).
- *
- * - $content: The main content of the current Drupal page.
- *
- * Footer/closing data:
- * - $footer : The footer region.
- * - $closure: Final closing markup from any modules that have altered the page.
- * This variable should always be output last, after all other dynamic content.
- *
- * @see template_preprocess()
- * @see template_preprocess_wysiwyg_dialog_page()
+ * Theme implementation to display a single Wysiwyg (plugin) dialog page.
*/
?>
-<!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" xml:lang="<?php print $language->language ?>" lang="<?php print $language->language ?>" dir="<?php print $language->dir ?>">
-<head>
- <title><?php print $head_title; ?></title>
- <?php print $head; ?>
- <?php print $styles; ?>
- <?php print $scripts; ?>
- <script type="text/javascript"><?php /* Needed to avoid Flash of Unstyled Content in IE */ ?> </script>
-</head>
-<body>
<div id="page">
- <div id="container" class="clear-block">
- <div id="main" class="column">
- <?php if (!empty($breadcrumb)): ?><div id="breadcrumb"><?php print $breadcrumb; ?></div><?php endif; ?>
- <div id="content">
- <?php if (!empty($title)): ?><h1 class="title" id="page-title"><?php print $title; ?></h1><?php endif; ?>
- <?php if (!empty($tabs)): ?><div class="tabs"><?php print $tabs; ?></div><?php endif; ?>
- <?php if (!empty($messages)): print $messages; endif; ?>
- <?php if (!empty($help)): print $help; endif; ?>
- <div id="content-content" class="clear-block">
- <?php print $content; ?>
- </div>
- </div>
+ <?php print $messages; ?>
- </div>
- </div>
- </div>
-<?php print $closure; ?>
-</body>
-</html>
+ <div id="main-wrapper"><div id="main" class="clearfix">
+
+ <div id="content" class="column"><div class="section">
+ <a id="main-content"></a>
+ <?php print render($title_prefix); ?>
+ <?php if ($title): ?><h1 class="title" id="page-title"><?php print $title; ?></h1><?php endif; ?>
+ <?php print render($title_suffix); ?>
+ <?php if ($tabs): ?><div class="tabs"><?php print render($tabs); ?></div><?php endif; ?>
+ <?php print render($page['help']); ?>
+ <?php if ($action_links): ?><ul class="action-links"><?php print render($action_links); ?></ul><?php endif; ?>
+ <?php print render($page['content']); ?>
+ </div></div> <!-- /.section, /#content -->
+
+ </div></div> <!-- /#main, /#main-wrapper -->
+
+ </div> <!-- /#page -->
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.admin.inc b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.admin.inc
index 510e1e3..497e5d4 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.admin.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.admin.inc
@@ -135,21 +135,22 @@ function wysiwyg_profile_form($form, &$form_state, $profile) {
}
$icon = file_exists($img_src) ? '<img src="' . base_path() . $img_src . '" title="' . $button . '" style="border: 1px solid grey; vertical-align: middle;" />' : '';
}
- $title = (isset($meta['url']) ? l($title, $meta['url'], array('target' => '_blank')) : $title);
- $title = (!empty($icon) ? $icon . ' ' . $title : $title);
+ $title = (!empty($icon) ? $icon . ' ' . check_plain($title) : check_plain($title));
$form['buttons'][$name][$button] = array(
'#type' => 'checkbox',
'#title' => $title,
'#default_value' => !empty($profile->settings['buttons'][$name][$button]) ? $profile->settings['buttons'][$name][$button] : FALSE,
+ '#description' => isset($meta['url']) ? l($meta['url'], $meta['url']) : NULL,
);
}
}
- else if (isset($meta['extensions']) && is_array($meta['extensions'])) {
+ elseif (isset($meta['extensions']) && is_array($meta['extensions'])) {
foreach ($meta['extensions'] as $extension => $title) {
$form['buttons'][$name][$extension] = array(
'#type' => 'checkbox',
- '#title' => isset($meta['url']) ? l($title, $meta['url'], array('target' => '_blank')) : $title,
+ '#title' => check_plain($title),
'#default_value' => !empty($profile->settings['buttons'][$name][$extension]) ? $profile->settings['buttons'][$name][$extension] : FALSE,
+ '#description' => isset($meta['url']) ? l($meta['url'], $meta['url']) : NULL,
);
}
}
@@ -299,6 +300,19 @@ function wysiwyg_profile_form($form, &$form_state, $profile) {
'#weight' => 110,
);
+ // Supply contextual information for other callbacks and handlers.
+ // @todo Modernize this form for D7+ and declare these earlier.
+ // $profile is the primary object of this form, and as an entity, usually
+ // expected to live in $form_state[$entity_type].
+ $form_state['wysiwyg_profile'] = $profile;
+ $form_state['wysiwyg']['editor'] = $editor;
+ $form_state['wysiwyg']['plugins'] = $plugins;
+
+ // Allow editor library specific changes to be made to the form.
+ if (isset($editor['settings form callback'])) {
+ $editor['settings form callback']($form, $form_state);
+ }
+
return $form;
}
@@ -363,14 +377,11 @@ function theme_wysiwyg_admin_button_table($variables) {
// Split checkboxes into rows with 3 columns.
$total = count($buttons);
$rows = array();
- for ($i = 0; $i < $total; $i++) {
+ for ($i = 0; $i < $total; $i += 3) {
$row = array();
- $row[] = array('data' => $buttons[$i]);
- if (isset($buttons[++$i])) {
- $row[] = array('data' => $buttons[$i]);
- }
- if (isset($buttons[++$i])) {
- $row[] = array('data' => $buttons[$i]);
+ $row_buttons = array_slice($buttons, $i, 3) + array_fill(0, 3, array());
+ foreach ($row_buttons as $row_button) {
+ $row[] = array('data' => $row_button);
}
$rows[] = $row;
}
@@ -416,6 +427,11 @@ function wysiwyg_profile_overview($form, &$form_state) {
$instructions = '<p>' . t('Extract the archive and copy its contents into a new folder in the following location:<br /><code>@editor-path</code>', $targs) . '</p>';
$instructions .= '<p>' . t('So the actual library can be found at:<br /><code>@library-filepath</code>', $targs) . '</p>';
+ // Add any install notes.
+ if (!empty($editor['install note callback']) && function_exists($editor['install note callback'])) {
+ $instructions .= '<div class="editor-install-note">' . $editor['install note callback']() . '</div>';
+ }
+
$status[$name]['description'] .= $instructions;
$count--;
}
@@ -457,9 +473,20 @@ function wysiwyg_profile_overview($form, &$form_state) {
// Only display editor selection for associated input formats to avoid
// confusion about disabled selection.
if (isset($profiles[$id]) && !empty($profiles[$id]->editor)) {
+ $editor_name = $profiles[$id]->editor;
+ $installed = !empty($editors[$editor_name]['installed']);
$form['formats'][$id]['editor'] = array(
- '#markup' => $options[$profiles[$id]->editor],
+ '#wysiwyg-editor-name' => $editor_name,
);
+ if ($installed) {
+ $form['formats'][$id]['editor']['#markup'] = $options[$editor_name];
+ }
+ else {
+ drupal_set_message(t('Missing %editor library for %format format. Re-install the %editor library or delete the editor profile.', array(
+ '%editor' => $editors[$editor_name]['title'],
+ '%format' => $format->name,
+ )), 'warning');
+ }
}
else {
$form['formats'][$id]['editor'] = array(
@@ -494,17 +521,28 @@ function theme_wysiwyg_profile_overview($variables) {
if (!isset($form['formats'])) {
return;
}
+ $editors = wysiwyg_get_all_editors();
$output = '';
- $header = array(t('Input format'), t('Editor'), array('data' => t('Operations'), 'colspan' => 2));
+ $header = array(t('Text format'), t('Editor'), array('data' => t('Operations'), 'colspan' => 2));
$rows = array();
foreach (element_children($form['formats']) as $item) {
$format = &$form['formats'][$item];
- $rows[] = array(
- drupal_render($format['name']),
- drupal_render($format['editor']),
- isset($format['edit']) ? drupal_render($format['edit']) : '',
- isset($format['delete']) ? drupal_render($format['delete']) : '',
+ $row = array(
+ 'data' => array(
+ drupal_render($format['name']),
+ drupal_render($format['editor']),
+ isset($format['edit']) ? drupal_render($format['edit']) : '',
+ isset($format['delete']) ? drupal_render($format['delete']) : '',
+ ),
);
+ if (empty($row['data'][1])) {
+ $row['data'][1] = array(
+ 'data' => t('Missing library: @library', array('@library' => $editors[$format['editor']['#wysiwyg-editor-name']]['title'])),
+ 'class' => 'error',
+ );
+ $row['class'] = array('error');
+ }
+ $rows[] = $row;
}
$form['formats']['table']['#markup'] = theme('table', array('header' => $header, 'rows' => $rows));
$output .= drupal_render_children($form);
@@ -554,4 +592,3 @@ function wysiwyg_profile_delete_confirm_submit($form, &$form_state) {
drupal_set_message(t('Wysiwyg profile for %name has been deleted.', array('%name' => $format->name)));
$form_state['redirect'] = 'admin/config/content/wysiwyg';
}
-
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.api.php b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.api.php
index 5f5b839..c4d8857 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.api.php
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.api.php
@@ -173,6 +173,83 @@ function hook_INCLUDE_plugin() {
}
/**
+ * Define a Wysiwyg editor library.
+ *
+ * @todo Complete this documentation.
+ */
+function hook_INCLUDE_editor() {
+ $editor['ckeditor'] = array(
+ // The official, human-readable label of the editor library.
+ 'title' => 'CKEditor',
+ // The URL to the library's homepage.
+ 'vendor url' => 'http://ckeditor.com',
+ // The URL to the library's download page.
+ 'download url' => 'http://ckeditor.com/download',
+ // A definition of available variants for the editor library.
+ // The first defined is used by default.
+ 'libraries' => array(
+ '' => array(
+ 'title' => 'Default',
+ 'files' => array(
+ 'ckeditor.js' => array('preprocess' => FALSE),
+ ),
+ ),
+ 'src' => array(
+ 'title' => 'Source',
+ 'files' => array(
+ 'ckeditor_source.js' => array('preprocess' => FALSE),
+ ),
+ ),
+ ),
+ // (optional) A callback to invoke to return additional notes for installing
+ // the editor library in the administrative list/overview.
+ 'install note callback' => 'wysiwyg_ckeditor_install_note',
+ // A callback to determine the library's version.
+ 'version callback' => 'wysiwyg_ckeditor_version',
+ // A callback to return available themes/skins for the editor library.
+ 'themes callback' => 'wysiwyg_ckeditor_themes',
+ // (optional) A callback to perform editor-specific adjustments or
+ // enhancements for the administrative editor profile settings form.
+ 'settings form callback' => 'wysiwyg_ckeditor_settings_form',
+ // (optional) A callback to return an initialization JavaScript snippet for
+ // this editor library, loaded before the actual library files. The returned
+ // JavaScript is executed as inline script in a primitive environment,
+ // before the DOM is loaded; typically used to prime a base path and other
+ // global window variables for the editor library before it is loaded.
+ // All implementations should verbosely document what they are doing and
+ // why that is required.
+ 'init callback' => 'wysiwyg_ckeditor_init',
+ // A callback to convert administrative profile/editor settings into
+ // JavaScript settings.
+ 'settings callback' => 'wysiwyg_ckeditor_settings',
+ // A callback to supply definitions of available editor plugins.
+ 'plugin callback' => 'wysiwyg_ckeditor_plugins',
+ // A callback to convert administrative plugin settings for a editor profile
+ // into JavaScript settings.
+ 'plugin settings callback' => 'wysiwyg_ckeditor_plugin_settings',
+ // (optional) Defines the proxy plugin that handles plugins provided by
+ // Drupal modules, which work in all editors that support proxy plugins.
+ 'proxy plugin' => array(
+ 'drupal' => array(
+ 'load' => TRUE,
+ 'proxy' => TRUE,
+ ),
+ ),
+ // (optional) A callback to convert proxy plugin settings into JavaScript
+ // settings.
+ 'proxy plugin settings callback' => 'wysiwyg_ckeditor_proxy_plugin_settings',
+ // Defines the list of supported (minimum) versions of the editor library,
+ // and the respective Drupal integration files to load.
+ 'versions' => array(
+ '3.0.0.3665' => array(
+ 'js files' => array('ckeditor-3.0.js'),
+ ),
+ ),
+ );
+ return $editor;
+}
+
+/**
* Act on editor profile settings.
*
* This hook is invoked from wysiwyg_get_editor_config() after the JavaScript
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.dialog.inc b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.dialog.inc
index 500f78d..c296d2e 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.dialog.inc
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.dialog.inc
@@ -6,7 +6,68 @@
*/
/**
- * Menu callback; Output a wysiwyg plugin dialog page.
+ * Page callback; Outputs a dialog page for a wysiwyg plugin.
+ *
+ * A Wysiwyg dialog is a bare minimum, simple HTML page; presented in a
+ * modal/popup window, triggered via JavaScript.
+ *
+ * However, Drupal core does not support such a concept, at all.
+ * Insanity happens on two separate layers:
+ * - All HTML pages go through the default delivery callback of
+ * drupal_deliver_html_page(), which calls into drupal_render_page(), which
+ * in turn *unconditionally* invokes hook_page_build() implementations. Thus,
+ * block_page_build() and similar implementations add the entirety of their
+ * page regions and blocks to our simple dialog page.
+ * Obviously, we don't want that.
+ * - There is a nice default 'page' theme template implementation, which
+ * performs all the heavy-lifting that is required for outputting a sane HTML
+ * page through preprocess and process functions. The theme system does not
+ * support to "inherit" preprocess and process hooks to alternative
+ * implementations. Even a very basic HTML page requires almost all of that.
+ * However, the default page template (normally overridden by a theme)
+ * contains too many regions and usually also huge a header and footer.
+ * Obviously, we don't want that.
+ *
+ * The poor workaround would be to follow the Overlay module's implementation in
+ * core: override the theme, build everything, and after doing all of that,
+ * strip away what isn't needed. Obviously, we don't want that.
+ *
+ * Instead, we bend Drupal to sane rules:
+ * - This page callback returns the actual main content.
+ * - wysiwyg_menu() defines a custom delivery callback that replaces
+ * drupal_deliver_html_page(), just because we need to replace
+ * drupal_render_page().
+ * - Our replacement for drupal_render_page() builds a $page that does not use
+ * #type 'page' but #type 'wysiwyg_dialog_page' instead.
+ * - #type 'wysiwyg_dialog_page' is defined like #type 'page' in
+ * system_element_info(), but is required, because there's no way to inherit
+ * a theme definition but override the page template file to be used.
+ * - As a consequence, #type 'wysiwyg_dialog_page' uses
+ * #theme 'wysiwyg_dialog_page', for which we have to implement stub
+ * preprocess and process callbacks in order to call into the ones for
+ * #theme 'page'.
+ *
+ * As a result we get:
+ * - A HTML response.
+ * - A HTML page wrapped into html.tpl.php.
+ * - A page title, title prefix/suffix, messages, help, etc.pp.
+ * - A simple page without regions and blocks (neither built nor rendered).
+ *
+ * @see wysiwyg_menu()
+ * @see wysiwyg_deliver_dialog_page
+ * @see wysiwyg_render_dialog_page()
+ * @see wysiwyg_element_info()
+ * @see wysiwyg_theme()
+ * @see template_preprocess_wysiwyg_dialog_page()
+ * @see template_process_wysiwyg_dialog_page()
+ *
+ * @see drupal_deliver_page()
+ * @see drupal_deliver_html_page()
+ * @see drupal_render_page()
+ * @see system_element_info()
+ * @see drupal_common_theme()
+ * @see template_preprocess_page()
+ * @see template_process_page()
*/
function wysiwyg_dialog($plugin, $instance) {
$plugins = wysiwyg_get_all_plugins();
@@ -27,7 +88,74 @@ function wysiwyg_dialog($plugin, $instance) {
);
drupal_add_js(array('wysiwyg' => $settings), 'setting');
- echo theme('wysiwyg_dialog_page', $callback($instance));
+ $build = $callback($instance);
+ if (!is_array($build)) {
+ $build = array('#markup' => $build);
+ }
+ $build += array(
+ '#instance' => $instance,
+ '#plugin' => $plugin,
+ );
+ return $build;
+}
+
+/**
+ * @see drupal_deliver_html_page()
+ */
+function wysiwyg_deliver_dialog_page($page_callback_result) {
+ // Menu status constants are integers; page content is a string or array.
+ if (is_int($page_callback_result)) {
+ return drupal_deliver_html_page($page_callback_result);
+ }
+
+ // Emit the correct charset HTTP header, but not if the page callback
+ // result is NULL, since that likely indicates that it printed something
+ // in which case, no further headers may be sent, and not if code running
+ // for this page request has already set the content type header.
+ if (isset($page_callback_result) && is_null(drupal_get_http_header('Content-Type'))) {
+ drupal_add_http_header('Content-Type', 'text/html; charset=utf-8');
+ }
+
+ // Send appropriate HTTP-Header for browsers and search engines.
+ global $language;
+ drupal_add_http_header('Content-Language', $language->language);
+
+ if (isset($page_callback_result)) {
+ // Print anything besides a menu constant, assuming it's not NULL or
+ // undefined.
+ print wysiwyg_render_dialog_page($page_callback_result);
+ }
+
+ // Perform end-of-request tasks.
+ drupal_page_footer();
+}
+
+/**
+ * @see drupal_render_page()
+ */
+function wysiwyg_render_dialog_page($page) {
+ $main_content_display = &drupal_static('system_main_content_added', FALSE);
+
+ // Allow menu callbacks to return strings or arbitrary arrays to render.
+ // If the array returned is not of #type page directly, we need to fill
+ // in the page with defaults.
+ if (is_string($page) || (is_array($page) && (!isset($page['#type']) || ($page['#type'] != 'page')))) {
+ drupal_set_page_content($page);
+ $page = element_info('wysiwyg_dialog_page');
+ }
+
+ // Modules alter the $page as needed. Blocks are populated into regions like
+ // 'sidebar_first', 'footer', etc.
+ drupal_alter(array('wysiwyg_dialog_page', 'page'), $page);
+
+ // If no module has taken care of the main content, add it to the page now.
+ // This allows the site to still be usable even if no modules that
+ // control page regions (for example, the Block module) are enabled.
+ if (!$main_content_display) {
+ $page['content']['system_main'] = drupal_set_page_content();
+ }
+
+ return drupal_render($page);
}
/**
@@ -35,29 +163,21 @@ function wysiwyg_dialog($plugin, $instance) {
*
* @see wysiwyg_dialog()
* @see wysiwyg-dialog-page.tpl.php
- * @see template_preprocess()
+ * @see template_preprocess_page()
*/
function template_preprocess_wysiwyg_dialog_page(&$variables) {
- // Construct page title
- $head_title = array(strip_tags(drupal_get_title()), variable_get('site_name', 'Drupal'));
-
- $variables['head_title'] = implode(' | ', $head_title);
- $variables['base_path'] = base_path();
- $variables['front_page'] = url();
- // @todo Would a breadcrumb make sense / possible at all?
- // $variables['breadcrumb'] = theme('breadcrumb', drupal_get_breadcrumb());
- $variables['head'] = drupal_get_html_head();
- $variables['help'] = theme('help');
- $variables['language'] = $GLOBALS['language'];
- $variables['language']->dir = $GLOBALS['language']->direction ? 'rtl' : 'ltr';
- $variables['messages'] = $variables['show_messages'] ? theme('status_messages') : '';
- $variables['site_name'] = (theme_get_setting('toggle_name') ? variable_get('site_name', 'Drupal') : '');
- $variables['css'] = drupal_add_css();
- $variables['styles'] = drupal_get_css();
- $variables['scripts'] = drupal_get_js();
- $variables['tabs'] = theme('menu_local_tasks');
- $variables['title'] = drupal_get_title();
- // Closure should be filled last.
- $variables['closure'] = theme('closure');
+ template_preprocess_page($variables);
+}
+
+
+/**
+ * Template process function for theme_wysiwyg_dialog_page().
+ *
+ * @see wysiwyg_dialog()
+ * @see wysiwyg-dialog-page.tpl.php
+ * @see template_process_page()
+ */
+function template_process_wysiwyg_dialog_page(&$variables) {
+ template_process_page($variables);
}
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.features.inc b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.features.inc
new file mode 100644
index 0000000..5edd642
--- /dev/null
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.features.inc
@@ -0,0 +1,92 @@
+<?php
+
+/**
+ * Implements hook_features_export_options().
+ */
+function wysiwyg_features_export_options() {
+ $profiles = array();
+
+ // Get human-readable name from filter module.
+ $formats = filter_formats();
+
+ foreach (array_keys(wysiwyg_profile_load_all()) as $format) {
+ // Text format may vanish without deleting the wysiwyg profile.
+ if (isset($formats[$format])) {
+ $profiles[$format] = $formats[$format]->name;
+ }
+ }
+ return $profiles;
+}
+
+/**
+ * Implements hook_features_export().
+ */
+function wysiwyg_features_export($data, &$export, $module_name = '') {
+ $pipe = array();
+
+ // The wysiwyg_default_formats() hook integration is provided by the
+ // features module so we need to add it as a dependency.
+ $export['dependencies']['features'] = 'features';
+ $export['dependencies']['wysiwyg'] = 'wysiwyg';
+
+ foreach ($data as $name) {
+ if ($profile = wysiwyg_get_profile($name)) {
+ // Add profile to exports.
+ $export['features']['wysiwyg'][$profile->format] = $profile->format;
+
+ // Chain filter format for export.
+ $pipe['filter'][] = $profile->format;
+ }
+ }
+
+ return $pipe;
+}
+
+/**
+ * Implements hook_features_export_render().
+ */
+function wysiwyg_features_export_render($module, $data, $export = NULL) {
+ $code = array();
+ $code[] = ' $profiles = array();';
+ $code[] = '';
+
+ foreach ($data as $name) {
+ if ($profile = wysiwyg_get_profile($name)) {
+ $profile_export = features_var_export($profile, ' ');
+ $profile_identifier = features_var_export($profile->format);
+ $code[] = " // Exported profile: {$profile->format}";
+ $code[] = " \$profiles[{$profile_identifier}] = {$profile_export};";
+ $code[] = "";
+ }
+ }
+
+ $code[] = ' return $profiles;';
+ $code = implode("\n", $code);
+ return array('wysiwyg_default_profiles' => $code);
+}
+
+/**
+ * Implements hook_features_revert().
+ */
+function wysiwyg_features_revert($module) {
+ return wysiwyg_features_rebuild($module);
+}
+
+/**
+ * Implements hook_features_rebuild().
+ */
+function wysiwyg_features_rebuild($module) {
+ if ($defaults = features_get_default('wysiwyg', $module)) {
+ foreach ($defaults as $profile) {
+ db_merge('wysiwyg')
+ ->key(array('format' => $profile['format']))
+ ->fields(array(
+ 'editor' => $profile['editor'],
+ 'settings' => serialize($profile['settings']),
+ ))
+ ->execute();
+ }
+ wysiwyg_profile_cache_clear();
+ }
+}
+
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.info b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.info
index 840817a..5f70c0c 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.info
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.info
@@ -9,9 +9,9 @@ configure = admin/config/content/wysiwyg
files[] = wysiwyg.module
files[] = tests/wysiwyg.test
-; Information added by drupal.org packaging script on 2011-06-19
-version = "7.x-2.1"
+; Information added by drupal.org packaging script on 2012-10-02
+version = "7.x-2.2"
core = "7.x"
project = "wysiwyg"
-datestamp = "1308450722"
+datestamp = "1349213776"
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.install b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.install
index 038ba46..e5dd046 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.install
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.install
@@ -30,6 +30,7 @@ function wysiwyg_schema() {
'description' => 'Configuration settings for the editor.',
'type' => 'text',
'size' => 'normal',
+ 'serialize' => TRUE,
),
),
'primary key' => array('format'),
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.js b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.js
index 72ca156..29e2c54 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.js
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.js
@@ -11,7 +11,6 @@ Drupal.wysiwygInit = function() {
if (/KDE/.test(navigator.vendor)) {
return;
}
-
jQuery.each(Drupal.wysiwyg.editor.init, function(editor) {
// Clone, so original settings are not overwritten.
this(jQuery.extend(true, {}, Drupal.settings.wysiwyg.configs[editor]));
@@ -38,13 +37,13 @@ Drupal.wysiwygInit = function() {
* A DOM element, supplied by Drupal.attachBehaviors().
*/
Drupal.behaviors.attachWysiwyg = {
- attach: function(context, settings) {
+ attach: function (context, settings) {
// This breaks in Konqueror. Prevent it from running.
if (/KDE/.test(navigator.vendor)) {
return;
}
- $('.wysiwyg', context).once('wysiwyg', function() {
+ $('.wysiwyg', context).once('wysiwyg', function () {
if (!this.id || typeof Drupal.settings.wysiwyg.triggers[this.id] === 'undefined') {
return;
}
@@ -76,9 +75,27 @@ Drupal.behaviors.attachWysiwyg = {
if (event.isDefaultPrevented()) {
return;
}
- Drupal.wysiwygDetach(context, params[format]);
+ Drupal.wysiwygDetach(context, params[format], 'serialize');
});
});
+ },
+
+ detach: function (context, settings, trigger) {
+ var wysiwygs;
+ // The 'serialize' trigger indicates that we should simply update the
+ // underlying element with the new text, without destroying the editor.
+ if (trigger == 'serialize') {
+ // Removing the wysiwyg-processed class guarantees that the editor will
+ // be reattached. Only do this if we're planning to destroy the editor.
+ wysiwygs = $('.wysiwyg-processed', context);
+ }
+ else {
+ wysiwygs = $('.wysiwyg', context).removeOnce('wysiwyg');
+ }
+ wysiwygs.each(function () {
+ var params = Drupal.settings.wysiwyg.triggers[this.id];
+ Drupal.wysiwygDetach(context, params, trigger);
+ });
}
};
@@ -136,11 +153,20 @@ Drupal.wysiwygAttach = function(context, params) {
* A DOM element, supplied by Drupal.attachBehaviors().
* @param params
* An object containing input format parameters.
+ * @param trigger
+ * A string describing what is causing the editor to be detached.
+ *
+ * @see Drupal.detachBehaviors
*/
-Drupal.wysiwygDetach = function(context, params) {
+Drupal.wysiwygDetach = function (context, params, trigger) {
+ // Do not attempt to detach an unknown editor instance (Ajax).
+ if (typeof Drupal.wysiwyg.instances[params.field] == 'undefined') {
+ return;
+ }
+ trigger = trigger || 'unload';
var editor = Drupal.wysiwyg.instances[params.field].editor;
if (jQuery.isFunction(Drupal.wysiwyg.editor.detach[editor])) {
- Drupal.wysiwyg.editor.detach[editor](context, params);
+ Drupal.wysiwyg.editor.detach[editor](context, params, trigger);
}
};
@@ -187,6 +213,7 @@ Drupal.wysiwyg.toggleWysiwyg = function (event) {
Drupal.wysiwyg.editor.attach.none(context, params);
Drupal.wysiwyg.instances[params.field] = Drupal.wysiwyg.editor.instance.none;
Drupal.wysiwyg.instances[params.field].editor = 'none';
+ Drupal.wysiwyg.instances[params.field].field = params.field;
$(this).html(Drupal.settings.wysiwyg.enable).blur();
}
else {
@@ -234,4 +261,9 @@ Drupal.wysiwyg.getParams = function(element, params) {
*/
Drupal.wysiwygInit();
+// Respond to CTools detach behaviors event.
+$(document).bind('CToolsDetachBehaviors', function(event, context) {
+ Drupal.behaviors.attachWysiwyg.detach(context, {}, 'unload');
+});
+
})(jQuery);
diff --git a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.module b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.module
index 771cbd7..22130ea 100644
--- a/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.module
+++ b/kolab.org/www/drupal-7.15/sites/all/modules/wysiwyg/wysiwyg.module
@@ -79,9 +79,11 @@ function wysiwyg_menu() {
'type' => MENU_LOCAL_TASK,
'weight' => 10,
);
+ // @see wysiwyg_dialog()
$items['wysiwyg/%'] = array(
'page callback' => 'wysiwyg_dialog',
'page arguments' => array(1),
+ 'delivery callback' => 'wysiwyg_deliver_dialog_page',
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
'file' => 'wysiwyg.dialog.inc',
@@ -90,6 +92,19 @@ function wysiwyg_menu() {
}
/**
+ * Implements hook_element_info().
+ */
+function wysiwyg_element_info() {
+ // @see wysiwyg_dialog()
+ $types['wysiwyg_dialog_page'] = array(
+ '#theme' => 'wysiwyg_dialog_page',
+ '#theme_wrappers' => array('html'),
+ '#show_messages' => TRUE,
+ );
+ return $types;
+}
+
+/**
* Implementation of hook_theme().
*
* @see drupal_common_theme(), common.inc
@@ -103,8 +118,9 @@ function wysiwyg_theme() {
'wysiwyg_admin_button_table' => array(
'render element' => 'form',
),
+ // @see wysiwyg_dialog()
'wysiwyg_dialog_page' => array(
- 'variables' => array('content' => NULL, 'show_messages' => TRUE),
+ 'render element' => 'page',
'file' => 'wysiwyg.dialog.inc',
'template' => 'wysiwyg-dialog-page',
),
@@ -117,7 +133,7 @@ function wysiwyg_theme() {
function wysiwyg_help($path, $arg) {
switch ($path) {
case 'admin/config/content/wysiwyg':
- $output = '<p>' . t('A Wysiwyg profile is associated with an input format. A Wysiwyg profile defines which client-side editor is loaded with a particular input format, what buttons or themes are enabled for the editor, how the editor is displayed, and a few other editor-specific functions.') . '</p>';
+ $output = '<p>' . t('A Wysiwyg profile is associated with a text format. A Wysiwyg profile defines which client-side editor is loaded with a particular text format, what buttons or themes are enabled for the editor, how the editor is displayed, and a few other editor-specific functions.') . '</p>';
return $output;
}
}
@@ -286,6 +302,7 @@ function wysiwyg_get_profile($format) {
function wysiwyg_load_editor($profile) {
static $settings_added;
static $loaded = array();
+ $path = drupal_get_path('module', 'wysiwyg');
$name = $profile->editor;
// Library files must be loaded only once.
@@ -293,6 +310,13 @@ function wysiwyg_load_editor($profile) {
// Load editor.
$editor = wysiwyg_get_editor($name);
if ($editor) {
+ $default_library_options = array(
+ 'type' => 'file',
+ 'scope' => 'header',
+ 'defer' => FALSE,
+ 'cache' => TRUE,
+ 'preprocess' => TRUE,
+ );
// Determine library files to load.
// @todo Allow to configure the library/execMode to use.
if (isset($profile->settings['library']) && isset($editor['libraries'][$profile->settings['library']])) {
@@ -305,9 +329,33 @@ function wysiwyg_load_editor($profile) {
$files = array_shift($editor['libraries']);
$files = $files['files'];
}
+
+ // Check whether the editor requires an initialization script.
+ if (!empty($editor['init callback'])) {
+ $init = $editor['init callback']($editor, $library, $profile);
+ if (!empty($init)) {
+ // Build a file for each of the editors to hold the init scripts.
+ // @todo Aggregate all initialization scripts into one file.
+ $uri = 'public://js/wysiwyg/wysiwyg_' . $name . '_' . drupal_hash_base64($init) . '.js';
+ $init_exists = file_exists($uri);
+ if (!$init_exists) {
+ $js_path = dirname($uri);
+ file_prepare_directory($js_path, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
+ }
+ // Attempt to create the file, or fall back to an inline script (which
+ // will not work in Ajax calls).
+ if (!$init_exists && !file_unmanaged_save_data($init, $uri, FILE_EXISTS_REPLACE)) {
+ drupal_add_js($init, array('type' => 'inline') + $default_library_options);
+ }
+ else {
+ drupal_add_js(file_create_url($uri), $default_library_options);
+ }
+ }
+ }
+
foreach ($files as $file => $options) {
if (is_array($options)) {
- $options += array('type' => 'file', 'scope' => 'header', 'defer' => FALSE, 'cache' => TRUE, 'preprocess' => TRUE);
+ $options += $default_library_options;
drupal_add_js($editor['library path'] . '/' . $file, $options);
}
else {
@@ -335,17 +383,6 @@ function wysiwyg_load_editor($profile) {
foreach ($files as $file) {
drupal_add_css($editor['css path'] . '/' . $file);
}
-
- drupal_add_js(array('wysiwyg' => array(
- 'configs' => array($editor['name'] => array('global' => array(
- // @todo Move into (global) editor settings.
- // If JS compression is enabled, at least TinyMCE is unable to determine
- // its own base path and exec mode since it can't find the script name.
- 'editorBasePath' => base_path() . $editor['library path'],
- 'execMode' => $library,
- ))),
- )), 'setting');
-
$loaded[$name] = TRUE;
}
else {
@@ -362,7 +399,6 @@ function wysiwyg_load_editor($profile) {
'enable' => t('Enable rich-text'),
)), 'setting');
- $path = drupal_get_path('module', 'wysiwyg');
// Initialize our namespaces in the *header* to do not force editor
// integration scripts to check and define Drupal.wysiwyg on its own.
drupal_add_js($path . '/wysiwyg.init.js', array('group' => JS_LIBRARY));
@@ -619,7 +655,10 @@ function wysiwyg_get_css() {
$files = array();
foreach (drupal_add_css() as $filepath => $info) {
if ($info['group'] >= CSS_THEME && $info['media'] != 'print') {
- if (file_exists($filepath)) {
+ if ($info['type'] == 'external') {
+ $files[] = $filepath;
+ }
+ elseif (file_exists($filepath)) {
$files[] = base_path() . $filepath;
}
}
@@ -809,6 +848,7 @@ function wysiwyg_get_all_editors() {
'libraries' => array(),
'version callback' => NULL,
'themes callback' => NULL,
+ 'settings form callback' => NULL,
'settings callback' => NULL,
'plugin callback' => NULL,
'plugin settings callback' => NULL,
@@ -1077,3 +1117,19 @@ function _wysiwyg_process_include($module, $identifier, $path, $hook) {
/**
* @} End of "defgroup wysiwyg_api".
*/
+
+/**
+ * Implements hook_features_api().
+ */
+function wysiwyg_features_api() {
+ return array(
+ 'wysiwyg' => array(
+ 'name' => t('Wysiwyg profiles'),
+ 'default_hook' => 'wysiwyg_default_profiles',
+ 'default_file' => FEATURES_DEFAULTS_INCLUDED,
+ 'feature_source' => TRUE,
+ 'file' => drupal_get_path('module', 'wysiwyg') . '/wysiwyg.features.inc',
+ ),
+ );
+}
+
More information about the commits
mailing list