| Drupal | PHP Cross Reference | Content Management Systems |
1 <?php 2 3 /** 4 * @file 5 * Tests for text.module. 6 */ 7 8 class TextFieldTestCase extends DrupalWebTestCase { 9 protected $instance; 10 protected $admin_user; 11 protected $web_user; 12 13 public static function getInfo() { 14 return array( 15 'name' => 'Text field', 16 'description' => "Test the creation of text fields.", 17 'group' => 'Field types' 18 ); 19 } 20 21 function setUp() { 22 parent::setUp('field_test'); 23 24 $this->admin_user = $this->drupalCreateUser(array('administer filters')); 25 $this->web_user = $this->drupalCreateUser(array('access field_test content', 'administer field_test content')); 26 $this->drupalLogin($this->web_user); 27 } 28 29 // Test fields. 30 31 /** 32 * Test text field validation. 33 */ 34 function testTextFieldValidation() { 35 // Create a field with settings to validate. 36 $max_length = 3; 37 $this->field = array( 38 'field_name' => drupal_strtolower($this->randomName()), 39 'type' => 'text', 40 'settings' => array( 41 'max_length' => $max_length, 42 ) 43 ); 44 field_create_field($this->field); 45 $this->instance = array( 46 'field_name' => $this->field['field_name'], 47 'entity_type' => 'test_entity', 48 'bundle' => 'test_bundle', 49 'widget' => array( 50 'type' => 'text_textfield', 51 ), 52 'display' => array( 53 'default' => array( 54 'type' => 'text_default', 55 ), 56 ), 57 ); 58 field_create_instance($this->instance); 59 // Test valid and invalid values with field_attach_validate(). 60 $entity = field_test_create_stub_entity(); 61 $langcode = LANGUAGE_NONE; 62 for ($i = 0; $i <= $max_length + 2; $i++) { 63 $entity->{$this->field['field_name']}[$langcode][0]['value'] = str_repeat('x', $i); 64 try { 65 field_attach_validate('test_entity', $entity); 66 $this->assertTrue($i <= $max_length, "Length $i does not cause validation error when max_length is $max_length"); 67 } 68 catch (FieldValidationException $e) { 69 $this->assertTrue($i > $max_length, "Length $i causes validation error when max_length is $max_length"); 70 } 71 } 72 } 73 74 /** 75 * Test widgets. 76 */ 77 function testTextfieldWidgets() { 78 $this->_testTextfieldWidgets('text', 'text_textfield'); 79 $this->_testTextfieldWidgets('text_long', 'text_textarea'); 80 } 81 82 /** 83 * Helper function for testTextfieldWidgets(). 84 */ 85 function _testTextfieldWidgets($field_type, $widget_type) { 86 // Setup a field and instance 87 $entity_type = 'test_entity'; 88 $this->field_name = drupal_strtolower($this->randomName()); 89 $this->field = array('field_name' => $this->field_name, 'type' => $field_type); 90 field_create_field($this->field); 91 $this->instance = array( 92 'field_name' => $this->field_name, 93 'entity_type' => 'test_entity', 94 'bundle' => 'test_bundle', 95 'label' => $this->randomName() . '_label', 96 'settings' => array( 97 'text_processing' => TRUE, 98 ), 99 'widget' => array( 100 'type' => $widget_type, 101 ), 102 'display' => array( 103 'full' => array( 104 'type' => 'text_default', 105 ), 106 ), 107 ); 108 field_create_instance($this->instance); 109 $langcode = LANGUAGE_NONE; 110 111 // Display creation form. 112 $this->drupalGet('test-entity/add/test-bundle'); 113 $this->assertFieldByName("{$this->field_name}[$langcode][0][value]", '', t('Widget is displayed')); 114 $this->assertNoFieldByName("{$this->field_name}[$langcode][0][format]", '1', t('Format selector is not displayed')); 115 116 // Submit with some value. 117 $value = $this->randomName(); 118 $edit = array( 119 "{$this->field_name}[$langcode][0][value]" => $value, 120 ); 121 $this->drupalPost(NULL, $edit, t('Save')); 122 preg_match('|test-entity/manage/(\d+)/edit|', $this->url, $match); 123 $id = $match[1]; 124 $this->assertRaw(t('test_entity @id has been created.', array('@id' => $id)), t('Entity was created')); 125 126 // Display the entity. 127 $entity = field_test_entity_test_load($id); 128 $entity->content = field_attach_view($entity_type, $entity, 'full'); 129 $this->content = drupal_render($entity->content); 130 $this->assertText($value, 'Filtered tags are not displayed'); 131 } 132 133 /** 134 * Test widgets + 'formatted_text' setting. 135 */ 136 function testTextfieldWidgetsFormatted() { 137 $this->_testTextfieldWidgetsFormatted('text', 'text_textfield'); 138 $this->_testTextfieldWidgetsFormatted('text_long', 'text_textarea'); 139 } 140 141 /** 142 * Helper function for testTextfieldWidgetsFormatted(). 143 */ 144 function _testTextfieldWidgetsFormatted($field_type, $widget_type) { 145 // Setup a field and instance 146 $entity_type = 'test_entity'; 147 $this->field_name = drupal_strtolower($this->randomName()); 148 $this->field = array('field_name' => $this->field_name, 'type' => $field_type); 149 field_create_field($this->field); 150 $this->instance = array( 151 'field_name' => $this->field_name, 152 'entity_type' => 'test_entity', 153 'bundle' => 'test_bundle', 154 'label' => $this->randomName() . '_label', 155 'settings' => array( 156 'text_processing' => TRUE, 157 ), 158 'widget' => array( 159 'type' => $widget_type, 160 ), 161 'display' => array( 162 'full' => array( 163 'type' => 'text_default', 164 ), 165 ), 166 ); 167 field_create_instance($this->instance); 168 $langcode = LANGUAGE_NONE; 169 170 // Disable all text formats besides the plain text fallback format. 171 $this->drupalLogin($this->admin_user); 172 foreach (filter_formats() as $format) { 173 if ($format->format != filter_fallback_format()) { 174 $this->drupalPost('admin/config/content/formats/' . $format->format . '/disable', array(), t('Disable')); 175 } 176 } 177 $this->drupalLogin($this->web_user); 178 179 // Display the creation form. Since the user only has access to one format, 180 // no format selector will be displayed. 181 $this->drupalGet('test-entity/add/test-bundle'); 182 $this->assertFieldByName("{$this->field_name}[$langcode][0][value]", '', t('Widget is displayed')); 183 $this->assertNoFieldByName("{$this->field_name}[$langcode][0][format]", '', t('Format selector is not displayed')); 184 185 // Submit with data that should be filtered. 186 $value = '<em>' . $this->randomName() . '</em>'; 187 $edit = array( 188 "{$this->field_name}[$langcode][0][value]" => $value, 189 ); 190 $this->drupalPost(NULL, $edit, t('Save')); 191 preg_match('|test-entity/manage/(\d+)/edit|', $this->url, $match); 192 $id = $match[1]; 193 $this->assertRaw(t('test_entity @id has been created.', array('@id' => $id)), t('Entity was created')); 194 195 // Display the entity. 196 $entity = field_test_entity_test_load($id); 197 $entity->content = field_attach_view($entity_type, $entity, 'full'); 198 $this->content = drupal_render($entity->content); 199 $this->assertNoRaw($value, t('HTML tags are not displayed.')); 200 $this->assertRaw(check_plain($value), t('Escaped HTML is displayed correctly.')); 201 202 // Create a new text format that does not escape HTML, and grant the user 203 // access to it. 204 $this->drupalLogin($this->admin_user); 205 $edit = array( 206 'format' => drupal_strtolower($this->randomName()), 207 'name' => $this->randomName(), 208 ); 209 $this->drupalPost('admin/config/content/formats/add', $edit, t('Save configuration')); 210 filter_formats_reset(); 211 $this->checkPermissions(array(), TRUE); 212 $format = filter_format_load($edit['format']); 213 $format_id = $format->format; 214 $permission = filter_permission_name($format); 215 $rid = max(array_keys($this->web_user->roles)); 216 user_role_grant_permissions($rid, array($permission)); 217 $this->drupalLogin($this->web_user); 218 219 // Display edition form. 220 // We should now have a 'text format' selector. 221 $this->drupalGet('test-entity/manage/' . $id . '/edit'); 222 $this->assertFieldByName("{$this->field_name}[$langcode][0][value]", NULL, t('Widget is displayed')); 223 $this->assertFieldByName("{$this->field_name}[$langcode][0][format]", NULL, t('Format selector is displayed')); 224 225 // Edit and change the text format to the new one that was created. 226 $edit = array( 227 "{$this->field_name}[$langcode][0][format]" => $format_id, 228 ); 229 $this->drupalPost(NULL, $edit, t('Save')); 230 $this->assertRaw(t('test_entity @id has been updated.', array('@id' => $id)), t('Entity was updated')); 231 232 // Display the entity. 233 $entity = field_test_entity_test_load($id); 234 $entity->content = field_attach_view($entity_type, $entity, 'full'); 235 $this->content = drupal_render($entity->content); 236 $this->assertRaw($value, t('Value is displayed unfiltered')); 237 } 238 } 239 240 class TextSummaryTestCase extends DrupalWebTestCase { 241 public static function getInfo() { 242 return array( 243 'name' => 'Text summary', 244 'description' => 'Test text_summary() with different strings and lengths.', 245 'group' => 'Field types', 246 ); 247 } 248 249 function setUp() { 250 parent::setUp(); 251 $this->article_creator = $this->drupalCreateUser(array('create article content', 'edit own article content')); 252 } 253 254 /** 255 * Tests an edge case where the first sentence is a question and 256 * subsequent sentences are not. This edge case is documented at 257 * http://drupal.org/node/180425. 258 */ 259 function testFirstSentenceQuestion() { 260 $text = 'A question? A sentence. Another sentence.'; 261 $expected = 'A question? A sentence.'; 262 $this->callTextSummary($text, $expected, NULL, 30); 263 } 264 265 /** 266 * Test summary with long example. 267 */ 268 function testLongSentence() { 269 $text = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ' . // 125 270 'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. ' . // 108 271 'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. ' . // 103 272 'Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'; // 110 273 $expected = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ' . 274 'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. ' . 275 'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.'; 276 // First three sentences add up to: 336, so add one for space and then 3 to get half-way into next word. 277 $this->callTextSummary($text, $expected, NULL, 340); 278 } 279 280 /** 281 * Test various summary length edge cases. 282 */ 283 function testLength() { 284 // This string tests a number of edge cases. 285 $text = "<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>"; 286 287 // The summaries we expect text_summary() to return when $size is the index 288 // of each array item. 289 // Using no text format: 290 $expected = array( 291 "<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>", 292 "<", 293 "<p", 294 "<p>", 295 "<p>\n", 296 "<p>\nH", 297 "<p>\nHi", 298 "<p>\nHi\n", 299 "<p>\nHi\n<", 300 "<p>\nHi\n</", 301 "<p>\nHi\n</p", 302 "<p>\nHi\n</p>", 303 "<p>\nHi\n</p>", 304 "<p>\nHi\n</p>", 305 "<p>\nHi\n</p>", 306 "<p>\nHi\n</p>", 307 "<p>\nHi\n</p>", 308 "<p>\nHi\n</p>", 309 "<p>\nHi\n</p>", 310 "<p>\nHi\n</p>", 311 "<p>\nHi\n</p>", 312 "<p>\nHi\n</p>", 313 "<p>\nHi\n</p>", 314 "<p>\nHi\n</p>", 315 "<p>\nHi\n</p>", 316 "<p>\nHi\n</p>", 317 "<p>\nHi\n</p>", 318 "<p>\nHi\n</p>", 319 "<p>\nHi\n</p>", 320 "<p>\nHi\n</p>", 321 "<p>\nHi\n</p>", 322 "<p>\nHi\n</p>", 323 "<p>\nHi\n</p>", 324 "<p>\nHi\n</p>", 325 "<p>\nHi\n</p>", 326 "<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>", 327 "<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>", 328 "<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>", 329 ); 330 331 // And using a text format WITH the line-break and htmlcorrector filters. 332 $expected_lb = array( 333 "<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>", 334 "", 335 "<p></p>", 336 "<p></p>", 337 "<p></p>", 338 "<p></p>", 339 "<p></p>", 340 "<p>\nHi</p>", 341 "<p>\nHi</p>", 342 "<p>\nHi</p>", 343 "<p>\nHi</p>", 344 "<p>\nHi\n</p>", 345 "<p>\nHi\n</p>", 346 "<p>\nHi\n</p>", 347 "<p>\nHi\n</p>", 348 "<p>\nHi\n</p>", 349 "<p>\nHi\n</p>", 350 "<p>\nHi\n</p>", 351 "<p>\nHi\n</p>", 352 "<p>\nHi\n</p>", 353 "<p>\nHi\n</p>", 354 "<p>\nHi\n</p>", 355 "<p>\nHi\n</p>", 356 "<p>\nHi\n</p>", 357 "<p>\nHi\n</p>", 358 "<p>\nHi\n</p>", 359 "<p>\nHi\n</p>", 360 "<p>\nHi\n</p>", 361 "<p>\nHi\n</p>", 362 "<p>\nHi\n</p>", 363 "<p>\nHi\n</p>", 364 "<p>\nHi\n</p>", 365 "<p>\nHi\n</p>", 366 "<p>\nHi\n</p>", 367 "<p>\nHi\n</p>", 368 "<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>", 369 "<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>", 370 "<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>", 371 ); 372 373 // Test text_summary() for different sizes. 374 for ($i = 0; $i <= 37; $i++) { 375 $this->callTextSummary($text, $expected[$i], NULL, $i); 376 $this->callTextSummary($text, $expected_lb[$i], 'plain_text', $i); 377 $this->callTextSummary($text, $expected_lb[$i], 'filtered_html', $i); 378 } 379 } 380 381 /** 382 * Calls text_summary() and asserts that the expected teaser is returned. 383 */ 384 function callTextSummary($text, $expected, $format = NULL, $size = NULL) { 385 $summary = text_summary($text, $format, $size); 386 $this->assertIdentical($summary, $expected, t('Generated summary "@summary" matches expected "@expected".', array('@summary' => $summary, '@expected' => $expected))); 387 } 388 389 /** 390 * Test sending only summary. 391 */ 392 function testOnlyTextSummary() { 393 // Login as article creator. 394 $this->drupalLogin($this->article_creator); 395 // Create article with summary but empty body. 396 $summary = $this->randomName(); 397 $edit = array( 398 "title" => $this->randomName(), 399 "body[und][0][summary]" => $summary, 400 ); 401 $this->drupalPost('node/add/article', $edit, t('Save')); 402 $node = $this->drupalGetNodeByTitle($edit['title']); 403 404 $this->assertIdentical($node->body['und'][0]['summary'], $summary, t('Article with with summary and no body has been submitted.')); 405 } 406 } 407 408 class TextTranslationTestCase extends DrupalWebTestCase { 409 public static function getInfo() { 410 return array( 411 'name' => 'Text translation', 412 'description' => 'Check if the text field is correctly prepared for translation.', 413 'group' => 'Field types', 414 ); 415 } 416 417 function setUp() { 418 parent::setUp('locale', 'translation'); 419 420 $full_html_format = filter_format_load('full_html'); 421 $this->format = $full_html_format->format; 422 $this->admin = $this->drupalCreateUser(array( 423 'administer languages', 424 'administer content types', 425 'access administration pages', 426 'bypass node access', 427 filter_permission_name($full_html_format), 428 )); 429 $this->translator = $this->drupalCreateUser(array('create article content', 'edit own article content', 'translate content')); 430 431 // Enable an additional language. 432 $this->drupalLogin($this->admin); 433 $edit = array('langcode' => 'fr'); 434 $this->drupalPost('admin/config/regional/language/add', $edit, t('Add language')); 435 436 // Set "Article" content type to use multilingual support with translation. 437 $edit = array('language_content_type' => 2); 438 $this->drupalPost('admin/structure/types/manage/article', $edit, t('Save content type')); 439 $this->assertRaw(t('The content type %type has been updated.', array('%type' => 'Article')), t('Article content type has been updated.')); 440 } 441 442 /** 443 * Test that a plaintext textfield widget is correctly populated. 444 */ 445 function testTextField() { 446 // Disable text processing for body. 447 $edit = array('instance[settings][text_processing]' => 0); 448 $this->drupalPost('admin/structure/types/manage/article/fields/body', $edit, t('Save settings')); 449 450 // Login as translator. 451 $this->drupalLogin($this->translator); 452 453 // Create content. 454 $langcode = LANGUAGE_NONE; 455 $body = $this->randomName(); 456 $edit = array( 457 "title" => $this->randomName(), 458 "language" => 'en', 459 "body[$langcode][0][value]" => $body, 460 ); 461 462 // Translate the article in french. 463 $this->drupalPost('node/add/article', $edit, t('Save')); 464 $node = $this->drupalGetNodeByTitle($edit['title']); 465 $this->drupalGet("node/$node->nid/translate"); 466 $this->clickLink(t('add translation')); 467 $this->assertFieldByXPath("//textarea[@name='body[$langcode][0][value]']", $body, t('The textfield widget is populated.')); 468 } 469 470 /** 471 * Check that user that does not have access the field format cannot see the 472 * source value when creating a translation. 473 */ 474 function testTextFieldFormatted() { 475 // Make node body multiple. 476 $edit = array('field[cardinality]' => -1); 477 $this->drupalPost('admin/structure/types/manage/article/fields/body', $edit, t('Save settings')); 478 $this->drupalGet('node/add/article'); 479 $this->assertFieldByXPath("//input[@name='body_add_more']", t('Add another item'), t('Body field cardinality set to multiple.')); 480 481 $body = array( 482 $this->randomName(), 483 $this->randomName(), 484 ); 485 486 // Create an article with the first body input format set to "Full HTML". 487 $title = $this->randomName(); 488 $edit = array( 489 'title' => $title, 490 'language' => 'en', 491 ); 492 $this->drupalPost('node/add/article', $edit, t('Save')); 493 494 // Populate the body field: the first item gets the "Full HTML" input 495 // format, the second one "Filtered HTML". 496 $formats = array('full_html', 'filtered_html'); 497 $langcode = LANGUAGE_NONE; 498 foreach ($body as $delta => $value) { 499 $edit = array( 500 "body[$langcode][$delta][value]" => $value, 501 "body[$langcode][$delta][format]" => array_shift($formats), 502 ); 503 $this->drupalPost('node/1/edit', $edit, t('Save')); 504 $this->assertText($body[$delta], t('The body field with delta @delta has been saved.', array('@delta' => $delta))); 505 } 506 507 // Login as translator. 508 $this->drupalLogin($this->translator); 509 510 // Translate the article in french. 511 $node = $this->drupalGetNodeByTitle($title); 512 $this->drupalGet("node/$node->nid/translate"); 513 $this->clickLink(t('add translation')); 514 $this->assertNoText($body[0], t('The body field with delta @delta is hidden.', array('@delta' => 0))); 515 $this->assertText($body[1], t('The body field with delta @delta is shown.', array('@delta' => 1))); 516 } 517 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
title