diff --git a/.scripts/validate_commit_msg.php b/.scripts/validate_commit_msg.php index e6dc3266104..cc3a17d7d1a 100755 --- a/.scripts/validate_commit_msg.php +++ b/.scripts/validate_commit_msg.php @@ -18,7 +18,7 @@ $rootDir = dirname(__DIR__); - require_once "$rootDir/vendor/autoload.php"; + require_once "$rootDir/autoloader.php"; $is_file = false; diff --git a/autoloader.php b/autoloader.php new file mode 100644 index 00000000000..e825d9a9eba --- /dev/null +++ b/autoloader.php @@ -0,0 +1,34 @@ +` that are triggered on every page 4. pagesetup, system 5. shutdown, system -The *boot*, *system* event is triggered before the plugins get loaded. There does not appear to be any difference between the timing of the next two events: *plugins_boot*, *system* and *init*, *system* so plugins tend to use *init*, *system*. This event is triggered just after the plugins are loaded near the end of the boot script (``/engine/start.php``). The *pagesetup*, *system* event is thrown the first time ``elgg_view()`` is called. Some pages like the default ``index.php`` do not call ``elgg_view()`` so it is not triggered for them. The *shutdown*, *system* event is triggered after the page has been sent to the requester and is handled through the PHP function ``register_shutdown_function()``. +The *boot*, *system* event is triggered before the plugins get loaded. There does not appear to be any difference between the timing of the next two events: *plugins_boot*, *system* and *init*, *system* so plugins tend to use *init*, *system*. This event is triggered in ``Elgg\Application::bootCore``. The *pagesetup*, *system* event is thrown the first time ``elgg_view()`` is called. Some pages like the default ``index.php`` do not call ``elgg_view()`` so it is not triggered for them. The *shutdown*, *system* event is triggered after the page has been sent to the requester and is handled through the PHP function ``register_shutdown_function()``. There are :doc:`other events ` that are triggered by the Elgg core but they happen occasionally (such as when a user logs in). diff --git a/docs/guides/guidelines.rst b/docs/guides/guidelines.rst index 3f10415207c..1821d04aa8c 100644 --- a/docs/guides/guidelines.rst +++ b/docs/guides/guidelines.rst @@ -80,27 +80,19 @@ The object/ view Actions ------- -Actions are transient states to perform an action such as updating the database or sending a notification to a user. Used correctly, actions are secure and prevent against CSRF and XSS attacks. +Actions are transient states to perform an action such as updating the database or sending a notification to a user. Used correctly, actions provide a level of access control and prevent against CSRF attacks. -.. note:: +Actions require action (CSRF) tokens to be submitted via GET/POST, but these are added automatically by elgg_view_form() and by using the ``is_action`` argument of the ``output/url`` view. - As of Elgg 1.7 all actions require action tokens. - Action best practices ^^^^^^^^^^^^^^^^^^^^^ -Never call an action directly by saying: - -.. code:: html - - ...href="/mod/mymod/actions/myaction.php" - -This circumvents the security systems in Elgg. - -There is no need to include the ``engine/start.php`` file in your actions. Actions should never be called directly, so the engine will be started automatically when called correctly. +Action files are included within Elgg's action system; like views, they are *not* regular scripts executable by users. Do not boot the Elgg core in your file and direct users to load it directly. Because actions are time-sensitive they are not suitable for links in emails or other delayed notifications. An example of this would be invitations to join a group. The clean way to create an invitation link is to create a page handler for invitations and email that link to the user. It is then the page handler's responsibility to create the action links for a user to join or ignore the invitation request. +Consider that actions may be submitted via XHR requests, not just links or form submissions. + Directly calling a file ----------------------- diff --git a/docs/guides/pagehandler.rst b/docs/guides/pagehandler.rst index 3e9683e6ce1..c1df50d4896 100644 --- a/docs/guides/pagehandler.rst +++ b/docs/guides/pagehandler.rst @@ -15,7 +15,7 @@ The plugin's page handler is passed two parameters: Code flow --------- -Pages in plugins should be served only through page handlers, stored in ``pages/`` of your plugin's directory and do not need to ``include`` or ``require`` Elgg's ``engine/start.php`` file. The purpose of these files are to knit together output from different views to form the page that the user sees. The program flow is something like this: +Pages in plugins should be served only through page handlers, stored in ``pages/`` of your plugin's directory and do not need to use ``Elgg\Application``. The purpose of these files are to knit together output from different views to form the page that the user sees. The program flow is something like this: 1. A user requests ``/plugin_name/section/entity`` 2. Elgg checks if ``plugin_name`` is registered to a page handler and calls that function, passing ``array('section', 'entity')`` as the first argument diff --git a/docs/guides/upgrading.rst b/docs/guides/upgrading.rst index 5531854d0c8..df30226406e 100644 --- a/docs/guides/upgrading.rst +++ b/docs/guides/upgrading.rst @@ -12,12 +12,14 @@ See the administrator guides for :doc:`how to upgrade a live site bootCore(); + From 1.10 to 1.11 ================= diff --git a/docs/guides/views.rst b/docs/guides/views.rst index 1b9e8172075..74fe6d2eec2 100644 --- a/docs/guides/views.rst +++ b/docs/guides/views.rst @@ -166,7 +166,7 @@ Note that if you extend the core css view like this: elgg_extend_view('css', 'custom/css'); -You **must** do so within code that is executed by engine/start.php (normally this would mean your plugin's init code). Because the core css view is loaded separately via a ```` tag, any extensions you add will not have the same context as the rest of your page. +You **must** do so within your plugin's init code. Because the core css view is loaded separately via a ```` tag, any extensions you add will not have the same context as the rest of your page. .. _guides/views#altering-view-input: diff --git a/engine/classes/Elgg/Application.php b/engine/classes/Elgg/Application.php new file mode 100644 index 00000000000..6949b2a762d --- /dev/null +++ b/engine/classes/Elgg/Application.php @@ -0,0 +1,349 @@ +services = $services; + + /** + * The time with microseconds when the Elgg engine was started. + * + * @global float + */ + global $START_MICROTIME; + if (!isset($START_MICROTIME)) { + $START_MICROTIME = microtime(true); + } + + $this->engine_dir = dirname(dirname(__DIR__)); + $this->install_dir = dirname($this->engine_dir); + } + + /** + * Get the service provider + * + * Developers should not use this function + * + * @return ServiceProvider + * @internal + * @access private + */ + public function getServices() { + return $this->services; + } + + /** + * Load settings.php + * + * This is done automatically during the boot process or before requesting a database object + * + * @see Config::loadSettingsFile + * @return void + */ + public function loadSettings() { + $this->services->config->loadSettingsFile(); + } + + /** + * Get the Elgg\Config object (not global $CONFIG) + * + * @note Before application boot, it may be unsafe to call Elgg\Config::get for some values. You should use + * Elgg\Config::getVolatile before system boot. + * + * @return Config + */ + public function getConfig() { + return $this->services->config; + } + + /** + * Load all Elgg procedural code and wire up boot events, but don't boot + * + * This is used for internal testing purposes + * + * @return void + * @access private + * @internal + */ + public function loadCore() { + if (function_exists('_elgg_services')) { + return; + } + + $lib_dir = $this->engine_dir . "/lib"; + + // we only depend on it to be defining _elgg_services function + require_once "$lib_dir/autoloader.php"; + + // set up autoloading and DIC + _elgg_services($this->services); + + // load the rest of the library files from engine/lib/ + // All on separate lines to make diffs easy to read + make it apparent how much + // we're actually loading on every page (Hint: it's too much). + $lib_files = array( + // Needs to be loaded first to correctly bootstrap + 'elgglib.php', + + // The order of these doesn't matter, so keep them alphabetical + 'access.php', + 'actions.php', + 'admin.php', + 'annotations.php', + 'cache.php', + 'comments.php', + 'configuration.php', + 'cron.php', + 'database.php', + 'entities.php', + 'extender.php', + 'filestore.php', + 'friends.php', + 'group.php', + 'input.php', + 'languages.php', + 'mb_wrapper.php', + 'memcache.php', + 'metadata.php', + 'metastrings.php', + 'navigation.php', + 'notification.php', + 'objects.php', + 'output.php', + 'pagehandler.php', + 'pageowner.php', + 'pam.php', + 'plugins.php', + 'private_settings.php', + 'relationships.php', + 'river.php', + 'sessions.php', + 'sites.php', + 'statistics.php', + 'system_log.php', + 'tags.php', + 'user_settings.php', + 'users.php', + 'upgrade.php', + 'views.php', + 'widgets.php', + + // backward compatibility + 'deprecated-1.7.php', + 'deprecated-1.8.php', + 'deprecated-1.9.php', + 'deprecated-1.10.php', + ); + + // isolate global scope + call_user_func(function () use ($lib_dir, $lib_files) { + + $setups = array(); + + // include library files, capturing setup functions + foreach ($lib_files as $file) { + $setup = (require_once "$lib_dir/$file"); + + if ($setup instanceof \Closure) { + $setups[$file] = $setup; + } + } + + $events = $this->services->events; + $hooks = $this->services->hooks; + + // run setups + foreach ($setups as $func) { + $func($events, $hooks); + } + }); + } + + /** + * Bootstrap the Elgg engine, loads plugins, and calls initial system events + * + * This method loads the full Elgg engine, checks the installation + * state, and triggers a series of events to finish booting Elgg: + * - {@elgg_event boot system} + * - {@elgg_event init system} + * - {@elgg_event ready system} + * + * If Elgg is not fully installed, the browser will be redirected to an installation page. + * + * @see install.php + * @return void + */ + public function bootCore() { + $config = $this->services->config; + + if ($config->getVolatile('boot_complete')) { + return; + } + + $this->loadSettings(); + + $config->set('boot_complete', false); + + // This will be overridden by the DB value but may be needed before the upgrade script can be run. + $config->set('default_limit', 10); + + // in case not loaded already + $this->loadCore(); + + $events = $this->services->events; + + // Connect to database, load language files, load configuration, init session + // Plugins can't use this event because they haven't been loaded yet. + $events->trigger('boot', 'system'); + + // Load the plugins that are active + $this->services->plugins->load(); + + // @todo move loading plugins into a single boot function that replaces 'boot', 'system' event + // and then move this code in there. + // This validates the view type - first opportunity to do it is after plugins load. + $viewtype = elgg_get_viewtype(); + if (!elgg_is_registered_viewtype($viewtype)) { + elgg_set_viewtype('default'); + } + + // @todo deprecate as plugins can use 'init', 'system' event + $events->trigger('plugins_boot', 'system'); + + // Complete the boot process for both engine and plugins + $events->trigger('init', 'system'); + + $config->set('boot_complete', true); + + // System loaded and ready + $events->trigger('ready', 'system'); + } + + /** + * Get the Database instance for performing queries with minimal resources loaded + * + * If settings.php has not been loaded, it will be loaded to configure the DB connection. + * + * Note: Before boot, the Database instance will not yet be bound to a Logger. + * + * @return Database + */ + public function getDb() { + $this->loadSettings(); + return $this->services->db; + } + + /** + * Rewrite rules for PHP cli webserver used for testing. Do not use on production sites + * as normal web server replacement. + * + * You need to explicitly point to index.php in order for router to work properly: + * + * php -S localhost:8888 index.php + * + * @return bool True if Elgg's router will handle the file, false if PHP should serve it directly + */ + protected function runPhpWebServer() { + $urlPath = parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH); + + if (preg_match('/^\/cache\/(.*)$/', $urlPath, $matches)) { + $_GET['request'] = $matches[1]; + $handler = new CacheHandler($this); + $handler->handleRequest($_GET, $_SERVER); + exit; + } + + if (preg_match('/^\/export\/([A-Za-z]+)\/([0-9]+)\/?$/', $urlPath, $matches)) { + $_GET['view'] = $matches[1]; + $_GET['guid'] = $matches[2]; + require "{$this->engine_dir}/handlers/export_handler.php"; + exit; + } + + if (preg_match('/^\/export\/([A-Za-z]+)\/([0-9]+)\/([A-Za-z]+)\/([A-Za-z0-9\_]+)\/$/', $urlPath, $matches)) { + $_GET['view'] = $matches[1]; + $_GET['guid'] = $matches[2]; + $_GET['type'] = $matches[3]; + $_GET['idname'] = $matches[4]; + require "{$this->engine_dir}/handlers/export_handler.php"; + exit; + } + + if (preg_match("/^\/rewrite.php$/", $urlPath, $matches)) { + require "{$this->install_dir}/install.php"; + exit; + } + + if ($urlPath !== '/' && file_exists($this->install_dir . $urlPath)) { + // serve the requested resource as-is. + return false; + } + + $_GET['__elgg_uri'] = $urlPath; + return true; + } + + /** + * Routes the request, booting core if not yet booted + * + * @return bool False if Elgg wants the PHP CLI server to handle the request + */ + public function run() { + if (php_sapi_name() === 'cli-server') { + if (!$this->runPhpWebServer()) { + // PHP will serve this file directly + return false; + } + } + + // allow testing from the upgrade page before the site is upgraded. + if (isset($_GET['__testing_rewrite'])) { + if (isset($_GET['__elgg_uri']) && false !== strpos($_GET['__elgg_uri'], '__testing_rewrite')) { + echo "success"; + } + return true; + } + + $this->bootCore(); + + if (!$this->services->router->route($this->services->request)) { + forward('', '404'); + } + + return true; + } +} diff --git a/engine/classes/Elgg/AutoloadManager.php b/engine/classes/Elgg/AutoloadManager.php index 3b687cbef29..b9b88e69131 100644 --- a/engine/classes/Elgg/AutoloadManager.php +++ b/engine/classes/Elgg/AutoloadManager.php @@ -193,5 +193,14 @@ public function getLoader() { public function setStorage(\ElggCache $storage) { $this->storage = $storage; } + + /** + * Save the cache on object destruction + * + * @return void + */ + public function __destruct() { + $this->saveCache(); + } } diff --git a/engine/classes/Elgg/CacheHandler.php b/engine/classes/Elgg/CacheHandler.php index a91b469770d..8b439493c71 100644 --- a/engine/classes/Elgg/CacheHandler.php +++ b/engine/classes/Elgg/CacheHandler.php @@ -10,15 +10,18 @@ */ class CacheHandler { - protected $config; + /** + * @var Application + */ + private $application; /** * Constructor * - * @param \stdClass $config Elgg config object + * @param Application $app Elgg Application */ - public function __construct($config) { - $this->config = $config; + public function __construct(Application $app) { + $this->application = $app; } /** @@ -29,6 +32,8 @@ public function __construct($config) { * @return void */ public function handleRequest($get_vars, $server_vars) { + $config = $this->application->getConfig(); + if (empty($get_vars['request'])) { $this->send403(); } @@ -45,8 +50,11 @@ public function handleRequest($get_vars, $server_vars) { // this may/may not have to connect to the DB $this->setupSimplecache(); - if (!$this->config->simplecache_enabled) { - $this->loadEngine(); + // we can't use $config->get yet. It fails before the core is booted + if (!$config->getVolatile('simplecache_enabled')) { + + $this->application->bootCore(); + if (!_elgg_is_view_cacheable($view)) { $this->send403(); } else { @@ -62,28 +70,28 @@ public function handleRequest($get_vars, $server_vars) { exit; } - $filename = $this->config->dataroot . 'views_simplecache/' . md5("$viewtype|$view"); + $filename = $config->getVolatile('dataroot') . 'views_simplecache/' . md5("$viewtype|$view"); if (file_exists($filename)) { $this->sendCacheHeaders($etag); readfile($filename); exit; } - $this->loadEngine(); + $this->application->bootCore(); elgg_set_viewtype($viewtype); if (!_elgg_is_view_cacheable($view)) { $this->send403(); } - $cache_timestamp = (int)_elgg_services()->config->get('lastcache'); + $cache_timestamp = (int)$config->get('lastcache'); if ($cache_timestamp == $ts) { $this->sendCacheHeaders($etag); $content = $this->getProcessedView($view, $viewtype); - $dir_name = $this->config->dataroot . 'views_simplecache/'; + $dir_name = $config->getDataPath() . 'views_simplecache/'; if (!is_dir($dir_name)) { mkdir($dir_name, 0700); } @@ -134,12 +142,16 @@ public function parseRequestVar($request_var) { * @return void */ protected function setupSimplecache() { - if (!empty($this->config->dataroot) && isset($this->config->simplecache_enabled)) { + // we can't use Elgg\Config::get yet. It fails before the core is booted + $config = $this->application->getConfig(); + $config->loadSettingsFile(); + + if ($config->getVolatile('dataroot') && $config->getVolatile('simplecache_enabled') !== null) { + // we can work with these... return; } - $db_config = new Database\Config($this->config); - $db = new Database($db_config, new Logger(new PluginHooksService())); + $db = $this->application->getDb(); try { $rows = $db->getData(" @@ -160,10 +172,10 @@ protected function setupSimplecache() { } foreach ($rows as $row) { - $this->config->{$row->name} = $row->value; + $config->set($row->name, $row->value); } - if (empty($this->config->dataroot)) { + if (!$config->getVolatile('dataroot')) { $this->send403('Cache error: unable to get the data root'); } } @@ -234,7 +246,7 @@ protected function renderView($view, $viewtype) { } // disable error reporting so we don't cache problems - _elgg_services()->config->set('debug', null); + $this->application->getConfig()->set('debug', null); // @todo elgg_view() checks if the page set is done (isset($CONFIG->pagesetupdone)) and // triggers an event if it's not. Calling elgg_view() here breaks submenus @@ -242,20 +254,11 @@ protected function renderView($view, $viewtype) { // contexts can be correctly set (since this is called before page_handler()). // To avoid this, lie about $CONFIG->pagehandlerdone to force // the trigger correctly when the first view is actually being output. - _elgg_services()->config->set('pagesetupdone', true); + $this->application->getConfig()->set('pagesetupdone', true); return elgg_view($view); } - /** - * Load the complete Elgg engine - * - * @return void - */ - protected function loadEngine() { - require_once dirname(dirname(dirname(__FILE__))) . "/start.php"; - } - /** * Send an error message to requestor * diff --git a/engine/classes/Elgg/Config.php b/engine/classes/Elgg/Config.php index 7323dba72b8..9a5a505b3c0 100644 --- a/engine/classes/Elgg/Config.php +++ b/engine/classes/Elgg/Config.php @@ -13,18 +13,46 @@ */ class Config { /** - * Global Elgg configuration + * Configuration storage. Is usually reference to global $CONFIG * * @var \stdClass */ - private $CONFIG; + private $config; + + /** + * @var bool + */ + private $settings_loaded = false; /** * Constructor + * + * @param \stdClass $config Elgg's $CONFIG object + * @param bool $set_global Copy the config object to global $CONFIG */ - public function __construct() { - global $CONFIG; - $this->CONFIG = $CONFIG; + public function __construct(\stdClass $config = null, $set_global = true) { + if (!$config) { + $config = new \stdClass(); + } + $this->config = $config; + + if ($set_global) { + /** + * Configuration values. + * + * The $CONFIG global contains configuration values required + * for running Elgg as defined in the settings.php file. + * + * Plugin authors are encouraged to use elgg_get_config() instead of accessing + * the global directly. + * + * @see elgg_get_config() + * @see engine/settings.php + * @global \stdClass $CONFIG + */ + global $CONFIG; + $CONFIG = $config; + } } /** @@ -33,10 +61,9 @@ public function __construct() { * @param int $site_guid The GUID of the site whose URL we want to grab * @return string */ - function getSiteUrl($site_guid = 0) { + public function getSiteUrl($site_guid = 0) { if ($site_guid == 0) { - - return $this->CONFIG->wwwroot; + return $this->config->wwwroot; } $site = get_entity($site_guid); @@ -54,9 +81,8 @@ function getSiteUrl($site_guid = 0) { * * @return string */ - function getPluginsPath() { - - return $this->CONFIG->pluginspath; + public function getPluginsPath() { + return $this->config->pluginspath; } /** @@ -64,9 +90,8 @@ function getPluginsPath() { * * @return string */ - function getDataPath() { - - return $this->CONFIG->dataroot; + public function getDataPath() { + return $this->config->dataroot; } /** @@ -74,27 +99,24 @@ function getDataPath() { * * @return string */ - function getRootPath() { - - return $this->CONFIG->path; + public function getRootPath() { + return $this->config->path; } - + /** - * Get an Elgg configuration value + * Get an Elgg configuration value, possibly loading it from the DB's config table * * @param string $name Name of the configuration value * @param int $site_guid null for installation setting, 0 for default site * * @return mixed Configuration value or null if it does not exist */ - function get($name, $site_guid = 0) { - - + public function get($name, $site_guid = 0) { $name = trim($name); - // do not return $CONFIG value if asking for non-current site - if (($site_guid === 0 || $site_guid === null || $site_guid == $this->CONFIG->site_guid) && isset($this->CONFIG->$name)) { - return $this->CONFIG->$name; + // do not return $config value if asking for non-current site + if (($site_guid === 0 || $site_guid === null || $site_guid == $this->config->site_guid) && isset($this->config->$name)) { + return $this->config->$name; } if ($site_guid === null) { @@ -102,11 +124,11 @@ function get($name, $site_guid = 0) { $value = _elgg_services()->datalist->get($name); } else { if ($site_guid == 0) { - $site_guid = (int) $this->CONFIG->site_guid; + $site_guid = (int) $this->config->site_guid; } // hit DB only if we're not sure if value isn't already loaded - if (!isset($this->CONFIG->site_config_loaded) || $site_guid != $this->CONFIG->site_guid) { + if (!isset($this->config->site_config_loaded) || $site_guid != $this->config->site_guid) { // site specific setting $value = _elgg_services()->configTable->get($name, $site_guid); } else { @@ -119,12 +141,24 @@ function get($name, $site_guid = 0) { return null; } - if ($site_guid == $this->CONFIG->site_guid || $site_guid === null) { - $this->CONFIG->$name = $value; + if ($site_guid == $this->config->site_guid || $site_guid === null) { + $this->config->$name = $value; } return $value; } + + /** + * Get a config value for the current site if it's already loaded. This should be used instead of + * reading directly from global $CONFIG. + * + * @param string $name Name of the configuration value + * + * @return mixed Returns null if value isn't set + */ + public function getVolatile($name) { + return isset($this->config->{$name}) ? $this->config->{$name} : null; + } /** * Set an Elgg configuration value @@ -136,12 +170,9 @@ function get($name, $site_guid = 0) { * * @return void */ - function set($name, $value) { - - + public function set($name, $value) { $name = trim($name); - - $this->CONFIG->$name = $value; + $this->config->$name = $value; } /** @@ -153,9 +184,7 @@ function set($name, $value) { * * @return bool */ - function save($name, $value, $site_guid = 0) { - - + public function save($name, $value, $site_guid = 0) { $name = trim($name); if (strlen($name) > 255) { @@ -170,15 +199,87 @@ function save($name, $value, $site_guid = 0) { $result = _elgg_services()->datalist->set($name, $value); } else { if ($site_guid == 0) { - $site_guid = (int) $this->CONFIG->site_guid; + $site_guid = (int) $this->config->site_guid; } $result = _elgg_services()->configTable->set($name, $value, $site_guid); } - if ($site_guid === null || $site_guid == $this->CONFIG->site_guid) { - _elgg_services()->config->set($name, $value); + if ($site_guid === null || $site_guid == $this->config->site_guid) { + $this->set($name, $value); } return $result; } + + /** + * Merge the settings file into the storage object + * + * A particular location can be specified via $CONFIG->Config_file + * + * To skip settings loading, set $CONFIG->Config_file to false + * + * @return void + */ + public function loadSettingsFile() { + if ($this->settings_loaded) { + return; + } + + if (isset($this->config->Config_file)) { + if ($this->config->Config_file === false) { + $this->settings_loaded = true; + return; + } + $path = $this->config->Config_file; + } else { + $path = dirname(dirname(__DIR__)) . '/settings.php'; + } + + // No settings means a fresh install + if (!is_file($path)) { + header("Location: install.php"); + exit; + } + + if (!is_readable($path)) { + echo "The Elgg settings file exists but the web server doesn't have read permission to it."; + exit; + } + + // we assume settings is going to write to CONFIG, but we may need to copy its values + // into our local config + global $CONFIG; + $global_is_bound = (isset($CONFIG) && $CONFIG === $this->config); + + require_once $path; + + // normalize commonly needed values + if (isset($CONFIG->dataroot)) { + $CONFIG->dataroot = rtrim($CONFIG->dataroot, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; + } + + if (!$global_is_bound) { + // must manually copy settings into our storage + foreach ($CONFIG as $key => $value) { + $this->config->{$key} = $value; + } + } + + $this->settings_loaded = true; + } + + /** + * Get the raw \stdClass object used for storage. + * + * We need this, for now, to construct some services. + * + * @internal Do not use this plugins or new core code! + * @todo Get rid of this. + * + * @return \stdClass + * @access private + */ + public function getStorageObject() { + return $this->config; + } } \ No newline at end of file diff --git a/engine/classes/Elgg/Database.php b/engine/classes/Elgg/Database.php index e5bf67891b7..b98dd1a5dec 100644 --- a/engine/classes/Elgg/Database.php +++ b/engine/classes/Elgg/Database.php @@ -1,6 +1,5 @@ logger = $logger; $this->config = $config; @@ -83,6 +82,16 @@ public function __construct(\Elgg\Database\Config $config, \Elgg\Logger $logger) $this->enableQueryCache(); } + /** + * Set the logger object + * + * @param \Elgg\Logger $logger The logger + * @return void + */ + public function setLogger(\Elgg\Logger $logger) { + $this->logger = $logger; + } + /** * Gets (if required, also creates) a database link resource. * @@ -205,7 +214,9 @@ public function getDataRow($query, $callback = '') { */ public function insertData($query) { - $this->logger->log("DB query $query", \Elgg\Logger::INFO); + if ($this->logger) { + $this->logger->info("DB query $query"); + } $dblink = $this->getLink('write'); @@ -231,7 +242,9 @@ public function insertData($query) { */ public function updateData($query, $getNumRows = false) { - $this->logger->log("DB query $query", \Elgg\Logger::INFO); + if ($this->logger) { + $this->logger->info("DB query $query"); + } $dblink = $this->getLink('write'); @@ -260,7 +273,9 @@ public function updateData($query, $getNumRows = false) { */ public function deleteData($query) { - $this->logger->log("DB query $query", \Elgg\Logger::INFO); + if ($this->logger) { + $this->logger->info("DB query $query"); + } $dblink = $this->getLink('write'); @@ -334,7 +349,9 @@ protected function getResults($query, $callback = null, $single = false) { // Is cached? if ($this->queryCache) { if (isset($this->queryCache[$hash])) { - $this->logger->log("DB query $query results returned from cache (hash: $hash)", \Elgg\Logger::INFO); + if ($this->logger) { + $this->logger->info("DB query $query results returned from cache (hash: $hash)"); + } return $this->queryCache[$hash]; } } @@ -357,14 +374,16 @@ protected function getResults($query, $callback = null, $single = false) { } } - if (empty($return)) { - $this->logger->log("DB query $query returned no results.", \Elgg\Logger::INFO); + if (empty($return) && $this->logger) { + $this->logger->info("DB query $query returned no results."); } // Cache result if ($this->queryCache) { $this->queryCache[$hash] = $return; - $this->logger->log("DB query $query results cached (hash: $hash)", \Elgg\Logger::INFO); + if ($this->logger) { + $this->logger->info("DB query $query results cached (hash: $hash)"); + } } return $return; @@ -383,7 +402,7 @@ protected function getResults($query, $callback = null, $single = false) { * @throws \DatabaseException * @todo should this be public? */ - public function executeQuery($query, $dblink) { + protected function executeQuery($query, $dblink) { if ($query == null) { throw new \DatabaseException("Query cannot be null"); @@ -513,9 +532,9 @@ public function executeDelayedQueries() { if ($link == 'read' || $link == 'write') { $link = $this->getLink($link); - } elseif (!is_resource($link)) { + } elseif (!is_resource($link) && $this->logger) { $msg = "Link for delayed query not valid resource or db_link type. Query: {$query_details['q']}"; - $this->logger->log($msg, \Elgg\Logger::WARNING); + $this->logger->warn($msg); } $result = $this->executeQuery($query_details['q'], $link); @@ -524,8 +543,10 @@ public function executeDelayedQueries() { $query_details['h']($result); } } catch (\DatabaseException $e) { - // Suppress all exceptions since page already sent to requestor - $this->logger->log($e, \Elgg\Logger::ERROR); + if ($this->logger) { + // Suppress all exceptions since page already sent to requestor + $this->logger->error($e); + } } } } @@ -564,7 +585,9 @@ public function disableQueryCache() { protected function invalidateQueryCache() { if ($this->queryCache) { $this->queryCache->clear(); - $this->logger->log("Query cache invalidated", \Elgg\Logger::INFO); + if ($this->logger) { + $this->logger->info("Query cache invalidated"); + } } } diff --git a/engine/classes/Elgg/Di/ServiceProvider.php b/engine/classes/Elgg/Di/ServiceProvider.php index 9d7e96d934e..46045db11c9 100644 --- a/engine/classes/Elgg/Di/ServiceProvider.php +++ b/engine/classes/Elgg/Di/ServiceProvider.php @@ -18,6 +18,7 @@ * @property-read \Elgg\Amd\Config $amdConfig * @property-read \Elgg\Database\Annotations $annotations * @property-read \ElggAutoP $autoP + * @property-read \Elgg\ClassLoader $classLoader * @property-read \Elgg\AutoloadManager $autoloadManager * @property-read \ElggCrypto $crypto * @property-read \Elgg\Config $config @@ -63,11 +64,25 @@ class ServiceProvider extends \Elgg\Di\DiContainer { /** * Constructor - * - * @param \Elgg\AutoloadManager $autoload_manager Class autoloader + * + * @param \Elgg\Config $config Elgg Config service */ - public function __construct(\Elgg\AutoloadManager $autoload_manager) { - $this->setValue('autoloadManager', $autoload_manager); + public function __construct(\Elgg\Config $config) { + + $this->setFactory('classLoader', function(ServiceProvider $c) { + $loader = new \Elgg\ClassLoader(new \Elgg\ClassMap()); + $loader->register(); + return $loader; + }); + + $this->setFactory('autoloadManager', function(ServiceProvider $c) { + $manager = new \Elgg\AutoloadManager($c->classLoader); + if (!$c->config->get('AutoloaderManager_skip_storage')) { + $manager->setStorage($c->systemCache->getFileCache()); + $manager->loadCache(); + } + return $manager; + }); $this->setFactory('accessCache', function(ServiceProvider $c) { return new \ElggStaticVariableCache('access'); @@ -91,7 +106,7 @@ public function __construct(\Elgg\AutoloadManager $autoload_manager) { $this->setClassName('autoP', '\ElggAutoP'); - $this->setClassName('config', '\Elgg\Config'); + $this->setValue('config', $config); $this->setClassName('configTable', '\Elgg\Database\ConfigTable'); @@ -108,9 +123,10 @@ public function __construct(\Elgg\AutoloadManager $autoload_manager) { }); $this->setFactory('db', function(ServiceProvider $c) { - global $CONFIG; - $db_config = new \Elgg\Database\Config($CONFIG); - return new \Elgg\Database($db_config, $c->logger); + $db_config = new \Elgg\Database\Config($c->config->getStorageObject()); + + // we inject the logger in _elgg_engine_boot() + return new \Elgg\Database($db_config); }); $this->setFactory('deprecation', function(ServiceProvider $c) { @@ -126,8 +142,7 @@ public function __construct(\Elgg\AutoloadManager $autoload_manager) { }); $this->setFactory('externalFiles', function(ServiceProvider $c) { - global $CONFIG; - return new \Elgg\Assets\ExternalFiles($CONFIG); + return new \Elgg\Assets\ExternalFiles($c->config->getStorageObject()); }); $this->setFactory('hooks', function(ServiceProvider $c) { @@ -165,7 +180,7 @@ public function __construct(\Elgg\AutoloadManager $autoload_manager) { }); $this->setFactory('persistentLogin', function(ServiceProvider $c) { - $global_cookies_config = _elgg_services()->config->get('cookies'); + $global_cookies_config = $c->config->get('cookies'); $cookie_config = $global_cookies_config['remember_me']; $cookie_name = $cookie_config['name']; $cookie_token = $c->request->cookies->get($cookie_name, ''); diff --git a/engine/classes/Elgg/ViewsService.php b/engine/classes/Elgg/ViewsService.php index 56db6468818..ff5c41582d1 100644 --- a/engine/classes/Elgg/ViewsService.php +++ b/engine/classes/Elgg/ViewsService.php @@ -246,7 +246,7 @@ public function renderView($view, array $vars = array(), $bypass = false, $viewt $view_orig = $view; // Trigger the pagesetup event - if (!isset($this->CONFIG->pagesetupdone) && $this->CONFIG->boot_complete) { + if (!isset($this->CONFIG->pagesetupdone) && !empty($this->CONFIG->boot_complete)) { $this->CONFIG->pagesetupdone = true; _elgg_services()->events->trigger('pagesetup', 'system'); } diff --git a/engine/classes/ElggInstaller.php b/engine/classes/ElggInstaller.php index df34641edc4..c2444105547 100644 --- a/engine/classes/ElggInstaller.php +++ b/engine/classes/ElggInstaller.php @@ -165,6 +165,7 @@ public function batchInstall(array $params, $createHtaccess = FALSE) { 'dbprefix' => 'elgg_', 'language' => 'en', 'siteaccess' => ACCESS_PUBLIC, + 'site_guid' => 1, ); $params = array_merge($defaults, $params); @@ -737,9 +738,9 @@ protected function resumeInstall($step) { * @return void */ protected function bootstrapEngine() { - - - require_once $this->CONFIG->path . 'engine/load.php'; + $config = new \Elgg\Config($this->CONFIG); + $services = new \Elgg\Di\ServiceProvider($config); + (new \Elgg\Application($services))->loadCore(); } /** @@ -862,7 +863,7 @@ protected function bootstrapConfig() { */ private function isHttps() { return (!empty($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on") || - $_SERVER['SERVER_PORT'] == 443; + (!empty($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443); } /** diff --git a/engine/handlers/cache_handler.php b/engine/handlers/cache_handler.php index 72d5077c0aa..3b4860f3ff1 100644 --- a/engine/handlers/cache_handler.php +++ b/engine/handlers/cache_handler.php @@ -14,21 +14,7 @@ * @subpackage Cache */ -// we need to load a few Elgg classes, but this is much lighter than /vendor/autoload.php -spl_autoload_register(function ($class) { - $file = dirname(__DIR__) . '/classes/' . strtr(ltrim($class, '\\'), '_\\', '//') . '.php'; - is_readable($file) && (require $file); -}); - -require_once dirname(dirname(__FILE__)) . '/settings.php'; -/* @var \stdClass $CONFIG */ - -// dataroot must have trailing slash -// @todo need a lib with core functions that have no depedencies -if (isset($CONFIG->dataroot)) { - $CONFIG->dataroot = rtrim($CONFIG->dataroot, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; -} - -$handler = new \Elgg\CacheHandler($CONFIG); +require_once dirname(dirname(__DIR__)) . '/autoloader.php'; +$handler = new \Elgg\CacheHandler(new Elgg\Application()); $handler->handleRequest($_GET, $_SERVER); diff --git a/engine/handlers/export_handler.php b/engine/handlers/export_handler.php index dee39f40e7f..c31f066ebba 100644 --- a/engine/handlers/export_handler.php +++ b/engine/handlers/export_handler.php @@ -6,8 +6,15 @@ * @subpackage Export */ -require_once(dirname(dirname(__FILE__)) . "/start.php"); - +if (isset($this)) { + // loaded from the PHP CLI application in Elgg\Application + /* @var Elgg\Application $this */ + $this->bootCore(); +} else { + require_once dirname(dirname(__DIR__)) . '/autoloader.php'; + $application = new Elgg\Application(); + $application->bootCore(); +} // Get input values, these will be mapped via modrewrite $guid = get_input("guid"); // guid of the entity diff --git a/engine/lib/actions.php b/engine/lib/actions.php index 39b111d28e0..b207cbf2098 100644 --- a/engine/lib/actions.php +++ b/engine/lib/actions.php @@ -64,7 +64,7 @@ function action($action, $forwarder = "") { * * @tip Put action files under the actions/ directory of your plugin. * - * @tip You don't need to include engine/start.php in your action files. + * @tip You don't need to use Elgg\Application in your action files. * * @internal Actions are saved in $CONFIG->actions as an array in the form: * diff --git a/engine/lib/autoloader.php b/engine/lib/autoloader.php index 3636504b243..7fe127db883 100644 --- a/engine/lib/autoloader.php +++ b/engine/lib/autoloader.php @@ -8,59 +8,18 @@ */ /** - * @return \Elgg\Di\ServiceProvider - * @access private - */ -function _elgg_services() { - static $provider; - if (null === $provider) { - $provider = _elgg_create_service_provider(); - } - return $provider; -} - -/** - * Sets up autoloading and creates the service provider (DIC) - * - * Setup global class map and loader instances and add the core classes to the map. - * We can't load this from dataroot because we don't know it yet, and we'll need - * several classes before we can find out! - * - * @throws RuntimeException - * @access private - */ -function _elgg_create_service_provider() { - $loader = new \Elgg\ClassLoader(new \Elgg\ClassMap()); - // until the cache can be loaded, just setup PSR-0 autoloading - // out of the classes directory. No need to build a full map. - $loader->register(); - $manager = new \Elgg\AutoloadManager($loader); - - return new \Elgg\Di\ServiceProvider($manager); -} - -/** - * Load cached data into the autoload system - * - * Note this has to wait until Elgg's data path is known. + * Get the global service provider * + * @param \Elgg\Di\ServiceProvider $services Elgg service provider. This must be set by the application. + * @return \Elgg\Di\ServiceProvider * @access private */ -function _elgg_load_autoload_cache() { - $manager = _elgg_services()->autoloadManager; - $manager->setStorage(elgg_get_system_cache()); - if (! $manager->loadCache()) { - $manager->addClasses(dirname(dirname(__FILE__)) . '/classes'); +function _elgg_services(\Elgg\Di\ServiceProvider $services = null) { + static $inst; + if ($services !== null) { + $inst = $services; } -} - -/** - * Save the autoload system cache - * - * @access private - */ -function _elgg_save_autoload_cache() { - _elgg_services()->autoloadManager->saveCache(); + return $inst; } /** @@ -78,7 +37,7 @@ function _elgg_delete_autoload_cache() { * @return \Elgg\ClassLoader */ function elgg_get_class_loader() { - return _elgg_services()->autoloadManager->getLoader(); + return _elgg_services()->classLoader; } /** @@ -112,6 +71,5 @@ function elgg_register_class($class, $location) { } return function(\Elgg\EventsService $events, \Elgg\HooksRegistrationService $hooks) { - $events->registerHandler('shutdown', 'system', '_elgg_save_autoload_cache', 1000); $events->registerHandler('upgrade', 'all', '_elgg_delete_autoload_cache'); }; diff --git a/engine/lib/deprecated-1.8.php b/engine/lib/deprecated-1.8.php index 17f06fd0c35..2f4a96a0b24 100644 --- a/engine/lib/deprecated-1.8.php +++ b/engine/lib/deprecated-1.8.php @@ -3072,19 +3072,6 @@ function isadminloggedin() { return elgg_is_admin_logged_in(); } - -/** - * Loads plugins - * - * @deprecated 1.8 Use elgg_load_plugins() - * - * @return bool - */ -function load_plugins() { - elgg_deprecated_notice('load_plugins() is deprecated by elgg_load_plugins()', 1.8); - return _elgg_load_plugins(); -} - /** * Find the plugin settings for a user. * diff --git a/engine/lib/elgglib.php b/engine/lib/elgglib.php index 32da04edbbc..00410f123c5 100644 --- a/engine/lib/elgglib.php +++ b/engine/lib/elgglib.php @@ -1835,13 +1835,15 @@ function _elgg_engine_boot() { set_error_handler('_elgg_php_error_handler'); set_exception_handler('_elgg_php_exception_handler'); - _elgg_services()->db->setupConnections(); + $db = _elgg_services()->db; - _elgg_services()->db->assertInstalled(); + // we inject the logger here to allow use of DB without loading core + $db->setLogger(_elgg_services()->logger); - _elgg_load_application_config(); + $db->setupConnections(); + $db->assertInstalled(); - _elgg_load_autoload_cache(); + _elgg_load_application_config(); _elgg_load_site_config(); diff --git a/engine/lib/plugins.php b/engine/lib/plugins.php index 60e5457b6dd..60cb9b37f4e 100644 --- a/engine/lib/plugins.php +++ b/engine/lib/plugins.php @@ -136,21 +136,6 @@ function elgg_is_active_plugin($plugin_id, $site_guid = null) { return _elgg_services()->plugins->isActive($plugin_id, $site_guid); } -/** - * Loads all active plugins in the order specified in the tool admin panel. - * - * @note This is called on every page load. If a plugin is active and problematic, it - * will be disabled and a visible error emitted. This does not check the deps system because - * that was too slow. - * - * @return bool - * @since 1.8.0 - * @access private - */ -function _elgg_load_plugins() { - return _elgg_services()->plugins->load(); -} - /** * Returns an ordered list of plugins * diff --git a/engine/load.php b/engine/load.php deleted file mode 100644 index 8f224048edb..00000000000 --- a/engine/load.php +++ /dev/null @@ -1,100 +0,0 @@ -events; - $hooks = _elgg_services()->hooks; - - // run setups - foreach ($setups as $func) { - $func($events, $hooks); - } -}); diff --git a/engine/start.php b/engine/start.php index 3ca5b75fccc..0de75327326 100644 --- a/engine/start.php +++ b/engine/start.php @@ -1,90 +1,7 @@ boot_complete = false; +(new \Elgg\Application())->bootCore(); -$engine_dir = dirname(__FILE__); - -// No settings means a fresh install -if (!is_file("$engine_dir/settings.php")) { - header("Location: install.php"); - exit; -} - -if (!is_readable("$engine_dir/settings.php")) { - echo "The Elgg settings file exists but the web server doesn't have read permission to it."; - exit; -} - -require_once "$engine_dir/settings.php"; - -// This will be overridden by the DB value but may be needed before the upgrade script can be run. -$CONFIG->default_limit = 10; - -require_once "$engine_dir/load.php"; - -// Connect to database, load language files, load configuration, init session -// Plugins can't use this event because they haven't been loaded yet. -elgg_trigger_event('boot', 'system'); - -// Load the plugins that are active -_elgg_load_plugins(); - -// @todo move loading plugins into a single boot function that replaces 'boot', 'system' event -// and then move this code in there. -// This validates the view type - first opportunity to do it is after plugins load. -$viewtype = elgg_get_viewtype(); -if (!elgg_is_registered_viewtype($viewtype)) { - elgg_set_viewtype('default'); -} - -// @todo deprecate as plugins can use 'init', 'system' event -elgg_trigger_event('plugins_boot', 'system'); - -// Complete the boot process for both engine and plugins -elgg_trigger_event('init', 'system'); - -$CONFIG->boot_complete = true; - -// System loaded and ready -elgg_trigger_event('ready', 'system'); +elgg_deprecated_notice('You should load the core using \Elgg\Application::bootCore() instead of including start.php', "2.0.0"); diff --git a/engine/tests/phpunit/Elgg/CacheHandlerTest.php b/engine/tests/phpunit/Elgg/CacheHandlerTest.php index 628c5b678b1..6efa7a11924 100644 --- a/engine/tests/phpunit/Elgg/CacheHandlerTest.php +++ b/engine/tests/phpunit/Elgg/CacheHandlerTest.php @@ -10,8 +10,7 @@ class CacheHandlerTest extends \PHPUnit_Framework_TestCase { protected $handler; public function setUp() { - $config = (object)array(); - $this->handler = new \Elgg\CacheHandler($config); + $this->handler = new \Elgg\CacheHandler(_elgg_testing_application()); } protected function _testParseFail($input) { diff --git a/engine/tests/phpunit/Elgg/DatabaseTest.php b/engine/tests/phpunit/Elgg/DatabaseTest.php index efaf0e5bc08..0f72d46203d 100644 --- a/engine/tests/phpunit/Elgg/DatabaseTest.php +++ b/engine/tests/phpunit/Elgg/DatabaseTest.php @@ -9,10 +9,7 @@ class Elgg_DatabaseTest extends PHPUnit_Framework_TestCase { * Database API. */ public function setUp() { - // Database class - // Cannot user _elgg_services() because ElggEntityTest replace - // the database instance with a mock. - $db = _elgg_create_service_provider()->db; + $db = _elgg_testing_application()->getDb(); $this->dbClass = get_class($db); // Config class diff --git a/engine/tests/phpunit/Elgg/Di/ServiceProviderTest.php b/engine/tests/phpunit/Elgg/Di/ServiceProviderTest.php index 682b4d4f149..266c8552f68 100644 --- a/engine/tests/phpunit/Elgg/Di/ServiceProviderTest.php +++ b/engine/tests/phpunit/Elgg/Di/ServiceProviderTest.php @@ -5,9 +5,8 @@ class ServiceProviderTest extends \PHPUnit_Framework_TestCase { public function testPropertiesReturnCorrectClassNames() { - $mgr = $this->getMock('\Elgg\AutoloadManager', array(), array(), '', false); + $sp = _elgg_testing_application()->getServices(); - $sp = new \Elgg\Di\ServiceProvider($mgr); $sp->setValue('session', \ElggSession::getMock()); $svcClasses = array( diff --git a/engine/tests/phpunit/bootstrap.php b/engine/tests/phpunit/bootstrap.php index 92e4bf0ff32..72335042439 100644 --- a/engine/tests/phpunit/bootstrap.php +++ b/engine/tests/phpunit/bootstrap.php @@ -1,21 +1,43 @@ 'elgg_', 'boot_complete' => false, 'wwwroot' => 'http://localhost/', + 'dataroot' => __DIR__ . '/test_files/dataroot/', 'site_guid' => 1, -); + 'AutoloaderManager_skip_storage' => true, +]; + +$app = new \Elgg\Application(new \Elgg\Di\ServiceProvider(new \Elgg\Config($CONFIG))); +$app->loadCore(); +_elgg_testing_application($app); -require_once "$engine/load.php"; +// PHPUnit will serialize globals between tests, $app contains Closures! +unset($app); diff --git a/engine/tests/suite.php b/engine/tests/suite.php index c5d59f32846..4f46c045520 100644 --- a/engine/tests/suite.php +++ b/engine/tests/suite.php @@ -6,14 +6,12 @@ * @subpackage Test */ -require_once(dirname( __FILE__ ) . '/../start.php'); +require_once __DIR__ . '/../../autoloader.php'; +(new \Elgg\Application())->bootCore(); -require_once(dirname( __FILE__ ) . '/../../vendor/autoload.php'); -$test_path = "$CONFIG->path/engine/tests"; - -require_once("$test_path/ElggCoreUnitTest.php"); -require_once("$test_path/ElggCoreGetEntitiesBaseTest.php"); +require_once __DIR__ . '/ElggCoreUnitTest.php'; +require_once __DIR__ . '/ElggCoreGetEntitiesBaseTest.php'; // don't expect admin session for CLI if (!TextReporter::inCli()) { @@ -24,6 +22,7 @@ echo "Failed to login as administrator."; exit(1); } + global $CONFIG; $CONFIG->debug = 'NOTICE'; } diff --git a/index.php b/index.php index bf2977f10c7..db54d52a52c 100644 --- a/index.php +++ b/index.php @@ -6,57 +6,8 @@ * @subpackage Core */ -/* - * Rewrite rules for PHP cli webserver used for testing. Do not use on production sites - * as normal web server replacement. - * - * You need to explicitly point to index.php in order for router to work properly: - * - * php -S localhost:8888 index.php - */ -if (php_sapi_name() === 'cli-server') { - $urlPath = parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH); - - if (preg_match('/^\/cache\/(.*)$/', $urlPath, $matches)) { - $_GET['request'] = $matches[1]; - require('engine/handlers/cache_handler.php'); - exit; - } else if (preg_match('/^\/export\/([A-Za-z]+)\/([0-9]+)\/?$/', $urlPath, $matches)) { - $_GET['view'] = $matches[1]; - $_GET['guid'] = $matches[2]; - require('engine/handlers/export_handler.php'); - exit; - } else if (preg_match('/^\/export\/([A-Za-z]+)\/([0-9]+)\/([A-Za-z]+)\/([A-Za-z0-9\_]+)\/$/', $urlPath, $matches)) { - $_GET['view'] = $matches[1]; - $_GET['guid'] = $matches[2]; - $_GET['type'] = $matches[3]; - $_GET['idname'] = $matches[4]; - require('engine/handlers/export_handler.php'); - exit; - } else if (preg_match("/^\/rewrite.php$/", $urlPath, $matches)) { - require('install.php'); - exit; - } else if ($urlPath !== '/' && file_exists(__DIR__ . $urlPath)) { - // serve the requested resource as-is. - return false; - } else { - $_GET['__elgg_uri'] = $urlPath; - } -} - -// allow testing from the upgrade page before the site is upgraded. -if (isset($_GET['__testing_rewrite'])) { - if (isset($_GET['__elgg_uri']) && false !== strpos($_GET['__elgg_uri'], '__testing_rewrite')) { - echo "success"; - } - exit; -} - -require_once(dirname(__FILE__) . "/engine/start.php"); +require_once __DIR__ . '/autoloader.php'; -$router = _elgg_services()->router; -$request = _elgg_services()->request; +$app = new \Elgg\Application(); -if (!$router->route($request)) { - forward('', '404'); -} \ No newline at end of file +return $app->run(); diff --git a/install.php b/install.php index b6c433f2581..03f2b81dc9d 100644 --- a/install.php +++ b/install.php @@ -12,11 +12,7 @@ exit; } -$autoload_path = __DIR__ . "/vendor/autoload.php"; -$autoload_available = include_once($autoload_path); -if (!$autoload_available) { - die("Couldn't include '$autoload_path'. Did you run `composer install`?"); -} +$autoloader = require_once(__DIR__ . '/autoloader.php'); $installer = new ElggInstaller(); diff --git a/install/cli/sample_installer.php b/install/cli/sample_installer.php index d6bf0883709..23b2b1adcfa 100644 --- a/install/cli/sample_installer.php +++ b/install/cli/sample_installer.php @@ -44,7 +44,7 @@ $elggRoot = dirname(dirname(__DIR__)); -require_once "$elggRoot/vendor/autoload.php"; +require_once "$elggRoot/autoloader.php"; $installer = new ElggInstaller(); diff --git a/install/cli/travis_installer.php b/install/cli/travis_installer.php index 8af15511107..4d75cbf4375 100644 --- a/install/cli/travis_installer.php +++ b/install/cli/travis_installer.php @@ -21,7 +21,7 @@ $elggRoot = dirname(dirname(__DIR__)); -require_once "$elggRoot/vendor/autoload.php"; +require_once "$elggRoot/autoloader.php"; $installer = new ElggInstaller(); diff --git a/mod/file/download.php b/mod/file/download.php index b2acdffecda..cd1d09a791b 100644 --- a/mod/file/download.php +++ b/mod/file/download.php @@ -4,7 +4,8 @@ * * @package ElggFile */ -require_once(dirname(dirname(dirname(__FILE__))) . "/engine/start.php"); +require_once dirname(dirname(__DIR__)) . '/autoloader.php'; +(new Elgg\Application())->bootCore(); // Get the guid $file_guid = get_input("file_guid"); diff --git a/mod/file/thumbnail.php b/mod/file/thumbnail.php index d25ea1c6fb3..0a24cf58376 100644 --- a/mod/file/thumbnail.php +++ b/mod/file/thumbnail.php @@ -6,7 +6,9 @@ */ // Get engine -require_once(dirname(dirname(dirname(__FILE__))) . "/engine/start.php"); +require_once dirname(dirname(__DIR__)) . '/autoloader.php'; +$application = new Elgg\Application(); +$application->bootCore(); // Get file GUID $file_guid = (int) get_input('file_guid', 0); diff --git a/mod/groups/icon.php b/mod/groups/icon.php index 011e4a7ea76..a54f4da42d4 100644 --- a/mod/groups/icon.php +++ b/mod/groups/icon.php @@ -5,7 +5,9 @@ * @package ElggGroups */ -require_once(dirname(dirname(dirname(__FILE__))) . "/engine/start.php"); +if (!isset($page)) { + die('This file cannot be called directly.'); +} $group_guid = get_input('group_guid'); diff --git a/mod/groups/topicposts.php b/mod/groups/topicposts.php index d0137e2f5c6..a13f5cc1c99 100644 --- a/mod/groups/topicposts.php +++ b/mod/groups/topicposts.php @@ -8,7 +8,8 @@ */ // Load Elgg engine -require_once(dirname(dirname(dirname(__FILE__))) . "/engine/start.php"); +require_once dirname(dirname(__DIR__)) . '/autoloader.php'; +(new \Elgg\Application())->bootCore(); elgg_load_library('elgg:discussion'); diff --git a/mod/profile/icondirect.php b/mod/profile/icondirect.php index 01c8a0741fa..7970a413910 100644 --- a/mod/profile/icondirect.php +++ b/mod/profile/icondirect.php @@ -6,13 +6,12 @@ * @package ElggProfile */ -// won't be able to serve anything if no joindate or guid -if (!isset($_GET['joindate']) || !isset($_GET['guid'])) { +// won't be able to serve anything if no guid +if (!isset($_GET['guid'])) { header("HTTP/1.1 404 Not Found"); exit; } -$join_date = (int)$_GET['joindate']; $last_cache = empty($_GET['lastcache']) ? 0 : (int)$_GET['lastcache']; // icontime $guid = (int)$_GET['guid']; @@ -23,14 +22,6 @@ exit; } -$base_dir = dirname(dirname(dirname(__FILE__))); - -// Get DB settings -require_once $base_dir . '/engine/settings.php'; -require_once $base_dir . '/vendor/autoload.php'; - -global $CONFIG; - $size = "medium"; if (!empty($_GET['size'])) { $size = strtolower($_GET['size']); @@ -39,16 +30,18 @@ } } -$path = dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR; +require_once dirname(dirname(__DIR__)) . '/autoloader.php'; +$app = new \Elgg\Application(); +$app->loadSettings(); -$data_root = call_user_func(function () use ($CONFIG) { - if (isset($CONFIG->dataroot)) { - return rtrim($CONFIG->dataroot, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; +$data_root = call_user_func(function () use ($app) { + $dataroot = $app->getConfig()->getVolatile('dataroot'); + if ($dataroot) { + return $dataroot; } // must get from DB - $conf = new \Elgg\Database\Config($CONFIG); - $db = new \Elgg\Database($conf, new \Elgg\Logger(new \Elgg\PluginHooksService())); + $db = $app->getDb(); try { $row = $db->getDataRow(" @@ -87,6 +80,6 @@ } // something went wrong so load engine and try to forward to default icon -require_once $base_dir . "/engine/start.php"; +$app->bootCore(); elgg_log("Profile icon direct failed.", "WARNING"); forward("_graphics/icons/user/default{$size}.gif"); diff --git a/mod/profile/start.php b/mod/profile/start.php index 5beb8146441..e5395bce6df 100644 --- a/mod/profile/start.php +++ b/mod/profile/start.php @@ -132,8 +132,7 @@ function profile_set_icon_url($hook, $type, $url, $params) { try { if ($filehandler->exists()) { - $join_date = $user->getTimeCreated(); - return "mod/profile/icondirect.php?lastcache=$icon_time&joindate=$join_date&guid=$user_guid&size=$size"; + return "mod/profile/icondirect.php?lastcache=$icon_time&guid=$user_guid&size=$size"; } } catch (InvalidParameterException $e) { elgg_log("Unable to get profile icon for user with GUID $user_guid", 'ERROR'); diff --git a/pages/friends/collections/pickercallback.php b/pages/friends/collections/pickercallback.php index afb3057279a..17d33b9442a 100644 --- a/pages/friends/collections/pickercallback.php +++ b/pages/friends/collections/pickercallback.php @@ -7,7 +7,8 @@ */ // Load Elgg engine -require_once(dirname(dirname(dirname(dirname(__FILE__)))) . "/engine/start.php"); +require_once dirname(dirname(dirname(__DIR__))) . '/autoloader.php'; +(new \Elgg\Application())->bootCore(); $site_url = elgg_get_site_url(); diff --git a/upgrade.php b/upgrade.php index 9fa6d1e16b3..762070fd000 100644 --- a/upgrade.php +++ b/upgrade.php @@ -22,7 +22,10 @@ ini_set('display_errors', 1); define('UPGRADING', 'upgrading'); -require_once(dirname(__FILE__) . "/engine/start.php"); + +require_once __DIR__ . '/autoloader.php'; + +(new Elgg\Application())->bootCore(); $site_url = elgg_get_config('url'); $site_host = parse_url($site_url, PHP_URL_HOST) . '/';