From 1b641b809c79699d7f54a424e9dc90b94da4c780 Mon Sep 17 00:00:00 2001 From: technicalguru Date: Fri, 20 Nov 2020 19:26:17 +0100 Subject: [PATCH 1/7] #9 Fix Exception into Throwable for stacktracing --- src/TgLog/Log.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TgLog/Log.php b/src/TgLog/Log.php index 21c4b5b..f7bf26e 100644 --- a/src/TgLog/Log.php +++ b/src/TgLog/Log.php @@ -102,7 +102,7 @@ public function __construct($logLevel = self::INFO, $appName = NULL) { protected function log($sev, $s, $o = null) { if (!is_string($s)) $s = json_encode($s, JSON_PRETTY_PRINT); if ($o != null) { - if ($o instanceof \Exception) { + if ($o instanceof \Throwable) { $s .= get_class($o).' "'.$o->getCode().' - '.$o->getMessage()."\" at\n".$o->getTraceAsString(); } else { $s .= json_encode($o, JSON_PRETTY_PRINT); From fcb015b1957a8c5e16dc783fad8a56a9b90a6771 Mon Sep 17 00:00:00 2001 From: technicalguru Date: Fri, 20 Nov 2020 19:34:01 +0100 Subject: [PATCH 2/7] #9 - Improve log message --- src/TgLog/Log.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/TgLog/Log.php b/src/TgLog/Log.php index f7bf26e..4b3d72a 100644 --- a/src/TgLog/Log.php +++ b/src/TgLog/Log.php @@ -103,9 +103,9 @@ protected function log($sev, $s, $o = null) { if (!is_string($s)) $s = json_encode($s, JSON_PRETTY_PRINT); if ($o != null) { if ($o instanceof \Throwable) { - $s .= get_class($o).' "'.$o->getCode().' - '.$o->getMessage()."\" at\n".$o->getTraceAsString(); + $s .= ': '.get_class($o).' "'.$o->getCode().' - '.$o->getMessage()."\" at\n".$o->getTraceAsString(); } else { - $s .= json_encode($o, JSON_PRETTY_PRINT); + $s .= ': '.json_encode($o, JSON_PRETTY_PRINT); } } $this->messages[$sev][] = $s; From 586d2cf1a204fccc165327926a312c87e888f183 Mon Sep 17 00:00:00 2001 From: technicalguru Date: Sun, 22 Nov 2020 08:53:46 +0100 Subject: [PATCH 3/7] #10 - Add doc and web root calculation --- src/TgUtils/Request.php | 45 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/TgUtils/Request.php b/src/TgUtils/Request.php index 0227c4b..8832f13 100644 --- a/src/TgUtils/Request.php +++ b/src/TgUtils/Request.php @@ -250,5 +250,50 @@ public function getParam($key, $default = NULL, $getPrecedes = true) { public function getElapsedTime() { return time() - $this->startTime; } + + /** + * Returns the full URL of the web root. + * @return string the URL to the root dir. + */ + public function getWebRootUrl() { + $protocol = $this->getProtocol(); + $host = $this->getHost(); + return $protocol.'://'.$host.self::getWebRoot(); + } + + /** + * Returns the document root - this is the real path name of the web root. + * @return string the document root or context document root if available. + */ + public static function getDocumentRoot() { + if (isset($_SERVER['CONTEXT_DOCUMENT_ROOT'])) { + return $_SERVER['CONTEXT_DOCUMENT_ROOT']; + } + return $_SERVER['DOCUMENT_ROOT']; + } + + /** + * Returns the web root - that is the web path where the current + * script is rooted and usually the base path for an application. + *

$_SERVER['PHP_SELF'] or $_SERVER['SCRIPT_NAME']

will + * be misleading as they would not tell the real document root.

