aboutsummaryrefslogtreecommitdiffhomepage
path: root/main/app/sprinkles/core/src/Util
diff options
context:
space:
mode:
Diffstat (limited to 'main/app/sprinkles/core/src/Util')
-rw-r--r--main/app/sprinkles/core/src/Util/BadClassNameException.php38
-rw-r--r--main/app/sprinkles/core/src/Util/Captcha.php308
-rw-r--r--main/app/sprinkles/core/src/Util/CheckEnvironment.php662
-rw-r--r--main/app/sprinkles/core/src/Util/ClassMapper.php180
-rw-r--r--main/app/sprinkles/core/src/Util/EnvironmentInfo.php134
-rw-r--r--main/app/sprinkles/core/src/Util/ShutdownHandler.php324
-rw-r--r--main/app/sprinkles/core/src/Util/Util.php348
7 files changed, 997 insertions, 997 deletions
diff --git a/main/app/sprinkles/core/src/Util/BadClassNameException.php b/main/app/sprinkles/core/src/Util/BadClassNameException.php
index 1cd6f4e..1271c44 100644
--- a/main/app/sprinkles/core/src/Util/BadClassNameException.php
+++ b/main/app/sprinkles/core/src/Util/BadClassNameException.php
@@ -1,19 +1,19 @@
-<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Core\Util;
-
-/**
- * Bad class name exception. Used when a class name is dynamically invoked, but the class does not exist.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class BadClassNameException extends \LogicException
-{
- //
-}
+<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Core\Util;
+
+/**
+ * Bad class name exception. Used when a class name is dynamically invoked, but the class does not exist.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class BadClassNameException extends \LogicException
+{
+ //
+}
diff --git a/main/app/sprinkles/core/src/Util/Captcha.php b/main/app/sprinkles/core/src/Util/Captcha.php
index 4c221cb..b93cc73 100644
--- a/main/app/sprinkles/core/src/Util/Captcha.php
+++ b/main/app/sprinkles/core/src/Util/Captcha.php
@@ -1,154 +1,154 @@
-<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Core\Util;
-
-use UserFrosting\Session\Session;
-
-/**
- * Captcha Class
- *
- * Implements the captcha for user registration.
- *
- * @author r3wt
- * @author Alex Weissman (https://alexanderweissman.com)
- * @see http://www.userfrosting.com/components/#messages
- */
-class Captcha
-{
- /**
- * @var string The randomly generated captcha code.
- */
- protected $code;
-
- /**
- * @var string The captcha image, represented as a binary string.
- */
- protected $image;
-
- /**
- * @var UserFrosting\Session\Session We use the session object so that the hashed captcha token will automatically appear in the session.
- */
- protected $session;
-
- /**
- * @var string
- */
- protected $key;
-
- /**
- * Create a new captcha.
- */
- public function __construct($session, $key) {
- $this->session = $session;
- $this->key = $key;
-
- if (!$this->session->has($key)) {
- $this->session[$key] = array();
- }
- }
-
- /**
- * Generates a new captcha for the user registration form.
- *
- * This generates a random 5-character captcha and stores it in the session with an md5 hash.
- * Also, generates the corresponding captcha image.
- */
- public function generateRandomCode() {
- $md5_hash = md5(rand(0, 99999));
- $this->code = substr($md5_hash, 25, 5);
- $enc = md5($this->code);
-
- // Store the generated captcha value to the session
- $this->session[$this->key] = $enc;
-
- $this->generateImage();
- }
-
- /**
- * Returns the captcha code.
- */
- public function getCaptcha() {
- return $this->code;
- }
-
- /**
- * Returns the captcha image.
- */
- public function getImage() {
- return $this->image;
- }
-
- /**
- * Check that the specified code, when hashed, matches the code in the session.
- *
- * Also, stores the specified code in the session with an md5 hash.
- * @param string
- * @return bool
- */
- public function verifyCode($code) {
- return (md5($code) == $this->session[$this->key]);
- }
-
- /**
- * Generate the image for the current captcha.
- *
- * This generates an image as a binary string.
- */
- protected function generateImage() {
- $width = 150;
- $height = 30;
-
- $image = imagecreatetruecolor(150, 30);
-
- //color pallette
- $white = imagecolorallocate($image, 255, 255, 255);
- $black = imagecolorallocate($image, 0, 0, 0);
- $red = imagecolorallocate($image, 255, 0, 0);
- $yellow = imagecolorallocate($image, 255, 255, 0);
- $dark_grey = imagecolorallocate($image, 64, 64, 64);
- $blue = imagecolorallocate($image, 0, 0, 255);
-
- //create white rectangle
- imagefilledrectangle($image, 0, 0, 150, 30, $white);
-
- //add some lines
- for ($i = 0; $i < 2; $i++) {
- imageline($image, 0, rand() % 10, 10, rand() % 30, $dark_grey);
- imageline($image, 0, rand() % 30, 150, rand() % 30, $red);
- imageline($image, 0, rand() % 30, 150, rand() % 30, $yellow);
- }
-
- // RandTab color pallette
- $randc[0] = imagecolorallocate($image, 0, 0, 0);
- $randc[1] = imagecolorallocate($image, 255, 0, 0);
- $randc[2] = imagecolorallocate($image, 255, 255, 0);
- $randc[3] = imagecolorallocate($image, 64, 64, 64);
- $randc[4] = imagecolorallocate($image, 0, 0, 255);
-
- //add some dots
- for ($i = 0; $i < 1000; $i++) {
- imagesetpixel($image, rand() % 200, rand() % 50, $randc[rand() % 5]);
- }
-
- //calculate center of text
- $x = (150 - 0 - imagefontwidth(5) * strlen($this->code)) / 2 + 0 + 5;
-
- //write string twice
- imagestring($image, 5, $x, 7, $this->code, $black);
- imagestring($image, 5, $x, 7, $this->code, $black);
- //start ob
- ob_start();
- imagepng($image);
-
- //get binary image data
- $this->image = ob_get_clean();
-
- return $this->image;
- }
-}
+<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Core\Util;
+
+use UserFrosting\Session\Session;
+
+/**
+ * Captcha Class
+ *
+ * Implements the captcha for user registration.
+ *
+ * @author r3wt
+ * @author Alex Weissman (https://alexanderweissman.com)
+ * @see http://www.userfrosting.com/components/#messages
+ */
+class Captcha
+{
+ /**
+ * @var string The randomly generated captcha code.
+ */
+ protected $code;
+
+ /**
+ * @var string The captcha image, represented as a binary string.
+ */
+ protected $image;
+
+ /**
+ * @var UserFrosting\Session\Session We use the session object so that the hashed captcha token will automatically appear in the session.
+ */
+ protected $session;
+
+ /**
+ * @var string
+ */
+ protected $key;
+
+ /**
+ * Create a new captcha.
+ */
+ public function __construct($session, $key) {
+ $this->session = $session;
+ $this->key = $key;
+
+ if (!$this->session->has($key)) {
+ $this->session[$key] = array();
+ }
+ }
+
+ /**
+ * Generates a new captcha for the user registration form.
+ *
+ * This generates a random 5-character captcha and stores it in the session with an md5 hash.
+ * Also, generates the corresponding captcha image.
+ */
+ public function generateRandomCode() {
+ $md5_hash = md5(rand(0, 99999));
+ $this->code = substr($md5_hash, 25, 5);
+ $enc = md5($this->code);
+
+ // Store the generated captcha value to the session
+ $this->session[$this->key] = $enc;
+
+ $this->generateImage();
+ }
+
+ /**
+ * Returns the captcha code.
+ */
+ public function getCaptcha() {
+ return $this->code;
+ }
+
+ /**
+ * Returns the captcha image.
+ */
+ public function getImage() {
+ return $this->image;
+ }
+
+ /**
+ * Check that the specified code, when hashed, matches the code in the session.
+ *
+ * Also, stores the specified code in the session with an md5 hash.
+ * @param string
+ * @return bool
+ */
+ public function verifyCode($code) {
+ return (md5($code) == $this->session[$this->key]);
+ }
+
+ /**
+ * Generate the image for the current captcha.
+ *
+ * This generates an image as a binary string.
+ */
+ protected function generateImage() {
+ $width = 150;
+ $height = 30;
+
+ $image = imagecreatetruecolor(150, 30);
+
+ //color pallette
+ $white = imagecolorallocate($image, 255, 255, 255);
+ $black = imagecolorallocate($image, 0, 0, 0);
+ $red = imagecolorallocate($image, 255, 0, 0);
+ $yellow = imagecolorallocate($image, 255, 255, 0);
+ $dark_grey = imagecolorallocate($image, 64, 64, 64);
+ $blue = imagecolorallocate($image, 0, 0, 255);
+
+ //create white rectangle
+ imagefilledrectangle($image, 0, 0, 150, 30, $white);
+
+ //add some lines
+ for ($i = 0; $i < 2; $i++) {
+ imageline($image, 0, rand() % 10, 10, rand() % 30, $dark_grey);
+ imageline($image, 0, rand() % 30, 150, rand() % 30, $red);
+ imageline($image, 0, rand() % 30, 150, rand() % 30, $yellow);
+ }
+
+ // RandTab color pallette
+ $randc[0] = imagecolorallocate($image, 0, 0, 0);
+ $randc[1] = imagecolorallocate($image, 255, 0, 0);
+ $randc[2] = imagecolorallocate($image, 255, 255, 0);
+ $randc[3] = imagecolorallocate($image, 64, 64, 64);
+ $randc[4] = imagecolorallocate($image, 0, 0, 255);
+
+ //add some dots
+ for ($i = 0; $i < 1000; $i++) {
+ imagesetpixel($image, rand() % 200, rand() % 50, $randc[rand() % 5]);
+ }
+
+ //calculate center of text
+ $x = (150 - 0 - imagefontwidth(5) * strlen($this->code)) / 2 + 0 + 5;
+
+ //write string twice
+ imagestring($image, 5, $x, 7, $this->code, $black);
+ imagestring($image, 5, $x, 7, $this->code, $black);
+ //start ob
+ ob_start();
+ imagepng($image);
+
+ //get binary image data
+ $this->image = ob_get_clean();
+
+ return $this->image;
+ }
+}
diff --git a/main/app/sprinkles/core/src/Util/CheckEnvironment.php b/main/app/sprinkles/core/src/Util/CheckEnvironment.php
index 05b555f..b8e5ec8 100644
--- a/main/app/sprinkles/core/src/Util/CheckEnvironment.php
+++ b/main/app/sprinkles/core/src/Util/CheckEnvironment.php
@@ -1,331 +1,331 @@
-<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Core\Util;
-
-use Psr\Http\Message\ResponseInterface;
-use Psr\Http\Message\ServerRequestInterface;
-use Slim\Http\Body;
-
-/**
- * Performs pre-flight tests on your server environment to check that it meets the requirements.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class CheckEnvironment
-{
- /**
- * @var \RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator Locator service for stream resources.
- */
- protected $locator;
-
- /**
- * @var array The results of any failed checks performed.
- */
- protected $resultsFailed = [];
-
- /**
- * @var array The results of any successful checks performed.
- */
- protected $resultsSuccess = [];
-
- /**
- * @var \Slim\Views\Twig The view object, needed for rendering error page.
- */
- protected $view;
-
- /**
- * @var \Illuminate\Cache\CacheManager Cache service for cache access.
- */
- protected $cache;
-
- /**
- * Constructor.
- *
- * @param $view \Slim\Views\Twig The view object, needed for rendering error page.
- * @param $locator \RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator Locator service for stream resources.
- */
- public function __construct($view, $locator, $cache) {
- $this->view = $view;
- $this->locator = $locator;
- $this->cache = $cache;
- }
-
- /**
- * Invoke the CheckEnvironment middleware, performing all pre-flight checks and returning an error page if problems were found.
- *
- * @param \Psr\Http\Message\ServerRequestInterface $request PSR7 request
- * @param \Psr\Http\Message\ResponseInterface $response PSR7 response
- * @param callable $next Next middleware
- *
- * @return \Psr\Http\Message\ResponseInterface
- */
- public function __invoke($request, $response, $next) {
- $problemsFound = FALSE;
-
- // If production environment and no cached checks, perform environment checks
- if ($this->isProduction() && $this->cache->get('checkEnvironment') != 'pass') {
- $problemsFound = $this->checkAll();
-
- // Cache if checks passed
- if (!$problemsFound) {
- $this->cache->forever('checkEnvironment', 'pass');
- }
- } else if (!$this->isProduction()) {
- $problemsFound = $this->checkAll();
- }
-
- if ($problemsFound) {
- $results = array_merge($this->resultsFailed, $this->resultsSuccess);
-
- $response = $this->view->render($response, 'pages/error/config-errors.html.twig', [
- "messages" => $results
- ]);
- } else {
- $response = $next($request, $response);
- }
-
- return $response;
- }
-
- /**
- * Run through all pre-flight checks.
- */
- public function checkAll() {
- $problemsFound = FALSE;
-
- if ($this->checkApache()) $problemsFound = TRUE;
-
- if ($this->checkPhp()) $problemsFound = TRUE;
-
- if ($this->checkPdo()) $problemsFound = TRUE;
-
- if ($this->checkGd()) $problemsFound = TRUE;
-
- if ($this->checkImageFunctions()) $problemsFound = TRUE;
-
- if ($this->checkPermissions()) $problemsFound = TRUE;
-
- return $problemsFound;
- }
-
- /**
- * For Apache environments, check that required Apache modules are installed.
- */
- public function checkApache() {
- $problemsFound = FALSE;
-
- // Perform some Apache checks. We may also need to do this before any routing takes place.
- if (strpos(php_sapi_name(), 'apache') !== FALSE) {
-
- $require_apache_modules = ['mod_rewrite'];
- $apache_modules = apache_get_modules();
-
- $apache_status = [];
-
- foreach ($require_apache_modules as $module) {
- if (!in_array($module, $apache_modules)) {
- $problemsFound = TRUE;
- $this->resultsFailed['apache-' . $module] = [
- "title" => "<i class='fa fa-server fa-fw'></i> Missing Apache module <b>$module</b>.",
- "message" => "Please make sure that the <code>$module</code> Apache module is installed and enabled. If you use shared hosting, you will need to ask your web host to do this for you.",
- "success" => FALSE
- ];
- } else {
- $this->resultsSuccess['apache-' . $module] = [
- "title" => "<i class='fa fa-server fa-fw'></i> Apache module <b>$module</b> is installed and enabled.",
- "message" => "Great, we found the <code>$module</code> Apache module!",
- "success" => TRUE
- ];
- }
- }
- }
-
- return $problemsFound;
- }
-
- /**
- * Check for GD library (required for Captcha).
- */
- public function checkGd() {
- $problemsFound = FALSE;
-
- if (!(extension_loaded('gd') && function_exists('gd_info'))) {
- $problemsFound = TRUE;
- $this->resultsFailed['gd'] = [
- "title" => "<i class='fa fa-image fa-fw'></i> GD library not installed",
- "message" => "We could not confirm that the <code>GD</code> library is installed and enabled. GD is an image processing library that UserFrosting uses to generate captcha codes for user account registration.",
- "success" => FALSE
- ];
- } else {
- $this->resultsSuccess['gd'] = [
- "title" => "<i class='fa fa-image fa-fw'></i> GD library installed!",
- "message" => "Great, you have <code>GD</code> installed and enabled.",
- "success" => TRUE
- ];
- }
-
- return $problemsFound;
- }
-
- /**
- * Check that all image* functions used by Captcha exist.
- *
- * Some versions of GD are missing one or more of these functions, thus why we check for them explicitly.
- */
- public function checkImageFunctions() {
- $problemsFound = FALSE;
-
- $funcs = [
- 'imagepng',
- 'imagecreatetruecolor',
- 'imagecolorallocate',
- 'imagefilledrectangle',
- 'imageline',
- 'imagesetpixel',
- 'imagefontwidth',
- 'imagestring'
- ];
-
- foreach ($funcs as $func) {
- if (!function_exists($func)) {
- $problemsFound = TRUE;
- $this->resultsFailed['function-' . $func] = [
- "title" => "<i class='fa fa-code fa-fw'></i> Missing image manipulation function.",
- "message" => "It appears that function <code>$func</code> is not available. UserFrosting needs this to render captchas.",
- "success" => FALSE
- ];
- } else {
- $this->resultsSuccess['function-' . $func] = [
- "title" => "<i class='fa fa-code fa-fw'></i> Function <b>$func</b> is available!",
- "message" => "Sweet!",
- "success" => TRUE
- ];
- }
- }
-
- return $problemsFound;
- }
-
- /**
- * Check that PDO is installed and enabled.
- */
- public function checkPdo() {
- $problemsFound = FALSE;
-
- if (!class_exists('PDO')) {
- $problemsFound = TRUE;
- $this->resultsFailed['pdo'] = [
- "title" => "<i class='fa fa-database fa-fw'></i> PDO is not installed.",
- "message" => "I'm sorry, you must have PDO installed and enabled in order for UserFrosting to access the database. If you don't know what PDO is, please see <a href='http://php.net/manual/en/book.pdo.php'>http://php.net/manual/en/book.pdo.php</a>.",
- "success" => FALSE
- ];
- } else {
- $this->resultsSuccess['pdo'] = [
- "title" => "<i class='fa fa-database fa-fw'></i> PDO is installed!",
- "message" => "You've got PDO installed. Good job!",
- "success" => TRUE
- ];
- }
-
- return $problemsFound;
- }
-
- /**
- * Check that log, cache, and session directories are writable, and that other directories are set appropriately for the environment.
- */
- function checkPermissions() {
- $problemsFound = FALSE;
-
- $shouldBeWriteable = [
- $this->locator->findResource('log://') => TRUE,
- $this->locator->findResource('cache://') => TRUE,
- $this->locator->findResource('session://') => TRUE
- ];
-
- if ($this->isProduction()) {
- // Should be write-protected in production!
- $shouldBeWriteable = array_merge($shouldBeWriteable, [
- \UserFrosting\SPRINKLES_DIR => FALSE,
- \UserFrosting\VENDOR_DIR => FALSE
- ]);
- }
-
- // Check for essential files & perms
- foreach ($shouldBeWriteable as $file => $assertWriteable) {
- $is_dir = FALSE;
- if (!file_exists($file)) {
- $problemsFound = TRUE;
- $this->resultsFailed['file-' . $file] = [
- "title" => "<i class='fa fa-file-o fa-fw'></i> File or directory does not exist.",
- "message" => "We could not find the file or directory <code>$file</code>.",
- "success" => FALSE
- ];
- } else {
- $writeable = is_writable($file);
- if ($assertWriteable !== $writeable) {
- $problemsFound = TRUE;
- $this->resultsFailed['file-' . $file] = [
- "title" => "<i class='fa fa-file-o fa-fw'></i> Incorrect permissions for file or directory.",
- "message" => "<code>$file</code> is "
- . ($writeable ? "writeable" : "not writeable")
- . ", but it should "
- . ($assertWriteable ? "be writeable" : "not be writeable")
- . ". Please modify the OS user or group permissions so that user <b>"
- . exec('whoami') . "</b> "
- . ($assertWriteable ? "has" : "does not have") . " write permissions for this directory.",
- "success" => FALSE
- ];
- } else {
- $this->resultsSuccess['file-' . $file] = [
- "title" => "<i class='fa fa-file-o fa-fw'></i> File/directory check passed!",
- "message" => "<code>$file</code> exists and is correctly set as <b>"
- . ($writeable ? "writeable" : "not writeable")
- . "</b>.",
- "success" => TRUE
- ];
- }
- }
- }
- return $problemsFound;
- }
-
- /**
- * Check that PHP meets the minimum required version.
- */
- public function checkPhp() {
- $problemsFound = FALSE;
-
- // Check PHP version
- if (version_compare(phpversion(), \UserFrosting\PHP_MIN_VERSION, '<')) {
- $problemsFound = TRUE;
- $this->resultsFailed['phpVersion'] = [
- "title" => "<i class='fa fa-code fa-fw'></i> You need to upgrade your PHP installation.",
- "message" => "I'm sorry, UserFrosting requires version " . \UserFrosting\PHP_MIN_VERSION . " or greater. Please upgrade your version of PHP, or contact your web hosting service and ask them to upgrade it for you.",
- "success" => FALSE
- ];
- } else {
- $this->resultsSuccess['phpVersion'] = [
- "title" => "<i class='fa fa-code fa-fw'></i> PHP version checks out!",
- "message" => "You're using PHP " . \UserFrosting\PHP_MIN_VERSION . "or higher. Great!",
- "success" => TRUE
- ];
- }
-
- return $problemsFound;
- }
-
- /**
- * Determine whether or not we are running in production mode.
- *
- * @return bool
- */
- public function isProduction() {
- return (getenv('UF_MODE') == 'production');
- }
-}
+<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Core\Util;
+
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Slim\Http\Body;
+
+/**
+ * Performs pre-flight tests on your server environment to check that it meets the requirements.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class CheckEnvironment
+{
+ /**
+ * @var \RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator Locator service for stream resources.
+ */
+ protected $locator;
+
+ /**
+ * @var array The results of any failed checks performed.
+ */
+ protected $resultsFailed = [];
+
+ /**
+ * @var array The results of any successful checks performed.
+ */
+ protected $resultsSuccess = [];
+
+ /**
+ * @var \Slim\Views\Twig The view object, needed for rendering error page.
+ */
+ protected $view;
+
+ /**
+ * @var \Illuminate\Cache\CacheManager Cache service for cache access.
+ */
+ protected $cache;
+
+ /**
+ * Constructor.
+ *
+ * @param $view \Slim\Views\Twig The view object, needed for rendering error page.
+ * @param $locator \RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator Locator service for stream resources.
+ */
+ public function __construct($view, $locator, $cache) {
+ $this->view = $view;
+ $this->locator = $locator;
+ $this->cache = $cache;
+ }
+
+ /**
+ * Invoke the CheckEnvironment middleware, performing all pre-flight checks and returning an error page if problems were found.
+ *
+ * @param \Psr\Http\Message\ServerRequestInterface $request PSR7 request
+ * @param \Psr\Http\Message\ResponseInterface $response PSR7 response
+ * @param callable $next Next middleware
+ *
+ * @return \Psr\Http\Message\ResponseInterface
+ */
+ public function __invoke($request, $response, $next) {
+ $problemsFound = FALSE;
+
+ // If production environment and no cached checks, perform environment checks
+ if ($this->isProduction() && $this->cache->get('checkEnvironment') != 'pass') {
+ $problemsFound = $this->checkAll();
+
+ // Cache if checks passed
+ if (!$problemsFound) {
+ $this->cache->forever('checkEnvironment', 'pass');
+ }
+ } else if (!$this->isProduction()) {
+ $problemsFound = $this->checkAll();
+ }
+
+ if ($problemsFound) {
+ $results = array_merge($this->resultsFailed, $this->resultsSuccess);
+
+ $response = $this->view->render($response, 'pages/error/config-errors.html.twig', [
+ "messages" => $results
+ ]);
+ } else {
+ $response = $next($request, $response);
+ }
+
+ return $response;
+ }
+
+ /**
+ * Run through all pre-flight checks.
+ */
+ public function checkAll() {
+ $problemsFound = FALSE;
+
+ if ($this->checkApache()) $problemsFound = TRUE;
+
+ if ($this->checkPhp()) $problemsFound = TRUE;
+
+ if ($this->checkPdo()) $problemsFound = TRUE;
+
+ if ($this->checkGd()) $problemsFound = TRUE;
+
+ if ($this->checkImageFunctions()) $problemsFound = TRUE;
+
+ if ($this->checkPermissions()) $problemsFound = TRUE;
+
+ return $problemsFound;
+ }
+
+ /**
+ * For Apache environments, check that required Apache modules are installed.
+ */
+ public function checkApache() {
+ $problemsFound = FALSE;
+
+ // Perform some Apache checks. We may also need to do this before any routing takes place.
+ if (strpos(php_sapi_name(), 'apache') !== FALSE) {
+
+ $require_apache_modules = ['mod_rewrite'];
+ $apache_modules = apache_get_modules();
+
+ $apache_status = [];
+
+ foreach ($require_apache_modules as $module) {
+ if (!in_array($module, $apache_modules)) {
+ $problemsFound = TRUE;
+ $this->resultsFailed['apache-' . $module] = [
+ "title" => "<i class='fa fa-server fa-fw'></i> Missing Apache module <b>$module</b>.",
+ "message" => "Please make sure that the <code>$module</code> Apache module is installed and enabled. If you use shared hosting, you will need to ask your web host to do this for you.",
+ "success" => FALSE
+ ];
+ } else {
+ $this->resultsSuccess['apache-' . $module] = [
+ "title" => "<i class='fa fa-server fa-fw'></i> Apache module <b>$module</b> is installed and enabled.",
+ "message" => "Great, we found the <code>$module</code> Apache module!",
+ "success" => TRUE
+ ];
+ }
+ }
+ }
+
+ return $problemsFound;
+ }
+
+ /**
+ * Check for GD library (required for Captcha).
+ */
+ public function checkGd() {
+ $problemsFound = FALSE;
+
+ if (!(extension_loaded('gd') && function_exists('gd_info'))) {
+ $problemsFound = TRUE;
+ $this->resultsFailed['gd'] = [
+ "title" => "<i class='fa fa-image fa-fw'></i> GD library not installed",
+ "message" => "We could not confirm that the <code>GD</code> library is installed and enabled. GD is an image processing library that UserFrosting uses to generate captcha codes for user account registration.",
+ "success" => FALSE
+ ];
+ } else {
+ $this->resultsSuccess['gd'] = [
+ "title" => "<i class='fa fa-image fa-fw'></i> GD library installed!",
+ "message" => "Great, you have <code>GD</code> installed and enabled.",
+ "success" => TRUE
+ ];
+ }
+
+ return $problemsFound;
+ }
+
+ /**
+ * Check that all image* functions used by Captcha exist.
+ *
+ * Some versions of GD are missing one or more of these functions, thus why we check for them explicitly.
+ */
+ public function checkImageFunctions() {
+ $problemsFound = FALSE;
+
+ $funcs = [
+ 'imagepng',
+ 'imagecreatetruecolor',
+ 'imagecolorallocate',
+ 'imagefilledrectangle',
+ 'imageline',
+ 'imagesetpixel',
+ 'imagefontwidth',
+ 'imagestring'
+ ];
+
+ foreach ($funcs as $func) {
+ if (!function_exists($func)) {
+ $problemsFound = TRUE;
+ $this->resultsFailed['function-' . $func] = [
+ "title" => "<i class='fa fa-code fa-fw'></i> Missing image manipulation function.",
+ "message" => "It appears that function <code>$func</code> is not available. UserFrosting needs this to render captchas.",
+ "success" => FALSE
+ ];
+ } else {
+ $this->resultsSuccess['function-' . $func] = [
+ "title" => "<i class='fa fa-code fa-fw'></i> Function <b>$func</b> is available!",
+ "message" => "Sweet!",
+ "success" => TRUE
+ ];
+ }
+ }
+
+ return $problemsFound;
+ }
+
+ /**
+ * Check that PDO is installed and enabled.
+ */
+ public function checkPdo() {
+ $problemsFound = FALSE;
+
+ if (!class_exists('PDO')) {
+ $problemsFound = TRUE;
+ $this->resultsFailed['pdo'] = [
+ "title" => "<i class='fa fa-database fa-fw'></i> PDO is not installed.",
+ "message" => "I'm sorry, you must have PDO installed and enabled in order for UserFrosting to access the database. If you don't know what PDO is, please see <a href='http://php.net/manual/en/book.pdo.php'>http://php.net/manual/en/book.pdo.php</a>.",
+ "success" => FALSE
+ ];
+ } else {
+ $this->resultsSuccess['pdo'] = [
+ "title" => "<i class='fa fa-database fa-fw'></i> PDO is installed!",
+ "message" => "You've got PDO installed. Good job!",
+ "success" => TRUE
+ ];
+ }
+
+ return $problemsFound;
+ }
+
+ /**
+ * Check that log, cache, and session directories are writable, and that other directories are set appropriately for the environment.
+ */
+ function checkPermissions() {
+ $problemsFound = FALSE;
+
+ $shouldBeWriteable = [
+ $this->locator->findResource('log://') => TRUE,
+ $this->locator->findResource('cache://') => TRUE,
+ $this->locator->findResource('session://') => TRUE
+ ];
+
+ if ($this->isProduction()) {
+ // Should be write-protected in production!
+ $shouldBeWriteable = array_merge($shouldBeWriteable, [
+ \UserFrosting\SPRINKLES_DIR => FALSE,
+ \UserFrosting\VENDOR_DIR => FALSE
+ ]);
+ }
+
+ // Check for essential files & perms
+ foreach ($shouldBeWriteable as $file => $assertWriteable) {
+ $is_dir = FALSE;
+ if (!file_exists($file)) {
+ $problemsFound = TRUE;
+ $this->resultsFailed['file-' . $file] = [
+ "title" => "<i class='fa fa-file-o fa-fw'></i> File or directory does not exist.",
+ "message" => "We could not find the file or directory <code>$file</code>.",
+ "success" => FALSE
+ ];
+ } else {
+ $writeable = is_writable($file);
+ if ($assertWriteable !== $writeable) {
+ $problemsFound = TRUE;
+ $this->resultsFailed['file-' . $file] = [
+ "title" => "<i class='fa fa-file-o fa-fw'></i> Incorrect permissions for file or directory.",
+ "message" => "<code>$file</code> is "
+ . ($writeable ? "writeable" : "not writeable")
+ . ", but it should "
+ . ($assertWriteable ? "be writeable" : "not be writeable")
+ . ". Please modify the OS user or group permissions so that user <b>"
+ . exec('whoami') . "</b> "
+ . ($assertWriteable ? "has" : "does not have") . " write permissions for this directory.",
+ "success" => FALSE
+ ];
+ } else {
+ $this->resultsSuccess['file-' . $file] = [
+ "title" => "<i class='fa fa-file-o fa-fw'></i> File/directory check passed!",
+ "message" => "<code>$file</code> exists and is correctly set as <b>"
+ . ($writeable ? "writeable" : "not writeable")
+ . "</b>.",
+ "success" => TRUE
+ ];
+ }
+ }
+ }
+ return $problemsFound;
+ }
+
+ /**
+ * Check that PHP meets the minimum required version.
+ */
+ public function checkPhp() {
+ $problemsFound = FALSE;
+
+ // Check PHP version
+ if (version_compare(phpversion(), \UserFrosting\PHP_MIN_VERSION, '<')) {
+ $problemsFound = TRUE;
+ $this->resultsFailed['phpVersion'] = [
+ "title" => "<i class='fa fa-code fa-fw'></i> You need to upgrade your PHP installation.",
+ "message" => "I'm sorry, UserFrosting requires version " . \UserFrosting\PHP_MIN_VERSION . " or greater. Please upgrade your version of PHP, or contact your web hosting service and ask them to upgrade it for you.",
+ "success" => FALSE
+ ];
+ } else {
+ $this->resultsSuccess['phpVersion'] = [
+ "title" => "<i class='fa fa-code fa-fw'></i> PHP version checks out!",
+ "message" => "You're using PHP " . \UserFrosting\PHP_MIN_VERSION . "or higher. Great!",
+ "success" => TRUE
+ ];
+ }
+
+ return $problemsFound;
+ }
+
+ /**
+ * Determine whether or not we are running in production mode.
+ *
+ * @return bool
+ */
+ public function isProduction() {
+ return (getenv('UF_MODE') == 'production');
+ }
+}
diff --git a/main/app/sprinkles/core/src/Util/ClassMapper.php b/main/app/sprinkles/core/src/Util/ClassMapper.php
index 11720f6..e29c524 100644
--- a/main/app/sprinkles/core/src/Util/ClassMapper.php
+++ b/main/app/sprinkles/core/src/Util/ClassMapper.php
@@ -1,90 +1,90 @@
-<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Core\Util;
-
-/**
- * UserFrosting class mapper.
- *
- * This creates an abstraction layer for overrideable classes.
- * For example, if we want to replace usages of the User class with MyUser, this abstraction layer handles that.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- * @author Roger Ardibee
- */
-class ClassMapper
-{
- /**
- * Mapping of generic class identifiers to specific class names.
- */
- protected $classMappings = [];
-
- /**
- * Creates an instance for a requested class identifier.
- *
- * @param string $identifier The identifier for the class, e.g. 'user'
- * @param mixed ...$arg Whatever needs to be passed to the constructor.
- */
- public function createInstance($identifier) {
- $className = $this->getClassMapping($identifier);
-
- $params = array_slice(func_get_args(), 1);
-
- // We must use reflection in PHP < 5.6. See http://stackoverflow.com/questions/8734522/dynamically-call-class-with-variable-number-of-parameters-in-the-constructor
- $reflection = new \ReflectionClass($className);
-
- return $reflection->newInstanceArgs($params);
- }
-
- /**
- * Gets the fully qualified class name for a specified class identifier.
- *
- * @param string $identifier
- * @return string
- */
- public function getClassMapping($identifier) {
- if (isset($this->classMappings[$identifier])) {
- return $this->classMappings[$identifier];
- } else {
- throw new \OutOfBoundsException("There is no class mapped to the identifier '$identifier'.");
- }
- }
-
- /**
- * Assigns a fully qualified class name to a specified class identifier.
- *
- * @param string $identifier
- * @param string $className
- * @return ClassMapper
- */
- public function setClassMapping($identifier, $className) {
- // Check that class exists
- if (!class_exists($className)) {
- throw new BadClassNameException("Unable to find the class '$className'.");
- }
-
- $this->classMappings[$identifier] = $className;
-
- return $this;
- }
-
- /**
- * Call a static method for a specified class.
- *
- * @param string $identifier The identifier for the class, e.g. 'user'
- * @param string $methodName The method to be invoked.
- * @param mixed ...$arg Whatever needs to be passed to the method.
- */
- public function staticMethod($identifier, $methodName) {
- $className = $this->getClassMapping($identifier);
-
- $params = array_slice(func_get_args(), 2);
-
- return call_user_func_array("$className::$methodName", $params);
- }
-}
+<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Core\Util;
+
+/**
+ * UserFrosting class mapper.
+ *
+ * This creates an abstraction layer for overrideable classes.
+ * For example, if we want to replace usages of the User class with MyUser, this abstraction layer handles that.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ * @author Roger Ardibee
+ */
+class ClassMapper
+{
+ /**
+ * Mapping of generic class identifiers to specific class names.
+ */
+ protected $classMappings = [];
+
+ /**
+ * Creates an instance for a requested class identifier.
+ *
+ * @param string $identifier The identifier for the class, e.g. 'user'
+ * @param mixed ...$arg Whatever needs to be passed to the constructor.
+ */
+ public function createInstance($identifier) {
+ $className = $this->getClassMapping($identifier);
+
+ $params = array_slice(func_get_args(), 1);
+
+ // We must use reflection in PHP < 5.6. See http://stackoverflow.com/questions/8734522/dynamically-call-class-with-variable-number-of-parameters-in-the-constructor
+ $reflection = new \ReflectionClass($className);
+
+ return $reflection->newInstanceArgs($params);
+ }
+
+ /**
+ * Gets the fully qualified class name for a specified class identifier.
+ *
+ * @param string $identifier
+ * @return string
+ */
+ public function getClassMapping($identifier) {
+ if (isset($this->classMappings[$identifier])) {
+ return $this->classMappings[$identifier];
+ } else {
+ throw new \OutOfBoundsException("There is no class mapped to the identifier '$identifier'.");
+ }
+ }
+
+ /**
+ * Assigns a fully qualified class name to a specified class identifier.
+ *
+ * @param string $identifier
+ * @param string $className
+ * @return ClassMapper
+ */
+ public function setClassMapping($identifier, $className) {
+ // Check that class exists
+ if (!class_exists($className)) {
+ throw new BadClassNameException("Unable to find the class '$className'.");
+ }
+
+ $this->classMappings[$identifier] = $className;
+
+ return $this;
+ }
+
+ /**
+ * Call a static method for a specified class.
+ *
+ * @param string $identifier The identifier for the class, e.g. 'user'
+ * @param string $methodName The method to be invoked.
+ * @param mixed ...$arg Whatever needs to be passed to the method.
+ */
+ public function staticMethod($identifier, $methodName) {
+ $className = $this->getClassMapping($identifier);
+
+ $params = array_slice(func_get_args(), 2);
+
+ return call_user_func_array("$className::$methodName", $params);
+ }
+}
diff --git a/main/app/sprinkles/core/src/Util/EnvironmentInfo.php b/main/app/sprinkles/core/src/Util/EnvironmentInfo.php
index 116a59e..e0e9d49 100644
--- a/main/app/sprinkles/core/src/Util/EnvironmentInfo.php
+++ b/main/app/sprinkles/core/src/Util/EnvironmentInfo.php
@@ -1,67 +1,67 @@
-<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Core\Util;
-
-use Illuminate\Database\Capsule\Manager as Capsule;
-
-/**
- * EnvironmentInfo Class
- *
- * Gets basic information about the application environment.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class EnvironmentInfo
-{
- /**
- * @var ContainerInterface The DI container for your application.
- */
- public static $ci;
-
- /**
- * Get an array of key-value pairs containing basic information about the default database.
- *
- * @return string[] the properties of this database.
- */
- public static function database() {
- static::$ci['db'];
-
- $pdo = Capsule::connection()->getPdo();
- $results = [];
-
- try {
- $results['type'] = $pdo->getAttribute(\PDO::ATTR_DRIVER_NAME);
- } catch (Exception $e) {
- $results['type'] = "Unknown";
- }
-
- try {
- $results['version'] = $pdo->getAttribute(\PDO::ATTR_SERVER_VERSION);
- } catch (Exception $e) {
- $results['version'] = "";
- }
-
- return $results;
- }
-
- /**
- * Test whether a DB connection can be established.
- *
- * @return bool true if the connection can be established, false otherwise.
- */
- public static function canConnectToDatabase() {
- try {
- Capsule::connection()->getPdo();
- } catch (\PDOException $e) {
- return FALSE;
- }
-
- return TRUE;
- }
-}
+<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Core\Util;
+
+use Illuminate\Database\Capsule\Manager as Capsule;
+
+/**
+ * EnvironmentInfo Class
+ *
+ * Gets basic information about the application environment.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class EnvironmentInfo
+{
+ /**
+ * @var ContainerInterface The DI container for your application.
+ */
+ public static $ci;
+
+ /**
+ * Get an array of key-value pairs containing basic information about the default database.
+ *
+ * @return string[] the properties of this database.
+ */
+ public static function database() {
+ static::$ci['db'];
+
+ $pdo = Capsule::connection()->getPdo();
+ $results = [];
+
+ try {
+ $results['type'] = $pdo->getAttribute(\PDO::ATTR_DRIVER_NAME);
+ } catch (Exception $e) {
+ $results['type'] = "Unknown";
+ }
+
+ try {
+ $results['version'] = $pdo->getAttribute(\PDO::ATTR_SERVER_VERSION);
+ } catch (Exception $e) {
+ $results['version'] = "";
+ }
+
+ return $results;
+ }
+
+ /**
+ * Test whether a DB connection can be established.
+ *
+ * @return bool true if the connection can be established, false otherwise.
+ */
+ public static function canConnectToDatabase() {
+ try {
+ Capsule::connection()->getPdo();
+ } catch (\PDOException $e) {
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+}
diff --git a/main/app/sprinkles/core/src/Util/ShutdownHandler.php b/main/app/sprinkles/core/src/Util/ShutdownHandler.php
index 5447c8f..18e60ec 100644
--- a/main/app/sprinkles/core/src/Util/ShutdownHandler.php
+++ b/main/app/sprinkles/core/src/Util/ShutdownHandler.php
@@ -1,162 +1,162 @@
-<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Core\Util;
-
-use Interop\Container\ContainerInterface;
-use UserFrosting\Sprinkle\Core\Http\Concerns\DeterminesContentType;
-
-/**
- * Registers a handler to be invoked whenever the application shuts down.
- * If it shut down due to a fatal error, will generate a clean error message.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class ShutdownHandler
-{
- use DeterminesContentType;
-
- /**
- * @var ContainerInterface The global container object, which holds all your services.
- */
- protected $ci;
-
- /**
- * @var bool
- */
- protected $displayErrorInfo;
-
- /**
- * Constructor.
- *
- * @param ContainerInterface $ci The global container object, which holds all your services.
- * @param bool $displayErrorInfo
- */
- public function __construct(ContainerInterface $ci, $displayErrorInfo) {
- $this->ci = $ci;
- $this->displayErrorInfo = $displayErrorInfo;
- }
-
- /**
- * Register this class with the shutdown handler.
- *
- * @return void
- */
- public function register() {
- register_shutdown_function([$this, 'fatalHandler']);
- }
-
- /**
- * Set up the fatal error handler, so that we get a clean error message and alert instead of a WSOD.
- */
- public function fatalHandler() {
- $error = error_get_last();
- $fatalErrorTypes = [
- E_ERROR,
- E_PARSE,
- E_CORE_ERROR,
- E_COMPILE_ERROR,
- E_RECOVERABLE_ERROR
- ];
-
- // Handle fatal errors and parse errors
- if ($error !== NULL && in_array($error['type'], $fatalErrorTypes)) {
-
- // Build the appropriate error message (debug or client)
- if ($this->displayErrorInfo) {
- $errorMessage = $this->buildErrorInfoMessage($error);
- } else {
- $errorMessage = "Oops, looks like our server might have goofed. If you're an admin, please ensure that <code>php.log_errors</code> is enabled, and then check the <strong>PHP</strong> error log.";
- }
-
- // For CLI, just print the message and exit.
- if (php_sapi_name() === 'cli') {
- exit($errorMessage . PHP_EOL);
- }
-
- // For all other environments, print a debug response for the requested data type
- echo $this->buildErrorPage($errorMessage);
-
- // If this is an AJAX request and AJAX debugging is turned off, write message to the alert stream
- if ($this->ci->request->isXhr() && !$this->ci->config['site.debug.ajax']) {
- if ($this->ci->alerts && is_object($this->ci->alerts)) {
- $this->ci->alerts->addMessageTranslated('danger', $errorMessage);
- }
- }
-
- header('HTTP/1.1 500 Internal Server Error');
- exit();
- }
- }
-
- /**
- * Build the error message string.
- *
- * @param array $error
- * @return string
- */
- protected function buildErrorInfoMessage(array $error) {
- $errfile = $error['file'];
- $errline = (string)$error['line'];
- $errstr = $error['message'];
-
- $errorTypes = [
- E_ERROR => 'Fatal error',
- E_PARSE => 'Parse error',
- E_CORE_ERROR => 'PHP core error',
- E_COMPILE_ERROR => 'Zend compile error',
- E_RECOVERABLE_ERROR => 'Catchable fatal error'
- ];
-
- return "<strong>" . $errorTypes[$error['type']] . "</strong>: $errstr in <strong>$errfile</strong> on line <strong>$errline</strong>";
- }
-
- /**
- * Build an error response of the appropriate type as determined by the request's Accept header.
- *
- * @param string $message
- * @return string
- */
- protected function buildErrorPage($message) {
- $contentType = $this->determineContentType($this->ci->request, $this->ci->config['site.debug.ajax']);
-
- switch ($contentType) {
- case 'application/json':
- $error = ['message' => $message];
- return json_encode($error, JSON_PRETTY_PRINT);
-
- case 'text/html':
- return $this->buildHtmlErrorPage($message);
-
- default:
- case 'text/plain':
- return $message;
- }
- }
-
- /**
- * Build an HTML error page from an error string.
- *
- * @param string $errorMessage
- * @return string
- */
- protected function buildHtmlErrorPage($message) {
- $title = 'UserFrosting Application Error';
- $html = "<p>$message</p>";
-
- return sprintf(
- "<html><head><meta http-equiv='Content-Type' content='text/html; charset=utf-8'>" .
- "<title>%s</title><style>body{margin:0;padding:30px;font:12px/1.5 Helvetica,Arial,Verdana," .
- "sans-serif;}h1{margin:0;font-size:48px;font-weight:normal;line-height:48px;}" .
- "</style></head><body><h1>%s</h1>%s</body></html>",
- $title,
- $title,
- $html
- );
- }
-}
+<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Core\Util;
+
+use Interop\Container\ContainerInterface;
+use UserFrosting\Sprinkle\Core\Http\Concerns\DeterminesContentType;
+
+/**
+ * Registers a handler to be invoked whenever the application shuts down.
+ * If it shut down due to a fatal error, will generate a clean error message.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class ShutdownHandler
+{
+ use DeterminesContentType;
+
+ /**
+ * @var ContainerInterface The global container object, which holds all your services.
+ */
+ protected $ci;
+
+ /**
+ * @var bool
+ */
+ protected $displayErrorInfo;
+
+ /**
+ * Constructor.
+ *
+ * @param ContainerInterface $ci The global container object, which holds all your services.
+ * @param bool $displayErrorInfo
+ */
+ public function __construct(ContainerInterface $ci, $displayErrorInfo) {
+ $this->ci = $ci;
+ $this->displayErrorInfo = $displayErrorInfo;
+ }
+
+ /**
+ * Register this class with the shutdown handler.
+ *
+ * @return void
+ */
+ public function register() {
+ register_shutdown_function([$this, 'fatalHandler']);
+ }
+
+ /**
+ * Set up the fatal error handler, so that we get a clean error message and alert instead of a WSOD.
+ */
+ public function fatalHandler() {
+ $error = error_get_last();
+ $fatalErrorTypes = [
+ E_ERROR,
+ E_PARSE,
+ E_CORE_ERROR,
+ E_COMPILE_ERROR,
+ E_RECOVERABLE_ERROR
+ ];
+
+ // Handle fatal errors and parse errors
+ if ($error !== NULL && in_array($error['type'], $fatalErrorTypes)) {
+
+ // Build the appropriate error message (debug or client)
+ if ($this->displayErrorInfo) {
+ $errorMessage = $this->buildErrorInfoMessage($error);
+ } else {
+ $errorMessage = "Oops, looks like our server might have goofed. If you're an admin, please ensure that <code>php.log_errors</code> is enabled, and then check the <strong>PHP</strong> error log.";
+ }
+
+ // For CLI, just print the message and exit.
+ if (php_sapi_name() === 'cli') {
+ exit($errorMessage . PHP_EOL);
+ }
+
+ // For all other environments, print a debug response for the requested data type
+ echo $this->buildErrorPage($errorMessage);
+
+ // If this is an AJAX request and AJAX debugging is turned off, write message to the alert stream
+ if ($this->ci->request->isXhr() && !$this->ci->config['site.debug.ajax']) {
+ if ($this->ci->alerts && is_object($this->ci->alerts)) {
+ $this->ci->alerts->addMessageTranslated('danger', $errorMessage);
+ }
+ }
+
+ header('HTTP/1.1 500 Internal Server Error');
+ exit();
+ }
+ }
+
+ /**
+ * Build the error message string.
+ *
+ * @param array $error
+ * @return string
+ */
+ protected function buildErrorInfoMessage(array $error) {
+ $errfile = $error['file'];
+ $errline = (string)$error['line'];
+ $errstr = $error['message'];
+
+ $errorTypes = [
+ E_ERROR => 'Fatal error',
+ E_PARSE => 'Parse error',
+ E_CORE_ERROR => 'PHP core error',
+ E_COMPILE_ERROR => 'Zend compile error',
+ E_RECOVERABLE_ERROR => 'Catchable fatal error'
+ ];
+
+ return "<strong>" . $errorTypes[$error['type']] . "</strong>: $errstr in <strong>$errfile</strong> on line <strong>$errline</strong>";
+ }
+
+ /**
+ * Build an error response of the appropriate type as determined by the request's Accept header.
+ *
+ * @param string $message
+ * @return string
+ */
+ protected function buildErrorPage($message) {
+ $contentType = $this->determineContentType($this->ci->request, $this->ci->config['site.debug.ajax']);
+
+ switch ($contentType) {
+ case 'application/json':
+ $error = ['message' => $message];
+ return json_encode($error, JSON_PRETTY_PRINT);
+
+ case 'text/html':
+ return $this->buildHtmlErrorPage($message);
+
+ default:
+ case 'text/plain':
+ return $message;
+ }
+ }
+
+ /**
+ * Build an HTML error page from an error string.
+ *
+ * @param string $errorMessage
+ * @return string
+ */
+ protected function buildHtmlErrorPage($message) {
+ $title = 'UserFrosting Application Error';
+ $html = "<p>$message</p>";
+
+ return sprintf(
+ "<html><head><meta http-equiv='Content-Type' content='text/html; charset=utf-8'>" .
+ "<title>%s</title><style>body{margin:0;padding:30px;font:12px/1.5 Helvetica,Arial,Verdana," .
+ "sans-serif;}h1{margin:0;font-size:48px;font-weight:normal;line-height:48px;}" .
+ "</style></head><body><h1>%s</h1>%s</body></html>",
+ $title,
+ $title,
+ $html
+ );
+ }
+}
diff --git a/main/app/sprinkles/core/src/Util/Util.php b/main/app/sprinkles/core/src/Util/Util.php
index 0db3b72..0cf3a56 100644
--- a/main/app/sprinkles/core/src/Util/Util.php
+++ b/main/app/sprinkles/core/src/Util/Util.php
@@ -1,174 +1,174 @@
-<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Core\Util;
-
-/**
- * Util Class
- *
- * Static utility functions.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class Util
-{
- /**
- * Extracts specific fields from one associative array, and places them into another.
- *
- * @param mixed[] $inputArray
- * @param string[] $fieldArray
- * @param bool $remove
- * @return mixed[]
- */
- static public function extractFields(&$inputArray, $fieldArray, $remove = TRUE) {
- $result = [];
-
- foreach ($fieldArray as $name) {
- if (array_key_exists($name, $inputArray)) {
- $result[$name] = $inputArray[$name];
-
- // Optionally remove value from input array
- if ($remove) {
- unset($inputArray[$name]);
- }
- }
- }
-
- return $result;
- }
-
- /**
- * Extracts numeric portion of a string (for example, for normalizing phone numbers).
- *
- * @param string $str
- * @return string
- */
- static public function extractDigits($str) {
- return preg_replace('/[^0-9]/', '', $str);
- }
-
- /**
- * Formats a phone number as a standard 7- or 10-digit string (xxx) xxx-xxxx
- *
- * @param string $phone
- * @return string
- */
- static public function formatPhoneNumber($phone) {
- $num = static::extractDigits($phone);
-
- $len = strlen($num);
-
- if ($len == 7) {
- $num = preg_replace('/([0-9]{3})([0-9]{4})/', '$1-$2', $num);
- } else if ($len == 10) {
- $num = preg_replace('/([0-9]{3})([0-9]{3})([0-9]{4})/', '($1) $2-$3', $num);
- }
-
- return $num;
- }
-
- /**
- * Nicely format an array for printing.
- * See https://stackoverflow.com/a/9776726/2970321
- *
- * @param array $arr
- * @return string
- */
- static public function prettyPrintArray(array $arr) {
- $json = json_encode($arr);
- $result = '';
- $level = 0;
- $inQuotes = FALSE;
- $inEscape = FALSE;
- $endsLineLevel = NULL;
- $jsonLength = strlen($json);
-
- for ($i = 0; $i < $jsonLength; $i++) {
- $char = $json[$i];
- $newLineLevel = NULL;
- $post = '';
- if ($endsLineLevel !== NULL) {
- $newLineLevel = $endsLineLevel;
- $endsLineLevel = NULL;
- }
- if ($inEscape) {
- $inEscape = FALSE;
- } else if ($char === '"') {
- $inQuotes = !$inQuotes;
- } else if (!$inQuotes) {
- switch ($char) {
- case '}':
- case ']':
- $level--;
- $endsLineLevel = NULL;
- $newLineLevel = $level;
- break;
-
- case '{':
- case '[':
- $level++;
-
- case ',':
- $endsLineLevel = $level;
- break;
-
- case ':':
- $post = ' ';
- break;
-
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- $char = '';
- $endsLineLevel = $newLineLevel;
- $newLineLevel = NULL;
- break;
- }
- } else if ($char === '\\') {
- $inEscape = TRUE;
- }
-
- if ($newLineLevel !== NULL) {
- $result .= '<br>' . str_repeat('&nbsp;&nbsp;', $newLineLevel);
- }
-
- $result .= $char . $post;
- }
-
- return $result;
- }
-
- /**
- * Generate a random phrase, consisting of a specified number of adjectives, followed by a noun.
- *
- * @param int $numAdjectives
- * @param int $maxLength
- * @param int $maxTries
- * @param string $separator
- * @return string
- */
- static public function randomPhrase($numAdjectives, $maxLength = 9999999, $maxTries = 10, $separator = '-') {
- $adjectives = include('extra://adjectives.php');
- $nouns = include('extra://nouns.php');
-
- for ($n = 0; $n < $maxTries; $n++) {
- $keys = array_rand($adjectives, $numAdjectives);
- $matches = array_only($adjectives, $keys);
-
- $result = implode($separator, $matches);
- $result .= $separator . $nouns[array_rand($nouns)];
- $result = str_slug($result, $separator);
- if (strlen($result) < $maxLength) {
- return $result;
- }
- }
-
- return '';
- }
-}
+<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Core\Util;
+
+/**
+ * Util Class
+ *
+ * Static utility functions.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class Util
+{
+ /**
+ * Extracts specific fields from one associative array, and places them into another.
+ *
+ * @param mixed[] $inputArray
+ * @param string[] $fieldArray
+ * @param bool $remove
+ * @return mixed[]
+ */
+ static public function extractFields(&$inputArray, $fieldArray, $remove = TRUE) {
+ $result = [];
+
+ foreach ($fieldArray as $name) {
+ if (array_key_exists($name, $inputArray)) {
+ $result[$name] = $inputArray[$name];
+
+ // Optionally remove value from input array
+ if ($remove) {
+ unset($inputArray[$name]);
+ }
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Extracts numeric portion of a string (for example, for normalizing phone numbers).
+ *
+ * @param string $str
+ * @return string
+ */
+ static public function extractDigits($str) {
+ return preg_replace('/[^0-9]/', '', $str);
+ }
+
+ /**
+ * Formats a phone number as a standard 7- or 10-digit string (xxx) xxx-xxxx
+ *
+ * @param string $phone
+ * @return string
+ */
+ static public function formatPhoneNumber($phone) {
+ $num = static::extractDigits($phone);
+
+ $len = strlen($num);
+
+ if ($len == 7) {
+ $num = preg_replace('/([0-9]{3})([0-9]{4})/', '$1-$2', $num);
+ } else if ($len == 10) {
+ $num = preg_replace('/([0-9]{3})([0-9]{3})([0-9]{4})/', '($1) $2-$3', $num);
+ }
+
+ return $num;
+ }
+
+ /**
+ * Nicely format an array for printing.
+ * See https://stackoverflow.com/a/9776726/2970321
+ *
+ * @param array $arr
+ * @return string
+ */
+ static public function prettyPrintArray(array $arr) {
+ $json = json_encode($arr);
+ $result = '';
+ $level = 0;
+ $inQuotes = FALSE;
+ $inEscape = FALSE;
+ $endsLineLevel = NULL;
+ $jsonLength = strlen($json);
+
+ for ($i = 0; $i < $jsonLength; $i++) {
+ $char = $json[$i];
+ $newLineLevel = NULL;
+ $post = '';
+ if ($endsLineLevel !== NULL) {
+ $newLineLevel = $endsLineLevel;
+ $endsLineLevel = NULL;
+ }
+ if ($inEscape) {
+ $inEscape = FALSE;
+ } else if ($char === '"') {
+ $inQuotes = !$inQuotes;
+ } else if (!$inQuotes) {
+ switch ($char) {
+ case '}':
+ case ']':
+ $level--;
+ $endsLineLevel = NULL;
+ $newLineLevel = $level;
+ break;
+
+ case '{':
+ case '[':
+ $level++;
+
+ case ',':
+ $endsLineLevel = $level;
+ break;
+
+ case ':':
+ $post = ' ';
+ break;
+
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ $char = '';
+ $endsLineLevel = $newLineLevel;
+ $newLineLevel = NULL;
+ break;
+ }
+ } else if ($char === '\\') {
+ $inEscape = TRUE;
+ }
+
+ if ($newLineLevel !== NULL) {
+ $result .= '<br>' . str_repeat('&nbsp;&nbsp;', $newLineLevel);
+ }
+
+ $result .= $char . $post;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Generate a random phrase, consisting of a specified number of adjectives, followed by a noun.
+ *
+ * @param int $numAdjectives
+ * @param int $maxLength
+ * @param int $maxTries
+ * @param string $separator
+ * @return string
+ */
+ static public function randomPhrase($numAdjectives, $maxLength = 9999999, $maxTries = 10, $separator = '-') {
+ $adjectives = include('extra://adjectives.php');
+ $nouns = include('extra://nouns.php');
+
+ for ($n = 0; $n < $maxTries; $n++) {
+ $keys = array_rand($adjectives, $numAdjectives);
+ $matches = array_only($adjectives, $keys);
+
+ $result = implode($separator, $matches);
+ $result .= $separator . $nouns[array_rand($nouns)];
+ $result = str_slug($result, $separator);
+ if (strlen($result) < $maxLength) {
+ return $result;
+ }
+ }
+
+ return '';
+ }
+}