addCoreResources(); $parts = explode('?', $requestUri); $args = explode('/', $parts[0] ?? ''); // Remove empty path segments, a//b becomes equivalent to a/b $args = array_values(array_filter($args)); if (!$args) { // This is a request for the site's homepage. See if we have one. $item = CRM_Core_Invoke::getItem('/'); if (!$item) { // We have no public homepage, so send them to login. // This doesn't allow for /civicrm itself to be public, // but that's got to be a pretty edge case, right?! CRM_Utils_System::redirect('/civicrm/login'); } } // This IS required for compatibility. e.g. the extensions (at least) quickform uses it for the form's action attribute. $_GET['q'] = implode('/', $args); // Render the page print CRM_Core_Invoke::invoke($args); } function findStandaloneSettings(): string { return dirname($_SERVER['DOCUMENT_ROOT']) . '/data/civicrm.settings.php'; } function findStandaloneCore(): ?string { $candidates = [ implode(DIRECTORY_SEPARATOR, [$_SERVER['DOCUMENT_ROOT'], 'core']), implode(DIRECTORY_SEPARATOR, [dirname($_SERVER['DOCUMENT_ROOT']), 'vendor', 'civicrm', 'civicrm-core']), ]; foreach ($candidates as $candidate) { if (file_exists($candidate)) { return $candidate; } } return NULL; } function findStandaloneAutoload(): ?string { $candidates = [ implode(DIRECTORY_SEPARATOR, [dirname($_SERVER['DOCUMENT_ROOT']), 'vendor', 'autoload.php']), implode(DIRECTORY_SEPARATOR, [$_SERVER['DOCUMENT_ROOT'], 'core', 'vendor', 'autoload.php']), ]; foreach ($candidates as $candidate) { if (file_exists($candidate)) { return $candidate; } } return NULL; } require_once findStandaloneAutoload(); $civiCorePath = findStandaloneCore(); $classLoader = implode(DIRECTORY_SEPARATOR, [$civiCorePath, 'CRM', 'Core', 'ClassLoader.php']); require_once $classLoader; CRM_Core_ClassLoader::singleton()->register(); function standaloneErrorHandler( int $errno, string $errstr, ?string $errfile, ?int $errline) { static $handlingError = FALSE; if ($handlingError) { throw new \RuntimeException("Died: error was thrown during error handling"); } $config = CRM_Core_Config::singleton(); if (!$config->debug) { // For these errors to show, we must be debugging. return; } $handlingError = TRUE; $trace = ''; if ($config->backtrace) { // Backtrace is configured for errors. $trace = []; foreach (array_slice(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), 1) as $item) { $_ = ''; if (!empty($item['function'])) { if (!empty($item['class']) && !empty($item['type'])) { $_ = htmlspecialchars("$item[class]$item[type]$item[function]() "); } else { $_ = htmlspecialchars("$item[function]() "); } } $_ .= "" . htmlspecialchars($item['file']) . ' line ' . $item['line']; $trace[] = $_; } $trace = '
' . implode("\n", $trace) . '
'; } if (!isset(Civi::$statics[__FUNCTION__])) { Civi::$statics[__FUNCTION__] = []; } Civi::$statics[__FUNCTION__][] = '
  • ' . htmlspecialchars("$errstr [$errno]\n") . '' . htmlspecialchars($errfile) . " line $errline" . $trace . '
  • '; CRM_Core_Smarty::singleton()->assign('standaloneErrors', implode("\n", Civi::$statics[__FUNCTION__])); $handlingError = FALSE; } if (file_exists(findStandaloneSettings())) { require_once findStandaloneSettings(); set_error_handler('standaloneErrorHandler', E_ALL); invoke(); } else { \Civi\Setup::assertProtocolCompatibility(1.0); \Civi\Setup::init([ // This is just enough information to get going. 'cms' => 'Standalone', 'srcPath' => $civiCorePath, ]); $coreUrl = \Civi\Setup::instance()->getModel()->mandatorySettings['userFrameworkResourceURL']; $ctrl = \Civi\Setup::instance()->createController()->getCtrl(); $ctrl->setUrls([ // The URL of this setup controller. May be used for POST-backs 'ctrl' => '/civicrm', /* @todo this had url('civicrm') ? */ // The base URL for loading resource files (images/javascripts) for this project. Includes trailing slash. 'res' => $coreUrl . '/setup/res/', 'jquery.js' => $coreUrl . '/bower_components/jquery/dist/jquery.min.js', 'font-awesome.css' => $coreUrl . '/bower_components/font-awesome/css/font-awesome.min.css', ]); \Civi\Setup\BasicRunner::run($ctrl); exit(); }