+ * @return string the presumed web root. + */ + public static function getWebRoot($considerForwarding = TRUE) { + if ($considerForwarding) { + $rootDef = $_SERVER['HTTP_X_FORWARDED_ROOT']; + if ($rootDef) { + $arr = explode(',', $rootDef); + return $arr[1]; + } + } + $docRoot = self::getDocumentRoot(); + $fileDir = dirname($_SERVER['SCRIPT_FILENAME']); + $webRoot = substr($fileDir, strlen($docRoot)); + if (isset($_SERVER['CONTEXT'])) { + $webRoot = $_SERVER['CONTEXT'].$webRoot; + } + return $webRoot; + } } From 1b84228567873c5ce7efc158a58e6b8ad3764acf Mon Sep 17 00:00:00 2001 From: technicalguru Date: Sat, 28 Nov 2020 16:19:59 +0100 Subject: [PATCH 4/7] #11 - add constants for various time periods --- src/TgUtils/Date.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/TgUtils/Date.php b/src/TgUtils/Date.php index 2cc14fd..55db535 100644 --- a/src/TgUtils/Date.php +++ b/src/TgUtils/Date.php @@ -37,6 +37,15 @@ class Date extends \DateTime { const MONTH_ABBR = "\x023\x03"; const MONTH_NAME = "\x024\x03"; + /** Seconds per minute */ + public const SECONDS_PER_MINUTE = 60; + /** Seconds per hour */ + public const SECONDS_PER_HOUR = 3600; + /** Seconds per day */ + public const SECONDS_PER_DAY = 86400; + /** Seconds per week */ + public const SECONDS_PER_WEEK = 604800; + /** * The format string to be applied when using the __toString() magic method. * From 25b77ed5b179293414f6e18ada703b61b6e752a0 Mon Sep 17 00:00:00 2001 From: technicalguru Date: Thu, 3 Dec 2020 11:45:45 +0100 Subject: [PATCH 5/7] #12 - streamline Request object --- src/TgUtils/Request.php | 139 +++++++++++++++++++++------------------- 1 file changed, 73 insertions(+), 66 deletions(-) diff --git a/src/TgUtils/Request.php b/src/TgUtils/Request.php index 8832f13..c02ce55 100644 --- a/src/TgUtils/Request.php +++ b/src/TgUtils/Request.php @@ -19,44 +19,70 @@ class Request { */ public static function getRequest() { if (!self::$request) { - self::$request = self::createFromGlobals(); + self::$request = new Request(); } return self::$request; } + /** The protocol (http or https) */ + public $protocol; + /** The HTTP method */ + public $method; + /** All headers from the request as array */ + public $headers; + /** The host as the user requested it (can differ from $httpHost in reverse proxy setups) */ + public $host; + /** The HTTP host - the host mentioned in Host: header */ + public $httpHost; /** The URI which includes the parameters */ public $uri; /** The path of the request. Does not include parameters */ public $path; + /** The path split in its elements */ + public $pathElements; /** The parameters as a string */ public $params; - /** The language code for this request (by default: en) */ - public $langCode; + /** The path parameters (GET params) */ + public $getParams; /** The epoch time in seconds when the request was created */ public $startTime; - /** The post params of the request (intentionally not public) */ - protected $postParams; + /** The body of the request (intentionally not public) */ protected $body; + /** The post params of the request */ + protected $postParams; + + /** DEPRECATED: The language code for this request (by default: en) */ + public $langCode; /** Constructor */ public function __construct() { + // Sequence matters! + $this->method = $_SERVER['REQUEST_METHOD']; + $this->headers = getallheaders(); + $this->protocol = $this->initProtocol(); + $this->httpHost = $_SERVER['HTTP_HOST']; + $this->host = $this->initHost(); if (isset($_SERVER['REQUEST_URI'])) { - $this->uri = $_SERVER['REQUEST_URI']; + $this->uri = $_SERVER['REQUEST_URI']; } else { - $this->uri = Request::DEFAULT_REQUEST_URI; + $this->uri = Request::DEFAULT_REQUEST_URI; } - $uri_parts = explode('?', $this->uri, 2); - $this->path = $uri_parts[0]; - $this->params = count($uri_parts) > 1 ? $uri_parts[1] : ''; - $this->langCode = 'en'; - $this->postParams = null; - $this->startTime = time(); - } + $uri_parts = explode('?', $this->uri, 2); + $this->path = $uri_parts[0]; + $this->pathElements = $this->initPathElements(); + $this->params = count($uri_parts) > 1 ? $uri_parts[1] : ''; + $this->getParams = $this->initGetParams(); + $this->postParams = NULL; + $this->body = NULL; + $this->documentRoot = $this->initDocumentRoot(); + $this->webRoot = $this->initWebRoot(TRUE); + $this->localWebRoot = $this->initWebRoot(FALSE); + $this->webRootUri = $this->initWebRootUri(); + $this->startTime = time(); - /** Create the instance from global vars */ - public static function createFromGlobals() { - return new Request(); + // Will be deprecated + $this->langCode = 'en'; } /** @@ -67,30 +93,22 @@ public static function createFromGlobals() { * host is returned then.

