Completed
Push — recommendation_api_cache ( 7da34d...88ceea )
by
unknown
14:54
created

api.php ➔ mm_api_export_count()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 9
dl 0
loc 10
rs 9.9332
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/**
3
* NRC Recommendation Platform API Library
4
*
5
* @author National Research Council
6
* @author Luc Belliveau
7
* @link http://www.nrc-cnrc.gc.ca/eng/rd/dt/ NRC Digital Technologies
8
*
9
* @license MIT
10
* @copyright Her Majesty the Queen in Right of Canada, as represented by the Minister of National Research Council, 2019
11
*
12
*/
13
require_once(elgg_get_plugins_path() . 'missions/api/v0/cache.php');
14
15
header('Content-Type: application/json');
16
17
global $subtypes;
18
$subtypes = NULL;
19
20
class FakeGUIDEntity {
21
  public $guid;
22
  public function __construct($guid) {
23
    $this->guid = $guid;
24
  }
25
}
26
27
class FakeEntity extends \ElggEntity {
28
  private $entity;
29
  public function __construct($entity) {
30
    $this->entity = $entity;
31
  }
32
  public function __get($name) {
33
    return $this->entity->$name;
34
  }
35
  public function getType() {
36
    return $this->entity->type;
37
  }
38
  public function getSubtype() {
39
    global $subtypes;
40
    return $subtypes["i_{$this->entity->subtype}"];
41
  }
42
  public function getOwnerEntity() {
43
    if ($this->entity->owner_guid > 0) {
44
      return new FakeGUIDEntity($this->entity->owner_guid);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return new \FakeGUIDEnti...s->entity->owner_guid); (FakeGUIDEntity) is incompatible with the return type of the parent method ElggEntity::getOwnerEntity of type ElggEntity.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
45
    } else return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type of the parent method ElggEntity::getOwnerEntity of type ElggEntity.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
46
  }
47
  public function getDisplayName() {
48
    return $this->entity->name;
49
  }
50
  public function getContainerEntity() {
51
    if ($this->entity->container_guid > 0) {
52
      return new FakeGUIDEntity($this->entity->container_guid);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return new \FakeGUIDEnti...ntity->container_guid); (FakeGUIDEntity) is incompatible with the return type of the parent method ElggEntity::getContainerEntity of type ElggEntity.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
53
    } else return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type of the parent method ElggEntity::getContainerEntity of type ElggEntity.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
54
  }
55
  public function setDisplayName($displayName) {}
