diff --git a/fieldable_panels_panes.module b/fieldable_panels_panes.module index cc8c072..bd9bca2 100644 --- a/fieldable_panels_panes.module +++ b/fieldable_panels_panes.module @@ -410,6 +410,14 @@ function fieldable_panels_panes_menu() { 'type' => MENU_LOCAL_ACTION, ) + $base; + $items['admin/ajax/fieldable-panels-panes/clone/%'] = array( + 'page callback' => 'fieldable_panels_pane_clone_ajax_endpoint', + 'page arguments' => array(4), + 'theme callback' => 'ajax_base_page_theme', + 'delivery callback' => 'ajax_deliver', + 'type' => MENU_CALLBACK, + ) + $base; + return $items; } @@ -1373,3 +1381,146 @@ function fieldable_panels_panes_entity_uri_callback($entity) { 'options' => array(), ); } + +/** + * Implements hook_panelizer_tab_links_alter(). + */ +function fieldable_panels_panes_panels_ipe_pane_links_alter(&$links, $context) { + if ($context['pane']->type == 'fieldable_panels_pane' && count(fieldable_panles_panes_pane_shares($context['pane']->pid)) > 1) { + ctools_add_css('fieldable_panels_panes_ipe', 'fieldable_panels_panes'); + $links['fieldable_panels_pane_clone'] = array( + 'title' => '' . t('Clone') . '', + 'href' => url('admin/ajax/fieldable-panels-panes/clone/' . $context['pane']->pid . '/ipe', array('absolute' => TRUE)), + 'html' => TRUE, + 'attributes' => array( + 'class' => 'use-ajax', + 'id' => "pane-clone-panel-pane-{$context['pane']->pid}", + 'title' => t('Clone'), + ), + ); + } +} + +/** + * Implements hook_get_pane_links_alter(). + */ +function fieldable_panels_panes_get_pane_links_alter(&$links, $pane, $content_type) { + if ($pane->type == 'fieldable_panels_pane' && count(fieldable_panles_panes_pane_shares($pane->pid)) > 1) { + $links['top']['fieldable_panels_pane_clone'] = array( + 'title' => t('Clone'), + 'href' => url('admin/ajax/fieldable-panels-panes/clone/' . $pane->pid . '/panels', array('absolute' => TRUE)), + 'attributes' => array('class' => array('use-ajax')), + ); + } +} + +/** + * Get all panes that reference same fieldable panel pane + * + * @param $pid + * + * @return array + */ +function fieldable_panles_panes_pane_shares($pid) { + $cache = &drupal_static(__FUNCTION__); + if (!isset($cache[$pid])) { + $query = db_select('panels_pane', 'p'); + $query->fields('ps', array('pid')); + $query->innerJoin('panels_pane', 'ps', 'p.subtype = ps.subtype'); + $query->condition('p.pid', $pid); + $query->countQuery(); + $cache[$pid] = $query->execute()->fetchCol(); + } + return $cache[$pid]; +} + +/** + * Fix cloned fieldable panel pane that reference to single entity + * + * @param $pid + * + * @return bool + * + * @throws \Exception + * @throws \InvalidMergeQueryException + */ +function _fieldable_panels_panes_clone($pid) { + + $query = db_select('panels_pane', 'pp'); + $query->fields('pp'); + $query->condition('pid', $pid); + $query->range(0, 1); + $result = $query->execute(); + + $pane = $result->fetch(); + if (!$pane) { + return FALSE; + } + + // Copy from _fieldable_panels_panes_load_entity(). + list($type, $id) = explode(':', $pane->subtype); + if ($type == 'uuid' && module_exists('uuid')) { + $ids = entity_get_id_by_uuid('fieldable_panels_pane', array($id)); + if ($content = entity_load('fieldable_panels_pane', $ids)) { + $content = reset($content); + } + } + elseif ($type == 'vid') { + $fpid = db_query('SELECT fpid FROM {fieldable_panels_panes_revision} WHERE vid = :vid', array(':vid' => $id))->fetchField(); + $content = fieldable_panels_panes_load($fpid, $id); + } + else { + $content = fieldable_panels_panes_load($id); + } + + if (!$content) { + return FALSE; + } + // Copy of entity_ui_clone_entity() from entity module. + + // Clone the entity and make sure it will get saved as a new entity. + $new_entity = clone $content; + + $entity_info = entity_get_info('fieldable_panels_pane'); + $new_entity->{$entity_info['entity keys']['id']} = FALSE; + if (!empty($entity_info['entity keys']['name'])) { + $new_entity->{$entity_info['entity keys']['name']} = FALSE; + } + $new_entity->is_new = TRUE; + + // Make sure the status of a cloned exportable is custom. + if (!empty($entity_info['exportable'])) { + $status_key = isset($entity_info['entity keys']['status']) ? $entity_info['entity keys']['status'] : 'status'; + $new_entity->$status_key = ENTITY_CUSTOM; + } + + if ($type == 'uuid' && module_exists('uuid')) { + $new_entity->vuuid = NULL; + $new_entity->uuid = NULL; + } + if (!empty($new_entity->vid)) { + $new_entity->vid = NULL; + } + + $new_entity = fieldable_panels_panes_save($new_entity); + if (!$new_entity) { + return FALSE; + } + + if (module_exists('uuid') && isset($new_entity->uuid)) { + $new_pane_subtype = 'uuid:' . $new_entity->uuid; + } + else { + $new_pane_subtype = 'fpid:' . $new_entity->fpid; + } + + db_merge('panels_pane') + ->key(array('pid' => $pid)) + ->fields(array( + 'subtype' => $new_pane_subtype, + )) + ->execute(); + + return TRUE; +} + diff --git a/includes/admin.inc b/includes/admin.inc index fa62511..753dae7 100644 --- a/includes/admin.inc +++ b/includes/admin.inc @@ -190,3 +190,39 @@ function fieldable_panels_panes_entity_make_current_page($entity) { drupal_set_message(t('The revision has been made current.')); drupal_goto("admin/structure/fieldable-panels-panes/view/$entity->fpid"); } + +/** + * AJAX endpoint for panelizer and panels pane editing menues + * + * @param $pid + * @param $editing_mode + * + * @return array + */ +function fieldable_panels_pane_clone_ajax_endpoint($pid, $editing_mode = 'panels') { + + $commands = array(); + + if (is_numeric($pid) && _fieldable_panels_panes_clone($pid)) { + $cloned_pane_label_markup = '' . t('(Cloned pane)') . ''; + if ($editing_mode == 'ipe') { + $commands[] = ajax_command_changed("#panels-ipe-paneid-{$pid}", "div.panels-ipe-dragbar span.panels-ipe-dragbar-admin-title"); + $commands[] = ajax_command_remove("#panels-ipe-paneid-{$pid} li.fieldable_panels_pane_clone"); + $commands[] = ajax_command_before("#panels-ipe-paneid-{$pid} div.panels-ipe-dragbar span.panels-ipe-dragbar-admin-title", $cloned_pane_label_markup); + } + else { + $commands[] = ajax_command_changed("#panel-pane-{$pid}", "div.grab-title span.text"); + $commands[] = ajax_command_remove("#panel-pane-{$pid} li.fieldable_panels_pane_clone"); + $commands[] = ajax_command_before("#panel-pane-{$pid} div.grab-title span.text", $cloned_pane_label_markup); + } + } + else { + $commands[] = ajax_command_alert(t('Problem while clonning pane')); + } + + return array( + '#type' => 'ajax', + '#commands' => $commands, + ); + +}