From 70e784bba51aef88a48d3f6f946e6c6163252311 Mon Sep 17 00:00:00 2001
From: "Adam J. DiCarlo" <adam.dicarlo@gmail.com>
Date: Sun, 25 Mar 2012 12:14:37 -0700
Subject: [PATCH] WIP: Support BeanSlide Plugins, using CTools.

---
 beanslide.info                                     |    1 +
 beanslide.module                                   |  143 ++++++++++++++++++++
 beanslide_cycle/beanslide_cycle.info               |    6 +
 beanslide_cycle/beanslide_cycle.module             |   30 ++++
 .../plugins/beanslide/beanslide_cycle.inc          |   55 ++++++++
 includes/interface.inc                             |   16 +++
 plugins/bean/beanslide.inc                         |   22 +++-
 7 files changed, 270 insertions(+), 3 deletions(-)
 create mode 100644 beanslide_cycle/beanslide_cycle.info
 create mode 100644 beanslide_cycle/beanslide_cycle.module
 create mode 100644 beanslide_cycle/plugins/beanslide/beanslide_cycle.inc
 create mode 100644 includes/interface.inc

diff --git a/beanslide.info b/beanslide.info
index a7ab185..b9fe249 100644
--- a/beanslide.info
+++ b/beanslide.info
@@ -3,6 +3,7 @@ dependencies[] = "bean"
 dependencies[] = "field_collection"
 dependencies[] = "image"
 description = "Provides a slideshow enabled block"
+files[] = "includes/interface.inc"
 files[] = "plugins/bean/beanslide.inc"
 name = "Bean Slide"
 php = "5.2.4"
