- Patch #372743 by bjaspan, yched, KarenS, catch et al: node body and teasers as fields. Oh, my.
parent
bfdea95337
commit
3d64cb5eca
|
@ -110,6 +110,8 @@ Drupal 7.0, xxxx-xx-xx (development version)
|
|||
for RDFa support.
|
||||
- Field API:
|
||||
* Custom data fields may be attached to nodes and users in Drupal.
|
||||
* Node bodies and teasers are now Field API fields instead of
|
||||
being a hard-coded property of node objects.
|
||||
* In addition, any other object type may register with Field API
|
||||
and allow custom data fields to be attached to itself.
|
||||
* Provides a subset of the features of the Content Construction
|
||||
|
|
|
@ -378,11 +378,11 @@ function theme_aggregator_page_rss($feeds, $category = NULL) {
|
|||
foreach ($feeds as $feed) {
|
||||
switch ($feed_length) {
|
||||
case 'teaser':
|
||||
$teaser = node_teaser($feed->description, NULL, variable_get('aggregator_teaser_length', 600));
|
||||
if ($teaser != $feed->description) {
|
||||
$teaser .= '<p><a href="' . check_url($feed->link) . '">' . t('read more') . "</a></p>\n";
|
||||
$summary = text_summary($feed->description, NULL, variable_get('aggregator_teaser_length', 600));
|
||||
if ($summary != $feed->description) {
|
||||
$summary .= '<p><a href="' . check_url($feed->link) . '">' . t('read more') . "</a></p>\n";
|
||||
}
|
||||
$feed->description = $teaser;
|
||||
$feed->description = $summary;
|
||||
break;
|
||||
case 'title':
|
||||
$feed->description = '';
|
||||
|
|
|
@ -252,7 +252,7 @@ EOF;
|
|||
for ($i = 0; $i < 5; $i++) {
|
||||
$edit = array();
|
||||
$edit['title'] = $this->randomName();
|
||||
$edit['body'] = $this->randomName();
|
||||
$edit['body[0][value]'] = $this->randomName();
|
||||
$this->drupalPost('node/add/article', $edit, t('Save'));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,12 +73,7 @@ function blog_help($path, $arg) {
|
|||
* Implement hook_form().
|
||||
*/
|
||||
function blog_form($node, $form_state) {
|
||||
global $nid;
|
||||
$type = node_type_get_type($node);
|
||||
|
||||
$form['title'] = array('#type' => 'textfield', '#title' => check_plain($type->title_label), '#required' => TRUE, '#default_value' => !empty($node->title) ? $node->title : NULL, '#weight' => -5);
|
||||
$form['body_field'] = node_body_field($node, $type->body_label, $type->min_word_count);
|
||||
return $form;
|
||||
return node_content_form($node, $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -89,8 +84,7 @@ function blog_view($node, $teaser) {
|
|||
// Breadcrumb navigation.
|
||||
drupal_set_breadcrumb(array(l(t('Home'), NULL), l(t('Blogs'), 'blog'), l(t("!name's blog", array('!name' => $node->name)), 'blog/' . $node->uid)));
|
||||
}
|
||||
|
||||
return node_prepare($node, $teaser);
|
||||
return $node;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -154,7 +154,7 @@ class BlogTestCase extends DrupalWebTestCase {
|
|||
// Edit blog node.
|
||||
$edit = array();
|
||||
$edit['title'] = 'node/' . $node->nid;
|
||||
$edit['body'] = $this->randomName(256);
|
||||
$edit['body[0][value]'] = $this->randomName(256);
|
||||
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
||||
$this->assertRaw(t('Blog entry %title has been updated.', array('%title' => $edit['title'])), t('Blog node was edited'));
|
||||
|
||||
|
|
|
@ -213,7 +213,7 @@ function blogapi_blogger_new_post($appkey, $blogid, $username, $password, $conte
|
|||
}
|
||||
else {
|
||||
$edit['title'] = blogapi_blogger_title($content);
|
||||
$edit['body'] = $content;
|
||||
$edit['body'][0]['value'] = $content;
|
||||
}
|
||||
|
||||
if (!node_access('create', $edit['type'])) {
|
||||
|
@ -274,12 +274,12 @@ function blogapi_blogger_edit_post($appkey, $postid, $username, $password, $cont
|
|||
// Check for bloggerAPI vs. metaWeblogAPI.
|
||||
if (is_array($content)) {
|
||||
$node->title = $content['title'];
|
||||
$node->body = $content['description'];
|
||||
$node->body[0]['value'] = $content['description'];
|
||||
_blogapi_mt_extra($node, $content);
|
||||
}
|
||||
else {
|
||||
$node->title = blogapi_blogger_title($content);
|
||||
$node->body = $content;
|
||||
$node->body[0]['value'] = $content;
|
||||
}
|
||||
|
||||
module_invoke_all('node_blogapi_edit', $node);
|
||||
|
@ -379,7 +379,7 @@ function blogapi_blogger_get_recent_posts($appkey, $blogid, $username, $password
|
|||
}
|
||||
|
||||
if ($bodies) {
|
||||
$result = db_query_range("SELECT n.nid, n.title, r.body, r.format, n.comment, n.created, u.name FROM {node} n, {node_revision} r, {users} u WHERE n.uid = u.uid AND n.vid = r.vid AND n.type = :type AND n.uid = :uid ORDER BY n.created DESC", array(
|
||||
$result = db_query_range("SELECT n.nid, n.title, n.comment, n.created, u.name FROM {node} n, {node_revision} r, {users} u WHERE n.uid = u.uid AND n.vid = r.vid AND n.type = :type AND n.uid = :uid ORDER BY n.created DESC", array(
|
||||
':type' => $blogid,
|
||||
':uid' => $user->uid
|
||||
), 0, $number_of_posts);
|
||||
|
@ -892,14 +892,14 @@ function _blogapi_mt_extra($node, $struct) {
|
|||
|
||||
// Merge the 3 body sections (description, mt_excerpt, mt_text_more) into one body.
|
||||
if ($struct['mt_excerpt']) {
|
||||
$node->body = $struct['mt_excerpt'] . '<!--break-->' . $node->body;
|
||||
$node->body[0]['value'] = $struct['mt_excerpt'] . '<!--break-->' . $node->body[0]['value'];
|
||||
}
|
||||
if ($struct['mt_text_more']) {
|
||||
$node->body = $node->body . '<!--extended-->' . $struct['mt_text_more'];
|
||||
$node->body[0]['value'] = $node->body[0]['value'] . '<!--extended-->' . $struct['mt_text_more'];
|
||||
}
|
||||
|
||||
if ($struct['mt_convert_breaks']) {
|
||||
$node->format = $struct['mt_convert_breaks'];
|
||||
$node->body[0]['format'] = $struct['mt_convert_breaks'];
|
||||
}
|
||||
|
||||
if ($struct['dateCreated']) {
|
||||
|
@ -922,17 +922,19 @@ function _blogapi_get_post($node, $bodies = TRUE) {
|
|||
);
|
||||
|
||||
if ($bodies) {
|
||||
$body = $node->body[0]['value'];
|
||||
$format = $node->body[0]['format'];
|
||||
if ($node->comment == 1) {
|
||||
$comment = 2;
|
||||
}
|
||||
elseif ($node->comment == 2) {
|
||||
$comment = 1;
|
||||
}
|
||||
$xmlrpcval['content'] = "<title>$node->title</title>$node->body";
|
||||
$xmlrpcval['description'] = $node->body;
|
||||
$xmlrpcval['content'] = "<title>$node->title</title>$body";
|
||||
$xmlrpcval['description'] = $body;
|
||||
// Add MT specific fields
|
||||
$xmlrpcval['mt_allow_comments'] = (int) $comment;
|
||||
$xmlrpcval['mt_convert_breaks'] = $node->format;
|
||||
$xmlrpcval['mt_convert_breaks'] = $format;
|
||||
}
|
||||
|
||||
return $xmlrpcval;
|
||||
|
|
|
@ -1037,7 +1037,7 @@ function book_export_traverse($tree, $visit_func) {
|
|||
function book_node_export($node, $children = '') {
|
||||
$node->build_mode = NODE_BUILD_PRINT;
|
||||
$node = node_build_content($node, FALSE, FALSE);
|
||||
$node->body = drupal_render($node->content);
|
||||
$node->rendered = drupal_render($node->content);
|
||||
|
||||
return theme('book_node_export_html', $node, $children);
|
||||
}
|
||||
|
@ -1054,7 +1054,7 @@ function book_node_export($node, $children = '') {
|
|||
function template_preprocess_book_node_export_html(&$variables) {
|
||||
$variables['depth'] = $variables['node']->book['depth'];
|
||||
$variables['title'] = check_plain($variables['node']->title);
|
||||
$variables['content'] = $variables['node']->body;
|
||||
$variables['content'] = $variables['node']->rendered;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -141,8 +141,7 @@ class BookTestCase extends DrupalWebTestCase {
|
|||
// Check printer friendly version.
|
||||
$this->drupalGet('book/export/html/' . $node->nid);
|
||||
$this->assertText($node->title, t('Printer friendly title found.'));
|
||||
$node->body = str_replace('<!--break-->', '', $node->body);
|
||||
$this->assertRaw(check_markup($node->body, $node->format), t('Printer friendly body found.'));
|
||||
$this->assertRaw(check_markup($node->body[0]['value'], $node->body[0]['format']), t('Printer friendly body found.'));
|
||||
|
||||
$number++;
|
||||
}
|
||||
|
@ -174,7 +173,7 @@ class BookTestCase extends DrupalWebTestCase {
|
|||
|
||||
$edit = array();
|
||||
$edit['title'] = $number . ' - SimpleTest test node ' . $this->randomName(10);
|
||||
$edit['body'] = 'SimpleTest test body ' . $this->randomName(32) . ' ' . $this->randomName(32);
|
||||
$edit['body[0][value]'] = 'SimpleTest test body ' . $this->randomName(32) . ' ' . $this->randomName(32);
|
||||
$edit['book[bid]'] = $book_nid;
|
||||
|
||||
if ($parent !== NULL) {
|
||||
|
|
|
@ -327,7 +327,7 @@ class DBLogTestCase extends DrupalWebTestCase {
|
|||
default:
|
||||
$content = array(
|
||||
'title' => $this->randomName(8),
|
||||
'body' => $this->randomName(32),
|
||||
'body[0][value]' => $this->randomName(32),
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
@ -351,7 +351,7 @@ class DBLogTestCase extends DrupalWebTestCase {
|
|||
|
||||
default:
|
||||
$content = array(
|
||||
'body' => $this->randomName(32),
|
||||
'body[0][value]' => $this->randomName(32),
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -425,7 +425,9 @@ function field_create_instance($instance) {
|
|||
// Set the field id.
|
||||
$instance['field_id'] = $field['id'];
|
||||
|
||||
// TODO: Check that the specifed bundle exists.
|
||||
// Note that we do *not* prevent creating a field on non-existing bundles,
|
||||
// because that would break the 'Body as field' upgrade for contrib
|
||||
// node types.
|
||||
|
||||
// TODO: Check that the widget type is known and can handle the field type ?
|
||||
// TODO: Check that the formatters are known and can handle the field type ?
|
||||
|
|
|
@ -930,10 +930,9 @@ class FieldInfoTestCase extends DrupalWebTestCase {
|
|||
$this->assertEqual($info[$w_key]['module'], 'field_test', t("Widget type field_test module appears"));
|
||||
}
|
||||
|
||||
// Verify that no fields or instances exist
|
||||
$fields = field_info_fields();
|
||||
// Verify that no unexpected instances exist.
|
||||
$core_fields = field_info_fields();
|
||||
$instances = field_info_instances(FIELD_TEST_BUNDLE);
|
||||
$this->assertTrue(empty($fields), t('With no fields, info fields is empty.'));
|
||||
$this->assertTrue(empty($instances), t('With no instances, info bundles is empty.'));
|
||||
|
||||
// Create a field, verify it shows up.
|
||||
|
@ -943,7 +942,7 @@ class FieldInfoTestCase extends DrupalWebTestCase {
|
|||
);
|
||||
field_create_field($field);
|
||||
$fields = field_info_fields();
|
||||
$this->assertEqual(count($fields), 1, t('One field exists'));
|
||||
$this->assertEqual(count($fields), count($core_fields) + 1, t('One new field exists'));
|
||||
$this->assertEqual($fields[$field['field_name']]['field_name'], $field['field_name'], t('info fields contains field name'));
|
||||
$this->assertEqual($fields[$field['field_name']]['type'], $field['type'], t('info fields contains field type'));
|
||||
$this->assertEqual($fields[$field['field_name']]['module'], 'field_test', t('info fields contains field module'));
|
||||
|
|
|
@ -5,3 +5,4 @@ package = Core - fields
|
|||
version = VERSION
|
||||
core = 7.x
|
||||
files[]=list.module
|
||||
required = TRUE
|
||||
|
|
|
@ -5,3 +5,4 @@ package = Core - fields
|
|||
version = VERSION
|
||||
core = 7.x
|
||||
files[]=number.module
|
||||
required = TRUE
|
||||
|
|
|
@ -5,3 +5,4 @@ package = Core - fields
|
|||
version = VERSION
|
||||
core = 7.x
|
||||
files[]=options.module
|
||||
required = TRUE
|
||||
|
|
|
@ -6,3 +6,4 @@ version = VERSION
|
|||
core = 7.x
|
||||
files[] = text.module
|
||||
files[] = text.test
|
||||
required = TRUE
|
|
@ -14,6 +14,9 @@ function text_theme() {
|
|||
'text_textarea' => array(
|
||||
'arguments' => array('element' => NULL),
|
||||
),
|
||||
'text_textarea_with_summary' => array(
|
||||
'arguments' => array('element' => NULL),
|
||||
),
|
||||
'text_textfield' => array(
|
||||
'arguments' => array('element' => NULL),
|
||||
),
|
||||
|
@ -26,11 +29,22 @@ function text_theme() {
|
|||
'field_formatter_text_trimmed' => array(
|
||||
'arguments' => array('element' => NULL),
|
||||
),
|
||||
'field_formatter_text_summary_or_trimmed' => array(
|
||||
'arguments' => array('element' => NULL),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement hook_field_info().
|
||||
*
|
||||
* Field settings:
|
||||
* - max_length: the maximum length for a varchar field.
|
||||
* Instance settings:
|
||||
* - text_processing: whether text input filters should be used.
|
||||
* - display_summary: whether the summary field should be displayed.
|
||||
* When empty and not displayed the summary will take its value from the
|
||||
* trimmed value of the main text field.
|
||||
*/
|
||||
function text_field_info() {
|
||||
return array(
|
||||
|
@ -39,18 +53,25 @@ function text_field_info() {
|
|||
'description' => t('This field stores varchar text in the database.'),
|
||||
'settings' => array('max_length' => 255),
|
||||
'instance_settings' => array('text_processing' => 0),
|
||||
'widget_settings' => array('size' => 60),
|
||||
'default_widget' => 'text_textfield',
|
||||
'default_formatter' => 'text_default',
|
||||
),
|
||||
'text_long' => array(
|
||||
'label' => t('Long text'),
|
||||
'description' => t('This field stores long text in the database.'),
|
||||
'settings' => array('max_length' => ''),
|
||||
'instance_settings' => array('text_processing' => 0),
|
||||
'widget_settings' => array('rows' => 5),
|
||||
'default_widget' => 'text_textarea',
|
||||
'default_formatter' => 'text_default',
|
||||
),
|
||||
'text_with_summary' => array(
|
||||
'label' => t('Long text and summary'),
|
||||
'description' => t('This field stores long text in the database along with optional summary text.'),
|
||||
'settings' => array('max_length' => ''),
|
||||
'instance_settings' => array('text_processing' => 1, 'display_summary' => 0),
|
||||
'default_widget' => 'text_textarea_with_summary',
|
||||
'default_formatter' => 'text_summary_or_trimmed',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -58,23 +79,39 @@ function text_field_info() {
|
|||
* Implement hook_field_schema().
|
||||
*/
|
||||
function text_field_schema($field) {
|
||||
if ($field['type'] == 'text_long') {
|
||||
$columns = array(
|
||||
'value' => array(
|
||||
'type' => 'text',
|
||||
'size' => 'big',
|
||||
'not null' => FALSE,
|
||||
),
|
||||
);
|
||||
}
|
||||
else {
|
||||
$columns = array(
|
||||
'value' => array(
|
||||
'type' => 'varchar',
|
||||
'length' => $field['settings']['max_length'],
|
||||
'not null' => FALSE,
|
||||
),
|
||||
);
|
||||
switch ($field['type']) {
|
||||
case 'text':
|
||||
$columns = array(
|
||||
'value' => array(
|
||||
'type' => 'varchar',
|
||||
'length' => $field['settings']['max_length'],
|
||||
'not null' => FALSE,
|
||||
),
|
||||
);
|
||||
break;
|
||||
case 'text_long':
|
||||
$columns = array(
|
||||
'value' => array(
|
||||
'type' => 'text',
|
||||
'size' => 'big',
|
||||
'not null' => FALSE,
|
||||
),
|
||||
);
|
||||
break;
|
||||
case 'text_with_summary':
|
||||
$columns = array(
|
||||
'value' => array(
|
||||
'type' => 'text',
|
||||
'size' => 'big',
|
||||
'not null' => FALSE,
|
||||
),
|
||||
'summary' => array(
|
||||
'type' => 'text',
|
||||
'size' => 'big',
|
||||
'not null' => FALSE,
|
||||
),
|
||||
);
|
||||
break;
|
||||
}
|
||||
$columns += array(
|
||||
'format' => array(
|
||||
|
@ -95,16 +132,27 @@ function text_field_schema($field) {
|
|||
* Implement hook_field_validate().
|
||||
*
|
||||
* Possible error codes:
|
||||
* - 'text_max_length': The value exceeds the maximum length.
|
||||
* - 'text_value_max_length': The value exceeds the maximum length.
|
||||
* - 'text_summary_max_length': The summary exceeds the maximum length.
|
||||
*/
|
||||
function text_field_validate($obj_type, $object, $field, $instance, $items, &$errors) {
|
||||
foreach ($items as $delta => $item) {
|
||||
if (!empty($item['value'])) {
|
||||
if (!empty($field['settings']['max_length']) && drupal_strlen($item['value']) > $field['settings']['max_length']) {
|
||||
$errors[$field['field_name']][$delta][] = array(
|
||||
'error' => 'text_max_length',
|
||||
'message' => t('%name: the value may not be longer than %max characters.', array('%name' => $instance['label'], '%max' => $field['settings']['max_length'])),
|
||||
);
|
||||
foreach (array('value' => t('full text'), 'summary' => t('summary')) as $column => $desc) {
|
||||
if (!empty($item[$column])) {
|
||||
if (!empty($field['settings']['max_length']) && drupal_strlen($item[$column]) > $field['settings']['max_length']) {
|
||||
switch ($column) {
|
||||
case 'value':
|
||||
$message = t('%name: the text may not be longer than %max characters.', array('%name' => $instance['label'], '%max' => $field['settings']['max_length']));
|
||||
break;
|
||||
case 'summary':
|
||||
$message = t('%name: the summary may not be longer than %max characters.', array('%name' => $instance['label'], '%max' => $field['settings']['max_length']));
|
||||
break;
|
||||
}
|
||||
$errors[$field['field_name']][$delta][] = array(
|
||||
'error' => "text_{$column}_length",
|
||||
'message' => $message,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -126,17 +174,22 @@ function text_field_load($obj_type, $objects, $field, $instances, &$items) {
|
|||
if (!empty($instances[$id]['settings']['text_processing'])) {
|
||||
// Only process items with a cacheable format, the rest will be
|
||||
// handled by text_field_sanitize().
|
||||
if (filter_format_allowcache($item['format'])) {
|
||||
$format = $item['format'];
|
||||
if (filter_format_allowcache($format)) {
|
||||
// TODO D7 : this code is really node-related.
|
||||
$check = is_null($object) || (isset($object->build_mode) && $object->build_mode == NODE_BUILD_PREVIEW);
|
||||
$text = isset($item['value']) ? check_markup($item['value'], $item['format'], isset($object->language) ? $object->language : $language->language, $check, FALSE) : '';
|
||||
$lang = isset($object->language) ? $object->language : $language->language;
|
||||
$items[$id][$delta]['safe'] = isset($item['value']) ? check_markup($item['value'], $format, $lang, $check, FALSE) : '';
|
||||
if ($field['type'] == 'text_with_summary') {
|
||||
$items[$id][$delta]['safe_summary'] = isset($item['summary']) ? check_markup($item['summary'], $format, $lang, $check, FALSE) : '';
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$text = check_plain($item['value']);
|
||||
}
|
||||
if (isset($text)) {
|
||||
$items[$id][$delta]['safe'] = $text;
|
||||
$items[$id][$delta]['safe'] = check_plain($item['value']);
|
||||
if ($field['type'] == 'text_with_summary') {
|
||||
$items[$id][$delta]['safe_summary'] = check_plain($item['summary']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -155,14 +208,21 @@ function text_field_sanitize($obj_type, $object, $field, $instance, &$items) {
|
|||
// from a form preview.
|
||||
if (!isset($items[$delta]['safe'])) {
|
||||
if (!empty($instance['settings']['text_processing'])) {
|
||||
$format = $item['format'];
|
||||
// TODO D7 : this code is really node-related.
|
||||
$check = is_null($object) || (isset($object->build_mode) && $object->build_mode == NODE_BUILD_PREVIEW);
|
||||
$text = isset($item['value']) ? check_markup($item['value'], $item['format'], isset($object->language) ? $object->language : $language->language, $check) : '';
|
||||
$lang = isset($object->language) ? $object->language : $language->language;
|
||||
$items[$delta]['safe'] = isset($item['value']) ? check_markup($item['value'], $format, $lang, $check) : '';
|
||||
if ($field['type'] == 'text_with_summary') {
|
||||
$items[$delta]['safe_summary'] = isset($item['summary']) ? check_markup($item['summary'], $format, $lang, $check) : '';
|
||||
}
|
||||
}
|
||||
else {
|
||||
$text = check_plain($item['value']);
|
||||
$item[$delta]['safe'] = check_plain($item['value']);
|
||||
if ($field['type'] == 'text_with_summary') {
|
||||
$item[$delta]['safe_summary'] = check_plain($item['summary']);
|
||||
}
|
||||
}
|
||||
$items[$delta]['safe'] = $text;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -184,21 +244,39 @@ function text_field_formatter_info() {
|
|||
return array(
|
||||
'text_default' => array(
|
||||
'label' => t('Default'),
|
||||
'field types' => array('text', 'text_long'),
|
||||
'field types' => array('text', 'text_long', 'text_with_summary'),
|
||||
'behaviors' => array(
|
||||
'multiple values' => FIELD_BEHAVIOR_DEFAULT,
|
||||
),
|
||||
),
|
||||
'text_plain' => array(
|
||||
'label' => t('Plain text'),
|
||||
'field types' => array('text', 'text_long'),
|
||||
'field types' => array('text', 'text_long', 'text_with_summary'),
|
||||
'behaviors' => array(
|
||||
'multiple values' => FIELD_BEHAVIOR_DEFAULT,
|
||||
),
|
||||
),
|
||||
|
||||
// The text_trimmed formatter displays the trimmed version of the
|
||||
// full element of the field. It is intended to be used with text
|
||||
// and text_long fields. It also works with text_with_summary
|
||||
// fields though the text_summary_or_trimmed formatter makes more
|
||||
// sense for that field type.
|
||||
'text_trimmed' => array(
|
||||
'label' => t('Trimmed'),
|
||||
'field types' => array('text', 'text_long'),
|
||||
'field types' => array('text', 'text_long', 'text_with_summary'),
|
||||
'behaviors' => array(
|
||||
'multiple values' => FIELD_BEHAVIOR_DEFAULT,
|
||||
),
|
||||
),
|
||||
|
||||
// The 'summary or trimmed' field formatter for text_with_summary
|
||||
// fields displays returns the summary element of the field or, if
|
||||
// the summary is empty, the trimmed version of the full element
|
||||
// of the field.
|
||||
'text_summary_or_trimmed' => array(
|
||||
'label' => t('Summary or trimmed'),
|
||||
'field types' => array('text_with_summary'),
|
||||
'behaviors' => array(
|
||||
'multiple values' => FIELD_BEHAVIOR_DEFAULT,
|
||||
),
|
||||
|
@ -226,7 +304,150 @@ function theme_field_formatter_text_plain($element) {
|
|||
function theme_field_formatter_text_trimmed($element) {
|
||||
$field = field_info_field($element['#field_name']);
|
||||
$instance = field_info_instance($element['#field_name'], $element['#bundle']);
|
||||
return $instance['settings']['text_processing'] ? $element['#item']['format'] : NULL;
|
||||
return text_summary($element['#item']['safe'], $instance['settings']['text_processing'] ? $element['#item']['format'] : NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Theme function for 'summary or trimmed' field formatter for
|
||||
* text_with_summary fields. This formatter returns the summary
|
||||
* element of the field or, if the summary is empty, the trimmed
|
||||
* version of the full element of the field.
|
||||
*/
|
||||
function theme_field_formatter_text_summary_or_trimmed($element) {
|
||||
$field = field_info_field($element['#field_name']);
|
||||
$instance = field_info_instance($element['#field_name'], $element['#bundle']);
|
||||
|
||||
if (!empty($element['#item']['safe_summary'])) {
|
||||
return $element['#item']['safe_summary'];
|
||||
}
|
||||
else {
|
||||
return text_summary($element['#item']['safe'], $instance['settings']['text_processing'] ? $element['#item']['format'] : NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a trimmed, formatted version of a text field value.
|
||||
*
|
||||
* If the end of the summary is not indicated using the <!--break--> delimiter
|
||||
* then we generate the summary automatically, trying to end it at a sensible
|
||||
* place such as the end of a paragraph, a line break, or the end of a
|
||||
* sentence (in that order of preference).
|
||||
*
|
||||
* @param $text
|
||||
* The content for which a summary will be generated.
|
||||
* @param $format
|
||||
* The format of the content.
|
||||
* If the PHP filter is present and $text contains PHP code, we do not
|
||||
* split it up to prevent parse errors.
|
||||
* If the line break filter is present then we treat newlines embedded in
|
||||
* $text as line breaks.
|
||||
* If the htmlcorrector filter is present, it will be run on the generated
|
||||
* summary (if different from the incoming $text).
|
||||
* @param $size
|
||||
* The desired character length of the summary. If omitted, the default
|
||||
* value will be used. Ignored if the special delimiter is present
|
||||
* in $text.
|
||||
* @return
|
||||
* The generated summary.
|
||||
*/
|
||||
function text_summary($text, $format = NULL, $size = NULL) {
|
||||
|
||||
if (!isset($size)) {
|
||||
// What used to be called 'teaser' is now called 'summary', but
|
||||
// the variable 'teaser_length' is preserved for backwards compatibility.
|
||||
$size = variable_get('teaser_length', 600);
|
||||
}
|
||||
|
||||
// Find where the delimiter is in the body
|
||||
$delimiter = strpos($text, '<!--break-->');
|
||||
|
||||
// If the size is zero, and there is no delimiter, the entire body is the summary.
|
||||
if ($size == 0 && $delimiter === FALSE) {
|
||||
return $text;
|
||||
}
|
||||
|
||||
// If a valid delimiter has been specified, use it to chop off the summary.
|
||||
if ($delimiter !== FALSE) {
|
||||
return substr($text, 0, $delimiter);
|
||||
}
|
||||
|
||||
// We check for the presence of the PHP evaluator filter in the current
|
||||
// format. If the body contains PHP code, we do not split it up to prevent
|
||||
// parse errors.
|
||||
if (isset($format)) {
|
||||
$filters = filter_list_format($format);
|
||||
if (isset($filters['php/0']) && strpos($text, '<?') !== FALSE) {
|
||||
return $text;
|
||||
}
|
||||
}
|
||||
|
||||
// If we have a short body, the entire body is the summary.
|
||||
if (drupal_strlen($text) <= $size) {
|
||||
return $text;
|
||||
}
|
||||
|
||||
// If the delimiter has not been specified, try to split at paragraph or
|
||||
// sentence boundaries.
|
||||
|
||||
// The summary may not be longer than maximum length specified. Initial slice.
|
||||
$summary = truncate_utf8($text, $size);
|
||||
|
||||
// Store the actual length of the UTF8 string -- which might not be the same
|
||||
// as $size.
|
||||
$max_rpos = strlen($summary);
|
||||
|
||||
// How much to cut off the end of the summary so that it doesn't end in the
|
||||
// middle of a paragraph, sentence, or word.
|
||||
// Initialize it to maximum in order to find the minimum.
|
||||
$min_rpos = $max_rpos;
|
||||
|
||||
// Store the reverse of the summary. We use strpos on the reversed needle and
|
||||
// haystack for speed and convenience.
|
||||
$reversed = strrev($summary);
|
||||
|
||||
// Build an array of arrays of break points grouped by preference.
|
||||
$break_points = array();
|
||||
|
||||
// A paragraph near the end of sliced summary is most preferable.
|
||||
$break_points[] = array('</p>' => 0);
|
||||
|
||||
// If no complete paragraph then treat line breaks as paragraphs.
|
||||
$line_breaks = array('<br />' => 6, '<br>' => 4);
|
||||
// Newline only indicates a line break if line break converter
|
||||
// filter is present.
|
||||
if (isset($filters['filter/1'])) {
|
||||
$line_breaks["\n"] = 1;
|
||||
}
|
||||
$break_points[] = $line_breaks;
|
||||
|
||||
// If the first paragraph is too long, split at the end of a sentence.
|
||||
$break_points[] = array('. ' => 1, '! ' => 1, '? ' => 1, '。' => 0, '؟ ' => 1);
|
||||
|
||||
// Iterate over the groups of break points until a break point is found.
|
||||
foreach ($break_points as $points) {
|
||||
// Look for each break point, starting at the end of the summary.
|
||||
foreach ($points as $point => $offset) {
|
||||
// The summary is already reversed, but the break point isn't.
|
||||
$rpos = strpos($reversed, strrev($point));
|
||||
if ($rpos !== FALSE) {
|
||||
$min_rpos = min($rpos + $offset, $min_rpos);
|
||||
}
|
||||
}
|
||||
|
||||
// If a break point was found in this group, slice and stop searching.
|
||||
if ($min_rpos !== $max_rpos) {
|
||||
// Don't slice with length 0. Length must be <0 to slice from RHS.
|
||||
$summary = ($min_rpos === 0) ? $summary : substr($summary, 0, 0 - $min_rpos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If the htmlcorrector filter is present, apply it to the generated summary.
|
||||
if (isset($filters['filter/3'])) {
|
||||
$summary = _filter_htmlcorrector($summary);
|
||||
}
|
||||
|
||||
return $summary;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -260,6 +481,15 @@ function text_field_widget_info() {
|
|||
'default value' => FIELD_BEHAVIOR_DEFAULT,
|
||||
),
|
||||
),
|
||||
'text_textarea_with_summary' => array(
|
||||
'label' => t('Text area with a summary'),
|
||||
'field types' => array('text_with_summary'),
|
||||
'settings' => array('rows' => 20, 'summary_rows' => 5),
|
||||
'behaviors' => array(
|
||||
'multiple values' => FIELD_BEHAVIOR_DEFAULT,
|
||||
'default value' => FIELD_BEHAVIOR_DEFAULT,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -281,14 +511,23 @@ function text_elements() {
|
|||
'#input' => TRUE,
|
||||
'#columns' => array('value'), '#delta' => 0,
|
||||
'#process' => array('text_textfield_elements_process'),
|
||||
'#theme_wrapper' => 'text_textfield',
|
||||
'#autocomplete_path' => FALSE,
|
||||
),
|
||||
),
|
||||
'text_textarea' => array(
|
||||
'#input' => TRUE,
|
||||
'#columns' => array('value', 'format'), '#delta' => 0,
|
||||
'#process' => array('text_textarea_elements_process'),
|
||||
'#theme_wrapper' => 'text_textarea',
|
||||
'#filter_value' => FILTER_FORMAT_DEFAULT,
|
||||
),
|
||||
),
|
||||
'text_textarea_with_summary' => array(
|
||||
'#input' => TRUE,
|
||||
'#columns' => array('value', 'format', 'summary'), '#delta' => 0,
|
||||
'#process' => array('text_textarea_with_summary_process'),
|
||||
'#theme_wrapper' => 'text_textarea_with_summary',
|
||||
'#filter_value' => FILTER_FORMAT_DEFAULT,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -329,6 +568,10 @@ function text_field_widget(&$form, &$form_state, $field, $instance, $items, $del
|
|||
'#type' => $instance['widget']['type'],
|
||||
'#default_value' => isset($items[$delta]) ? $items[$delta] : '',
|
||||
);
|
||||
if (!empty($instance['settings']['text_processing'])) {
|
||||
$element['#value_callback'] = 'text_field_widget_formatted_text_value';
|
||||
}
|
||||
|
||||
return $element;
|
||||
}
|
||||
|
||||
|
@ -336,7 +579,17 @@ function text_field_widget(&$form, &$form_state, $field, $instance, $items, $del
|
|||
* Implement hook_field_widget_error().
|
||||
*/
|
||||
function text_field_widget_error($element, $error) {
|
||||
form_error($element['value'], $error['message']);
|
||||
switch ($error['error']) {
|
||||
case 'text_summary_max_length':
|
||||
$error_element = $element[$element['#columns'][1]];
|
||||
break;
|
||||
|
||||
default:
|
||||
$error_element = $element[$element['#columns'][0]];
|
||||
break;
|
||||
}
|
||||
|
||||
form_error($error_element, $error['message']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -364,24 +617,17 @@ function text_textfield_elements_process($element, $form_state, $form) {
|
|||
'#autocomplete_path' => $element['#autocomplete_path'],
|
||||
'#size' => $instance['widget']['settings']['size'],
|
||||
'#attributes' => array('class' => 'text'),
|
||||
// The following values were set by the field module and need
|
||||
// to be passed down to the nested element.
|
||||
'#title' => $element['#title'],
|
||||
'#description' => $element['#description'],
|
||||
'#required' => $element['#required'],
|
||||
'#field_name' => $element['#field_name'],
|
||||
'#bundle' => $element['#bundle'],
|
||||
'#delta' => $element['#delta'],
|
||||
'#columns' => $element['#columns'],
|
||||
);
|
||||
|
||||
$element[$field_key]['#maxlength'] = !empty($field['settings']['max_length']) ? $field['settings']['max_length'] : NULL;
|
||||
|
||||
if (!empty($instance['settings']['text_processing'])) {
|
||||
$filter_key = $element['#columns'][1];
|
||||
$filter_key = (count($element['#columns']) == 2) ? $element['#columns'][1] : 'format';
|
||||
$format = isset($element['#value'][$filter_key]) ? $element['#value'][$filter_key] : FILTER_FORMAT_DEFAULT;
|
||||
$parents = array_merge($element['#parents'] , array($filter_key));
|
||||
$element[$filter_key] = filter_form($format, 1, $parents);
|
||||
$element[$field_key]['#text_format'] = $format;
|
||||
}
|
||||
|
||||
return $element;
|
||||
|
@ -400,32 +646,94 @@ function text_textarea_elements_process($element, $form_state, $form) {
|
|||
$instance = $form['#fields'][$element['#field_name']]['instance'];
|
||||
$field_key = $element['#columns'][0];
|
||||
$delta = $element['#delta'];
|
||||
|
||||
$element[$field_key] = array(
|
||||
'#type' => 'textarea',
|
||||
'#default_value' => isset($element['#value'][$field_key]) ? $element['#value'][$field_key] : NULL,
|
||||
'#rows' => $instance['widget']['settings']['rows'],
|
||||
'#weight' => 0,
|
||||
// The following values were set by the field module and need
|
||||
// to be passed down to the nested element.
|
||||
'#title' => $element['#title'],
|
||||
'#description' => $element['#description'],
|
||||
'#required' => $element['#required'],
|
||||
'#field_name' => $element['#field_name'],
|
||||
'#bundle' => $element['#bundle'],
|
||||
'#delta' => $element['#delta'],
|
||||
'#columns' => $element['#columns'],
|
||||
);
|
||||
|
||||
if (!empty($instance['settings']['text_processing'])) {
|
||||
$filter_key = (count($element['#columns']) == 2) ? $element['#columns'][1] : 'format';
|
||||
$format = isset($element['#value'][$filter_key]) ? $element['#value'][$filter_key] : FILTER_FORMAT_DEFAULT;
|
||||
$parents = array_merge($element['#parents'] , array($filter_key));
|
||||
$element[$filter_key] = filter_form($format, 1, $parents);
|
||||
$element[$field_key]['#text_format'] = $format;
|
||||
}
|
||||
|
||||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process an individual element.
|
||||
*
|
||||
* Build the form element. When creating a form using FAPI #process,
|
||||
* note that $element['#value'] is already set.
|
||||
*
|
||||
* The $field and $instance arrays are in $form['#fields'][$element['#field_name']].
|
||||
*/
|
||||
function text_textarea_with_summary_process($element, $form_state, $form) {
|
||||
$field = $form['#fields'][$element['#field_name']]['field'];
|
||||
$instance = $form['#fields'][$element['#field_name']]['instance'];
|
||||
$delta = $element['#delta'];
|
||||
|
||||
$field_key = $element['#columns'][1];
|
||||
$display = !empty($element['#value'][$field_key]) || !empty($instance['settings']['display_summary']);
|
||||
$element[$field_key] = array(
|
||||
'#title' => t('Summary'),
|
||||
'#type' => $display ? 'textarea' : 'value',
|
||||
'#default_value' => isset($element['#value'][$field_key]) ? $element['#value'][$field_key] : NULL,
|
||||
'#rows' => $instance['widget']['settings']['summary_rows'],
|
||||
'#weight' => 0,
|
||||
'#title' => t('Summary'),
|
||||
'#description' => t('Leave blank to use trimmed value of full text as the summary.'),
|
||||
'#required' => $element['#required'],
|
||||
'#display' => $display,
|
||||
);
|
||||
|
||||
$field_key = $element['#columns'][0];
|
||||
$element[$field_key] = array(
|
||||
'#type' => 'textarea',
|
||||
'#default_value' => isset($element['#value'][$field_key]) ? $element['#value'][$field_key] : NULL,
|
||||
'#rows' => $instance['widget']['settings']['rows'],
|
||||
'#weight' => 1,
|
||||
'#title' => $display ? t('Full text') : $element['#title'],
|
||||
'#description' => $element['#description'],
|
||||
'#required' => $element['#required'],
|
||||
'#required' => $instance['required'],
|
||||
);
|
||||
|
||||
if (!empty($instance['settings']['text_processing'])) {
|
||||
$filter_key = (count($element['#columns']) == 2) ? $element['#columns'][1] : 'format';
|
||||
$format = isset($element['#value'][$filter_key]) ? $element['#value'][$filter_key] : FILTER_FORMAT_DEFAULT;
|
||||
$element[$field_key]['#text_format'] = $format;
|
||||
}
|
||||
|
||||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to determine the value for a formatted text widget.
|
||||
*
|
||||
* '#text_format' puts the format in '[column 0]_format' in incoming values,
|
||||
* while we need it in '[column 1]'.
|
||||
*/
|
||||
function text_field_widget_formatted_text_value($form, $edit = FALSE) {
|
||||
if ($edit !== FALSE) {
|
||||
$field_key = $form['#columns'][0];
|
||||
$filter_key = (count($form['#columns']) == 2) ? $form['#columns'][1] : 'format';
|
||||
$default_key = $field_key . '_format';
|
||||
// The format selector uses #access = FALSE if only one format is
|
||||
// available. In this case, we don't receive its value, and need to
|
||||
// manually set it.
|
||||
$edit['format'] = !empty($edit[$default_key]) ? $edit[$default_key] : filter_resolve_format(FILTER_FORMAT_DEFAULT);
|
||||
unset($edit[$default_key]);
|
||||
return $edit;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* FAPI theme for an individual text elements.
|
||||
*
|
||||
|
@ -444,3 +752,21 @@ function theme_text_textfield($element) {
|
|||
function theme_text_textarea($element) {
|
||||
return $element['#children'];
|
||||
}
|
||||
|
||||
function theme_text_textarea_with_summary($element) {
|
||||
// If displaying both a textarea and a summary field, wrap them
|
||||
// in a fieldset to make it clear they belong together.
|
||||
$field_key = $element['#columns'][1];
|
||||
if (!empty($element[$field_key]['#display'])) {
|
||||
$fieldset = array(
|
||||
'#title' => $element['#title'],
|
||||
'#value' => $element['#children'],
|
||||
'#attributes' => array('class' => 'text-textarea'),
|
||||
'#id' => str_replace('_', '-', $element['#field_name']) . '-summary-wrapper',
|
||||
);
|
||||
return theme('fieldset', $fieldset);
|
||||
}
|
||||
else {
|
||||
return $element['#children'];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ class TextFieldTestCase extends DrupalWebTestCase {
|
|||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp('field', 'text', 'field_test');
|
||||
parent::setUp('field_test');
|
||||
|
||||
$web_user = $this->drupalCreateUser(array('access field_test content', 'administer field_test content'));
|
||||
$this->drupalLogin($web_user);
|
||||
|
@ -149,7 +149,7 @@ class TextFieldTestCase extends DrupalWebTestCase {
|
|||
// selector is displayed
|
||||
$this->drupalGet('test-entity/add/test-bundle');
|
||||
$this->assertFieldByName($this->field_name . '[0][value]', '', t('Widget is displayed'));
|
||||
$this->assertNoFieldByName($this->field_name . '[0][format]', '1', t('Format selector is not displayed'));
|
||||
$this->assertNoFieldByName($this->field_name . '[0][value_format]', '1', t('Format selector is not displayed'));
|
||||
|
||||
// Submit with data that should be filtered.
|
||||
$value = $this->randomName() . '<br />' . $this->randomName();
|
||||
|
@ -175,11 +175,11 @@ class TextFieldTestCase extends DrupalWebTestCase {
|
|||
// We should now have a 'text format' selector.
|
||||
$this->drupalGet('test-entity/' . $id . '/edit');
|
||||
$this->assertFieldByName($this->field_name . '[0][value]', '', t('Widget is displayed'));
|
||||
$this->assertFieldByName($this->field_name . '[0][format]', '1', t('Format selector is displayed'));
|
||||
$this->assertFieldByName($this->field_name . '[0][value_format]', '1', t('Format selector is displayed'));
|
||||
|
||||
// Edit and change the format to 'Full HTML'.
|
||||
$edit = array(
|
||||
$this->field_name . '[0][format]' => 2,
|
||||
$this->field_name . '[0][value_format]' => 2,
|
||||
);
|
||||
$this->drupalPost(NULL, $edit, t('Save'));
|
||||
$this->assertRaw(t('test_entity @id has been updated.', array('@id' => $id)), t('Entity was updated'));
|
||||
|
@ -196,3 +196,148 @@ class TextFieldTestCase extends DrupalWebTestCase {
|
|||
*
|
||||
*/
|
||||
}
|
||||
|
||||
class TextSummaryTestCase extends DrupalWebTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => t('Text summary'),
|
||||
'description' => t('Test text_summary() with different strings and lengths.'),
|
||||
'group' => t('Field'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests an edge case where the first sentence is a question and
|
||||
* subsequent sentences are not. This edge case is documented at
|
||||
* http://drupal.org/node/180425.
|
||||
*/
|
||||
function testFirstSentenceQuestion() {
|
||||
$text = 'A question? A sentence. Another sentence.';
|
||||
$expected = 'A question? A sentence.';
|
||||
$this->callTextSummary($text, $expected, NULL, 30);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test summary with long example.
|
||||
*/
|
||||
function testLongSentence() {
|
||||
$text = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ' . // 125
|
||||
'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. ' . // 108
|
||||
'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. ' . // 103
|
||||
'Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'; // 110
|
||||
$expected = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ' .
|
||||
'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. ' .
|
||||
'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.';
|
||||
// First three sentences add up to: 336, so add one for space and then 3 to get half-way into next word.
|
||||
$this->callTextSummary($text, $expected, NULL, 340);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test various summary length edge cases.
|
||||
*/
|
||||
function testLength() {
|
||||
// This string tests a number of edge cases.
|
||||
$text = "<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>";
|
||||
|
||||
// The summaries we expect text_summary() to return when $size is the index
|
||||
// of each array item.
|
||||
// Using no text format:
|
||||
$expected = array(
|
||||
"<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>",
|
||||
"<",
|
||||
"<p",
|
||||
"<p>",
|
||||
"<p>\n",
|
||||
"<p>\nH",
|
||||
"<p>\nHi",
|
||||
"<p>\nHi\n",
|
||||
"<p>\nHi\n<",
|
||||
"<p>\nHi\n</",
|
||||
"<p>\nHi\n</p",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>",
|
||||
"<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>",
|
||||
"<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>",
|
||||
);
|
||||
|
||||
// And using a text format WITH the line-break and htmlcorrector filters.
|
||||
$expected_lb = array(
|
||||
"<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>",
|
||||
"<",
|
||||
"<p",
|
||||
"<p></p>",
|
||||
"<p></p>",
|
||||
"<p></p>",
|
||||
"<p></p>",
|
||||
"<p>\nHi</p>",
|
||||
"<p>\nHi</p>",
|
||||
"<p>\nHi</p>",
|
||||
"<p>\nHi</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>",
|
||||
"<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>",
|
||||
"<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>",
|
||||
);
|
||||
|
||||
// Test text_summary() for different sizes.
|
||||
for ($i = 0; $i <= 37; $i++) {
|
||||
$this->callTextSummary($text, $expected[$i], NULL, $i);
|
||||
$this->callTextSummary($text, $expected_lb[$i], 1, $i);
|
||||
$this->callTextSummary($text, $expected_lb[$i], 2, $i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls text_summary() and asserts that the expected teaser is returned.
|
||||
*/
|
||||
function callTextSummary($text, $expected, $format = NULL, $size = NULL) {
|
||||
$summary = text_summary($text, $format, $size);
|
||||
$this->assertIdentical($summary, $expected, t('Generated summary "@summary" matches expected "@expected".', array('@summary' => $summary, '@expected' => $expected)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,11 @@ form .field-add-more-submit {
|
|||
margin: .5em 0 0;
|
||||
}
|
||||
|
||||
.form-item .number {
|
||||
form .form-item .text {
|
||||
display: inline;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
form .form-item .number {
|
||||
display: inline;
|
||||
width: auto;
|
||||
}
|
||||
|
|
|
@ -311,10 +311,6 @@ function filter_admin_delete_submit($form, &$form_state) {
|
|||
|
||||
$default = variable_get('filter_default_format', 1);
|
||||
// Replace existing instances of the deleted format with the default format.
|
||||
db_update('node_revision')
|
||||
->fields(array('format' => $default))
|
||||
->condition('format', $form_state['values']['format'])
|
||||
->execute();
|
||||
if (db_table_exists('comment')) {
|
||||
db_update('comment')
|
||||
->fields(array('format' => $default))
|
||||
|
|
|
@ -109,8 +109,8 @@ class FilterAdminTestCase extends DrupalWebTestCase {
|
|||
|
||||
$edit = array();
|
||||
$edit['title'] = $this->randomName();
|
||||
$edit['body'] = $body . '<random>' . $extra_text . '</random>';
|
||||
$edit['body_format'] = $filtered;
|
||||
$edit['body[0][value]'] = $body . '<random>' . $extra_text . '</random>';
|
||||
$edit['body[0][value_format]'] = $filtered;
|
||||
$this->drupalPost('node/add/page', $edit, t('Save'));
|
||||
$this->assertRaw(t('Page %title has been created.', array('%title' => $edit['title'])), t('Filtered node created.'));
|
||||
|
||||
|
|
|
@ -549,8 +549,6 @@ function forum_form($node, $form_state) {
|
|||
$form['shadow'] = array('#type' => 'checkbox', '#title' => t('Leave shadow copy'), '#default_value' => $shadow, '#description' => t('If you move this topic, you can leave a link in the old forum to the new forum.'));
|
||||
}
|
||||
|
||||
$form['body_field'] = node_body_field($node, $type->body_label, 1);
|
||||
|
||||
$form['#submit'][] = 'forum_submit';
|
||||
// Assign the forum topic submit handler.
|
||||
|
||||
|
|
|
@ -233,7 +233,7 @@ class ForumTestCase extends DrupalWebTestCase {
|
|||
|
||||
$edit = array(
|
||||
'title' => $title,
|
||||
'body' => $body,
|
||||
'body[0][value]' => $body,
|
||||
'taxonomy[1]' => $tid
|
||||
);
|
||||
|
||||
|
@ -322,7 +322,7 @@ class ForumTestCase extends DrupalWebTestCase {
|
|||
// Edit forum node (including moving it to another forum).
|
||||
$edit = array();
|
||||
$edit['title'] = 'node/' . $node->nid;
|
||||
$edit['body'] = $this->randomName(256);
|
||||
$edit['body[0][value]'] = $this->randomName(256);
|
||||
$edit['taxonomy[1]'] = $this->root_forum['tid']; // Assumes the topic is initially associated with $forum.
|
||||
$edit['shadow'] = TRUE;
|
||||
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
||||
|
|
|
@ -54,14 +54,19 @@ class HelpTestCase extends DrupalWebTestCase {
|
|||
// View module help node.
|
||||
$this->drupalGet('admin/help/' . $module);
|
||||
$this->assertResponse($response);
|
||||
if ($response == 200) {
|
||||
// NOTE: The asserts fail on blog and poll because the get returns the 'admin/help' node instead of the indicated node???
|
||||
// if ($module == 'blog' || $module == 'poll') {
|
||||
// continue;
|
||||
// }
|
||||
$this->assertTitle($name . ' | Drupal', t('[' . $module . '] Title was displayed'));
|
||||
$this->assertRaw('<h2>' . t($name) . '</h2>', t('[' . $module . '] Heading was displayed'));
|
||||
$this->assertText(t('Home ' . $crumb . ' Administer ' . $crumb . ' Help'), t('[' . $module . '] Breadcrumbs were displayed'));
|
||||
if (drupal_function_exists($module . '_help')) {
|
||||
// View module help node.
|
||||
$this->drupalGet('admin/help/' . $module);
|
||||
$this->assertResponse($response);
|
||||
if ($response == 200) {
|
||||
// NOTE: The asserts fail on blog and poll because the get returns the 'admin/help' node instead of the indicated node???
|
||||
// if ($module == 'blog' || $module == 'poll') {
|
||||
// continue;
|
||||
// }
|
||||
$this->assertTitle($name . ' | Drupal', t('[' . $module . '] Title was displayed'));
|
||||
$this->assertRaw('<h2>' . t($name) . '</h2>', t('[' . $module . '] Heading was displayed'));
|
||||
$this->assertText(t('Home ' . $crumb . ' Administer ' . $crumb . ' Help'), t('[' . $module . '] Breadcrumbs were displayed'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1395,7 +1395,7 @@ class LocaleContentFunctionalTest extends DrupalWebTestCase {
|
|||
$edit = array(
|
||||
'type' => 'page',
|
||||
'title' => $node_title,
|
||||
'body' => $node_body,
|
||||
'body' => array(array('value' => $node_body)),
|
||||
'language' => $langcode,
|
||||
);
|
||||
$node = $this->drupalCreateNode($edit);
|
||||
|
|
|
@ -204,7 +204,7 @@ function hook_node_grants_alter(&$grants, $account, $op) {
|
|||
|
||||
// Get our list of banned roles.
|
||||
$restricted = variable_get('example_restricted_roles', array());
|
||||
|
||||
|
||||
if ($op != 'view' && !empty($restricted)) {
|
||||
// Now check the roles for this account against the restrictions.
|
||||
foreach ($restricted as $role_id) {
|
||||
|
@ -904,7 +904,6 @@ function hook_view($node, $teaser = FALSE) {
|
|||
menu_set_location($breadcrumb);
|
||||
}
|
||||
|
||||
$node = node_prepare($node, $teaser);
|
||||
$node->content['myfield'] = array(
|
||||
'#value' => theme('mymodule_myfield', $node->myfield),
|
||||
'#weight' => 1,
|
||||
|
|
|
@ -213,18 +213,6 @@ function node_schema() {
|
|||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
),
|
||||
'body' => array(
|
||||
'description' => 'The body of this version.',
|
||||
'type' => 'text',
|
||||
'not null' => TRUE,
|
||||
'size' => 'big',
|
||||
),
|
||||
'teaser' => array(
|
||||
'description' => 'The teaser of this version.',
|
||||
'type' => 'text',
|
||||
'not null' => TRUE,
|
||||
'size' => 'big',
|
||||
),
|
||||
'log' => array(
|
||||
'description' => 'The log entry explaining the changes in this version.',
|
||||
'type' => 'text',
|
||||
|
@ -237,12 +225,6 @@ function node_schema() {
|
|||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
),
|
||||
'format' => array(
|
||||
'description' => "The text format used by this version's body.",
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
),
|
||||
),
|
||||
'indexes' => array(
|
||||
'nid' => array('nid'),
|
||||
|
@ -304,7 +286,7 @@ function node_schema() {
|
|||
'default' => '',
|
||||
),
|
||||
'has_body' => array(
|
||||
'description' => 'Boolean indicating whether this type uses the {node_revision}.body field.',
|
||||
'description' => 'Boolean indicating whether this type has the body field attached.',
|
||||
'type' => 'int',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
|
@ -416,6 +398,7 @@ function node_update_7004() {
|
|||
|
||||
// Map old preview setting to new values order.
|
||||
$original_preview ? $original_preview = 2 : $original_preview = 1;
|
||||
$node_types_clear();
|
||||
$type_list = node_type_get_types();
|
||||
|
||||
// Apply original settings to all types.
|
||||
|
@ -429,6 +412,119 @@ function node_update_7004() {
|
|||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert body and teaser from node properties to fields.
|
||||
*/
|
||||
function node_update_7005(&$context) {
|
||||
$ret = array('#finished' => 0);
|
||||
|
||||
// Get node type info for every invocation.
|
||||
node_type_clear();
|
||||
$node_types = node_type_get_types();
|
||||
$body_types = array();
|
||||
foreach ($node_types as $type => $info) {
|
||||
if ($info->has_body) {
|
||||
$body_types[] = $type;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($context['total'])) {
|
||||
// Initial invocation.
|
||||
|
||||
// Re-save node types to create body field instances.
|
||||
foreach ($node_types as $type => $info) {
|
||||
if ($info->has_body) {
|
||||
node_type_save($info);
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize state for future calls.
|
||||
$context['last'] = 0;
|
||||
$context['count'] = 0;
|
||||
|
||||
$query = db_select('node', 'n');
|
||||
$query->join('node_revision', 'nr', 'n.vid = nr.vid');
|
||||
$query->condition('n.type', $body_types, 'IN');
|
||||
$context['total'] = $query->countQuery()->execute()->fetchField();
|
||||
}
|
||||
else {
|
||||
// Subsequent invocations.
|
||||
|
||||
$found = FALSE;
|
||||
if ($context['total']) {
|
||||
// Operate on every revision of every node (whee!), in batches.
|
||||
$batch_size = 50;
|
||||
$query = db_select('node', 'n');
|
||||
$nr = $query->innerJoin('node_revision', 'nr', 'n.vid = nr.vid');
|
||||
$revisions = $query
|
||||
->fields('n', array('type'))
|
||||
->fields($nr)
|
||||
->condition('nr.vid', $context['last'], '>')
|
||||
->condition('n.type', $body_types, 'IN')
|
||||
->orderBy('nr.vid', 'ASC')
|
||||
->execute();
|
||||
|
||||
// Load each reversion of each node, set up 'body'
|
||||
// appropriately, and save the node's field data. Note that
|
||||
// node_load() will not return the body or teaser values from
|
||||
// {node_revision} because those columns have been removed from the
|
||||
// schema structure in memory (but not yet from the database),
|
||||
// so we get the values from the explicit query of the table
|
||||
// instead.
|
||||
foreach ($revisions as $revision) {
|
||||
$found = TRUE;
|
||||
|
||||
if ($node_types[$revision->type]->has_body) {
|
||||
$node = (object) array(
|
||||
'nid' => $revision->nid,
|
||||
'vid' => $revision->vid,
|
||||
'type' => $revision->type,
|
||||
);
|
||||
if (!empty($revision->teaser) && $revision->teaser != text_summary($revision->body)) {
|
||||
$node->body[0]['summary'] = $revision->teaser;
|
||||
}
|
||||
// Do this after text_summary() above.
|
||||
$break = '<!--break-->';
|
||||
if (substr($revision->body, 0, strlen($break)) == $break) {
|
||||
$revision->body = substr($revision->body, strlen($break));
|
||||
}
|
||||
$node->body[0]['value'] = $revision->body;
|
||||
$node->body[0]['format'] = $revision->format;
|
||||
// This is a core update and no contrib modules are enabled yet, so
|
||||
// we can assume default field storage for a faster update.
|
||||
field_sql_storage_field_storage_write('node', $node, FIELD_STORAGE_INSERT, array());
|
||||
}
|
||||
|
||||
$context['last'] = $revision->vid;
|
||||
$context['count'] += 1;
|
||||
|
||||
if (--$batch_size == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$ret['#finished'] = min(0.99, $context['count'] / $context['total']);
|
||||
}
|
||||
|
||||
if (!$found) {
|
||||
// All nodes are processed.
|
||||
$ret[] = array('success' => TRUE, 'query' => "{$context['total']} node body and teaser properties migrated to the 'body' field.");
|
||||
|
||||
// Remove the now-obsolete body info from node_revision.
|
||||
db_drop_field($ret, 'node_revision', 'body');
|
||||
db_drop_field($ret, 'node_revision', 'teaser');
|
||||
db_drop_field($ret, 'node_revision', 'format');
|
||||
|
||||
// We're done.
|
||||
$ret['#finished'] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @} End of "defgroup updates-6.x-to-7.x"
|
||||
* The next series of updates should start at 8000.
|
||||
|
|
|
@ -290,186 +290,6 @@ function node_mark($nid, $timestamp) {
|
|||
return MARK_READ;
|
||||
}
|
||||
|
||||
/**
|
||||
* See if the user used JS to submit a teaser.
|
||||
*/
|
||||
function node_teaser_js(&$form, &$form_state) {
|
||||
if (isset($form_state['input']['teaser_js'])) {
|
||||
// Glue the teaser to the body.
|
||||
if (trim($form_state['values']['teaser_js'])) {
|
||||
// Space the teaser from the body
|
||||
$body = trim($form_state['values']['teaser_js']) . "\r\n<!--break-->\r\n" . trim($form_state['values']['body']);
|
||||
}
|
||||
else {
|
||||
// Empty teaser, no spaces.
|
||||
$body = '<!--break-->' . $form_state['values']['body'];
|
||||
}
|
||||
// Pass updated body value on to preview/submit form processing.
|
||||
form_set_value($form['body'], $body, $form_state);
|
||||
// Pass updated body value back onto form for those cases
|
||||
// in which the form is redisplayed.
|
||||
$form['body']['#value'] = $body;
|
||||
}
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure value of "teaser_include" checkbox is consistent with other form data.
|
||||
*
|
||||
* This handles two situations in which an unchecked checkbox is rejected:
|
||||
*
|
||||
* 1. The user defines a teaser (summary) but it is empty;
|
||||
* 2. The user does not define a teaser (summary) (in this case an
|
||||
* unchecked checkbox would cause the body to be empty, or missing
|
||||
* the auto-generated teaser).
|
||||
*
|
||||
* If JavaScript is active then it is used to force the checkbox to be
|
||||
* checked when hidden, and so the second case will not arise.
|
||||
*
|
||||
* In either case a warning message is output.
|
||||
*/
|
||||
function node_teaser_include_verify(&$form, &$form_state) {
|
||||
$message = '';
|
||||
|
||||
// $form_state['input'] is set only when the form is built for preview/submit.
|
||||
if (isset($form_state['input']['body']) && isset($form_state['values']['teaser_include']) && !$form_state['values']['teaser_include']) {
|
||||
// "teaser_include" checkbox is present and unchecked.
|
||||
if (strpos($form_state['values']['body'], '<!--break-->') === 0) {
|
||||
// Teaser is empty string.
|
||||
$message = t('You specified that the summary should not be shown when this post is displayed in full view. This setting is ignored when the summary is empty.');
|
||||
}
|
||||
elseif (strpos($form_state['values']['body'], '<!--break-->') === FALSE) {
|
||||
// Teaser delimiter is not present in the body.
|
||||
$message = t('You specified that the summary should not be shown when this post is displayed in full view. This setting has been ignored since you have not defined a summary for the post. (To define a summary, insert the delimiter "<!--break-->" (without the quotes) in the Body of the post to indicate the end of the summary and the start of the main content.)');
|
||||
}
|
||||
|
||||
if (!empty($message)) {
|
||||
drupal_set_message($message, 'warning');
|
||||
// Pass new checkbox value on to preview/submit form processing.
|
||||
form_set_value($form['teaser_include'], 1, $form_state);
|
||||
// Pass new checkbox value back onto form for those cases
|
||||
// in which form is redisplayed.
|
||||
$form['teaser_include']['#value'] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a teaser for a node body.
|
||||
*
|
||||
* If the end of the teaser is not indicated using the <!--break--> delimiter
|
||||
* then we generate the teaser automatically, trying to end it at a sensible
|
||||
* place such as the end of a paragraph, a line break, or the end of a
|
||||
* sentence (in that order of preference).
|
||||
*
|
||||
* @param $body
|
||||
* The content for which a teaser will be generated.
|
||||
* @param $format
|
||||
* The format of the content. If the content contains PHP code, we do not
|
||||
* split it up to prevent parse errors. If the line break filter is present
|
||||
* then we treat newlines embedded in $body as line breaks.
|
||||
* @param $size
|
||||
* The desired character length of the teaser. If omitted, the default
|
||||
* value will be used. Ignored if the special delimiter is present
|
||||
* in $body.
|
||||
* @return
|
||||
* The generated teaser.
|
||||
*/
|
||||
function node_teaser($body, $format = NULL, $size = NULL) {
|
||||
|
||||
if (!isset($size)) {
|
||||
$size = variable_get('teaser_length', 600);
|
||||
}
|
||||
|
||||
// Find where the delimiter is in the body
|
||||
$delimiter = strpos($body, '<!--break-->');
|
||||
|
||||
// If the size is zero, and there is no delimiter, the entire body is the teaser.
|
||||
if ($size == 0 && $delimiter === FALSE) {
|
||||
return $body;
|
||||
}
|
||||
|
||||
// If a valid delimiter has been specified, use it to chop off the teaser.
|
||||
if ($delimiter !== FALSE) {
|
||||
return substr($body, 0, $delimiter);
|
||||
}
|
||||
|
||||
// We check for the presence of the PHP evaluator filter in the current
|
||||
// format. If the body contains PHP code, we do not split it up to prevent
|
||||
// parse errors.
|
||||
if (isset($format)) {
|
||||
$filters = filter_list_format($format);
|
||||
if (isset($filters['php/0']) && strpos($body, '<?') !== FALSE) {
|
||||
return $body;
|
||||
}
|
||||
}
|
||||
|
||||
// If we have a short body, the entire body is the teaser.
|
||||
if (drupal_strlen($body) <= $size) {
|
||||
return $body;
|
||||
}
|
||||
|
||||
// If the delimiter has not been specified, try to split at paragraph or
|
||||
// sentence boundaries.
|
||||
|
||||
// The teaser may not be longer than maximum length specified. Initial slice.
|
||||
$teaser = truncate_utf8($body, $size);
|
||||
|
||||
// Store the actual length of the UTF8 string -- which might not be the same
|
||||
// as $size.
|
||||
$max_rpos = strlen($teaser);
|
||||
|
||||
// How much to cut off the end of the teaser so that it doesn't end in the
|
||||
// middle of a paragraph, sentence, or word.
|
||||
// Initialize it to maximum in order to find the minimum.
|
||||
$min_rpos = $max_rpos;
|
||||
|
||||
// Store the reverse of the teaser. We use strpos on the reversed needle and
|
||||
// haystack for speed and convenience.
|
||||
$reversed = strrev($teaser);
|
||||
|
||||
// Build an array of arrays of break points grouped by preference.
|
||||
$break_points = array();
|
||||
|
||||
// A paragraph near the end of sliced teaser is most preferable.
|
||||
$break_points[] = array('</p>' => 0);
|
||||
|
||||
// If no complete paragraph then treat line breaks as paragraphs.
|
||||
$line_breaks = array('<br />' => 6, '<br>' => 4);
|
||||
// Newline only indicates a line break if line break converter
|
||||
// filter is present.
|
||||
if (isset($filters['filter/1'])) {
|
||||
$line_breaks["\n"] = 1;
|
||||
}
|
||||
$break_points[] = $line_breaks;
|
||||
|
||||
// If the first paragraph is too long, split at the end of a sentence.
|
||||
$break_points[] = array('. ' => 1, '! ' => 1, '? ' => 1, '。' => 0, '؟ ' => 1);
|
||||
|
||||
// Iterate over the groups of break points until a break point is found.
|
||||
foreach ($break_points as $points) {
|
||||
// Look for each break point, starting at the end of the teaser.
|
||||
foreach ($points as $point => $offset) {
|
||||
// The teaser is already reversed, but the break point isn't.
|
||||
$rpos = strpos($reversed, strrev($point));
|
||||
if ($rpos !== FALSE) {
|
||||
$min_rpos = min($rpos + $offset, $min_rpos);
|
||||
}
|
||||
}
|
||||
|
||||
// If a break point was found in this group, slice and return the teaser.
|
||||
if ($min_rpos !== $max_rpos) {
|
||||
// Don't slice with length 0. Length must be <0 to slice from RHS.
|
||||
return ($min_rpos === 0) ? $teaser : substr($teaser, 0, 0 - $min_rpos);
|
||||
}
|
||||
}
|
||||
|
||||
// If a break point was not found, still return a teaser.
|
||||
return $teaser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the type name.
|
||||
*
|
||||
|
@ -632,6 +452,7 @@ function node_type_save($info) {
|
|||
if (!empty($type->old_type) && $type->old_type != $type->type) {
|
||||
field_attach_rename_bundle($type->old_type, $type->type);
|
||||
}
|
||||
node_configure_fields($type);
|
||||
module_invoke_all('node_type', 'update', $type);
|
||||
return SAVED_UPDATED;
|
||||
}
|
||||
|
@ -642,12 +463,73 @@ function node_type_save($info) {
|
|||
->execute();
|
||||
|
||||
field_attach_create_bundle($type->type);
|
||||
|
||||
node_configure_fields($type);
|
||||
module_invoke_all('node_type', 'insert', $type);
|
||||
return SAVED_NEW;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Manage the field(s) for a node type.
|
||||
*
|
||||
* Currently, the node module manages a single Field API field,
|
||||
* 'body'. If $type->has_body is true, this function ensures the
|
||||
* 'body' field exists and creates an instance of it for the bundle
|
||||
* $type->type (e.g. 'page', 'story', ...). If $type->has_body is
|
||||
* false, this function removes the instance (if it exists) for the
|
||||
* 'body' field on $type->type.
|
||||
*/
|
||||
function node_configure_fields($type) {
|
||||
// Add or remove the body field, as needed.
|
||||
$field = field_info_field('body');
|
||||
$instance = field_info_instance('body', $type->type);
|
||||
if ($type->has_body) {
|
||||
if (empty($field)) {
|
||||
$field = array(
|
||||
'field_name' => 'body',
|
||||
'type' => 'text_with_summary',
|
||||
);
|
||||
$field = field_create_field($field);
|
||||
}
|
||||
if (empty($instance)) {
|
||||
$instance = array(
|
||||
'field_name' => 'body',
|
||||
'bundle' => $type->type,
|
||||
'label' => $type->body_label,
|
||||
'widget_type' => 'text_textarea_with_summary',
|
||||
'settings' => array('display_summary' => TRUE),
|
||||
|
||||
// With no UI in core, we have to define default
|
||||
// formatters for the teaser and full view.
|
||||
// This may change if the method of handling displays
|
||||
// is changed or if a UI gets into core.
|
||||
'display' => array(
|
||||
'full' => array(
|
||||
'label' => 'hidden',
|
||||
'type' => 'text_default',
|
||||
'exclude' => 0,
|
||||
),
|
||||
'teaser' => array(
|
||||
'label' => 'hidden',
|
||||
'type' => 'text_summary_or_trimmed',
|
||||
'exclude' => 0,
|
||||
),
|
||||
),
|
||||
);
|
||||
field_create_instance($instance);
|
||||
}
|
||||
else {
|
||||
$instance['label'] = $type->body_label;
|
||||
$instance['settings']['display_summary'] = TRUE;
|
||||
field_update_instance($instance);
|
||||
}
|
||||
}
|
||||
elseif (!empty($instance)) {
|
||||
field_delete_instance($instance);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a node type from the database.
|
||||
*
|
||||
|
@ -1004,7 +886,8 @@ function node_validate($node, $form = array()) {
|
|||
|
||||
// Make sure the body has the minimum number of words.
|
||||
// TODO : use a better word counting algorithm that will work in other languages
|
||||
if (!empty($type->min_word_count) && isset($node->body) && count(explode(' ', $node->body)) < $type->min_word_count) {
|
||||
if (!empty($type->min_word_count) && isset($node->body[0]['value']) && count(explode(' ', $node->body[0]['value'])) < $type->min_word_count) {
|
||||
// TODO: Use Field API to set this error.
|
||||
form_set_error('body', t('The body of your @type is too short. You need at least %words words.', array('%words' => $type->min_word_count, '@type' => $type->name)));
|
||||
}
|
||||
|
||||
|
@ -1041,25 +924,6 @@ function node_submit($node) {
|
|||
// Convert the node to an object, if necessary.
|
||||
$node = (object)$node;
|
||||
|
||||
// Generate the teaser, but only if it hasn't been set (e.g. by a
|
||||
// module-provided 'teaser' form item).
|
||||
if (!isset($node->teaser)) {
|
||||
if (isset($node->body)) {
|
||||
$node->format = (!empty($node->body_format) ? $node->body_format : FILTER_FORMAT_DEFAULT);
|
||||
$node->teaser = node_teaser($node->body, isset($node->format) ? $node->format : NULL, variable_get('teaser_length_' . $node->type, 600));
|
||||
// Chop off the teaser from the body if needed. The teaser_include
|
||||
// property might not be set (eg. in Blog API postings), so only act on
|
||||
// it, if it was set with a given value.
|
||||
if (isset($node->teaser_include) && !$node->teaser_include && $node->teaser == substr($node->body, 0, strlen($node->teaser))) {
|
||||
$node->body = substr($node->body, strlen($node->teaser));
|
||||
}
|
||||
}
|
||||
else {
|
||||
$node->teaser = '';
|
||||
$node->format = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (user_access('administer nodes')) {
|
||||
// Populate the "authored by" field.
|
||||
if ($account = user_load_by_name($node->name)) {
|
||||
|
@ -1105,16 +969,6 @@ function node_save($node) {
|
|||
if (!isset($node->log)) {
|
||||
$node->log = '';
|
||||
}
|
||||
|
||||
// For the same reasons, make sure we have $node->teaser and
|
||||
// $node->body. We should consider making these fields nullable
|
||||
// in a future version since node types are not required to use them.
|
||||
if (!isset($node->teaser)) {
|
||||
$node->teaser = '';
|
||||
}
|
||||
if (!isset($node->body)) {
|
||||
$node->body = '';
|
||||
}
|
||||
}
|
||||
elseif (!empty($node->revision)) {
|
||||
$node->old_vid = $node->vid;
|
||||
|
@ -1273,30 +1127,6 @@ function node_build($node, $teaser = FALSE) {
|
|||
return $build;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply filters and build the node's standard elements.
|
||||
*/
|
||||
function node_prepare($node, $teaser = FALSE) {
|
||||
// First we'll overwrite the existing node teaser and body with
|
||||
// the filtered copies! Then, we'll stick those into the content
|
||||
// array and set the read more flag if appropriate.
|
||||
$node->readmore = (strlen($node->teaser) < strlen($node->body));
|
||||
|
||||
if ($teaser == FALSE) {
|
||||
$node->body = check_markup($node->body, $node->format, $node->language, FALSE);
|
||||
}
|
||||
else {
|
||||
$node->teaser = check_markup($node->teaser, $node->format, $node->language, FALSE);
|
||||
}
|
||||
|
||||
$node->content['body'] = array(
|
||||
'#markup' => $teaser ? $node->teaser : $node->body,
|
||||
'#weight' => 0,
|
||||
);
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a structured array representing the node's content.
|
||||
*
|
||||
|
@ -1322,30 +1152,41 @@ function node_prepare($node, $teaser = FALSE) {
|
|||
*
|
||||
* @return
|
||||
* An structured array containing the individual elements
|
||||
* of the node's body.
|
||||
* of the node's content.
|
||||
*/
|
||||
function node_build_content($node, $teaser = FALSE) {
|
||||
|
||||
// The build mode identifies the target for which the node is built.
|
||||
if (!isset($node->build_mode)) {
|
||||
$node->build_mode = NODE_BUILD_NORMAL;
|
||||
}
|
||||
|
||||
// Remove the delimiter (if any) that separates the teaser from the body.
|
||||
$node->body = isset($node->body) ? str_replace('<!--break-->', '', $node->body) : '';
|
||||
|
||||
// The 'view' hook can be implemented to overwrite the default function
|
||||
// to display nodes.
|
||||
if (node_hook($node, 'view')) {
|
||||
$node = node_invoke($node, 'view', $teaser);
|
||||
}
|
||||
else {
|
||||
$node = node_prepare($node, $teaser);
|
||||
}
|
||||
|
||||
// Build fields content.
|
||||
if (empty($node->content)) {
|
||||
$node->content = array();
|
||||
};
|
||||
$node->content += field_attach_view('node', $node, $teaser);
|
||||
|
||||
// Always display a read more link on teasers because we have no way
|
||||
// to know when a teaser view is different than a full view.
|
||||
$links = array();
|
||||
if ($teaser) {
|
||||
$links['node_readmore'] = array(
|
||||
'title' => t('Read more'),
|
||||
'href' => 'node/' . $node->nid,
|
||||
'attributes' => array('rel' => 'tag', 'title' => strip_tags($node->title))
|
||||
);
|
||||
}
|
||||
$node->content['links']['node'] = array(
|
||||
'#type' => 'node_links',
|
||||
'#value' => $links
|
||||
);
|
||||
|
||||
// Allow modules to make their own additions to the node.
|
||||
module_invoke_all('node_view', $node, $teaser);
|
||||
|
||||
|
@ -1649,16 +1490,16 @@ function node_search($op = 'search', $keys = NULL) {
|
|||
// Load results.
|
||||
$results = array();
|
||||
foreach ($find as $item) {
|
||||
// Build the node body.
|
||||
// Render the node.
|
||||
$node = node_load($item->sid);
|
||||
$node->build_mode = NODE_BUILD_SEARCH_RESULT;
|
||||
$node = node_build_content($node, FALSE, FALSE);
|
||||
$node->body = drupal_render($node->content);
|
||||
$node->rendered = drupal_render($node->content);
|
||||
|
||||
// Fetch comments for snippet.
|
||||
$node->body .= module_invoke('comment', 'node_update_index', $node);
|
||||
$node->rendered .= module_invoke('comment', 'node_update_index', $node);
|
||||
// Fetch terms for snippet.
|
||||
$node->body .= module_invoke('taxonomy', 'node_update_index', $node);
|
||||
$node->rendered .= module_invoke('taxonomy', 'node_update_index', $node);
|
||||
|
||||
$extra = module_invoke_all('node_search_result', $node);
|
||||
|
||||
|
@ -1671,7 +1512,7 @@ function node_search($op = 'search', $keys = NULL) {
|
|||
'node' => $node,
|
||||
'extra' => $extra,
|
||||
'score' => $total ? ($item->calculated_score / $total) : 0,
|
||||
'snippet' => search_excerpt($keys, $node->body),
|
||||
'snippet' => search_excerpt($keys, $node->rendered),
|
||||
);
|
||||
}
|
||||
return $results;
|
||||
|
@ -1801,7 +1642,7 @@ function node_link($type, $node = NULL, $teaser = FALSE) {
|
|||
$links = array();
|
||||
|
||||
if ($type == 'node') {
|
||||
if ($teaser == 1 && $node->teaser && !empty($node->readmore)) {
|
||||
if ($teaser == 1) {
|
||||
$links['node_read_more'] = array(
|
||||
'title' => t('Read more'),
|
||||
'href' => "node/$node->nid",
|
||||
|
@ -2254,12 +2095,12 @@ function _node_index_node($node) {
|
|||
// results half-life calculation.
|
||||
variable_set('node_cron_last', $node->changed);
|
||||
|
||||
// Build the node body.
|
||||
// Render the node.
|
||||
$node->build_mode = NODE_BUILD_SEARCH_INDEX;
|
||||
$node = node_build_content($node, FALSE, FALSE);
|
||||
$node->body = drupal_render($node->content);
|
||||
$node->rendered = drupal_render($node->content);
|
||||
|
||||
$text = '<h1>' . check_plain($node->title) . '</h1>' . $node->body;
|
||||
$text = '<h1>' . check_plain($node->title) . '</h1>' . $node->rendered;
|
||||
|
||||
// Fetch extra data normally not visible
|
||||
$extra = module_invoke_all('node_update_index', $node);
|
||||
|
@ -2464,10 +2305,6 @@ function node_access($op, $node, $account = NULL) {
|
|||
if (empty($account)) {
|
||||
$account = $user;
|
||||
}
|
||||
// If the node is in a restricted format, disallow editing.
|
||||
if ($op == 'update' && !filter_access($node->format)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (user_access('bypass node access', $account)) {
|
||||
return TRUE;
|
||||
|
@ -2977,9 +2814,9 @@ function node_content_access($op, $node, $account) {
|
|||
* Implement hook_form().
|
||||
*/
|
||||
function node_content_form($node, $form_state) {
|
||||
|
||||
|
||||
$type = node_type_get_type($node);
|
||||
|
||||
|
||||
$form = array();
|
||||
|
||||
if ($type->has_title) {
|
||||
|
@ -2993,8 +2830,6 @@ function node_content_form($node, $form_state) {
|
|||
);
|
||||
}
|
||||
|
||||
$form['body_field'] = node_body_field($node, $type->body_label, $type->min_word_count);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@ function node_form(&$form_state, $node) {
|
|||
$form['#prefix'] = $form_state['node_preview'];
|
||||
}
|
||||
$node = (object)$node;
|
||||
foreach (array('body', 'title', 'format') as $key) {
|
||||
foreach (array('title') as $key) {
|
||||
if (!isset($node->$key)) {
|
||||
$node->$key = NULL;
|
||||
}
|
||||
|
@ -286,52 +286,6 @@ function node_form(&$form_state, $node) {
|
|||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a node body field, with format and teaser.
|
||||
*/
|
||||
function node_body_field($node, $label, $word_count) {
|
||||
// Do not generate a body field if the type does not specify one.
|
||||
if (!node_type_get_type($node->type)->has_body) {
|
||||
return array();
|
||||
}
|
||||
|
||||
// Check if we need to restore the teaser at the beginning of the body.
|
||||
$include = !isset($node->teaser) || ($node->teaser == substr($node->body, 0, strlen($node->teaser)));
|
||||
|
||||
$form = array(
|
||||
'#after_build' => array('node_teaser_js', 'node_teaser_include_verify'));
|
||||
|
||||
$form['#prefix'] = '<div class="body-field-wrapper clearfix">';
|
||||
$form['#suffix'] = '</div>';
|
||||
|
||||
$form['teaser_js'] = array(
|
||||
'#type' => 'textarea',
|
||||
'#rows' => 10,
|
||||
'#teaser' => 'edit-body',
|
||||
'#teaser_checkbox' => 'edit-teaser-include',
|
||||
'#disabled' => TRUE,
|
||||
);
|
||||
|
||||
$form['teaser_include'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Show summary in full view'),
|
||||
'#default_value' => $include,
|
||||
'#prefix' => '<div class="teaser-checkbox">',
|
||||
'#suffix' => '</div>',
|
||||
);
|
||||
|
||||
$form['body'] = array(
|
||||
'#type' => 'textarea',
|
||||
'#title' => check_plain($label),
|
||||
'#default_value' => $include ? $node->body : ($node->teaser . $node->body),
|
||||
'#rows' => 20,
|
||||
'#required' => ($word_count > 0),
|
||||
'#text_format' => isset($node->format) ? $node->format : FILTER_FORMAT_DEFAULT,
|
||||
);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Button submit function: handle the 'Delete' button on the node form.
|
||||
*/
|
||||
|
@ -393,16 +347,6 @@ function node_preview($node) {
|
|||
|
||||
$node->changed = REQUEST_TIME;
|
||||
|
||||
// Extract a teaser, if it hasn't been set (e.g. by a module-provided
|
||||
// 'teaser' form item).
|
||||
if (!isset($node->teaser)) {
|
||||
$node->teaser = empty($node->body) ? '' : node_teaser($node->body, $node->format, variable_get('teaser_length_' . $type, 600));
|
||||
// Chop off the teaser from the body if needed.
|
||||
if (!$node->teaser_include && $node->teaser == substr($node->body, 0, strlen($node->teaser))) {
|
||||
$node->body = substr($node->body, strlen($node->teaser));
|
||||
}
|
||||
}
|
||||
|
||||
// Display a preview of the node.
|
||||
// Previewing alters $node so it needs to be cloned.
|
||||
if (!form_get_errors()) {
|
||||
|
@ -428,28 +372,20 @@ function theme_node_preview($node) {
|
|||
$output = '<div class="preview">';
|
||||
|
||||
$preview_trimmed_version = FALSE;
|
||||
|
||||
$trimmed = drupal_render(node_build(clone $node, TRUE));
|
||||
$full = drupal_render(node_build($node, FALSE));
|
||||
|
||||
// Do we need to preview trimmed version of post as well as full version?
|
||||
if (isset($node->teaser) && isset($node->body)) {
|
||||
$teaser = trim($node->teaser);
|
||||
$body = trim(str_replace('<!--break-->', '', $node->body));
|
||||
|
||||
// Preview trimmed version if teaser and body will appear different;
|
||||
// also (edge case) if both teaser and body have been specified by the user
|
||||
// and are actually the same.
|
||||
if ($teaser != $body || ($body && strpos($node->body, '<!--break-->') === 0)) {
|
||||
$preview_trimmed_version = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if ($preview_trimmed_version) {
|
||||
if ($trimmed != $full) {
|
||||
drupal_set_message(t('The trimmed version of your post shows what your post looks like when promoted to the main page or when exported for syndication.<span class="no-js"> You can insert the delimiter "<!--break-->" (without the quotes) to fine-tune where your post gets split.</span>'));
|
||||
$output .= '<h3>' . t('Preview trimmed version') . '</h3>';
|
||||
$output .= drupal_render(node_build(clone $node, TRUE));
|
||||
$output .= $trimmed;
|
||||
$output .= '<h3>' . t('Preview full version') . '</h3>';
|
||||
$output .= drupal_render(node_build($node, FALSE));
|
||||
$output .= $full;
|
||||
}
|
||||
else {
|
||||
$output .= drupal_render(node_build($node, FALSE));
|
||||
$output .= $full;
|
||||
}
|
||||
$output .= "</div>\n";
|
||||
|
||||
|
|
|
@ -141,7 +141,7 @@ class NodeRevisionsTestCase extends DrupalWebTestCase {
|
|||
|
||||
// Confirm the correct revision text appears on "view revisions" page.
|
||||
$this->drupalGet("node/$node->nid/revisions/$node->vid/view");
|
||||
$this->assertText($node->body, t('Correct text displays for version.'));
|
||||
$this->assertText($node->body[0]['value'], t('Correct text displays for version.'));
|
||||
|
||||
// Confirm the correct log message appears on "revisions overview" page.
|
||||
$this->drupalGet("node/$node->nid/revisions");
|
||||
|
@ -155,7 +155,7 @@ class NodeRevisionsTestCase extends DrupalWebTestCase {
|
|||
array('@type' => 'Page', '%title' => $nodes[1]->title,
|
||||
'%revision-date' => format_date($nodes[1]->revision_timestamp))), t('Revision reverted.'));
|
||||
$reverted_node = node_load($node->nid);
|
||||
$this->assertTrue(($nodes[1]->body == $reverted_node->body), t('Node reverted correctly.'));
|
||||
$this->assertTrue(($nodes[1]->body[0]['value'] == $reverted_node->body[0]['value']), t('Node reverted correctly.'));
|
||||
|
||||
// Confirm revisions delete properly.
|
||||
$this->drupalPost("node/$node->nid/revisions/{$nodes[1]->vid}/delete", array(), t('Delete'));
|
||||
|
@ -166,151 +166,6 @@ class NodeRevisionsTestCase extends DrupalWebTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
class NodeTeaserTestCase extends DrupalWebTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => t('Node teaser'),
|
||||
'description' => t('Test node_teaser() with different strings and lengths.'),
|
||||
'group' => t('Node'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests an edge case where if the first sentence is a question and
|
||||
* subsequent sentences are not. This is edge case is documented at
|
||||
* http://drupal.org/node/180425.
|
||||
*/
|
||||
function testFirstSentenceQuestion() {
|
||||
$body = 'A question? A sentence. Another sentence.';
|
||||
$expected = 'A question? A sentence.';
|
||||
$this->callNodeTeaser($body, $expected, NULL, 30);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test teaser with long example.
|
||||
*/
|
||||
function testLongSentence() {
|
||||
$body = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ' . // 125
|
||||
'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. ' . // 108
|
||||
'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. ' . // 103
|
||||
'Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'; // 110
|
||||
$expected = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ' .
|
||||
'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. ' .
|
||||
'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.';
|
||||
// First three sentences add up to: 336, so add one for space and then 3 to get half-way into next word.
|
||||
$this->callNodeTeaser($body, $expected, NULL, 340);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test various teaser length edge cases.
|
||||
*/
|
||||
function testLength() {
|
||||
// This body string tests a number of edge cases.
|
||||
$body = "<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>";
|
||||
|
||||
// The teasers we expect node_teaser() to return when $size is the index
|
||||
// of each array item.
|
||||
// Using an text format with no line-break filter:
|
||||
$teasers = array(
|
||||
"<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>",
|
||||
"<",
|
||||
"<p",
|
||||
"<p>",
|
||||
"<p>\n",
|
||||
"<p>\nH",
|
||||
"<p>\nHi",
|
||||
"<p>\nHi\n",
|
||||
"<p>\nHi\n<",
|
||||
"<p>\nHi\n</",
|
||||
"<p>\nHi\n</p",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>",
|
||||
"<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>",
|
||||
"<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>",
|
||||
);
|
||||
|
||||
// And Using an text format WITH the line-break filter.
|
||||
$teasers_lb = array(
|
||||
"<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>",
|
||||
"<",
|
||||
"<p",
|
||||
"<p>",
|
||||
"<p>",
|
||||
"<p>",
|
||||
"<p>",
|
||||
"<p>\nHi",
|
||||
"<p>\nHi",
|
||||
"<p>\nHi",
|
||||
"<p>\nHi",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>",
|
||||
"<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>",
|
||||
"<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>",
|
||||
"<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>",
|
||||
);
|
||||
|
||||
// Test node_teaser() for different sizes.
|
||||
for ($i = 0; $i <= 37; $i++) {
|
||||
$this->callNodeTeaser($body, $teasers[$i], NULL, $i);
|
||||
$this->callNodeTeaser($body, $teasers_lb[$i], 1, $i);
|
||||
$this->callNodeTeaser($body, $teasers_lb[$i], 2, $i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls node_teaser() and asserts that the expected teaser is returned.
|
||||
*/
|
||||
function callNodeTeaser($body, $expected, $format = NULL, $size = NULL) {
|
||||
$teaser = node_teaser($body, $format, $size);
|
||||
$this->assertIdentical($teaser, $expected, t('Generated teaser "@teaser" matches expected teaser.', array('@teaser' => $teaser)));
|
||||
}
|
||||
}
|
||||
|
||||
class PageEditTestCase extends DrupalWebTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
|
@ -331,10 +186,11 @@ class PageEditTestCase extends DrupalWebTestCase {
|
|||
* Check node edit functionality.
|
||||
*/
|
||||
function testPageEdit() {
|
||||
$body_key = 'body[0][value]';
|
||||
// Create node to edit.
|
||||
$edit = array();
|
||||
$edit['title'] = $this->randomName(8);
|
||||
$edit['body'] = $this->randomName(16);
|
||||
$edit[$body_key] = $this->randomName(16);
|
||||
$this->drupalPost('node/add/page', $edit, t('Save'));
|
||||
|
||||
// Check that the node exists in the database.
|
||||
|
@ -350,18 +206,18 @@ class PageEditTestCase extends DrupalWebTestCase {
|
|||
// Check that the title and body fields are displayed with the correct values.
|
||||
$this->assertLink(t('Edit'), 0, t('Edit tab found.'));
|
||||
$this->assertFieldByName('title', $edit['title'], t('Title field displayed.'));
|
||||
$this->assertFieldByName('body', '<!--break-->' . $edit['body'], t('Body field displayed.'));
|
||||
$this->assertFieldByName($body_key, $edit[$body_key], t('Body field displayed.'));
|
||||
|
||||
// Edit the content of the node.
|
||||
$edit = array();
|
||||
$edit['title'] = $this->randomName(8);
|
||||
$edit['body'] = $this->randomName(16);
|
||||
$edit[$body_key] = $this->randomName(16);
|
||||
// Stay on the current page, without reloading.
|
||||
$this->drupalPost(NULL, $edit, t('Save'));
|
||||
|
||||
// Check that the title and body fields are displayed with the updated values.
|
||||
$this->assertText($edit['title'], t('Title displayed.'));
|
||||
$this->assertText($edit['body'], t('Body displayed.'));
|
||||
$this->assertText($edit[$body_key], t('Body displayed.'));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -385,44 +241,47 @@ class PagePreviewTestCase extends DrupalWebTestCase {
|
|||
* Check the node preview functionality.
|
||||
*/
|
||||
function testPagePreview() {
|
||||
$body_key = 'body[0][value]';
|
||||
|
||||
// Fill in node creation form and preview node.
|
||||
$edit = array();
|
||||
$edit['title'] = $this->randomName(8);
|
||||
$edit['body'] = $this->randomName(16);
|
||||
$edit[$body_key] = $this->randomName(16);
|
||||
$this->drupalPost('node/add/page', $edit, t('Preview'));
|
||||
|
||||
// Check that the preview is displaying the title and body.
|
||||
$this->assertTitle(t('Preview | Drupal'), t('Page title is preview.'));
|
||||
$this->assertText($edit['title'], t('Title displayed.'));
|
||||
$this->assertText($edit['body'], t('Body displayed.'));
|
||||
$this->assertText($edit[$body_key], t('Body displayed.'));
|
||||
|
||||
// Check that the title and body fields are displayed with the correct values.
|
||||
$this->assertFieldByName('title', $edit['title'], t('Title field displayed.'));
|
||||
$this->assertFieldByName('body', '<!--break-->' . $edit['body'], t('Body field displayed.'));
|
||||
$this->assertFieldByName($body_key, $edit[$body_key], t('Body field displayed.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the node preview functionality, when using revisions.
|
||||
*/
|
||||
function testPagePreviewWithRevisions() {
|
||||
$body_key = 'body[0][value]';
|
||||
// Force revision on page content.
|
||||
variable_set('node_options_page', array('status', 'revision'));
|
||||
|
||||
// Fill in node creation form and preview node.
|
||||
$edit = array();
|
||||
$edit['title'] = $this->randomName(8);
|
||||
$edit['body'] = $this->randomName(16);
|
||||
$edit[$body_key] = $this->randomName(16);
|
||||
$edit['log'] = $this->randomName(32);
|
||||
$this->drupalPost('node/add/page', $edit, t('Preview'));
|
||||
|
||||
// Check that the preview is displaying the title and body.
|
||||
$this->assertTitle(t('Preview | Drupal'), t('Page title is preview.'));
|
||||
$this->assertText($edit['title'], t('Title displayed.'));
|
||||
$this->assertText($edit['body'], t('Body displayed.'));
|
||||
$this->assertText($edit[$body_key], t('Body displayed.'));
|
||||
|
||||
// Check that the title and body fields are displayed with the correct values.
|
||||
$this->assertFieldByName('title', $edit['title'], t('Title field displayed.'));
|
||||
$this->assertFieldByName('body', '<!--break-->' . $edit['body'], t('Body field displayed.'));
|
||||
$this->assertFieldByName($body_key, $edit[$body_key], t('Body field displayed.'));
|
||||
|
||||
// Check that the log field has the correct value.
|
||||
$this->assertFieldByName('log', $edit['log'], t('Log field displayed.'));
|
||||
|
@ -452,7 +311,7 @@ class PageCreationTestCase extends DrupalWebTestCase {
|
|||
// Create a node.
|
||||
$edit = array();
|
||||
$edit['title'] = $this->randomName(8);
|
||||
$edit['body'] = $this->randomName(16);
|
||||
$edit['body[0][value]'] = $this->randomName(16);
|
||||
$this->drupalPost('node/add/page', $edit, t('Save'));
|
||||
|
||||
// Check that the page has been created.
|
||||
|
@ -599,7 +458,7 @@ class NodePostSettingsTestCase extends DrupalWebTestCase {
|
|||
// Create a node.
|
||||
$edit = array();
|
||||
$edit['title'] = $this->randomName(8);
|
||||
$edit['body'] = $this->randomName(16);
|
||||
$edit['body[0][value]'] = $this->randomName(16);
|
||||
$this->drupalPost('node/add/page', $edit, t('Save'));
|
||||
|
||||
// Check that the post information is displayed.
|
||||
|
@ -620,7 +479,7 @@ class NodePostSettingsTestCase extends DrupalWebTestCase {
|
|||
// Create a node.
|
||||
$edit = array();
|
||||
$edit['title'] = $this->randomName(8);
|
||||
$edit['body'] = $this->randomName(16);
|
||||
$edit['body[0][value]'] = $this->randomName(16);
|
||||
$this->drupalPost('node/add/page', $edit, t('Save'));
|
||||
|
||||
// Check that the post information is displayed.
|
||||
|
@ -726,7 +585,7 @@ class NodeAccessRecordsAlterUnitTest extends DrupalWebTestCase {
|
|||
$this->assertEqual(count($records), 1, t('Returned the correct number of rows.'));
|
||||
$this->assertEqual($records[0]->realm, 'test_page_realm', t('Grant with page_realm acquired for node without alteration.'));
|
||||
$this->assertEqual($records[0]->gid, 1, t('Grant with gid = 1 acquired for node without alteration.'));
|
||||
|
||||
|
||||
// Create a promoted page node.
|
||||
$node3 = $this->drupalCreateNode(array('type' => 'page', 'promote' => 1));
|
||||
$this->assertTrue(node_load($node3->nid), t('Promoted page node created.'));
|
||||
|
@ -785,7 +644,7 @@ class NodeSaveTestCase extends DrupalWebTestCase {
|
|||
$title = $this->randomName(8);
|
||||
$node = array(
|
||||
'title' => $title,
|
||||
'body' => $this->randomName(32),
|
||||
'body' => array(array('value' => $this->randomName(32))),
|
||||
'uid' => $this->web_user->uid,
|
||||
'type' => 'article',
|
||||
'nid' => $test_nid,
|
||||
|
@ -845,7 +704,7 @@ class NodeAccessRebuildTestCase extends DrupalWebTestCase {
|
|||
'group' => t('Node'),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
|
@ -853,7 +712,7 @@ class NodeAccessRebuildTestCase extends DrupalWebTestCase {
|
|||
$this->drupalLogin($web_user);
|
||||
$this->web_user = $web_user;
|
||||
}
|
||||
|
||||
|
||||
function testNodeAccessRebuild() {
|
||||
$this->drupalGet('admin/reports/status');
|
||||
$this->clickLink(t('Rebuild permissions'));
|
||||
|
|
|
@ -212,7 +212,7 @@ class PathLanguageTestCase extends DrupalWebTestCase {
|
|||
$this->clickLink(t('add translation'));
|
||||
$edit = array();
|
||||
$edit['title'] = $this->randomName();
|
||||
$edit['body'] = $this->randomName();
|
||||
$edit['body[0][value]'] = $this->randomName();
|
||||
$edit['path'] = $this->randomName();
|
||||
$this->drupalPost(NULL, $edit, t('Save'));
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ class PHPTestCase extends DrupalWebTestCase {
|
|||
* @return stdObject Node object.
|
||||
*/
|
||||
function createNodeWithCode() {
|
||||
return $this->drupalCreateNode(array('body' => '<?php print "SimpleTest PHP was executed!"; ?>'));
|
||||
return $this->drupalCreateNode(array('body' => array('value' => '<?php print "SimpleTest PHP was executed!"; ?>')));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ class PHPFilterTestCase extends PHPTestCase {
|
|||
|
||||
// Change filter to PHP filter and see that PHP code is evaluated.
|
||||
$edit = array();
|
||||
$edit['body_format'] = 3;
|
||||
$edit['body[0][value_format]'] = 3;
|
||||
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
||||
$this->assertRaw(t('Page %title has been updated.', array('%title' => $node->title)), t('PHP code filter turned on.'));
|
||||
|
||||
|
|
|
@ -245,32 +245,23 @@ function hook_search_preprocess($text) {
|
|||
* @ingroup search
|
||||
*/
|
||||
function hook_update_index() {
|
||||
$last = variable_get('node_cron_last', 0);
|
||||
$limit = (int)variable_get('search_cron_limit', 100);
|
||||
|
||||
$result = db_query_range('SELECT n.nid, c.last_comment_timestamp FROM {node} n LEFT JOIN {node_comment_statistics} c ON n.nid = c.nid WHERE n.status = 1 AND n.moderate = 0 AND (n.created > %d OR n.changed > %d OR c.last_comment_timestamp > %d) ORDER BY GREATEST(n.created, n.changed, c.last_comment_timestamp) ASC', $last, $last, $last, 0, $limit);
|
||||
$result = db_query_range("SELECT n.nid FROM {node} n LEFT JOIN {search_dataset} d ON d.type = 'node' AND d.sid = n.nid WHERE d.sid IS NULL OR d.reindex <> 0 ORDER BY d.reindex ASC, n.nid ASC", 0, $limit);
|
||||
|
||||
while ($node = db_fetch_object($result)) {
|
||||
$last_comment = $node->last_comment_timestamp;
|
||||
$node = node_load(array('nid' => $node->nid));
|
||||
foreach ($result as $node) {
|
||||
$node = node_load($node->nid);
|
||||
|
||||
// We update this variable per node in case cron times out, or if the node
|
||||
// cannot be indexed (PHP nodes which call drupal_goto, for example).
|
||||
// In rare cases this can mean a node is only partially indexed, but the
|
||||
// chances of this happening are very small.
|
||||
variable_set('node_cron_last', max($last_comment, $node->changed, $node->created));
|
||||
// Save the changed time of the most recent indexed node, for the search
|
||||
// results half-life calculation.
|
||||
variable_set('node_cron_last', $node->changed);
|
||||
|
||||
// Get node output (filtered and with module-specific fields).
|
||||
if (node_hook($node, 'view')) {
|
||||
node_invoke($node, 'view', FALSE, FALSE);
|
||||
}
|
||||
else {
|
||||
$node = node_prepare($node, FALSE);
|
||||
}
|
||||
// Allow modules to change $node->body before viewing.
|
||||
module_invoke_all('node_view', $node, FALSE, FALSE);
|
||||
// Render the node.
|
||||
$node->build_mode = NODE_BUILD_SEARCH_INDEX;
|
||||
$node = node_build_content($node, FALSE, FALSE);
|
||||
$node->rendered = drupal_render($node->content);
|
||||
|
||||
$text = '<h1>' . drupal_specialchars($node->title) . '</h1>' . $node->body;
|
||||
$text = '<h1>' . check_plain($node->title) . '</h1>' . $node->rendered;
|
||||
|
||||
// Fetch extra data normally not visible
|
||||
$extra = module_invoke_all('node_update_index', $node);
|
||||
|
|
|
@ -312,7 +312,7 @@ class SearchRankingTestCase extends DrupalWebTestCase {
|
|||
|
||||
// Create nodes for testing.
|
||||
foreach ($node_ranks as $node_rank) {
|
||||
$settings = array('type' => 'page', 'title' => 'Drupal rocks', 'body' => "Drupal's search rocks");
|
||||
$settings = array('type' => 'page', 'title' => 'Drupal rocks', 'body' => array(array('value' => "Drupal's search rocks")));
|
||||
foreach (array(0, 1) as $num) {
|
||||
if ($num == 1) {
|
||||
switch ($node_rank) {
|
||||
|
@ -321,7 +321,7 @@ class SearchRankingTestCase extends DrupalWebTestCase {
|
|||
$settings[$node_rank] = 1;
|
||||
break;
|
||||
case 'relevance':
|
||||
$settings['body'] .= " really rocks";
|
||||
$settings['body'][0]['value'] .= " really rocks";
|
||||
break;
|
||||
case 'recent':
|
||||
$settings['created'] = REQUEST_TIME + 3600;
|
||||
|
|
|
@ -632,18 +632,17 @@ class DrupalWebTestCase extends DrupalTestCase {
|
|||
*
|
||||
* @param $settings
|
||||
* An associative array of settings to change from the defaults, keys are
|
||||
* node properties, for example 'body' => 'Hello, world!'.
|
||||
* node properties, for example 'title' => 'Hello, world!'.
|
||||
* @return
|
||||
* Created node object.
|
||||
*/
|
||||
protected function drupalCreateNode($settings = array()) {
|
||||
// Populate defaults array.
|
||||
$settings += array(
|
||||
'body' => $this->randomName(32),
|
||||
'body' => array(array()),
|
||||
'title' => $this->randomName(8),
|
||||
'comment' => 2,
|
||||
'changed' => REQUEST_TIME,
|
||||
'format' => FILTER_FORMAT_DEFAULT,
|
||||
'moderate' => 0,
|
||||
'promote' => 0,
|
||||
'revision' => 1,
|
||||
|
@ -660,11 +659,6 @@ class DrupalWebTestCase extends DrupalTestCase {
|
|||
$settings['date'] = format_date($settings['created'], 'custom', 'Y-m-d H:i:s O');
|
||||
}
|
||||
|
||||
// Add the default teaser.
|
||||
if (!isset($settings['teaser'])) {
|
||||
$settings['teaser'] = $settings['body'];
|
||||
}
|
||||
|
||||
// If the node's user uid is not specified manually, use the currently
|
||||
// logged in user if available, or else the user running the test.
|
||||
if (!isset($settings['uid'])) {
|
||||
|
@ -677,6 +671,13 @@ class DrupalWebTestCase extends DrupalTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
// Merge body field value and format separately.
|
||||
$body = array(
|
||||
'value' => $this->randomName(32),
|
||||
'format' => FILTER_FORMAT_DEFAULT
|
||||
);
|
||||
$settings['body'][0] += $body;
|
||||
|
||||
$node = (object) $settings;
|
||||
node_save($node);
|
||||
|
||||
|
@ -989,9 +990,18 @@ class DrupalWebTestCase extends DrupalTestCase {
|
|||
$this->preloadRegistry();
|
||||
|
||||
// Add the specified modules to the list of modules in the default profile.
|
||||
$args = func_get_args();
|
||||
$modules = array_unique(array_merge(drupal_get_profile_modules('default', 'en'), $args));
|
||||
drupal_install_modules($modules, TRUE);
|
||||
// Install the modules specified by the default profile.
|
||||
$core_modules = drupal_get_profile_modules('default', 'en');
|
||||
drupal_install_modules($core_modules, TRUE);
|
||||
|
||||
node_type_clear();
|
||||
|
||||
// Install additional modules one at a time in order to make sure that the
|
||||
// list of modules is updated between each module's installation.
|
||||
$modules = func_get_args();
|
||||
foreach ($modules as $module) {
|
||||
drupal_install_modules(array($module), TRUE);
|
||||
}
|
||||
|
||||
// Because the schema is static cached, we need to flush
|
||||
// it between each run. If we don't, then it will contain
|
||||
|
|
|
@ -261,9 +261,7 @@ class CascadingStylesheetsTestCase extends DrupalWebTestCase {
|
|||
// Create a node, using the PHP filter that tests drupal_add_css().
|
||||
$settings = array(
|
||||
'type' => 'page',
|
||||
'format' => 3, // PHP filter.
|
||||
'body_format' => 3,
|
||||
'body' => t('This tests the inline CSS!') . "<?php drupal_add_css('$css', 'inline'); ?>",
|
||||
'body' => array(array('value' => t('This tests the inline CSS!') . "<?php drupal_add_css('$css', 'inline'); ?>", 'format' => 3)), // PHP filter.
|
||||
'promote' => 1,
|
||||
);
|
||||
$node = $this->drupalCreateNode($settings);
|
||||
|
|
|
@ -22,19 +22,24 @@ class ModuleUnitTest extends DrupalWebTestCase {
|
|||
* The basic functionality of module_list().
|
||||
*/
|
||||
function testModuleList() {
|
||||
$base_module_list = drupal_get_profile_modules('default', 'en');
|
||||
// Key the list by module name.
|
||||
$base_module_list = array_combine($base_module_list, $base_module_list);
|
||||
// All default profile modules have a weight equal to 0, the default sort
|
||||
// order is thus simply alphabetical.
|
||||
ksort($base_module_list);
|
||||
$this->assertModuleList($base_module_list, t('Default profile'));
|
||||
// Build a list of modules filenames.
|
||||
$base_module_list = array();
|
||||
foreach (drupal_get_profile_modules('default', 'en') as $module) {
|
||||
$base_module_list[$module] = drupal_get_path('module', $module);
|
||||
}
|
||||
asort($base_module_list);
|
||||
// Build a list of module names based on that order. Since all default
|
||||
// profile modules have a weight equal to 0, the default sort order is
|
||||
// simply alphabetical.
|
||||
$module_list = array_keys($base_module_list);
|
||||
$this->assertModuleList($module_list, t('Default profile'));
|
||||
|
||||
// Try to install a new module.
|
||||
drupal_install_modules(array('path'));
|
||||
$base_module_list['path'] = 'path';
|
||||
ksort($base_module_list);
|
||||
$this->assertModuleList($base_module_list, t('After adding a module'));
|
||||
$base_module_list['path'] = drupal_get_path('module', 'path');
|
||||
asort($base_module_list);
|
||||
$module_list = array_keys($base_module_list);
|
||||
$this->assertModuleList($module_list, t('After adding a module'));
|
||||
|
||||
// Try to mess with the module weights.
|
||||
db_update('system')
|
||||
|
@ -46,8 +51,9 @@ class ModuleUnitTest extends DrupalWebTestCase {
|
|||
module_list(TRUE);
|
||||
// Move path at the end of the array.
|
||||
unset($base_module_list['path']);
|
||||
$base_module_list['path'] = 'path';
|
||||
$this->assertModuleList($base_module_list, t('After changing weights'));
|
||||
$base_module_list['path'] = drupal_get_path('module', 'path');
|
||||
$module_list = array_keys($base_module_list);
|
||||
$this->assertModuleList($module_list, t('After changing weights'));
|
||||
|
||||
// Test the fixed list feature.
|
||||
$fixed_list = array(
|
||||
|
@ -60,7 +66,7 @@ class ModuleUnitTest extends DrupalWebTestCase {
|
|||
|
||||
// Reset the module list.
|
||||
module_list(TRUE);
|
||||
$this->assertModuleList($base_module_list, t('After reset'));
|
||||
$this->assertModuleList($module_list, t('After reset'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -70,6 +76,7 @@ class ModuleUnitTest extends DrupalWebTestCase {
|
|||
* The expected values, sorted by weight and file name.
|
||||
*/
|
||||
protected function assertModuleList(Array $expected_values, $condition) {
|
||||
$expected_values = array_combine($expected_values, $expected_values);
|
||||
$this->assertIdentical($expected_values, module_list(), t('@condition: module_list() returns correct results', array('@condition' => $condition)));
|
||||
ksort($expected_values);
|
||||
$this->assertIdentical($expected_values, module_list(FALSE, TRUE), t('@condition: module_list() returns correctly sorted results', array('@condition' => $condition)));
|
||||
|
|
|
@ -3548,6 +3548,17 @@ function system_update_7026() {
|
|||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable field type modules.
|
||||
*/
|
||||
function system_update_7027() {
|
||||
$ret = array();
|
||||
$module_list = array('text', 'number', 'list', 'options');
|
||||
drupal_install_modules($module_list);
|
||||
module_enable($module_list);
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @} End of "defgroup updates-6.x-to-7.x"
|
||||
* The next series of updates should start at 8000.
|
||||
|
|
|
@ -518,7 +518,7 @@ class AccessDeniedTestCase extends DrupalWebTestCase {
|
|||
|
||||
$edit = array(
|
||||
'title' => $this->randomName(10),
|
||||
'body' => $this->randomName(100)
|
||||
'body' => array(array('value' => $this->randomName(100))),
|
||||
);
|
||||
$node = $this->drupalCreateNode($edit);
|
||||
|
||||
|
@ -579,7 +579,7 @@ class PageNotFoundTestCase extends DrupalWebTestCase {
|
|||
|
||||
$edit = array(
|
||||
'title' => $this->randomName(10),
|
||||
'body' => $this->randomName(100)
|
||||
'body' => array(array('value' => $this->randomName(100))),
|
||||
);
|
||||
$node = $this->drupalCreateNode($edit);
|
||||
|
||||
|
@ -705,7 +705,7 @@ class PageTitleFiltering extends DrupalWebTestCase {
|
|||
// Generate node content.
|
||||
$edit = array(
|
||||
'title' => '!SimpleTest! ' . $title . $this->randomName(20),
|
||||
'body' => '!SimpleTest! test body' . $this->randomName(200),
|
||||
'body[0][value]' => '!SimpleTest! test body' . $this->randomName(200),
|
||||
);
|
||||
// Create the node with HTML in the title.
|
||||
$this->drupalPost('node/add/page', $edit, t('Save'));
|
||||
|
|
|
@ -474,7 +474,7 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase {
|
|||
// Post an article.
|
||||
$edit = array();
|
||||
$edit['title'] = $this->randomName();
|
||||
$edit['body'] = $this->randomName();
|
||||
$edit['body[0][value]'] = $this->randomName();
|
||||
$edit['taxonomy[' . $this->vocabulary->vid . ']'] = $term1->tid;
|
||||
$this->drupalPost('node/add/article', $edit, t('Save'));
|
||||
|
||||
|
@ -516,7 +516,7 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase {
|
|||
// Insert the terms in a comma separated list. Vocabulary 1 is a
|
||||
// free-tagging field created by the default profile.
|
||||
$edit['taxonomy[tags][' . $this->vocabulary->vid . ']'] = implode(', ', $terms);
|
||||
$edit['body'] = $this->randomName();
|
||||
$edit['body[0][value]'] = $this->randomName();
|
||||
$this->drupalPost('node/add/article', $edit, t('Save'));
|
||||
$this->assertRaw(t('@type %title has been created.', array('@type' => t('Article'), '%title' => $edit['title'])), t('The node was created successfully'));
|
||||
foreach ($terms as $term) {
|
||||
|
|
|
@ -213,7 +213,6 @@ function translation_node_prepare($node) {
|
|||
$node->language = $language;
|
||||
$node->translation_source = $source_node;
|
||||
$node->title = $node->translation_source->title;
|
||||
$node->body = $node->translation_source->body;
|
||||
// Let every module add custom translated fields.
|
||||
module_invoke_all('node_prepare_translation', $node);
|
||||
}
|
||||
|
|
|
@ -60,14 +60,14 @@ class TranslationTestCase extends DrupalWebTestCase {
|
|||
// to return to the page then resubmitting the form without a refresh.
|
||||
$edit = array();
|
||||
$edit['title'] = $this->randomName();
|
||||
$edit['body'] = $this->randomName();
|
||||
$edit['body[0][value]'] = $this->randomName();
|
||||
$this->drupalPost('node/add/page', $edit, t('Save'), array('query' => array('translation' => $node->nid, 'language' => 'es')));
|
||||
$duplicate = $this->drupalGetNodeByTitle($edit['title']);
|
||||
$this->assertEqual($duplicate->tnid, 0, t('The node does not have a tnid.'));
|
||||
|
||||
// Update original and mark translation as outdated.
|
||||
$edit = array();
|
||||
$edit['body'] = $this->randomName();
|
||||
$edit['body[0][value]'] = $this->randomName();
|
||||
$edit['translation[retranslate]'] = TRUE;
|
||||
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
||||
$this->assertRaw(t('Page %title has been updated.', array('%title' => $node_title)), t('Original node updated.'));
|
||||
|
@ -78,7 +78,7 @@ class TranslationTestCase extends DrupalWebTestCase {
|
|||
|
||||
// Update translation and mark as updated.
|
||||
$edit = array();
|
||||
$edit['body'] = $this->randomName();
|
||||
$edit['body[0][value]'] = $this->randomName();
|
||||
$edit['translation[status]'] = FALSE;
|
||||
$this->drupalPost('node/' . $node_translation->nid . '/edit', $edit, t('Save'));
|
||||
$this->assertRaw(t('Page %title has been updated.', array('%title' => $node_translation_title)), t('Translated node updated.'));
|
||||
|
@ -128,7 +128,7 @@ class TranslationTestCase extends DrupalWebTestCase {
|
|||
function createPage($title, $body, $language) {
|
||||
$edit = array();
|
||||
$edit['title'] = $title;
|
||||
$edit['body'] = $body;
|
||||
$edit['body[0][value]'] = $body;
|
||||
$edit['language'] = $language;
|
||||
$this->drupalPost('node/add/page', $edit, t('Save'));
|
||||
$this->assertRaw(t('Page %title has been created.', array('%title' => $edit['title'])), t('Page created.'));
|
||||
|
@ -153,7 +153,7 @@ class TranslationTestCase extends DrupalWebTestCase {
|
|||
|
||||
$edit = array();
|
||||
$edit['title'] = $title;
|
||||
$edit['body'] = $body;
|
||||
$edit['body[0][value]'] = $body;
|
||||
$this->drupalPost(NULL, $edit, t('Save'));
|
||||
$this->assertRaw(t('Page %title has been created.', array('%title' => $edit['title'])), t('Translation created.'));
|
||||
|
||||
|
|
|
@ -37,8 +37,8 @@ class TriggerContentTestCase extends DrupalWebTestCase {
|
|||
$web_user = $this->drupalCreateUser(array('create page content', 'access content', 'administer nodes'));
|
||||
$this->drupalLogin($web_user);
|
||||
$edit = array();
|
||||
$edit['title'] = '!SimpleTest test node! ' . $this->randomName(10);
|
||||
$edit['body'] = '!SimpleTest test body! ' . $this->randomName(32) . ' ' . $this->randomName(32);
|
||||
$edit['title'] = '!SimpleTest test node! ' . $this->randomName(10);
|
||||
$edit['body[0][value]'] = '!SimpleTest test body! ' . $this->randomName(32) . ' ' . $this->randomName(32);
|
||||
$edit[$info['property']] = !$info['expected'];
|
||||
$this->drupalPost('node/add/page', $edit, t('Save'));
|
||||
// Make sure the text we want appears.
|
||||
|
|
Loading…
Reference in New Issue