Issues (36)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/EcDataUtils.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * @file
4
 * Useful helpers for the esdportal_api module.
5
 *
6
 * Contains:
7
 *   Drupal\esdportal_api\EcDataUtils.
8
 */
9
10
namespace Drupal\esdportal_api;
11
12
/**
13
 * Some static helpers.
14
 */
15
class EcDataUtils {
16
  /**
17
   * Given an ec entity, return its id.
18
   *
19
   * @param object $ec
20
   *   An early childhood taxonomy term.
21
   *
22
   * @return int|null entity id
23
   *   The taxonomy term's id.
24
   */
25
  public static function getEcId($ec) {
26
    if (isset($ec->field_esd_ec_id['und']) && isset($ec->field_esd_ec_id['und'][0]) && isset($ec->field_esd_ec_id['und'][0]['value'])) {
27
      return $ec->field_esd_ec_id['und'][0]['value'];
28
    }
29
    elseif (gettype($ec->field_esd_ec_id) == 'string') {
30
      return $ec->field_esd_ec_id;
31
    }
32
    else {
33
      return NULL;
34
    }
35
  }
36
37
  /**
38
   * Returns data tables that JOIN by buildingcode.
39
   *
40
   * @return array
41
   *   Array of drupal data table objects.
42
   */
43
  public static function getDataTablesWithBcodes() {
44
    return array_filter(data_get_all_tables(), function($table) {
45
      return (isset($table->meta['join']) && isset($table->meta['join']['field_data_field_bcode']));
46
    });
47
  }
48
49
  /**
50
   * Returns data tables that JOIN by ESD internal school ID.
51
   *
52
   * @return array
53
   *   Array of drupal data table objects.
54
   */
55
  public static function getDataTablesWithEsdSchids() {
56
    return array_filter(data_get_all_tables(), function($table) {
57
      return (isset($table->meta['join']) && isset($table->meta['join']['field_data_field_esd_schid']));
58
    });
59
  }
60
61
  /**
62
   * Returns data tables that JOIN by earlychild programid.
63
   *
64
   * @return array
65
   *   Array of drupal data table objects.
66
   */
67
  public static function getDataTablesWithProgramIds() {
68
    return array_filter(data_get_all_tables(), function($table) {
69
      return (isset($table->meta['join']) && isset($table->meta['join']['earlychild']));
70
    });
71
  }
72
73
  /**
74
   * Extracts table names from array of drupal data table objects.
75
   *
76
   * @return array
77
   *   table names
78
   */
79
  public static function extractDataTableNames($tables) {
80
    return array_keys($tables);
81
  }
82
83
  /**
84
   * As seen in commerce_services: flatten fields.
85
   *
86
   * For the ESD api, we:
87
   *   * flatten fields (remove i18n & change multiple fields to arrays)
88
   *   * output taxonomy term references as [{tid:'tid',name:'name'},{...}]
89
   *     or just {tid:'tid',name:'name'}
90
   *
91
   * The original docs:
92
   *
93
   * Flattens field value arrays on the given entity.
94
   *
95
   * Field flattening in Commerce Services involves reducing their value arrays
96
   * to just the current language of the entity and reducing fields with single
97
   * column schemas to simple scalar values or arrays of scalar values.
98
   *
99
   * Note that because this function irreparably alters an entity's structure,
100
   * it should only be called using a clone of the entity whose field value
101
   * arrays should be flattened. Otherwise the flattening will affect the entity
102
   * as stored in the entity cache, causing potential errors should that entity
103
   * be loaded and manipulated later in the same request.
104
   *
105
   * @param string $entity_type
106
   *   The machine-name entity type of the given entity.
107
   * @param object $cloned_entity
108
   *   A clone of the entity whose field value arrays should be flattened.
109
   */
110
  public static function flattenFields($entity_type, $cloned_entity) {
111
    $bundle = field_extract_bundle($entity_type, $cloned_entity);
112
    $clone_wrapper = entity_metadata_wrapper($entity_type, $cloned_entity);
113
114
    // Loop over every field instance on the given entity.
115
    foreach (field_info_instances($entity_type, $bundle) as $field_name => $instance) {
116
      $field_info = field_info_field($field_name);
117
118
      // Add file & image URLs.
119
      if (in_array($field_info['type'], array('file', 'image'))) {
120
        $url_field_name = $field_name . '_url';
121
        // Set the URL for a single value field.
122
        if ($field_info['cardinality'] == 1) {
123
          $field_value = $clone_wrapper->{$field_name}->raw();
124
          $cloned_entity->{$url_field_name} = '';
125
          $url = NULL;
126
          // If the field value contains a URI...
127 View Code Duplication
          if (!empty($field_value['uri'])) {
128
            // And we can generate a URL to the file at that URI...
129
            $url = file_create_url($field_value['uri']);
130
            if (!empty($url)) {
131
              // Add it to the entity using the URL field name.
132
              $cloned_entity->{$url_field_name} = $url;
133
            }
134
          }
135
        }
136
        else {
137
          // Otherwise loop over the field and generate each URL.
138
          $cloned_entity->{$url_field_name} = array();
139
          foreach ($clone_wrapper->{$field_name}->getIterator() as $delta => $field_wrapper) {
140
            $field_value = $field_wrapper->raw();
141
            $url = NULL;
142
            // If the field value contains a URI...
143 View Code Duplication
            if (!empty($field_value['uri'])) {
144
              // And we can generate a URL to the file at that URI...
145
              $url = file_create_url($field_value['uri']);
146
              if (!empty($url)) {
147
                // Add it to the entity using the URL field name.
148
                $cloned_entity->{$url_field_name}[$delta] = $url;
149
              }
150
            }
151
            // If the field value did not have a URI or the URL to the file could not
152
            // be determined, add an empty URL string to the entity.
153
            if (empty($url)) {
154
              $cloned_entity->{$url_field_name}[$delta] = '';
155
            }
156
          }
157
        }
158
      }
159
160
      // Set the field property to the raw wrapper value, which applies the
161
      // desired flattening of the value array.
162
      // For taxonomy term refs, format nicely using loadtermnames module 'name'
163
      if ($clone_wrapper->{$field_name}->type() == 'taxonomy_term') {
164
        $term = $clone_wrapper->{$field_name}->value();
165
        // Explicitly set single-value taxonomy_term fields as null, rather than
166
        // an empty array.
167
        if (count($cloned_entity->{$field_name}) == 0) {
168
          $cloned_entity->{$field_name} = NULL;
169
        }
170
        if ($cloned_entity->{$field_name}) {
171
          $cloned_entity->{$field_name} = ['tid' => $term->tid, 'name' => $term->name];
172
        }
173
      }
174
      elseif ($clone_wrapper->{$field_name}->type() == 'list<taxonomy_term>') {
175
        $new_val = [];
176
        foreach ($clone_wrapper->{$field_name}->value() as $term) {
177
          $new_val[] = ['tid' => $term->tid, 'name' => $term->name];
178
        }
179
        $cloned_entity->{$field_name} = $new_val;
180
      }
181
      elseif ($clone_wrapper->{$field_name}->type() == 'list<text>') {
182
        $opts = $clone_wrapper->{$field_name}->optionsList();
183
        $newval = [];
184
        $iter = 0;
185
186
        foreach ($clone_wrapper->{$field_name}->value() as $machine_val) {
187
          $label = $opts[$machine_val];
188
189
          $newval[$iter]['machine_name'] = $machine_val;
190
          // For fields with only labels, set both as the same thing.
191
          $newval[$iter]['label'] = ($label) ? $label : $machine_val;
192
          $iter++;
193
        }
194
        unset($iter);
195
196
        $cloned_entity->{$field_name} = $newval;
197
        unset($newval);
198
      }
199
      elseif ($clone_wrapper->{$field_name}->type() == 'text' && $clone_wrapper->{$field_name}->label()) {
200
        $cloned_entity->{$field_name} = [
201
          'machine_name' => $clone_wrapper->{$field_name}->value(),
202
          'label' => $clone_wrapper->{$field_name}->label(),
203
        ];
204
      }
205
      else {
206
        $cloned_entity->{$field_name} = $clone_wrapper->{$field_name}->raw();
207
      }
208
    }
209
  }
210
211
  /**
212
   * Converts underscore_name to camelName.
213
   */
214
  public static function underscoreToCamel($underscore_name) {
215
    $underscore_name[0] = strtoupper($underscore_name[0]);
216
217
    return preg_replace_callback('/_([a-z0-9])/', function($c) {
218
      return strtoupper($c[1]);
219
    }, $underscore_name);
220
  }
221
222
  /**
223
   * Converts camelName to underscore_name.
224
   */
225
  public static function camelToUnderscore($camel_name) {
226
    return strtolower(preg_replace('/([a-z])([A-Z0-9])/', '$1_$2', $camel_name));
227
  }
228
229
  /**
230
   * As seen in commerce_services...
231
   *
232
   * Returns a list of properties for the specified entity type.
233
   *
234
   * For the purpose of the Commerce Services module, the properties returned
235
   * are those that correspond to a database column as determined by the Entity
236
   * API. These may be used to filter and sort index queries.
237
   *
238
   * @param string $entity_type
239
   *   Machine-name of the entity type whose properties should be returned.
240
   *
241
   * @return array
242
   *   An associative array of properties for the specified entity type with the
243
   *   key being the property name and the value being the corresponding schema
244
   *   field on the entity type's base table.
245
   */
246
  public static function entityTypeProperties($entity_type) {
247
    $properties = drupal_static(__FUNCTION__);
248
249
    if (!isset($properties[$entity_type])) {
250
      $entity_info = entity_get_info($entity_type);
251
      $info = entity_get_property_info($entity_type);
252
      $properties[$entity_type] = array();
253
254
      // Loop over only the properties of the entity type.
255 View Code Duplication
      foreach ($info['properties'] as $key => $value) {
256
        // If the value specifies a schema field...
257
        if (!empty($value['schema field'])) {
258
          $properties[$entity_type][$key] = $value['schema field'];
259
        }
260
      }
261
262
      // If the entity type supports revisions, add revision and log to the
263
      // array of acceptable properties.
264
      if (!empty($entity_info['revision table'])) {
265
        $properties[$entity_type] += array('revision', 'log');
266
      }
267
    }
268
269
    return $properties[$entity_type];
270
  }
271
272
  /**
273
   * As seen in commerce_services...
274
   *
275
   * Returns a list of fields for the specified entity type.
276
   *
277
   * @param string $entity_type
278
   *   Machine-name of the entity type whose properties should be returned.
279
   * @param string $bundle
280
   *   Optional bundle name to limit the returned fields to.
281
   *
282
   * @return array
283
   *   An associative array of fields for the specified entity type with the key
284
   *   being the field name and the value being the Entity API property type.
285
   */
286
  public static function entityTypeFields($entity_type, $bundle = NULL) {
287
    $fields = drupal_static(__FUNCTION__);
288
289
    if (!isset($fields[$entity_type])) {
290
      $info = entity_get_property_info($entity_type);
291
      $fields = array();
292
293
      // Loop over the bundles info to inspect their fields.
294
      foreach ($info['bundles'] as $bundle_name => $bundle_info) {
295
        // Loop over the properties on the bundle to find field information.
296 View Code Duplication
        foreach ($bundle_info['properties'] as $key => $value) {
297
          if (!empty($value['field'])) {
298
            $fields[$entity_type][$bundle_name][$key] = $value['type'];
299
          }
300
        }
301
      }
302
    }
303
304
    // If a specific bundle's fields was requested, return just those.
305
    if (!empty($bundle)) {
306
      return $fields[$entity_type][$bundle];
307
    }
308
    else {
309
      // Otherwise combine all the fields for various bundles of the entity type
310
      // into a single return value.
311
      $combined_fields = array();
312
313
      foreach ($fields[$entity_type] as $bundle_name => $bundle_fields) {
314
        $combined_fields += $bundle_fields;
315
      }
316
317
      return $combined_fields;
318
    }
319
  }
320
321
  /**
322
   * As seen in commerce_services: filtering.
323
   *
324
   * Adds property and field conditions to an index EntityFieldQuery.
325
   *
326
   * @param \EntityFieldQuery $query
327
   *   The EntityFieldQuery object being built for the index query.
328
   * @param string $entity_type
329
   *   Machine-name of the entity type of the index query.
330
   * @param array $filter
331
   *   An associative array of property names, single column field names, or
332
   *   multi-column field column names with their values to use to filter the
333
   *   result set of the index request.
334
   * @param array $filter_op
335
   *   An associative array of field and property names with the operators to
336
   *   use when applying their filter conditions to the index request query.
337
   */
338
  public static function indexQueryFilter(\EntityFieldQuery $query, $entity_type, array $filter, array $filter_op) {
339
    // Loop over each filter field to add them as property or field conditions
340
    // on the query object. This function assumes the $filter and $filter_op
341
    // arrays contain matching keys to set the correct operator to the filter
342
    // fields.
343
    foreach ($filter as $filter_field => $filter_value) {
344
      // Determine the corresponding operator for this filter field, defaulting
345
      // to = in case of an erroneous request.
346
      $operator = '=';
347
348
      if (!empty($filter_op[$filter_field])) {
349
        $operator = $filter_op[$filter_field];
350
      }
351
352
      // If operator is IN, try to turn the filter into an array.
353
      if ($operator == 'IN') {
354
        $filter_value = explode(',', $filter_value);
355
      }
356
357
      // If the current filter field is a property, use a property condition.
358
      $properties = self::entityTypeProperties($entity_type);
359
360
      if (in_array($filter_field, array_keys($properties), TRUE)) {
361
        $query->propertyCondition($properties[$filter_field], $filter_value, $operator);
362
      }
363
      else {
364
        // Look for the field name among the entity type's field list.
365
        foreach (self::entityTypeFields($entity_type) as $field_name => $field_type) {
366
          // If the filter field begins with a field name, then either the
367
          // filter field is the field name or is a column of the field.
368
          if (strpos($filter_field, $field_name) === 0) {
369
            $field_info = field_info_field($field_name);
370
371
            // If field is list_boolean, convert true => 1 and false => 0.
0 ignored issues
show
Unused Code Comprehensibility introduced by
36% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
372
            if ($field_info['type'] == 'list_boolean') {
373
              if ($filter_value === 'true') {
374
                $filter_value = 1;
375
              }
376
              if ($filter_value === 'false') {
377
                $filter_value = 0;
378
              }
379
            }
380
381
            // If it is the field name and the field type has a single column
382
            // schema, add the field condition to the index query.
383 View Code Duplication
            if ($field_name == $filter_field && count($field_info['columns']) == 1) {
384
              $column = key($field_info['columns']);
385
              $query->fieldCondition($field_name, $column, $filter_value, $operator);
386
              break;
387
            }
388
            else {
389
              // Otherwise if the filter field contains a valid column
390
              // specification for the field type, add the field condition to
391
              // the index query.
392
              $column = substr($filter_field, strlen($field_name) + 1);
393
394
              if (in_array($column, array_keys($field_info['columns']))) {
395
                $query->fieldCondition($field_name, $column, $filter_value, $operator);
396
                break;
397
              }
398
            }
399
          }
400
        }
401
      }
402
    }
403
  }
404
405
  /**
406
   * As seen in commerce_services: sorting.
407
   *
408
   * Adds property and field order by directions to an index EntityFieldQuery.
409
   *
410
   * @param \EntityFieldQuery $query
411
   *   The EntityFieldQuery object being built for the index query.
412
   * @param string $entity_type
413
   *   Machine-name of the entity type of the index query.
414
   * @param array $sort_by
415
   *   An array of database fields to sort the query by, with sort fields being
416
   *   valid properties, single column field names, or multi-column field column
417
   *   names for the matching entity type.
418
   * @param array $sort_order
419
   *   The corresponding sort orders for the fields specified in the $sort_by
420
   *   array; one of either 'DESC' or 'ASC'.
421
   */
422
  public static function indexQuerySort(\EntityFieldQuery $query, $entity_type, array $sort_by, array $sort_order) {
423
    // Loop over each sort field to add them as property or field order by
424
    // directions on the query object. This function assumes the $sort_by and
425
    // $sort_order arrays contain an equal number of elements with keys matching
426
    // the sort field to the appropriate sort order.
427
    foreach ($sort_by as $sort_key => $sort_field) {
428
      // Determine the corresponding sort direction for this sort field,
429
      // defaulting to DESC in case of an erroneous request.
430
      $direction = 'DESC';
431
432
      if (!empty($sort_order[$sort_key])) {
433
        $direction = strtoupper($sort_order[$sort_key]);
434
      }
435
436
      // If the current sort field is a property, use a property condition.
437
      $properties = self::entityTypeProperties($entity_type);
438
439
      if (in_array($sort_field, array_keys($properties), TRUE)) {
440
        $query->propertyOrderBy($properties[$sort_field], $direction);
441
      }
442
      else {
443
        // Look for the field name among the entity type's field list.
444
        foreach (self::entityTypeFields($entity_type) as $field_name => $field_type) {
445
          // If the sort field begins with a field name, then either the sort
446
          // field is the field name or is a column of the field.
447
          if (strpos($sort_field, $field_name) === 0) {
448
            $field_info = field_info_field($field_name);
449
450
            // If it is the field name and the field type has a single column
451
            // schema, add the field condition to the index query.
452 View Code Duplication
            if ($field_name == $sort_field && count($field_info['columns']) == 1) {
453
              $column = key($field_info['columns']);
454
              $query->fieldOrderBy($field_name, $column, $direction);
455
              break;
456
            }
457
            else {
458
              // Otherwise if the sort field contains a valid column
459
              // specification for the field type, add the field condition to
460
              // the index query.
461
              $column = substr($sort_field, strlen($field_name) + 1);
462
463
              if (in_array($column, array_keys($field_info['columns']))) {
464
                $query->fieldOrderBy($field_name, $column, $direction);
465
                break;
466
              }
467
            }
468
          }
469
        }
470
      }
471
    }
472
  }
473
474
}
475