# This patch file was generated by NetBeans IDE # This patch can be applied using context Tools: Apply Diff Patch action on respective folder. # It uses platform neutral UTF-8 encoding. # Above lines and this line are ignored by the patching process. Index: contributions/modules/image/contrib/image_gallery/image_gallery.module --- contributions/modules/image/contrib/image_gallery/image_gallery.module Base (1.31) +++ contributions/modules/image/contrib/image_gallery/image_gallery.module Locally Modified (Based On 1.31) @@ -374,6 +374,12 @@ 'image_gallery' => array( 'arguments' => array('galleries' => NULL, 'images' => NULL), ), + 'image_gallery_count' => array( + 'arguments' => array('count' => 0), + ), + 'image_gallery_updated' => array( + 'arguments' => array('timestamp' => 0), + ), 'image_gallery_img' => array( 'arguments' => array('image' => NULL, 'size' => NULL), ), @@ -450,6 +456,20 @@ } /** + * Theme the count of gallery items on a gallery list. + */ +function theme_image_gallery_count($count) { + return "There are $count images in this gallery."; +} + +/** + * Theme the gallery last updated time on a gallery list. + */ +function theme_image_gallery_updated($timestamp) { + return '
'. t('%date', array('%date' => format_date($timestamp))) ."
\n"; +} + +/** * Returns (and possibly creates) a new vocabulary for Image galleries. */ function _image_gallery_get_vid() { @@ -467,3 +487,13 @@ return $vid; } + +/** + * Implementation of hook_views_api(). + */ +function image_gallery_views_api() { + return array( + 'api' => 2, + 'path' => drupal_get_path('module', 'image_gallery') .'/views', + ); +} Index: contributions/modules/image/contrib/image_gallery/views/image_gallery.views.inc --- contributions/modules/image/contrib/image_gallery/views/image_gallery.views.inc Base (1.1) +++ contributions/modules/image/contrib/image_gallery/views/image_gallery.views.inc Locally Modified (Based On 1.1) @@ -6,3 +6,327 @@ * Image Gallery views integration. */ +/* + * strategy + * + * two ways of getting the image gallery cover image + * - a plain field. This allows complex code like recursion (check the gallery itself, + * if empty, check the child galleries, etc) + * Plain field also allows us to grab the sort order set on the gallery images + * and get the first image from that order as the front. + * (combining the two options will be MONSTROUS!) + * - a relationship + * This gets us onto the node table, so any fields can be used for the cover. + * Depth should be possible too -- eg, "the newest image out of the gammery or its immediate children" + * + * so we want two families of handlers + * - field handlers + * - relationship handlers + * + * top-level classes should cover all the depth and recursion stuff. + */ + + + +/** + * Implementation of hook_views_data_alter(). + * Add fields for image gallery (ie vocabulary terms) to the term_data table. + */ +function image_gallery_views_data_alter(&$data) { + // ---------------------------------------------------------------------- + // Relationships for cover node. + // + // These allow any node field to be used to create the gallery cover node. + // The limitation, however, is that either consider the immediate gallery, + // or a flat pool of the gallery and descendants. + // Note that a bug in Views -- http://drupal.org/node/380560 -- will cause + // an error message when adding node fields on these relationships. + $data['term_data']['gallery_cover_latest'] = array( + 'group' => t('Image gallery'), + 'relationship' => array( + 'title' => t('Latest image'), + 'label' => t('Cover image, latest'), + 'help' => t('Relate an image gallery to its most recently updated node (does not consider child galleries).'), + 'handler' => 'image_gallery_handler_relationship_gallery_cover', + 'base' => 'node', + 'field' => 'nid', + 'correlated field' => 'tid', + 'subquery order' => ' ORDER BY gallery_cover_node.created DESC ', + // TODO: standardize -- remove ORDER BY part! + ), + ); + $data['term_data']['gallery_cover_oldest'] = array( + 'group' => t('Image gallery'), + 'relationship' => array( + 'title' => t('Oldest image'), + 'label' => t('Cover image, oldest'), + 'help' => t('Relate an image gallery to its oldest node (does not consider child galleries).'), + 'handler' => 'image_gallery_handler_relationship_gallery_cover', + 'base' => 'node', + 'field' => 'nid', + 'correlated field' => 'tid', + 'subquery order' => ' ORDER BY gallery_cover_node.created ASC ', + ), + ); + $data['term_data']['gallery_cover_node_title'] = array( + 'group' => t('Image gallery'), + 'relationship' => array( + 'title' => t('First image by title'), + 'label' => t('Cover image, first by title'), + 'help' => t('Relate an image gallery to its first node when sorted by title (does not consider child galleries).'), + 'handler' => 'image_gallery_handler_relationship_gallery_cover', + 'base' => 'node', + 'field' => 'nid', + 'correlated field' => 'tid', + 'subquery order' => ' ORDER BY gallery_cover_node.title ASC ', + ), + ); + + // ---------------------------------------------------------------------- + // Simple fields. + + // Gallery count. + $data['term_data']['gallery_count'] = array( + 'group' => t('Image gallery'), + 'field' => array( + 'title' => t('Count'), + 'help' => t('Count of items in a gallery.'), + 'handler' => 'image_gallery_handler_field_gallery_count', + ), + ); + + // ---------------------------------------------------------------------- + // Fields for cover image. + // + // These use a combination of code and separate queries to get a cover node. + // This makes them more powerful that using the relationship cover node, + // as we can consider child galleries recursively rather than just + // flattening all descendant galleries. + // We can also do complex things such as grab the top-most node from the + // gallery according to how the view for that gallery sorts them. + // The downside however is that without a relationship, the fields here are + // all you've got. + // To add more fields, define them on term_data and optionally add handlers. + // See image_gallery_handler_field_gallery_cover for more information. + $data['term_data']['gallery_latest_thumbnail'] = array( + 'group' => t('Image gallery'), + 'field' => array( + 'title' => t('Latest image'), + 'help' => t('The most recently posted image in the gallery or its child galleries.'), + 'handler' => 'image_gallery_handler_field_gallery_cover_thumbnail', + 'order clause' => 'n.sticky DESC, n.created DESC', + ), + ); + $data['term_data']['gallery_latest_time'] = array( + 'group' => t('Image gallery'), + 'field' => array( + 'title' => t('Last updated time'), + 'help' => t('The time of the most recently posted image in the gallery or its child galleries.'), + 'handler' => 'image_gallery_handler_field_gallery_cover_latest_time', + 'order clause' => 'n.sticky DESC, n.created DESC', + ), + ); + $data['term_data']['gallery_first_title'] = array( + 'group' => t('Image gallery'), + 'field' => array( + 'title' => t('First image by title'), + 'help' => t('The first posted image in the gallery or its child galleries.'), + 'handler' => 'image_gallery_handler_field_gallery_cover_thumbnail', + 'order clause' => 'n.sticky DESC, n.title ASC', + ), + ); + $data['term_data']['gallery_oldest_thumbnail'] = array( + 'group' => t('Image gallery'), + 'field' => array( + 'title' => t('Oldest image'), + 'help' => t('The first posted image in the gallery or its child galleries.'), + 'handler' => 'image_gallery_handler_field_gallery_cover_thumbnail', + 'order clause' => 'n.sticky DESC, n.created ASC', + ), + ); + + // Cover from the gallery view sort order. TODO: better name! + $data['term_data']['gallery_cover_view_first_thumbnail'] = array( + 'group' => t('Image gallery'), + 'field' => array( + 'title' => t('Cover image (view)'), + 'help' => t('The cover thumbnail from the gallery, given by the gallery view sort order.'), + 'handler' => 'image_gallery_handler_field_gallery_cover_gallery_view_first', + ), + ); + + // Add a parent term argument to the term_hierarchy table. + // We need this because the Views relationship won't work for top-level + // terms that have no parent. See http://drupal.org/node/408180 for details. + $data['term_hierarchy']['image_gallery_parent'] = array( + 'real field' => 'parent', + 'title' => t('Parent term'), + 'help' => t('The parent term of the term. This can produce duplicate entries if you are using a vocabulary that allows multiple parents.'), + 'argument' => array( + 'handler' => 'views_handler_argument_numeric', + ), + ); + +} + +/** + * Implementation of hook_views_handlers(). + */ +function image_gallery_views_handlers() { + return array( + 'info' => array( + 'path' => drupal_get_path('module', 'image_gallery') . '/views', + ), + 'handlers' => array( + 'image_gallery_handler_field_gallery_count' => array( + 'parent' => 'views_handler_field_taxonomy', + ), + 'image_gallery_handler_field_gallery_cover' => array( + 'parent' => 'views_handler_field_taxonomy', + ), + 'image_gallery_handler_field_gallery_cover_thumbnail' => array( + 'parent' => 'image_gallery_handler_field_gallery_cover', + ), + 'image_gallery_handler_field_gallery_cover_latest_time' => array( + 'parent' => 'image_gallery_handler_field_gallery_cover', + ), + // uses gallery view to get first + // slightly skewed inheritance so we don't have to repeat all the image code + 'image_gallery_handler_field_gallery_cover_gallery_view_first' => array( + 'parent' => 'image_gallery_handler_field_gallery_cover_thumbnail', + ), + // gallery cover relationship + 'image_gallery_handler_relationship_gallery_cover' => array( + 'parent' => 'views_handler_relationship', + ), + // plugins + 'image_gallery_plugin_display_image_gallery' => array( + 'parent' => 'views_plugin_display_page', + ), + ), + ); +} + + +/** + * Implementation of hook_views_plugins(). + */ +function image_gallery_views_plugins() { + return array( + 'display' => array( + 'image_gallery' => array( + 'title' => t('Gallery'), + 'help' => t('Display the view as a gallery of images, with a URL and menu links.'), + 'handler' => 'image_gallery_plugin_display_image_gallery', + 'theme' => 'views_view', // TODO ?? + 'uses hook menu' => TRUE, + 'use ajax' => TRUE, + 'use pager' => TRUE, + 'accept attachments' => TRUE, + 'admin' => t('Page'), + 'help topic' => 'display-page', // TODO + 'parent' => 'page', + 'path' => drupal_get_path('module', 'image_gallery') . '/views', + + ), + ), + ); +} + + +/** + * Join handler for relationships that join with a subquery as the left field. + * To use this join, set 'left query' in the definition as a subquery to go on the + * left side of the JOIN condition, ie: + * LEFT JOIN node node_term_data ON ([YOUR SUBQUERY HERE]) = node_term_data.nid + */ +class image_gallery_join_subquery extends views_join { + // PHP 4 doesn't call constructors of the base class automatically from a + // constructor of a derived class. It is your responsibility to propagate + // the call to constructors upstream where appropriate. + function construct($table = NULL, $left_table = NULL, $left_field = NULL, $field = NULL, $extra = array(), $type = 'LEFT') { + parent::construct($table, $left_table, $left_field, $field, $extra, $type); + + $this->left_query = $this->definition['left query']; + } + + /** + * Build the SQL for the join this object represents. + */ + function join($table, &$query) { + $left = $query->get_table_info($this->left_table); + $output = " $this->type JOIN {" . $this->table . "} $table[alias] ON ($this->left_query) = $table[alias].$this->field"; + + // Tack on the extra. + if (isset($this->extra)) { + if (is_array($this->extra)) { + $extras = array(); + foreach ($this->extra as $info) { + $extra = ''; + // Figure out the table name. Remember, only use aliases provided + // if at all possible. + $join_table = ''; + if (!array_key_exists('table', $info)) { + $join_table = $table['alias'] . '.'; + } + elseif (isset($info['table'])) { + $join_table = $info['table'] . '.'; + } + + // And now deal with the value and the operator. Set $q to + // a single-quote for non-numeric values and the + // empty-string for numeric values, then wrap all values in $q. + $raw_value = $this->db_safe($info['value']); + $q = (empty($info['numeric']) ? "'" : ''); + + if (is_array($raw_value)) { + $operator = !empty($info['operator']) ? $info['operator'] : 'IN'; + // Transform from IN() notation to = notation if just one value. + if (count($raw_value) == 1) { + $value = $q . array_shift($raw_value) . $q; + $operator = $operator == 'NOT IN' ? '!=' : '='; + } + else { + $value = "($q" . implode("$q, $q", $raw_value) . "$q)"; + } + } + else { + $operator = !empty($info['operator']) ? $info['operator'] : '='; + $value = "$q$raw_value$q"; + } + $extras[] = "$join_table$info[field] $operator $value"; + } + + if ($extras) { + if (count($extras) == 1) { + $output .= ' AND ' . array_shift($extras); + } + else { + $output .= ' AND (' . implode(' ' . $this->extra_type . ' ', $extras) . ')'; + } + } + } + else if ($this->extra && is_string($this->extra)) { + $output .= " AND ($this->extra)"; + } + } + return $output; + } +} // class image_gallery_join_subquery + + +/** + * Gallery Display -- add the gallery view above the gallery image view + * + * also show, optionally, the gallery term description above its images + * + * IRC:: What's the best way to programatically insert code into a view header? + * hook_views_pre_render() and append to $view->display['mydisplay']->display_options['header'] + * + * + * + * + * + */ + +// end \ No newline at end of file Index: contributions/modules/image/contrib/image_gallery/views/image_gallery_handler_field_gallery_count.inc --- contributions/modules/image/contrib/image_gallery/views/image_gallery_handler_field_gallery_count.inc No Base Revision +++ contributions/modules/image/contrib/image_gallery/views/image_gallery_handler_field_gallery_count.inc Locally New @@ -0,0 +1,31 @@ +ensure_my_table(); + $this->add_additional_fields(); + } + + /** + * Returns field html. + */ + function render($values) { + $count = taxonomy_term_count_nodes($values->tid, 'image'); + $output = theme('image_gallery_count', $count); + return $this->render_link($output, $values); + } + +} + Index: contributions/modules/image/contrib/image_gallery/views/image_gallery_handler_field_gallery_cover.inc --- contributions/modules/image/contrib/image_gallery/views/image_gallery_handler_field_gallery_cover.inc No Base Revision +++ contributions/modules/image/contrib/image_gallery/views/image_gallery_handler_field_gallery_cover.inc Locally New @@ -0,0 +1,213 @@ +additional_fields['tid'] = 'tid'; + } + + function init(&$view, $options) { + parent::init($view, $options); + + $this->vid = _image_gallery_get_vid(); + + // The name of a key that is safe to use in $values to stash our nid. + // This is just a dummy that should be overridden. + // Groups of handlers that use the same query (eg, latest image and last + // update time) should override this to a safe key that they can share. + // This avoids running the query/ies to get the cover nid multiple times for + // each row of the view. + // TODO: doesn't work and probably can't ever. + if ($this->definition['cover group']) { + $this->cover_stash = $this->definition['cover group']; + } + else { + $this->cover_stash = 'image_gallery_cover'; + } + } + + function option_definition() { + $options = parent::option_definition(); + + $options['depth'] = array('default' => 0); + $options['descendants'] = array('default' => 'single'); + + return $options; + } + + function options_form(&$form, &$form_state) { + parent::options_form($form, $form_state); + + $form['descendants'] = array( + '#type' => 'radios', + '#title' => t('Descendant handling'), + '#description' => // COMING SOON theme('advanced_help_topic', 'image_gallery', 'descendants') . + t('How to handle images from subgalleries: either only choose a cover from this gallery itself, or consider subgalleries all together, or recurse into subgalleries if the gallery itself is empty.'), + '#options' => array( + 'single' => t('Only get a cover image from this gallery'), + 'flat' => t('Consider subgalleries, flattened.'), + 'recurse' => t('Consider subgalleries, recursively. (Warning: this can produce many queries per row if your parent galleries are empty!).'), + ), + '#default_value' => $this->options['descendants'], + ); + + $form['depth'] = array( + '#type' => 'weight', + '#title' => t('Depth'), + '#default_value' => $this->options['depth'], + '#description' => t('How deeply to go into subgalleries if one of the descendant options is selected above.'), + ); + + } + + /** + * Get the cover nid for the current tid. + * + * This makes up our query from the field definition and handler functions, + * and then runs it according to the descendant and depth options given + * for the field. + */ + function get_cover_node_nid($values) { + // The term id of the current gallery. + // This comes straight from the database row so should be safe for + // inclusion in a query. + $tid = $values->tid; + + // Get the basic query but only once for all rows of the view. + // This can be set in the handler definition, or in the handler class's + // get_cover_node_nid_query function for more complex cases. + // The handler definition takes priority over the function. + // This is stored in the handler object so we only have to get it + // once for the whole view. + if (!isset($this->basic_query)) { + if (isset($this->definition['basic query'])) { + $this->basic_query = $this->definition['basic query']; + } + else { + $this->basic_query = $this->get_cover_node_nid_query(); + } + } + + // If we don't have a query, return NULL now to prevent SQL errors. + if (is_null($this->basic_query)) { + return NULL; + } + + // Add the definition's ORDER clause, if there is one. + if ($this->definition['order clause']) { + $this->basic_query = str_replace('***ORDER_CLAUSE***', $this->definition['order clause'], $this->basic_query); + } + + // Add our WHERE clause. + switch ($this->options['descendants']) { + // Plain: only consider this gallery. + // Recursive: only consider this gallery (we'll recurse later) + case 'single': + case 'recurse': + $where_clause = "tn.tid = $tid "; + $query = str_replace('***WHERE_CLAUSE***', $where_clause, $this->basic_query); + break; + // Flat: all descendant galleries considered for the cover query. + case 'flat': + $tree = taxonomy_get_tree($this->vid, $tid, -1, $this->options['depth']); + $descendant_tids = array_merge(array($tid), array_map('_taxonomy_get_tid_from_term', $tree)); + // The values of $descendant_tids should be safe for raw inclusion in the + // SQL since they're all loaded from integer fields in the database. + $where_clause = 'tn.tid IN (' . implode(',', $descendant_tids) . ')'; + $query = str_replace('***WHERE_CLAUSE***', $where_clause, $this->basic_query); + break; + } + + #dsm($query); + + // Run the query to get the cover nid. + if ($nid = db_result(db_query_range(db_rewrite_sql($query), '', 0, 1))) { + return $nid; + } + + // We have no nid: the gallery is empty. Should we recurse? + if ($this->options['descendants'] == 'recurse' && $this->options['depth'] > 0) { + $nid = $this->get_cover_node_nid_recurse($tid, 1); + return $nid; + } + } + + /** + * Recursively query descendant tids until we get a cover nid. + * + * Warning! This is probably quite intensive, as it drills down the term + * hierarchy doing a query on each term until it finds a node -- and this is + * done for EVERY row of the main gallery term view! + * + * @param $tid The tid whose children we should investigate for a cover nid. + * @param $recurse The current recursion depth. + */ + function get_cover_node_nid_recurse($tid, $recurse) { + $tree = taxonomy_get_tree($this->vid, $tid, -1, 1); + foreach ($tree as $term) { + $where_clause = 'tn.tid = ' . $term->tid; + $query = str_replace('***WHERE_CLAUSE***', $where_clause, $this->basic_query); + if ($nid = db_result(db_query_range(db_rewrite_sql($query), '', 0, 1))) { + return $nid; + } + + // Recurse into this gallery, if we may. + if ($this->options['depth'] > $recurse) { + if ($nid = $this->get_cover_node_nid_recurse($term->tid, $recurse + 1)) { + return $nid; + } + } + } + } + + /** + * The query this handler should use to gets its cover node id, unless + * the field definition specifies one. + * + * The return string should include a placeholder for the WHERE clause + * as in this basic case. This is where the tid(s) will go. + * The order clause should be supplied by the handler definition. + * Warning: this is NOT sophisticated stuff. The WHERE clause inserted into + * this string will expect to find a row "tn.tid" in the query. + */ + function get_cover_node_nid_query() { + return 'SELECT n.nid from {node} n INNER JOIN {term_node} tn ON n.nid = tn.nid ' . + "WHERE ***WHERE_CLAUSE*** AND n.type = 'image' AND n.status = 1 " . + 'ORDER BY ***ORDER_CLAUSE***'; + } + + /** + * Override query() so we don't query: fake field. + */ + function query() { + $this->ensure_my_table(); + $this->add_additional_fields(); + } + + /** + * Returns field html. Just a dummy to inherit. + */ + function render($values) { + $nid = $this->get_cover_node_nid($values); + return $nid; + } +} \ No newline at end of file Index: contributions/modules/image/contrib/image_gallery/views/image_gallery_handler_field_gallery_cover_gallery_view_first.inc --- contributions/modules/image/contrib/image_gallery/views/image_gallery_handler_field_gallery_cover_gallery_view_first.inc No Base Revision +++ contributions/modules/image/contrib/image_gallery/views/image_gallery_handler_field_gallery_cover_gallery_view_first.inc Locally New @@ -0,0 +1,97 @@ +preview stuff + $gallery_view->preview = TRUE; + $gallery_view->set_display('preview'); + + // must set $args + #$args = array($tid); + +/* + * + * + * $preview = $view->preview($form_state['display_id'], $args); + + // Get information from the preview for display. + if (!empty($view->build_info['query'])) { + $rows = array(); + $query = db_prefix_tables($view->build_info['query']); + + */ + + #dsm($gallery_view); + #$gallery_view->pre_execute($args); + + // ugh!!! + //$gallery_view->display['default']->display_options[''] + + // calls DISPLAY->execute + $gallery_view->build('default'); // Build the query + // gets us a query obj. + // and builds up the query too! too much, can't alter it! + + + + + // can we add a WHERE here???? + // $this->query->add_where(0, "$this->table_alias.$this->real_field IN ($subquery$where )", $args); + $gallery_view->query->add_where(0, "45 = 45"); + // nope! + + // nicked from views admin.inc + $query = db_prefix_tables($gallery_view->build_info['query']); + if ($gallery_view->build_info['query_args']) { + _db_query_callback($gallery_view->build_info['query_args'], TRUE); + $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query); + } + + + # dsm($gallery_view->build_info); + #dsm($gallery_view->build_info['query']); + #dsm($query); + + ####!!! this gets us the query string! + ## stash it and play with it ;) + + // override the set number of items per page to just get the first one. + $gallery_view->pager['items_per_page'] = 1; + // Some streamlining could be done here: execute does paging and allsorts. + $gallery_view->execute(); // Run the query + $gallery_view->post_execute(); + + //dsm($gallery_view->result); + + $cover_nid = $gallery_view->result[0]->nid; + + // We need to insert some placeholders + // Some assumptions: + // - the query already has a WHERE -- because image galleries + // filter on node type at the very least! + // - the query has an ORDER BY clause -- because if your gallery has no + // order why do you want to use its order here? + // - the query doesn't have a join to term_node -- the gallery view only + // adds this when the argument is present. + $query = str_replace('WHERE', "INNER JOIN {term_node} tn ON node.nid = tn.nid \n WHERE", $query); + $query = str_replace('ORDER BY', " AND ***WHERE_CLAUSE***\n ORDER BY", $query); + + #dsm($query); + + return $query; + } +} Index: contributions/modules/image/contrib/image_gallery/views/image_gallery_handler_field_gallery_cover_latest_time.inc --- contributions/modules/image/contrib/image_gallery/views/image_gallery_handler_field_gallery_cover_latest_time.inc No Base Revision +++ contributions/modules/image/contrib/image_gallery/views/image_gallery_handler_field_gallery_cover_latest_time.inc Locally New @@ -0,0 +1,21 @@ +get_cover_node_nid($values); + + $latest_node = node_load($nid); + if ($latest_node->changed) { + $output = theme('image_gallery_updated', $latest_node->changed); + return $this->render_link($output, $values); + } + } +} Index: contributions/modules/image/contrib/image_gallery/views/image_gallery_handler_field_gallery_cover_thumbnail.inc --- contributions/modules/image/contrib/image_gallery/views/image_gallery_handler_field_gallery_cover_thumbnail.inc No Base Revision +++ contributions/modules/image/contrib/image_gallery/views/image_gallery_handler_field_gallery_cover_thumbnail.inc Locally New @@ -0,0 +1,53 @@ + array(IMAGE_THUMBNAIL)); + + return $options; + } + + /** + * Extends the field's basic options with more image specific + * options. + */ + function options_form(&$form, &$form_state) { + parent::options_form($form, $form_state); + + foreach (image_get_sizes() as $key => $size) { + $sizes[$key] = $size['label']; + } + $form['image_derivative'] = array( + '#type' => 'select', + '#title' => t('Image size to show'), + '#options' => $sizes, + '#default_value' => $this->options['image_derivative'], + '#description' => t('Pick an image derivative to display.') + ); + } + + /** + * Returns field html. + */ + function render($values) { + $nid = $this->get_cover_node_nid($values); + + $latest_node = node_load($nid); + $output = image_display($latest_node, $this->options['image_derivative']); + return $nid . $this->render_link($output, $values); + } + +} + Index: contributions/modules/image/contrib/image_gallery/views/image_gallery_handler_relationship_gallery_cover.inc --- contributions/modules/image/contrib/image_gallery/views/image_gallery_handler_relationship_gallery_cover.inc No Base Revision +++ contributions/modules/image/contrib/image_gallery/views/image_gallery_handler_relationship_gallery_cover.inc Locally New @@ -0,0 +1,196 @@ + array( + * 'title' => t('Latest image'), + * 'label' => t('Cover image, latest'), + * 'help' => t('Relate an image gallery to its most recently updated node (does not consider child galleries).'), + * 'handler' => 'image_gallery_handler_relationship_gallery_cover', + * 'base' => 'node', + * 'field' => 'nid', + * 'correlated field' => 'tid', + * 'subquery order' => ' ORDER BY gallery_cover_node.changed DESC ', + * ) + * This example gets you a cover image that is the latest changed node. + * + * If you need a different query, subclass this handler and override the + * left_query() method to return your own subquery on which to join. + */ +class image_gallery_handler_relationship_gallery_cover extends views_handler_relationship { + /** + * Defines default values for options. + */ + function option_definition() { + $options = parent::option_definition(); + + $options['depth'] = array('default' => array(1)); + + return $options; + } + + /** + * Extends the field's basic options with more image specific + * options. + */ + function options_form(&$form, &$form_state) { + parent::options_form($form, $form_state); + + $form['depth'] = array( + '#type' => 'weight', + '#title' => t('Depth'), + '#default_value' => $this->options['depth'], + '#description' => t('The depth will determine how deep to look into descendant galleries to cover nodes.' . + 'There is no recursion: so setting the depth to 1 will choose the best fitting node out of the pool of images in the gallery and its children taken all together.' . + 'Setting this to 0 will only consider the gallery itself.' + ), + ); + } + + /** + * Return the subquery to use for the left side of the relationship join clause. + * + */ + function left_query() { + $order = $this->definition['subquery order']; + $field = $this->definition['correlated field']; + $where_tid = $this->table_alias . '.' . $field; + + + /* + // simple version + $subquery = 'SELECT gallery_cover_node.nid FROM ' . + '{term_node} gallery_cover_term_node INNER JOIN ' . + ' {node} gallery_cover_node ' . + 'ON gallery_cover_term_node.nid = gallery_cover_node.nid ' . + 'WHERE gallery_cover_node.status = 1 AND ' . + 'gallery_cover_term_node.tid = ' . $where_tid . ' ' . + $order . + 'LIMIT 1'; + */ + // now rip it up! + + $subquery = "\nSELECT gallery_cover_node.nid FROM " . + "{term_node} gallery_cover_term_node INNER JOIN {node} gallery_cover_node \n" . + "ON gallery_cover_term_node.nid = gallery_cover_node.nid "; + $where = " WHERE gallery_cover_node.status = 1 AND " . + "gallery_cover_term_node.tid = $where_tid "; + + // Depth: this is shamelessly ripped from views_handler_argument_term_node_tid_depth + if ($this->options['depth'] > 0) { + $subquery .= " LEFT JOIN {term_hierarchy} th ON th.tid = gallery_cover_term_node.tid\n"; + $last = "th"; + foreach (range(1, abs($this->options['depth'])) as $count) { + $subquery .= " LEFT JOIN {term_hierarchy} th$count ON $last.parent = th$count.tid\n"; + $where .= "\n OR th$count.tid = $where_tid\n"; + $last = "th$count"; + } + } + else if ($this->options['depth'] < 0) { + $last = "tn"; + foreach (range(1, abs($this->options['depth'])) as $count) { + $subquery .= " LEFT JOIN {term_hierarchy} th$count ON $last.tid = th$count.parent\n"; + $where .= "\n OR th$count.tid = $where_tid\n"; + $last = "th$count"; + } + } + $subquery = "$subquery $where $order LIMIT 1"; + + dsm($subquery); + + return $subquery; + } + + /** + * Called to implement a relationship in a query. + */ + function query() { + // Figure out what base table this relationship brings to the party. + $table_data = views_fetch_data($this->definition['base']); + $base_field = empty($this->definition['base field']) ? $table_data['table']['base']['field'] : $this->definition['base field']; + + $this->ensure_my_table(); + + $def = $this->definition; + $def['table'] = $this->definition['base']; + $def['field'] = $base_field; + $def['left_table'] = $this->table_alias; + $def['left_field'] = $this->field; + if (!empty($this->options['required'])) { + $def['type'] = 'INNER'; + } + + if (!empty($this->definition['left query'])) { + $def['left query'] = $this->definition['left query']; + } + else { + $def['left query'] = $this->left_query(); + } + + if (!empty($def['join_handler']) && class_exists($def['join_handler'])) { + $join = new $def['join_handler']; + } + else { + $join = new image_gallery_join_subquery(); + } + + $join->definition = $def; + $join->construct(); + $join->adjusted = TRUE; + + // use a short alias for this: + $alias = $def['table'] . '_' . $this->table; + + $this->alias = $this->query->add_relationship($alias, $join, $this->definition['base'], $this->relationship); + } +} + +/** + * Subclass example. + */ +/* +class image_gallery_handler_relationship_gallery_cover_example extends views_handler_relationship { + function left_query($field) { + $order = $this->definition['left query order']; + $sub_query = 'SELECT gallery_cover_node.nid FROM ' . + '{term_node} gallery_cover_term_node INNER JOIN ' . + ' {node} gallery_cover_node ' . + 'ON gallery_cover_term_node.nid = gallery_cover_node.nid ' . + 'WHERE gallery_cover_node.status = 1 AND ' . + 'gallery_cover_term_node.tid = ' . $field . ' ' . + $order . + 'LIMIT 1'; + + return $sub_query; + } +*/ Index: contributions/modules/image/contrib/image_gallery/views/image_gallery_plugin_display_image_gallery.inc --- contributions/modules/image/contrib/image_gallery/views/image_gallery_plugin_display_image_gallery.inc No Base Revision +++ contributions/modules/image/contrib/image_gallery/views/image_gallery_plugin_display_image_gallery.inc Locally New @@ -0,0 +1,24 @@ +