diff --git a/beanslide.module b/beanslide.module
index 9b94c59..3b10a87 100644
--- a/beanslide.module
+++ b/beanslide.module
@@ -35,6 +35,149 @@ function beanslide_bean_types() {
 }
 
 /**
+ * Minimal version of the BeanSlide plugin API a module must use in order
+ * to have its plugins be used.
+ */
+function beanslide_min_version() {
+  return 1;
+}
+
+/**
+ * Current version of the BeanSlide plugin API.
+ */
+function beanslide_current_version() {
+  return 1;
+}
+
+/**
+ * Implements hook_ctools_plugin_type().
+ */
+function beanslide_ctools_plugin_type() {
+  return array(
+    'plugins' => array(
+      'cache' => FALSE, // TODO: This is for dev. Set to TRUE.
+      'use hooks' => TRUE,
+      'classes' => array('handler'),
+      'info file' => TRUE,
+      'alterable' => TRUE,
+      'defaults' => array(
+        'label' => t('BeanSlide Plugin'),
+        'description' => '',
+        'cache_level' => DRUPAL_CACHE_PER_ROLE,
+        'editable' => FALSE,
+        'plugin' => array(
+        ),
+      ),
+    ),
+  );
+}
+
+/**
+ * Load a plugin class.
+ *
+ * @param $plugin_key string
+ *   The key of the plugin.
+ * @return BeanSlidePluginInterface | Boolean
+ *   An instance of the BeanSlidePluginType-based class or FALSE on failure.
+ */
+function beanslide_load_plugin_class($plugin_key = NULL) {
+  $cache = &drupal_static(__FUNCTION__);
+
+  if (!isset($cache[$plugin_key])) {
+    ctools_include('plugins');
+    $class = ctools_plugin_load_class('beanslide', 'plugins', $plugin_key, 'handler');
+    if ($class && beanslide_check_plugin_class($class)) {
+      $cache[$plugin_key] = new $class(beanslide_fetch_plugin_info($plugin_key));
+    }
+  }
+
+  return isset($cache[$plugin_key]) ? $cache[$plugin_key] : FALSE;
+}
+
+/**
+ * Check the plugin type class
+ *
+ * @param $class string
+ *  The name of the beanslide type class
+ * @return Boolean
+ */
+function beanslide_check_plugin_class($class) {
+  $ref_class = new ReflectionClass($class);
+  if (in_array('BeanSlidePluginInterface', $ref_class->getInterfaceNames())) {
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+/**
+ * Fetch the widget plugin info
+ */
+function beanslide_fetch_plugin_info($plugin = NULL) {
+  $plugins = &drupal_static(__FUNCTION__);
+  ctools_include('plugins');
+
+  if (empty($plugins)) {
+    if (($cache = cache_get('beanslide_plugins')) && !empty($cache->data)) {
+      $plugins = $cache->data;
+    }
+    else {
+      $plugins = ctools_get_plugins('beanslide', 'plugins');
+
+      // Only use modules with the same version.
+      $allowed_modules = array_keys(ctools_plugin_api_info('beanslide', 'plugins', beanslide_current_version(), beanslide_min_version()));
+      foreach ($plugins as $key => $plugin_value) {
+        if (!in_array($plugin_value['module'], $allowed_modules) || ($plugin_value['abstract'])) {
+          unset($plugins[$key]);
+        }
+      }
+      cache_set('beanslide_plugins', $plugins);
+    }
+  }
+
+  if (empty($plugin)) {
+    return $plugins;
+  }
+  else {
+    // Make sure the plugin is in the cache.
+    if (!isset($plugins[$plugin])) {
+      $plugin_info = ctools_get_plugins('beanslide', 'plugins', $plugin);
+      if (empty($allowed_modules)) {
+        $allowed_modules = array_keys(ctools_plugin_api_info('beanslide', 'plugins', beanslide_current_version(), beanslide_min_version()));
+      }
+      if (in_array($plugin_info['module'], $allowed_modules)) {
+        $plugins[$plugin] = $plugin_info;
+
+        cache_set('beanslide_plugins', $plugins);
+      }
+    }
+
+    // If we still don't have the plugin then return NULL.
+    if (empty($plugins[$plugin])) {
+      return NULL;
+    }
+    return $plugins[$plugin];
+  }
+}
+
+/**
+ * Retrieves an array of all slideshow plugins.
+ */
+function beanslide_get_plugins() {
+  $beanslide_plugins = &drupal_static(__FUNCTION__);
+
+  if (empty($beanslide_plugins)) {
+    $beanslide_plugins = array();
+    foreach (beanslide_fetch_plugin_info() as $plugin) {
+      if (!empty($plugin['name']) && $plugin['name'] !== 'beanslide' && $plugin_class = beanslide_load_plugin_class($plugin['name'])) {
+        $beanslide_plugins[$plugin['name']] = $plugin_class;
+      }
+    }
+  }
+  return $beanslide_plugins;
+}
+
+/**
  * Implements hook_theme()
  */
 function beanslide_theme($existing, $type, $theme, $path) {
diff --git a/beanslide_cycle/beanslide_cycle.info b/beanslide_cycle/beanslide_cycle.info
new file mode 100644
index 0000000..005d767
--- /dev/null
+++ b/beanslide_cycle/beanslide_cycle.info
@@ -0,0 +1,6 @@
+core = "7.x"
+dependencies[] = "beanslide"
+description = "Provides the jQuery.Cycle BeanSlide slideshow type."
+files[] = "plugins/beanslide/beanslide_cycle.inc"
+name = "Bean Slide Cycle"
+php = "5.2.4"
diff --git a/beanslide_cycle/beanslide_cycle.module b/beanslide_cycle/beanslide_cycle.module
new file mode 100644
index 0000000..1d4edd8
--- /dev/null
+++ b/beanslide_cycle/beanslide_cycle.module
@@ -0,0 +1,30 @@
+<?php
+
+/**
+ * Implements hook_beanslide_plugins_api_info().
+ */
+function beanslide_cycle_beanslide_plugins_api_info() {
+  return array(
+    'api' => 1,
+  );
+}
+
+/**
+ * Implements hook_beanslide_plugins().
+ */
+function beanslide_cycle_beanslide_plugins() {
+  $plugin_path = drupal_get_path('module', 'beanslide_cycle') . '/plugins/beanslide';
+
+  $plugins['beanslide_cycle'] = array(
+    'name' => 'beanslide_cycle',
+    'label' => t('Cycle'),
+    'handler' => array(
+      'class' => 'BeanSlideCycle',
+      'parent' => 'BeanSlidePluginInterface',
+    ),
+    'editable' => FALSE,
+    'path' => $plugin_path,
+    'file' => 'beanslide_cycle.inc',
+  );
+  return $plugins;
+}
diff --git a/beanslide_cycle/plugins/beanslide/beanslide_cycle.inc b/beanslide_cycle/plugins/beanslide/beanslide_cycle.inc
new file mode 100644
index 0000000..8d74d29
--- /dev/null
+++ b/beanslide_cycle/plugins/beanslide/beanslide_cycle.inc
@@ -0,0 +1,55 @@
+<?php
+/**
+ * @file
+ * jQuery.Cycle Bean Slide plugin.
+ */
+
+class BeanSlideCycle implements BeanSlidePluginInterface {
+
+  /**
+   * Implements BeanSlidePluginInterface::__construct();
+   */
+  public function __construct($plugin_info) {
+  }
+
+  /**
+   * Implements BeanSlidePluginInterface::values();
+   */
+  public function values() {
+    return array(
+      'transition' => 'fade',
+      'transition_duration' => 2000,
+      'timeout' => 8000,
+    );
+  }
+
+  /**
+   * Implements BeanSlidePluginInterface::form();
+   */
+  public function form($bean, $settings, $form, &$form_state) {
+    $form['transition'] = array(
+      '#type' => 'select',
+      '#title' => t('Transition effect'),
+      '#options' => array(
+        'fade' => t('Fade'),
+      ),
+      '#default_value' => $settings['transition'],
+    );
+
+    $form['transition_duration'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Transition duration'),
+      '#description' => t('The amount of time each transition effect should run, in milliseconds.'),
+      '#default_value' => $settings['transition_duration'],
+    );
+
+    $form['timeout'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Timeout'),
+      '#description' => t('The time each slide is shown, in milliseconds.'),
+      '#default_value' => $settings['timeout'],
+    );
+
+    return $form;
+  }
+}
diff --git a/includes/interface.inc b/includes/interface.inc
new file mode 100644
index 0000000..a4ee969
--- /dev/null
+++ b/includes/interface.inc
@@ -0,0 +1,16 @@
+<?php
+/**
+ * @file
+ * BeanSlidePluginInterface.
+ */
+
+interface BeanSlidePluginInterface {
+
+  public function __construct($plugin_info);
+
+  public function values();
+
+  public function form($beanslide, $form, &$form_state);
+
+  public function view($beanslide, $content, $view_mode = 'default', $langcode = NULL);
+}
diff --git a/plugins/bean/beanslide.inc b/plugins/bean/beanslide.inc
index b7cf8c1..002b7d0 100644
--- a/plugins/bean/beanslide.inc
+++ b/plugins/bean/beanslide.inc
@@ -6,17 +6,33 @@
 
 class BeanslideBean extends BeanPlugin {
   /**
+   *
+   */
+  var $plugin;
+
+  /**
+   * Implements BeanPlugin::__construct().
+   */
+  public function __construct($plugin_info) {
+
+  }
+
+  /**
    * Implements BeanPlugin::values().
    */
   public function values() {
-    return array();
+    return array('settings' => array());
   }
 
   /**
    * Implements BeanPlugin::form().
    */
   public function form($bean, $form, &$form_state) {
-    $form = array();
+    $plugins = beanslide_get_plugins();
+
+    if ($this->plugin) {
+      $form = $this->plugin->form($bean, $settings, $form, $form_state);
+    }
     return $form;
   }
 
@@ -24,6 +40,6 @@ class BeanslideBean extends BeanPlugin {
    * Implements BeanPlugin::view().
    */
   public function view($bean, $content, $view_mode = 'full', $langcode = NULL) {
-    return $content;
+    return $this->plugin->view($bean, $content, $view_mode, $langcode);
   }
 }
-- 
1.7.5.4

