I am trying to modify the link module to include a date field which has a popup. I have looked far and wide in the docs, and I am close, things save, and display (formatting issues I will get to later), but when you click submit it errors with the following:
* warning: mb_strlen() expects parameter 1 to be string, array given in /var/www/clubs/includes/unicode.inc on line 370.
I set up http://lullabot.com/articles/quick_and_dirty_debugging (woohoo!) to help me backtrace it, and it gives me 7.2MB of text (obviously a lot to weed through). The relevant part is, well not sure, but the beginning is that it is erroring in _form_validate in form.inc - the date is an array, not a value. The neat part of this is that field_date is a normal date_popup field added to the cck type, and it is an almost identical date array (about 35 lines down) as the one that blows up (about another 35 lines down). Now the real question. I have the form part correct, it came right out of your wonderful docs, but I am missing stuff in the process or validate or some hook part. What am I supposed to do to get it to not be an array? Since it is an API (5.x v2 RC3) I am sure there is a function I am supposed to call that will change it from an array to a string in hook_process or validate or some such. What might it be (or where would I look)? As far as the formatting problems, what do I call in the formatter that will format the date the way I have the form set up? Sorry for the long post, just wanted to provide as much supporting docs as I could. Thanks for all your hard work on these collection of modules. They are amazing (if only I could wrap my brain around them...).
liveoutloud2day
--------------- diff of link module (so you can see what little I changed) -------------------
--- link.module.orig 2008-07-15 14:50:41.000000000 -0400
+++ link.module 2008-07-15 16:01:49.000000000 -0400
@@ -154,6 +154,8 @@
return array(
'url' => array('type' => 'varchar', 'length' => 1024, 'not null' => TRUE, 'default' => "''", 'sortable' => TRUE),
'title' => array('type' => 'varchar', 'length' => 1024, 'not null' => TRUE, 'default' => "''", 'sortable' => TRUE),
+ // link_field_settings ($op == 'database columns') changes
+ 'date' => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => "''"),
'attributes' => array('type' => 'mediumtext', 'not null' => FALSE),
);
@@ -402,6 +404,20 @@
'#default_value' => ($item['url']) ? $item['url'] : $default_url,
'#required' => ($delta == 0) ? ($field['required'] && empty($field['url'])) : FALSE,
);
+ // _link_widget_form changes
+ $form_item['date'] = array(
+ '#type' => 'date_popup',
+ '#date_type' => DATE_DATETIME,
+ '#date_format' => 'm/d/Y',
+ '#maxlength' => '255',
+ '#date_year_range' => '-12:0',
+ '#process' => array('date_popup_process' => array()),
+ // is there supposed to be something in the array ^^^
+ '#validate' => array('date_popup_validate' => array()),
+ // is there supposed to be something in the array ^^^
+ '#description' => NULL,
+ '#title' => ($delta == 0) ? t('Birthdate') : NULL,
+ '#required' => ($delta == 0) ? $field['required'] : FALSE,
+ );
+
if ($field['title'] != 'value' && $field['title'] != 'none') {
$default_title = "";
if (isset($field['widget']['default_value'][$delta]['title'])) {
@@ -437,6 +453,8 @@
}
// Trim whitespace from URL.
$item['url'] = trim($item['url']);
+ // my attempt to process? found in _link_widget_process
+ $item['date'] = date_popup_process($item['date']);
+
// Serialize the attributes array.
$item['attributes'] = serialize($item['attributes']);
@@ -449,6 +467,8 @@
}
function _link_widget_validate(&$item, $delta, $field, $node, &$optional_field_found) {
+ obviously in _link_wigdet_validate - my attempt to validate ?
+ $field['date'] = date_popup_validate($field['date']);
+
if ($item['url'] && !(isset($field['widget']['default_value'][$delta]['url']) && $item['url'] == $field['widget']['default_value'][$delta]['url'] && !$field['required'])) {
// Validate the link.
if (link_validate_url(trim($item['url'])) == FALSE) {
@@ -532,6 +552,9 @@
$output .= '<div class="link-field-title link-field-column">' . drupal_render($element['title']) . '</div>';
}
$output .= '<div class="link-field-url' . ($element['title'] ? ' link-field-column' : '') . '">' . drupal_render($element['url']) . '</div>';
+ // theme_link_widget_form_row changes - adds the field to the form nicely (css can be used then to place it correctly)
+ $output .= '<div class="link-field-date' . ($element['title'] ? ' link-field-column' : '') . '">' . drupal_render($element['date']) . '</div>';
$output .= '</div>';
if ($element['attributes']) {
$output .= '<div class="link-attributes">' . drupal_render($element['attributes']) . '</div>';
@@ -582,7 +605,11 @@
}
if ($formatter == 'plain') {
- return empty($item['url']) ? check_plain($item['title']) : check_plain(link_cleanup_url($item['url']));
+ // link_field_formatter changes - not sure what gives me a date in the same format I saved it in (m/d/y)....
+ //return empty($item['url']) ? check_plain($item['title']) : check_plain(link_cleanup_url($item['url']));
+ return empty($item['url']) ? check_plain($item['title'] . ' ' . $item['date']) : check_plain(link_cleanup_url($item['url']) . ' ' . $item['date']);
+ //return check_plain($item['url'] .' '. check_plain($item['date']));
+
}
// Replace URL tokens.
@@ -641,14 +668,17 @@
// Give the link the title 'Link'.
if ($formatter == 'short') {
$output = l(t('Link'), $url, $attributes, $query, $fragment);
+ $output .= ' ' . $item['date'];
}
// Build the link using the widget label.
elseif ($formatter == 'label') {
$output = l(t($field['widget']['label']), $url, $attributes, $query, $fragment);
+ $output .= ' ' . $item['date'];
}
// Build the link using the URL as title
elseif ($formatter == 'url') {
$output = l($display_url, $url, $attributes, $query, $fragment);
+ $output .= ' ' . $item['date'];
}
// Build the link using the widget label as separate title.
elseif ($formatter == 'separate') {
@@ -666,15 +696,18 @@
elseif (strlen(trim($item['title'])) || ($field['title'] == 'value' && strlen(trim($field['title_value'])))) {
$title = _link_field_formatter_title($field, $item, $node);
if (empty($url) && !empty($title)) {
- $output = check_plain($title);
+ $output = check_plain($title. ' ' . $item['date']);
+ ;
}
else {
$output = l($title, $url, $attributes, $query, $fragment, FALSE, $item['html']);
+ $output .= ' ' . $item['date'];
}
}
// Build the link with the URL or email address as the title (max 80 characters).
else {
$output = l($display_url, $url, $attributes, $query, $fragment);
+ $output .= ' ' . $item['date'];
}
return $output;
}
---------------------- backtrace ---------------------
[4] => Array
(
[file] => /var/www/clubs/includes/form.inc
[line] => 527
[function] => _form_validate
[args] => Array
(
[0] => Array
(
[#type] => date_popup
[#date_type] => datetime
[#date_format] => m/d/Y
[#maxlength] => 255
[#date_year_range] => -12:0
[#process] => Array
(
[date_popup_process] => Array
(
)
)
[#validate] => Array
(
[date_popup_validate] => Array
(
)
)
[#description] => Format: 07/16/2008
[#title] => Birthdate
[#required] => 1
[#post] => Array
(
[title] => Test
[field_date] => Array
(
[0] => Array
(
[value] => Array
(
[date] => 23/07/2008
)
)
[1] => Array
(
[value] => Array
(
[date] =>
)
)
[2] => Array
(
[value] => Array
(
[date] =>
)
)
[3] => Array
(
[value] => Array
(
[date] =>
)
)
)
[field_link] => Array
(
[0] => Array
(
[title] => Test
[url] => http://google.com
[date] => Array
(
[date] => 07/24/2008
)
)
.
.
.
| Comment | File | Size | Author |
|---|---|---|---|
| #1 | link.diff | 5.23 KB | liveoutloud2day |
Comments
Comment #1
liveoutloud2day commentedJust realized that the manual editing I did of the patch file (to comment it) broke it. _This_ patch actually applies to link v5.x.2.3 (and is better commented). I think I must need to do something in hook_validate or hook_process, but I thought this part
'#process' => array('date_popup_process' => array()),
'#validate' => array('date_popup_validate' => array()),
of the date field form (_link_widget_form) would or might take care of it.
Any other ideas? Any other info you might need to help? I would love to write up the sample of the code that needs to be in whatever hook it needs to be when I get it working... Thanks!
liveoutlout2day
----------- diff -rua of link.module -----------------------
--- link.module.orig 2008-07-21 16:11:21.000000000 -0400
+++ link.module 2008-07-21 16:44:13.000000000 -0400
@@ -155,6 +155,8 @@
'url' => array('type' => 'varchar', 'length' => 1024, 'not null' => TRUE, 'default' => "''", 'sortable' => TRUE),
'title' => array('type' => 'varchar', 'length' => 1024, 'not null' => TRUE, 'default' => "''", 'sortable' => TRUE),
'attributes' => array('type' => 'mediumtext', 'not null' => FALSE),
+ // changes to link_field_settings ($op == 'database columns')
+ 'date' => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => "''"),
);
case 'filters':
@@ -402,6 +404,22 @@
'#default_value' => ($item['url']) ? $item['url'] : $default_url,
'#required' => ($delta == 0) ? ($field['required'] && empty($field['url'])) : FALSE,
);
+ // changes to _link_widget_form
+ $form_item['date'] = array(
+ '#type' => 'date_popup',
+ '#date_type' => DATE_DATETIME,
+ '#date_format' => 'm/d/Y',
+ '#maxlength' => '255',
+ '#date_year_range' => '-12:0',
+ '#process' => array('date_popup_process' => array()),
+ // is there supposed to be something in the array ^^^
+ '#validate' => array('date_popup_validate' => array()),
+ // is there supposed to be something in the array ^^^
+ '#description' => NULL,
+ '#title' => ($delta == 0) ? t('Birthdate') : NULL,
+ '#required' => ($delta == 0) ? $field['required'] : FALSE,
+ );
+
if ($field['title'] != 'value' && $field['title'] != 'none') {
$default_title = "";
if (isset($field['widget']['default_value'][$delta]['title'])) {
@@ -437,6 +455,12 @@
}
// Trim whitespace from URL.
$item['url'] = trim($item['url']);
+ // my attempt to process? found in _link_widget_process - gives me a fatal error
+ //Fatal error: Cannot use string offset as an array
+ // in /var/www/clubs/sites/all/modules/date/date_popup/date_popup.module
+ // on line 177 - if I uncomment the next line....
+ //$item['date'] = date_popup_process($item['date']);
+
// Serialize the attributes array.
$item['attributes'] = serialize($item['attributes']);
@@ -449,6 +473,10 @@
}
function _link_widget_validate(&$item, $delta, $field, $node, &$optional_field_found) {
+ // obviously in _link_wigdet_validate - my attempt to validate ?
+ // uncommenting the next line gives me a fatal error
+ // - out of memory (at 128MB for apache)
+ //$field['date'] = date_popup_validate($field['date']);
if ($item['url'] && !(isset($field['widget']['default_value'][$delta]['url']) && $item['url'] == $field['widget']['default_value'][$delta]['url'] && !$field['required'])) {
// Validate the link.
if (link_validate_url(trim($item['url'])) == FALSE) {
@@ -532,6 +560,9 @@
$output .= '
';
}
$output .= '
';
+ // changes to theme_link_widget_form_row - adds the field to the form nicely (css can be used then to place it correctly)
+ $output .= '
';
+
$output .= '
';
if ($element['attributes']) {
$output .= '
';
@@ -582,7 +613,9 @@
}
if ($formatter == 'plain') {
- return empty($item['url']) ? check_plain($item['title']) : check_plain(link_cleanup_url($item['url']));
+ //return empty($item['url']) ? check_plain($item['title']) : check_plain(link_cleanup_url($item['url']));
+ // changes to link_field_formatter - not sure what would give me a date in the same format I saved it in (m/d/y)....
+ return empty($item['url']) ? check_plain($item['title'] . ' ' . $item['date']) : check_plain(link_cleanup_url($item['url']) . ' ' . $item['date']);
}
// Replace URL tokens.
@@ -641,14 +674,17 @@
// Give the link the title 'Link'.
if ($formatter == 'short') {
$output = l(t('Link'), $url, $attributes, $query, $fragment);
+ $output .= ' ' . $item['date'];
}
// Build the link using the widget label.
elseif ($formatter == 'label') {
$output = l(t($field['widget']['label']), $url, $attributes, $query, $fragment);
+ $output .= ' ' . $item['date'];
}
// Build the link using the URL as title
elseif ($formatter == 'url') {
$output = l($display_url, $url, $attributes, $query, $fragment);
+ $output .= ' ' . $item['date'];
}
// Build the link using the widget label as separate title.
elseif ($formatter == 'separate') {
@@ -667,14 +703,17 @@
$title = _link_field_formatter_title($field, $item, $node);
if (empty($url) && !empty($title)) {
$output = check_plain($title);
+ $output .= ' ' . $item['date'];
}
else {
$output = l($title, $url, $attributes, $query, $fragment, FALSE, $item['html']);
+ $output .= ' ' . $item['date'];
}
}
// Build the link with the URL or email address as the title (max 80 characters).
else {
$output = l($display_url, $url, $attributes, $query, $fragment);
+ $output .= ' ' . $item['date'];
}
return $output;
}
Comment #2
liveoutloud2day commentedOK - I figured out what is causing it, but not yet a clue how to fix it. The '#maxlength' => '255' part of the form causes it to call drupal_strlen in unicode.inc which fails with 'expected a string got an array' kind of message. So, is there supposed to be something in the code that is supposed to change it to a string before this? It is in _form_validate in form.inc that calls drupal_strlen, and blows up. I noticed that by removing the the maxlength part of the form definition, the form maxlength becomes 20 characters, so actually a much better maxlength. Is this bug I have uncovered, or should I not have specified a maxlength? Question related to this, but not the error, what do I do to get it to give me just the date in the output instead of the date and time? Thanks!
Comment #3
karens commentedThe beginnings of documentation about using the API are at http://drupal.org/node/287128.
The Date Popup is a self-validating element, you shouldn't need to do anything except include it in your form. You pass it parameters for the timezone, format, and a default value in the format YYYY-MM-DD HH:MM:SS, and it will convert your input into the format the popup wants, split the date and time into two different fields if you provided a format that has time in it, then accept and validate the user input and convert it back into a string in the same format you originally provided (YYYY-MM-DD HH:MM:SS). So you pass it a string and it will pass back a string by the time you get to your own validation function. You are responsible for doing your own timezone conversion if you're storing the date in UTC, the element uses the timezone just so it can create a date object with the right timezone for doing its formatting. So if you need to do timezone conversion, you pull your UTC date out of the database and convert it to a local date, pass that value to the Date Popup widget, then take what it returns and convert it back to UTC and store it in the database again.
You control whether it uses date or date and time by the format you supply in #date_format. If you don't have any time parts in the format, you won't get a time element.
The jquery widget (the 'date' part of the popup) can only accept a limited number of formats, things like Y-m-d or m/d/Y or d.m.Y.
I haven't read through your whole example carefully or tried to reproduce it. I don't have time to do that now, but I wanted to get you pointed in the right direction.
Once you figure it out, feel free to expand on the example in the documention to help others use this.
Comment #4
Anonymous (not verified) commentedAutomatically closed -- issue fixed for two weeks with no activity.