'Pathologic path filtering', 'description' => 'Test Pathologic’s path translation and conversion.', 'group' => 'Filter', ); } public function setUp() { parent::setUp('pathologic'); } public function testPathologic() { // Start by testing our function to build protocol-relative URLs. $this->assertEqual( _pathologic_url_to_protocol_relative('http://example.com/foo/bar'), '//example.com/foo/bar', t('Protocol-relative URL creation with http:// URL') ); $this->assertEqual( _pathologic_url_to_protocol_relative('https://example.org/baz'), '//example.org/baz', t('Protocol-relative URL creation with https:// URL') ); // Build some paths to check against. $test_paths = array( 'foo' => array( 'path' => 'foo', 'opts' => array(), ), 'foo/bar' => array( 'path' => 'foo/bar', 'opts' => array(), ), 'foo/bar?baz' => array( 'path' => 'foo/bar', 'opts' => array('query' => array('baz' => NULL)), ), 'foo/bar?baz=qux' => array( 'path' => 'foo/bar', 'opts' => array('query' => array('baz' => 'qux')), ), 'foo/bar#baz' => array( 'path' => 'foo/bar', 'opts' => array('fragment' => 'baz'), ), 'foo/bar?baz=qux&quux=quuux#quuuux' => array( 'path' => 'foo/bar', 'opts' => array( 'query' => array('baz' => 'qux', 'quux' => 'quuux'), 'fragment' => 'quuuux', ), ), 'foo%20bar?baz=qux%26quux' => array( 'path' => 'foo bar', 'opts' => array( 'query' => array('baz' => 'qux&quux'), ), ), '/' => array( 'path' => '', 'opts' => array(), ), ); // Run tests with clean URLs both enabled and disabled. foreach (array(TRUE, FALSE) as $clean_url) { variable_set('clean_url', $clean_url); // Run tests with absoulte filtering enabled and disabled. foreach (array('full', 'proto-rel', 'path') as $protocol_style) { $format_id = _pathologic_build_format(array('protocol_style' => $protocol_style, 'settings_source' => 'local')); $paths = array(); foreach ($test_paths as $path => $args) { $args['opts']['absolute'] = $protocol_style !== 'path'; $paths[$path] = _pathologic_content_url($args['path'], $args['opts']); if ($protocol_style === 'proto-rel') { $paths[$path] = _pathologic_url_to_protocol_relative($paths[$path]); } } $t10ns = array( '!clean' => $clean_url ? t('Yes') : t('No'), '!ps' => $protocol_style, ); $this->assertEqual( check_markup('', $format_id), '', t('Simple paths. Clean URLs: !clean; protocol style: !ps.', $t10ns) ); $this->assertEqual( check_markup('
', $format_id), '', t('Paths with query string. Clean URLs: !clean; protocol style: !ps.', $t10ns) ); $this->assertEqual( check_markup('', $format_id), '', t('Path with fragment. Clean URLs: !clean; protocol style: !ps.', $t10ns) ); $this->assertEqual( check_markup('', $format_id), '', t('Fragment-only href. Clean URLs: !clean; protocol style: !ps.', $t10ns) ); // @see https://drupal.org/node/2208223 $this->assertEqual( check_markup('', $format_id), '', t('Hash-only href. Clean URLs: !clean; protocol style: !ps.', $t10ns) ); $this->assertEqual( check_markup('', $format_id), '', t('Path with query string and fragment. Clean URLs: !clean; protocol style: !ps.', $t10ns) ); $this->assertEqual( check_markup('', $format_id), '', t('Path with URL encoded parts') ); $this->assertEqual( check_markup('', $format_id), '', t('Path with just slash. Clean URLs: !clean; protocol style: !ps', $t10ns) ); } } global $base_path; $this->assertEqual( check_markup('bar', $format_id), 'bar', t('Paths beginning with $base_path (like WYSIWYG editors like to make)') ); global $base_url; $this->assertEqual( check_markup('bar', $format_id), 'bar', t('Paths beginning with $base_url') ); // @see http://drupal.org/node/1617944 $this->assertEqual( check_markup('bar', $format_id), 'bar', t('Off-site schemeless URLs (//example.com/foo) ignored') ); // Test internal: and all base paths. $format_id = _pathologic_build_format(array( 'protocol_style' => 'full', 'local_paths' => "http://example.com/qux\nhttp://example.org\n/bananas", 'settings_source' => 'local', )); // @see https://drupal.org/node/2030789 $this->assertEqual( check_markup('bar', $format_id), 'bar', t('On-site schemeless URLs processed') ); $this->assertEqual( check_markup('', $format_id), '', t('Path Filter compatibility (internal:)') ); $this->assertEqual( check_markup('', $format_id), '', t('Path Filter compatibility (files:)') ); $this->assertEqual( check_markup('', $format_id), '', t('"All base paths for this site" functionality') ); $this->assertEqual( check_markup('bar', $format_id), 'bar', t('URLs with likely protocols are ignored') ); // Test hook_pathologic_alter() implementation. $this->assertEqual( check_markup('', $format_id), '', t('hook_pathologic_alter(): Alter $url_params') ); $this->assertEqual( check_markup('', $format_id), '', t('hook_pathologic_alter(): Passthrough with use_original option') ); // Test paths to existing files when clean URLs are disabled. // @see http://drupal.org/node/1672430 variable_set('clean_url', FALSE); $filtered_tag = check_markup('', $format_id); $this->assertTrue( strpos($filtered_tag, 'q=') === FALSE, t("Paths to files don't have ?q= when clean URLs are off") ); $format_id = _pathologic_build_format(array( 'protocol_style' => 'rel', 'settings_source' => 'global', )); variable_set('pathologic_protocol_style', 'proto-rel'); variable_set('pathologic_local_paths', 'http://example.com/'); $this->assertEqual( check_markup('', $format_id), '', t('Use global settings when so configured on the format') ); } } /** * Wrapper around url() which does HTML entity decoding and encoding. * * Since Pathologic works with paths in content, it needs to decode paths which * have been HTML-encoded, and re-encode them when done. This is a wrapper * around url() which does the same thing so that we can expect the results * from it and from Pathologic to still match in our tests. * * @see url() * @see http://drupal.org/node/1672932 * @see http://www.w3.org/TR/xhtml1/guidelines.html#C_12 */ function _pathologic_content_url($path, $options) { // If we should pretend this is a path to a file, temporarily enable clean // URLs if necessary. // @see _pathologic_replace() // @see http://drupal.org/node/1672430 if (!empty($options['is_file'])) { $options['orig_clean_url'] = !empty($GLOBALS['conf']['clean_url']); if (!$options['orig_clean_url']) { $GLOBALS['conf']['clean_url'] = TRUE; } } $url = check_plain(url(htmlspecialchars_decode($path), $options)); if (!empty($options['is_file']) && !$options['orig_clean_url']) { $GLOBALS['conf']['clean_url'] = FALSE; } return $url; } /** * Build a text format with Pathologic configured a certain way. * * @param $settings * An array of settings for the Pathologic instance on the format. * @return * A format machine name (consisting of random characters) for the format. */ function _pathologic_build_format($settings) { $format_id = user_password(); $format = (object) array( 'format' => $format_id, 'name' => $format_id, 'filters' => array( 'pathologic' => array( 'status' => 1, 'settings' => $settings, ), ), ); filter_format_save($format); return $format_id; } /** * Implements hook_pathologic_alter() for testing that functionality. */ function pathologic_pathologic_alter(&$url_params, $parts, $settings) { if (is_array($parts['qparts']) && isset($parts['qparts']['test'])) { if ($parts['qparts']['test'] === 'add_foo_qpart') { // Add a "foo" query part. if (empty($url_params['options']['query'])) { $url_params['options']['query'] = array(); } $url_params['options']['query']['foo'] = 'bar'; } elseif ($parts['qparts']['test'] === 'use_original') { $url_params['options']['use_original'] = TRUE; } } } /** * Tests with entity translation and language path prefixes. */ if (class_exists('EntityTranslationTestCase')) { class PathologicEntityTranslationTestCase extends EntityTranslationTestCase { public static function getInfo() { return array( 'name' => 'Pathologic & Entity Translation', 'description' => 'Tests with entity translation and language prefixes.', 'group' => 'Filter', ); } public function setUp() { parent::setUp('pathologic_test'); $this->login($this->getAdminUser(array('administer filters'))); $this->enableCleanUrls(); $this->addLanguage('en'); $this->addLanguage('es'); $this->enableUrlLanguageDetection(); $this->configureContentType(); $this->enablePathologicForTextFormat('filtered_html', array( 'filters[pathologic][settings][local_settings][protocol_style]' => 'path', )); $this->login($this->getTranslatorUser()); } public function addLanguage($langcode) { parent::addLanguage($langcode); // Check to make sure that language has a prefix. $this->drupalGet('admin/config/regional/language/edit/' . $langcode); if ($this->xpath('//input[@type="text" and @name="prefix" and @value=""]')) { $this->drupalPost(NULL, array('prefix' => $langcode), t('Save language')); } } public function enablePathologicForTextFormat($format, $edit) { $this->drupalGet('admin/config/content/formats/' . $format); $edit['filters[pathologic][status]'] = 1; $edit['filters[pathologic][weight]'] = 50; $edit['filters[pathologic][settings][settings_source]'] = 'local'; $this->drupalPost(NULL, $edit, t('Save configuration')); } public function testEntityTranslation() { // Create Basic page in English. $node_title = $this->randomName(); $node_body = 'EN: ' . $this->randomName(); $node_one = $this->createPage($node_title, $node_body, 'en'); // Submit translation in Spanish. $node_translation_title = $this->randomName(); $node_translation_body = 'ES: ' . $this->randomName(); $node_translation_one = $this->createTranslation($node_one, $node_translation_title, $node_translation_body, 'es', 'en'); $this->drupalGet('en/node/' . $node_one->nid); $this->drupalGet('es/node/' . $node_one->nid); // Create Basic page in English. $node_title = $this->randomName(); $node_body = 'EN: ' . $this->randomName() . 'FixMe'; $node_two = $this->createPage($node_title, $node_body, 'en'); // Submit translation in Spanish. $node_translation_title = $this->randomName(); $node_translation_body = 'ES: ' . $this->randomName() . 'FixMe'; $node_translation_two = $this->createTranslation($node_two, $node_translation_title, $node_translation_body, 'es', 'en'); // Check that the english translation points to the english version of node // one. $this->drupalGet('en/node/' . $node_two->nid); $this->assertLinkByHref('en/node/' . $node_one->nid); // Check that the spanish translation points to the spanish version of node // one. $this->drupalGet('es/node/' . $node_two->nid); $this->assertLinkByHref('es/node/' . $node_one->nid); } } }