56
}
57
58
/**
59
* Verify that the API request has the appropriate X-Custom-Authorization
60
* header, and make sure the script has all require privileges to run.
61
*
62
* Responds with a 403 if authorization is missing or invalid.
63
*
64
*/
65
function mm_api_secure() {
0 ignored issues
show
Coding Style introduced by
mm_api_secure uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
66
67
  if (
68
      !isset($_SERVER['HTTP_X_CUSTOM_AUTHORIZATION'])
69
      || (!openssl_public_decrypt(base64_decode($_SERVER['HTTP_X_CUSTOM_AUTHORIZATION']), $decrypted, PUBLIC_KEY))
70
      || ($decrypted !== '-- NRC -- LPSS -- GCTools -- Sig -- dsaj9843uj80w7IJHYS&UHSJY(*IOIJHY*')
71
    ) {
72
    header('HTTP/1.0 403 Forbidden');
73
    exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The function mm_api_secure() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
74
  }
75
76
  # Ensure API has full access
77
  session_destroy();
78
  elgg_set_ignore_access(true);
79
80
  # Increase the script timeout value
81
  set_time_limit(14400);
82
}
83
global $CONFIG;
84
function getURL($entity) {
85
  global $CONFIG;
86
  global $subtypes;
87
  $type = $entity->type;
88
  $subtype = $subtypes["i_{$entity->subtype}"];
89
90
  $url = '';
91
92
  if (isset($CONFIG->entity_url_handler[$type][$subtype])) {
93
    $function = $CONFIG->entity_url_handler[$type][$subtype];
94
    if (is_callable($function)) {
95
      $url = call_user_func($function, $entity);
96
    }
97
  } elseif (isset($CONFIG->entity_url_handler[$type]['all'])) {
98
    $function = $CONFIG->entity_url_handler[$type]['all'];
99
    if (is_callable($function)) {
100
      $url = call_user_func($function, $entity);
101
    }
102
  } elseif (isset($CONFIG->entity_url_handler['all']['all'])) {
103
    $function = $CONFIG->entity_url_handler['all']['all'];
104
    if (is_callable($function)) {
105
      $url = call_user_func($function, $entity);
106
    }
107
  }
108
109
  if ($url) {
110
    $url = elgg_normalize_url($url);
111
  }
112
113
  $params = array('entity' => new FakeEntity($entity));
114
  $url = _elgg_services()->hooks->trigger('entity:url', $type, $params, $url);
115
116
  return elgg_normalize_url($url);
117
}
118
119
function mm_build_subtypes_array() {
120
  global $subtypes;
121
  if (is_null($subtypes)) {
122
    $dbprefix = elgg_get_config('dbprefix');
123
    $dblink = _elgg_services()->db->getLink('read');
124
125
    // Get all subtypes
126
    $subtypes = [];
127
    $subtype_results = mysql_unbuffered_query(
128
      "select id, subtype from {$dbprefix}entity_subtypes",
129
      $dblink
130
    );
131
    while ($row = mysql_fetch_object($subtype_results)) {
132
      $subtypes["i_{$row->id}"] = $row->subtype;
133
      $subtypes["s_{$row->subtype}"] = $row->id;
134
    }
135
    mysql_free_result($subtype_results);
136
  }
137
}
138
139
function mm_api_generateWhereStatement($type, $subtype = false, $guid = null,
140
  $since = null, $before = null, $limit = null, $resume = null, $sort = false,
141
  $omit = null) {
142
  mm_build_subtypes_array();
143
144
  $dbprefix = elgg_get_config('dbprefix');
145
  $dblink = _elgg_services()->db->getLink('read');
146
147
  $where = ['a.enabled = "yes"'];
148
  if ($type !== 'export') {
149
    $where[] = 'a.type = "' . mysql_escape_string($type) . '"';
150
  }
151
  if ($subtype !== false) {
152
    $where[] = 'a.subtype = ' .
153
      (($subtypes["s_$subtype"]) ? $subtypes["s_$subtype"] : -1);
0 ignored issues
show
Bug introduced by
The variable $subtypes does not exist. Did you mean $subtype?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
154
  }
155
156
  if (!is_null($guid) && is_numeric($guid)) {
157
    $where[] = 'a.guid = ' . mysql_escape_string(intval($guid));
158
  }
159
  if (is_numeric($since)) {
160
    $where[] = 'a.time_updated > ' . mysql_escape_string($since);
161
  }
162
  if (is_numeric($before)) {
163
    $where[] = 'a.time_updated < ' . mysql_escape_string($before);
164
  }
165
  if (!is_null($omit)) {
166
    $omitGuids = explode(',', $omit);
167
    if (count($omitGuids) > 0) {
168
      $ogs = [];
169
      foreach ($omitGuids as $og) {
170
        $ogs[] = mysql_escape_string(intval($og));
171
      }
172
      $where[] = 'a.guid NOT IN ('.implode(',', $ogs).')';
173
    }
174
  }
175
176
  $where_sql = '';
177
  if (count($where) > 0) {
178
    $where_sql = 'WHERE ' . implode(' AND ', $where);
179
  }
180
  return $where_sql;
181
}
182
183
function mm_api_export_count($type, $subtype = false, $guid = null,
184
$since = null, $before = null, $limit = null, $resume = null, $sort = false,
185
$omit = null) {
186
  $where_sql = mm_api_generateWhereStatement($type, $subtype, $guid,
187
    $since, $before, $limit, $resume, $sort, $omit);
188
  $dbprefix = elgg_get_config('dbprefix');
189
  return (int)get_data(
190
    "select count(guid) c from {$dbprefix}entities a $where_sql"
191
    )[0]->c;
192
}
193
194
195
/**
196
* Stream the requested entities as efficently as possible using JSON.
197
*
198
* @param str $type Desired entity type.  (object, user, export)
199
* @param str $subtype Desired subtype.  (mission)
200
* @param int $guid GUID of single object, for single entity fetch.
201
* @param int $since: Fetch entities that have been modified since the specified time
0 ignored issues
show
Documentation introduced by
There is no parameter named $since:. Did you maybe mean $since?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
202
* @param int $before: Fetch entities that have been modified before the specified time
0 ignored issues
show
Documentation introduced by
There is no parameter named $before:. Did you maybe mean $before?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
203
* @param int $limit: Fetch at most X entities.
0 ignored issues
show
Documentation introduced by
There is no parameter named $limit:. Did you maybe mean $limit?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
204
* @param int $resume: Resume starting at the specified GUID.
0 ignored issues
show
Documentation introduced by
There is no parameter named $resume:. Did you maybe mean $resume?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
205
* @param bool $sort: If true sorts entities based on time created.
0 ignored issues
show
Bug introduced by
There is no parameter named $sort:. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
206
* @param str $omit: Comma separated list of GUIDs to omit.
0 ignored issues
show
Bug introduced by
There is no parameter named $omit:. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
207
*
208
* @return Generator[] JSON formatted text stream
209
*/
210
function mm_api_export_entities($type, $subtype = false, $guid = null,
211
$since = null, $before = null, $limit = null, $resume = null, $sort = false,
212
$omit = null) {
213
  $cache = new NRC\ApiCache([
214
    $type, $subtype, $guid, $since, $before,
215
    $limit, $resume, $sort, $omit
216
  ]);
217
  $data = $cache->get(
218
    function() use ($type, $subtype, $guid, $since, $before,
0 ignored issues
show
Documentation introduced by
function () use($type, $...on_encode($e)); } } is of type object<Closure>, but the function expects a object<NRC\Closure>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
219
    $limit, $resume, $sort, $omit) {
220
      _elgg_services()->db->establishLink('api_exporter');
221
      $dbprefix = elgg_get_config('dbprefix');
222
      $dblink = _elgg_services()->db->getLink('read');
223
      function dismount($object) {
224
        $reflectionClass = new ReflectionClass(get_class($object));
225
        $array = array();
226
        foreach ($reflectionClass->getProperties() as $property) {
227
            $property->setAccessible(true);
228
            $array[$property->getName()] = $property->getValue($object);
229
            $property->setAccessible(false);
230
        }
231
        return $array;
232
      }
233
      global $in_array;
234
      $in_array = false;
235
      function outVal($val, $start_with_comma=true) {
236
        global $in_array;
237
        $value = ($val->meta_type === 'integer') ?
238
          json_encode(intval($val->meta_value)) : json_encode($val->meta_value);
239
        if (($in_array !== false) && ($in_array == $val->meta_name)) {
240
          return (($start_with_comma) ? ',' : '').$value;
241
        }
242
        $ret = '';
243
        if (($in_array !== false) && (($in_array != $val->meta_name) || ($val->arr == 0))) {
244
          $ret .= ']';
245
          $in_array = false;
246
        }
247
        if ($start_with_comma) $ret .= ',';
248
        $ret .= '"' . $val->meta_name . '":';
249
        if ($val->arr != 0) {
250
          $ret .= '[';
251
          $in_array = $val->meta_name;
252
        }
253
        $ret .= $value;
254
        return $ret;
255
      }
256
      function finalizeEntity($uguid) {
257
        global $in_array;
258
        $dbprefix = elgg_get_config('dbprefix');
259
        $dblink = _elgg_services()->db->getLink('read');
260
261
        if ($uguid > 0) {
262
          if ($in_array) {
263
            yield ']';
264
            $in_array = false;
265
          }
266
267
          $options = array('guid' => $uguid, 'limit' => 0);
268
          $annotations = elgg_get_annotations($options);
269
270
          if ($annotations) {
271
            $data = [ 'annotations' => []];
272
            foreach ($annotations as $v) {
273
              if (!isset($data['annotations'][$v->name])) {
274
                $data['annotations'][$v->name] = [];
275
              };
276
              $data['annotations'][$v->name][] = dismount($v);
277
            }
278
            yield ','.substr(json_encode($data), 1, -1);
279
          }
280
          yield ',"relationships":[';
281
282
          $relstart = false;
283
          $reltable = "{$dbprefix}entity_relationships";
284
          $relationships = mysql_unbuffered_query(
285
            "SELECT * from $reltable where guid_one = " .
286
            mysql_escape_string($uguid) .
287
            ' OR guid_two = ' . mysql_escape_string($uguid),
288
            $dblink
289
          );
290
          while ($v = mysql_fetch_object($relationships)) {
291
            yield (($relstart) ? ',' : '') . json_encode(array(
292
              'direction' => ($v->guid_one == $uguid) ? 'OUT' : 'IN',
293
              'time_created' => $v->time_created,
294
              'id' => $v->id,
295
              'relationship' => $v->relationship,
296
              'entity' => ($v->guid_one == $uguid) ? $v->guid_two : $v->guid_one,
297
            ));
298
            $relstart = true;
299
          }
300
          mysql_free_result($relationships);
301
          yield ']}';
302
        }
303
      }
304
305
      $where_sql = mm_api_generateWhereStatement($type, $subtype, $guid,
0 ignored issues
show
Bug introduced by
It seems like $subtype defined by parameter $subtype on line 210 can also be of type string; however, mm_api_generateWhereStatement() does only seem to accept boolean, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
306
        $since, $before, $limit, $resume, $sort, $omit);
307
308
      if ($sort) {
309
        $sort_sql = 'ORDER BY a.time_updated ASC';
310
      }
311
312
      try {
313
        $sql = "
314
        SELECT
315
          a.guid,
316
          a.type,
317
          a.subtype,
318
          a.owner_guid,
319
          a.site_guid,
320
          a.container_guid,
321
          a.time_created,
322
          a.time_updated,
323
          a.access_id,
324
          a.enabled,
325
          a.last_action,
326
          o.title,
327
          o.description,
328
          u.name,
329
          u.username,
330
          u.admin,
331
          u.banned,
332
          u.language,
333
          u.last_action AS user_last_action,
334
          u.prev_last_action,
335
          u.last_login,
336
          u.prev_last_login,
337
          g.name as group_name,
338
          g.description as group_description,
339
          (
340
            SELECT
341
              COUNT(name_id)
342
            FROM
343
              elggmetadata
344
            WHERE
345
              entity_guid = a.guid
346
              AND name_id = b.name_id
347
          ) > 1 as arr,
348
          b.value_type as meta_type,
349
          c.string as meta_name,
350
          d.string as meta_value
351
        FROM
352
          {$dbprefix}entities a
353
          LEFT JOIN {$dbprefix}objects_entity o on o.guid = a.guid
354
          LEFT JOIN {$dbprefix}users_entity u ON u.guid = a.guid
355
          LEFT JOIN {$dbprefix}groups_entity g ON g.guid = a.guid
356
          LEFT JOIN {$dbprefix}metadata b ON b.entity_guid = a.guid
357
          LEFT JOIN {$dbprefix}metastrings c ON c.id = b.name_id
358
          LEFT JOIN {$dbprefix}metastrings d ON d.id = b.value_id
359
        $where_sql
360
        $sort_sql";
0 ignored issues
show
Bug introduced by
The variable $sort_sql does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
361
362
        $entity_data = mysql_unbuffered_query(
363
          $sql,
364
          _elgg_services()->db->getLink('api_exporter')
365
        );
366
        $emit = !is_numeric($resume);
367
        $max = (is_numeric($limit) && ($limit > 0)) ? $limit : false;
368
        $count = 0;
369
        $currentGuid = -1;
370
        $uguid = -1;
371
        $euguid = -1;
372
        while ($row = mysql_fetch_object($entity_data)) {
373
          if ($emit) {
374
            if ($currentGuid != $row->guid) {
375
              $fin = finalizeEntity($currentGuid);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $fin is correct as finalizeEntity($currentGuid) (which targets finalizeEntity()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
376
              foreach ($fin as $fs) yield $fs;
0 ignored issues
show
Bug introduced by
The expression $fin of type null is not traversable.
Loading history...
377
              $currentGuid = -1;
378
              $count += 1;
379
              if (($max !== false) && ($count > $max)) break;
380
              if ($count > 1) yield ',';
381
              yield '{';
382
              $currentGuid = $row->guid;
383
              $euguid = mysql_escape_string(intval($row->guid));
384
              $uguid = $row->guid;
385
386
              yield '"guid":' . $row->guid . ',' .
387
                '"type":"' . $row->type . '",' .
388
                '"subtype":' . $row->subtype . ',' .
389
                '"subtype_name":' . json_encode($subtypes["i_{$row->subtype}"]) . ',' .
0 ignored issues
show
Bug introduced by
The variable $subtypes does not exist. Did you mean $subtype?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
390
                '"time_created":' . $row->time_created . ',' .
391
                '"url":' . json_encode(getURL($row)) . ',' .
392
                '"access_id":' . $row->access_id . ',' .
393
                '"time_updated":' . $row->time_updated . ',' .
394
                '"owner_guid":' . $row->owner_guid . ',' .
395
                '"container_guid":' . $row->container_guid . ',' .
396
                '"enabled":"' . $row->enabled . '",' .
397
                '"site_guid":' . $row->site_guid;
398
              if (!is_null($row->title)) {
399
                yield ',"title":' . json_encode($row->title) . ',' .
400
                  '"description":' . json_encode($row->description);
401
              }
402
              if (!is_null($row->group_name)) {
403
                yield ',"name":' . json_encode($row->group_name) . ',' .
404
                  '"description":' . json_encode($row->group_description);
405
              }
406
              if (!is_null($row->name)) {
407
                yield ',"name":' . json_encode($row->name) . ',' .
408
                  '"username":' . json_encode($row->username) . ',' .
409
                  '"language":"' . $row->language . '",' .
410
                  '"admin":"' . $row->admin . '",' .
411
                  '"banned":"' . $row->banned . '",' .
412
                  '"last_action":' . $row->user_last_action . ',' .
413
                  '"prev_last_action":' . $row->prev_last_action . ',' .
414
                  '"last_login":' . $row->last_login . ',' .
415
                  '"prev_last_login":' . $row->prev_last_login;
416
              } else {
417
                yield ',"last_action":' . $row->last_action;
418
              }
419
            }
420
            if (!is_null($row->meta_name)) yield outVal($row);
421
          }
422
          if (!$emit) {
423
            if ($row->guid == $resume) {
424
              $emit = true;
425
            }
426
          }
427
        }
428
        if ($currentGuid > 0) {
429
          $fin = finalizeEntity($currentGuid);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $fin is correct as finalizeEntity($currentGuid) (which targets finalizeEntity()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
430
          foreach ($fin as $fs) yield $fs;
0 ignored issues
show
Bug introduced by
The expression $fin of type null is not traversable.
Loading history...
431
        }
432
      } catch (Exception $e) {
433
        yield ',"error": ' . json_encode($e);
434
      }
435
    }
436
  );
437
  while ($data->valid()) {
438
    yield $data->current();
439
    $data->next();
440
  }
441
}
442
443
// Public key of server authorized to make requests against this API.
444
define('PUBLIC_KEY', "-----BEGIN PUBLIC KEY-----
445
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAmYj9ceaqHi7UmUmhE8e/
446
eU/02ZEJeLD8HN7Ku+VN8IB1dIwoSibvoxWZv5bfKnVajkGvud88TMNw3NwqO1jP
447
b2XiXs/1VvJkqHC/KYkd82iDUOdiDxvXtl8ZxVRA3m4WjtTIB8eJCZitc75fNrzl
448
fshoP0XQfbNQBBvfP7IBvPIhNuRPgmRMcDdzisqM+c2mAAzQQ04AZ11olhTZzYW0
449
HEx6vExkdNBXy/Q0pWas5Zvxe4eTONi7ls14GMKzMeecDnlbQh6P/dCf9ZGF06eM
450
biMSsnUiYeGsCgtAm9voq0omuVaDY6BDtlsJ50UyMnS5cCIkQrA1Vlt6g8MNt3jh
451
yXX8L0SxORCBiLGobFnxMSqvuxZkHjp7Jq/k4S3JK2mYxWlJHzcOB8yioI99ErqU
452
IO+2bqljuNe9v95bh3wu82UjhpU+gmbL5TMqR3mVGGH6mW2WJaRkujQL9hK/efde
453
V5T4oSM85QajxodYF4nsnhVjmQLzyDxQcVTyj6yQk+cwr68guOMkh389G29Kxgoi
454
otz1VvR5vYO5/KOFRDkELA8XLEIWtKmwYXTwmwzjX36GdeQpDny3JGJMlBPP7xVd
455
cBCzK/zh7Ize/pWhN5KSAhJ/a0jByClU0VtMD5d8da6dClWkO6k+Mg9nynSsIAOr
456
ALJ7RZP/EF2k6WwUtdrGluUCAwEAAQ==
457
-----END PUBLIC KEY-----
458
");
459
460
?>
0 ignored issues
show
Best Practice introduced by
It is not recommended to use PHP's closing tag ?> in files other than templates.

Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore.

A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.

Loading history...