diff --git a/lib/accesslib.php b/lib/accesslib.php index 29aac48d35720..81c5bca9cc8ed 100644 --- a/lib/accesslib.php +++ b/lib/accesslib.php @@ -4487,7 +4487,7 @@ function role_change_permission($roleid, $context, $capname, $permission) { * @property-read string $path path to context, starts with system context * @property-read dept $depth */ -abstract class context extends stdClass { +abstract class context extends stdClass implements IteratorAggregate { /* * Google confirms that no other important framework is using "context" class, @@ -4695,6 +4695,25 @@ public function __unset($name) { debugging('Can not unset context instance properties!'); } + // ====== implementing method from interface IteratorAggregate ====== + + /** + * Create an iterator because magic vars can't be seen by 'foreach'. + * + * Now we can convert context object to array using convert_to_array(), + * and feed it properly to json_encode(). + */ + public function getIterator() { + $ret = array( + 'id' => $this->id, + 'contextlevel' => $this->contextlevel, + 'instanceid' => $this->instanceid, + 'path' => $this->path, + 'depth' => $this->depth + ); + return new ArrayIterator($ret); + } + // ====== general context methods ====== /** diff --git a/lib/moodlelib.php b/lib/moodlelib.php index 36c4c7606523b..c9016c160db42 100644 --- a/lib/moodlelib.php +++ b/lib/moodlelib.php @@ -10081,6 +10081,40 @@ function object_property_exists( $obj, $property ) { return array_key_exists( $property, $properties ); } +/** + * Converts an object into an associative array + * + * This function converts an object into an associative array by iterating + * over its public properties. Because this function uses the foreach + * construct, Iterators are respected. It works recursively on arrays of objects. + * Arrays and simple values are returned as is. + * + * If class has magic properties, it can implement IteratorAggregate + * and return all available properties in getIterator() + * + * @param mixed $var + * @return array + */ +function convert_to_array($var) { + $result = array(); + $references = array(); + + // loop over elements/properties + foreach ($var as $key => $value) { + // recursively convert objects + if (is_object($value) || is_array($value)) { + // but prevent cycles + if (!in_array($value, $references)) { + $result[$key] = convert_to_array($value); + $references[] = $value; + } + } else { + // simple values are untouched + $result[$key] = $value; + } + } + return $result; +} /** * Detect a custom script replacement in the data directory that will diff --git a/lib/outputcomponents.php b/lib/outputcomponents.php index f87c4ac26ca89..337452af0b466 100644 --- a/lib/outputcomponents.php +++ b/lib/outputcomponents.php @@ -1589,7 +1589,7 @@ class js_writer { */ public static function function_call($function, array $arguments = null, $delay=0) { if ($arguments) { - $arguments = array_map('json_encode', $arguments); + $arguments = array_map('json_encode', convert_to_array($arguments)); $arguments = implode(', ', $arguments); } else { $arguments = ''; @@ -1611,7 +1611,7 @@ public static function function_call($function, array $arguments = null, $delay= */ public static function function_call_with_Y($function, array $extraarguments = null) { if ($extraarguments) { - $extraarguments = array_map('json_encode', $extraarguments); + $extraarguments = array_map('json_encode', convert_to_array($extraarguments)); $arguments = 'Y, ' . implode(', ', $extraarguments); } else { $arguments = 'Y'; @@ -1630,7 +1630,7 @@ public static function function_call_with_Y($function, array $extraarguments = n */ public static function object_init($var, $class, array $arguments = null, array $requirements = null, $delay=0) { if (is_array($arguments)) { - $arguments = array_map('json_encode', $arguments); + $arguments = array_map('json_encode', convert_to_array($arguments)); $arguments = implode(', ', $arguments); } diff --git a/lib/outputrequirementslib.php b/lib/outputrequirementslib.php index f7a5e8afd593f..834604ca89f62 100644 --- a/lib/outputrequirementslib.php +++ b/lib/outputrequirementslib.php @@ -715,7 +715,7 @@ public function yui_module($modules, $function, array $arguments = null, $galler // Set Y's config.gallery to the version $jscode = 'Y.config.gallery='.json_encode($galleryversion).';'; } - $jscode .= 'Y.use('.join(',', array_map('json_encode', $modules)).',function() {'.js_writer::function_call($function, $arguments).'});'; + $jscode .= 'Y.use('.join(',', array_map('json_encode', convert_to_array($modules))).',function() {'.js_writer::function_call($function, $arguments).'});'; if ($ondomready) { $jscode = "Y.on('domready', function() { $jscode });"; }