Changeset View
Changeset View
Standalone View
Standalone View
src/moduleutils/PhutilBootloader.php
| Show First 20 Lines • Show All 198 Lines • ▼ Show 20 Lines | final class PhutilBootloader { | ||||
| public function loadLibrary($path) { | public function loadLibrary($path) { | ||||
| $root = null; | $root = null; | ||||
| if (!empty($_SERVER['PHUTIL_LIBRARY_ROOT'])) { | if (!empty($_SERVER['PHUTIL_LIBRARY_ROOT'])) { | ||||
| if ($path[0] != '/') { | if ($path[0] != '/') { | ||||
| $root = $_SERVER['PHUTIL_LIBRARY_ROOT']; | $root = $_SERVER['PHUTIL_LIBRARY_ROOT']; | ||||
| } | } | ||||
| } | } | ||||
| $okay = $this->executeInclude($root.$path.'/__phutil_library_init__.php'); | |||||
| if (!$okay) { | $this->executeInclude($root.$path.'/__phutil_library_init__.php'); | ||||
| throw new PhutilBootloaderException( | |||||
| "Include of '{$path}/__phutil_library_init__.php' failed!"); | |||||
| } | |||||
| } | } | ||||
| public function loadLibrarySource($library, $source) { | public function loadLibrarySource($library, $source) { | ||||
| $path = $this->getLibraryRoot($library).'/'.$source; | $path = $this->getLibraryRoot($library).'/'.$source; | ||||
| $okay = $this->executeInclude($path); | $this->executeInclude($path); | ||||
| if (!$okay) { | |||||
| throw new PhutilBootloaderException("Include of '{$path}' failed!"); | |||||
| } | |||||
| } | } | ||||
| private function executeInclude($path) { | private function executeInclude($path) { | ||||
| // Suppress warning spew if the file does not exist; we'll throw an | // Include the source using `include_once`, but convert any warnings or | ||||
| // exception instead. We still emit error text in the case of syntax errors. | // errors into exceptions. | ||||
| $old = error_reporting(E_ALL & ~E_WARNING); | |||||
| // Some messages, including "Declaration of X should be compatible with Y", | |||||
| // do not cause `include_once` to return an error code. Use | |||||
| // error_get_last() to make sure we're catching everything in every PHP | |||||
| // version. | |||||
| // (Also, the severity of some messages changed between versions of PHP.) | |||||
| // Note that we may enter this method after some earlier, unrelated error. | |||||
| // In this case, error_get_last() will return information for that error. | |||||
| // In PHP7 and later we could use error_clear_last() to clear that error, | |||||
| // but the function does not exist in earlier versions of PHP. Instead, | |||||
| // check if the value has changed. | |||||
| // See also T12190. | |||||
| $old_last = error_get_last(); | |||||
| $old = error_reporting(0); | |||||
| $okay = include_once $path; | $okay = include_once $path; | ||||
| error_reporting($old); | error_reporting($old); | ||||
| return $okay; | if (!$okay) { | ||||
| throw new Exception("Source file \"{$path}\" failed to load."); | |||||
| } | |||||
| $new_last = error_get_last(); | |||||
| if ($new_last !== null) { | |||||
| if ($new_last !== $old_last) { | |||||
| $message = $new_last['message']; | |||||
| throw new Exception( | |||||
| "Error while loading file \"{$path}\": {$message}"); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| private function loadExtension($library, $root, $path) { | private function loadExtension($library, $root, $path) { | ||||
| $old_functions = get_defined_functions(); | $old_functions = get_defined_functions(); | ||||
| $old_functions = array_fill_keys($old_functions['user'], true); | $old_functions = array_fill_keys($old_functions['user'], true); | ||||
| $old_classes = array_fill_keys(get_declared_classes(), true); | $old_classes = array_fill_keys(get_declared_classes(), true); | ||||
| $old_interfaces = array_fill_keys(get_declared_interfaces(), true); | $old_interfaces = array_fill_keys(get_declared_interfaces(), true); | ||||
| $ok = $this->executeInclude($path); | $this->executeInclude($path); | ||||
| if (!$ok) { | |||||
| throw new PhutilBootloaderException( | |||||
| "Include of extension file '{$path}' failed!"); | |||||
| } | |||||
| $new_functions = get_defined_functions(); | $new_functions = get_defined_functions(); | ||||
| $new_functions = array_fill_keys($new_functions['user'], true); | $new_functions = array_fill_keys($new_functions['user'], true); | ||||
| $new_classes = array_fill_keys(get_declared_classes(), true); | $new_classes = array_fill_keys(get_declared_classes(), true); | ||||
| $new_interfaces = array_fill_keys(get_declared_interfaces(), true); | $new_interfaces = array_fill_keys(get_declared_interfaces(), true); | ||||
| $add_functions = array_diff_key($new_functions, $old_functions); | $add_functions = array_diff_key($new_functions, $old_functions); | ||||
| $add_classes = array_diff_key($new_classes, $old_classes); | $add_classes = array_diff_key($new_classes, $old_classes); | ||||
| ▲ Show 20 Lines • Show All 41 Lines • Show Last 20 Lines | |||||