Skip to content

Instantly share code, notes, and snippets.

@fabsor
Last active August 29, 2015 14:04
Show Gist options
  • Save fabsor/27b8de2ce2b3785e6330 to your computer and use it in GitHub Desktop.
Save fabsor/27b8de2ce2b3785e6330 to your computer and use it in GitHub Desktop.
patch for refererences dialog edit
diff --git a/js/references-dialog.js b/js/references-dialog.js
index 0c23b31..23caa22 100644
--- a/js/references-dialog.js
+++ b/js/references-dialog.js
@@ -1,52 +1,123 @@
(function ($) {
-
var $window = $(window);
-
Drupal.behaviors.referencesDialog = {
- attach: function (context, settings) {
- // Add appropriate classes on all fields that should have it. This is
- // necessary since we don't actually know what markup we are dealing with.
- if (typeof settings.ReferencesDialog !== 'undefined') {
- $.each(settings.ReferencesDialog.fields, function (key, widget_settings) {
- $('.' + key + ' a.references-dialog-activate', context).click(function (e) {
- e.preventDefault();
- Drupal.ReferencesDialog.open($(this).attr('href'), $(this).html());
- Drupal.ReferencesDialog.entityIdReceived = function (entity_type, entity_id, label) {
- if (typeof widget_settings.format !== 'undefined') {
- var value = widget_settings.format
- .replace('$label', label)
- .replace('$entity_id', entity_id)
- .replace('$entity_type', entity_type);
- }
- // If we have a callback path, let's invoke that.
- if (typeof widget_settings.callback_path !== 'undefined') {
- var entity_info = {
- label: label,
- entity_id: entity_id,
- entity_type: entity_type
- };
- Drupal.ReferencesDialog.invokeCallback(widget_settings.callback_path, entity_info, widget_settings.callback_settings);
- }
- // If we have a target, use that.
- else if (typeof widget_settings.target !== 'undefined') {
- var target = $('#' + widget_settings.target);
- target.val(value);
- target.change();
+
+ /**
+ * Manage edit links by doing access checks and adding edit links
+ * where appropriate.
+ * @param field_name the name of the field
+ * @param target the target jQuery element.
+ * @param the settings for the widget handling the field.
+ */
+ editLinkController: function (field_name, settings) {
+ var _this = this;
+ return function () {
+ var val = $(this).val();
+ var result = val.match(settings.match)
+ if (result && result[1]) {
+ var entity_id = result[1];
+ var url = '$callback/$entity_type/$entity_id'
+ .replace('$callback', _this.settings.access_callback)
+ .replace('$entity_type', settings.entity_type)
+ .replace('$entity_id', entity_id)
+ $.get(url, function (data) {
+ if (data.access) {
+ var selector = '.dialog-links.' + field_name + ' > ul';
+ if ($(selector + ' .edit-dialog').size() === 0) {
+ $(selector)
+ .append('<li><a href="' + data.path +
+ '" class="edit-dialog references-dialog-activate">' +
+ Drupal.t('Edit') + '</a></li>');
+ $(selector + ' .edit-dialog').click(_this.dialogController(field_name, settings));
}
- // If we have none of the above, we just insert the value in the item
- // that invoked this.
else {
- var key_el = $('#' + key);
- key_el.val(value);
- key_el.change();
+ $(selector + ' .edit-dialog').attr('href', data.path);
}
}
- return false;
});
- });
+ }
+ };
+ },
+
+ /**
+ * Get the target jQuery element. This will not work if the
+ * widget settings are fetched from a callback.
+ * @return
+ * The jquery element of the target, or null if the target
+ * is fetched with a callback.
+ */
+ getTarget: function (field_name, settings) {
+ if (settings.target) {
+ return $('#' + widget_settings.target);
}
+ else if (!settings.callback_path){
+ return $('#' + field_name);
+ }
+ },
+
+ /**
+ * Manage opening and return values from dialogs.
+ * @param field_name the name of the field
+ * param settings settings for the widget.
+ * @return a function that can be used in an event.
+ */
+ dialogController: function (field_name, settings) {
+ var _this = this;
+ return function (e) {
+ e.preventDefault();
+ Drupal.ReferencesDialog.open($(this).attr('href'), $(this).html());
+ Drupal.ReferencesDialog.entityIdReceived = function (entity_type, entity_id, label) {
+ if (settings.format) {
+ var value = settings.format
+ .replace('$label', label)
+ .replace('$entity_id', entity_id)
+ .replace('$entity_type', entity_type);
+ }
+ var target = _this.getTarget(field_name, settings);
+ if (target) {
+ target.val(value);
+ target.change();
+ }
+ // We can't get the target in the cases where
+ // we have a custom callback.
+ else {
+ var entity_info = {
+ label: label,
+ entity_id: entity_id,
+ entity_type: entity_type
+ };
+ Drupal.ReferencesDialog
+ .invokeCallback(settings.callback_path, entity_info,
+ settings.callback_settings);
+ }
+ }
+ return false;
+ };
+ },
+ attach: function (context, settings) {
+ if (typeof settings.ReferencesDialog === 'undefined') {
+ return;
+ }
+ var _this = this;
+ this.settings = settings.ReferencesDialog;
+ this.context = context;
+ // Add appropriate classes on all fields that should have it. This is
+ // necessary since we don't actually know what markup we are dealing with.
+ $.each(this.settings.fields, function (key, widget_settings) {
+ var target = _this.getTarget(key, widget_settings);
+ // We can insert an edit link automatically if the widget provider
+ // supplied us with a match regexp and an entity type.
+ if (target && widget_settings.editable && widget_settings.match
+ && widget_settings.entity_type) {
+ var editController = _this.editLinkController(key, widget_settings);
+ target.change(editController);
+ target.blur(editController);
+ }
+ // Attach a dialog controller to our links.
+ $('.' + key + ' a.references-dialog-activate', context).click(_this.dialogController(key, widget_settings));
+ });
}
- };
+ }
/**
* Our dialog object. Can be used to open a dialog to anywhere.
diff --git a/references_dialog.api.php b/references_dialog.api.php
index 73835c6..60a451d 100644
--- a/references_dialog.api.php
+++ b/references_dialog.api.php
@@ -17,6 +17,9 @@
* An array keyed by the widget you want to attach links to. This array
* should contain the following keys:
* - 'element_type': The type of FAPI element the widget is.
+ * - 'entity_type': The type of entity that is being created by this widget.
+ * - 'type_callback': Specify a callback if the entity may vary.
+ * - 'match': A regular expreession that matches the id from a textarea.
* - 'format': The format in which the data should be inserted as a value
* into the form element. The following patterns are provided, $label, $entity_id and $entity_type.
* - operations: An array of available operations.
diff --git a/references_dialog.dialog_widgets.inc b/references_dialog.dialog_widgets.inc
index 02efc48..a6d6888 100644
--- a/references_dialog.dialog_widgets.inc
+++ b/references_dialog.dialog_widgets.inc
@@ -15,6 +15,7 @@ function references_dialog_references_dialog_widgets() {
'dialog_form' => 'node_reference_dialog_form',
'entity_type' => 'node',
'format' => '$label [nid: $entity_id]',
+ 'match' => 'nid:\s?([1-9][0-9]*)',
'views_query' => 'references_dialog_node_reference_views_query',
'operations' => array(
'search' => array(
@@ -35,6 +36,7 @@ function references_dialog_references_dialog_widgets() {
'element_type' => 'textfield',
'entity_type' => 'user',
'format' => '$label [uid: $entity_id]',
+ 'match' => 'uid:\s?([1-9][0-9]*)',
'operations' => array(
'search' => array(
'function' => 'references_dialog_get_field_search_links',
@@ -56,6 +58,7 @@ function references_dialog_references_dialog_widgets() {
'views_query' => 'references_dialog_entityreference_views_query',
'type_callback' => 'references_dialog_entityreference_get_type',
'format' => '$label ($entity_id)',
+ 'match' => '\(([1-9][0-9]*)\)',
'operations' => array(
'edit' => array(
'function' => 'references_dialog_entityreference_edit_link',
diff --git a/references_dialog.module b/references_dialog.module
index 26b203e..5973c75 100644
--- a/references_dialog.module
+++ b/references_dialog.module
@@ -22,7 +22,17 @@ function references_dialog_element_info() {
*/
function references_dialog_attached() {
return array(
- 'js' => array(drupal_get_path('module', 'references_dialog') . '/js/references-dialog.js'),
+ 'js' => array(
+ drupal_get_path('module', 'references_dialog') . '/js/references-dialog.js',
+ array(
+ 'data' => array(
+ 'ReferencesDialog' => array(
+ 'access_callback' => url('references-dialog/access'),
+ ),
+ ),
+ 'type' => 'setting',
+ ),
+ ),
'css' => array(drupal_get_path('module', 'references_dialog') . '/css/references-dialog-admin.css'),
'library' => array(array('system', 'ui.dialog')),
);
@@ -56,9 +66,25 @@ function references_dialog_menu() {
'access callback' => 'references_dialog_redirect_access',
'access arguments' => array(2, 3),
);
+ // Determine if we have access to create or update entities
+ // of a particular type.
+ $items['references-dialog/access/%/%'] = array(
+ 'page callback' => 'references_dialog_entity_access',
+ 'page arguments' => array(2,3),
+ 'access callback' => TRUE,
+ );
return $items;
}
+function references_dialog_entity_access($entity_type, $entity) {
+ $entity = entity_load_single($entity_type, $entity);
+ return drupal_json_output(array(
+ 'access' => !empty($entity) && entity_access('update', $entity_type, $entity),
+ 'path' => url(references_dialog_get_admin_path($entity_type, 'edit', NULL, $entity)),
+ )
+ );
+}
+
/**
* Implements hook_admin_paths().
*/
@@ -308,14 +334,27 @@ function references_dialog_process_widget(&$element) {
// Attach javascript and CSS needed.
$attached = references_dialog_attached();
$element['#attached']['js'][] = $attached['js'][0];
- $element['#attached']['js'][] = references_dialog_js_settings($element['#id'], array('format' => $dialog_widget['format']));
+ $element['#attached']['js'][] = $attached['js'][1];
+
+ $js_settings = array(
+ 'format' => $dialog_widget['format'],
+ 'match' => !empty($dialog_widget['match']) ? $dialog_widget['match'] : NULL,
+ );
+ if (isset($dialog_widget['entity_type'])) {
+ $js_settings['entity_type'] = $dialog_widget['entity_type'];
+ }
+ elseif (isset($dialog_widget['type_callback'])) {
+ $js_settings['entity_type'] = $dialog_widget['type_callback']($instance, $field);
+ }
$element['#attached']['css'][] = $attached['css'][0];
$element['#attached']['library'][] = $attached['library'][0];
-
$link_options = array('attributes' => array('class' => array('references-dialog-activate')));
$dialog_links = array();
foreach ($dialog_widget['operations'] as $operation => $settings) {
if (isset($widget_settings['references_dialog_' . $operation]) && $widget_settings['references_dialog_' . $operation]) {
+ if ($operation == 'edit') {
+ $js_settings['editable'] = TRUE;
+ }
$links = $settings['function']($element, $widget_settings, $field, $instance);
foreach ($links as $link) {
$link['attributes']['class'][] = $operation . '-dialog';
@@ -323,6 +362,7 @@ function references_dialog_process_widget(&$element) {
}
}
}
+ $element['#attached']['js'][] = references_dialog_js_settings($element['#id'], $js_settings);
if (count($dialog_links)) {
// We add a div directly into the markup here since we really need it in order
// to make sure the javascript works.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment