From 5fe09f20b9ac600a998119c038d50980554e7167 Mon Sep 17 00:00:00 2001 From: Adaa Date: Tue, 16 Feb 2021 23:02:46 +0100 Subject: [PATCH 01/10] fix issue with deprecation --- src/Action/BaseAction.php | 17 ++- src/Action/DeleteAction.php | 7 +- src/Action/SaveAction.php | 10 +- src/Action/SoftDeleteAction.php | 5 +- src/Action/UpdateAction.php | 5 +- src/Constants/Messages.php | 8 +- src/Controller/BaseConsoleController.php | 32 ++--- src/Controller/BaseController.php | 109 ++++++++++-------- src/Data/PaginatedDataProvider.php | 2 +- src/Date/DateUtils.php | 32 ++--- src/HttpClient/BaseHttpClient.php | 32 ++--- .../Exceptions/HttpClientException.php | 2 +- src/HttpClient/TerraHttpClient.php | 26 ++--- src/HttpResponse/BaseResponse.php | 18 +-- src/HttpResponse/JSendResponse.php | 37 +++--- src/Model/BaseModel.php | 75 ++++++------ .../Exceptions/Oauth2ClientException.php | 2 +- src/OauthClient/Oauth2Client.php | 81 +++++++------ src/Template/HandlebarsTemplatingEngine.php | 2 +- .../Helpers/AppendCountableSuffixHelper.php | 5 +- src/Template/Helpers/FormatToNairaHelper.php | 2 +- src/Text/Utils.php | 27 ++--- tests/Date/DateUtilsTest.php | 18 +-- .../Exceptions/HttpClientExceptionTest.php | 2 +- tests/HttpClient/TerraHttpClientTest.php | 15 ++- tests/HttpResponse/JSendResponseTest.php | 2 +- .../Exceptions/Oauth2ClientExceptionTest.php | 2 +- tests/OauthClient/Oauth2ClientTest.php | 55 ++++++--- 28 files changed, 357 insertions(+), 273 deletions(-) diff --git a/src/Action/BaseAction.php b/src/Action/BaseAction.php index eaf409d..3f590ce 100644 --- a/src/Action/BaseAction.php +++ b/src/Action/BaseAction.php @@ -9,24 +9,23 @@ class BaseAction extends Action { - /** @var ActiveRecord $model */ - public $model; + public ActiveRecord $model; public $postData; - public $returnUrl = ''; + public string $returnUrl = ''; - public $recordNotFound = 'Record not found'; - public $errorMessage = ''; - public $successMessage = ''; + public string $recordNotFound = 'Record not found'; + public string $errorMessage = ''; + public string $successMessage = ''; /** @var bool Checks if the login is required before action is executed */ - public $requireLogin = true; + public bool $requireLogin = true; /** + * @return bool|Response * @author Olawale Lawal - * @return bool|\yii\web\Response */ - public function beforeRun() + public function beforeRun(): Response|bool { if (!$this->requireLogin) { return true; diff --git a/src/Action/DeleteAction.php b/src/Action/DeleteAction.php index 3bc90e8..5e8640b 100644 --- a/src/Action/DeleteAction.php +++ b/src/Action/DeleteAction.php @@ -6,6 +6,7 @@ namespace CottaCush\Yii2\Action; use CottaCush\Yii2\Controller\BaseController; +use yii\web\Response; /** * Class DeleteAction @@ -17,7 +18,7 @@ class DeleteAction extends BaseAction { public $deleteAttribute = 'is_active'; public $deleteStatus = 0; - public $errorMessage = 'Record not found'; + public string $errorMessage = 'Record not found'; public $extraFields = null; public $formName = ''; @@ -25,9 +26,9 @@ class DeleteAction extends BaseAction /** * @author Adegoke Obasa * @author Akinwunmi Taiwo - * @return \yii\web\Response + * @return Response */ - public function run() + public function run(): Response { /** @var BaseController $controller */ $controller = $this->controller; diff --git a/src/Action/SaveAction.php b/src/Action/SaveAction.php index 639f007..eb9fea4 100644 --- a/src/Action/SaveAction.php +++ b/src/Action/SaveAction.php @@ -7,7 +7,9 @@ use CottaCush\Yii2\Controller\BaseController; use CottaCush\Yii2\Model\BaseModel; +use Yii; use yii\helpers\Json; +use yii\web\Response; use yii\widgets\ActiveForm; /** @@ -20,11 +22,11 @@ class SaveAction extends BaseAction public $enableAjaxValidation = false; /** - * @author Adegoke Obasa + * @return string|Response * @author Akinwunmi Taiwo - * @return \yii\web\Response + * @author Adegoke Obasa */ - public function run() + public function run(): Response|string { /** @var BaseController $controller */ $controller = $this->controller; @@ -40,7 +42,7 @@ public function run() $model = new $this->model; $model->load($this->postData); - if (\Yii::$app->request->isAjax && $this->enableAjaxValidation) { + if (Yii::$app->request->isAjax && $this->enableAjaxValidation) { return Json::encode(ActiveForm::validate($model)); } diff --git a/src/Action/SoftDeleteAction.php b/src/Action/SoftDeleteAction.php index 0960558..cad338f 100644 --- a/src/Action/SoftDeleteAction.php +++ b/src/Action/SoftDeleteAction.php @@ -6,6 +6,7 @@ use CottaCush\Yii2\Controller\BaseController; use CottaCush\Yii2\Model\BaseModel; use yii\db\IntegrityException; +use yii\web\Response; class SoftDeleteAction extends DeleteAction { @@ -18,9 +19,9 @@ class SoftDeleteAction extends DeleteAction /** * @author Olawale Lawal - * @return \yii\web\Response + * @return Response */ - public function run() + public function run(): Response { /** @var BaseController $controller */ $controller = $this->controller; diff --git a/src/Action/UpdateAction.php b/src/Action/UpdateAction.php index 1d5e102..9b257cf 100644 --- a/src/Action/UpdateAction.php +++ b/src/Action/UpdateAction.php @@ -7,6 +7,7 @@ use CottaCush\Yii2\Controller\BaseController; use yii\db\IntegrityException; +use yii\web\Response; /** * Class UpdateAction @@ -21,9 +22,9 @@ class UpdateAction extends BaseAction /** * @author Adegoke Obasa * @author Akinwunmi Taiwo - * @return \yii\web\Response + * @return Response */ - public function run() + public function run(): Response { /** @var BaseController $controller */ $controller = $this->controller; diff --git a/src/Constants/Messages.php b/src/Constants/Messages.php index 4efbd88..21d855e 100644 --- a/src/Constants/Messages.php +++ b/src/Constants/Messages.php @@ -24,7 +24,7 @@ class Messages * @param string $task * @return string */ - public static function getSuccessMessage($entity, $task = self::TASK_CREATE) + public static function getSuccessMessage($entity, $task = self::TASK_CREATE): string { return sprintf('%s %s successfully', $entity, $task); } @@ -35,7 +35,7 @@ public static function getSuccessMessage($entity, $task = self::TASK_CREATE) * @param string $creationTask * @return string */ - public static function getEmptyStateMessage($entity, $creationTask = self::TASK_CREATE) + public static function getEmptyStateMessage($entity, $creationTask = self::TASK_CREATE): string { return sprintf('No %s has been %s', $entity, $creationTask); } @@ -46,12 +46,12 @@ public static function getEmptyStateMessage($entity, $creationTask = self::TASK_ * @param string $action * @return string */ - public static function getWarningMessage($entity, $action) + public static function getWarningMessage($entity, $action): string { return sprintf('Are you sure you want to %s this %s?', $action, $entity); } - public static function getIntegrityViolationMsg($entity, $task = self::TASK_DELETE) + public static function getIntegrityViolationMsg($entity, $task = self::TASK_DELETE): string { return sprintf('This %s is in use, hence cannot be %s', $entity, $task); } diff --git a/src/Controller/BaseConsoleController.php b/src/Controller/BaseConsoleController.php index 8ac7423..22ada49 100644 --- a/src/Controller/BaseConsoleController.php +++ b/src/Controller/BaseConsoleController.php @@ -2,8 +2,11 @@ namespace CottaCush\Yii2\Controller; +use Yii; +use yii\base\Action; use yii\console\Controller; use yii\db\Connection; +use yii\db\Exception; use yii\db\Query; use yii\db\Transaction; @@ -23,14 +26,14 @@ class BaseConsoleController extends Controller protected $transaction; /** - * @author Olawale Lawal - * @param \yii\base\Action $action + * @param Action $action * @return bool + * @author Olawale Lawal */ - public function beforeAction($action) + public function beforeAction(Action $action): bool { if (is_null($this->db)) { - $this->db = \Yii::$app->db; + $this->db = Yii::$app->db; } return parent::beforeAction($action); } @@ -44,6 +47,7 @@ public function beginTransaction() } /** + * @throws Exception * @author Olawale Lawal */ public function commitTransaction() @@ -67,44 +71,46 @@ public function rollbackTransaction() * @param string $returnColumn * @return false|null|string */ - public static function getColumnByField($table, $field, $value, $returnColumn = 'id') + public static function getColumnByField($table, $field, $value, $returnColumn = 'id'): bool|string|null { return (new Query)->select($returnColumn) ->from($table)->filterWhere([$field => $value]) ->scalar(); } - public function getRandomOne($table, $column, $conditions = []) + public function getRandomOne($table, $column, $conditions = []): bool|array { return (new Query)->select($column) ->from($table)->filterWhere($conditions)->orderBy('rand()')->one(); } - public function getAll($table, $columns, $conditions = []) + public function getAll($table, $columns, $conditions = []): array { return (new Query)->select($columns) ->from($table)->andFilterWhere($conditions)->all(); } /** - * @author Olawale Lawal * @param $table * @param array $columns * @return int + * @throws Exception + * @author Olawale Lawal */ - public function insert($table, array $columns) + public function insert($table, array $columns): int { return $this->db->createCommand()->insert($table, $columns)->execute(); } /** - * @author Olawale Lawal * @param $table * @param array $columns * @param array $rows - * @return int + * @return bool|int + * @throws Exception + * @author Olawale Lawal */ - public function batchInsert($table, array $columns, array $rows) + public function batchInsert($table, array $columns, array $rows): bool|int { if (empty($rows)) { return true; @@ -113,7 +119,7 @@ public function batchInsert($table, array $columns, array $rows) return $this->db->createCommand()->batchInsert($table, $columns, $rows)->execute(); } - public function stdout($string) + public function stdout($string): bool|int { parent::stdout($string . PHP_EOL); } diff --git a/src/Controller/BaseController.php b/src/Controller/BaseController.php index c52e38f..7a3ae1b 100644 --- a/src/Controller/BaseController.php +++ b/src/Controller/BaseController.php @@ -7,12 +7,21 @@ use CottaCush\Yii2\Action\UpdateAction; use CottaCush\Yii2\Constants\Messages; use CottaCush\Yii2\Model\BaseModel; +use Exception; use Lukasoppermann\Httpstatus\Httpstatus; use Yii; +use yii\base\Action; +use yii\base\ExitException; +use yii\base\InvalidConfigException; +use yii\base\Security; use yii\helpers\ArrayHelper; use yii\helpers\Html; use yii\web\Controller; +use yii\web\ForbiddenHttpException; +use yii\web\Request; use yii\web\Response; +use yii\web\Session; +use yii\web\User; /** * Class BaseController @@ -45,12 +54,12 @@ public function init() /** * Executed after action - * @author Adegoke Obasa - * @param \yii\base\Action $action + * @param Action $action * @param mixed $result * @return mixed + * @author Adegoke Obasa */ - public function afterAction($action, $result) + public function afterAction(Action $action, mixed $result): mixed { $result = parent::afterAction($action, $result); $this->setSecurityHeaders(); @@ -83,10 +92,10 @@ private function setSecurityHeaders() * @param $data * @return array */ - public function sendSuccessResponse($data) + public function sendSuccessResponse($data): array { - \Yii::$app->response->format = Response::FORMAT_JSON; - \Yii::$app->response->setStatusCode(200, $this->httpStatuses->getReasonPhrase(200)); + Yii::$app->response->format = Response::FORMAT_JSON; + Yii::$app->response->setStatusCode(200, $this->httpStatuses->getReasonPhrase(200)); return [ 'status' => 'success', @@ -104,11 +113,11 @@ public function sendSuccessResponse($data) * @param null $data * @return array */ - public function sendErrorResponse($message, $code, $httpStatusCode, $data = null) + public function sendErrorResponse($message, $code, $httpStatusCode, $data = null): array { - \Yii::$app->response->format = Response::FORMAT_JSON; - \Yii::$app->response->setStatusCode($httpStatusCode, $this->httpStatuses->getReasonPhrase($httpStatusCode)); + Yii::$app->response->format = Response::FORMAT_JSON; + Yii::$app->response->setStatusCode($httpStatusCode, $this->httpStatuses->getReasonPhrase($httpStatusCode)); $response = [ 'status' => 'error', @@ -131,10 +140,10 @@ public function sendErrorResponse($message, $code, $httpStatusCode, $data = null * @param int $httpStatusCode * @return array */ - public function sendFailResponse($data, $httpStatusCode = 500) + public function sendFailResponse($data, $httpStatusCode = 500): array { - \Yii::$app->response->format = Response::FORMAT_JSON; - \Yii::$app->response->setStatusCode($httpStatusCode, $this->httpStatuses->getReasonPhrase($httpStatusCode)); + Yii::$app->response->format = Response::FORMAT_JSON; + Yii::$app->response->setStatusCode($httpStatusCode, $this->httpStatuses->getReasonPhrase($httpStatusCode)); return [ 'status' => 'fail', @@ -176,36 +185,36 @@ protected function flash($key, $messages) Yii::$app->session->addFlash($key, $message); } } else { - \Yii::$app->session->setFlash($key, $messages); + Yii::$app->session->setFlash($key, $messages); } } /** * Get Yii2 request object + * @return \yii\console\Request|Request * @author Adegoke Obasa - * @return \yii\console\Request|\yii\web\Request */ - public function getRequest() + public function getRequest(): Request|\yii\console\Request { return Yii::$app->request; } /** * Get Yii2 response object - * @author Adegoke Obasa - * @return \yii\console\Request|\yii\web\Response + * @return \yii\console\Request|Response + *@author Adegoke Obasa */ - public function getResponse() + public function getResponse(): Response|\yii\console\Request { return Yii::$app->response; } /** * Get Yii2 session object + * @return mixed * @author Adegoke Obasa - * @return mixed|\yii\web\Session */ - public function getSession() + public function getSession(): mixed { return Yii::$app->session; } @@ -213,9 +222,9 @@ public function getSession() /** * Get Yii2 security object * @author Adegoke Obasa - * @return \yii\base\Security + * @return Security */ - public function getSecurity() + public function getSecurity(): Security { return Yii::$app->security; } @@ -235,7 +244,7 @@ public function getUser() * @param bool $sticky * @return string */ - public function showFlashMessages($sticky = false) + public function showFlashMessages($sticky = false): string { $timeout = $sticky ? 0 : 5000; $flashMessages = []; @@ -260,7 +269,7 @@ public function showFlashMessages($sticky = false) * @param $messageArray * @return string */ - protected function mergeFlashMessages($messageArray) + protected function mergeFlashMessages($messageArray): string { $messages = array_values($messageArray); $flashMessage = ''; @@ -282,17 +291,18 @@ protected function mergeFlashMessages($messageArray) /** * Returns the user for the current module * @author Adegoke Obasa - * @return \yii\web\User null|object - * @throws \yii\base\InvalidConfigException + * @return User null|object + * @throws InvalidConfigException */ - public function getModuleUser() + public function getModuleUser(): User { return $this->module->get('user'); } /** - * @author Olawale Lawal * @param $url + * @throws ExitException + * @author Olawale Lawal */ public function sendTerminalResponse($url) { @@ -302,11 +312,12 @@ public function sendTerminalResponse($url) /** * Checks if the current request is a POST and handles redirection - * @author Olawale Lawal * @param null $redirectUrl * @return bool + * @throws ExitException + * @author Olawale Lawal */ - public function isPostCheck($redirectUrl = null) + public function isPostCheck($redirectUrl = null): bool { if ($this->getRequest()->isPost) { return true; @@ -317,10 +328,14 @@ public function isPostCheck($redirectUrl = null) $this->sendTerminalResponse($redirectUrl); } - public function loginRequireBeforeAction() + /** + * @return bool + * @throws ForbiddenHttpException + * @throws Exception + */ + public function loginRequireBeforeAction(): bool { - $excludedPaths = ArrayHelper::getValue(\Yii::$app->params, 'excludedPaths', []); - + $excludedPaths = ArrayHelper::getValue(Yii::$app->params, 'excludedPaths', []); $currentRoute = $this->getRoute(); /** @@ -342,7 +357,7 @@ public function loginRequireBeforeAction() * @param null $redirectUrl * @return Response */ - public function returnError($message, $redirectUrl = null) + public function returnError($message, $redirectUrl = null): Response { $this->flashError($message); if (is_null($redirectUrl)) { @@ -357,7 +372,7 @@ public function returnError($message, $redirectUrl = null) * @param null $redirectUrl * @return Response */ - public function returnSuccess($message, $redirectUrl = null) + public function returnSuccess($message, $redirectUrl = null): Response { $this->flashSuccess($message); if (is_null($redirectUrl)) { @@ -373,7 +388,7 @@ public function returnSuccess($message, $redirectUrl = null) * @param null $redirectToOnFail URL to redirect to on fail or if request is not an ajax request * @return string */ - public function renderWidgetAsAjax($widget, $config, $redirectToOnFail = null) + public function renderWidgetAsAjax($widget, $config, $redirectToOnFail = null): string { $referrer = $this->getRequest()->getReferrer() ?: Yii::$app->homeUrl; @@ -400,13 +415,13 @@ public function renderWidgetAsAjax($widget, $config, $redirectToOnFail = null) /** * Sets a session variable and redirects to the URL - * @author Taiwo Ladipo * @param $key * @param $value * @param $redirectUrl - * @return \yii\web\Response + * @return Response + *@author Taiwo Ladipo */ - public function setSessionAndRedirect($key, $value, $redirectUrl) + public function setSessionAndRedirect($key, $value, $redirectUrl): Response { $this->getSession()->set($key, $value); return $this->redirect($redirectUrl); @@ -417,7 +432,7 @@ public function setSessionAndRedirect($key, $value, $redirectUrl) * @author Taiwo Ladipo * @return mixed */ - public function getPermissionManager() + public function getPermissionManager(): mixed { return Yii::$app->permissionManager; } @@ -431,10 +446,10 @@ public function getPermissionManager() * @param $errorMsg * @param $defaultUrl * @return bool|Response - * @throws \yii\base\ExitException - * @throws \yii\web\ForbiddenHttpException + * @throws ExitException + * @throws ForbiddenHttpException */ - public function canAccess($permissionKeys, $fullAccessKey, $errorMsg, $defaultUrl, $redirect = false) + public function canAccess($permissionKeys, $fullAccessKey, $errorMsg, $defaultUrl, $redirect = false): Response|bool { if ($this->getUser()->isGuest) { return $this->getUser()->loginRequired(); @@ -470,15 +485,17 @@ public function canAccess($permissionKeys, $fullAccessKey, $errorMsg, $defaultUr } /** - * @author Olawale Lawal * @param $model * @param $entityName * @param $actions * @param $returnUrl - * @param $formName + * @param null $formName * @return array + * @throws InvalidConfigException + * @throws Exception + * @author Olawale Lawal */ - public function generateLOVActions($model, $entityName, $actions, $returnUrl, $formName = null) + public function generateLOVActions($model, $entityName, $actions, $returnUrl, $formName = null): array { $generatedActions = []; $postData = $this->getRequest()->post(); diff --git a/src/Data/PaginatedDataProvider.php b/src/Data/PaginatedDataProvider.php index 9f4ca5b..b28d654 100644 --- a/src/Data/PaginatedDataProvider.php +++ b/src/Data/PaginatedDataProvider.php @@ -15,7 +15,7 @@ class PaginatedDataProvider extends ArrayDataProvider /** * @inheritdoc */ - protected function prepareModels() + protected function prepareModels(): array { if (($models = $this->allModels) === null) { return []; diff --git a/src/Date/DateUtils.php b/src/Date/DateUtils.php index 19fdcc7..639fd8d 100644 --- a/src/Date/DateUtils.php +++ b/src/Date/DateUtils.php @@ -3,6 +3,7 @@ namespace CottaCush\Yii2\Date; use DateTime; +use Exception; /** * Class DateUtils @@ -15,13 +16,14 @@ class DateUtils /** * Gets the difference between two date periods - * @author Olawale Lawal * @param $fromTime * @param string $toTime * @param string $format * @return string + * @throws Exception + * @author Olawale Lawal */ - public static function toRelativeTime($fromTime, $toTime = 'now', $format = 'days') + public static function toRelativeTime($fromTime, $toTime = 'now', $format = 'days'): string { $startTime = new DateTime($fromTime); $endTime = new DateTime($toTime); @@ -31,14 +33,14 @@ public static function toRelativeTime($fromTime, $toTime = 'now', $format = 'day /** * Returns date range text - * @author Adeyemi Olaoye - * @author Olawale Lawal * @param $startDate * @param $endDate * @param string $toSeparator - * @return string + * @return bool|string + * @author Adeyemi Olaoye + * @author Olawale Lawal */ - public static function getDateRangeText($startDate, $endDate, $toSeparator = 'to') + public static function getDateRangeText($startDate, $endDate, $toSeparator = 'to'): bool|string { if ($startDate == $endDate) { return self::format($startDate, DateFormat::FORMAT_SHORT); @@ -63,7 +65,7 @@ public static function getDateRangeText($startDate, $endDate, $toSeparator = 'to * @param $datetime * @return bool|string */ - public static function format($datetime, $format = DateFormat::FORMAT_SHORT) + public static function format($datetime, $format = DateFormat::FORMAT_SHORT): bool|string { $datetime = strtotime($datetime); if (!$datetime) { @@ -77,7 +79,7 @@ public static function format($datetime, $format = DateFormat::FORMAT_SHORT) * @author Adegoke Obasa * @return bool|string */ - public static function getMysqlNow() + public static function getMysqlNow(): bool|string { return self::getCurrentDateTime(DateFormat::FORMAT_MYSQL_STYLE); } @@ -88,7 +90,7 @@ public static function getMysqlNow() * @param $format * @return bool|string */ - public static function getCurrentDateTime($format) + public static function getCurrentDateTime($format): bool|string { return date($format); } @@ -98,7 +100,7 @@ public static function getCurrentDateTime($format) * @author Adegoke Obasa * @return bool|string */ - public static function getOracleNow() + public static function getOracleNow(): bool|string { return self::getCurrentDateTime(DateFormat::FORMAT_ORACLE); } @@ -111,7 +113,7 @@ public static function getOracleNow() * @param $toFormat * @return string */ - public static function convertDate($dateString, $fromFormat, $toFormat) + public static function convertDate($dateString, $fromFormat, $toFormat): string { $date = DateTime::createFromFormat($fromFormat, $dateString); if (!$date && $fromFormat == DateFormat::FORMAT_ORACLE_WITH_MICROSECONDS) { @@ -126,12 +128,12 @@ public static function convertDate($dateString, $fromFormat, $toFormat) /** * Get's the datetime in the specified format - * @author Adegoke Obasa * @param $format - * @param null|string $timestamp - * @return bool|string + * @param string $timestamp + * @return bool|string|null= + * @author Adegoke Obasa */ - public static function getDateTime($format, $timestamp = 'now') + public static function getDateTime($format, $timestamp = 'now'): bool|string|null { $date = strtotime($timestamp); if (!$date) { diff --git a/src/HttpClient/BaseHttpClient.php b/src/HttpClient/BaseHttpClient.php index cea1e24..4d21e71 100644 --- a/src/HttpClient/BaseHttpClient.php +++ b/src/HttpClient/BaseHttpClient.php @@ -7,6 +7,7 @@ use CottaCush\Yii2\HttpClient\Exceptions\HttpClientException; use CottaCush\Yii2\HttpClient\Messages\HttpClientErrorMessages; +use Exception; use linslin\yii2\curl\Curl; abstract class BaseHttpClient implements HttpClientInterface @@ -51,7 +52,7 @@ public function useJsonResponse() * @author Adegoke Obasa * @return boolean */ - public function isRawResponse() + public function isRawResponse(): bool { return $this->rawResponse; } @@ -60,7 +61,7 @@ public function isRawResponse() * @author Adegoke Obasa * @return mixed */ - public function getBaseUrl() + public function getBaseUrl(): mixed { return $this->baseUrl; } @@ -69,7 +70,7 @@ public function getBaseUrl() * @author Adegoke Obasa * @return Curl */ - public function getCurlAgent() + public function getCurlAgent(): Curl { return $this->curlAgent; } @@ -78,7 +79,7 @@ public function getCurlAgent() * @author Adegoke Obasa * @return mixed */ - public function getLastRequestUrl() + public function getLastRequestUrl(): mixed { return $this->lastRequestUrl; } @@ -87,20 +88,20 @@ public function getLastRequestUrl() * @author Adegoke Obasa * @return mixed */ - public function getLastRequestParams() + public function getLastRequestParams(): mixed { return $this->lastRequestParams; } /** * Performs GET HTTP request - * @author Adegoke Obasa * @param $url * @param array $params * @return mixed - * @throws HttpClientException + * @throws HttpClientException*@throws \Exception + * @author Adegoke Obasa */ - public function get($url, $params = []) + public function get($url, $params = []): mixed { if (!is_array($params)) { throw new HttpClientException(HttpClientErrorMessages::INVALID_QUERY_PARAMS); @@ -113,12 +114,13 @@ public function get($url, $params = []) /** * Performs POST HTTP request - * @author Adegoke Obasa * @param $url * @param $params * @return mixed + * @throws Exception + * @author Adegoke Obasa */ - public function post($url, $params) + public function post($url, $params): mixed { if (is_array($params)) { $params = $this->filterParams($params); @@ -131,12 +133,13 @@ public function post($url, $params) /** * Performs PUT HTTP request - * @author Adegoke Obasa * @param $url * @param $params * @return mixed + * @throws Exception + * @author Adegoke Obasa */ - public function put($url, $params) + public function put($url, $params): mixed { if (is_array($params)) { $params = $this->filterParams($params); @@ -149,12 +152,13 @@ public function put($url, $params) /** * Performs DELETE HTTP request - * @author Adegoke Obasa * @param $url * @param $params * @return mixed + * @throws Exception + * @author Adegoke Obasa */ - public function delete($url, $params) + public function delete($url, $params): mixed { if (is_array($params)) { $params = $this->filterParams($params); diff --git a/src/HttpClient/Exceptions/HttpClientException.php b/src/HttpClient/Exceptions/HttpClientException.php index ccb9e19..655c3f3 100644 --- a/src/HttpClient/Exceptions/HttpClientException.php +++ b/src/HttpClient/Exceptions/HttpClientException.php @@ -17,7 +17,7 @@ class HttpClientException extends Exception /** * @return string the user-friendly name of this exception */ - public function getName() + public function getName(): string { return 'HttpClientException'; } diff --git a/src/HttpClient/TerraHttpClient.php b/src/HttpClient/TerraHttpClient.php index 01f24c3..519071a 100644 --- a/src/HttpClient/TerraHttpClient.php +++ b/src/HttpClient/TerraHttpClient.php @@ -3,6 +3,7 @@ use CottaCush\Yii2\HttpClient\Exceptions\HttpClientException; use CottaCush\Yii2\HttpClient\Messages\HttpClientErrorMessages; +use JetBrains\PhpStorm\Pure; use linslin\yii2\curl\Curl; /** @@ -13,7 +14,7 @@ class TerraHttpClient extends BaseHttpClient { protected $accessToken; - protected $useOauth = true; + protected bool $useOauth = true; protected function init($baseUrl) { @@ -31,13 +32,12 @@ protected function init($baseUrl) /** * Builds request URL - * @author Adegoke Obasa * @param $url * @param array $params * @return string - * @throws HttpClientException + * @author Adegoke Obasa */ - protected function buildUrl($url, $params = []) + protected function buildUrl($url, $params = []): string { if ($this->useOauth) { $params['access_token'] = $this->getAccessToken(); @@ -50,17 +50,17 @@ protected function buildUrl($url, $params = []) * @author Adegoke Obasa * @return mixed */ - public function getAccessToken() + public function getAccessToken(): mixed { return $this->accessToken; } /** - * @author Adegoke Obasa * @param mixed $accessToken * @return $this + * @author Adegoke Obasa */ - public function setAccessToken($accessToken) + public function setAccessToken(mixed $accessToken): self { $this->accessToken = $accessToken; return $this; @@ -70,28 +70,28 @@ public function setAccessToken($accessToken) * @author Adegoke Obasa * @return boolean */ - public function isUseOauth() + public function isUseOauth(): bool { return $this->useOauth; } /** - * @author Adegoke Obasa * @param boolean $useOauth * @return $this + * @author Adegoke Obasa */ - public function setUseOauth($useOauth) + public function setUseOauth(bool $useOauth): self { $this->useOauth = $useOauth; return $this; } /** - * @author Adegoke Obasa * @param $params - * @return mixed + * @return array + *@author Adegoke Obasa */ - protected function filterParams($params) + protected function filterParams($params): array { return array_filter($params, function ($item) { return is_array($item) || is_object($item) || strlen($item); diff --git a/src/HttpResponse/BaseResponse.php b/src/HttpResponse/BaseResponse.php index 95b8f89..48770d0 100644 --- a/src/HttpResponse/BaseResponse.php +++ b/src/HttpResponse/BaseResponse.php @@ -2,6 +2,7 @@ namespace CottaCush\Yii2\HttpResponse; +use Exception; use yii\helpers\ArrayHelper; /** @@ -34,7 +35,7 @@ public function __construct($response, $responseParsed = true) * @author Adegoke Obasa * @return mixed */ - public function getRawResponse() + public function getRawResponse(): mixed { return $this->rawResponse; } @@ -43,17 +44,18 @@ public function getRawResponse() * @author Adegoke Obasa * @return mixed */ - public function getParsedResponse() + public function getParsedResponse(): mixed { return $this->parsedResponse; } /** * Returns true if response is a success response + * @return bool + * @throws Exception * @author Adegoke Obasa - * @return mixed */ - public function isSuccess() + public function isSuccess(): bool { return ArrayHelper::getValue($this->parsedResponse, $this->getStatusParam()) == $this->getSuccessValue(); } @@ -65,27 +67,27 @@ public function isSuccess() * @param null $default * @return mixed */ - abstract public function get($key, $default = null); + abstract public function get($key, $default = null): mixed; /** * Returns the Status parameter * @author Adegoke Obasa * @return mixed */ - abstract public function getStatusParam(); + abstract public function getStatusParam(): mixed; /** * Returns the value for a success status * @author Adegoke Obasa * @return mixed */ - abstract public function getSuccessValue(); + abstract public function getSuccessValue(): mixed; /** * @author Adegoke Obasa * @return boolean */ - public function isResponseParsed() + public function isResponseParsed(): bool { return $this->responseParsed; } diff --git a/src/HttpResponse/JSendResponse.php b/src/HttpResponse/JSendResponse.php index 918f6b1..b65351b 100644 --- a/src/HttpResponse/JSendResponse.php +++ b/src/HttpResponse/JSendResponse.php @@ -1,6 +1,7 @@ * @param null $defaultValue * @return mixed + * @throws Exception + * @author Adegoke Obasa */ - public function getData($defaultValue = null) + public function getData($defaultValue = null): mixed { return ArrayHelper::getValue($this->parsedResponse, self::RESPONSE_DATA_PARAM, $defaultValue); } /** * Gets the error message from the response - * @author Adegoke Obasa * @return mixed + * @throws Exception + * @author Adegoke Obasa */ - public function getErrorMessage() + public function getErrorMessage(): mixed { return ArrayHelper::getValue( $this->parsedResponse, @@ -58,22 +61,24 @@ public function getErrorMessage() /** * Gets the response code from the response - * @author Adegoke Obasa * @return mixed + * @throws Exception + * @author Adegoke Obasa */ - public function getCode() + public function getCode(): mixed { return ArrayHelper::getValue($this->parsedResponse, self::RESPONSE_CODE_PARAM, self::CODE_NO_CODE); } /** * Gets the value of key if key exists, default value otherwise - * @author Adegoke Obasa * @param $key * @param null $default * @return mixed + * @throws Exception + * @author Adegoke Obasa */ - public function get($key, $default = null) + public function get($key, $default = null): mixed { return ArrayHelper::getValue( $this->parsedResponse, @@ -84,20 +89,20 @@ public function get($key, $default = null) /** * Returns the Status parameter - * @author Adegoke Obasa - * @return mixed + * @return string + *@author Adegoke Obasa */ - public function getStatusParam() + public function getStatusParam(): string { return self::RESPONSE_STATUS_PARAM; } /** * Returns the value for a success status - * @author Adegoke Obasa - * @return mixed + * @return string + *@author Adegoke Obasa */ - public function getSuccessValue() + public function getSuccessValue(): string { return self::RESPONSE_STATUS_SUCCESS; } @@ -107,7 +112,7 @@ public function getSuccessValue() * @author Adegoke Obasa * @return string */ - public function getCodeParam() + public function getCodeParam(): string { return self::RESPONSE_CODE_PARAM; } @@ -117,7 +122,7 @@ public function getCodeParam() * @author Adegoke Obasa * @return string */ - public function getMessageParam() + public function getMessageParam(): string { return self::RESPONSE_MESSAGE_PARAM; } diff --git a/src/Model/BaseModel.php b/src/Model/BaseModel.php index 2f38b85..eb04f4c 100644 --- a/src/Model/BaseModel.php +++ b/src/Model/BaseModel.php @@ -4,6 +4,7 @@ use CottaCush\Yii2\Date\DateUtils; use CottaCush\Yii2\Text\Utils; +use Exception; use yii\data\ActiveDataProvider; use yii\db\ActiveQuery; use yii\db\ActiveRecord; @@ -11,6 +12,10 @@ /** * Class BaseModel + * @property bool|mixed|string|null updated_at + * @property bool|mixed|string|null created_at + * @property mixed|null id + * @property mixed|null is_active * @package app\models * @author Olawale Lawal * @codeCoverageIgnore @@ -21,7 +26,7 @@ class BaseModel extends ActiveRecord * @author Adeyemi Olaoye * @return bool */ - public function beforeValidate() + public function beforeValidate(): bool { if ($this->hasAttribute('updated_at')) { $this->updated_at = DateUtils::getMysqlNow(); @@ -41,7 +46,7 @@ public function beforeValidate() * @param $limit * @return ActiveQuery */ - public static function addPaginationParameters($query, $offset, $limit) + public static function addPaginationParameters($query, $offset, $limit): ActiveQuery { if (!is_null($offset)) { $query->offset($offset); @@ -56,12 +61,12 @@ public static function addPaginationParameters($query, $offset, $limit) /** * Get all model rows - * @author Adeyemi Olaoye * @param null $offset * @param null $limit - * @return array|\yii\db\ActiveRecord[] + * @return array + * @author Adeyemi Olaoye */ - public static function getAll($offset = null, $limit = null) + public static function getAll($offset = null, $limit = null): array { $query = self::find(); self::addPaginationParameters($query, $offset, $limit); @@ -77,7 +82,7 @@ public static function getAll($offset = null, $limit = null) * @param null $limit * @return ActiveDataProvider */ - public static function getAllProvider($relatedRecords = [], $sort = [], $limit = null) + public static function getAllProvider($relatedRecords = [], $sort = [], $limit = null): ActiveDataProvider { $query = self::find()->with($relatedRecords)->orderBy($sort); return self::convertToProvider($query, [], $limit); @@ -90,17 +95,15 @@ public static function getAllProvider($relatedRecords = [], $sort = [], $limit = * @param null $pageSize * @return ActiveDataProvider */ - public static function convertToProvider($query, $dataProviderSort = [], $pageSize = null) + public static function convertToProvider($query, $dataProviderSort = [], $pageSize = null): ActiveDataProvider { - $dataProvider = new ActiveDataProvider([ + return new ActiveDataProvider([ 'query' => $query, 'pagination' => [ 'defaultPageSize' => is_null($pageSize) ? self::getDefaultPageSize() : $pageSize ], 'sort' => $dataProviderSort, ]); - - return $dataProvider; } /** @@ -108,7 +111,7 @@ public static function convertToProvider($query, $dataProviderSort = [], $pageSi * @param null $countField * @return int|string */ - public static function getTotalCount($countField = null) + public static function getTotalCount($countField = null): int|string { $model = get_called_class(); $model = new $model(); @@ -125,15 +128,15 @@ public static function getTotalCount($countField = null) /** * Gets all active - * @author Adegoke Obasa - * @author Olawale Lawal - * @author Adeyemi Olaoye * @param array $orderBy * @param string $activeColumn * @param int $activeValue - * @return array|ActiveRecord[] + * @return array + * @author Olawale Lawal + * @author Adeyemi Olaoye + * @author Adegoke Obasa */ - public static function getActive($orderBy = [], $activeColumn = 'is_active', $activeValue = 1) + public static function getActive($orderBy = [], $activeColumn = 'is_active', $activeValue = 1): array { return self::findActive($orderBy, $activeColumn, $activeValue)->all(); } @@ -146,7 +149,7 @@ public static function getActive($orderBy = [], $activeColumn = 'is_active', $ac * @param int $activeValue * @return ActiveQuery */ - public static function findActive($orderBy = [], $activeColumn = 'is_active', $activeValue = 1) + public static function findActive($orderBy = [], $activeColumn = 'is_active', $activeValue = 1): ActiveQuery { /** @var self $model */ $model = get_called_class(); @@ -163,7 +166,7 @@ public static function findActive($orderBy = [], $activeColumn = 'is_active', $a * @param $value * @return self | null */ - public static function getIdByField($field, $value) + public static function getIdByField($field, $value): ?BaseModel { $result = self::find()->where([$field => $value])->limit(1)->one(); return ($result) ? $result->id : null; @@ -177,11 +180,8 @@ public static function getIdByField($field, $value) * @param string $createdAtColumn * @return array|ActiveQuery */ - public static function getByCreatedDateRange( - $startDate, - $endDate, - $createdAtColumn = 'created_at' - ) { + public static function getByCreatedDateRange($startDate, $endDate, $createdAtColumn = 'created_at'): ActiveQuery|array + { $model = get_called_class(); $model = new $model; @@ -195,31 +195,33 @@ public static function getByCreatedDateRange( /** * Get hash for model id - * @author Adeyemi Olaoye * @param $salt * @return string + * @throws Exception + * @author Adeyemi Olaoye */ - public function getIdHash($salt) + public function getIdHash($salt): string { return Utils::encodeId($this->id, $salt); } /** - * @author Olawale Lawal * @return mixed + * @throws Exception + * @author Olawale Lawal */ - public static function getDefaultPageSize() + public static function getDefaultPageSize(): mixed { return ArrayHelper::getValue(\Yii::$app->params, 'defaultPageSize', 20); } /** * Returns the first error in the model + * @param null $attribute + * @return string|null * @author Olawale Lawal - * @param string $attribute - * @return string */ - public function getFirstError($attribute = null) + public function getFirstError($attribute = null): ?string { if (!$this->errors) { return null; @@ -228,18 +230,17 @@ public function getFirstError($attribute = null) reset($errors); $firstError = current($errors); $arrayKeys = array_keys($firstError); - $error = $firstError[$arrayKeys[0]]; - return $error; + return $firstError[$arrayKeys[0]]; } return parent::getFirstError($attribute); } /** + * @return mixed * @author Olawale Lawal - * @return bool|mixed */ - public function isActive() + public function isActive(): mixed { if ($this->hasAttribute('is_active')) { return $this->is_active; @@ -265,7 +266,7 @@ public function isActive() * an array map of the value to the labels * @return array */ - public static function getDropdownMap($keyAttribute, $valueAttribute, array $default = []) + public static function getDropdownMap($keyAttribute, $valueAttribute, array $default = []): array { $map = ArrayHelper::map(self::getActive(), $keyAttribute, $valueAttribute); if ($default) { @@ -283,7 +284,7 @@ public static function getDropdownMap($keyAttribute, $valueAttribute, array $def * @return int * @throws \yii\db\Exception */ - public static function batchInsert($table, $columns, $rows) + public static function batchInsert($table, $columns, $rows): int { $db = self::getDb(); @@ -303,7 +304,7 @@ public static function batchInsert($table, $columns, $rows) * @param string $column * @return array|BaseModel|null|ActiveRecord */ - public static function fetchWithRelatedRecords($id, $relatedRecords, $column = 'id') + public static function fetchWithRelatedRecords($id, $relatedRecords, $column = 'id'): BaseModel|array|ActiveRecord|null { /** @var BaseModel $model */ $model = get_called_class(); diff --git a/src/OauthClient/Exceptions/Oauth2ClientException.php b/src/OauthClient/Exceptions/Oauth2ClientException.php index b7cbfb8..51a4f11 100644 --- a/src/OauthClient/Exceptions/Oauth2ClientException.php +++ b/src/OauthClient/Exceptions/Oauth2ClientException.php @@ -17,7 +17,7 @@ class Oauth2ClientException extends Exception /** * @return string the user-friendly name of this exception */ - public function getName() + public function getName(): string { return 'Oauth2ClientException'; } diff --git a/src/OauthClient/Oauth2Client.php b/src/OauthClient/Oauth2Client.php index d052340..55cdb2b 100644 --- a/src/OauthClient/Oauth2Client.php +++ b/src/OauthClient/Oauth2Client.php @@ -7,7 +7,7 @@ use yii\authclient\OAuth2; use yii\authclient\OAuthToken; use yii\base\Exception; -use yii\base\InvalidParamException; +use yii\base\InvalidArgumentException; use yii\helpers\ArrayHelper; /** @@ -48,8 +48,9 @@ class Oauth2Client /** * Oauth2Client constructor. - * @author Adegoke Obasa * @param array $params + * @throws \Exception + * @author Adegoke Obasa */ public function __construct($params = []) { @@ -60,12 +61,13 @@ public function __construct($params = []) /** * Handles authorize request response - * @author Adegoke Obasa * @param $response * @return mixed * @throws Oauth2ClientException + * @throws \Exception + * @author Adegoke Obasa */ - private function handleAuthorizeResponse($response) + private function handleAuthorizeResponse($response): mixed { $status = ArrayHelper::getValue($response, 'status'); @@ -83,12 +85,13 @@ private function handleAuthorizeResponse($response) /** * Authorizes and returns authorization code - * @author Adegoke Obasa * @return mixed code * @throws Oauth2ClientException - * @throws InvalidParamException + * @throws InvalidArgumentException + * @throws \Exception + * @author Adegoke Obasa */ - public function authorize() + public function authorize(): mixed { $this->validateAuthParams(); try { @@ -102,18 +105,19 @@ public function authorize() 'state' => self::STATE_ALIVE )) )->post($this->authUrl, false); - } catch (InvalidParamException $invalidParamException) { - throw new Oauth2ClientException($invalidParamException->getMessage()); + } catch (InvalidArgumentException $invalidArgumentException) { + throw new Oauth2ClientException($invalidArgumentException->getMessage()); } return $this->handleAuthorizeResponse($response); } /** - * @author Akinwunmi Taiwo * @return mixed * @throws Oauth2ClientException + * @throws \Exception + * @author Akinwunmi Taiwo */ - public function fetchAccessTokenWithClientCredentials() + public function fetchAccessTokenWithClientCredentials(): mixed { $this->validateTokenParams(); try { @@ -125,8 +129,8 @@ public function fetchAccessTokenWithClientCredentials() 'client_secret' => $this->clientSecret )) )->post($this->tokenUrl, false); - } catch (InvalidParamException $invalidParamException) { - throw new Oauth2ClientException($invalidParamException->getMessage()); + } catch (InvalidArgumentException $invalidArgumentException) { + throw new Oauth2ClientException($invalidArgumentException->getMessage()); } return $this->handleTokenResponse($response); @@ -134,12 +138,13 @@ public function fetchAccessTokenWithClientCredentials() /** * Handles token request response - * @author Adegoke Obasa * @param OAuthToken $response * @return mixed * @throws Oauth2ClientException + * @throws \Exception + * @author Adegoke Obasa */ - private function handleTokenResponse($response) + private function handleTokenResponse($response): mixed { $params = ($response instanceof OAuthToken) ? $response->getParams() : $response; $status = ArrayHelper::getValue($params, 'status'); @@ -162,7 +167,7 @@ private function handleTokenResponse($response) * @return mixed Access token * @throws Oauth2ClientException */ - public function fetchAccessToken($code) + public function fetchAccessToken($code): mixed { $this->validateTokenParams(); @@ -184,7 +189,7 @@ public function fetchAccessToken($code) * @return bool * @throws Oauth2ClientException */ - protected function validateAuthParams() + protected function validateAuthParams(): bool { if (empty($this->authUrl) || filter_var($this->authUrl, FILTER_VALIDATE_URL) === false) { throw new Oauth2ClientException(sprintf(self::INVALID_AUTH_URL, $this->authUrl)); @@ -207,7 +212,7 @@ protected function validateAuthParams() * @return bool * @throws Oauth2ClientException */ - protected function validateTokenParams() + protected function validateTokenParams(): bool { if (empty($this->tokenUrl) || filter_var($this->tokenUrl, FILTER_VALIDATE_URL) === false) { throw new Oauth2ClientException(sprintf(self::INVALID_TOKEN_URL, $this->tokenUrl)); @@ -226,8 +231,9 @@ protected function validateTokenParams() /** * - * @author Adegoke Obasa * @param $params + * @throws \Exception + * @author Adegoke Obasa */ private function setDefaultParams($params) { @@ -241,16 +247,16 @@ private function setDefaultParams($params) * @author Adegoke Obasa * @return mixed */ - public function getClientId() + public function getClientId(): mixed { return $this->clientId; } /** - * @author Adegoke Obasa * @param mixed $clientId + * @author Adegoke Obasa */ - public function setClientId($clientId) + public function setClientId(mixed $clientId) { $this->clientId = $clientId; } @@ -259,16 +265,16 @@ public function setClientId($clientId) * @author Adegoke Obasa * @return mixed */ - public function getClientSecret() + public function getClientSecret(): mixed { return $this->clientSecret; } /** - * @author Adegoke Obasa * @param mixed $clientSecret + * @author Adegoke Obasa */ - public function setClientSecret($clientSecret) + public function setClientSecret(mixed $clientSecret) { $this->clientSecret = $clientSecret; } @@ -277,16 +283,16 @@ public function setClientSecret($clientSecret) * @author Adegoke Obasa * @return mixed */ - public function getAuthUrl() + public function getAuthUrl(): mixed { return $this->authUrl; } /** - * @author Adegoke Obasa * @param mixed $authUrl + * @author Adegoke Obasa */ - public function setAuthUrl($authUrl) + public function setAuthUrl(mixed $authUrl) { $this->authUrl = $authUrl; } @@ -295,16 +301,16 @@ public function setAuthUrl($authUrl) * @author Adegoke Obasa * @return mixed */ - public function getTokenUrl() + public function getTokenUrl(): mixed { return $this->tokenUrl; } /** - * @author Adegoke Obasa * @param mixed $tokenUrl + * @author Adegoke Obasa */ - public function setTokenUrl($tokenUrl) + public function setTokenUrl(mixed $tokenUrl) { $this->tokenUrl = $tokenUrl; } @@ -313,7 +319,7 @@ public function setTokenUrl($tokenUrl) * @author Adegoke Obasa * @return OAuth2 */ - public function getOauth2() + public function getOauth2(): OAuth2 { return $this->oauth2; } @@ -322,23 +328,24 @@ public function getOauth2() * @author Adegoke Obasa * @return Curl */ - public function getCurl() + public function getCurl(): Curl { return $this->curl; } /** * Returns the access token - * @author Adegoke Obasa * @return mixed + * @throws Oauth2ClientException + * @throws \Exception + * @author Adegoke Obasa */ - public static function getAccessToken() + public static function getAccessToken(): mixed { $oauthClientParams = ArrayHelper::getValue(\Yii::$app->params, 'oauth'); $oauthClient = new Oauth2Client($oauthClientParams); $code = $oauthClient->authorize(); $token = $oauthClient->fetchAccessToken($code); - $accessToken = ArrayHelper::getValue($token, 'access_token'); - return $accessToken; + return ArrayHelper::getValue($token, 'access_token'); } } diff --git a/src/Template/HandlebarsTemplatingEngine.php b/src/Template/HandlebarsTemplatingEngine.php index 5089186..bff076b 100644 --- a/src/Template/HandlebarsTemplatingEngine.php +++ b/src/Template/HandlebarsTemplatingEngine.php @@ -23,7 +23,7 @@ public function __construct(array $options = array()) parent::__construct($options); } - public function renderTemplate($template, array $data) + public function renderTemplate($template, array $data): string { return $this->render($template, $data); } diff --git a/src/Template/Helpers/AppendCountableSuffixHelper.php b/src/Template/Helpers/AppendCountableSuffixHelper.php index 72ea5e2..41dc5fb 100644 --- a/src/Template/Helpers/AppendCountableSuffixHelper.php +++ b/src/Template/Helpers/AppendCountableSuffixHelper.php @@ -45,13 +45,12 @@ public function execute(Template $template, Context $context, $args, $source) * @param $pluralForm * @return string */ - public static function appendCountableSuffix($text, $suffix, $pluralForm) + public static function appendCountableSuffix($text, $suffix, $pluralForm): string { if (is_null($text) || !is_numeric($text)) { return $text; } - $textWithLabel = ($text > 1) ? $text . ' ' . $pluralForm : $text . ' ' . $suffix; - return $textWithLabel; + return ($text > 1) ? $text . ' ' . $pluralForm : $text . ' ' . $suffix; } } diff --git a/src/Template/Helpers/FormatToNairaHelper.php b/src/Template/Helpers/FormatToNairaHelper.php index 82d67ae..cdb3a3d 100644 --- a/src/Template/Helpers/FormatToNairaHelper.php +++ b/src/Template/Helpers/FormatToNairaHelper.php @@ -43,7 +43,7 @@ public function execute(Template $template, Context $context, $args, $source) * @param $amount * @return string */ - public static function formatToNaira($amount) + public static function formatToNaira($amount): string { if (is_null($amount) || !is_numeric($amount)) { return $amount; diff --git a/src/Text/Utils.php b/src/Text/Utils.php index dc5531d..e53cf25 100644 --- a/src/Text/Utils.php +++ b/src/Text/Utils.php @@ -3,6 +3,7 @@ namespace CottaCush\Yii2\Text; use CottaCush\Yii2\Template\HandlebarsTemplatingEngine; +use Exception; use Hashids\Hashids; use yii\helpers\ArrayHelper; use yii\helpers\Html; @@ -24,7 +25,7 @@ class Utils * @param string $char * @return string */ - public static function asteriskise($text, $untouchedLength = 6, $char = '*') + public static function asteriskise($text, $untouchedLength = 6, $char = '*'): string { $length = strlen($text); if ($length <= $untouchedLength) { @@ -47,9 +48,9 @@ public static function asteriskise($text, $untouchedLength = 6, $char = '*') * @param $salt * @param int $hashLength * @return string - * @throws \Exception + * @throws Exception */ - public static function encodeId($id, $salt, $hashLength = self::MIN_HASH_LENGTH) + public static function encodeId($id, $salt, $hashLength = self::MIN_HASH_LENGTH): string { $hashIds = new Hashids($salt, $hashLength); return $hashIds->encode($id); @@ -62,9 +63,9 @@ public static function encodeId($id, $salt, $hashLength = self::MIN_HASH_LENGTH) * @param $salt * @param int $hashLength * @return int - * @throws \Exception + * @throws Exception */ - public static function decodeId($hash, $salt, $hashLength = self::MIN_HASH_LENGTH) + public static function decodeId($hash, $salt, $hashLength = self::MIN_HASH_LENGTH): int { $hashIds = new Hashids($salt, $hashLength); return ArrayHelper::getValue($hashIds->decode($hash), '0'); @@ -80,7 +81,7 @@ public static function decodeId($hash, $salt, $hashLength = self::MIN_HASH_LENGT * @param string $tag * @return string */ - public static function getStatusHtml($status, $extraClasses = '', $baseClass = 'label', $tag = 'span') + public static function getStatusHtml($status, $extraClasses = '', $baseClass = 'label', $tag = 'span'): string { $status = strtolower($status); $statusHyphenated = implode('-', explode(' ', $status)); @@ -96,7 +97,7 @@ public static function getStatusHtml($status, $extraClasses = '', $baseClass = ' * @param $numberLength * @return string */ - public static function formatPhoneNumberToInternationalFormat($countryCode, $number, $numberLength) + public static function formatPhoneNumberToInternationalFormat($countryCode, $number, $numberLength): string { $actualNumber = substr($number, -($numberLength), $numberLength); @@ -108,22 +109,22 @@ public static function formatPhoneNumberToInternationalFormat($countryCode, $num } /** - * @author Olawale Lawal * @param array $base * @param array $challenger * @return bool + * @author Olawale Lawal */ - public static function isArrayDifferent($base, $challenger) + public static function isArrayDifferent(array $base, array $challenger): bool { return count($base) != count($challenger) || array_diff($challenger, $base); } /** - * @author Olawale Lawal * @param array $array * @return array + * @author Olawale Lawal */ - public static function flattenArray($array) + public static function flattenArray(array $array): array { $result = array(); @@ -146,7 +147,7 @@ public static function flattenArray($array) * @param $amount * @return string */ - public static function formatToNaira($amount) + public static function formatToNaira($amount): string { if (is_null($amount) || !is_numeric($amount)) { return $amount; @@ -161,7 +162,7 @@ public static function formatToNaira($amount) * @param array $params * @return string */ - public static function getActualMessage($template, array $params) + public static function getActualMessage($template, array $params): string { $engine = new HandlebarsTemplatingEngine(); return $engine->renderTemplate($template, $params); diff --git a/tests/Date/DateUtilsTest.php b/tests/Date/DateUtilsTest.php index ddf374e..3e4e4b7 100644 --- a/tests/Date/DateUtilsTest.php +++ b/tests/Date/DateUtilsTest.php @@ -15,24 +15,26 @@ class DateUtilsTest extends TestCase { public function testToRelativeTime() { - $relativeTime = DateUtils::toRelativeTime(date(DateFormat::FORMAT_MYSQL_STYLE_NO_TIME, strtotime('-1 day'))); + $relativeTime = DateUtils::toRelativeTime( + date(DateFormat::FORMAT_MYSQL_STYLE_NO_TIME, strtotime('-1 day')) + ); $this->assertEquals(1, $relativeTime); } /** - * @author Adeyemi Olaoye * @param $startDate string starting date * @param $endDate string ending date * @param $expectedDateRange string date range text * @dataProvider providerTestGetDateRangeText + * @author Adeyemi Olaoye */ - public function testGetDateRangeText($startDate, $endDate, $expectedDateRange) + public function testGetDateRangeText(string $startDate, string $endDate, string $expectedDateRange) { $dateRangeText = DateUtils::getDateRangeText($startDate, $endDate); $this->assertEquals($expectedDateRange, $dateRangeText); } - public function providerTestGetDateRangeText() + public function providerTestGetDateRangeText(): array { return [ ['2016-09-15', '2016-09-16', '15th to 16th Sep 2016'], @@ -56,7 +58,7 @@ public function testFormat($format, $actualDateText, $dateTime = '2016-09-16 11: $this->assertEquals($actualDateText, $dateText); } - public function providerTestFormat() + public function providerTestFormat(): array { return [ [DateFormat::FORMAT_MYSQL_STYLE, '2016-09-16 11:40:40'], @@ -111,14 +113,14 @@ public function testGetOracleNow() } /** - * @author Adeyemi Olaoye * @param $fromFormat * @param $toFormat * @param $expectedDateTime * @param string $dateTime * @dataProvider providerTestConvertDate + * @author Adeyemi Olaoye */ - public function testConvertDate($fromFormat, $toFormat, $expectedDateTime, $dateTime) + public function testConvertDate($fromFormat, $toFormat, $expectedDateTime, string $dateTime) { $convertedDate = DateUtils::convertDate( $dateTime, @@ -128,7 +130,7 @@ public function testConvertDate($fromFormat, $toFormat, $expectedDateTime, $date $this->assertEquals($expectedDateTime, $convertedDate); } - public function providerTestConvertDate() + public function providerTestConvertDate(): array { return [ [ diff --git a/tests/HttpClient/Exceptions/HttpClientExceptionTest.php b/tests/HttpClient/Exceptions/HttpClientExceptionTest.php index 8d1ec60..45c5ec6 100644 --- a/tests/HttpClient/Exceptions/HttpClientExceptionTest.php +++ b/tests/HttpClient/Exceptions/HttpClientExceptionTest.php @@ -3,7 +3,7 @@ * @author Adegoke Obasa */ -namespace CottaCush\Yii2\Tests\HttpClient\Exceptions; +namespace CottaCush\Yii2\Tests\OauthClient\Exceptions; use CottaCush\Yii2\HttpClient\Exceptions\HttpClientException; use PHPUnit\Framework\TestCase; diff --git a/tests/HttpClient/TerraHttpClientTest.php b/tests/HttpClient/TerraHttpClientTest.php index aa7e2c7..591dad1 100644 --- a/tests/HttpClient/TerraHttpClientTest.php +++ b/tests/HttpClient/TerraHttpClientTest.php @@ -5,6 +5,7 @@ namespace CottaCush\Yii2\Tests\HttpClient; +use CottaCush\Yii2\HttpClient\Exceptions\HttpClientException; use CottaCush\Yii2\HttpClient\TerraHttpClient; use linslin\yii2\curl\Curl; use PHPUnit\Framework\TestCase; @@ -13,11 +14,11 @@ class TerraHttpClientTest extends TestCase { const BASE_URL = "http://jsonplaceholder.typicode.com"; - private $testPostParams = ['title' => 'test', 'author' => 'test']; + private array $testPostParams = ['title' => 'test', 'author' => 'test']; const ACCESS_TOKEN = "123456"; /** @var $httpClient TerraHttpClient */ - protected $httpClient; + protected TerraHttpClient $httpClient; public function setUp(): void { @@ -26,11 +27,11 @@ public function setUp(): void } /** - * @expectedException \CottaCush\Yii2\HttpClient\Exceptions\HttpClientException * @author Adegoke Obasa */ public function testInitializeWithInvalidUrl() { + $this->expectException(HttpClientException::class); new TerraHttpClient(''); } @@ -75,6 +76,9 @@ public function testUseAccessTokenWhenUseOauthFalse() $this->assertFalse($this->httpClient->isUseOauth()); } + /** + * @throws HttpClientException + */ public function testSetAccessToken() { $this->assertNull($this->httpClient->getAccessToken()); @@ -87,6 +91,9 @@ public function testSetAccessToken() ); } + /** + * @throws HttpClientException + */ public function testBuildUrl() { $this->httpClient->get('posts', ['id' => 1]); @@ -97,11 +104,11 @@ public function testBuildUrl() } /** - * @expectedException \CottaCush\Yii2\HttpClient\Exceptions\HttpClientException * @author Adegoke Obasa */ public function testGetWithInvalidParams() { + $this->expectException(HttpClientException::class); $this->httpClient->get('posts', "Adegoke Obasa"); } diff --git a/tests/HttpResponse/JSendResponseTest.php b/tests/HttpResponse/JSendResponseTest.php index c3237d2..6f34ae5 100644 --- a/tests/HttpResponse/JSendResponseTest.php +++ b/tests/HttpResponse/JSendResponseTest.php @@ -14,7 +14,7 @@ class JSendResponseTest extends TestCase { /** @var Generator $faker */ - protected $faker; + protected Generator $faker; public function setUp(): void { diff --git a/tests/OauthClient/Exceptions/Oauth2ClientExceptionTest.php b/tests/OauthClient/Exceptions/Oauth2ClientExceptionTest.php index 2fa4ee0..e8326a8 100644 --- a/tests/OauthClient/Exceptions/Oauth2ClientExceptionTest.php +++ b/tests/OauthClient/Exceptions/Oauth2ClientExceptionTest.php @@ -3,7 +3,7 @@ * @author Adegoke Obasa */ -namespace CottaCush\Yii2\Tests\HttpClient\Exceptions; +namespace CottaCush\Yii2\Tests\OauthClient\Exceptions; use CottaCush\Yii2\OauthClient\Exceptions\Oauth2ClientException; use PHPUnit\Framework\TestCase; diff --git a/tests/OauthClient/Oauth2ClientTest.php b/tests/OauthClient/Oauth2ClientTest.php index 134de23..da17216 100644 --- a/tests/OauthClient/Oauth2ClientTest.php +++ b/tests/OauthClient/Oauth2ClientTest.php @@ -3,9 +3,11 @@ * @author Adegoke Obasa */ -namespace CottaCush\Yii2\Tests\HttpClient; +namespace CottaCush\Yii2\Tests\OauthClient; +use CottaCush\Yii2\OauthClient\Exceptions\Oauth2ClientException; use CottaCush\Yii2\OauthClient\Oauth2Client; +use Exception; use Faker\Factory; use Faker\Generator; use linslin\yii2\curl\Curl; @@ -14,9 +16,7 @@ class Oauth2ClientTest extends TestCase { - - /** @var Generator $faker */ - protected $faker; + protected Generator $faker; public function setUp(): void { @@ -36,7 +36,7 @@ public function testAuthClientIsValid() $this->assertInstanceOf(OAuth2::class, $oauth2Client->getOauth2()); } - protected function getDefaultParams() + protected function getDefaultParams(): array { return [ Oauth2Client::AUTH_URL => $this->faker->url, @@ -46,11 +46,19 @@ protected function getDefaultParams() ]; } - protected function getOauth2ClientWithDefaultParams($defaultParams) + /** + * @param $defaultParams + * @return Oauth2Client + * @throws Exception + */ + protected function getOauth2ClientWithDefaultParams($defaultParams): Oauth2Client { return new Oauth2Client($defaultParams); } + /** + * @throws Exception + */ public function testInitializeWithDefaultParams() { $defaultParams = $this->getDefaultParams(); @@ -62,6 +70,9 @@ public function testInitializeWithDefaultParams() $this->assertEquals($defaultParams[Oauth2Client::CLIENT_SECRET], $oauthClient->getClientSecret()); } + /** + * @throws Exception + */ public function testSetAndGetAuthUrl() { $oauthClient = $this->getOauth2ClientWithDefaultParams([]); @@ -70,6 +81,9 @@ public function testSetAndGetAuthUrl() $this->assertEquals($authUrl, $oauthClient->getAuthUrl()); } + /** + * @throws Exception + */ public function testSetAndGetTokenUrl() { $oauthClient = $this->getOauth2ClientWithDefaultParams([]); @@ -78,6 +92,9 @@ public function testSetAndGetTokenUrl() $this->assertEquals($tokenUrl, $oauthClient->getTokenUrl()); } + /** + * @throws Exception + */ public function testSetAndGetClientId() { $oauthClient = $this->getOauth2ClientWithDefaultParams([]); @@ -86,6 +103,9 @@ public function testSetAndGetClientId() $this->assertEquals($clientId, $oauthClient->getClientId()); } + /** + * @throws Exception + */ public function testSetAndGetClientSecret() { $oauthClient = $this->getOauth2ClientWithDefaultParams([]); @@ -95,11 +115,12 @@ public function testSetAndGetClientSecret() } /** - * @expectedException \CottaCush\Yii2\OauthClient\Exceptions\Oauth2ClientException + * @throws Exception * @author Adegoke Obasa */ public function testAuthorizeWithInvalidAuthUrl() { + $this->expectException(Oauth2ClientException::class); $oauthClient = new Oauth2Client([ Oauth2Client::CLIENT_ID => $this->faker->md5, Oauth2Client::CLIENT_SECRET => $this->faker->md5, @@ -108,11 +129,12 @@ public function testAuthorizeWithInvalidAuthUrl() } /** - * @expectedException \CottaCush\Yii2\OauthClient\Exceptions\Oauth2ClientException + * @throws Exception * @author Adegoke Obasa */ public function testAuthorizeWithInvalidClientId() { + $this->expectException(Oauth2ClientException::class); $oauthClient = new Oauth2Client([ Oauth2Client::AUTH_URL => $this->faker->url, Oauth2Client::CLIENT_SECRET => $this->faker->md5, @@ -121,22 +143,23 @@ public function testAuthorizeWithInvalidClientId() } /** - * @expectedException \CottaCush\Yii2\OauthClient\Exceptions\Oauth2ClientException * @author Adegoke Obasa */ public function testAuthorizeFailure() { + $this->expectException(Oauth2ClientException::class); $oauthClient = $this->getOauth2ClientWithDefaultParams($this->getDefaultParams()); $oauthClient->setAuthUrl("http://localhost"); // Set to a url that doesn't exist $oauthClient->authorize(); } /** - * @expectedException \CottaCush\Yii2\OauthClient\Exceptions\Oauth2ClientException + * @throws Exception * @author Adegoke Obasa */ public function testAuthorizeWithClientSecret() { + $this->expectException(Oauth2ClientException::class); $oauthClient = new Oauth2Client([ Oauth2Client::AUTH_URL => $this->faker->url, Oauth2Client::CLIENT_ID => $this->faker->md5, @@ -145,11 +168,12 @@ public function testAuthorizeWithClientSecret() } /** - * @expectedException \CottaCush\Yii2\OauthClient\Exceptions\Oauth2ClientException + * @throws Exception * @author Adegoke Obasa */ public function testFetchTokenWithInvalidTokenUrl() { + $this->expectException(Oauth2ClientException::class); $oauthClient = new Oauth2Client([ Oauth2Client::CLIENT_ID => $this->faker->md5, Oauth2Client::CLIENT_SECRET => $this->faker->md5, @@ -158,11 +182,12 @@ public function testFetchTokenWithInvalidTokenUrl() } /** - * @expectedException \CottaCush\Yii2\OauthClient\Exceptions\Oauth2ClientException + * @throws Exception * @author Adegoke Obasa */ public function testFetchTokenWithInvalidClientId() { + $this->expectException(Oauth2ClientException::class); $oauthClient = new Oauth2Client([ Oauth2Client::TOKEN_URL => $this->faker->url, Oauth2Client::CLIENT_SECRET => $this->faker->md5, @@ -171,11 +196,12 @@ public function testFetchTokenWithInvalidClientId() } /** - * @expectedException \CottaCush\Yii2\OauthClient\Exceptions\Oauth2ClientException + * @throws Exception * @author Adegoke Obasa */ public function testFetchTokenWithInvalidClientSecret() { + $this->expectException(Oauth2ClientException::class); $oauthClient = new Oauth2Client([ Oauth2Client::TOKEN_URL => $this->faker->url, Oauth2Client::CLIENT_ID => $this->faker->md5, @@ -184,11 +210,12 @@ public function testFetchTokenWithInvalidClientSecret() } /** - * @expectedException \CottaCush\Yii2\OauthClient\Exceptions\Oauth2ClientException + * @throws Exception * @author Akinwunmi Taiwo */ public function testFetchTokenWithClientGrantType() { + $this->expectException(Oauth2ClientException::class); $oauthClient = new Oauth2Client([ Oauth2Client::TOKEN_URL => $this->faker->url, Oauth2Client::CLIENT_ID => $this->faker->md5, From 768c7ca3d8dd03eef50382d0e4fded3257fddfe6 Mon Sep 17 00:00:00 2001 From: Adaa Date: Wed, 17 Feb 2021 10:46:07 +0100 Subject: [PATCH 02/10] fix issue with deprecation --- src/Controller/BaseController.php | 2 +- src/HttpClient/TerraHttpClient.php | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Controller/BaseController.php b/src/Controller/BaseController.php index 7a3ae1b..8995e5a 100644 --- a/src/Controller/BaseController.php +++ b/src/Controller/BaseController.php @@ -202,7 +202,7 @@ public function getRequest(): Request|\yii\console\Request /** * Get Yii2 response object * @return \yii\console\Request|Response - *@author Adegoke Obasa + * @author Adegoke Obasa */ public function getResponse(): Response|\yii\console\Request { diff --git a/src/HttpClient/TerraHttpClient.php b/src/HttpClient/TerraHttpClient.php index 519071a..2132408 100644 --- a/src/HttpClient/TerraHttpClient.php +++ b/src/HttpClient/TerraHttpClient.php @@ -3,7 +3,6 @@ use CottaCush\Yii2\HttpClient\Exceptions\HttpClientException; use CottaCush\Yii2\HttpClient\Messages\HttpClientErrorMessages; -use JetBrains\PhpStorm\Pure; use linslin\yii2\curl\Curl; /** From b4f4ea2fde81590dcd2b2f921c955a54127de53f Mon Sep 17 00:00:00 2001 From: Adaa Date: Wed, 17 Feb 2021 11:03:05 +0100 Subject: [PATCH 03/10] fix issue with deprecation --- src/Model/BaseModel.php | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/Model/BaseModel.php b/src/Model/BaseModel.php index eb04f4c..0d83a31 100644 --- a/src/Model/BaseModel.php +++ b/src/Model/BaseModel.php @@ -75,12 +75,13 @@ public static function getAll($offset = null, $limit = null): array /** * Get all model rows with the - * @author Adeyemi Olaoye - * @author Olawale Lawal * @param array $relatedRecords - * @param array|null $sort + * @param array $sort * @param null $limit * @return ActiveDataProvider + * @throws Exception + * @author Olawale Lawal + * @author Adeyemi Olaoye */ public static function getAllProvider($relatedRecords = [], $sort = [], $limit = null): ActiveDataProvider { @@ -89,11 +90,12 @@ public static function getAllProvider($relatedRecords = [], $sort = [], $limit = } /** - * @author Olawale Lawal * @param $query * @param array $dataProviderSort * @param null $pageSize * @return ActiveDataProvider + * @throws Exception + * @author Olawale Lawal */ public static function convertToProvider($query, $dataProviderSort = [], $pageSize = null): ActiveDataProvider { @@ -180,8 +182,11 @@ public static function getIdByField($field, $value): ?BaseModel * @param string $createdAtColumn * @return array|ActiveQuery */ - public static function getByCreatedDateRange($startDate, $endDate, $createdAtColumn = 'created_at'): ActiveQuery|array - { + public static function getByCreatedDateRange( + $startDate, + $endDate, + $createdAtColumn = 'created_at' + ): ActiveQuery|array { $model = get_called_class(); $model = new $model; @@ -304,8 +309,11 @@ public static function batchInsert($table, $columns, $rows): int * @param string $column * @return array|BaseModel|null|ActiveRecord */ - public static function fetchWithRelatedRecords($id, $relatedRecords, $column = 'id'): BaseModel|array|ActiveRecord|null - { + public static function fetchWithRelatedRecords( + $id, + $relatedRecords, + $column = 'id' + ): BaseModel|array|ActiveRecord|null { /** @var BaseModel $model */ $model = get_called_class(); $model = $model::find()->where([$model::tableName() . '.' . $column => $id]) From 677e906bb74800aa8724d92fb20da7bb5b8aabfa Mon Sep 17 00:00:00 2001 From: Adaa Date: Fri, 19 Feb 2021 22:38:36 +0100 Subject: [PATCH 04/10] fix issue with deprecation --- src/Action/BaseAction.php | 2 + src/Action/DeleteAction.php | 4 +- src/Action/SaveAction.php | 2 + src/Action/SoftDeleteAction.php | 4 +- src/Action/UpdateAction.php | 4 +- src/Constants/Messages.php | 5 ++ src/Controller/BaseConsoleController.php | 2 +- src/Date/DateUtils.php | 2 +- src/HttpClient/BaseHttpClient.php | 7 ++- src/HttpClient/TerraHttpClient.php | 4 ++ tests/Date/DateUtilsTest.php | 4 ++ .../Exceptions/HttpClientExceptionTest.php | 2 +- tests/HttpClient/TerraHttpClientTest.php | 34 +++++++++++ tests/HttpResponse/JSendResponseTest.php | 61 +++++++++++++++++++ tests/OauthClient/Oauth2ClientTest.php | 1 + 15 files changed, 129 insertions(+), 9 deletions(-) diff --git a/src/Action/BaseAction.php b/src/Action/BaseAction.php index 3f590ce..f9687aa 100644 --- a/src/Action/BaseAction.php +++ b/src/Action/BaseAction.php @@ -5,6 +5,7 @@ use CottaCush\Yii2\Controller\BaseController; use yii\base\Action; use yii\db\ActiveRecord; +use yii\web\ForbiddenHttpException; use yii\web\Response; class BaseAction extends Action @@ -23,6 +24,7 @@ class BaseAction extends Action /** * @return bool|Response + * @throws ForbiddenHttpException * @author Olawale Lawal */ public function beforeRun(): Response|bool diff --git a/src/Action/DeleteAction.php b/src/Action/DeleteAction.php index 5e8640b..c637812 100644 --- a/src/Action/DeleteAction.php +++ b/src/Action/DeleteAction.php @@ -6,6 +6,7 @@ namespace CottaCush\Yii2\Action; use CottaCush\Yii2\Controller\BaseController; +use yii\base\ExitException; use yii\web\Response; /** @@ -24,9 +25,10 @@ class DeleteAction extends BaseAction public $formName = ''; /** + * @return Response + * @throws ExitException * @author Adegoke Obasa * @author Akinwunmi Taiwo - * @return Response */ public function run(): Response { diff --git a/src/Action/SaveAction.php b/src/Action/SaveAction.php index eb9fea4..fe0f0f7 100644 --- a/src/Action/SaveAction.php +++ b/src/Action/SaveAction.php @@ -8,6 +8,7 @@ use CottaCush\Yii2\Controller\BaseController; use CottaCush\Yii2\Model\BaseModel; use Yii; +use yii\base\ExitException; use yii\helpers\Json; use yii\web\Response; use yii\widgets\ActiveForm; @@ -23,6 +24,7 @@ class SaveAction extends BaseAction /** * @return string|Response + * @throws ExitException * @author Akinwunmi Taiwo * @author Adegoke Obasa */ diff --git a/src/Action/SoftDeleteAction.php b/src/Action/SoftDeleteAction.php index cad338f..eb93a8e 100644 --- a/src/Action/SoftDeleteAction.php +++ b/src/Action/SoftDeleteAction.php @@ -5,6 +5,7 @@ use CottaCush\Yii2\Constants\Messages; use CottaCush\Yii2\Controller\BaseController; use CottaCush\Yii2\Model\BaseModel; +use yii\base\ExitException; use yii\db\IntegrityException; use yii\web\Response; @@ -18,8 +19,9 @@ class SoftDeleteAction extends DeleteAction public $integrityViolationMessage = Messages::RECORD_USED_ALREADY; /** - * @author Olawale Lawal * @return Response + * @throws ExitException + * @author Olawale Lawal */ public function run(): Response { diff --git a/src/Action/UpdateAction.php b/src/Action/UpdateAction.php index 9b257cf..d32c5aa 100644 --- a/src/Action/UpdateAction.php +++ b/src/Action/UpdateAction.php @@ -6,6 +6,7 @@ namespace CottaCush\Yii2\Action; use CottaCush\Yii2\Controller\BaseController; +use yii\base\ExitException; use yii\db\IntegrityException; use yii\web\Response; @@ -20,9 +21,10 @@ class UpdateAction extends BaseAction public $integrityExceptionMessage = 'Record cannot be updated as it is in use elsewhere'; /** + * @return Response + * @throws ExitException * @author Adegoke Obasa * @author Akinwunmi Taiwo - * @return Response */ public function run(): Response { diff --git a/src/Constants/Messages.php b/src/Constants/Messages.php index 21d855e..472dcb9 100644 --- a/src/Constants/Messages.php +++ b/src/Constants/Messages.php @@ -51,6 +51,11 @@ public static function getWarningMessage($entity, $action): string return sprintf('Are you sure you want to %s this %s?', $action, $entity); } + /** + * @param $entity + * @param string $task + * @return string + */ public static function getIntegrityViolationMsg($entity, $task = self::TASK_DELETE): string { return sprintf('This %s is in use, hence cannot be %s', $entity, $task); diff --git a/src/Controller/BaseConsoleController.php b/src/Controller/BaseConsoleController.php index 22ada49..ec2ca32 100644 --- a/src/Controller/BaseConsoleController.php +++ b/src/Controller/BaseConsoleController.php @@ -119,7 +119,7 @@ public function batchInsert($table, array $columns, array $rows): bool|int return $this->db->createCommand()->batchInsert($table, $columns, $rows)->execute(); } - public function stdout($string): bool|int + public function stdout($string): void { parent::stdout($string . PHP_EOL); } diff --git a/src/Date/DateUtils.php b/src/Date/DateUtils.php index 639fd8d..ad12341 100644 --- a/src/Date/DateUtils.php +++ b/src/Date/DateUtils.php @@ -130,7 +130,7 @@ public static function convertDate($dateString, $fromFormat, $toFormat): string * Get's the datetime in the specified format * @param $format * @param string $timestamp - * @return bool|string|null= + * @return bool|string|null * @author Adegoke Obasa */ public static function getDateTime($format, $timestamp = 'now'): bool|string|null diff --git a/src/HttpClient/BaseHttpClient.php b/src/HttpClient/BaseHttpClient.php index 4d21e71..9e467cf 100644 --- a/src/HttpClient/BaseHttpClient.php +++ b/src/HttpClient/BaseHttpClient.php @@ -33,7 +33,7 @@ abstract protected function filterParams($params); /** * @author Adegoke Obasa */ - public function useRawResponse() + public function useRawResponse(): self { $this->rawResponse = true; return $this; @@ -42,7 +42,7 @@ public function useRawResponse() /** * @author Adegoke Obasa */ - public function useJsonResponse() + public function useJsonResponse(): self { $this->rawResponse = false; return $this; @@ -98,7 +98,8 @@ public function getLastRequestParams(): mixed * @param $url * @param array $params * @return mixed - * @throws HttpClientException*@throws \Exception + * @throws HttpClientException + * @throws Exception * @author Adegoke Obasa */ public function get($url, $params = []): mixed diff --git a/src/HttpClient/TerraHttpClient.php b/src/HttpClient/TerraHttpClient.php index 2132408..4a53a68 100644 --- a/src/HttpClient/TerraHttpClient.php +++ b/src/HttpClient/TerraHttpClient.php @@ -15,6 +15,10 @@ class TerraHttpClient extends BaseHttpClient protected $accessToken; protected bool $useOauth = true; + /** + * @param $baseUrl + * @throws HttpClientException + */ protected function init($baseUrl) { if (filter_var($baseUrl, FILTER_VALIDATE_URL) === false) { diff --git a/tests/Date/DateUtilsTest.php b/tests/Date/DateUtilsTest.php index 3e4e4b7..0deb899 100644 --- a/tests/Date/DateUtilsTest.php +++ b/tests/Date/DateUtilsTest.php @@ -4,6 +4,7 @@ use CottaCush\Yii2\Date\DateFormat; use CottaCush\Yii2\Date\DateUtils; +use Exception; use PHPUnit\Framework\TestCase; /** @@ -13,6 +14,9 @@ */ class DateUtilsTest extends TestCase { + /** + * @throws Exception + */ public function testToRelativeTime() { $relativeTime = DateUtils::toRelativeTime( diff --git a/tests/HttpClient/Exceptions/HttpClientExceptionTest.php b/tests/HttpClient/Exceptions/HttpClientExceptionTest.php index 45c5ec6..8d1ec60 100644 --- a/tests/HttpClient/Exceptions/HttpClientExceptionTest.php +++ b/tests/HttpClient/Exceptions/HttpClientExceptionTest.php @@ -3,7 +3,7 @@ * @author Adegoke Obasa */ -namespace CottaCush\Yii2\Tests\OauthClient\Exceptions; +namespace CottaCush\Yii2\Tests\HttpClient\Exceptions; use CottaCush\Yii2\HttpClient\Exceptions\HttpClientException; use PHPUnit\Framework\TestCase; diff --git a/tests/HttpClient/TerraHttpClientTest.php b/tests/HttpClient/TerraHttpClientTest.php index 591dad1..f5664b6 100644 --- a/tests/HttpClient/TerraHttpClientTest.php +++ b/tests/HttpClient/TerraHttpClientTest.php @@ -7,6 +7,7 @@ use CottaCush\Yii2\HttpClient\Exceptions\HttpClientException; use CottaCush\Yii2\HttpClient\TerraHttpClient; +use Exception; use linslin\yii2\curl\Curl; use PHPUnit\Framework\TestCase; use yii\helpers\Json; @@ -112,6 +113,9 @@ public function testGetWithInvalidParams() $this->httpClient->get('posts', "Adegoke Obasa"); } + /** + * @throws Exception + */ public function testGetWithRawResponse() { $response = $this->httpClient->setUseOauth(false) @@ -120,6 +124,9 @@ public function testGetWithRawResponse() $this->assertJson($response); } + /** + * @throws HttpClientException + */ public function testGetWithJsonResponse() { $rawResponse = $this->httpClient->setUseOauth(false) @@ -132,6 +139,9 @@ public function testGetWithJsonResponse() $this->assertEquals(Json::decode($rawResponse), $jsonResponse); } + /** + * @throws Exception + */ public function testPostWithRawResponse() { $response = $this->httpClient @@ -141,6 +151,9 @@ public function testPostWithRawResponse() $this->assertJson($response); } + /** + * @throws Exception + */ public function testPostWithJsonResponse() { $response = $this->httpClient @@ -150,6 +163,9 @@ public function testPostWithJsonResponse() $this->assertEquals(['id' => 101], $response); } + /** + * @throws Exception + */ public function testPutWithRawResponse() { $id = 1; @@ -160,6 +176,9 @@ public function testPutWithRawResponse() $this->assertJson($response); } + /** + * @throws Exception + */ public function testPutWithJsonResponse() { $id = 1; @@ -170,6 +189,9 @@ public function testPutWithJsonResponse() $this->assertEquals(['id' => $id], $response); } + /** + * @throws Exception + */ public function testDeleteWithRawResponse() { $id = 1; @@ -180,6 +202,9 @@ public function testDeleteWithRawResponse() $this->assertJson($response); } + /** + * @throws Exception + */ public function testDeleteWithJsonResponse() { $id = 1; @@ -190,6 +215,9 @@ public function testDeleteWithJsonResponse() $this->assertEquals([], $response); } + /** + * @throws Exception + */ public function testGetParams() { $this->httpClient @@ -199,6 +227,9 @@ public function testGetParams() $this->assertEquals($this->testPostParams, $this->httpClient->getLastRequestParams()); } + /** + * @throws Exception + */ public function testPostParams() { $this->httpClient @@ -208,6 +239,9 @@ public function testPostParams() $this->assertEquals($this->testPostParams, $this->httpClient->getLastRequestParams()); } + /** + * @throws Exception + */ public function testPostJsonBody() { $params = Json::encode($this->testPostParams); diff --git a/tests/HttpResponse/JSendResponseTest.php b/tests/HttpResponse/JSendResponseTest.php index 6f34ae5..a0175b1 100644 --- a/tests/HttpResponse/JSendResponseTest.php +++ b/tests/HttpResponse/JSendResponseTest.php @@ -2,6 +2,7 @@ namespace CottaCush\Yii2\Tests\HttpResponse; use CottaCush\Yii2\HttpResponse\JSendResponse; +use Exception; use Faker\Factory; use Faker\Generator; use PHPUnit\Framework\TestCase; @@ -72,42 +73,63 @@ public function testCodeParamIsCorrect() $this->assertEquals($jsonResponse->getCodeParam(), JSendResponse::RESPONSE_CODE_PARAM); } + /** + * @throws Exception + */ public function testMessageParamIsCorrect() { $jsonResponse = new JSendResponse(json_encode([]), false); $this->assertEquals($jsonResponse->getMessageParam(), JSendResponse::RESPONSE_MESSAGE_PARAM); } + /** + * @throws Exception + */ public function testSuccessValueIsCorrect() { $jsonResponse = new JSendResponse(json_encode([]), false); $this->assertEquals($jsonResponse->getSuccessValue(), JSendResponse::RESPONSE_STATUS_SUCCESS); } + /** + * @throws Exception + */ public function testIsSuccessReturnsTrueWhenStatusIsSuccessWhenResponseIsParsed() { $jsonResponse = new JSendResponse(json_encode(['status' => JSendResponse::RESPONSE_STATUS_SUCCESS]), false); $this->assertEquals($jsonResponse->isSuccess(), true); } + /** + * @throws Exception + */ public function testIsSuccessReturnsTrueWhenStatusIsSuccessWhenResponseNotParsed() { $jsonResponse = new JSendResponse(['status' => JSendResponse::RESPONSE_STATUS_SUCCESS]); $this->assertEquals($jsonResponse->isSuccess(), true); } + /** + * @throws Exception + */ public function testIsSuccessReturnsFalseWhenStatusIsSuccessWhenResponseIsParsed() { $jsonResponse = new JSendResponse(json_encode(['status' => 'error']), false); $this->assertEquals($jsonResponse->isSuccess(), false); } + /** + * @throws Exception + */ public function testIsSuccessReturnsFalseWhenStatusIsSuccessWhenResponseNotParsed() { $jsonResponse = new JSendResponse(['status' => 'error']); $this->assertEquals($jsonResponse->isSuccess(), false); } + /** + * @throws Exception + */ public function testGetErrorMessageWhenResponseIsNotParsed() { $message = $this->faker->sentence; @@ -115,6 +137,9 @@ public function testGetErrorMessageWhenResponseIsNotParsed() $this->assertEquals($jsonResponse->getErrorMessage(), $message); } + /** + * @throws Exception + */ public function testGetErrorMessageWhenResponseIsParsed() { $message = $this->faker->sentence; @@ -122,6 +147,9 @@ public function testGetErrorMessageWhenResponseIsParsed() $this->assertEquals($jsonResponse->getErrorMessage(), $message); } + /** + * @throws Exception + */ public function testGetCodeWhenResponseIsNotParsed() { $code = $this->faker->randomDigitNotNull; @@ -129,6 +157,9 @@ public function testGetCodeWhenResponseIsNotParsed() $this->assertEquals($jsonResponse->getCode(), $code); } + /** + * @throws Exception + */ public function testGetCodeWhenResponseIsParsed() { $code = $this->faker->randomDigitNotNull; @@ -136,18 +167,27 @@ public function testGetCodeWhenResponseIsParsed() $this->assertEquals($jsonResponse->getCode(), $code); } + /** + * @throws Exception + */ public function testGetCodeWhenNotSetAndResponseIsNotParsed() { $jsonResponse = new JSendResponse(['status' => 'error']); $this->assertEquals($jsonResponse->getCode(), JSendResponse::CODE_NO_CODE); } + /** + * @throws Exception + */ public function testGetCodeWhenSetAndResponseIsParsed() { $jsonResponse = new JSendResponse(json_encode(['status' => 'error']), false); $this->assertEquals($jsonResponse->getCode(), JSendResponse::CODE_NO_CODE); } + /** + * @throws Exception + */ public function testGetDataWhenResponseIsNotParsed() { $words = $this->faker->words; @@ -155,6 +195,9 @@ public function testGetDataWhenResponseIsNotParsed() $this->assertEquals($jsonResponse->getData(), $words); } + /** + * @throws Exception + */ public function testGetDataWhenResponseIsParsed() { $words = $this->faker->words; @@ -162,18 +205,27 @@ public function testGetDataWhenResponseIsParsed() $this->assertEquals($jsonResponse->getData(), $words); } + /** + * @throws Exception + */ public function testGetDataWhenNotSetAndResponseIsNotParsed() { $jsonResponse = new JSendResponse(['status' => 'success']); $this->assertEquals($jsonResponse->getData([]), []); } + /** + * @throws Exception + */ public function testGetDataWhenNotSetAndResponseIsParsed() { $jsonResponse = new JSendResponse(json_encode(['status' => 'success']), false); $this->assertEquals($jsonResponse->getData([]), []); } + /** + * @throws Exception + */ public function testGetWhenResponseIsNotParsed() { $words = $this->faker->words; @@ -181,6 +233,9 @@ public function testGetWhenResponseIsNotParsed() $this->assertEquals($jsonResponse->get('words'), $words); } + /** + * @throws Exception + */ public function testGetWhenResponseIsParsed() { $words = $this->faker->words; @@ -188,12 +243,18 @@ public function testGetWhenResponseIsParsed() $this->assertEquals($jsonResponse->get('words'), $words); } + /** + * @throws Exception + */ public function testGetWhenNotSetAndResponseIsNotParsed() { $jsonResponse = new JSendResponse(['status' => 'success']); $this->assertEquals($jsonResponse->get('words', []), []); } + /** + * @throws Exception + */ public function testGetWhenNotSetAndResponseIsParsed() { $jsonResponse = new JSendResponse(json_encode(['status' => 'success']), false); diff --git a/tests/OauthClient/Oauth2ClientTest.php b/tests/OauthClient/Oauth2ClientTest.php index da17216..0dcdee1 100644 --- a/tests/OauthClient/Oauth2ClientTest.php +++ b/tests/OauthClient/Oauth2ClientTest.php @@ -143,6 +143,7 @@ public function testAuthorizeWithInvalidClientId() } /** + * @throws Exception * @author Adegoke Obasa */ public function testAuthorizeFailure() From cc6238e458d9d4b79573a8798d2339dcde8976f7 Mon Sep 17 00:00:00 2001 From: Adaa Date: Sat, 20 Feb 2021 00:23:12 +0100 Subject: [PATCH 05/10] fix issue with Handlebar --- src/Template/Handlebars.php | 101 ++++ src/Template/HandlebarsTemplatingEngine.php | 1 - src/Template/Parser.php | 95 ++++ src/Template/Template.php | 492 ++++++++++++++++++++ src/Template/Tokenizer.php | 377 +++++++++++++++ 5 files changed, 1065 insertions(+), 1 deletion(-) create mode 100644 src/Template/Handlebars.php create mode 100644 src/Template/Parser.php create mode 100644 src/Template/Template.php create mode 100644 src/Template/Tokenizer.php diff --git a/src/Template/Handlebars.php b/src/Template/Handlebars.php new file mode 100644 index 0000000..fda3572 --- /dev/null +++ b/src/Template/Handlebars.php @@ -0,0 +1,101 @@ +getCache()->get($hash); + if ($tree === false) { + $tokens = $this->getTokenizer()->scan($source); + $tree = $this->getParser()->parse($tokens); + $this->getCache()->set($hash, $tree, $this->_ttl); + } + + return $tree; + } + + /** + * Get the current Handlebars Tokenizer instance. + * + * If no Tokenizer instance has been explicitly specified, this method will + * instantiate and return a new one. + * + * @return Tokenizer + */ + public function getTokenizer(): Tokenizer + { + if (!isset($this->_tokenizer)) { + $this->_tokenizer = new Tokenizer(); + } + + return $this->_tokenizer; + } + + /** + * Get the current Handlebars Parser instance. + * + * If no Parser instance has been explicitly specified, this method will + * instantiate and return a new one. + * + * @return Parser + */ + public function getParser(): Parser + { + if (!isset($this->_parser)) { + $this->_parser = new Parser(); + } + + return $this->_parser; + } + + /** + * Load a template by name with current template loader + * + * @param string $name template name + * + * @return Template + */ + public function loadTemplate($name): Template + { + $source = $this->getLoader()->load($name); + $tree = $this->_tokenize($source); + + return new $this->_templateClass($this, $tree, $source); + } + + /** + * Shortcut 'render' invocation. + * + * Equivalent to calling `$handlebars->loadTemplate($template)->render($data);` + * + * @param string $template template name + * @param mixed $data data to use as context + * + * @return string Rendered template + * @see Handlebars::loadTemplate + * @see Template::render + */ + public function render($template, $data): string + { + return $this->loadTemplate($template)->render($data); + } +} diff --git a/src/Template/HandlebarsTemplatingEngine.php b/src/Template/HandlebarsTemplatingEngine.php index bff076b..54b1efb 100644 --- a/src/Template/HandlebarsTemplatingEngine.php +++ b/src/Template/HandlebarsTemplatingEngine.php @@ -4,7 +4,6 @@ use CottaCush\Yii2\Template\Helpers\HandleBarsHelpers; use CottaCush\Yii2\Template\Helpers\TemplatingEngineInterface; -use Handlebars\Handlebars; /** * Class HandlebarsTemplatingEngine diff --git a/src/Template/Parser.php b/src/Template/Parser.php new file mode 100644 index 0000000..9b87e47 --- /dev/null +++ b/src/Template/Parser.php @@ -0,0 +1,95 @@ +_buildTree(new \ArrayIterator($tokens)); + } + + /** + * Helper method for recursively building a parse tree. + * Trim right and trim left is a bit tricky here. + * {{#begin~}}{{TOKEN}}, TOKEN.. {{LAST}}{{~/begin}} is translated to: + * {{#begin}}{{~TOKEN}}, TOKEN.. {{LAST~}}{{/begin}} + * + * @param \ArrayIterator $tokens Stream of tokens + * + * @throws \LogicException when nesting errors or mismatched section tags + * are encountered. + * @return array Token parse tree + */ + private function _buildTree(\ArrayIterator $tokens): array + { + $stack = array(); + + do { + $token = $tokens->current(); + $tokens->next(); + + if ($token !== null) { + switch ($token[Tokenizer::TYPE]) { + case Tokenizer::T_END_SECTION: + $newNodes = array($token); + do { + $result = array_pop($stack); + if ($result === null) { + throw new \LogicException( + sprintf( + 'Unexpected closing tag: /%s', + $token[Tokenizer::NAME] + ) + ); + } + + if (!array_key_exists(Tokenizer::NODES, $result) + && isset($result[Tokenizer::NAME]) + && ($result[Tokenizer::TYPE] == Tokenizer::T_SECTION + || $result[Tokenizer::TYPE] == Tokenizer::T_INVERTED) + && $result[Tokenizer::NAME] == $token[Tokenizer::NAME] + ) { + if (isset($result[Tokenizer::TRIM_RIGHT]) + && $result[Tokenizer::TRIM_RIGHT] + ) { + // If the start node has trim right, then its equal + //with the first item in the loop with + // Trim left + $newNodes[0][Tokenizer::TRIM_LEFT] = true; + } + + if (isset($token[Tokenizer::TRIM_RIGHT]) + && $token[Tokenizer::TRIM_RIGHT] + ) { + //OK, if we have trim right here, we should + //pass it to the upper level. + $result[Tokenizer::TRIM_RIGHT] = true; + } + + $result[Tokenizer::NODES] = $newNodes; + $result[Tokenizer::END] = $token[Tokenizer::INDEX]; + array_push($stack, $result); + break; + } else { + array_unshift($newNodes, $result); + } + } while (true); + break; + default: + array_push($stack, $token); + } + } + + } while ($tokens->valid()); + + return $stack; + } +} diff --git a/src/Template/Template.php b/src/Template/Template.php new file mode 100644 index 0000000..dc8a49d --- /dev/null +++ b/src/Template/Template.php @@ -0,0 +1,492 @@ +_section($context, $current); + + if ($escaped && !($result instanceof SafeString)) { + $escape_args = $this->handlebars->getEscapeArgs(); + array_unshift($escape_args, $result); + $result = call_user_func_array( + $this->handlebars->getEscape(), + array_values($escape_args) + ); + } + + return $result; + } + + /** + * Process variable + * + * @param Context $context current context + * @param array $current section node data + * @param boolean $escaped escape result or not + * + * @return string the result + */ + protected function _getVariable(Context $context, array $current, bool $escaped): string + { + $name = $current[Tokenizer::NAME]; + $value = $context->get($name); + if (is_array($value)) { + return 'Array'; + } + if ($escaped && !($value instanceof SafeString)) { + $args = $this->handlebars->getEscapeArgs(); + array_unshift($args, (string)$value); + $value = call_user_func_array( + $this->handlebars->getEscape(), + array_values($args) + ); + } + + return (string)$value; + } + + /** + * Prepare the arguments of a partial to actual array values to be used in a new context + * + * @param Context $context Current context + * @param Arguments $arguments Arguments for partial + * + * @return array + */ + protected function _preparePartialArguments(Context $context, Arguments $arguments): array + { + $positionalArgs = array(); + foreach ($arguments->getPositionalArguments() as $positionalArg) { + $contextArg = $context->get($positionalArg); + if (is_array($contextArg)) { + foreach ($contextArg as $key => $value) { + $positionalArgs[$key] = $value; + } + } else { + $positionalArgs[$positionalArg] = $contextArg; + } + } + + $namedArguments = array(); + foreach ($arguments->getNamedArguments() as $key => $value) { + $namedArguments[$key] = $context->get($value); + } + + return array_merge($positionalArgs, $namedArguments); + } + + + /** + * Check if there is a helper with this variable name available or not. + * + * @param array $current current token + * + * @return boolean + */ + protected function _isSection(array $current): bool + { + $helpers = $this->getEngine()->getHelpers(); + // Tokenizer doesn't process the args -if any- so be aware of that + $name = explode(' ', $current[Tokenizer::NAME], 2); + + return $helpers->has(reset($name)); + } + + /** + * Get replacing value of a tag + * + * Will process the tag as section, if a helper with the same name could be + * found, so {{helper arg}} can be used instead of {{#helper arg}}. + * + * @param Context $context current context + * @param array $current section node data + * @param boolean $escaped escape result or not + * + * @return string|SafeString the string to be replaced with the tag + */ + protected function _get(Context $context, array $current, bool $escaped): string|SafeString + { + if ($this->_isSection($current)) { + return $this->_getSection($context, $current, $escaped); + } else { + return $this->_getVariable($context, $current, $escaped); + } + } + + /** + * Process inverted section + * + * @param Context $context current context + * @param array $current section node data + * + * @return string the result + */ + protected function _inverted(Context $context, array $current): string + { + $sectionName = $current[Tokenizer::NAME]; + $data = $context->get($sectionName); + if (!$data) { + return $this->render($context); + } else { + //No need to discard here, since it has no else + return ''; + } + } + + /** + * Process section nodes + * + * @param Context $context current context + * @param array $current section node data + * + * @return string the result + * @throws RuntimeException + */ + protected function _section(Context $context, array $current): string + { + $helpers = $this->handlebars->getHelpers(); + $sectionName = $current[Tokenizer::NAME]; + if ($helpers->has($sectionName)) { + return $this->_handlebarsStyleSection($context, $current); + } elseif (trim($current[Tokenizer::ARGS]) == '') { + return $this->_mustacheStyleSection($context, $current); + } else { + throw new RuntimeException( + sprintf( + '"%s"" is not registered as a helper', + $sectionName + ) + ); + } + } + + /** + * Process handlebars section style + * + * @param Context $context current context + * @param array $current section node data + * + * @return mixed + */ + protected function _handlebarsStyleSection(Context $context, array $current): mixed + { + $helpers = $this->handlebars->getHelpers(); + $sectionName = $current[Tokenizer::NAME]; + + if (isset($current[Tokenizer::END])) { + $source = substr( + $this->getSource(), + $current[Tokenizer::INDEX], + $current[Tokenizer::END] - $current[Tokenizer::INDEX] + ); + } else { + $source = ''; + } + + // subexpression parsing loop + // will contain all subexpressions + // inside outermost brackets + $subexprs = array(); + $insideOf = array( 'single' => false, 'double' => false ); + $lvl = 0; + $cur_start = 0; + for ($i=0; $i < strlen($current[Tokenizer::ARGS]); $i++) { + $cur = substr($current[Tokenizer::ARGS], $i, 1); + if ($cur == "'") { + $insideOf['single'] = ! $insideOf['single']; + } + if ($cur == '"') { + $insideOf['double'] = ! $insideOf['double']; + } + if ($cur == '(' && ! $insideOf['single'] && ! $insideOf['double']) { + if ($lvl == 0) { + $cur_start = $i+1; + } + $lvl++; + continue; + } + if ($cur == ')' && ! $insideOf['single'] && ! $insideOf['double']) { + $lvl--; + if ($lvl == 0) { + $subexprs[] = substr( + $current[Tokenizer::ARGS], + $cur_start, + $i - $cur_start + ); + } + } + } + + if (! empty($subexprs)) { + foreach ($subexprs as $expr) { + $cmd = explode(" ", $expr); + $name = trim($cmd[0]); + // construct artificial section node + $section_node = array( + Tokenizer::TYPE => Tokenizer::T_ESCAPED, + Tokenizer::NAME => $name, + Tokenizer::OTAG => $current[Tokenizer::OTAG], + Tokenizer::CTAG => $current[Tokenizer::CTAG], + Tokenizer::INDEX => $current[Tokenizer::INDEX], + Tokenizer::ARGS => implode(" ", array_slice($cmd, 1)) + ); + + // resolve the node recursively + $resolved = $this->_handlebarsStyleSection( + $context, + $section_node + ); + + $resolved = addcslashes($resolved, '"'); + // replace original subexpression with result + $current[Tokenizer::ARGS] = str_replace( + '('.$expr.')', + '"' . $resolved . '"', + $current[Tokenizer::ARGS] + ); + } + } + + $return = $helpers->call( + $sectionName, + $this, + $context, + $current[Tokenizer::ARGS], + $source + ); + + if ($return instanceof StringWrapper) { + return $this->handlebars->loadString($return)->render($context); + } else { + return $return; + } + } + + /** + * Process Mustache section style + * + * @param Context $context current context + * @param array $current section node data + * + * @return string + */ + protected function _mustacheStyleSection(Context $context, array $current): string + { + $sectionName = $current[Tokenizer::NAME]; + + // fallback to mustache style each/with/for just if there is + // no argument at all. + try { + $sectionVar = $context->get($sectionName, false); + } catch (\InvalidArgumentException $e) { + throw new \RuntimeException( + sprintf( + '"%s" is not registered as a helper', + $sectionName + ) + ); + } + $buffer = ''; + if (is_array($sectionVar) || $sectionVar instanceof \Traversable) { + $isList = is_array($sectionVar) && + (array_keys($sectionVar) === range(0, count($sectionVar) - 1)); + $index = 0; + $lastIndex = $isList ? (count($sectionVar) - 1) : false; + + foreach ($sectionVar as $key => $d) { + $specialVariables = array( + '@index' => $index, + '@first' => ($index === 0), + '@last' => ($index === $lastIndex), + ); + if (!$isList) { + $specialVariables['@key'] = $key; + } + $context->pushSpecialVariables($specialVariables); + $context->push($d); + $buffer .= $this->render($context); + $context->pop(); + $context->popSpecialVariables(); + $index++; + } + } elseif (is_object($sectionVar)) { + //Act like with + $context->push($sectionVar); + $buffer = $this->render($context); + $context->pop(); + } elseif ($sectionVar) { + $buffer = $this->render($context); + } + + return $buffer; + } + + /** + * Process partial section + * + * @param Context $context current context + * @param array $current section node data + * + * @return string the result + */ + protected function _partial(Context $context, array $current): string + { + $partial = $this->handlebars->loadPartial($current[Tokenizer::NAME]); + + if ($current[Tokenizer::ARGS]) { + $arguments = new Arguments($current[Tokenizer::ARGS]); + + $context = new Context($this->_preparePartialArguments($context, $arguments)); + } + + return $partial->render($context); + } + + /** + * Render tokens base on type of tokens + * + * @param array $current current token + * @param mixed $context current context + * + * @return string + */ + protected function renderInternal($current, mixed $context): string + { + $result = ''; + switch ($current[Tokenizer::TYPE]) { + case Tokenizer::T_END_SECTION: + break; // Its here just for handling whitespace trim. + case Tokenizer::T_SECTION: + $newStack = isset($current[Tokenizer::NODES]) + ? $current[Tokenizer::NODES] : array(); + array_push($this->stack, array(0, $newStack, false)); + $result = $this->_section($context, $current); + array_pop($this->stack); + break; + case Tokenizer::T_INVERTED: + $newStack = isset($current[Tokenizer::NODES]) ? + $current[Tokenizer::NODES] : array(); + array_push($this->stack, array(0, $newStack, false)); + $result = $this->_inverted($context, $current); + array_pop($this->stack); + break; + case Tokenizer::T_COMMENT: + $result = ''; + break; + case Tokenizer::T_PARTIAL: + case Tokenizer::T_PARTIAL_2: + $result = $this->_partial($context, $current); + break; + case Tokenizer::T_UNESCAPED: + case Tokenizer::T_UNESCAPED_2: + $result = $this->_get($context, $current, false); + break; + case Tokenizer::T_ESCAPED: + $result = $this->_get($context, $current, true); + break; + case Tokenizer::T_TEXT: + $result = $current[Tokenizer::VALUE]; + break; + /* How we could have another type of token? this part of code + is not used at all. + default: + throw new \RuntimeException( + 'Invalid node type : ' . json_encode($current) + ); + */ + } + + return $result; + } + + /** + * Render top tree + * + * @param mixed $context current context + * + * @return string + * @throws RuntimeException + */ + public function render(mixed $context): string + { + if (!$context instanceof Context) { + $context = new Context($context); + } + $topTree = end($this->stack); // never pop a value from stack + list($index, $tree, $stop) = $topTree; + + $buffer = ''; + $rTrim = false; + while (array_key_exists($index, $tree)) { + $current = $tree[$index]; + $index++; + //if the section is exactly like waitFor + if (is_string($stop) + && $current[Tokenizer::TYPE] == Tokenizer::T_ESCAPED + && $current[Tokenizer::NAME] === $stop + ) { + break; + } + if (isset($current[Tokenizer::TRIM_LEFT]) + && $current[Tokenizer::TRIM_LEFT] + ) { + $buffer = rtrim($buffer); + } + + $tmp = $this->renderInternal($current, $context); + + if (isset($current[Tokenizer::TRIM_LEFT]) + && $current[Tokenizer::TRIM_LEFT] + ) { + $tmp = rtrim($tmp); + } + + if ($rTrim + || (isset($current[Tokenizer::TRIM_RIGHT]) + && $current[Tokenizer::TRIM_RIGHT]) + ) { + $tmp = ltrim($tmp); + } + + $buffer .= $tmp; + // Some time, there is more than + //one string token (first is empty), + //so we need to trim all of them in one shot + + $rTrim = (empty($tmp) && $rTrim) || + isset($current[Tokenizer::TRIM_RIGHT]) + && $current[Tokenizer::TRIM_RIGHT]; + } + if ($stop) { + //Ok break here, the helper should be aware of this. + $newStack = array_pop($this->stack); + $newStack[0] = $index; + $newStack[2] = false; //No stop token from now on + array_push($this->stack, $newStack); + } + + return $buffer; + } +} diff --git a/src/Template/Tokenizer.php b/src/Template/Tokenizer.php new file mode 100644 index 0000000..c8c5b7e --- /dev/null +++ b/src/Template/Tokenizer.php @@ -0,0 +1,377 @@ +'; + const T_PARTIAL_2 = '<'; + const T_DELIM_CHANGE = '='; + const T_ESCAPED = '_v'; + const T_UNESCAPED = '{'; + const T_UNESCAPED_2 = '&'; + const T_TEXT = '_t'; + const T_ESCAPE = "\\"; + const T_SINGLE_Q = "'"; + const T_DOUBLE_Q = "\""; + const T_TRIM = "~"; + + // Valid token types + protected static $_tagTypes = array( + self::T_SECTION => true, + self::T_INVERTED => true, + self::T_END_SECTION => true, + self::T_COMMENT => true, + self::T_PARTIAL => true, + self::T_PARTIAL_2 => true, + self::T_DELIM_CHANGE => true, + self::T_ESCAPED => true, + self::T_UNESCAPED => true, + self::T_UNESCAPED_2 => true, + ); + + // Interpolated tags + protected static $_interpolatedTags = array( + self::T_ESCAPED => true, + self::T_UNESCAPED => true, + self::T_UNESCAPED_2 => true, + ); + + // Token properties + const TYPE = 'type'; + const NAME = 'name'; + const OTAG = 'otag'; + const CTAG = 'ctag'; + const INDEX = 'index'; + const END = 'end'; + const INDENT = 'indent'; + const NODES = 'nodes'; + const VALUE = 'value'; + const ARGS = 'args'; + const TRIM_LEFT = 'tleft'; + const TRIM_RIGHT = 'tright'; + + protected $state; + protected $tagType; + protected $tag; + protected $buffer = ''; + protected $tokens; + protected $seenTag; + protected $lineStart; + protected $otag; + protected $ctag; + protected $escaped; + protected $escaping; + protected $trimLeft; + protected $trimRight; + + /** + * Scan and tokenize template source. + * + * @param string $text Mustache template source to tokenize + * + * @return array Set of Mustache tokens + * @internal string $delimiters Optional, pass opening and closing delimiters + * + */ + public function scan(string $text/*, $delimiters = null*/): array + { + if ($text instanceof StringWrapper) { + $text = $text->getString(); + } + $this->reset(); + + /* Actually we not support this. so this code is not used at all, yet. + if ($delimiters = trim($delimiters)) { + list($otag, $ctag) = explode(' ', $delimiters); + $this->otag = $otag; + $this->ctag = $ctag; + } + */ + $len = strlen($text); + for ($i = 0; $i < $len; $i++) { + $this->escaping = $this->tagChange(self::T_ESCAPE, $text, $i); + + // To play nice with helpers' arguments quote and apostrophe marks + // should be additionally escaped only when they are not in a tag. + $quoteInTag = $this->state != self::IN_TEXT + && ($text[$i] == self::T_SINGLE_Q || $text[$i] == self::T_DOUBLE_Q); + + if ($this->escaped && !$this->tagChange($this->otag, $text, $i) && !$quoteInTag) { + $this->buffer .= "\\"; + } + + switch ($this->state) { + case self::IN_TEXT: + // Handlebars.js does not think that openning curly brace in + // "\\\{{data}}" template is escaped. Instead it removes one + // slash and leaves others "as is". To emulate similar behavior + // we have to check the last character in the buffer. If it's a + // slash we actually does not need to escape openning curly + // brace. + $prev_slash = substr($this->buffer, -1) == '\\'; + + if ($this->tagChange($this->otag. self::T_TRIM, $text, $i) and (!$this->escaped || $prev_slash)) { + $this->flushBuffer(); + $this->state = self::IN_TAG_TYPE; + $this->trimLeft = true; + } elseif ($this->tagChange(self::T_UNESCAPED.$this->otag, $text, $i) and $this->escaped) { + $this->buffer .= "{{{"; + $i += 2; + continue 2; + } elseif ($this->tagChange($this->otag, $text, $i) and (!$this->escaped || $prev_slash)) { + $i--; + $this->flushBuffer(); + $this->state = self::IN_TAG_TYPE; + } elseif ($this->escaped and $this->escaping) { + // We should not add extra slash before opening tag because + // doubled slash where should be transformed to single one + if (($i + 1) < $len && !$this->tagChange($this->otag, $text, $i + 1)) { + $this->buffer .= "\\"; + } + } elseif (!$this->escaping) { + if ($text[$i] == "\n") { + $this->filterLine(); + } else { + $this->buffer .= $text[$i]; + } + } + break; + + case self::IN_TAG_TYPE: + $i += strlen($this->otag) - 1; + if (isset(self::$_tagTypes[$text[$i + 1]])) { + $tag = $text[$i + 1]; + $this->tagType = $tag; + } else { + $tag = null; + $this->tagType = self::T_ESCAPED; + } + + if ($this->tagType === self::T_DELIM_CHANGE) { + $i = $this->changeDelimiters($text, $i); + $this->state = self::IN_TEXT; + } else { + if ($tag !== null) { + $i++; + } + $this->state = self::IN_TAG; + } + $this->seenTag = $i; + break; + + default: + if ($this->tagChange(self::T_TRIM . $this->ctag, $text, $i)) { + $this->trimRight = true; + continue 2; + } + if ($this->tagChange($this->ctag, $text, $i)) { + // Sections (Helpers) can accept parameters + // Same thing for Partials (little known fact) + if (($this->tagType == self::T_SECTION) + || ($this->tagType == self::T_PARTIAL) + || ($this->tagType == self::T_PARTIAL_2) + ) { + $newBuffer = explode(' ', trim($this->buffer), 2); + $args = ''; + if (count($newBuffer) == 2) { + $args = $newBuffer[1]; + } + $this->buffer = $newBuffer[0]; + } + $t = array( + self::TYPE => $this->tagType, + self::NAME => trim($this->buffer), + self::OTAG => $this->otag, + self::CTAG => $this->ctag, + self::INDEX => ($this->tagType == self::T_END_SECTION) ? + $this->seenTag - strlen($this->otag) : + $i + strlen($this->ctag), + self::TRIM_LEFT => $this->trimLeft, + self::TRIM_RIGHT => $this->trimRight + ); + if (isset($args)) { + $t[self::ARGS] = $args; + } + $this->tokens[] = $t; + unset($t); + unset($args); + $this->buffer = ''; + $this->trimLeft = false; + $this->trimRight = false; + $i += strlen($this->ctag) - 1; + $this->state = self::IN_TEXT; + if ($this->tagType == self::T_UNESCAPED) { + if ($this->ctag == '}}') { + $i++; + } /* else { // I can't remember why this part is here! the ctag is always }} and + // Clean up `{{{ tripleStache }}}` style tokens. + $lastIndex = count($this->tokens) - 1; + $lastName = $this->tokens[$lastIndex][self::NAME]; + if (substr($lastName, -1) === '}') { + $this->tokens[$lastIndex][self::NAME] = trim( + substr($lastName, 0, -1) + ); + } + } */ + } + } else { + $this->buffer .= $text[$i]; + } + break; + } + + $this->escaped = ($this->escaping and !$this->escaped); + } + + $this->filterLine(true); + + return $this->tokens; + } + + /** + * Helper function to reset tokenizer internal state. + * + * @return void + */ + protected function reset() + { + $this->state = self::IN_TEXT; + $this->escaped = false; + $this->escaping = false; + $this->tagType = null; + $this->tag = null; + $this->buffer = ''; + $this->tokens = array(); + $this->seenTag = false; + $this->lineStart = 0; + $this->otag = '{{'; + $this->ctag = '}}'; + $this->trimLeft = false; + $this->trimRight = false; + } + + /** + * Flush the current buffer to a token. + * + * @return void + */ + protected function flushBuffer() + { + if ($this->buffer !== '') { + $this->tokens[] = array( + self::TYPE => self::T_TEXT, + self::VALUE => $this->buffer + ); + $this->buffer = ''; + } + } + + /** + * Test whether the current line is entirely made up of whitespace. + * + * @return boolean True if the current line is all whitespace + */ + protected function lineIsWhitespace(): bool + { + $tokensCount = count($this->tokens); + for ($j = $this->lineStart; $j < $tokensCount; $j++) { + $token = $this->tokens[$j]; + if (isset(self::$_tagTypes[$token[self::TYPE]])) { + if (isset(self::$_interpolatedTags[$token[self::TYPE]])) { + return false; + } + } elseif ($token[self::TYPE] == self::T_TEXT) { + if (preg_match('/\S/', $token[self::VALUE])) { + return false; + } + } + } + + return true; + } + + /** + * Filter out whitespace-only lines and store indent levels for partials. + * + * @param bool $noNewLine Suppress the newline? (default: false) + * + * @return void + */ + protected function filterLine($noNewLine = false) + { + $this->flushBuffer(); + if ($this->seenTag && $this->lineIsWhitespace()) { + $tokensCount = count($this->tokens); + for ($j = $this->lineStart; $j < $tokensCount; $j++) { + if ($this->tokens[$j][self::TYPE] == self::T_TEXT) { + if (isset($this->tokens[$j + 1]) + && $this->tokens[$j + 1][self::TYPE] == self::T_PARTIAL + ) { + $this->tokens[$j + 1][self::INDENT] + = $this->tokens[$j][self::VALUE]; + } + + $this->tokens[$j] = null; + } + } + } elseif (!$noNewLine) { + $this->tokens[] = array(self::TYPE => self::T_TEXT, self::VALUE => "\n"); + } + + $this->seenTag = false; + $this->lineStart = count($this->tokens); + } + + /** + * Change the current Handlebars delimiters. Set new `otag` and `ctag` values. + * + * @param string $text Mustache template source + * @param int $index Current tokenizer index + * + * @return int New index value + */ + protected function changeDelimiters(string $text, int $index): int + { + $startIndex = strpos($text, '=', $index) + 1; + $close = '=' . $this->ctag; + $closeIndex = strpos($text, $close, $index); + + list($otag, $ctag) = explode( + ' ', + trim(substr($text, $startIndex, $closeIndex - $startIndex)) + ); + $this->otag = $otag; + $this->ctag = $ctag; + + return $closeIndex + strlen($close) - 1; + } + + /** + * Test whether it's time to change tags. + * + * @param string $tag Current tag name + * @param string $text Handlebars template source + * @param int $index Current tokenizer index + * + * @return boolean True if this is a closing section tag + */ + protected function tagChange(string $tag, string $text, int $index): bool + { + return substr($text, $index, strlen($tag)) === $tag; + } +} From 203dd48ed4ca79cb68fa6329c9fb1bb538c756f7 Mon Sep 17 00:00:00 2001 From: Adaa Date: Sat, 20 Feb 2021 12:33:00 +0100 Subject: [PATCH 06/10] fix issue with Handlebar --- .travis.yml | 1 + src/Template/Parser.php | 13 ++++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 746fb43..8c58579 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,6 +28,7 @@ before_script: script: - vendor/bin/phpcs --standard=psr2 src/ + - vendor/bin/phpcbf --standard=PSR2 src/Template/ - vendor/bin/phpunit --coverage-clover build/logs/clover.xml after_success: diff --git a/src/Template/Parser.php b/src/Template/Parser.php index 9b87e47..b2ad767 100644 --- a/src/Template/Parser.php +++ b/src/Template/Parser.php @@ -2,6 +2,9 @@ namespace CottaCush\Yii2\Template; +use ArrayIterator; +use LogicException; + class Parser extends \Handlebars\Parser { /** @@ -13,7 +16,7 @@ class Parser extends \Handlebars\Parser */ public function parse(array $tokens = array()): array { - return $this->_buildTree(new \ArrayIterator($tokens)); + return $this->_buildTree(new ArrayIterator($tokens)); } /** @@ -22,13 +25,13 @@ public function parse(array $tokens = array()): array * {{#begin~}}{{TOKEN}}, TOKEN.. {{LAST}}{{~/begin}} is translated to: * {{#begin}}{{~TOKEN}}, TOKEN.. {{LAST~}}{{/begin}} * - * @param \ArrayIterator $tokens Stream of tokens + * @param ArrayIterator $tokens Stream of tokens * - * @throws \LogicException when nesting errors or mismatched section tags + * @throws LogicException when nesting errors or mismatched section tags * are encountered. * @return array Token parse tree */ - private function _buildTree(\ArrayIterator $tokens): array + private function _buildTree(ArrayIterator $tokens): array { $stack = array(); @@ -43,7 +46,7 @@ private function _buildTree(\ArrayIterator $tokens): array do { $result = array_pop($stack); if ($result === null) { - throw new \LogicException( + throw new LogicException( sprintf( 'Unexpected closing tag: /%s', $token[Tokenizer::NAME] From fc376858b99140c95ebe15457d19c2ef34170c99 Mon Sep 17 00:00:00 2001 From: Adaa Date: Sat, 20 Feb 2021 12:39:51 +0100 Subject: [PATCH 07/10] fix issue with Handlebar --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8c58579..f8f01c2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,9 +27,9 @@ before_script: - travis_retry composer require php-coveralls/php-coveralls:~2.0 script: + - vendor/bin/phpcbf --standard=psr2 src/ - vendor/bin/phpcs --standard=psr2 src/ - - vendor/bin/phpcbf --standard=PSR2 src/Template/ - - vendor/bin/phpunit --coverage-clover build/logs/clover.xml + - vendor/bin/phpunit --coverage-text --coverage-clover=.build/logs/clover.xml after_success: - sh -c 'php vendor/bin/coveralls -v' From 7e4492241fcb1df7324aa6d67c0c5a8ae0830720 Mon Sep 17 00:00:00 2001 From: Adaa Date: Sat, 20 Feb 2021 12:49:37 +0100 Subject: [PATCH 08/10] fix issue with Handlebar --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index f8f01c2..d5183d8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,8 +27,8 @@ before_script: - travis_retry composer require php-coveralls/php-coveralls:~2.0 script: - - vendor/bin/phpcbf --standard=psr2 src/ - - vendor/bin/phpcs --standard=psr2 src/ + - vendor/bin/phpcbf --standard=psr2 src + - vendor/bin/phpcs --standard=psr2 src -n - vendor/bin/phpunit --coverage-text --coverage-clover=.build/logs/clover.xml after_success: From 2b491fd1b5121476307003fff06731635bbebb1c Mon Sep 17 00:00:00 2001 From: Adaa Date: Sat, 20 Feb 2021 12:58:07 +0100 Subject: [PATCH 09/10] fix issue with Handlebar --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d5183d8..72614ae 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,7 +27,6 @@ before_script: - travis_retry composer require php-coveralls/php-coveralls:~2.0 script: - - vendor/bin/phpcbf --standard=psr2 src - vendor/bin/phpcs --standard=psr2 src -n - vendor/bin/phpunit --coverage-text --coverage-clover=.build/logs/clover.xml From a2fb5dbbbac4ac1a2cb004b938e3c6685e3e9ee3 Mon Sep 17 00:00:00 2001 From: Adaa Date: Sat, 20 Feb 2021 13:02:49 +0100 Subject: [PATCH 10/10] fix issue with Handlebar --- src/Template/Parser.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Template/Parser.php b/src/Template/Parser.php index b2ad767..a578511 100644 --- a/src/Template/Parser.php +++ b/src/Template/Parser.php @@ -90,9 +90,7 @@ private function _buildTree(ArrayIterator $tokens): array array_push($stack, $token); } } - } while ($tokens->valid()); - return $stack; } }