* @return string the Host requested by the user. */ - public function getHost() { + protected function initHost() { if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) { $forwarded = explode(',', $_SERVER['HTTP_X_FORWARDED_HOST']); return trim($forwarded[count($forwarded)-1]); } - return $this->getHttpHost(); - } - - /** - * Returns the hostname as given in HTTP_HOST. - * @return string the HTTP_HOST variable. - */ - public function getHttpHost() { - return $_SERVER['HTTP_HOST']; + return $this->httpHost; } /** * Returns the protocol (http, https) being used by the user. *

The protocol can be switched at reverse proxies, that's * why the HTTP_X_FORWARDED_PROTO variable is checked. - * Otherwise t will be the REQUEST_SCHEME.

+ * Otherwise it will be the REQUEST_SCHEME.

* @return string the protocol as used by the user. */ - public function getProtocol() { + protected function initProtocol() { if (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) { return $_SERVER['HTTP_X_FORWARDED_PROTO']; } @@ -102,7 +120,7 @@ public function getProtocol() { *

E.g. /my/path/index.html will return three elements: my, path and index.

* @return array the path elements. */ - public function getPathElements() { + protected function initPathElements() { $path = substr($this->path, 1); if (substr($path, strlen($path)-5) == '.html') $path = substr($path, 0, strlen($path)-5); if (substr($path, strlen($path)-1) == '/') $path = substr($path, 0, strlen($path)-1); @@ -116,7 +134,7 @@ public function getPathElements() { * @return TRUE when parameter was set. */ public function hasGetParam($key) { - $params = $this->getParams(); + $params = $this->getParams; return isset($params[$key]); } @@ -127,7 +145,7 @@ public function hasGetParam($key) { * @return mixed the parameter value or its default. */ public function getGetParam($key, $default = NULL) { - $params = $this->getParams(); + $params = $this->getParams; return isset($params[$key]) ? $params[$key] : $default; } @@ -135,19 +153,8 @@ public function getGetParam($key, $default = NULL) { * Returns the parameters as an array. * @return array array of parameters. */ - public function getParams() { - if ($this->paramsArray == null) { - $this->paramsArray = self::parseQueryString($this->params); - } - return $this->paramsArray; - } - - /** - * Returns the request method, e.g. HEAD, GET, POST. - * @param string the request method. - */ - public function getMethod() { - return $_SERVER['REQUEST_METHOD']; + protected function initGetParams() { + return self::parseQueryString($this->params); } /** @@ -175,9 +182,9 @@ public function getPostParam($key, $default = NULL) { * @return array post parameters */ public function getPostParams() { - if ($this->postParams == null) { + if ($this->postParams == NULL) { $this->postParams = array(); - $headers = getallheaders(); + $headers = $this->headers; // Check that we have content-length if (isset($headers['Content-Length'])) { $len = intval($headers['Content-Length']); @@ -197,8 +204,8 @@ public function getPostParams() { * @return string the request body. */ public function getBody() { - if (in_array($this->getMethod(), array('POST', 'PUT'))) { - if ($this->body == null) { + if (in_array($this->method, array('POST', 'PUT'))) { + if ($this->body == NULL) { $this->body = file_get_contents('php://input'); } } @@ -222,9 +229,8 @@ public static function parseQueryString($s) { * @return string the value of the header. */ public function getHeader($key) { - $headers = getallheaders(); - if (isset($headers[$key])) return $headers[$key]; - return null; + if (isset($this->headers[$key])) return $this->headers[$key]; + return NULL; } /** @@ -250,22 +256,12 @@ public function getParam($key, $default = NULL, $getPrecedes = true) { public function getElapsedTime() { return time() - $this->startTime; } - - /** - * Returns the full URL of the web root. - * @return string the URL to the root dir. - */ - public function getWebRootUrl() { - $protocol = $this->getProtocol(); - $host = $this->getHost(); - return $protocol.'://'.$host.self::getWebRoot(); - } - + /** * Returns the document root - this is the real path name of the web root. * @return string the document root or context document root if available. */ - public static function getDocumentRoot() { + protected function initDocumentRoot() { if (isset($_SERVER['CONTEXT_DOCUMENT_ROOT'])) { return $_SERVER['CONTEXT_DOCUMENT_ROOT']; } @@ -279,7 +275,7 @@ public static function getDocumentRoot() { * be misleading as they would not tell the real document root.

* @return string the presumed web root. */ - public static function getWebRoot($considerForwarding = TRUE) { + protected function initWebRoot($considerForwarding = TRUE) { if ($considerForwarding) { $rootDef = $_SERVER['HTTP_X_FORWARDED_ROOT']; if ($rootDef) { @@ -287,7 +283,7 @@ public static function getWebRoot($considerForwarding = TRUE) { return $arr[1]; } } - $docRoot = self::getDocumentRoot(); + $docRoot = $this->documentRoot; $fileDir = dirname($_SERVER['SCRIPT_FILENAME']); $webRoot = substr($fileDir, strlen($docRoot)); if (isset($_SERVER['CONTEXT'])) { @@ -295,5 +291,16 @@ public static function getWebRoot($considerForwarding = TRUE) { } return $webRoot; } + + /** + * Returns the full URL of the web root. + * @return string the URL to the root dir. + */ + protected function initWebRootUri() { + $protocol = $this->protocol; + $host = $this->host; + return $protocol.'://'.$host.$this->webRoot; + } + } From e76033705dab1ee1970d2e580a6eb20e511e4d29 Mon Sep 17 00:00:00 2001 From: technicalguru Date: Sun, 6 Dec 2020 14:30:44 +0100 Subject: [PATCH 6/7] #12 - Add appRoot capability --- src/TgUtils/Request.php | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/TgUtils/Request.php b/src/TgUtils/Request.php index c02ce55..ec5b874 100644 --- a/src/TgUtils/Request.php +++ b/src/TgUtils/Request.php @@ -44,8 +44,20 @@ public static function getRequest() { public $params; /** The path parameters (GET params) */ public $getParams; + /** The (context) document root */ + public $documentRoot; + /** The web root as seen by the user, usually '/' or an alias or mapped path from a proxy */ + public $webRoot; + /** The web root as defined by the local web server */ + public $localWebRoot; + /** The web root URI as it can be requested by the user */ + public $webRootUri; /** The epoch time in seconds when the request was created */ public $startTime; + /** Usually the document root */ + public $appRoot; + /** relative path from docroot to the app root, usually empty */ + public $relativeAppPath; /** The body of the request (intentionally not public) */ protected $body; @@ -79,6 +91,9 @@ public function __construct() { $this->webRoot = $this->initWebRoot(TRUE); $this->localWebRoot = $this->initWebRoot(FALSE); $this->webRootUri = $this->initWebRootUri(); + $this->appRoot = $this->documentRoot; + $this->relativeAppPath = ''; + $this->startTime = time(); // Will be deprecated @@ -301,6 +316,20 @@ protected function initWebRootUri() { $host = $this->host; return $protocol.'://'.$host.$this->webRoot; } - + + /** + * Initializes the appRoot and relativeAppPath according to the root of the app. + * The appRoot can differ from document root as it can be installed in a subdir. + * @param string $appRoot - the application root directory (absolute path) + */ + public function setAppRoot($appRoot) { + $appRootLen = strlen($appRoot); + $docRootLen = strlen($this->documentRoot); + if (($docRootLen < $appRootLen) && (strpos($appRoot, $this->documentRoot) === 0)) { + $this->relativeAppPath = substr($appRoot, $docRootLen); + } else { + $this->relativeAppPath = ''; + } + } } From 1a99b5646c33dc798aef17e2109fadcbf7d4351f Mon Sep 17 00:00:00 2001 From: technicalguru Date: Fri, 11 Dec 2020 14:13:22 +0100 Subject: [PATCH 7/7] #13 - Logger interface --- src/TgLog/LogWrapper.php | 66 ++++++++++++++++++++++++++++++++++++++++ src/TgLog/Logger.php | 38 +++++++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 src/TgLog/LogWrapper.php create mode 100644 src/TgLog/Logger.php diff --git a/src/TgLog/LogWrapper.php b/src/TgLog/LogWrapper.php new file mode 100644 index 0000000..5af5e56 --- /dev/null +++ b/src/TgLog/LogWrapper.php @@ -0,0 +1,66 @@ +log = $log; + } + + /** + * @see \TgLog\Logger::warn() + */ + public function warn($s, $object = NULL) { + $this->log->logWarn($s, $object); + } + + /** + * @see \TgLog\Logger::debug() + */ + public function debug($s, $object = NULL) { + $this->log->logDebug($s, $object); + } + + /** + * @see \TgLog\Logger::error() + */ + public function error($s, $object = NULL) { + $this->log->logError($s, $object); + } + + /** + * @see \TgLog\Logger::info() + */ + public function info($s, $object = NULL) { + $this->log->logInfo($s, $object); + } +} + diff --git a/src/TgLog/Logger.php b/src/TgLog/Logger.php new file mode 100644 index 0000000..fd1835e --- /dev/null +++ b/src/TgLog/Logger.php @@ -0,0 +1,38 @@ +