Commit 51220300 authored by merlinofchaos's avatar merlinofchaos
Browse files

Sync from HEAD

parent 01cfda8c
......@@ -102,3 +102,20 @@ Views 5.x-1.4-rc1
o 103649: allow customizing date interval granularity
Views --dev
Bugs fixed:
o 109456: Match API documentation on 'field' definition on fields.
o 104459: Correct theme wizard field names.
o 104854: Fixed $arg at the beginning of the URL *again*
o 107855: Removed double check_plain in RSS feed titles.
o 107723: Removed use of IDs on table fields -- this might require your CSS files to be adjusted!
o 107713: Popular recent and popular alltime are now disabled by default.
o 106460: Update of module weight was not run on install of 1.4, causing taxonomy/term view to not override Drupal default.
o 107974: Ensure file_revisions table is added to query when using 'node has files' filter.
o 107371: Correct spelling of 'weather' to 'whether'.
o 107218: 107217: Fixed some E_NOTICE errors.
o 106464: Taxonomy links showed up as Array | Array | Array rather than the taxonomy terms.
o 110212: Text patch to clarify date fields.
New features:
o 107471: Spiffy new theme wizard features. Thanks Crell!!
......@@ -141,7 +141,7 @@ function comment_views_tables() {
'value' => views_handler_filter_date_value_form(),
'handler' => 'views_handler_filter_timestamp',
'option' => 'string',
'help' => t('This filter allows nodes to be filtered by the last comment timestamp. Enter dates in the format: CCYY-MM-DD HH:MM:SS. Enter \'now\' to use the current time. You may enter a delta (in seconds) to the option that will be added to the time; this is most useful when combined with now. If you have the jscalendar module from jstools installed, you can use a popup date picker here.'),
'help' => t('This filter allows nodes to be filtered by the timestamp for the last comment or node edit. The "Value" can either be a date in the format: CCYY-MM-DD HH:MM:SS or the word "NOW" to use the current time. You may enter a positive or negative number in the "Option" field that will represent the amount of seconds that will be added or substracted to the time; this is most useful when combined with "NOW". If you have the jscalendar module from jstools installed, you can use a popup date picker here.'),
),
'last_changed' => array(
'name' => t('Comment: Last Changed Time'),
......@@ -149,7 +149,7 @@ function comment_views_tables() {
'value' => views_handler_filter_date_value_form(),
'handler' => 'views_handler_filter_last_changed',
'option' => 'string',
'help' => t('This filter allows nodes to be filtered by the timestamp for the last comment or node edit. Enter dates in the format: CCYY-MM-DD HH:MM:SS. Enter \'now\' to use the current time. You may enter a delta (in seconds) to the option that will be added to the time; this is most useful when combined with now. If you have the jscalendar module from jstools installed, you can use a popup date picker here.'),
'help' => t('This filter allows nodes to be filtered by the timestamp for the last comment or node edit. The "Value" can either be a date in the format: CCYY-MM-DD HH:MM:SS or the word "NOW" to use the current time. You may enter a positive or negative number in the "Option" field that will represent the amount of seconds that will be added or substracted to the time; this is most useful when combined with "NOW". If you have the jscalendar module from jstools installed, you can use a popup date picker here.'),
),
),
......@@ -209,6 +209,7 @@ function views_query_handler_field_last_comment_name($field, $fieldinfo, &$query
}
function views_handler_field_last_comment_name($fieldinfo, $fielddata, $value, $data) {
$obj = new stdClass();
$obj->name = $value;
$uidfield = $fielddata['tablename'] . "_" . $fieldinfo['uid'];
$obj->uid = $data->$uidfield;
......@@ -259,6 +260,7 @@ function views_handler_field_commentlink_with_mark($fieldinfo, $fielddata, $valu
* Format a field as a comment
*/
function views_handler_field_comment($fieldinfo, $fielddata, $value, $data) {
$obj = new stdClass();
$obj->comment = check_markup($data->comments_comment, $data->comments_format, FALSE);
comment_invoke_comment($obj, 'view');
return $obj->comment;
......
......@@ -64,6 +64,7 @@ function statistics_views_arguments() {
function statistics_views_default_views() {
$view = new stdClass();
$view->name = 'popular_recent';
$view->disabled = TRUE;
$view->description = t('Nodes sorted by recent page-views');
$view->access = array (
);
......@@ -152,6 +153,7 @@ function statistics_views_default_views() {
$view = new stdClass();
$view->name = 'popular_alltime';
$view->disabled = TRUE;
$view->description = t('Nodes sorted by total page-views');
$view->access = array (
);
......
......@@ -249,12 +249,14 @@ function views_handler_field_allterms($fieldinfo, $fielddata, $value, $data) {
foreach ($terms as $term) {
$links[] = check_plain($term->name);
}
$links = !empty($links) ? implode(' | ', $links) : '';
}
else {
$node = new stdClass();
$node->taxonomy = $terms;
$links = taxonomy_link('taxonomy terms', $node);
$links = theme('links', taxonomy_link('taxonomy terms', $node));
}
return !empty($links) ? implode(' | ', $links) : '';
return $links;
}
/**
......
......@@ -37,14 +37,14 @@ function upload_views_tables() {
'list' => 'views_handler_operator_yesno',
'list-type' => 'select',
'handler' => 'views_handler_file_filter_fid_exist',
'help' => t('Filter weather the node has files for download'),
'help' => t('Filter whether the node has files for download'),
),
'list' => array(
'name' => t('File: Listed in file downloads'),
'operator' => array('=' => t('Equals')),
'list' => 'views_handler_operator_yesno',
'list-type' => 'select',
'help' => t('Filter weather the file is listed in downloads'),
'help' => t('Filter whether the file is listed in downloads'),
),
),
);
......@@ -157,6 +157,7 @@ function views_handler_file_filename_download($fieldinfo, $fielddata, $value, $d
function views_handler_file_filter_fid_exist($op, $filter, $filterdata, &$query) {
switch ($op) {
case 'handler':
$query->ensure_table('file_revisions');
if ($filter['value']) {
$query->add_where('file_revisions.fid');
}
......
......@@ -184,6 +184,7 @@ function user_views_query_substitutions($view) {
* specified in the field info.
*/
function views_handler_field_username($fieldinfo, $fielddata, $value, $data) {
$obj = new stdClass();
$uidfield = $fielddata['tablename'] . "_" . $fieldinfo['uid'];
if (!$value && $data->$uidfield) {
$obj = user_load(array('uid' => $data->$uidfield));
......
......@@ -103,7 +103,7 @@ function views_reset_inline_args_cache($locale = 'en') {
while ($view = db_fetch_object($result)) {
// Skip over any non-argument views
if (strrpos($view->url, '$arg') == FALSE) {
if (strrpos($view->url, '$arg') === FALSE) {
continue;
}
// unpack the array
......@@ -128,7 +128,7 @@ function views_reset_inline_args_cache($locale = 'en') {
foreach ($default_views as $name => $view) {
if ($view->page && !$used[$name] && ($views_status[$name] == 'enabled' || (!$view->disabled && $views_status[$name] != 'disabled'))) {
if (strrpos($view->url, '$arg')) {
if (strrpos($view->url, '$arg') !== FALSE) {
$views_with_inline_args[$view->name] = $view;
}
}
......@@ -1136,8 +1136,7 @@ function _views_construct_header($view, $fields) {
}
// Add CSS id to table cell header cell.
$header['id'] = views_css_safe('view-field-'. $field['queryname']);
$header['class'] = "view-cell-header";
$header['class'] = "view-cell-header" . views_css_safe(' view-field-'. $field['queryname']);
$headers[] = $header;
}
return $headers;
......
......@@ -90,7 +90,7 @@ function _views_view_build_filters(&$query, &$view) {
foreach($view->exposed_filter as $count => $expose) {
if ($filter['id'] == $expose['id']) {
$id = $expose['id'];
if (isset($view->exposed_filter_offset)) {
$count += $view->exposed_filter_offset;
}
......@@ -125,7 +125,7 @@ function _views_view_build_filters(&$query, &$view) {
$replace = array('&gt;' => '>', '&lt;' => '<');
$filter['operator'] = strtr($filter['operator'], $replace);
if (function_exists($filterinfo['handler'])) {
$filterinfo['handler']('handler', $filter, $filterinfo, $query);
}
......@@ -223,7 +223,12 @@ function _views_view_build_fields(&$query, &$view) {
}
if (!$fieldinfo['notafield']) {
$query->add_field($field['field'], $field['tablename'], $field['queryname']);
if ($fieldinfo['field']) {
$query->add_field($fieldinfo['field'], $field['tablename'], $field['queryname']);
}
else {
$query->add_field($field['field'], $field['tablename'], $field['queryname']);
}
}
// special handling
if (is_array($fieldinfo['addlfields'])) {
......@@ -232,7 +237,7 @@ function _views_view_build_fields(&$query, &$view) {
}
}
$plugins = _views_get_style_plugins();
if (($view->page && $plugins[$view->page_type]['needs_table_header']) ||
if (($view->page && $plugins[$view->page_type]['needs_table_header']) ||
($view->block && $plugins[$view->block_type]['needs_table_header'])) { // table only
$view->table_header = _views_construct_header($view, $fields);
$query->set_header($view->table_header);
......@@ -568,14 +573,14 @@ class _views_query {
$joininfo = (!$this->joins[$table][$table_num] ?
$table_data[$table]['join'] : $this->joins[$table][$table_num]);
$left_table_alias = isset($joininfo['left']['alias']) ? $joininfo['left']['alias'] : $tinfo['alias_prefix'];
$left_table_alias .= $joininfo['left']['table'];
// the { is a special character which seems to be treated differently
// in PHP5 than PHP4 so we do this a little oddly.
$join_type = $joininfo['type'] == 'inner' ? 'INNER' : 'LEFT';
$joins .= " $join_type JOIN {" . $table_real . "} $table_alias ON " . $left_table_alias .".".
$joins .= " $join_type JOIN {" . $table_real . "} $table_alias ON " . $left_table_alias .".".
$joininfo['left']['field'] . " = $table_alias." . $joininfo['right']['field'];
if (isset($joininfo['extra'])) {
......
......@@ -96,9 +96,11 @@ function theme_views_rss_feed($view, $nodes, $type) {
global $base_url;
$channel = array(
'title' => check_plain(views_get_title($view, 'page')),
// a check_plain isn't required on these because format_rss_channel
// already does this.
'title' => views_get_title($view, 'page'),
'link' => url($view->real_url, NULL, NULL, true),
'description' => check_plain($view->description),
'description' => $view->description,
);
$item_length = variable_get('feed_item_length', 'teaser');
......
......@@ -33,89 +33,202 @@ function views_theme_wizard_page() {
return drupal_get_form('views_theme_wizard_form', $views);
}
function views_theme_wizard_form($views) {
function views_theme_wizard_form($views, $form_values = array()) {
$form = array();
if (!isset($form_values['step'])) {
$step = 1;
}
else {
$step = $form_values['step'];
}
$form['markup'] = array(
'#value' => t('<p>The views theming wizard generates code that you can use in your phptemplate theme to help you customize the output of a view. Simply select a theme and it will generate code for your template.php as well as template files for the individual views.</p><p>At this time this code assumes your view is a <b>list type view</b>! It may not generate effective code for other types of views. Future versions of this program will be smarter, and give more options, but this wizard is still a huge start.</p>'),
'#weight' => 0,
);
$form['vid'] = array(
'#type' => 'select',
'#options' => $views,
'#title' => t('Select a view'),
'#weight' => 5,
);
$form['code1'] = array(
'#type' => 'markup',
'#value' => '',
);
$form['code2'] = array(
'#type' => 'markup',
'#value' => '',
);
$form['code3'] = array(
'#type' => 'markup',
'#value' => '',
);
$form['submit'] = array(
'#type' => 'button',
'#value' => t('Generate Theme'),
'#weight' => 10,
);
$form['submit2'] = array(
'#type' => 'button',
'#value' => t('List Theme Fields'),
'#weight' => 10,
);
$form['#after_build'] = array(
'views_theme_wizard_generate',
);
$op = isset($form_values['op']) ? $form_values['op'] : '';
while ($step != 0) {
if (1 == $step) {
$form['step'] = array(
'#type' => 'hidden',
'#value' => $step,
);
$form['vid'] = array(
'#type' => 'select',
'#options' => $views,
'#title' => t('Select a view'),
'#weight' => 5,
);
$form['theme_type'] = array(
'#type' => 'select',
'#title' => t('Select Theme Type'),
'#options' => views_theme_wizard_get_theme_types(),
'#weight' => 6,
);
$form['submit'] = array(
'#type' => 'button',
'#value' => t('Select Theme Type'),
'#weight' => 10,
);
$form['submit2'] = array(
'#type' => 'button',
'#value' => t('List Theme Fields'),
'#weight' => 11,
);
$form['step'] = array(
'#type' => 'hidden',
'#value' => $step + 1,
);
$step = 0;
}
elseif (2 == $step && $op == t('List Theme Fields')) {
$view = views_get_view($form_values['vid']);
$form['code1']['#type'] = 'textarea';
$form['code1']['#value'] = views_theme_wizard_list_fields($view);
$form['code1']['#title'] = t('This is a list of all the theme functions you can use to override individual field displays');
$form['code1']['#rows'] = 20;
$form['code2']['#type'] = 'textarea';
$form['code2']['#value'] = views_theme_wizard_example_field($view);
$form['code2']['#title'] = t('This is a basic theme function', array('@s' => $view->name));
$form['code2']['#rows'] = 20;
$step = 0;
}
elseif (2 == $step && $op = t('Select Theme Type')) {
$view = views_get_view($form_values['vid']);
$type = $form_values['theme_type'];
$additions = module_invoke_all('views_theme_wizard_types', 'configure', $type, $view);
if (! $additions) {
$step = 3;
continue;
}
$form['theme_type'] = array(
'#type' => 'hidden',
'#value' => $type,
);
$form['vid'] = array(
'#type' => 'hidden',
'#value' => $form_values['vid'],
);
foreach ($additions as $k => $v) {
$form[$k] = $v;
}
$form['generate'] = array(
'#type' => 'button',
'#value' => t('Generate Theme'),
'#weight' => 10,
);
$form['step'] = array(
'#type' => 'hidden',
'#value' => $step + 1,
);
$step = 0;
}
elseif (3 == $step) {
$view = views_get_view($form_values['vid']);
$form['code1']['#type'] = 'textarea';
$form['code1']['#value'] = views_theme_wizard_generate_list_code($form_values['theme_type'], $view, $form_values);
$form['code1']['#title'] = t('This code goes in your template.php file');
$form['code1']['#rows'] = 20;
$form['code2']['#type'] = 'textarea';
$form['code2']['#value'] = views_theme_wizard_generate_list_template_code($view);
$form['code2']['#title'] = t('This code goes in a file named views-list-@s.tpl.php', array('@s' => $view->name));
$form['code2']['#rows'] = 20;
$form['code3']['#type'] = 'textarea';
$form['code3']['#value'] = views_theme_wizard_generate_list_stylesheet_code($view);
$form['code3']['#title'] = t('This code goes in a file named views-list-@s.css', array('@s' => $view->name));
$form['code3']['#rows'] = 20;
$step = 0;
}
}
$form['#multistep'] = TRUE;
$form['#redirect'] = FALSE;
return $form;
}
function views_theme_wizard_generate($form, $form_values) {
$view = views_get_view($form_values['vid']);
if (!$view) {
return $form;
}
$op = $_POST['op'];
if ($op == t('Generate Theme')) {
$form['code1']['#type'] = 'textarea';
$form['code1']['#value'] = views_theme_wizard_generate_list_code($view);
$form['code1']['#title'] = t('This code goes in your template.php file');
$form['code1']['#rows'] = 20;
$form['code2']['#type'] = 'textarea';
$form['code2']['#value'] = views_theme_wizard_generate_list_template_code($view);
$form['code2']['#title'] = t('This code goes in a file named views-list-%s.tpl.php', array('%s' => $view->name));
$form['code2']['#rows'] = 20;
$form['code3']['#type'] = 'textarea';
$form['code3']['#value'] = views_theme_wizard_generate_list_stylesheet_code($view);
$form['code3']['#title'] = t('This code goes in a file named views-list-%s.css', array('%s' => $view->name));
$form['code3']['#rows'] = 20;
}
function views_theme_wizard_get_theme_types() {
$types = module_invoke_all('views_theme_wizard_types', 'list');
ksort($types);
return $types;
}
if ($op == t('List Theme Fields')) {
$form['code1']['#type'] = 'textarea';
$form['code1']['#value'] = views_theme_wizard_list_fields($view);
$form['code1']['#title'] = t('This is a list of all the theme functions you can use to override individual field displays');
$form['code1']['#rows'] = 20;
$form['code2']['#type'] = 'textarea';
$form['code2']['#value'] = views_theme_wizard_example_field($view);
$form['code2']['#title'] = t('This is a basic theme function', array('%s' => $view->name));
$form['code2']['#rows'] = 20;
function views_theme_wizard_views_theme_wizard_types($op='list', $delta='', $view=NULL, $options = array()) {
switch($op) {
case 'list':
if ('list' == $op) {
return array(
'simple' => t('Simple List'),
'grouped' => t('Grouped List'),
'tree' => t('Nested Tree'),
);
}
case 'configure':
switch ($delta) {
case 'simple':
break;
case 'grouped':
$options = array();
foreach ($view->field as $field) {
$options[$field['queryname']] = $field['label'] ? $field['label'] : $field['queryname'];
}
$form['group_field'] = array(
'#type' => 'select',
'#title' => t('Select the field on which to group'),
'#options' => $options,
);
$form['test'] = array('#type'=>'markup');
return $form;
break;
case 'tree':
$options = array();
foreach ($view->field as $field) {
$options[$field['queryname']] = $field['label'] ? $field['label'] : $field['queryname'];
}
$form['tree_key_field'] = array(
'#type' => 'select',
'#title' => t('Select the field to use as the ID for each row (usually nid)'),
'#options' => $options,
);
$form['tree_reference_field'] = array(
'#type' => 'select',
'#title' => t('Select the field that refers to the parent node by the ID field'),
'#options' => $options,
);
return $form;
break;
}
break;
case 'code':
switch ($delta) {
case 'simple':
return views_theme_wizard_type_generate_code_simple($view);
break;
case 'grouped':
return views_theme_wizard_type_generate_code_grouped($view, $options);
break;
case 'tree':
return views_theme_wizard_type_generate_code_tree($view, $options);
break;
}
break;
}
return $form;
}
function views_theme_wizard_list_fields($view) {
......@@ -156,9 +269,10 @@ EOT;
return $output;
}
function views_theme_wizard_generate_list_code($view) {
function views_theme_wizard_generate_list_code($theme_type, $view, $options) {
$now = format_date(time());
$code = <<<EOT
$header = <<<EOT
/**
* views template to output a view.
* This code was generated by the views theming wizard
......@@ -167,6 +281,17 @@ function views_theme_wizard_generate_list_code($view) {
*
* This function goes in your template.php file
*/
EOT;
$function = module_invoke_all('views_theme_wizard_types', 'code', $theme_type, $view, $options);
return $header . implode($function);
}
function views_theme_wizard_type_generate_code_simple($view) {
$code = <<<EOT
function phptemplate_views_view_list_{$view->name}(\$view, \$nodes, \$type) {
\$fields = _views_get_fields();
......@@ -207,6 +332,143 @@ function phptemplate_views_view_list_{$view->name}(\$view, \$nodes, \$type) {
}
}
EOT;
return $code;
}
function views_theme_wizard_type_generate_code_grouped($view, $options) {
$group_field = $options['group_field'];
$code = <<<EOT
function phptemplate_views_view_list_{$view->name}(\$view, \$nodes, \$type) {
\$fields = _views_get_fields();
\$taken = array();
// Group our nodes
\$set = array();
foreach (\$nodes as \$node) {
\$set[\$node->{$group_field}][] = \$node;
}
// Set up the fields in nicely named chunks.
foreach (\$view->field as \$id => \$field) {
\$field_name = \$field['field'];
if (isset(\$taken[\$field_name])) {
\$field_name = \$field['queryname'];
}
\$taken[\$field_name] = true;
\$field_names[\$id] = \$field_name;
}
// Set up some variables that won't change.
\$base_vars = array(
'view' => \$view,
'view_type' => \$type,
);
\$output = '';
foreach (\$set as \$label => \$nodes) {
\$items = array();
foreach (\$nodes as \$i => \$node) {
\$vars = \$base_vars;
\$vars['node'] = \$node;
\$vars['count'] = \$i;
\$vars['stripe'] = \$i % 2 ? 'even' : 'odd';
foreach (\$view->field as \$id => \$field) {
\$name = \$field_names[\$id];
\$vars[\$name] = views_theme_field('views_handle_field', \$field['queryname'], \$fields, \$field, \$node, \$view);
if (isset(\$field['label'])) {
\$vars[\$name . '_label'] = \$field['label'];
}
}
\$items[] = _phptemplate_callback('views-list-{$view->name}', \$vars);
}
if (\$items) {
\$output .= theme('item_list', \$items, \$label);
}
}
return \$output;
}
EOT;
return $code;
}
function views_theme_wizard_type_generate_code_tree($view, $options) {
$tree_key_field = $options['tree_key_field'];
$tree_reference_field = $options['tree_reference_field'];
$code = <<<EOT
function phptemplate_views_view_list_{$view->name}(\$view, \$nodes, \$type, \$parent=NULL) {
\$fields = _views_get_fields();
\$taken = array();
// Normalize the top level of nodes to all point to 0 as their parent
// We only have to do this on the top-level pass, because otherwise it's
// irrelevant.
if (!isset(\$parent)) {
\$parents = array();
foreach (\$nodes as \$node) {
\$parents[] = \$node->{$tree_key_field};
}
foreach (\$nodes as \$node) {