Issue #1479454 by Hugo Wetterberg, galooph, dawehner, andypost, marcingy, heyrocker...
[project/drupal.git] / core / modules / filter / lib / Drupal / filter / Tests / FilterFormatAccessTest.php
1 <?php
2
3 /**
4 * @file
5 * Definition of Drupal\filter\Tests\FilterFormatAccessTest.
6 */
7
8 namespace Drupal\filter\Tests;
9
10 use Drupal\simpletest\WebTestBase;
11
12 /**
13 * Tests the filter format access functionality in the Filter module.
14 */
15 class FilterFormatAccessTest extends WebTestBase {
16 /**
17 * A user with administrative permissions.
18 *
19 * @var object
20 */
21 protected $admin_user;
22
23 /**
24 * A user with 'administer filters' permission.
25 *
26 * @var object
27 */
28 protected $filter_admin_user;
29
30 /**
31 * A user with permission to create and edit own content.
32 *
33 * @var object
34 */
35 protected $web_user;
36
37 /**
38 * An object representing an allowed text format.
39 *
40 * @var object
41 */
42 protected $allowed_format;
43
44 /**
45 * An object representing a disallowed text format.
46 *
47 * @var object
48 */
49 protected $disallowed_format;
50
51 public static function getInfo() {
52 return array(
53 'name' => 'Filter format access',
54 'description' => 'Tests access to text formats.',
55 'group' => 'Filter',
56 );
57 }
58
59 function setUp() {
60 parent::setUp();
61
62 $this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page'));
63
64 // Create a user who can administer text formats, but does not have
65 // specific permission to use any of them.
66 $this->filter_admin_user = $this->drupalCreateUser(array(
67 'administer filters',
68 'create page content',
69 'edit any page content',
70 ));
71
72 // Create two text formats.
73 $this->drupalLogin($this->filter_admin_user);
74 $formats = array();
75 for ($i = 0; $i < 2; $i++) {
76 $edit = array(
77 'format' => drupal_strtolower($this->randomName()),
78 'name' => $this->randomName(),
79 );
80 $this->drupalPost('admin/config/content/formats/add', $edit, t('Save configuration'));
81 $this->resetFilterCaches();
82 $formats[] = filter_format_load($edit['format']);
83 }
84 list($this->allowed_format, $this->disallowed_format) = $formats;
85 $this->drupalLogout();
86
87 // Create a regular user with access to one of the formats.
88 $this->web_user = $this->drupalCreateUser(array(
89 'create page content',
90 'edit any page content',
91 filter_permission_name($this->allowed_format),
92 ));
93
94 // Create an administrative user who has access to use both formats.
95 $this->admin_user = $this->drupalCreateUser(array(
96 'administer filters',
97 'create page content',
98 'edit any page content',
99 filter_permission_name($this->allowed_format),
100 filter_permission_name($this->disallowed_format),
101 ));
102 }
103
104 /**
105 * Tests the Filter format access permissions functionality.
106 */
107 function testFormatPermissions() {
108 // Make sure that a regular user only has access to the text format they
109 // were granted access to, as well to the fallback format.
110 $this->assertTrue(filter_access($this->allowed_format, $this->web_user), 'A regular user has access to a text format they were granted access to.');
111 $this->assertFalse(filter_access($this->disallowed_format, $this->web_user), 'A regular user does not have access to a text format they were not granted access to.');
112 $this->assertTrue(filter_access(filter_format_load(filter_fallback_format()), $this->web_user), 'A regular user has access to the fallback format.');
113
114 // Perform similar checks as above, but now against the entire list of
115 // available formats for this user.
116 $this->assertTrue(in_array($this->allowed_format->format, array_keys(filter_formats($this->web_user))), 'The allowed format appears in the list of available formats for a regular user.');
117 $this->assertFalse(in_array($this->disallowed_format->format, array_keys(filter_formats($this->web_user))), 'The disallowed format does not appear in the list of available formats for a regular user.');
118 $this->assertTrue(in_array(filter_fallback_format(), array_keys(filter_formats($this->web_user))), 'The fallback format appears in the list of available formats for a regular user.');
119
120 // Make sure that a regular user only has permission to use the format
121 // they were granted access to.
122 $this->assertTrue(user_access(filter_permission_name($this->allowed_format), $this->web_user), 'A regular user has permission to use the allowed text format.');
123 $this->assertFalse(user_access(filter_permission_name($this->disallowed_format), $this->web_user), 'A regular user does not have permission to use the disallowed text format.');
124
125 // Make sure that the allowed format appears on the node form and that
126 // the disallowed format does not.
127 $this->drupalLogin($this->web_user);
128 $this->drupalGet('node/add/page');
129 $langcode = LANGUAGE_NOT_SPECIFIED;
130 $elements = $this->xpath('//select[@name=:name]/option', array(
131 ':name' => "body[$langcode][0][format]",
132 ':option' => $this->allowed_format->format,
133 ));
134 $options = array();
135 foreach ($elements as $element) {
136 $options[(string) $element['value']] = $element;
137 }
138 $this->assertTrue(isset($options[$this->allowed_format->format]), 'The allowed text format appears as an option when adding a new node.');
139 $this->assertFalse(isset($options[$this->disallowed_format->format]), 'The disallowed text format does not appear as an option when adding a new node.');
140 $this->assertTrue(isset($options[filter_fallback_format()]), 'The fallback format appears as an option when adding a new node.');
141
142 // Check regular user access to the filter tips pages.
143 $this->drupalGet('filter/tips/' . $this->allowed_format->format);
144 $this->assertResponse(200);
145 $this->drupalGet('filter/tips/' . $this->disallowed_format->format);
146 $this->assertResponse(403);
147 $this->drupalGet('filter/tips/' . filter_fallback_format());
148 $this->assertResponse(200);
149 $this->drupalGet('filter/tips/invalid-format');
150 $this->assertResponse(404);
151
152 // Check admin user access to the filter tips pages.
153 $this->drupalLogin($this->admin_user);
154 $this->drupalGet('filter/tips/' . $this->allowed_format->format);
155 $this->assertResponse(200);
156 $this->drupalGet('filter/tips/' . $this->disallowed_format->format);
157 $this->assertResponse(200);
158 $this->drupalGet('filter/tips/' . filter_fallback_format());
159 $this->assertResponse(200);
160 $this->drupalGet('filter/tips/invalid-format');
161 $this->assertResponse(404);
162 }
163
164 /**
165 * Tests if text format is available to a role.
166 */
167 function testFormatRoles() {
168 // Get the role ID assigned to the regular user.
169 $roles = $this->web_user->roles;
170 unset($roles[DRUPAL_AUTHENTICATED_RID]);
171 $rid = key($roles);
172
173 // Check that this role appears in the list of roles that have access to an
174 // allowed text format, but does not appear in the list of roles that have
175 // access to a disallowed text format.
176 $this->assertTrue(in_array($rid, array_keys(filter_get_roles_by_format($this->allowed_format))), 'A role which has access to a text format appears in the list of roles that have access to that format.');
177 $this->assertFalse(in_array($rid, array_keys(filter_get_roles_by_format($this->disallowed_format))), 'A role which does not have access to a text format does not appear in the list of roles that have access to that format.');
178
179 // Check that the correct text format appears in the list of formats
180 // available to that role.
181 $this->assertTrue(in_array($this->allowed_format->format, array_keys(filter_get_formats_by_role($rid))), 'A text format which a role has access to appears in the list of formats available to that role.');
182 $this->assertFalse(in_array($this->disallowed_format->format, array_keys(filter_get_formats_by_role($rid))), 'A text format which a role does not have access to does not appear in the list of formats available to that role.');
183
184 // Check that the fallback format is always allowed.
185 $this->assertEqual(filter_get_roles_by_format(filter_format_load(filter_fallback_format())), user_role_names(), 'All roles have access to the fallback format.');
186 $this->assertTrue(in_array(filter_fallback_format(), array_keys(filter_get_formats_by_role($rid))), 'The fallback format appears in the list of allowed formats for any role.');
187 }
188
189 /**
190 * Tests editing a page using a disallowed text format.
191 *
192 * Verifies that regular users and administrators are able to edit a page, but
193 * not allowed to change the fields which use an inaccessible text format.
194 * Also verifies that fields which use a text format that does not exist can
195 * be edited by administrators only, but that the administrator is forced to
196 * choose a new format before saving the page.
197 */
198 function testFormatWidgetPermissions() {
199 $langcode = LANGUAGE_NOT_SPECIFIED;
200 $title_key = "title";
201 $body_value_key = "body[$langcode][0][value]";
202 $body_format_key = "body[$langcode][0][format]";
203
204 // Create node to edit.
205 $this->drupalLogin($this->admin_user);
206 $edit = array();
207 $edit['title'] = $this->randomName(8);
208 $edit[$body_value_key] = $this->randomName(16);
209 $edit[$body_format_key] = $this->disallowed_format->format;
210 $this->drupalPost('node/add/page', $edit, t('Save'));
211 $node = $this->drupalGetNodeByTitle($edit['title']);
212
213 // Try to edit with a less privileged user.
214 $this->drupalLogin($this->web_user);
215 $this->drupalGet('node/' . $node->nid);
216 $this->clickLink(t('Edit'));
217
218 // Verify that body field is read-only and contains replacement value.
219 $this->assertFieldByXPath("//textarea[@name='$body_value_key' and @disabled='disabled']", t('This field has been disabled because you do not have sufficient permissions to edit it.'), 'Text format access denied message found.');
220
221 // Verify that title can be changed, but preview displays original body.
222 $new_edit = array();
223 $new_edit['title'] = $this->randomName(8);
224 $this->drupalPost(NULL, $new_edit, t('Preview'));
225 $this->assertText($edit[$body_value_key], 'Old body found in preview.');
226
227 // Save and verify that only the title was changed.
228 $this->drupalPost(NULL, $new_edit, t('Save'));
229 $this->assertNoText($edit['title'], 'Old title not found.');
230 $this->assertText($new_edit['title'], 'New title found.');
231 $this->assertText($edit[$body_value_key], 'Old body found.');
232
233 // Check that even an administrator with "administer filters" permission
234 // cannot edit the body field if they do not have specific permission to
235 // use its stored format. (This must be disallowed so that the
236 // administrator is never forced to switch the text format to something
237 // else.)
238 $this->drupalLogin($this->filter_admin_user);
239 $this->drupalGet('node/' . $node->nid . '/edit');
240 $this->assertFieldByXPath("//textarea[@name='$body_value_key' and @disabled='disabled']", t('This field has been disabled because you do not have sufficient permissions to edit it.'), 'Text format access denied message found.');
241
242 // Disable the text format used above.
243 filter_format_disable($this->disallowed_format);
244 $this->resetFilterCaches();
245
246 // Log back in as the less privileged user and verify that the body field
247 // is still disabled, since the less privileged user should not be able to
248 // edit content that does not have an assigned format.
249 $this->drupalLogin($this->web_user);
250 $this->drupalGet('node/' . $node->nid . '/edit');
251 $this->assertFieldByXPath("//textarea[@name='$body_value_key' and @disabled='disabled']", t('This field has been disabled because you do not have sufficient permissions to edit it.'), 'Text format access denied message found.');
252
253 // Log back in as the filter administrator and verify that the body field
254 // can be edited.
255 $this->drupalLogin($this->filter_admin_user);
256 $this->drupalGet('node/' . $node->nid . '/edit');
257 $this->assertNoFieldByXPath("//textarea[@name='$body_value_key' and @disabled='disabled']", NULL, 'Text format access denied message not found.');
258 $this->assertFieldByXPath("//select[@name='$body_format_key']", NULL, 'Text format selector found.');
259
260 // Verify that trying to save the node without selecting a new text format
261 // produces an error message, and does not result in the node being saved.
262 $old_title = $new_edit['title'];
263 $new_title = $this->randomName(8);
264 $edit = array('title' => $new_title);
265 $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
266 $this->assertText(t('!name field is required.', array('!name' => t('Text format'))), 'Error message is displayed.');
267 $this->drupalGet('node/' . $node->nid);
268 $this->assertText($old_title, 'Old title found.');
269 $this->assertNoText($new_title, 'New title not found.');
270
271 // Now select a new text format and make sure the node can be saved.
272 $edit[$body_format_key] = filter_fallback_format();
273 $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
274 $this->assertUrl('node/' . $node->nid);
275 $this->assertText($new_title, 'New title found.');
276 $this->assertNoText($old_title, 'Old title not found.');
277
278 // Switch the text format to a new one, then disable that format and all
279 // other formats on the site (leaving only the fallback format).
280 $this->drupalLogin($this->admin_user);
281 $edit = array($body_format_key => $this->allowed_format->format);
282 $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
283 $this->assertUrl('node/' . $node->nid);
284 foreach (filter_formats() as $format) {
285 if ($format->format != filter_fallback_format()) {
286 filter_format_disable($format);
287 }
288 }
289
290 // Since there is now only one available text format, the widget for
291 // selecting a text format would normally not display when the content is
292 // edited. However, we need to verify that the filter administrator still
293 // is forced to make a conscious choice to reassign the text to a different
294 // format.
295 $this->drupalLogin($this->filter_admin_user);
296 $old_title = $new_title;
297 $new_title = $this->randomName(8);
298 $edit = array('title' => $new_title);
299 $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
300 $this->assertText(t('!name field is required.', array('!name' => t('Text format'))), 'Error message is displayed.');
301 $this->drupalGet('node/' . $node->nid);
302 $this->assertText($old_title, 'Old title found.');
303 $this->assertNoText($new_title, 'New title not found.');
304 $edit[$body_format_key] = filter_fallback_format();
305 $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
306 $this->assertUrl('node/' . $node->nid);
307 $this->assertText($new_title, 'New title found.');
308 $this->assertNoText($old_title, 'Old title not found.');
309 }
310
311 /**
312 * Rebuilds text format and permission caches in the thread running the tests.
313 */
314 protected function resetFilterCaches() {
315 filter_formats_reset();
316 $this->checkPermissions(array(), TRUE);
317 }
318 }