-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfield_validation_report.module
364 lines (317 loc) · 11.8 KB
/
field_validation_report.module
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
<?php
/**
* @file
* Code for the Field Validation Report module.
*/
include_once 'field_validation_report.forms.inc';
/**
* Implements hook_menu().
*/
function field_validation_report_menu() {
$return = array();
$return['admin/reports/field-validation-report'] = array(
'title' => 'Field Validation Report',
'description' => 'Provides a report of all entities that do not pass field validation.',
'page callback' => 'field_validation_report_page',
'access arguments' => array('view field validation report'),
'file' => 'field_validation_report.pages.inc',
'type' => MENU_NORMAL_ITEM,
);
$return['admin/config/system/field-validation-report'] = array(
'title' => 'Field Validation Report',
'description' => 'Provides configuration options for Field Validation Report.',
'page callback' => 'drupal_get_form',
'page arguments' => array('field_validation_report_config'),
'access arguments' => array('administer field validation report'),
'file' => 'field_validation_report.admin.inc',
'type' => MENU_NORMAL_ITEM,
);
return $return;
}
/**
* Implements hook_permission().
*/
function field_validation_report_permission() {
return array(
'view field validation report' => array(
'title' => t('View the Field Validation Report'),
'description' => t('Allows the user to view the field validation report.'),
),
'administer field validation report' => array(
'title' => t('Administer Field Validation Report'),
'description' => t('Allow the user to administer the configuration for field validation report.'),
),
);
}
/**
* Identify whether an entity type is capable of being validated.
*
* In order to be capable of appearing in the field validation report,
* an entity type must be fieldable, and may not be a configuration entity.
*
* @param string $entity_type
* @param array $entity_info
*
* @return bool
*/
function field_validation_report_entity_type_is_suitable($entity_type, $entity_info = array()) {
$suitable = TRUE;
// If the entity info was not passed along, load it.
if (empty($entity_info)) {
$entity_info = entity_get_info($entity_type);
}
// Configuration entities may not be validated.
if (isset($entity_info['configuration']) && $entity_info['configuration'] == TRUE) {
$suitable = FALSE;
}
// Entities must have bundles.
elseif (empty($entity_info['bundles'])) {
$suitable = FALSE;
}
// The entity type must be fieldable.
elseif (empty($entity_info['fieldable'])) {
$suitable = FALSE;
}
// Trigger hook_field_validation_report_entity_type_is_supported_alter() to allow other
// modules to either enable or disable certain entity types.
drupal_alter('field_validation_report_entity_type_is_supported', $suitable, $entity_type, $entity_info);
return $suitable;
}
/**
* Check whether the requested entity type (and bundle) is enabled.
*
* By default the entities are disabled, only certain entities will have been
* enabled during installation. If an entity type is enabled it is assumed that
* the entity bundles will also be enabled by default.
*
* @param string $entity_type
* The entity type.
* @param string $bundle
* The bundle name.
*
* @return mixed
* TRUE/FALSE if checking a single entity type/bundle is enabled.
* Otherwise, a full array of entity types and bundles indicating
* whether they are enabled.
*
* @see field_validation_report_entity_type_is_suitable().
*/
function field_validation_report_entities_enabled($entity_type = NULL, $bundle = NULL) {
$entity_types = &drupal_static(__FUNCTION__);
// Identify which entities & bundles are supported the first time the
// function is called.
if (!isset($entity_types)) {
foreach (entity_get_info() as $entity_name => $entity_info) {
// Verify that this entity type is suitable.
$entity_types[$entity_name] = field_validation_report_entity_type_is_suitable($entity_name, $entity_info);
// The entity type technically supports validation.
if (!empty($entity_types[$entity_name])) {
// Entity types are enabled by default.
// Allow entities to be disabled by assigning a variable
// 'field_validation_report_enable_{$entity_type}' the value FALSE.
if (variable_get('field_validation_report_enable_' . $entity_name, FALSE) == FALSE) {
$entity_types[$entity_name] = FALSE;
}
// Check each bundle.
else {
$entity_types[$entity_name] = array();
foreach ($entity_info['bundles'] as $bundle_name => $bundle_info) {
// Allow bundles to be disabled by assigning a variable
// 'field_validation_report_enable_{$entity_type}__{$bundle}' the value FALSE, e.g.:
if (count($entity_info['bundles']) > 1 && variable_get('field_validation_report_enable_' . $entity_name . '__' . $bundle_name, TRUE) == FALSE) {
$entity_types[$entity_name][$bundle_name] = FALSE;
}
else {
$entity_types[$entity_name][$bundle_name] = TRUE;
}
}
}
}
}
}
// It was requested to check a specific entity.
if (isset($entity_type)) {
// It was also requested to check a specific bundle for this entity.
if (isset($bundle)) {
$supported = !empty($entity_types[$entity_type][$bundle]);
}
// Check the entity.
else {
$supported = !empty($entity_types[$entity_type]);
}
return $supported;
}
// If nothing specific was requested, return the complete list of
// entities & bundles indicating whether they are supported.
return $entity_types;
}
/**
* Helper function to run all enabled validations.
*/
function field_validation_report_run_validations() {
// Clear the cache.
$errors = cache_get('field_validation_report_errors');
if (!empty($errors->data)) {
cache_clear_all('field_validation_report_errors', 'cache');
}
// Loop over configuration, if bundle is enabled then run the validations.
foreach (field_validation_report_entities_enabled() as $entity_type => $bundles) {
if (!$bundles) {
continue;
}
foreach ($bundles as $bundle_name => $bundle_enabled) {
if (!$bundle_enabled) {
continue;
}
_field_validation_report_validate_bundle($entity_type, $bundle_name);
}
}
$errors = _field_validation_report_get_errors();
cache_set('field_validation_report_errors', $errors);
}
/**
* Stores the current collected error messages in a static variable.
*
* @return array
* An array of errors collected through the validations, keyed by
* entity type, bundle name and entity id.
* e.g $errors['node']['page'][1] = 'the error';
*/
function &_field_validation_report_get_errors() {
$errors = cache_get('field_validation_report_errors');
if ($errors) {
return $errors->data;
}
$errors = &drupal_static(__FUNCTION__, array());
return $errors;
}
/**
* Validates an entity type.
*
* Runs the validation functions for all entities of this type.
* To view the errors you will need to call
* _field_validation_report_get_errors();
*
* @param string $entity_type
* The machine name of the entity type, e.g `node`
*/
function _field_validation_report_validate_entity_type($entity_type) {
$entity_type_info = entity_get_info($entity_type);
foreach ($entity_type_info['bundles'] as $bundle_name => $bundle) {
_field_validation_report_validate_bundle($entity_type, $bundle_name);
}
}
/**
* Validates a bundle of an entity type.
*
* Runs the validation functions for the specified bundle
* of this entity type.
* To view the errors you will need to call
* _field_validation_report_get_errors();
*
* @param string $entity_type
* The machine name of the entity type, e.g `node`
* @param string $bundle_name
* The machine name of the bundle, e.g `page`
*/
function _field_validation_report_validate_bundle($entity_type, $bundle_name) {
$entity_type_info = entity_get_info($entity_type);
$query = new \EntityFieldQuery();
$query->entityCondition('entity_type', $entity_type);
if (count($entity_type_info['bundles']) > 1) {
$query->entityCondition('bundle', $bundle_name);
}
if ($entity_type == 'comment') {
$query->addTag('comment_bundle_fix');
}
$results = $query->execute();
if (!empty($results[$entity_type])) {
$entities = entity_load($entity_type, array_keys($results[$entity_type]));
foreach ($entities as $entity) {
_field_validation_report_validate_entity($entity_type, $entity);
}
}
}
/**
* Validates a particular entity.
*
* Runs the validation functions for a particular entity.
* To view the errors you will need to call
* _field_validation_report_get_errors();
*
* @param string $entity_type
* The machine name of the entity type, e.g `node`
* @param stdClass $entity
* The entity object to validate.
*/
function _field_validation_report_validate_entity($entity_type, $entity) {
$errors = &_field_validation_report_get_errors();
list($entity_id, $revision_id, $bundle_name) = entity_extract_ids($entity_type, $entity);
$form_state = array(
'programmed' => TRUE,
'build_info' => array(
'args' => array(
0 => $entity_type,
1 => &$entity,
),
),
'triggering_element' => array(
'#parents' => array(),
'#limit_validation_errors' => FALSE,
));
$form = drupal_build_form('field_validation_report_pseudo_form', $form_state);
field_attach_form_validate($entity_type, $entity, $form, $form_state);
// Report errors.
$form_errors = form_get_errors();
// Setup errors array if not set.
$errors['__count'] = 0;
if (!isset($errors[$entity_type])) {
$errors[$entity_type] = array();
$errors[$entity_type]['__count'] = 0;
}
if (!isset($errors[$entity_type][$bundle_name])) {
$errors[$entity_type][$bundle_name] = array();
$errors[$entity_type][$bundle_name]['__count'] = 0;
}
if (!isset($errors[$entity_type][$bundle_name][$entity_id])) {
$errors[$entity_type][$bundle_name][$entity_id] = array();
$errors[$entity_type][$bundle_name][$entity_id]['__count'] = 0;
}
if (!empty($form_errors)) {
foreach ($form_errors as $form_error) {
$errors['__count']++;
$errors[$entity_type]['__count']++;
$errors[$entity_type][$bundle_name]['__count']++;
$errors[$entity_type][$bundle_name][$entity_id]['__count']++;
$errors[$entity_type][$bundle_name][$entity_id][] = $form_error;
// Remove the error message created by this validation.
$messages = drupal_get_messages('error', FALSE);
foreach ($messages['error'] as $key => $message) {
if ($message == $form_error) {
unset($_SESSION['messages']['error'][$key]);
}
}
}
}
// Prevent duplicate error messages.
form_clear_error();
// Prevent blank error message.
if (empty($_SESSION['messages']['error'])) {
unset($_SESSION['messages']['error']);
}
}
/**
* Implements hook_TAG_query_alter().
*
* Fix until https://www.drupal.org/node/2581225 is committed.
* As bundles do not specify a bundle column in the comment schema,
* EntityFieldQuery throws a column not found error when attempting
* to filter comment entities by bundle. This hook modifies the query
* to correctly filter the comments by the bundle.
*/
function field_validation_report_query_comment_bundle_fix_alter(QueryAlterableInterface $query) {
$query->innerJoin('node', NULL, 'comment.nid = node.nid');
$conditions = &$query->conditions();
$conditions[0]['field'] = 'node.type';
$conditions[0]['value'] = str_replace('comment_node_', '', $conditions[0]['value']);
}