Compare commits

...

63 Commits

Author SHA1 Message Date
Timothy Warren 762d8ca1c4 Make sure fresh dependencies are installed on CI runs
Gitea - aviat/ion/master This commit looks good Details
2019-12-05 16:28:28 -05:00
Timothy Warren b5adf036bf CI tweaks
Gitea - aviat/ion/master This commit looks good Details
2019-12-05 16:26:05 -05:00
Timothy Warren 9313cb33b7 Fix syntax of Jenkinsfile
Gitea - aviat/ion/master There was a failure building this commit Details
2019-12-05 16:21:19 -05:00
Timothy Warren b84145248f Fix dependency version, visual code tweaks
Gitea - aviat/ion/master There was a failure building this commit Details
2019-12-05 16:20:10 -05:00
Timothy Warren 10682b8d60 Update headers
Gitea - aviat/ion/master This commit looks good Details
2019-12-05 15:39:02 -05:00
Timothy Warren 4034b8b2c0 Update minimum PHP version to 7.2, bump version number 2019-12-05 15:38:34 -05:00
Timothy Warren a2cb95aa5b Update dependencies
Gitea - aviat/ion/master This commit looks good Details
2019-12-05 15:25:47 -05:00
Timothy Warren 6ff9476c0b Move XML codec from Hummingbird
Gitea - aviat/ion/master This commit looks good Details
2019-03-12 09:51:38 -04:00
Timothy Warren 68914d22c4 Add silly build status image, remove colors from CI output
Gitea - aviat/ion/master This commit looks good Details
2018-10-11 14:00:51 -04:00
Timothy Warren 69c3f0354e Update CI command
Gitea - aviat/ion/master This commit looks good Details
2018-10-11 13:49:39 -04:00
Timothy Warren ac798d840f Set up Jenkins build
Gitea - aviat/ion/master There was a failure building this commit Details
2018-10-11 13:30:20 -04:00
Timothy Warren 4347c8e2cc Update version 2018-10-05 13:04:59 -04:00
Timothy Warren 2f8c05ac67 Add the Emitter class for the Response object...because it's separate now 2018-10-05 13:03:33 -04:00
Timothy Warren 723c7dadef Update version 2018-10-05 11:44:11 -04:00
Timothy Warren 354eb147f6 Fix test configuration for travis 2018-10-05 11:42:44 -04:00
Timothy Warren c8856ecac0 Add some new helper methods, with updated tests 2018-10-05 11:32:12 -04:00
Timothy Warren 77ebf107de overwrite variables in templates so they work more intuitively 2018-01-30 13:39:43 -05:00
Timothy Warren 128eeea639 Update the version in the header comments 2018-01-17 16:35:01 -05:00
Timothy Warren e1a13f1ad2 More code style fixes 2018-01-17 16:33:57 -05:00
Timothy Warren 38e3e6e686 Fix autoloading 2018-01-17 15:43:47 -05:00
Timothy Warren 578aad3e2e More code style fixes 2018-01-17 15:32:41 -05:00
Timothy Warren 22dc29f945 Update CI build config 2018-01-17 12:49:52 -05:00
Timothy Warren 951d63c87f Update header comments 2018-01-17 12:45:58 -05:00
Timothy Warren f64a8e0e9d Code style updates 2018-01-17 12:43:44 -05:00
Timothy Warren d52515a24a Update dependencies, fix code style check script 2018-01-17 12:00:08 -05:00
Timothy Warren c648cb9a8e Update header comments, and add a changelog entry for a new version 2017-09-13 16:54:09 -04:00
Timothy Warren 640f405a56 Add a method to StringType to be able to compare strings formatted in different ways 2017-09-13 16:43:58 -04:00
Timothy Warren cf068198c4 Update changelog and dependencies 2017-04-13 14:48:11 -04:00
Timothy Warren 2f139fd78b Update version 2017-04-13 14:30:49 -04:00
Timothy Warren ab763252aa Remove server push header method, as support is virtually non-existent 2017-04-13 14:27:37 -04:00
Timothy Warren f5b29e8f17 Remove default CSP header 2017-04-12 16:38:23 -04:00
Timothy Warren a00ec4473c Add method to add http2 server push headers 2017-04-12 12:52:49 -04:00
Timothy Warren 9105b40b5e Add method to view to allow adding request headers 2017-04-12 11:14:16 -04:00
Timothy Warren 57c6d6a34d Remove extra dependency 2017-03-28 10:40:25 -04:00
Timothy Warren 3345ed069f Simplify test setup 2017-03-24 16:57:27 -04:00
Timothy Warren 4c3b75c3d6 Remove static instance trait, remove codeCoverageIgnore annotations 2017-03-24 16:34:20 -04:00
Timothy Warren 47f260b5f0 Test coverage for every line! 2017-03-24 16:27:14 -04:00
Timothy Warren 65105a0559 Fix readme images 2017-03-24 16:26:38 -04:00
Timothy Warren 8ddbcebf4f Update test header comments 2017-03-24 16:18:02 -04:00
Timothy Warren 91286d877f Pare down dev dependencies a bit 2017-03-24 16:15:18 -04:00
Timothy Warren 9a4ff3e2e0 Add sanity check test for StringWrapper trait 2017-03-24 16:14:36 -04:00
Timothy Warren 7e705289df Update readme 2017-03-24 13:01:20 -04:00
Timothy Warren f44d4cb6c9 Add very basic html minification 2017-03-24 12:55:30 -04:00
Timothy Warren 0270ba397c Fix php 7.1 build 2017-03-24 12:55:04 -04:00
Timothy Warren 5a75eb26b2 Simplify phpunit config 2017-03-20 16:42:55 -04:00
Timothy Warren d2be68728a Test commit 2017-03-20 13:41:48 -04:00
Timothy Warren ba7d95ee4f Misc meta updates 2017-02-28 16:39:14 -05:00
Timothy Warren bee154de87 Test setup cleanup 2017-02-28 13:11:27 -05:00
Timothy Warren 735b982451 Add testing status badges to README 2017-02-28 09:56:23 -05:00
Timothy Warren eeeb7ed4d9 Don't bug me about xsl 2017-02-28 09:44:25 -05:00
Timothy Warren 37b14e4c8a Don't bug me about xsl 2017-02-28 09:42:44 -05:00
Timothy Warren eaca5d9b44 Another go at gitlab ci code coverage 2017-02-28 09:39:43 -05:00
Timothy Warren 01da294fea Try, try agin 2017-02-28 09:31:20 -05:00
Timothy Warren fb8baf247a Stop trying to run bash, which isn't in the alpine docker images 2017-02-28 09:30:04 -05:00
Timothy Warren 46c9569132 Try again for gitlab ci code coverage 2017-02-28 09:28:21 -05:00
Timothy Warren 0fe00056dd Attempt gitlab ci code coverage with phpdbg 2017-02-28 09:25:08 -05:00
Timothy Warren 004e643fde Update LICENSE 2017-02-23 08:53:27 -05:00
Timothy Warren 874d07e1b7 Update CHANGELOG 2017-02-23 08:53:07 -05:00
Timothy Warren 497d616cec Add changelog 2017-02-23 08:52:50 -05:00
Timothy Warren 3ebb3b95a9 Add license 2017-02-23 08:51:35 -05:00
Timothy Warren 9795880651 Update gitlab ci setup 2017-02-22 16:54:13 -05:00
Timothy Warren 1f1395ae88 Update all the header comments 2017-02-22 15:42:09 -05:00
Timothy Warren 023f3f8c69 Start work toward 2.0 2017-02-22 15:41:30 -05:00
91 changed files with 1562 additions and 2226 deletions

1
.gitignore vendored
View File

@ -30,3 +30,4 @@ build/humbuglog.txt
phpdoc/
tests/test_data/json_write.json
tests/test_data/sessions/
.phpunit.result.cache

View File

@ -1,28 +0,0 @@
# Composer stores all downloaded packages in the vendor/ directory.
# Do not use the following if the vendor/ directory is commited to
# your git repository.
cache:
paths:
- vendor/
services:
- redis:latest
test:7:
before_script:
- bash build/docker_install.sh > /dev/null
- curl -sS https://getcomposer.org/installer | php
- php composer.phar update
- php composer.phar install
image: php:7
script:
- vendor/bin/phpunit --coverage-text --colors=never
test:hhvm:
before_script:
- /usr/local/bin/composer self-update
- composer update
- composer install
image: 51systems/docker-gitlab-ci-runner-hhvm
script:
- hhvm -d hhvm.php7.all=true vendor/bin/phpunit --coverage-text --colors=never

View File

@ -4,8 +4,9 @@ install:
- composer install
php:
- 7
- hhvm
- 7.2
- 7.3
- 7.4
- nightly
script:
@ -13,7 +14,7 @@ script:
- vendor/bin/phpunit -c build
services:
- redis
- redis-server
matrix:
allow_failures:

13
CHANGELOG.md Normal file
View File

@ -0,0 +1,13 @@
# Changelog
## Version 2.2
* Added `fuzzyCaseMatch` method to StringType
## Version 2.1
* Added `addHeader` method to base View class
## Version 2
* Removed instance/static dual calling from Enum - now just uses static methods

50
Jenkinsfile vendored Normal file
View File

@ -0,0 +1,50 @@
pipeline {
agent none
stages {
stage('PHP 7.2') {
agent {
docker {
image 'php:7.2-alpine'
args '-u root --privileged'
}
}
steps {
sh 'apk add --no-cache php7-phpdbg'
sh 'curl -sS https://getcomposer.org/installer | php'
sh 'rm -f composer.lock'
sh 'php composer.phar install --ignore-platform-reqs'
sh 'php composer.phar run-script coverage -- --coverage-text --colors=never'
}
}
stage('PHP 7.3') {
agent {
docker {
image 'php:7.3-alpine'
args '-u root --privileged'
}
}
steps {
sh 'apk add --no-cache php7-phpdbg'
sh 'curl -sS https://getcomposer.org/installer | php'
sh 'rm -f composer.lock'
sh 'php composer.phar install --ignore-platform-reqs'
sh 'php composer.phar run-script coverage -- --coverage-text --colors=never'
}
}
stage('PHP 7.4') {
agent {
docker {
image 'php:7.4-alpine'
args '-u root --privileged'
}
}
steps {
sh 'apk add --no-cache php7-phpdbg'
sh 'curl -sS https://getcomposer.org/installer | php'
sh 'rm -f composer.lock'
sh 'php composer.phar install --ignore-platform-reqs'
sh 'php composer.phar run-script coverage -- --coverage-text --colors=never'
}
}
}
}

21
LICENSE.md Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2017 Timothy J Warren
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,3 +1,6 @@
# Ion
[![Build Status](https://travis-ci.org/timw4mail/ion.svg?branch=master)](https://travis-ci.org/timw4mail/ion)
[![Build Status](https://jenkins.timshomepage.net/buildStatus/icon?job=Gitea%20-%20aviat/ion/master)](https://jenkins.timshomepage.net/job/Gitea%20-%20aviat/ion/master)
Ion is a set of helpful PHP libraries for general web development

View File

@ -102,10 +102,7 @@ class RoboFile extends \Robo\Tasks {
*/
public function coverage()
{
$this->taskPhpUnit()
->configFile('build/phpunit.xml')
->printed(true)
->run();
$this->_run(['phpdbg -qrr -- vendor/bin/phpunit -c build']);
}
/**
@ -207,7 +204,7 @@ class RoboFile extends \Robo\Tasks {
'tests'
];
$cmd_parts = ($report) ? $report_cmd_parts : $normal_cmd_parts;
$cmd_parts = $report ? $report_cmd_parts : $normal_cmd_parts;
$this->_run($cmd_parts);
}
@ -227,7 +224,7 @@ class RoboFile extends \Robo\Tasks {
{
$this->lint();
$this->taskPHPUnit()
->configFile('phpunit.xml')
->configFile('build/phpunit.xml')
->printed(true)
->run();
}

View File

@ -93,12 +93,12 @@ class InlineCommentSniff implements Sniff
private function _checkCommentStyle(File $phpcsFile, $stackPtr)
{
$tokens = $phpcsFile->getTokens();
if ($tokens[$stackPtr]['content']{0} === '#') {
if ($tokens[$stackPtr]['content'][0] === '#') {
$error = 'Perl-style comments are not allowed; use "// Comment" or DocBlock comments instead';
$phpcsFile->addError($error, $stackPtr, 'WrongStyle');
return FALSE;
} else if (substr($tokens[$stackPtr]['content'], 0, 2) === '/*'
|| $tokens[$stackPtr]['content']{0} === '*'
|| $tokens[$stackPtr]['content'][0] === '*'
) {
$error = 'Multi lines comments are not allowed; use "// Comment" DocBlock comments instead';
$phpcsFile->addError($error, $stackPtr, 'WrongStyle');

View File

@ -90,7 +90,7 @@ class ByteOrderMarkSniff implements Sniff
$fileStartHex = bin2hex(substr($fileStartString, 0, $bomByteLength));
if ($fileStartHex === $expectedBomHex) {
$error = "File contains a $bomName byte order mark (BOM).";
$phpcsFile->addError($error, $stackPtr);
$phpcsFile->addError($error, $stackPtr, 'no byte order mark');
break;
}
}

View File

@ -70,15 +70,15 @@ class Utf8EncodingSniff implements Sniff
$file_content = file_get_contents($file_path);
if (false === mb_check_encoding($file_content, 'UTF-8')) {
$error = 'File "' . $file_name . '" should be saved with Unicode (UTF-8) encoding.';
$phpcsFile->addError($error, 0);
$phpcsFile->addError($error, 0, 'utf8OrDie');
}
if ( ! self::_checkUtf8W3c($file_content)) {
$error = 'File "' . $file_name . '" should be saved with Unicode (UTF-8) encoding, but it did not successfully pass the W3C test.';
$phpcsFile->addError($error, 0);
$phpcsFile->addError($error, 0, 'utf8OrDie1');
}
if ( ! self::_checkUtf8Rfc3629($file_content)) {
$error = 'File "' . $file_name . '" should be saved with Unicode (UTF-8) encoding, but it did not meet RFC3629 requirements.';
$phpcsFile->addError($error, 0);
$phpcsFile->addError($error, 0, 'utf8OrDie2');
}
}//end process()

View File

@ -67,11 +67,11 @@ class LogicalOperatorAndSniff implements Sniff
$error_message = 'Logical operator should be in upper case;'
. ' use "' . strtoupper($operator_string)
. '" instead of "' . $operator_string . '"';
$phpcsFile->addError($error_message, $stackPtr);
$phpcsFile->addError($error_message, $stackPtr, 'uppercase operator');
}
$warning_message = 'The symbolic form "&&" is preferred over the literal form "AND"';
$phpcsFile->addWarning($warning_message, $stackPtr);
$phpcsFile->addWarning($warning_message, $stackPtr, '&& over AND');
}//end process()

View File

@ -72,7 +72,7 @@ class StrictComparisonOperatorSniff implements Sniff
$error_message = '"==" and "!=" are prohibited; use "'
. self::$_replacements[$operator_code] . '" instead of "'
. $operator_string . '".';
$phpcsFile->addError($error_message, $stackPtr);
$phpcsFile->addError($error_message, $stackPtr, 'strict type comparison');
}//end process()

View File

@ -1,84 +0,0 @@
<?php
/**
* CodeIgniter_Sniffs_Operators_UppercaseLogicalOperatorOrSniff.
*
* PHP version 5
*
* @category PHP
* @package PHP_CodeSniffer
* @author Thomas Ernest <thomas.ernest@baobaz.com>
* @copyright 2006 Thomas Ernest
* @license http://thomas.ernest.fr/developement/php_cs/licence GNU General Public License
* @link http://pear.php.net/package/PHP_CodeSniffer
*/
/**
* CodeIgniter_Sniffs_Operators_UppercaseLogicalOperatorOrSniff.
*
* Ensures that the logical operator 'OR' is in upper cases and its symbolic equivalent.
*
* @category PHP
* @package PHP_CodeSniffer
* @author Thomas Ernest <thomas.ernest@baobaz.com>
* @copyright 2006 Thomas Ernest
* @license http://thomas.ernest.fr/developement/php_cs/licence GNU General Public License
* @link http://pear.php.net/package/PHP_CodeSniffer
*/
namespace CodeIgniter\Sniffs\Operators;
use PHP_CodeSniffer\Sniffs\Sniff;
use PHP_CodeSniffer\Files\File;
class UppercaseLogicalOperatorOrSniff implements Sniff
{
/**
* Returns an array of tokens this test wants to listen for: literal and symbolic operators or.
*
* @return array
*/
public function register()
{
return array(
T_BOOLEAN_OR,
T_LOGICAL_OR,
);
}//end register()
/**
* Processes this test, when one of its tokens is encountered.
*
* @param File $phpcsFile The current file being scanned.
* @param int $stackPtr The position of the current token
* in the stack passed in $tokens.
*
* @return void
*/
public function process(File $phpcsFile, $stackPtr)
{
$tokens = $phpcsFile->getTokens();
$operator_token = $tokens[$stackPtr];
$operator_string = $operator_token['content'];
$operator_code = $operator_token['code'];
if ($operator_code == T_BOOLEAN_OR) {
$error_message = 'Logical operator "' . $operator_string
. '" is prohibited; use "OR" instead';
$phpcsFile->addError($error_message, $stackPtr, 'UseOf||InsteadOfOR');
}
// it is literal, if it is not symbolic
else if ($operator_string !== strtoupper($operator_string)) {
$error_message = 'Logical operator should be in upper case;'
. ' use "' . strtoupper($operator_string)
. '" instead of "' . $operator_string . '"';
$phpcsFile->addError($error_message, $stackPtr, 'UseOfLowercaseOr');
}
}//end process()
}//end class
?>

View File

@ -18,6 +18,8 @@ namespace CodeIgniter\Sniffs\Strings;
use PHP_CodeSniffer\Sniffs\Sniff;
use PHP_CodeSniffer\Files\File;
use Exception;
/**
* CodeIgniter_Sniffs_Strings_DoubleQuoteUsageSniff.
*
@ -104,19 +106,19 @@ class VariableUsageSniff implements Sniff
$this->_parseVariable($strTokens, $strPtr);
} catch (Exception $err) {
$error = 'There is no variable, object nor array between curly braces. Please use the escape char for $ or {.';
$phpcsFile->addError($error, $stackPtr);
$phpcsFile->addError($error, $stackPtr, 1987234);
}
$variableFound = TRUE;
if ('}' !== $strTokens[$strPtr]) {
$error = 'There is no matching closing curly brace.';
$phpcsFile->addError($error, $stackPtr);
$phpcsFile->addError($error, $stackPtr, 987234);
}
// don't move forward, since it will be done in the main loop
// $strPtr++;
} else if (T_VARIABLE === $strToken[0]) {
$variableFound = TRUE;
$error = "Variable {$strToken[1]} in double-quoted strings should be enclosed with curly braces. Please consider {{$strToken[1]}}";
$phpcsFile->addError($error, $stackPtr);
$phpcsFile->addError($error, $stackPtr, 29087234);
}
}
$strPtr++;
@ -146,7 +148,7 @@ class VariableUsageSniff implements Sniff
if (is_array($strToken)) {
if (T_VARIABLE === $strToken[0]) {
$error = "Variables like {$strToken[1]} should be in double-quoted strings only.";
$phpcsFile->addError($error, $stackPtr);
$phpcsFile->addError($error, $stackPtr, 12343);
}
}
$strPtr++;
@ -392,12 +394,12 @@ class DoubleQuoteUsageSniff extends VariableUsageSniff
&& false === $smpl_qt_at
) {
$error = 'Single-quoted strings should be used unless it contains variables, special chars like \n or single quotes.';
$phpcsFile->addError($error, $stackPtr);
$phpcsFile->addError($error, $stackPtr, 1982);
} else if (false !== $smpl_qt_at && false !== $dbl_qt_at
&& false === $has_variable && false === $has_specific_sequence
) {
$warning = 'It is encouraged to use a single-quoted string, since it doesn\'t contain any variable nor special char though it mixes single and double quotes.';
$phpcsFile->addWarning($warning, $stackPtr);
$phpcsFile->addWarning($warning, $stackPtr, 1982734);
}
}//end processDoubleQuotedString()
@ -425,7 +427,7 @@ class DoubleQuoteUsageSniff extends VariableUsageSniff
$smpl_qt_at = strpos($qtString, "'");
if (false === $has_variable && false !== $smpl_qt_at && false === $dbl_qt_at) {
$warning = 'You may also use double-quoted strings if the string contains single quotes, so you do not have to use escape characters.';
$phpcsFile->addWarning($warning, $stackPtr);
$phpcsFile->addWarning($warning, $stackPtr, 98723);
}
}//end processSingleQuotedString()
@ -460,5 +462,3 @@ class DoubleQuoteUsageSniff extends VariableUsageSniff
}//end _hasSpecificSequence()
}//end class
?>

View File

@ -77,7 +77,7 @@ class DisallowSpaceIndentSniff implements Sniff
if (strpos($tokens[$stackPtr]['content'], " ") !== false) {
$error = 'Tabs must be used to indent lines; spaces are not allowed for code indentation';
$phpcsFile->addError($error, $stackPtr);
$phpcsFile->addError($error, $stackPtr, 'indent with tabs!');
}
}//end process()

View File

@ -72,7 +72,7 @@ class DisallowWitheSpaceAroundPhpTagsSniff implements Sniff
$isFirst = 0 === $stackPtr;
if ( ! $isFirst) {
$error = 'Any char before the opening PHP tag is prohibited. Please remove newline or indentation before the opening PHP tag.';
$phpcsFile->addError($error, $stackPtr);
$phpcsFile->addError($error, $stackPtr, 'nothing before opening tag');
}
} else {
// if (T_CLOSE_TAG === $php_tag_code)
@ -84,7 +84,7 @@ class DisallowWitheSpaceAroundPhpTagsSniff implements Sniff
$containsEndTagOnly = strlen($php_tag_string) > 2;
if ( ! $isLast || ! $containsEndTagOnly ) {
$error = 'Any char after the closing PHP tag is prohibited. Please removes newline or spaces after the closing PHP tag.';
$phpcsFile->addError($error, $stackPtr);
$phpcsFile->addError($error, $stackPtr, 'nothing after closing tag');
}
}
}//end process()

View File

@ -71,12 +71,10 @@ class ElseOnNewLineSniff implements Sniff
$previous_non_blank_token = $tokens[$previous_non_blank_token_ptr];
if ($previous_non_blank_token['line'] === $else_token['line']) {
$error = '"' . $else_token['content'] . '" should be on a new line.';
$phpcsFile->addError($error, $stackPtr);
$phpcsFile->addError($error, $stackPtr, 'else on new line');
}
}//end process()
}//end class
?>
}//end class

View File

@ -65,7 +65,7 @@ class LogicalNotSpacingSniff implements Sniff
$next_token = $tokens[$stackPtr + 1];
if (T_WHITESPACE !== $previous_token['code'] || T_WHITESPACE !== $next_token['code']) {
$error = 'Logical operator ! should always be preceded and followed with a whitespace.';
$phpcsFile->addError($error, $stackPtr);
$phpcsFile->addError($error, $stackPtr, 'Logical Not operator');
}
}//end process()

View File

@ -1,104 +0,0 @@
<?php
/**
* CodeIgniter_Sniffs_Files_AbstractClosingCommentSniff.
*
* PHP version 5
*
* @category PHP
* @package PHP_CodeSniffer
* @author Thomas Ernest <thomas.ernest@baobaz.com>
* @copyright 2006 Thomas Ernest
* @license http://thomas.ernest.fr/developement/php_cs/licence GNU General Public License
* @link http://pear.php.net/package/PHP_CodeSniffer
*/
/**
* CodeIgniter_Sniffs_Files_AbstractClosingCommentSniff.
*
* Defines some methods used by
* CodeIgniter_Sniffs_Files_ClosingFileCommentSniff
* and CodeIgniter_Sniffs_Files_ClosingLocationCommentSniff.
*
* @category PHP
* @package PHP_CodeSniffer
* @author Thomas Ernest <thomas.ernest@baobaz.com>
* @copyright 2006 Thomas Ernest
* @license http://thomas.ernest.fr/developement/php_cs/licence GNU General Public License
* @link http://pear.php.net/package/PHP_CodeSniffer
*/
namespace CodeIgniter\Sniffs\Files;
use PHP_CodeSniffer\Sniffs\Sniff;
use PHP_CodeSniffer\Files\File;
class AbstractClosingCommentSniff implements Sniff
{
/**
* As an abstract class, this sniff is not associated to any token.
*/
public function register()
{
return array();
}
/**
* As an abstract class, this sniff is not dedicated to process a token.
*/
public function process(File $phpcsFile, $stackPtr)
{
$error = __CLASS__.'::'.__METHOD__.' is abstract. Please develop this method in a child class.';
throw new PHP_CodeSniffer_Exception($error);
}
/**
* Returns the comment without its delimiter(s) as well as leading
* and traling whitespaces.
*
* It removes the first #, the two first / (i.e. //) or the first /*
* and last \*\/. If a comment starts with /**, then the last * will remain
* as well as whitespaces between this star and the comment content.
*
* @param string $comment Comment containing either comment delimiter(s) and
* trailing or leading whitspaces to clean.
*
* @return string Comment without comment delimiter(s) and whitespaces.
*/
protected static function _getCommentContent ($comment)
{
if (self::_stringStartsWith($comment, '#')) {
$comment = substr($comment, 1);
} else if (self::_stringStartsWith($comment, '//')) {
$comment = substr($comment, 2);
} else if (self::_stringStartsWith($comment, '/*')) {
$comment = substr($comment, 2, strlen($comment) - 2 - 2);
}
$comment = trim($comment);
return $comment;
}//_getCommentContent()
/**
* Binary safe string comparison between $needle and
* the beginning of $haystack. Returns true if $haystack starts with
* $needle, false otherwise.
*
* @param string $haystack The string to search in.
* @param string $needle The string to search for.
*
* @return bool true if $haystack starts with $needle, false otherwise.
*/
protected static function _stringStartsWith ($haystack, $needle)
{
$startsWith = false;
if (strlen($needle) <= strlen($haystack)) {
$haystackBeginning = substr($haystack, 0, strlen($needle));
if (0 === strcmp($haystackBeginning, $needle)) {
$startsWith = true;
}
}
return $startsWith;
}//_stringStartsWith()
}//end class
?>

View File

@ -1,109 +0,0 @@
<?php
/**
* CodeIgniter_Sniffs_Files_ClosingFileCommentSniff.
*
* PHP version 5
*
* @category PHP
* @package PHP_CodeSniffer
* @author Thomas Ernest <thomas.ernest@baobaz.com>
* @copyright 2006 Thomas Ernest
* @license http://thomas.ernest.fr/developement/php_cs/licence GNU General Public License
* @link http://pear.php.net/package/PHP_CodeSniffer
*/
/**
* CodeIgniter_Sniffs_Files_ClosingFileCommentSniff.
*
* Ensures that a comment containing the file name is available at the end of file.
* Only other comments and whitespaces are allowed to follow this specific comment.
*
* It may be all kind of comment like multi-line and inline C-style comments as
* well as PERL-style comments. Any number of white may separate comment delimiters
* from comment content. However, content has to be equal to template
* "End of file <file_name>". Comparison between content and template is
* case-sensitive.
*
* @category PHP
* @package PHP_CodeSniffer
* @author Thomas Ernest <thomas.ernest@baobaz.com>
* @copyright 2006 Thomas Ernest
* @license http://thomas.ernest.fr/developement/php_cs/licence GNU General Public License
* @link http://pear.php.net/package/PHP_CodeSniffer
*/
namespace CodeIgniter\Sniffs\Files;
use PHP_CodeSniffer\Files\File;
class ClosingFileCommentSniff extends AbstractClosingCommentSniff
{
/**
* Returns an array of tokens this test wants to listen for.
*
* @return array
*/
public function register()
{
return array(
T_OPEN_TAG,
);
}//end register()
/**
* Processes this test, when one of its tokens is encountered.
*
* @param File $phpcsFile The current file being scanned.
* @param int $stackPtr The position of the current token
* in the stack passed in $tokens.
*
* @return void
*/
public function process(File $phpcsFile, $stackPtr)
{
// We are only interested if this is the first open tag.
if ($stackPtr !== 0) {
if ($phpcsFile->findPrevious(T_OPEN_TAG, ($stackPtr - 1)) !== false) {
return;
}
}
$fullFilename = $phpcsFile->getFilename();
$filename = basename($fullFilename);
$commentTemplate = "End of file $filename";
$tokens = $phpcsFile->getTokens();
$currentToken = count($tokens) - 1;
$hasClosingFileComment = false;
$isNotAWhitespaceOrAComment = false;
while ($currentToken >= 0
&& ! $isNotAWhitespaceOrAComment
&& ! $hasClosingFileComment
) {
$token = $tokens[$currentToken];
$tokenCode = $token['code'];
if (T_COMMENT === $tokenCode) {
$commentString = self::_getCommentContent($token['content']);
if (0 === strcmp($commentString, $commentTemplate)) {
$hasClosingFileComment = true;
}
} else if (T_WHITESPACE === $tokenCode) {
// Whitespaces are allowed between the closing file comment,
// other comments and end of file
} else {
$isNotAWhitespaceOrAComment = true;
}
$currentToken--;
}
if ( ! $hasClosingFileComment) {
$error = 'No comment block marks the end of file instead of the closing PHP tag. Please add a comment block containing only "' . $commentTemplate . '".';
$phpcsFile->addError($error, $currentToken);
}
}//end process()
}//end class
?>

View File

@ -1,182 +0,0 @@
<?php
/**
* CodeIgniter_Sniffs_Files_ClosingLocationCommentSniff.
*
* PHP version 5
*
* @category PHP
* @package PHP_CodeSniffer
* @author Thomas Ernest <thomas.ernest@baobaz.com>
* @copyright 2006 Thomas Ernest
* @license http://thomas.ernest.fr/developement/php_cs/licence GNU General Public License
* @link http://pear.php.net/package/PHP_CodeSniffer
*/
/**
* CodeIgniter_Sniffs_Files_ClosingLocationCommentSniff.
*
* Ensures that a comment containing the file location exists at the end of file.
* Only other comments and whitespaces are allowed between this comment and
* the end of file.
*
* It may be all kind of comment like multi-line and inline C-style comments as
* well as PERL-style comments. Any number of white may separate comment delimiters
* from comment content. However, content has to be equal to template
* "Location: <file_path_relative_to_application_root>".
* Comparison between content and template is case-sensitive.
*
* There are several ways to configure the application root. In order of priority :
* - Configuration variable ci_application_root.
* - Rule property applicationRoot.
* - Default value '/application/'
*
* @category PHP
* @package PHP_CodeSniffer
* @author Thomas Ernest <thomas.ernest@baobaz.com>
* @copyright 2006 Thomas Ernest
* @license http://thomas.ernest.fr/developement/php_cs/licence GNU General Public License
* @link http://pear.php.net/package/PHP_CodeSniffer
*/
namespace CodeIgniter\Sniffs\Files;
use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Util\Common;
class ClosingLocationCommentSniff extends AbstractClosingCommentSniff
{
public $applicationRoot = '/application/';
/**
* Returns an array of tokens this test wants to listen for.
*
* @return array
*/
public function register()
{
return array(
T_OPEN_TAG
);
}//end register()
/**
* Processes this test, when one of its tokens is encountered.
*
* @param File $phpcsFile The current file being scanned.
* @param int $stackPtr The position of the current token
* in the stack passed in $tokens.
*
* @return void
*/
public function process(File $phpcsFile, $stackPtr)
{
// We are only interested if this is the first open tag.
if ($stackPtr !== 0) {
if ($phpcsFile->findPrevious(T_OPEN_TAG, ($stackPtr - 1)) !== false) {
return;
}
}
$filePath = $phpcsFile->getFilename();
$tokens = $phpcsFile->getTokens();
// removes the application root from the beginning of the file path
$locationPath = self::_getLocationPath($filePath, $this->_getAppRoot());
// add an error, if application root doesn't exist in current file path
if (false === $locationPath) {
$error = 'Unable to find "' . $this->_getAppRoot() . '" in file path "' . $filePath . '". Please set your project\'s application root.';
$phpcsFile->addError($error, count($tokens) - 1);
return;
}
// generates the expected comment
$commentTemplate = "Location: $locationPath";
$currentToken = count($tokens) - 1;
$hasClosingLocationComment = false;
$isNotAWhitespaceOrAComment = false;
while ($currentToken >= 0
&& ! $isNotAWhitespaceOrAComment
&& ! $hasClosingLocationComment
) {
$token = $tokens[$currentToken];
$tokenCode = $token['code'];
if (T_COMMENT === $tokenCode) {
$commentString = self::_getCommentContent($token['content']);
if (0 === strcmp($commentString, $commentTemplate)) {
$hasClosingLocationComment = true;
}
} else if (T_WHITESPACE === $tokenCode) {
// Whitespaces are allowed between the closing file comment,
//other comments and end of file
} else {
$isNotAWhitespaceOrAComment = true;
}
$currentToken--;
}
if ( ! $hasClosingLocationComment) {
$error = 'No comment block marks the end of file instead of the closing PHP tag. Please add a comment block containing only "' . $commentTemplate . '".';
$phpcsFile->addError($error, $currentToken);
}
}//end process()
/**
* Returns the relative path from $appRoot to $filePath, or false if
* $appRoot cannot be found in $filePath, because $appRoot is not a parent
* of $filePath.
*
* @param string $filePath Full path to the file being proceed.
* @param string $appRoot Partial or full path to the CodeIgniter
* application root of the file being proceed. It must not contain the
* full path to the application root, but at least the name of the
* application root. Parent directory of the application root are allowed
* but not mandatory.
*
* @return string|bool The relative path from $appRoot to $filePath, or
* false if $appRoot cannot be found in $filePath.
*/
private static function _getLocationPath ($filePath, $appRoot)
{
// removes the path to application root
// from the beginning of the file path
$appRootAt = strpos($filePath, $appRoot);
if (false === $appRootAt) {
return false;
}
$localPath = substr($filePath, $appRootAt + strlen($appRoot));
// ensures the location path to be a relative path starting with "./".
if ( ! self::_stringStartsWith($localPath, './')) {
$localPath = './' . $localPath;
} else if ( ! self::_stringStartsWith($localPath, '.')
&& self::_stringStartsWith($localPath, '/')
) {
$localPath = '.' . $localPath;
}
return $localPath;
}//end _getLocationPath()
/**
* Returns the application root that should be used first.
*
* There are several ways to configure the application root.
* In order of priority :
* - Configuration variable ci_application_root.
* - Rule property applicationRoot.
* - Default value '/application/'
*
* @return string Path to your project application root.
*/
private function _getAppRoot()
{
$appRoot = Common::getConfigData('ci_application_root');
if (null === $appRoot) {
$appRoot = $this->applicationRoot;
}
return $appRoot;
}//end _getAppRoot()
}//end class
?>

View File

@ -1,142 +0,0 @@
<?php
/**
* CodeIgniter_Sniffs_NamingConventions_ConstructorNameSniff.
*
* PHP version 5
*
* @category PHP
* @package PHP_CodeSniffer
* @author Thomas Ernest <thomas.ernest@gmail.com>
* @copyright 2011 Thomas Ernest
* @license http://thomas.ernest.fr/developement/php_cs/licence GNU General Public License
* @link http://pear.php.net/package/PHP_CodeSniffer
*/
namespace CodeIgniter\Sniffs\NamingConventions;
use PHP_CodeSniffer\Sniffs\AbstractScopeSniff;
use PHP_CodeSniffer\Files\File;
/**
* CodeIgniter_Sniffs_NamingConventions_ConstructorNameSniff.
*
* Favor PHP 4 constructor syntax, which uses "function ClassName()".
* Avoid PHP 5 constructor syntax, which uses "function __construct()".
*
* @todo Try to avoid overly long and verbose names.
*
* @category PHP
* @package PHP_CodeSniffer
* @author Thomas Ernest <thomas.ernest@gmail.com>
* @copyright 2010 Thomas Ernest
* @license http://thomas.ernest.fr/developement/php_cs/licence GNU General Public License
* @link http://pear.php.net/package/PHP_CodeSniffer
*/
class ConstructorNameSniff extends AbstractScopeSniff
{
public $php5Constructors = '1';
/**
* Constructs the test with the tokens it wishes to listen for.
*
* @return void
*/
public function __construct()
{
parent::__construct(array(T_CLASS, T_INTERFACE), array(T_FUNCTION), true);
}//end __construct()
/**
* Processes this test when one of its tokens is encountered.
*
* @param File $phpcsFile The current file being scanned.
* @param int $stackPtr The position of the current token
* in the stack passed in $tokens.
* @param int $currScope A pointer to the start of the scope.
*
* @return void
*/
protected function processTokenWithinScope(
File $phpcsFile,
$stackPtr,
$currScope
) {
$methodName = $phpcsFile->getDeclarationName($stackPtr);
$className = $phpcsFile->getDeclarationName($currScope);
$isPhp4Constructor = strcasecmp($methodName, $className) === 0;
$isPhp5Constructor = strcasecmp($methodName, '__construct') === 0;
if ($this->php5Constructors != '0') {
if ($isPhp4Constructor) {
$error = "PHP4 style constructors are not allowed; use \"__construct\" instead";
$phpcsFile->addError($error, $stackPtr);
}
} else {
if ($isPhp5Constructor) {
$error = "PHP5 style constructors are not allowed; use \"$className\" instead";
$phpcsFile->addError($error, $stackPtr);
}
}
if ( ! $isPhp4Constructor && ! $isPhp5Constructor ) {
return;
}
$tokens = $phpcsFile->getTokens();
$parentClassName = $phpcsFile->findExtendedClassName($currScope);
$wrongConstructor = '';
// prepares the error message and wrong constructor
if ($this->php5Constructors != '0') {
$error = 'PHP4 style calls to parent constructors are not allowed.';
$error = "$error Please use \"parent::__construct\" instead.";
if (false !== $parentClassName) {
$wrongConstructor = $parentClassName;
}
// Else $wrongConstructor will be empty
// and the test expression will always be false.
// It doesn't check that no parent method should be called
// when no parent class is defined.
} else {
$error = 'PHP5 style calls to parent constructors are not allowed.';
if (false !== $parentClassName) {
$error = "$error Please use \"parent::$parentClassName\" instead.";
}
$wrongConstructor = '__construct';
}
// looks for the use of a wrong constructor.
$endFunctionIndex = $tokens[$stackPtr]['scope_closer'];
$doubleColonIndex = $phpcsFile->findNext(
array(T_DOUBLE_COLON),
$stackPtr,
$endFunctionIndex
);
while ($doubleColonIndex) {
if ($tokens[($doubleColonIndex + 1)]['code'] === T_STRING
&& $tokens[($doubleColonIndex + 1)]['content'] === $wrongConstructor
) {
$phpcsFile->addError($error, ($doubleColonIndex + 1));
}
$doubleColonIndex = $phpcsFile->findNext(
array(T_DOUBLE_COLON),
$doubleColonIndex + 1,
$endFunctionIndex
);
}
}//end processTokenWithinScope()
protected function processTokenOutsideScope(File $phpcsFile, $stackPtr)
{
// TODO: Implement processTokenOutsideScope() method.
}
}//end class
?>

View File

@ -1,84 +0,0 @@
<?php
/**
* CodeIgniter_Sniffs_NamingConventions_ValidClassNameSniff.
*
* PHP version 5
*
* @category PHP
* @package PHP_CodeSniffer
* @author Thomas Ernest <thomas.ernest@baoabz.com>
* @copyright 2010 Thomas Ernest
* @license http://thomas.ernest.fr/developement/php_cs/licence GNU General Public License
* @link http://pear.php.net/package/PHP_CodeSniffer
*/
/**
* CodeIgniter_Sniffs_NamingConventions_ValidClassNameSniff.
*
* Ensures that class and interface names have their first letter uppercase
* and that words are separated with an underscore, and not CamelCased.
*
* @todo Try to avoid overly long and verbose names in using property rule and
* configuration variable to set limits. Have a look at
* CodeIgniter_Sniffs_NamingConventions_ValidMethodNameSniff.
*
* @category PHP
* @package PHP_CodeSniffer
* @author Thomas Ernest <thomas.ernest@baoabz.com>
* @copyright 2010 Thomas Ernest
* @license http://thomas.ernest.fr/developement/php_cs/licence GNU General Public License
* @link http://pear.php.net/package/PHP_CodeSniffer
*/
namespace CodeIgniter\Sniffs\NamingConventions;
use PHP_CodeSniffer\Sniffs\Sniff;
use PHP_CodeSniffer\Files\File;
class ValidClassNameSniff implements Sniff
{
/**
* Returns an array of tokens this test wants to listen for.
*
* @return array
*/
public function register()
{
return array(
T_CLASS,
T_INTERFACE,
);
}//end register()
/**
* Processes this test, when one of its tokens is encountered.
*
* @param File $phpcsFile The current file being processed.
* @param int $stackPtr The position of the current token
* in the stack passed in $tokens.
*
* @return void
*/
public function process(File $phpcsFile, $stackPtr)
{
// get the class name
$className = trim($phpcsFile->getDeclarationName($stackPtr));
// compute the expected class name
// [^_] means "something different from _", but not "nothing or something different from _"
$lcClassNameChunk = preg_replace('/([^_])([A-Z])/', '${1}_${2}', $className);
$expectedClassName
= strtoupper($className[0]) . strtolower(substr($lcClassNameChunk,1));
// ensures that the current class name
// and the expected class name are identical
if (0 !== strcmp($className, $expectedClassName)) {
$error = 'Class names should always have their first letter uppercase. Multiple words should be separated with an underscore, and not CamelCased. Please consider ' . $expectedClassName . ' instead of ' . $className . '.';
$phpcsFile->addError($error, $stackPtr);
}
}//end process()
}//end class
?>

View File

@ -1,84 +0,0 @@
<?php
/**
* CodeIgniter_Sniffs_NamingConventions_ValidFileNameSniff.
*
* PHP version 5
*
* @category PHP
* @package PHP_CodeSniffer
* @author Thomas Ernest <thomas.ernest@baobaz.com>
* @copyright 2011 Thomas Ernest
* @license http://thomas.ernest.fr/developement/php_cs/licence GNU General Public License
* @link http://pear.php.net/package/PHP_CodeSniffer
*/
/**
* CodeIgniter_Sniffs_NamingConventions_ValidFileNameSniff.
*
* Tests that the file name matchs the name of the class that it contains in lower case.
*
* @category PHP
* @package PHP_CodeSniffer
* @author Thomas Ernest <thomas.ernest@baobaz.com>
* @copyright 2011 Thomas Ernest
* @license http://thomas.ernest.fr/developement/php_cs/licence GNU General Public License
* @link http://pear.php.net/package/PHP_CodeSniffer
*/
namespace CodeIgniter\Sniffs\NamingConventions;
use PHP_CodeSniffer\Sniffs\Sniff;
use PHP_CodeSniffer\Files\File;
class ValidFileNameSniff implements Sniff
{
/**
* Returns an array of tokens this test wants to listen for.
*
* @return array
*/
public function register()
{
return array(
T_CLASS,
T_INTERFACE,
);
}//end register()
/**
* Processes this test, when one of its tokens is encountered.
*
* @param File $phpcsFile The file being scanned.
* @param int $stackPtr The position of the current token in the
* stack passed in $tokens.
*
* @return void
*/
public function process(File $phpcsFile, $stackPtr)
{
$tokens = $phpcsFile->getTokens();
// computes the expected filename based on the name of the class or interface that it contains.
$decNamePtr = $phpcsFile->findNext(T_STRING, $stackPtr);
$decName = $tokens[$decNamePtr]['content'];
$expectedFileName = strtolower($decName);
// extracts filename without extension from its path.
$fullPath = $phpcsFile->getFilename();
$fileNameAndExt = basename($fullPath);
$fileName = substr($fileNameAndExt, 0, strrpos($fileNameAndExt, '.'));
if ($expectedFileName !== $fileName) {
$errorTemplate = 'Filename "%s" doesn\'t match the name of the %s that it contains "%s" in lower case. "%s" was expected.';
$errorMessage = sprintf(
$errorTemplate,
$fileName,
strtolower($tokens[$stackPtr]['content']), // class or interface
$decName,
$expectedFileName
);
$phpcsFile->addError($errorMessage, 0);
}
}//end process()
}//end class
?>

View File

@ -1,161 +0,0 @@
<?php
/**
* CodeIgniter_Sniffs_NamingConventions_ValidMethodNameSniff.
*
* PHP version 5
*
* @category PHP
* @package PHP_CodeSniffer
* @author Thomas Ernest <thomas.ernest@baoabz.com>
* @copyright 2010 Thomas Ernest
* @license http://thomas.ernest.fr/developement/php_cs/licence GNU General Public License
* @link http://pear.php.net/package/PHP_CodeSniffer
*/
/**
* CodeIgniter_Sniffs_NamingConventions_ValidMethodNameSniff.
*
* Ensures that class methods and functions areentirely lowercased and that
* words are separated with an underscore, and not CamelCased.
* Ensures that private class methods are prefixed with an underscore and that
* all other methods are not prefixed with an underscored.
* Ensures that names longer than 50 chars are prohibited. Likewise names longer
* than 35 chars raise a warning.
*
* @todo Use a rule property or a configuration variable to allow users to set
* their own maximum lengths for function and method names. Have a look at
* CodeIgniter_Sniffs_Files_ClosingLocationCommentSniff and application root.
*
* @category PHP
* @package PHP_CodeSniffer
* @author Thomas Ernest <thomas.ernest@baoabz.com>
* @copyright 2010 Thomas Ernest
* @license http://thomas.ernest.fr/developement/php_cs/licence GNU General Public License
* @link http://pear.php.net/package/PHP_CodeSniffer
*/
namespace CodeIgniter\Sniffs\NamingConventions;
use PHP_CodeSniffer\Sniffs\AbstactScopeSniff;
use PHP_CodeSniffer\Files\File;
class ValidMethodNameSniff extends AbstractScopeSniff
{
/**
* A list of all PHP magic methods.
*
* @var array
*/
protected static $magicMethods = array(
'construct',
'destruct',
'call',
'callStatic',
'get',
'set',
'isset',
'unset',
'sleep',
'wakeup',
'toString',
'set_state',
'clone',
);
/**
* Defines which token(s) in which scope(s) will be proceed.
*/
public function __construct()
{
parent::__construct(array(T_CLASS, T_INTERFACE), array(T_FUNCTION), true);
}//end __construct()
/**
* Processes the tokens within the scope.
*
* @param File $phpcsFile The file being processed.
* @param int $stackPtr The position where this token was
* found.
* @param int $currScope The position of the current scope.
*
* @return void
*/
protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope)
{
$methodName = $phpcsFile->getDeclarationName($stackPtr);
if ($methodName === null) {
// Ignore closures.
return;
}
$className = $phpcsFile->getDeclarationName($currScope);
// Is this a magic method i.e. is prefixed with "__".
if (0 === strcmp(substr($methodName, 0, 2), '__')) {
$magicPart = substr($methodName, 2);
if (in_array($magicPart, self::$magicMethods) === false) {
$error = "Method name \"$className::$methodName\" is invalid; only PHP magic methods should be prefixed with a double underscore";
$phpcsFile->addError($error, $stackPtr);
}
return;
}
// PHP4 constructors are allowed to break our rules.
if ($methodName === $className) {
return;
}
// PHP4 destructors are allowed to break our rules.
if ($methodName === '_'.$className) {
return;
}
if (0 !== strcmp($methodName, strtolower($methodName))) {
$uscrdMethodName = preg_replace('/([A-Z])/', '_${1}', $methodName);
$expectedMethodName = strtolower($uscrdMethodName);
$error = "Class methods should be entirely lowercased. Please consider \"$expectedMethodName\" instead of \"$methodName\".";
$phpcsFile->addError($error, $stackPtr);
return;
}
$methodProps = $phpcsFile->getMethodProperties($stackPtr);
$scope = $methodProps['scope'];
$scopeSpecified = $methodProps['scope_specified'];
// If it's a private method, it must have an underscore on the front.
if ($scope === 'private' && $methodName{0} !== '_') {
$error = "Private method name \"$className::$methodName\" must be prefixed with an underscore";
$phpcsFile->addError($error, $stackPtr);
return;
}
// If it's not a private method, it must not have an underscore on the front.
if ($scope !== 'private' && $methodName{0} === '_') {
if (true === $scopeSpecified) {
$error = "Public method name \"$className::$methodName\" must not be prefixed with an underscore";
} else {
$error = ucfirst($scope)." method name \"$className::$methodName\" must not be prefixed with an underscore";
}
$phpcsFile->addError($error, $stackPtr);
return;
}
// If name is too verbose,
// then either an error or a warning is displayed.
$error_limit = 50;
$warning_limit = 35;
if (strlen($methodName) > $error_limit) {
$error = "Overly long and verbose names are prohibited. Please find a name shorter than $error_limit chars.";
$phpcsFile->addError($error, $stackPtr);
return;
} else if (strlen($methodName) > $warning_limit) {
$warning = "Try to avoid overly long and verbose names in finding a name shorter than $warning_limit chars.";
$phpcsFile->addWarning($warning, $stackPtr);
}
}//end processTokenWithinScope()
}//end class
?>

View File

@ -1,562 +0,0 @@
<?php
/**
* CodeIgniter_Sniffs_NamingConventions_ValidVariableNameSniff.
*
* PHP version 5
*
* @category PHP
* @package PHP_CodeSniffer
* @author Thomas Ernest <thomas.ernest@baoabz.com>
* @copyright 2010 Thomas Ernest
* @license http://thomas.ernest.fr/developement/php_cs/licence GNU General Public License
* @link http://pear.php.net/package/PHP_CodeSniffer
*/
/**
* CodeIgniter_Sniffs_NamingConventions_ValidVariableNameSniff.
*
* Ensures that variable names contain only lowercase letters,
* use underscore separators.
* Ensures that class attribute names are prefixed with an underscore,
* only when they are private.
* Ensure that variable names are longer than 3 chars except those declared
* in for loops.
*
* @todo Try to avoid overly long and verbose names in using property rule and
* configuration variable to set limits. Have a look at
* CodeIgniter_Sniffs_NamingConventions_ValidMethodNameSniff.
* @todo Use a property rule or a configuration variable to allow users to set
* minimum variable name length. Have a look at
* CodeIgniter_Sniffs_Files_ClosingLocationCommentSniff and application root.
*
* @category PHP
* @package PHP_CodeSniffer
* @author Thomas Ernest <thomas.ernest@baoabz.com>
* @copyright 2010 Thomas Ernest
* @license http://thomas.ernest.fr/developement/php_cs/licence GNU General Public License
* @link http://pear.php.net/package/PHP_CodeSniffer
*/
namespace CodeIgniter\Sniffs\NamingConventions;
use PHP_CodeSniffer\Sniffs\AbstractVariableSniff;
use PHP_CodeSniffer\Files\File;
class ValidVariableNameSniff extends AbstractVariableSniff
{
/**
* Processes class member variables.
*
* @param File $phpcsFile The file being scanned.
* @param int $stackPtr The position of the current token
* in the stack passed in $tokens.
*
* @return void
*/
protected function processMemberVar(File $phpcsFile, $stackPtr)
{
// get variable name and properties
$tokens = $phpcsFile->getTokens();
$varTk = $tokens[$stackPtr];
$varName = substr($varTk['content'], 1);
$varProps = $phpcsFile->getMemberProperties($stackPtr);
// check(s)
if ( ! $this->checkLowerCase($phpcsFile, $stackPtr, $varName) ) {
return;
}
if ( ! $this->checkVisibilityPrefix($phpcsFile, $stackPtr, $varName, $varProps)) {
return;
}
if ( ! $this->checkLength($phpcsFile, $stackPtr, $varName)) {
return;
}
}//end processMemberVar()
/**
* Processes normal variables.
*
* @param File $phpcsFile The file where this token was found.
* @param int $stackPtr The position where the token was found.
*
* @return void
*/
protected function processVariable(File $phpcsFile, $stackPtr)
{
// get variable name
$tokens = $phpcsFile->getTokens();
$varTk = $tokens[$stackPtr];
$varName = substr($varTk['content'], 1);
// skip the current object variable, i.e. $this
if (0 === strcmp($varName, 'this')) {
return;
}
// check(s)
if ( ! $this->checkLowerCase($phpcsFile, $stackPtr, $varName)) {
return;
}
if ( ! $this->checkLength($phpcsFile, $stackPtr, $varName)) {
return;
}
}//end processVariable()
/**
* Processes variables in double quoted strings.
*
* @param File $phpcsFile The file where this token was found.
* @param int $stackPtr The position where the token was found.
*
* @return void
*/
protected function processVariableInString(File $phpcsFile, $stackPtr)
{
$tokens = $phpcsFile->getTokens();
$stringTk = $tokens[$stackPtr];
$stringString = $stringTk['content'];
$varAt = self::_getVariablePosition($stringString, 0);
while (false !== $varAt) {
// get variable name
$matches = array();
preg_match('/^\$\{?([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\}?/', substr($stringString, $varAt), $matches);
$varName = $matches[1];
// check(s)
if ( ! $this->checkLowerCase($phpcsFile, $stackPtr, $varName)) {
return;
}
if ( ! $this->checkLength($phpcsFile, $stackPtr, $varName)) {
return;
}
// prepare checking next variable
$varAt = self::_getVariablePosition($stringString, $varAt + 1);
}
}//end processVariableInString()
/**
* Checks that the variable name is all in lower case, else it add an error
* to $phpcsFile. Returns true if variable name is all in lower case, false
* otherwise.
*
* @param File $phpcsFile The current file being processed.
* @param int $stackPtr The position of the current token
* in the stack passed in $tokens.
* @param string $varName The name of the variable to
* procced without $, { nor }.
*
* @return bool true if variable name is all in lower case, false otherwise.
*/
protected function checkLowerCase(File $phpcsFile, $stackPtr, $varName)
{
$isInLowerCase = true;
if (0 !== strcmp($varName, strtolower($varName))) {
// get the expected variable name
$varNameWithUnderscores = preg_replace('/([A-Z])/', '_${1}', $varName);
$expectedVarName = strtolower(ltrim($varNameWithUnderscores, '_'));
// adapts the error message to the error case
if (strlen($varNameWithUnderscores) > strlen($varName)) {
$error = 'Variables should not use CamelCasing or start with a Capital.';
} else {
$error = 'Variables should be entirely lowercased.';
}
$error = $error . 'Please consider "' . $expectedVarName
. '" instead of "' . $varName . '".';
// adds the error and changes return value
$phpcsFile->addError($error, $stackPtr);
$isInLowerCase = false;
}
return $isInLowerCase;
}//end checkLowerCase()
/**
* Checks that an underscore is used at the beginning of a variable only if
* it is about a private variable. If it isn't a private variable, then it
* must not be prefixed with an underscore. Returns true if $varName is
* properly prefixed according to the variable visibility provided in
* $varProps, false otherwise.
*
* @param File $phpcsFile The current file being processed.
* @param int $stackPtr The position of the current token
* in the stack passed in $tokens.
* @param string $varName The name of the variable to
* procced without $, { nor }.
* @param array $varProps Member variable properties like
* its visibility.
*
* @return bool true if variable name is prefixed with an underscore only
* when it is about a private variable, false otherwise.
*/
protected function checkVisibilityPrefix(File $phpcsFile, $stackPtr, $varName, $varProps)
{
$isVisibilityPrefixRight = true;
$scope = $varProps['scope'];
// If it's a private variable, it must have an underscore on the front.
if ($scope === 'private' && $varName{0} !== '_') {
$error = "Private variable name \"$varName\" must be prefixed with an underscore";
$phpcsFile->addError($error, $stackPtr);
$isVisibilityPrefixRight = false;
} else if ($scope !== 'private' && $varName{0} === '_') {
// If it's not a private variable,
// then it must not start with an underscore.
if (isset ($scopeSpecified) && true === $scopeSpecified) {
$error = "Public variable name \"$varName\" must not be prefixed with an underscore";
} else {
$error = ucfirst($scope) . " variable name \"$varName\" must not be prefixed with an underscore";
}
$phpcsFile->addError($error, $stackPtr);
$isVisibilityPrefixRight = false;
}
return $isVisibilityPrefixRight;
}//end checkVisibilityPrefix()
/**
* Checks that variable name length is not too short. Returns true, if it
* meets minimum length requirement, false otherwise.
*
* A variable name is too short if it is shorter than the minimal
* length and it isn't in the list of allowed short names nor declared in a
* for loop (in which it would be nested).
* The minimal length is defined in the function. It is 3 chars now.
* The list of allowed short names is defined in the function.
* It is case-sensitive. It contains only 'ci' now.
*
* @param File $phpcsFile The current file being processed.
* @param int $stackPtr The position of the current token
* in the stack passed in $tokens.
* @param string $varName The name of the variable to
* procced without $, { nor }.
*
* @return bool false if variable name $varName is shorter than the minimal
* length and it isn't in the list of allowed short names nor declared in a
* for loop (in which it would be nested), otherwise true.
*/
protected function checkLength(File $phpcsFile, $stackPtr, $varName)
{
$minLength = 3;
$allowedShortName = array('ci');
$isLengthRight = true;
// cleans variable name
$varName = ltrim($varName, '_');
if (strlen($varName) <= $minLength) {
// skips adding an error, if it is a specific variable name
if (in_array($varName, $allowedShortName)) {
return $isLengthRight;
}
// skips adding an error, if the variable is in a for loop
if (false !== self::_isInForLoop($phpcsFile, $stackPtr, $varName)) {
return $isLengthRight;
}
// adds the error message finally
$error = 'Very short'
. (
$minLength > 0 ?
' (i.e. less than ' . ($minLength + 1) . ' chars)'
: ''
)
. ', non-word variables like "' . $varName
. '" should only be used as iterators in for() loops.';
$phpcsFile->addError($error, $stackPtr);
$isLengthRight = false;
}
return $isLengthRight;
}//end checkLength()
/**
* Returns the position of closest previous T_FOR, if token associated with
* $stackPtr in $phpcsFile is in a for loop, otherwise false.
*
* @param File $phpcsFile The current file being processed.
* @param int $stackPtr The position of the current token
* in the stack passed in $tokens.
* @param string $varName The name of the variable to
* procced without $, { nor }.
*
* @return int|bool Position of T_FOR if token associated with $stackPtr in
* $phpcsFile is in the head of a for loop, otherwise false.
*/
private static function _isInForLoop(File $phpcsFile, $stackPtr, $varName)
{
$keepLookingFromPtr = $stackPtr;
while (false !== $keepLookingFromPtr) {
// looks if it is in (head or body) of a for loop
$forPtr = self::_isInForLoopHead($phpcsFile, $keepLookingFromPtr);
if (false === $forPtr) {
$forPtr = self::_isInForLoopBody($phpcsFile, $keepLookingFromPtr);
}
// checks if it is declared in here and prepares next step
if (false !== $forPtr) {
if (false !== self::_isDeclaredInForLoop($phpcsFile, $forPtr, $varName)) {
return $forPtr;
}
$keepLookingFromPtr = $forPtr;
} else {
$keepLookingFromPtr = false;
}
}
return false;
}//end _isInForLoop()
/**
* Returns the position of closest previous T_FOR, if token associated with
* $stackPtr in $phpcsFile is in the head of a for loop, otherwise false.
* The head is the code placed between parenthesis next to the key word
* 'for' : for (<loop_head>) {<loop_body>}.
*
* @param File $phpcsFile The current file being processed.
* @param int $stackPtr The position of the current token
* in the stack passed in $tokens.
*
* @return int|bool Position of T_FOR if token associated with $stackPtr in
* $phpcsFile is in the head of a for loop, otherwise false.
*/
private static function _isInForLoopHead(File $phpcsFile, $stackPtr)
{
$isInForLoop = false;
$tokens = $phpcsFile->getTokens();
$currentTk = $tokens[$stackPtr];
if (array_key_exists('nested_parenthesis', $currentTk)) {
$nestedParenthesis = $currentTk['nested_parenthesis'];
foreach ( $nestedParenthesis as $openParPtr => $closeParPtr) {
$nonWhitspacePtr = $phpcsFile->findPrevious(
array(T_WHITESPACE),
$openParPtr - 1,
null,
true,
null,
true
);
if (false !== $nonWhitspacePtr) {
$isFor = T_FOR === $tokens[$nonWhitspacePtr]['code'];
if ($isFor) {
$isInForLoop = $nonWhitspacePtr;
break;
}
}
}
}
return $isInForLoop;
}//end _isInForLoopHead()
/**
* Returns the position of closest previous T_FOR, if token associated with
* $stackPtr in $phpcsFile is in the body of a for loop, otherwise false.
* The body are the instructions placed after parenthesis of a 'for'
* declaration, enclosed with curly brackets usually.
* 'for' : for (<loop_head>) {<loop_body>}.
*
* @param File $phpcsFile The current file being processed.
* @param int $stackPtr The position of the current token
* in the stack passed in $tokens.
*
* @return int|bool Position of T_FOR if token associated with $stackPtr in
* $phpcsFile is in the body of a for loop, otherwise false.
*/
private static function _isInForLoopBody(File $phpcsFile, $stackPtr)
{
$isInForLoop = false;
$tokens = $phpcsFile->getTokens();
// get englobing hierarchy
$parentPtrAndCode = $tokens[$stackPtr]['conditions'];
krsort($parentPtrAndCode);
// looks for a for loop having a body not enclosed with curly brackets,
// which involves that its body contains only one instruction.
if (is_array($parentPtrAndCode) && ! empty($parentPtrAndCode)) {
$parentCode = reset($parentPtrAndCode);
$parentPtr = key($parentPtrAndCode);
$openBracketPtr = $tokens[$parentPtr]['scope_opener'];
} else {
$parentCode = 0;
$parentPtr = 0;
$openBracketPtr = 0;
}
$openResearchScopePtr = $stackPtr;
// recursive search, since a for statement may englobe other inline
// control statement or may be near to function calls, etc...
while (false !== $openResearchScopePtr) {
$closeParPtr = $phpcsFile->findPrevious(
array(T_CLOSE_PARENTHESIS),
$openResearchScopePtr,
null,
false,
null,
true
);
// is there a closing parenthesis with a control statement before
// the previous instruction ?
if (false !== $closeParPtr) {
// is there no opening curly bracket specific to
// set of instructions, between the closing parenthesis
// and the current token ?
if ($openBracketPtr < $closeParPtr) {
// starts the search from the token before the closing
// parenthesis, if it isn't a for statement
$openResearchScopePtr = $closeParPtr - 1;
// is this parenthesis associated with a for statement ?
$closeParenthesisTk = $tokens[$closeParPtr];
if (array_key_exists('parenthesis_owner', $closeParenthesisTk)) {
$mayBeForPtr = $closeParenthesisTk['parenthesis_owner'];
$mayBeForTk = $tokens[$mayBeForPtr];
if (T_FOR === $mayBeForTk['code']) {
return $mayBeForPtr;
}
}
} else {
// if it is about a for loop, don't go further
// and detect it after one more loop execution, do it now
if (T_FOR === $parentCode) {
return $parentPtr;
}
// starts the search from the token before the one
// englobing the current statement
$openResearchScopePtr = $parentPtr - 1;
// re-initialize variables about the englobing structure
if (is_array($parentPtrAndCode)) {
$parentCode = next($parentPtrAndCode);
$parentPtr = key($parentPtrAndCode);
$openBracketPtr = $tokens[$parentPtr]['scope_opener'];
}
}
} else {
$openResearchScopePtr = false;
}
}
// looks for a for loop having a body enclosed with curly brackets
foreach ($parentPtrAndCode as $parentPtr => $parentCode) {
if (T_FOR === $parentCode) {
return $parentPtr;
}
}
return false;
}//end _isInForLoopBody()
/**
* Returns true if a variable declared in the head of the for loop pointed
* by $forPtr in file $phpcsFile has the name $varName.
*
* @param File $phpcsFile The current file being processed.
* @param int $forPtr The position of the 'for' token
* in the stack passed in $tokens.
* @param string $varName The name of the variable to
* procced without $, { nor }.
*
* @return int|bool true if a variable declared in the head of the for loop
* pointed by $forPtr in file $phpcsFile has the name $varName.
*/
private static function _isDeclaredInForLoop(File $phpcsFile, $forPtr, $varName)
{
$isDeclaredInFor = false;
$tokens = $phpcsFile->getTokens();
$forVarPtrs = self::_getVarDeclaredInFor($phpcsFile, $forPtr);
foreach ($forVarPtrs as $forVarPtr) {
$forVarTk = $tokens[$forVarPtr];
// get variable name
$matches = array();
preg_match('/^\$\{?([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\}?/', $forVarTk['content'], $matches);
$forVarName = $matches[1];
if (0 === strcmp($forVarName, $varName)) {
$isDeclaredInFor = $forVarPtr;
break;
}
}
return $isDeclaredInFor;
}//end _isDeclaredInForLoop()
/**
* Returns list of pointers to variables declared in for loop associated to
* $forPtr in file $phpcsFile.
*
* All pointers in the result list are pointing to token with code
* T_VARIABLE. An exception is raised, if $forPtr doesn't point a token with
* code T_FOR.
*
* @param File $phpcsFile The current file being processed.
* @param int $forPtr The position of the current token
* in the stack passed in $tokens.
*
* @return array List of pointers to variables declared in for loop $forPtr.
*/
private static function _getVarDeclaredInFor(File $phpcsFile, $forPtr)
{
$tokens = $phpcsFile->getTokens();
$forTk = $tokens[$forPtr];
if (T_FOR !== $forTk['code']) {
throw new PHP_CodeSniffer_Exception('$forPtr must be of type T_FOR');
}
$openParPtr = $forTk['parenthesis_opener'];
$openParenthesisTk = $tokens[$openParPtr];
$endOfDeclPtr = $phpcsFile->findNext(array(T_SEMICOLON), $openParPtr);
$forVarPtrs = array();
$varPtr = $phpcsFile->findNext(
array(T_VARIABLE),
$openParPtr + 1,
$endOfDeclPtr
);
while (false !== $varPtr) {
$forVarPtrs [] = $varPtr;
$varPtr = $phpcsFile->findNext(
array(T_VARIABLE),
$varPtr + 1,
$endOfDeclPtr
);
}
return $forVarPtrs;
}//end _getVarDeclaredInFor()
/**
* Returns the position of first occurrence of a PHP variable starting with
* $ in $haystack from $offset.
*
* @param string $haystack The string to search in.
* @param int $offset The optional offset parameter allows you to
* specify which character in haystack to start
* searching. The returned position is still
* relative to the beginning of haystack.
*
* @return mixed The position as an integer
* or the boolean false, if no variable is found.
*/
private static function _getVariablePosition($haystack, $offset = 0)
{
$var_starts_at = strpos($haystack, '$', $offset);
$is_a_var = false;
while (false !== $var_starts_at && ! $is_a_var) {
// makes sure that $ is used for a variable and not as a symbol,
// if $ is protected with the escape char, then it is a symbol.
if (0 !== strcmp($haystack[$var_starts_at - 1], '\\')) {
if (0 === strcmp($haystack[$var_starts_at + 1], '{')) {
// there is an opening brace in the right place
// so it looks for the closing brace in the right place
$hsChunk2 = substr($haystack, $var_starts_at + 2);
if (1 === preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*\}/', $hsChunk2)) {
$is_a_var = true;
}
} else {
$hsChunk1 = substr($haystack, $var_starts_at + 1);
if (1 === preg_match('/^[a-zA-Z_\x7f-\xff]/', $hsChunk1)) {
// $ is used for a variable and not as a symbol,
// since what follows $ matchs the definition of
// a variable label for PHP.
$is_a_var = true;
}
}
}
// update $var_starts_at for the next variable
// only if no variable was found, since it is returned otherwise.
if ( ! $is_a_var) {
$var_starts_at = strpos($haystack, '$', $var_starts_at + 1);
}
}
if ($is_a_var) {
return $var_starts_at;
} else {
return false;
}
}//end _getVariablePosition()
}//end class
?>

View File

@ -1,38 +0,0 @@
#!/bin/bash
# We need to install dependencies only for Docker
[[ ! -e /.dockerenv ]] && [[ ! -e /.dockerinit ]] && exit 0
# Where am I?
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
set -xe
# Install git (the php image doesn't have it) which is required by composer
apt-get update -yqq
apt-get install \
git \
unzip \
libfreetype6 \
libjpeg62-turbo \
libmcrypt4 \
libpng12-0 \
libfreetype6-dev \
libjpeg-dev \
libmcrypt-dev \
libpng12-dev \
libxslt1-dev \
libxslt1.1 \
zlib1g-dev \
-yqq
# Install phpunit, the tool that we will use for testing
curl -Lo /usr/local/bin/phpunit https://phar.phpunit.de/phpunit.phar
chmod +x /usr/local/bin/phpunit
# Install gd
docker-php-ext-configure gd --enable-gd-native-ttf --with-jpeg-dir=/usr/lib/x86_64-linux-gnu --with-png-dir=/usr/lib/x86_64-linux-gnu --with-freetype-dir=/usr/lib/x86_64-linux-gnu
docker-php-ext-install gd
docker-php-ext-install mcrypt
docker-php-ext-install xsl
docker-php-ext-install zip

View File

@ -3,13 +3,13 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/

View File

@ -1,129 +1,134 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- This is a skeleton phpDox config file - Check http://phpDox.de for latest version and more info -->
<phpdox xmlns="http://xml.phpdox.net/config" silent="false">
<!-- @silent: true | false to enable or disable visual output of progress -->
<!-- Additional bootstrap files to load for additional parsers, enrichers and/or engines -->
<!-- Place as many require nodes as you feel like in this container -->
<!-- syntax: <require file="/path/to/file.php" /> -->
<bootstrap />
<!-- A phpDox project to process, you can have multiple projects in one config file -->
<project name="Ion Framework" source="../src" workdir="${basedir}/phpdox/xml">
<!-- @name - The name of the project -->
<!-- @source - The source directory of the application to process -->
<!-- @workdir - The directory to store the xml data files in -->
<!-- A phpDox project to process, you can have multiple projects in one config file -->
<project name="Ion Framework" source="../src" workdir="phpdox/xml">
<!-- @name - The name of the project -->
<!-- @source - The source directory of the application to process -->
<!-- @workdir - The directory to store the xml data files in -->
<!-- A phpDox config file can define additional variables (properties) per project -->
<!-- <property name="some.name" value="the.value" /> -->
<!-- A phpDox config file can define additional variables (properties) per project -->
<!-- <property name="some.name" value="the.value" /> -->
<!-- Values can make use of previously defined properties -->
<!-- The following are defined by default:
<!-- Values can make use of previously defined properties -->
<!-- The following are defined by default:
${basedir} Directory the loaded config file is in
${basedir} Directory the loaded config file is in
${phpDox.home} Directory of the phpDox installation
${phpDox.file} The current config file
${phpDox.version} phpDox' version number
${phpDox.home} Directory of the phpDox installation
${phpDox.file} The current config file
${phpDox.version} phpDox' version number
${phpDox.project.name} The value of project/@name if set, otherwise 'unnamed'
${phpDox.project.source} The value of project/@source if set, otherwise '${basedir}/src'
${phpDox.project.workdir} The value of project/@workdir if set, otherwise '${basedir}/build/phpdox/xml'
${phpDox.project.name} The value of project/@name if set, otherwise 'unnamed'
${phpDox.project.source} The value of project/@source if set, otherwise '${basedir}/src'
${phpDox.project.workdir} The value of project/@workdir if set, otherwise '${basedir}/build/phpdox/xml'
${phpDox.php.version} The PHP Version of the interpreter in use
${phpDox.php.version} The PHP Version of the interpreter in use
-->
-->
<!-- Additional configuration for the collecting process (parsing of php code, generation of xml data) -->
<collector publiconly="false" backend="parser" encoding="auto">
<!-- @publiconly - Flag to disable/enable processing of non public methods and members -->
<!-- @backend - The collector backend to use, currently only shipping with 'parser' -->
<!-- @encoding - Charset encoding of source files (overwrite default 'auto' if detection fails) -->
<!-- Additional configuration for the collecting process (parsing of php code, generation of xml data) -->
<collector publiconly="false" backend="parser" encoding="auto">
<!-- @publiconly - Flag to disable/enable processing of non public methods and members -->
<!-- @backend - The collector backend to use, currently only shipping with 'parser' -->
<!-- @encoding - Charset encoding of source files (overwrite default 'auto' if detection fails) -->
<!-- <include / exclude filter for filelist generator, mask must follow fnmatch() requirements -->
<!-- Multiple elements can be added to define more than one mask per filter -->
<include mask="*.php" />
<exclude mask="" />
<!-- <include / exclude filter for filelist generator, mask must follow fnmatch() requirements -->
<include mask="*.php" />
<exclude mask="" />
<!-- How to handle inheritance -->
<inheritance resolve="true">
<!-- @resolve - Flag to enable/disable resolving of inheritance -->
<!-- How to handle inheritance -->
<inheritance resolve="true">
<!-- @resolve - Flag to enable/disable resolving of inheritance -->
<!-- You can define multiple (external) dependencies to be included -->
<!-- <dependency path="" -->
<!-- @path - path to a directory containing an index.xml for a dependency project -->
</inheritance>
</collector>
<!-- Configuration of generation process -->
<generator output="../docs">
<!-- @output - (Base-)Directory to store output data in -->
<!-- A generation process consists of one or more build tasks and of (optional) enrich sources -->
<enrich base="${basedir}/logs">
<!-- @base - (Base-)Directory of datafiles used for enrich process -->
<!--<source type="...">-->
<!-- @type - the handler for the enrichment -->
<!-- known types by default are: build, checkstyle, git, phpcs, phploc, phpunit, pmd -->
<!-- every enrichment source can have additional configuration nodes, most probably need a logfile -->
<!-- <file name="path/to/log.xml" /> -->
<!--</source> -->
<!-- add phploc output -->
<source type="phploc">
<file name="phploc.xml" />
</source>
<!-- git vcs information -->
<source type="git">
<git binary="/usr/bin/git" />
<history enabled="true" limit="15" cache="${phpDox.project.workdir}/gitlog.xml" />
</source>
<!-- PHP Code Sniffer findings -->
<!-- <source type="checkstyle">
<file name="phpcs.xml" />
</source> -->
<!-- PHPMessDetector -->
<!--
<source type="pmd">
<file name="pmd.xml" />
</source>
-->
<!-- PHPUnit Coverage XML -->
<!-- <source type="phpunit"> -->
<!-- <coverage path="" /> -->
<!-- @path - the directory where the xml code coverage report can be found -->
<!--</source>-->
<!--
<source type="phpunit">
<filter directory="${phpDox.project.source}" />
</source>
-->
<!-- PHPUnit Coverage XML -->
<source type="phpunit">
<coverage path="${basedir}/logs/coverage" />
<!-- <coverage path="" /> -->
<!-- @path - the directory where the xml code coverage report can be found -->
<!--<filter directory="${phpDox.project.source}" />-->
<!-- @directory - path of the phpunit config whitelist filter directory -->
<filter directory="${phpDox.project.source}" />
</source>
<!-- You can define multiple (external) dependencies to be included -->
<!-- <dependency path="" -->
<!-- @path - path to a directory containing an index.xml for a dependency project -->
</inheritance>
</collector>
</enrich>
<!-- Configuration of generation process -->
<generator output="../docs">
<!-- @output - (Base-)Directory to store output data in -->
<!-- <build engine="..." enabled="true" output="..." /> -->
<!-- @engine - The name of the engine this build task uses, use ./phpDox - -engines to get a list of available engines -->
<!-- @enabled - Flag to enable/disable this engine, default: enabled=true -->
<!-- @output - (optional) Output directory; if relative (no / as first char) it is interpreted as relative to generator/@output -->
<!-- A generation process consists of one or more build tasks and of (optional) enrich sources -->
<!-- An engine and thus build node can have additional configuration child nodes, please check the documentation for the engine to find out more -->
<enrich base="logs">
<!-- @base - (Base-)Directory of datafiles used for enrich process -->
<!-- default engine "html" -->
<build engine="html" enabled="true">
<template dir="${phpDox.home}/templates/html" />
<file extension="html" />
</build>
<!--<source type="...">-->
<!-- @type - the handler for the enrichment -->
<!-- known types by default are: build, checkstyle, git, phpcs, phploc, phpunit, pmd -->
</generator>
</project>
<!-- every enrichment source can have additional configuration nodes, most probably need a logfile -->
<!-- <file name="path/to/log.xml" /> -->
<!--</source> -->
<!-- add phploc output -->
<source type="phploc">
<file name="phploc.xml" />
</source>
<!-- git vcs information -->
<source type="git">
<git binary="/usr/bin/git" />
<history enabled="true" limit="15" cache="${phpDox.project.workdir}/gitlog.xml" />
</source>
<!-- PHP Code Sniffer findings -->
<source type="checkstyle">
<file name="phpcs.xml" />
</source>
<!-- PHPMessDetector -->
<!--
<source type="pmd">
<file name="pmd.xml" />
</source>
-->
<!-- PHPUnit Coverage XML -->
<source type="phpunit">
<coverage path="coverage/clover.xml" />
<!-- <coverage path="clover.xml" />-->
<!-- @path - the directory where the xml code coverage report can be found -->
<!--<filter directory="${phpDox.project.source}" />-->
<!-- @directory - path of the phpunit config whitelist filter directory -->
</source>
<source type="phpunit">
<filter directory="${phpDox.project.source}" />
</source>
</enrich>
<!-- <build engine="..." enabled="true" output="..." /> -->
<!-- @engine - The name of the engine this build task uses, use ./phpDox - -engines to get a list of available engines -->
<!-- @enabled - Flag to enable/disable this engine, default: enabled=true -->
<!-- @output - (optional) Output directory; if relative (no / as first char) it is interpreted as relative to generator/@output -->
<!-- An engine and thus build node can have additional configuration child nodes, please check the documentation for the engine to find out more -->
<!-- default engine "html" -->
<build engine="html" enabled="true">
<template dir="${phpDox.home}/templates/html" />
<file extension="html" />
</build>
</generator>
</project>
</phpdox>
</phpdox>

View File

@ -4,7 +4,6 @@
stopOnFailure="false"
bootstrap="../tests/bootstrap.php"
beStrictAboutTestsThatDoNotTestAnything="true"
checkForUnintentionallyCoveredCode="true"
>
<filter>
<whitelist>
@ -18,10 +17,10 @@
</testsuites>
<logging>
<log type="coverage-html" target="../coverage"/>
<log type="coverage-clover" target="logs/clover.xml"/>
<log type="coverage-crap4j" target="logs/crap4j.xml"/>
<!-- <log type="coverage-clover" target="logs/clover.xml"/>
<log type="coverage-crap4j" target="logs/crap4j.xml"/> -->
<log type="coverage-xml" target="logs/coverage" />
<log type="junit" target="logs/junit.xml" logIncompleteSkipped="false"/>
<log type="junit" target="logs/junit.xml" />
</logging>
<php>
<server name="HTTP_USER_AGENT" value="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14393" />

View File

@ -3,7 +3,9 @@ declare(strict_types=1);
$file_patterns = [
'src/*.php',
'tests/**/*.php',
'src/**/*.php',
'tests/*.php',
'tests/**/*.php'
];
if ( ! function_exists('glob_recursive'))

View File

@ -1,50 +1,55 @@
{
"name": "aviat/ion",
"description": "Basic PHP Framework",
"license":"MIT",
"autoload": {
"psr-4": {
"Aviat\\Ion\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Aviat\\Ion\\Tests\\": "tests/",
"CodeIgniter\\": "build/CodeIgniter/"
}
},
"require": {
"aviat/query": "^2.5",
"aura/html": "2.*",
"container-interop/container-interop": "1.*",
"danielstjules/stringy": "~2.1",
"guzzlehttp/guzzle": "6.*",
"psr/http-message": "~1.0",
"psr/log": "~1.0",
"zendframework/zend-diactoros": "1.3.*"
},
"require-dev": {
"pdepend/pdepend": "^2.2",
"sebastian/phpcpd": "^2.0",
"theseer/phpdox": "~0.9.0",
"phploc/phploc": "^3.0",
"phpmd/phpmd": "^2.4",
"phpunit/phpunit": "^5.4",
"robmorgan/phinx": "^0.6.4",
"humbug/humbug": "~1.0@dev",
"consolidation/robo": "~1.0@RC",
"henrikbjorn/lurker": "^1.1.0",
"nikic/php-parser": "3.0.*@beta",
"monolog/monolog": "1.*",
"squizlabs/php_codesniffer": "^3.0.0@RC"
},
"scripts": {
"coverage": "vendor/bin/phpunit -c build",
"build": "vendor/bin/robo build",
"docs": "cd build && ../vendor/bin/phpdox && cd ..",
"test": "vendor/bin/phpunit"
},
"suggest": {
"monolog/monolog": "Provides implementation of psr/log"
"name": "aviat/ion",
"description": "Basic PHP Framework",
"license": "MIT",
"autoload": {
"files": [
"src/functions.php"
],
"psr-4": {
"Aviat\\Ion\\": "src/"
}
}
},
"autoload-dev": {
"psr-4": {
"Aviat\\Ion\\Tests\\": "tests/",
"CodeIgniter\\": "build/CodeIgniter/"
}
},
"require": {
"aura/html": "^2.5.0",
"aviat/query": "^2.5.1",
"danielstjules/stringy": "^3.1.0",
"ext-dom": "*",
"ext-json": "*",
"php": "^7.2",
"psr/http-message": "~1.0",
"psr/log": "~1.0",
"zendframework/zend-diactoros": "^2.0.0",
"zendframework/zend-httphandlerrunner": "^1.0"
},
"require-dev": {
"aura/session": "^2.1.0",
"consolidation/robo": "^2.0.0",
"monolog/monolog": "^2.0.1",
"pdepend/pdepend": "^2.2",
"phploc/phploc": "^5.0",
"phpmd/phpmd": "^2.4",
"phpstan/phpstan": "^0.12.0",
"phpunit/phpunit": "^8.4.3",
"roave/security-advisories": "dev-master",
"sebastian/phpcpd": "^4.1.0",
"squizlabs/php_codesniffer": "^3.0.0",
"theseer/phpdox": "^0.12.0"
},
"scripts": {
"coverage": "phpdbg -qrr -- vendor/bin/phpunit -c build",
"build": "robo build",
"docs": "cd build && ../vendor/bin/phpdox && cd ..",
"phpstan": "phpstan analyse -l 7 -c phpstan.neon src tests",
"test": "phpunit -c phpunit.dist.xml"
},
"suggest": {
"monolog/monolog": "Provides implementation of psr/log"
}
}

12
phpstan.neon Normal file
View File

@ -0,0 +1,12 @@
parameters:
autoload_files:
- %rootDir%/../../../tests/mocks.php
- %rootDir%/../../../tests/Di/ContainerTest.php
- %rootDir%/../../../tests/Di/ContainerAwareTest.php
ignoreErrors:
- '#Access to an undefined property Aviat\\Ion\\Tests\\[a-zA-Z0-9_]+Test::\$[a-zA-Z0-9_]+#'
- '#Call to an undefined method Aviat\\Ion\\Type\\ArrayType::[a-zA-Z0-9_]+\(\)#'
- '#Call to an undefined method Aura\\Html\\HelperLocator::[a-zA-Z0-9_]+\(\)#'
- '#Undefined variable: \$var#'
excludes_analyse:
- %rootDir%/tests/Di/*

19
phpunit.dist.xml Normal file
View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/6.3/phpunit.xsd"
colors="true"
stopOnFailure="false"
bootstrap="tests/bootstrap.php"
beStrictAboutTestsThatDoNotTestAnything="true">
<filter>
<whitelist>
<directory suffix=".php">src</directory>
</whitelist>
</filter>
<testsuites>
<testsuite name="Ion">
<directory>tests</directory>
</testsuite>
</testsuites>
</phpunit>

View File

@ -1,25 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
colors="true"
stopOnFailure="false"
bootstrap="tests/bootstrap.php"
beStrictAboutTestsThatDoNotTestAnything="true"
>
<filter>
<whitelist>
<directory suffix=".php">src</directory>
</whitelist>
</filter>
<testsuites>
<testsuite name="Ion">
<directory>tests</directory>
</testsuite>
</testsuites>
<php>
<server name="HTTP_USER_AGENT" value="Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:38.0) Gecko/20100101 Firefox/38.0" />
<server name="HTTP_HOST" value="localhost" />
<server name="SERVER_NAME" value="localhost" />
<server name="REQUEST_URI" value="/" />
<server name="REQUEST_METHOD" value="GET" />
</php>
</phpunit>

View File

@ -4,14 +4,14 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion;

View File

@ -4,14 +4,14 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion;
@ -32,7 +32,7 @@ class Config implements ConfigInterface {
*
* @var ArrayType
*/
protected $map = [];
protected $map;
/**
* Constructor
@ -44,16 +44,27 @@ class Config implements ConfigInterface {
$this->map = $this->arr($configArray);
}
/**
* Does the config item exist?
*
* @param string|int|array $key
* @return bool
*/
public function has($key): bool
{
return $this->map->hasKey($key);
}
/**
* Get a config value
*
* @param array|string $key
* @param array|string|null $key
* @return mixed
* @throws ConfigException
*/
public function get($key)
public function get($key = NULL)
{
if (is_array($key))
if (\is_array($key))
{
return $this->map->getDeepKey($key);
}
@ -67,9 +78,9 @@ class Config implements ConfigInterface {
* @param string|array $key
* @return void
*/
public function delete($key)
public function delete($key): void
{
if (is_array($key))
if (\is_array($key))
{
$this->map->setDeepKey($key, NULL);
}
@ -90,7 +101,7 @@ class Config implements ConfigInterface {
*/
public function set($key, $value): ConfigInterface
{
if (is_array($key))
if (\is_array($key))
{
$this->map->setDeepKey($key, $value);
}
@ -100,7 +111,7 @@ class Config implements ConfigInterface {
}
else
{
throw new InvalidArgumentException("Key must be integer, string, or array, and cannot be empty");
throw new InvalidArgumentException('Key must be integer, string, or array, and cannot be empty');
}
return $this;

View File

@ -4,14 +4,14 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion;
@ -20,13 +20,21 @@ namespace Aviat\Ion;
* Standard interface for retrieving/setting configuration values
*/
interface ConfigInterface {
/**
* Does the config item exist?
*
* @param string|int|array $key
* @return bool
*/
public function has($key): bool;
/**
* Get a config value
*
* @param array|string $key
* @param array|string|null $key
* @return mixed
*/
public function get($key);
public function get($key = NULL);
/**
* Set a config value
@ -36,7 +44,7 @@ interface ConfigInterface {
* @throws \InvalidArgumentException
* @return ConfigInterface
*/
public function set($key, $value): ConfigInterface;
public function set($key, $value): self;
/**
* Remove a config value
@ -44,5 +52,5 @@ interface ConfigInterface {
* @param string|array $key
* @return void
*/
public function delete($key);
public function delete($key): void;
}

View File

@ -4,14 +4,14 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\Di;
@ -68,9 +68,9 @@ class Container implements ContainerInterface {
*/
public function get($id)
{
if ( ! is_string($id))
if ( ! \is_string($id))
{
throw new ContainerException("Id must be a string");
throw new ContainerException('Id must be a string');
}
if ($this->has($id))
@ -101,7 +101,7 @@ class Container implements ContainerInterface {
*/
public function getNew($id, array $args = NULL)
{
if ( ! is_string($id))
if ( ! \is_string($id))
{
throw new ContainerException('Id must be a string');
}
@ -109,8 +109,8 @@ class Container implements ContainerInterface {
if ($this->has($id))
{
// By default, call a factory with the Container
$args = is_array($args) ? $args : [$this];
$obj = call_user_func_array($this->container[$id], $args);
$args = \is_array($args) ? $args : [$this];
$obj = \call_user_func_array($this->container[$id], $args);
// Check for container interface, and apply the container to the object
// if applicable
@ -194,7 +194,7 @@ class Container implements ContainerInterface {
* @param string $id The logger to retrieve
* @return LoggerInterface|null
*/
public function getLogger(string $id = 'default')
public function getLogger(string $id = 'default'): ?LoggerInterface
{
return $this->hasLogger($id)
? $this->loggers[$id]
@ -211,13 +211,13 @@ class Container implements ContainerInterface {
*/
private function applyContainer($obj)
{
$trait_name = __NAMESPACE__ . '\\ContainerAware';
$interface_name = __NAMESPACE__ . '\\ContainerAwareInterface';
$trait_name = ContainerAware::class;
$interface_name = ContainerAwareInterface::class;
$uses_trait = in_array($trait_name, class_uses($obj), TRUE);
$implements_interface = in_array($interface_name, class_implements($obj), TRUE);
$uses_trait = \in_array($trait_name, class_uses($obj), TRUE);
$implements_interface = \in_array($interface_name, class_implements($obj), TRUE);
if ($uses_trait OR $implements_interface)
if ($uses_trait || $implements_interface)
{
$obj->setContainer($this);
}

View File

@ -4,14 +4,14 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\Di;
@ -32,9 +32,9 @@ trait ContainerAware {
* Set the container for the current object
*
* @param ContainerInterface $container
* @return $this
* @return self
*/
public function setContainer(ContainerInterface $container)
public function setContainer(ContainerInterface $container): self
{
$this->container = $container;
return $this;

View File

@ -4,14 +4,14 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\Di;

View File

@ -4,14 +4,14 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\Di;
@ -32,8 +32,8 @@ interface ContainerInterface {
* Finds an entry of the container by its identifier and returns it.
*
* @param string $id Identifier of the entry to look for.
* @throws NotFoundException No entry was found for this identifier.
* @throws ContainerException Error while retrieving the entry.
* @throws Exception\NotFoundException No entry was found for this identifier.
* @throws Exception\ContainerException Error while retrieving the entry.
* @return mixed Entry.
*/
public function get($id);
@ -75,6 +75,7 @@ interface ContainerInterface {
/**
* Determine whether a logger channel is registered
*
* @param string $id The logger channel
* @return boolean
*/
@ -95,5 +96,5 @@ interface ContainerInterface {
* @param string $id The logger to retrieve
* @return LoggerInterface|null
*/
public function getLogger(string $id = 'default');
public function getLogger(string $id = 'default'): ?LoggerInterface;
}

View File

@ -4,14 +4,14 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\Di\Exception;

View File

@ -4,14 +4,14 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\Di\Exception;

View File

@ -4,14 +4,14 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion;
@ -20,34 +20,40 @@ use ReflectionClass;
/**
* Class emulating an enumeration type
*
* @method bool isValid(mixed $key)
* @method array getConstList()
*/
abstract class Enum {
use StaticInstance;
/**
* Return the list of constant values for the Enum
*
* @return array
* @throws \ReflectionException
*/
protected function getConstList(): array
public static function getConstList(): array
{
$reflect = new ReflectionClass($this);
static $self;
if ($self === NULL)
{
$class = static::class;
$self = new $class;
}
$reflect = new ReflectionClass($self);
return $reflect->getConstants();
}
/**
* Verify that a constant value is valid
*
* @param mixed $key
* @return boolean
* @throws \ReflectionException
*/
protected function isValid($key): bool
public static function isValid($key): bool
{
$values = array_values($this->getConstList());
return in_array($key, $values);
$values = array_values(static::getConstList());
return \in_array($key, $values, TRUE);
}
}
// End of Enum.php

View File

@ -4,14 +4,14 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\Exception;

View File

@ -4,14 +4,14 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\Exception;
@ -29,7 +29,7 @@ class DoubleRenderException extends LogicException {
*
* @param string $message
* @param int $code
* @param null $previous
* @param Exception|null $previous
*/
public function __construct(string $message = 'A view can only be rendered once, because headers can only be sent once.', int $code = 0, Exception $previous = NULL)
{

View File

@ -4,14 +4,14 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion;
@ -29,27 +29,28 @@ class Friend {
/**
* Object to create a friend of
* @var object
* @var mixed
*/
private $_friend_;
/**
* Reflection class of the object
* @var object
* @var ReflectionClass
*/
private $_reflect_;
/**
* Create a friend object
*
* @param object $obj
* @param mixed $obj
* @throws InvalidArgumentException
* @throws \ReflectionException
*/
public function __construct($obj)
{
if ( ! is_object($obj))
if ( ! \is_object($obj))
{
throw new InvalidArgumentException("Friend must be an object");
throw new InvalidArgumentException('Friend must be an object');
}
$this->_friend_ = $obj;
@ -64,15 +65,30 @@ class Friend {
*/
public function __get(string $key)
{
if ($this->_reflect_->hasProperty($key))
if ($this->__isset($key))
{
$property = $this->_get_property($key);
return $property->getValue($this->_friend_);
if ($property !== NULL)
{
return $property->getValue($this->_friend_);
}
}
return NULL;
}
/**
* See if a property exists on the friend
*
* @param string $name
* @return bool
*/
public function __isset(string $name): bool
{
return $this->_reflect_->hasProperty($name);
}
/**
* Set a friend's property
*
@ -82,10 +98,14 @@ class Friend {
*/
public function __set(string $key, $value)
{
if ($this->_reflect_->hasProperty($key))
if ($this->__isset($key))
{
$property = $this->_get_property($key);
$property->setValue($this->_friend_, $value);
if ($property !== NULL)
{
$property->setValue($this->_friend_, $value);
}
}
}
@ -96,6 +116,7 @@ class Friend {
* @param array $args
* @return mixed
* @throws BadMethodCallException
* @throws \ReflectionException
*/
public function __call(string $method, array $args)
{
@ -112,11 +133,10 @@ class Friend {
/**
* Iterates over parent classes to get a ReflectionProperty
*
* @codeCoverageIgnore
* @param string $name
* @return ReflectionProperty|null
*/
private function _get_property(string $name)
private function _get_property(string $name): ?ReflectionProperty
{
try
{

View File

@ -4,14 +4,14 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion;
@ -29,6 +29,7 @@ class Json {
* @param mixed $data
* @param int $options
* @param int $depth
* @throws JsonException
* @return string
*/
public static function encode($data, $options = 0, $depth = 512): string
@ -45,6 +46,7 @@ class Json {
* @param mixed $data
* @param int $jsonOptions - Options to pass to json_encode
* @param int $fileOptions - Options to pass to file_get_contents
* @throws JsonException
* @return int
*/
public static function encodeFile(string $filename, $data, int $jsonOptions = 0, int $fileOptions = 0): int
@ -60,18 +62,18 @@ class Json {
* @param bool $assoc
* @param int $depth
* @param int $options
* @throws JsonException
* @return mixed
*/
public static function decode($json, bool $assoc = TRUE, int $depth = 512, int $options = 0)
{
// Don't try to decode null
if (empty($json))
if ($json === NULL)
{
return NULL;
}
// cast json to string so that streams from guzzle are correctly decoded
$data = json_decode((string) $json, $assoc, $depth, $options);
$data = json_decode($json, $assoc, $depth, $options);
self::check_json_error();
return $data;
@ -84,6 +86,7 @@ class Json {
* @param bool $assoc
* @param int $depth
* @param int $options
* @throws JsonException
* @return mixed
*/
public static function decodeFile(string $filename, bool $assoc = TRUE, int $depth = 512, int $options = 0)
@ -96,6 +99,7 @@ class Json {
* Determines whether a string is valid json
*
* @param string $string
* @throws \InvalidArgumentException
* @return boolean
*/
public static function isJson(string $string): bool
@ -109,7 +113,7 @@ class Json {
* @throws JsonException
* @return void
*/
protected static function check_json_error()
protected static function check_json_error(): void
{
$constant_map = [
JSON_ERROR_NONE => 'JSON_ERROR_NONE',
@ -126,7 +130,7 @@ class Json {
$error = json_last_error();
$message = json_last_error_msg();
if (\JSON_ERROR_NONE !== $error)
if (JSON_ERROR_NONE !== $error)
{
throw new JsonException("{$constant_map[$error]} - {$message}", $error);
}

View File

@ -4,14 +4,14 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion;

View File

@ -4,14 +4,14 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion;

View File

@ -4,14 +4,14 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\Model;

View File

@ -1,67 +0,0 @@
<?php declare(strict_types=1);
/**
* Ion
*
* Building blocks for web development
*
* PHP version 7
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
*/
namespace Aviat\Ion;
/**
* Trait to allow calling a method statically,
* as well as with an instance
*/
trait StaticInstance {
/**
* Instance for 'faking' static methods
*
* @var object
*/
private static $instance = [];
/**
* Call protected methods to allow for
* static and instance calling
*
* @codeCoverageIgnore
* @param string $method
* @param array $args
* @return mixed
*/
public function __call(string $method, array $args)
{
if (method_exists($this, $method))
{
return call_user_func_array([$this, $method], $args);
}
}
/**
* Call non-static methods statically, so that
* an instance of the class isn't required
*
* @param string $method
* @param array $args
* @return mixed
*/
public static function __callStatic(string $method, array $args)
{
$class = get_called_class();
if ( ! array_key_exists($class, self::$instance))
{
self::$instance[$class] = new $class();
}
return call_user_func_array([self::$instance[$class], $method], $args);
}
}
// End of StaticInstance.php

View File

@ -4,14 +4,14 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion;
@ -27,6 +27,7 @@ trait StringWrapper {
* Wrap the String in the Stringy class
*
* @param string $str
* @throws \InvalidArgumentException
* @return StringType
*/
public function string($str): StringType

View File

@ -4,22 +4,24 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\Transformer;
use Aviat\Ion\StringWrapper;
use BadMethodCallException;
/**
* Base class for data trasformation
* Base class for data transformation
*/
abstract class AbstractTransformer implements TransformerInterface {
@ -36,13 +38,32 @@ abstract class AbstractTransformer implements TransformerInterface {
/**
* Transform a set of structures
*
* @param array|object $collection
* @param iterable $collection
* @return array
*/
public function transformCollection($collection): array
public function transformCollection(iterable $collection): array
{
$list = (array)$collection;
return array_map([$this, 'transform'], $list);
}
/**
* Untransform a set of structures
*
* Requires an 'untransform' method in the extending class
*
* @param iterable $collection
* @return array
*/
public function untransformCollection(iterable $collection): array
{
if ( ! method_exists($this, 'untransform'))
{
throw new BadMethodCallException('untransform() method does not exist.');
}
$list = (array)$collection;
return array_map([$this, 'untransform'], $list);
}
}
// End of AbstractTransformer.php

View File

@ -4,14 +4,14 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\Transformer;

View File

@ -4,14 +4,14 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\Type;
@ -41,15 +41,15 @@ class ArrayType {
*/
protected $nativeMethods = [
'chunk' => 'array_chunk',
'pluck' => 'array_column',
'key_diff' => 'array_diff_key',
'diff' => 'array_diff',
'filter' => 'array_filter',
'flip' => 'array_flip',
'intersect' => 'array_intersect',
'key_diff' => 'array_diff_key',
'keys' => 'array_keys',
'merge' => 'array_merge',
'pad' => 'array_pad',
'pluck' => 'array_column',
'product' => 'array_product',
'random' => 'array_rand',
'reduce' => 'array_reduce',
@ -97,7 +97,7 @@ class ArrayType {
{
$func = $this->nativeMethods[$method];
// Set the current array as the first argument of the method
return call_user_func($func, $this->arr, ...$args);
return $func($this->arr, ...$args);
}
// Mapping for in-place methods
@ -114,11 +114,28 @@ class ArrayType {
/**
* Does the passed key exist in the current array?
*
* @param int|string $key
* @param int|string|array $key
* @return bool
*/
public function hasKey($key): bool
{
if (\is_array($key))
{
$pos =& $this->arr;
foreach($key as $level)
{
if ( ! array_key_exists($level, $pos))
{
return FALSE;
}
$pos =& $pos[$level];
}
return TRUE;
}
return array_key_exists($key, $this->arr);
}
@ -167,7 +184,7 @@ class ArrayType {
*/
public function has($value, bool $strict = TRUE): bool
{
return in_array($value, $this->arr, $strict);
return \in_array($value, $this->arr, $strict);
}
/**
@ -179,7 +196,7 @@ class ArrayType {
public function &get($key = NULL)
{
$value = NULL;
if (is_null($key))
if ($key === NULL)
{
$value =& $this->arr;
}
@ -222,7 +239,7 @@ class ArrayType {
foreach ($key as $level)
{
if (empty($pos) OR ! is_array($pos))
if (empty($pos) || ! is_array($pos))
{
// Directly returning a NULL value here will
// result in a reference error. This isn't
@ -253,7 +270,7 @@ class ArrayType {
// create the levels if they don't exist
foreach ($key as $level)
{
if ( ! is_array($pos) && empty($pos))
if ( ! \is_array($pos) && empty($pos))
{
$pos = [];
$pos[$level] = [];

View File

@ -4,14 +4,14 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\Type;
@ -23,5 +23,20 @@ use Stringy\Stringy;
*/
class StringType extends Stringy {
/**
* See if two strings match, despite being delimited differently,
* such as camelCase, PascalCase, kebab-case, or snake_case.
*
* @param string $strToMatch
* @throws \InvalidArgumentException
* @return boolean
*/
public function fuzzyCaseMatch(string $strToMatch): bool
{
$firstStr = (string)self::create($this->str)->dasherize();
$secondStr = (string)self::create($strToMatch)->dasherize();
return $firstStr === $secondStr;
}
}
// End of StringType.php

View File

@ -4,14 +4,14 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion;
@ -50,6 +50,8 @@ abstract class View
* Constructor
*
* @param ContainerInterface $container
* @throws Di\Exception\ContainerException
* @throws Di\Exception\NotFoundException
*/
public function __construct(ContainerInterface $container)
{
@ -85,10 +87,26 @@ abstract class View
return $this->getOutput();
}
/**
* Add an http header
*
* @param string $name
* @param string|string[] $value
* @throws \InvalidArgumentException
* @return ViewInterface
*/
public function addHeader(string $name, $value): ViewInterface
{
$this->response = $this->response->withHeader($name, $value);
return $this;
}
/**
* Set the output string
*
* @param mixed $string
* @throws \InvalidArgumentException
* @throws \RuntimeException
* @return ViewInterface
*/
public function setOutput($string): ViewInterface
@ -102,6 +120,8 @@ abstract class View
* Append additional output.
*
* @param string $string
* @throws \InvalidArgumentException
* @throws \RuntimeException
* @return ViewInterface
*/
public function appendOutput(string $string): ViewInterface
@ -117,7 +137,7 @@ abstract class View
*/
public function getOutput(): string
{
return $this->response->getBody()->__toString();
return (string)$this->response->getBody();
}
}
// End of View.php

View File

@ -4,19 +4,22 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\View;
use Aura\Html\HelperLocator;
use Aviat\Ion\Di\ContainerInterface;
use Aviat\Ion\Di\Exception\ContainerException;
use Aviat\Ion\Di\Exception\NotFoundException;
/**
* View class for outputting HTML
@ -26,7 +29,7 @@ class HtmlView extends HttpView {
/**
* HTML generator/escaper helper
*
* @var Aura\Html\HelperLocator
* @var HelperLocator
*/
protected $helper;
@ -41,6 +44,8 @@ class HtmlView extends HttpView {
* Create the Html View
*
* @param ContainerInterface $container
* @throws ContainerException
* @throws NotFoundException
*/
public function __construct(ContainerInterface $container)
{
@ -62,10 +67,13 @@ class HtmlView extends HttpView {
$data['container'] = $this->container;
ob_start();
extract($data);
extract($data, \EXTR_OVERWRITE);
include_once $path;
$buffer = ob_get_contents();
ob_end_clean();
$buffer = ob_get_clean();
// Very basic html minify, that won't affect content between html tags
$buffer = preg_replace('/>\s+</', '> <', $buffer);
return $buffer;
}

View File

@ -4,19 +4,20 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\View;
use Zend\Diactoros\Response\SapiEmitter;
use Zend\Diactoros\Response;
use Zend\HttpHandlerRunner\Emitter\SapiEmitter;
use Aviat\Ion\Exception\DoubleRenderException;
use Aviat\Ion\View as BaseView;
@ -36,32 +37,22 @@ class HttpView extends BaseView {
/**
* Do a redirect
*
* @codeCoverageIgnore
* @param string $url
* @param int $code
* @param array $headers
* @throws \InvalidArgumentException
* @return void
*/
public function redirect(string $url, int $code)
public function redirect(string $url, int $code = 302, array $headers = []): void
{
ob_start();
$message = $this->response->getReasonPhrase($code);
$this->setStatusCode($code);
$this->response->withHeader('Location', $url);
if (PHP_SAPI !== 'cli')
{
header("HTTP/1.1 ${code} ${message}");
header("Location: {$url}");
}
$this->hasRendered = TRUE;
ob_end_clean();
$this->response = new Response\RedirectResponse($url, $code, $headers);
}
/**
* Set the status code of the request
*
* @param int $code
* @throws \InvalidArgumentException
* @return HttpView
*/
public function setStatusCode(int $code): HttpView
@ -76,9 +67,10 @@ class HttpView extends BaseView {
* any attempt to call again will result in a DoubleRenderException.
*
* @throws DoubleRenderException
* @throws \InvalidArgumentException
* @return void
*/
public function send()
public function send(): void
{
$this->output();
}
@ -86,25 +78,24 @@ class HttpView extends BaseView {
/**
* Send the appropriate response
*
* @codeCoverageIgnore
* @throws DoubleRenderException
* @throws \InvalidArgumentException
* @return void
*/
protected function output()
protected function output(): void
{
if ($this->hasRendered)
{
throw new DoubleRenderException();
}
$this->response = $this->response->withHeader('Content-type', "{$this->contentType};charset=utf-8")
->withHeader('Content-Security-Policy', "script-src 'self'")
$this->response = $this->response
->withHeader('Content-type', "{$this->contentType};charset=utf-8")
->withHeader('X-Content-Type-Options', 'nosniff')
->withHeader('X-XSS-Protection', '1;mode=block')
->withHeader('X-Frame-Options', 'SAMEORIGIN');
$sender = new SapiEmitter($this->response);
$sender->emit($this->response);
(new SapiEmitter())->emit($this->response);
$this->hasRendered = TRUE;
}

View File

@ -4,19 +4,20 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\View;
use Aviat\Ion\Json;
use Aviat\Ion\JsonException;
use Aviat\Ion\ViewInterface;
/**
@ -35,11 +36,14 @@ class JsonView extends HttpView {
* Set the output string
*
* @param mixed $string
* @throws \InvalidArgumentException
* @throws \RuntimeException
* @throws JsonException
* @return ViewInterface
*/
public function setOutput($string): ViewInterface
{
if ( ! is_string($string))
if ( ! \is_string($string))
{
$string = Json::encode($string);
}

View File

@ -4,14 +4,14 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion;
@ -37,7 +37,7 @@ interface ViewInterface {
* @param mixed $string
* @return ViewInterface
*/
public function setOutput($string): ViewInterface;
public function setOutput($string): self;
/**
* Append additional output.
@ -45,7 +45,16 @@ interface ViewInterface {
* @param string $string
* @return ViewInterface
*/
public function appendOutput(string $string): ViewInterface;
public function appendOutput(string $string): self;
/**
* Add an http header
*
* @param string $name
* @param string|string[] $value
* @return ViewInterface
*/
public function addHeader(string $name, $value): self;
/**
* Get the current output as a string. Does not
@ -62,5 +71,5 @@ interface ViewInterface {
* @throws DoubleRenderException
* @return void
*/
public function send();
public function send(): void;
}

279
src/XML.php Normal file
View File

@ -0,0 +1,279 @@
<?php declare(strict_types=1);
/**
* Ion
*
* Building blocks for web development
*
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion;
use DOMDocument, DOMNode, DOMNodeList, InvalidArgumentException;
/**
* XML <=> PHP Array codec
*/
final class XML {
/**
* XML representation of the data
*
* @var string
*/
private $xml;
/**
* PHP array version of the data
*
* @var array
*/
private $data;
/**
* XML constructor
*
* @param string $xml
* @param array $data
*/
public function __construct(string $xml = '', array $data = [])
{
$this->setXML($xml)->setData($data);
}
/**
* Serialize the data to an xml string
*
* @return string
*/
public function __toString(): string
{
return static::toXML($this->getData());
}
/**
* Get the data parsed from the XML
*
* @return array
*/
public function getData(): array
{
return $this->data;
}
/**
* Set the data to create xml from
*
* @param array $data
* @return self
*/
public function setData(array $data): self
{
$this->data = $data;
return $this;
}
/**
* Get the xml created from the data
*
* @return string
*/
public function getXML(): string
{
return $this->xml;
}
/**
* Set the xml to parse the data from
*
* @param string $xml
* @return self
*/
public function setXML(string $xml): self
{
$this->xml = $xml;
return $this;
}
/**
* Parse an xml document string to a php array
*
* @param string $xml
* @return array
*/
public static function toArray(string $xml): array
{
$data = [];
$xml = static::stripXMLWhitespace($xml);
$dom = new DOMDocument();
$hasLoaded = @$dom->loadXML($xml);
if ( ! $hasLoaded)
{
throw new InvalidArgumentException('Failed to load XML');
}
$root = $dom->documentElement;
$data[$root->tagName] = [];
if ($root->hasChildNodes())
{
static::childNodesToArray($data[$root->tagName], $root->childNodes);
}
return $data;
}
/**
* Transform the array into XML
*
* @param array $data
* @return string
*/
public static function toXML(array $data): string
{
$dom = new DOMDocument();
$dom->encoding = 'UTF-8';
static::arrayPropertiesToXmlNodes($dom, $dom, $data);
return $dom->saveXML();
}
/**
* Parse the xml document string to a php array
*
* @return array
*/
public function parse(): array
{
$xml = $this->getXML();
$data = static::toArray($xml);
return $this->setData($data)->getData();
}
/**
* Transform the array into XML
*
* @return string
*/
public function createXML(): string
{
return static::toXML($this->getData());
}
/**
* Strip whitespace from raw xml to remove irrelevant text nodes
*
* @param string $xml
* @return string
*/
private static function stripXMLWhitespace(string $xml): string
{
// Get rid of unimportant text nodes by removing
// whitespace characters from between xml tags,
// except for the xml declaration tag, Which looks
// something like:
/* <?xml version="1.0" encoding="UTF-8"?> */
return preg_replace('/([^?])>\s+</', '$1><', $xml);
}
/**
* Recursively create array structure based on xml structure
*
* @param array $root A reference to the current array location
* @param DOMNodeList $nodeList The current NodeList object
* @return void
*/
private static function childNodesToArray(array &$root, DOMNodelist $nodeList): void
{
$length = $nodeList->length;
for ($i = 0; $i < $length; $i++)
{
$el = $nodeList->item($i);
$current =& $root[$el->nodeName];
// It's a top level element!
if (( ! $el->hasChildNodes()) || ($el->childNodes->item(0) instanceof \DomText))
{
$current = $el->textContent;
continue;
}
// An empty value at the current root
if ($current === NULL)
{
$current = [];
static::childNodesToArray($current, $el->childNodes);
continue;
}
$keys = array_keys($current);
// Wrap the array in a containing array
// if there are only string keys
if ( ! is_numeric($keys[0]))
{
// But if there is only one key, don't wrap it in
// an array, just recurse to parse the child nodes
if (count($current) === 1)
{
static::childNodesToArray($current, $el->childNodes);
continue;
}
$current = [$current];
}
$current[] = [];
$index = count($current) - 1;
static::childNodesToArray($current[$index], $el->childNodes);
}
}
/**
* Recursively create xml nodes from array properties
*
* @param DOMDocument $dom The current DOM object
* @param DOMNode $parent The parent element to append children to
* @param array $data The data for the current node
* @return void
*/
private static function arrayPropertiesToXmlNodes(DOMDocument $dom, DOMNode $parent, array $data): void
{
foreach ($data as $key => $props)
{
// 'Flatten' the array as you create the xml
if (is_numeric($key))
{
foreach ($props as $k => $p)
{
break;
}
}
$node = $dom->createElement($key);
if (\is_array($props))
{
static::arrayPropertiesToXmlNodes($dom, $node, $props);
} else
{
$tNode = $dom->createTextNode((string)$props);
$node->appendChild($tNode);
}
$parent->appendChild($node);
}
}
}

29
src/functions.php Normal file
View File

@ -0,0 +1,29 @@
<?php declare(strict_types=1);
/**
* Ion
*
* Building blocks for web development
*
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion;
/**
* Joins paths together. Variadic to take an
* arbitrary number of arguments
*
* @param string ...$args
* @return string
*/
function _dir(string ...$args): string
{
return implode(DIRECTORY_SEPARATOR, $args);
}

View File

@ -1,4 +1,18 @@
<?php
<?php declare(strict_types=1);
/**
* Ion
*
* Building blocks for web development
*
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\Tests;

View File

@ -1,4 +1,18 @@
<?php
<?php declare(strict_types=1);
/**
* Ion
*
* Building blocks for web development
*
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\Tests;
@ -6,16 +20,32 @@ use Aviat\Ion\Config;
class ConfigTest extends Ion_TestCase {
public function setUp()
protected $config;
public function setUp(): void
{
$this->config = new Config([
'foo' => 'bar',
'asset_path' => '/assets',
'bar' => 'baz'
'bar' => 'baz',
'a' => [
'b' => [
'c' => TRUE,
],
],
]);
}
public function testConfigGet()
public function testConfigHas(): void
{
$this->assertTrue($this->config->has('foo'));
$this->assertTrue($this->config->has(['a', 'b', 'c']));
$this->assertFalse($this->config->has('baz'));
$this->assertFalse($this->config->has(['c', 'b', 'a']));
}
public function testConfigGet(): void
{
$this->assertEquals('bar', $this->config->get('foo'));
$this->assertEquals('baz', $this->config->get('bar'));
@ -23,27 +53,26 @@ class ConfigTest extends Ion_TestCase {
$this->assertNull($this->config->get(['apple', 'sauce', 'is']));
}
public function testConfigSet()
public function testConfigSet(): void
{
$ret = $this->config->set('foo', 'foobar');
$this->assertInstanceOf('Aviat\Ion\Config', $ret);
$this->assertInstanceOf(Config::class, $ret);
$this->assertEquals('foobar', $this->config->get('foo'));
$this->config->set(['apple', 'sauce', 'is'], 'great');
$apple = $this->config->get('apple');
$this->assertEquals('great', $apple['sauce']['is'], "Config value not set correctly");
$this->assertEquals('great', $apple['sauce']['is'], 'Config value not set correctly');
$this->assertEquals('great', $this->config->get(['apple', 'sauce', 'is']), "Array argument get for config failed.");
}
public function testConfigBadSet()
public function testConfigBadSet(): void
{
$this->expectException('InvalidArgumentException');
$this->config->set(NULL, FALSE);
}
public function dataConfigDelete()
public function dataConfigDelete(): array
{
return [
'top level delete' => [
@ -103,7 +132,7 @@ class ConfigTest extends Ion_TestCase {
/**
* @dataProvider dataConfigDelete
*/
public function testConfigDelete($key, $assertKeys)
public function testConfigDelete($key, array $assertKeys): void
{
$config = new Config([]);
$config->set(['apple', 'sauce', 'is'], 'great');
@ -115,7 +144,7 @@ class ConfigTest extends Ion_TestCase {
}
}
public function testGetNonExistentConfigItem()
public function testGetNonExistentConfigItem(): void
{
$this->assertNull($this->config->get('foobar'));
}

View File

@ -4,20 +4,19 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\Tests\Di;
use Aviat\Ion\Di\{Container, ContainerAware, ContainerInterface};
use Aviat\Ion\Di\Exception\ContainerException;
use Aviat\Ion\Tests\Ion_TestCase;
class Aware {
@ -32,13 +31,15 @@ class Aware {
class ContainerAwareTest extends Ion_TestCase {
public function setUp()
protected $aware;
public function setUp(): void
{
$this->container = new Container();
$this->aware = new Aware($this->container);
}
public function testContainerAwareTrait()
public function testContainerAwareTrait(): void
{
// The container was set in setup
// check that the get method returns the same

View File

@ -4,14 +4,14 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\Tests\Di;
@ -21,6 +21,8 @@ use Aviat\Ion\Di\Exception\ContainerException;
use Aviat\Ion\Tests\Ion_TestCase;
use Monolog\Logger;
use Monolog\Handler\{TestHandler, NullHandler};
use Aviat\Ion\Di\ContainerInterface;
use Aviat\Ion\Di\Exception\NotFoundException;
class FooTest {
@ -37,27 +39,27 @@ class FooTest2 {
class ContainerTest extends Ion_TestCase {
public function setUp()
public function setUp(): void
{
$this->container = new Container();
}
public function dataGetWithException()
public function dataGetWithException(): array
{
return [
'Bad index type: number' => [
'id' => 42,
'exception' => 'Aviat\Ion\Di\Exception\ContainerException',
'exception' => ContainerException::class,
'message' => 'Id must be a string'
],
'Bad index type: array' => [
'id' => [],
'exception' => 'Aviat\Ion\Di\Exception\ContainerException',
'exception' => ContainerException::class,
'message' => 'Id must be a string'
],
'Non-existent id' => [
'id' => 'foo',
'exception' => 'Aviat\Ion\Di\Exception\NotFoundException',
'exception' => NotFoundException::class,
'message' => "Item 'foo' does not exist in container."
]
];
@ -66,7 +68,7 @@ class ContainerTest extends Ion_TestCase {
/**
* @dataProvider dataGetWithException
*/
public function testGetWithException($id, $exception, $message)
public function testGetWithException($id, $exception, $message): void
{
try
{
@ -82,24 +84,24 @@ class ContainerTest extends Ion_TestCase {
/**
* @dataProvider dataGetWithException
*/
public function testGetNewWithException($id, $exception, $message)
public function testGetNewWithException($id, $exception, $message): void
{
$this->expectException($exception);
$this->expectExceptionMessage($message);
$this->container->getNew($id);
}
public function dataSetInstanceWithException()
public function dataSetInstanceWithException(): array
{
return [
'Non-existent id' => [
'id' => 'foo',
'exception' => 'Aviat\Ion\Di\Exception\NotFoundException',
'exception' => NotFoundException::class,
'message' => "Factory 'foo' does not exist in container. Set that first.",
],
'Non-existent id 2' => [
'id' => 'foobarbaz',
'exception' => 'Aviat\Ion\Di\Exception\NotFoundException',
'exception' => NotFoundException::class,
'message' => "Factory 'foobarbaz' does not exist in container. Set that first.",
],
];
@ -108,7 +110,7 @@ class ContainerTest extends Ion_TestCase {
/**
* @dataProvider dataSetInstanceWithException
*/
public function testSetInstanceWithException($id, $exception, $message)
public function testSetInstanceWithException($id, $exception, $message): void
{
try
{
@ -121,21 +123,21 @@ class ContainerTest extends Ion_TestCase {
}
}
public function testGetNew()
public function testGetNew(): void
{
$this->container->set('footest', function($item) {
$this->container->set('footest', static function($item) {
return new FooTest($item);
});
// Check that the item is the container, if called without arguments
$footest1 = $this->container->getNew('footest');
$this->assertInstanceOf('Aviat\Ion\Di\ContainerInterface', $footest1->item);
$this->assertInstanceOf(ContainerInterface::class, $footest1->item);
$footest2 = $this->container->getNew('footest', ['Test String']);
$this->assertEquals('Test String', $footest2->item);
}
public function testSetContainerInInstance()
public function testSetContainerInInstance(): void
{
$this->container->set('footest2', function() {
return new FooTest2();
@ -145,36 +147,36 @@ class ContainerTest extends Ion_TestCase {
$this->assertEquals($this->container, $footest2->getContainer());
}
public function testGetNewReturnCallable()
public function testGetNewReturnCallable(): void
{
$this->container->set('footest', function($item) {
return function() use ($item) {
$this->container->set('footest', static function($item) {
return static function() use ($item) {
return $item;
};
});
// Check that the item is the container, if called without arguments
$footest1 = $this->container->getNew('footest');
$this->assertInstanceOf('Aviat\Ion\Di\ContainerInterface', $footest1());
$this->assertInstanceOf(ContainerInterface::class, $footest1());
$footest2 = $this->container->getNew('footest', ['Test String']);
$this->assertEquals('Test String', $footest2());
}
public function testGetSet()
public function testGetSet(): void
{
$container = $this->container->set('foo', function() {
return function() {};
$container = $this->container->set('foo', static function() {
return static function() {};
});
$this->assertInstanceOf('Aviat\Ion\Di\Container', $container);
$this->assertInstanceOf('Aviat\Ion\Di\ContainerInterface', $container);
$this->assertInstanceOf(Container::class, $container);
$this->assertInstanceOf(ContainerInterface::class, $container);
// The factory returns a callable
$this->assertTrue(is_callable($container->get('foo')));
}
public function testLoggerMethods()
public function testLoggerMethods(): void
{
// Does the container have the default logger?
$this->assertFalse($this->container->hasLogger());
@ -189,8 +191,8 @@ class ContainerTest extends Ion_TestCase {
$container = $this->container->setLogger($logger1);
$container2 = $this->container->setLogger($logger2, 'test');
$this->assertInstanceOf('Aviat\Ion\Di\ContainerInterface', $container);
$this->assertInstanceOf('Aviat\Ion\Di\Container', $container2);
$this->assertInstanceOf(ContainerInterface::class, $container);
$this->assertInstanceOf(Container::class, $container2);
$this->assertEquals($logger1, $this->container->getLogger('default'));
$this->assertEquals($logger2, $this->container->getLogger('test'));

View File

@ -1,4 +1,18 @@
<?php
<?php declare(strict_types=1);
/**
* Ion
*
* Building blocks for web development
*
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\Tests;
@ -12,8 +26,7 @@ class EnumTest extends Ion_TestCase {
'FOOBAR' => 'baz'
];
public function setUp()
{
public function setUp(): void {
parent::setUp();
$this->enum = new TestEnum();
}

View File

@ -4,14 +4,14 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\Tests\Exception;

View File

@ -1,4 +1,18 @@
<?php
<?php declare(strict_types=1);
/**
* Ion
*
* Building blocks for web development
*
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\Tests;
@ -7,8 +21,7 @@ use Aviat\Ion\Tests\FriendTestClass;
class FriendTest extends Ion_TestCase {
public function setUp()
{
public function setUp(): void {
parent::setUp();
$obj = new FriendTestClass();
$this->friend = new Friend($obj);

View File

@ -1,16 +1,25 @@
<?php
<?php declare(strict_types=1);
/**
* Ion
*
* Building blocks for web development
*
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\Tests;
use Aura\Web\WebFactory;
use Aviat\Ion\Json;
use GuzzleHttp\Client;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Response;
use function Aviat\Ion\_dir;
use PHPUnit\Framework\TestCase;
use Zend\Diactoros\ServerRequestFactory;
use Zend\Diactoros\Response as HttpResponse;
define('ROOT_DIR', realpath(__DIR__ . '/../') . '/');
define('SRC_DIR', ROOT_DIR . 'src/');
@ -22,10 +31,10 @@ define('TEST_VIEW_DIR', __DIR__ . '/test_views');
*/
class Ion_TestCase extends TestCase {
// Test directory constants
const ROOT_DIR = ROOT_DIR;
const SRC_DIR = SRC_DIR;
const TEST_DATA_DIR = TEST_DATA_DIR;
const TEST_VIEW_DIR = TEST_VIEW_DIR;
public const ROOT_DIR = ROOT_DIR;
public const SRC_DIR = SRC_DIR;
public const TEST_DATA_DIR = TEST_DATA_DIR;
public const TEST_VIEW_DIR = TEST_VIEW_DIR;
protected $container;
protected static $staticContainer;
@ -39,7 +48,7 @@ class Ion_TestCase extends TestCase {
self::$session_handler = $session_handler;
}*/
public function setUp()
public function setUp(): void
{
parent::setUp();
@ -88,7 +97,7 @@ class Ion_TestCase extends TestCase {
// Set up DI container
$di = require('di.php');
$container = $di($config_array);
$container->set('session-handler', function() {
$container->set('session-handler', static function() {
// Use mock session handler
$session_handler = new TestSessionHandler();
session_set_save_handler($session_handler, TRUE);
@ -104,7 +113,7 @@ class Ion_TestCase extends TestCase {
* @param array $supers
* @return void
*/
public function setSuperGlobals(array $supers = [])
public function setSuperGlobals(array $supers = []): void
{
$default = [
'_SERVER' => $_SERVER,
@ -115,7 +124,7 @@ class Ion_TestCase extends TestCase {
];
$request = call_user_func_array(
['Zend\Diactoros\ServerRequestFactory', 'fromGlobals'],
[ServerRequestFactory::class, 'fromGlobals'],
array_merge($default, $supers)
);
$this->container->setInstance('request', $request);

View File

@ -1,7 +1,23 @@
<?php
<?php declare(strict_types=1);
/**
* Ion
*
* Building blocks for web development
*
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\Tests;
use function Aviat\Ion\_dir;
use Aviat\Ion\{Json, JsonException};
class JsonTest extends Ion_TestCase {

View File

@ -4,14 +4,14 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\Tests\Model;

View File

@ -0,0 +1,39 @@
<?php declare(strict_types=1);
/**
* Ion
*
* Building blocks for web development
*
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\Tests;
use Aviat\Ion\StringWrapper;
use Aviat\Ion\Type\StringType;
use PHPUnit\Framework\TestCase;
class StringWrapperTest extends TestCase {
protected $wrapper;
public function setUp(): void {
$this->wrapper = new class {
use StringWrapper;
};
}
public function testString()
{
$str = $this->wrapper->string('foo');
$this->assertInstanceOf(StringType::class, $str);
}
}

View File

@ -1,4 +1,18 @@
<?php
<?php declare(strict_types=1);
/**
* Ion
*
* Building blocks for web development
*
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\Tests;

View File

@ -4,29 +4,30 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\Tests\Transformer;
use Aviat\Ion\Tests\Ion_TestCase;
use Aviat\Ion\Tests\TestTransformer;
use Aviat\Ion\Tests\{TestTransformer, TestTransformerUntransform};
class AbstractTransformerTest extends Ion_TestCase {
protected $transformer;
protected $untransformer;
public function setUp()
{
public function setUp(): void {
$this->transformer = new TestTransformer();
$this->untransformer = new TestTransformerUntransform();
}
public function dataTransformCollection()
@ -87,6 +88,36 @@ class AbstractTransformerTest extends Ion_TestCase {
];
}
public function dataUnTransformCollection()
{
return [
'object' => [
'original' => [
(object)['Comedy', 'Romance', 'School', 'Harem'],
(object)['Action', 'Comedy', 'Magic', 'Fantasy', 'Mahou Shoujo'],
(object)['Comedy', 'Sci-Fi']
],
'expected' => [
['Comedy', 'Romance', 'School', 'Harem'],
['Action', 'Comedy', 'Magic', 'Fantasy', 'Mahou Shoujo'],
['Comedy', 'Sci-Fi']
]
],
'array' => [
'original' => [
['Comedy', 'Romance', 'School', 'Harem'],
['Action', 'Comedy', 'Magic', 'Fantasy', 'Mahou Shoujo'],
['Comedy', 'Sci-Fi']
],
'expected' => [
['Comedy', 'Romance', 'School', 'Harem'],
['Action', 'Comedy', 'Magic', 'Fantasy', 'Mahou Shoujo'],
['Comedy', 'Sci-Fi']
]
]
];
}
public function testTransform()
{
$data = $this->dataTransformCollection();
@ -105,4 +136,22 @@ class AbstractTransformerTest extends Ion_TestCase {
$actual = $this->transformer->transformCollection($original);
$this->assertEquals($expected, $actual);
}
/**
* @dataProvider dataUnTransformCollection
*/
public function testUntransformCollection($original, $expected)
{
$actual = $this->untransformer->untransformCollection($original);
$this->assertEquals($expected, $actual);
}
/**
* @dataProvider dataUnTransformCollection
*/
public function testUntransformCollectionWithException($original, $expected)
{
$this->expectException(\BadMethodCallException::class);
$this->transformer->untransformCollection($original);
}
}

View File

@ -4,14 +4,14 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\Tests\Type;
@ -22,8 +22,7 @@ use Aviat\Ion\Tests\Ion_TestCase;
class ArrayTypeTest extends Ion_TestCase {
use ArrayWrapper;
public function setUp()
{
public function setUp(): void {
parent::setUp();
}
@ -169,6 +168,29 @@ class ArrayTypeTest extends Ion_TestCase {
$this->assertFalse($obj->hasKey('b'));
}
public function testHasKeyArray()
{
$obj = $this->arr([
'foo' => [
'bar' => [
'baz' => [
'foobar' => NULL,
'one' => 1,
],
],
],
]);
$this->assertTrue($obj->hasKey(['foo']));
$this->assertTrue($obj->hasKey(['foo', 'bar']));
$this->assertTrue($obj->hasKey(['foo', 'bar', 'baz']));
$this->assertTrue($obj->hasKey(['foo', 'bar', 'baz', 'one']));
$this->assertTrue($obj->hasKey(['foo', 'bar', 'baz', 'foobar']));
$this->assertFalse($obj->hasKey(['foo', 'baz']));
$this->assertFalse($obj->hasKey(['bar', 'baz']));
}
public function testHas()
{
$obj = $this->arr([1, 2, 6, 8, 11]);

View File

@ -0,0 +1,66 @@
<?php declare(strict_types=1);
/**
* Ion
*
* Building blocks for web development
*
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\Tests\Type;
use Aviat\Ion\StringWrapper;
use Aviat\Ion\Tests\Ion_TestCase;
class StringTypeTest extends Ion_TestCase {
use StringWrapper;
public function dataFuzzyCaseMatch()
{
return [
'space separated' => [
'str1' => 'foo bar baz',
'str2' => 'foo-bar-baz',
'expected' => true
],
'camelCase' => [
'str1' => 'fooBarBaz',
'str2' => 'foo-bar-baz',
'expected' => true
],
'PascalCase' => [
'str1' => 'FooBarBaz',
'str2' => 'foo-bar-baz',
'expected' => true
],
'snake_case' => [
'str1' => 'foo_bar_baz',
'str2' => 'foo-bar-baz',
'expected' => true
],
'mEsSYcAse' => [
'str1' => 'fOObArBAZ',
'str2' => 'foo-bar-baz',
'expected' => false
],
];
}
/**
* @dataProvider dataFuzzyCaseMatch
*/
public function testFuzzyCaseMatch($str1, $str2, $expected)
{
$actual = $this->string($str1)->fuzzyCaseMatch($str2);
$this->assertEquals($expected, $actual);
}
}

View File

@ -4,28 +4,27 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\Tests\View;
use Aviat\Ion\Tests\TestHtmlView;
use function Aviat\Ion\_dir;
use function _dir;
use Aviat\Ion\Tests\TestHtmlView;
class HtmlViewTest extends HttpViewTest {
protected $template_path;
public function setUp()
{
public function setUp(): void {
parent::setUp();
$this->view = new TestHtmlView($this->container);
}

View File

@ -4,14 +4,14 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\Tests\View;
@ -26,8 +26,7 @@ class HttpViewTest extends Ion_TestCase {
protected $view;
protected $friend;
public function setUp()
{
public function setUp(): void {
parent::setUp();
$this->view = new TestHttpView($this->container);
$this->friend = new Friend($this->view);
@ -63,6 +62,13 @@ class HttpViewTest extends Ion_TestCase {
$this->assertEquals(404, $view->response->getStatusCode());
}
public function testAddHeader()
{
$view = $this->view->addHeader('foo', 'bar');
$this->assertTrue($view->response->hasHeader('foo'));
$this->assertEquals(['bar'], $view->response->getHeader('foo'));
}
public function testSendDoubleRenderException()
{
$this->expectException(DoubleRenderException::class);

View File

@ -4,14 +4,14 @@
*
* Building blocks for web development
*
* PHP version 7
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2016 Timothy J. Warren
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/ion
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\Tests\View;
@ -21,8 +21,7 @@ use Aviat\Ion\Tests\TestJsonView;
class JsonViewTest extends HttpViewTest {
public function setUp()
{
public function setUp(): void {
parent::setUp();
$this->view = new TestJsonView($this->container);

88
tests/XMLTest.php Normal file
View File

@ -0,0 +1,88 @@
<?php declare(strict_types=1);
/**
* Ion
*
* Building blocks for web development
*
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\Tests;
use Aviat\Ion\XML;
use PHPUnit\Framework\TestCase;
class XMLTest extends TestCase {
protected $xml;
protected $expectedXml;
protected $object;
protected $array;
public function setUp(): void {
$this->xml = file_get_contents(__DIR__ . '/test_data/XML/xmlTestFile.xml');
$this->expectedXml = file_get_contents(__DIR__ . '/test_data/XML/minifiedXmlTestFile.xml');
$this->array = [
'entry' => [
'foo' => [
'bar' => [
'baz' => 42
]
],
'episode' => '11',
'status' => 'watching',
'score' => '7',
'storage_type' => '1',
'storage_value' => '2.5',
'times_rewatched' => '1',
'rewatch_value' => '3',
'date_start' => '01152015',
'date_finish' => '10232016',
'priority' => '2',
'enable_discussion' => '0',
'enable_rewatching' => '1',
'comments' => 'Should you say something?',
'tags' => 'test tag, 2nd tag'
]
];
$this->object = new XML();
}
public function testToArray()
{
$this->assertEquals($this->array, XML::toArray($this->xml));
}
public function testParse()
{
$this->object->setXML($this->xml);
$this->assertEquals($this->array, $this->object->parse());
}
public function testToXML()
{
$this->assertEquals($this->expectedXml, XML::toXML($this->array));
}
public function testCreateXML()
{
$this->object->setData($this->array);
$this->assertEquals($this->expectedXml, $this->object->createXML());
}
public function testToString()
{
$this->object->setData($this->array);
$this->assertEquals($this->expectedXml, $this->object->__toString());
$this->assertEquals($this->expectedXml, (string)$this->object);
}
}

View File

@ -10,37 +10,19 @@ if ($timezone === '' || $timezone === FALSE)
ini_set('date.timezone', 'GMT');
}
// -----------------------------------------------------------------------------
// Global functions
// -----------------------------------------------------------------------------
/**
* Joins paths together. Variadic to take an
* arbitrary number of arguments
*
* @return string
*/
function _dir()
{
return implode(DIRECTORY_SEPARATOR, func_get_args());
}
// -----------------------------------------------------------------------------
// Autoloading
// -----------------------------------------------------------------------------
require 'Ion_TestCase.php';
// Composer autoload
require __DIR__ . '/../vendor/autoload.php';
require realpath(__DIR__ . '/../vendor/autoload.php');
require 'Ion_TestCase.php';
// -----------------------------------------------------------------------------
// Ini Settings
// -----------------------------------------------------------------------------
ini_set('session.use_cookies', 0);
ini_set("session.use_only_cookies",0);
ini_set("session.use_trans_sid",1);
ini_set('session.use_only_cookies',0);
ini_set('session.use_trans_sid',1);
// Start session here to surpress error about headers not sent
session_start();

View File

@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
use Aura\Html\HelperLocatorFactory;
use Aura\Session\SessionFactory;
@ -11,16 +11,16 @@ use Aviat\Ion\Di\Container;
// -----------------------------------------------------------------------------
// Setup DI container
// -----------------------------------------------------------------------------
return function(array $config_array = []) {
return static function(array $config_array = []) {
$container = new Container();
$container->set('config', function() {
$container->set('config', static function() {
return new Config([]);
});
$container->setInstance('config', new Config($config_array));
$container->set('request', function() {
$container->set('request', static function() {
return ServerRequestFactory::fromGlobals(
$_SERVER,
$_GET,
@ -30,17 +30,17 @@ return function(array $config_array = []) {
);
});
$container->set('response', function() {
$container->set('response', static function() {
return new Response();
});
// Create session Object
$container->set('session', function() {
$container->set('session', static function() {
return (new SessionFactory())->newInstance($_COOKIE);
});
// Create Html helper Object
$container->set('html-helper', function() {
$container->set('html-helper', static function() {
return (new HelperLocatorFactory)->newInstance();
});

33
tests/functionsTest.php Normal file
View File

@ -0,0 +1,33 @@
<?php declare(strict_types=1);
/**
* Ion
*
* Building blocks for web development
*
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\Tests;
use function Aviat\Ion\_dir;
use PHPUnit\Framework\TestCase;
class functionsTest extends TestCase {
public function test_dir()
{
$args = ['foo', 'bar', 'baz'];
$expected = implode(\DIRECTORY_SEPARATOR, $args);
$this->assertEquals(_dir(...$args), $expected);
}
}

View File

@ -1,6 +1,17 @@
<?php
<?php declare(strict_types=1);
/**
* All the mock classes that extend the classes they are used to test
* Ion
*
* Building blocks for web development
*
* PHP version 7.2
*
* @package Ion
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 3.0.0
* @link https://git.timshomepage.net/aviat/ion
*/
namespace Aviat\Ion\Tests;
@ -70,6 +81,13 @@ class TestTransformer extends AbstractTransformer {
}
}
class TestTransformerUntransform extends TestTransformer {
public function untransform($item)
{
return (array)$item;
}
}
trait MockViewOutputTrait {
/*protected function output() {
$reflect = new ReflectionClass($this);
@ -92,7 +110,7 @@ trait MockViewOutputTrait {
//$friend->output();
}*/
public function send()
public function send(): void
{
if ($this->hasRendered)
{
@ -104,7 +122,7 @@ trait MockViewOutputTrait {
}
class TestView extends View {
public function send()
public function send(): void
{
if ($this->hasRendered)
{
@ -117,7 +135,7 @@ class TestView extends View {
}
class TestHtmlView extends HtmlView {
protected function output()
protected function output(): void
{
if ($this->hasRendered)
{
@ -129,7 +147,7 @@ class TestHtmlView extends HtmlView {
}
class TestHttpView extends HttpView {
protected function output()
protected function output(): void
{
if ($this->hasRendered)
{
@ -143,7 +161,7 @@ class TestHttpView extends HttpView {
class TestJsonView extends JsonView {
public function __destruct() {}
protected function output()
protected function output(): void
{
if ($this->hasRendered)
{

View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<entry><foo><bar><baz>42</baz></bar></foo><episode>11</episode><status>watching</status><score>7</score><storage_type>1</storage_type><storage_value>2.5</storage_value><times_rewatched>1</times_rewatched><rewatch_value>3</rewatch_value><date_start>01152015</date_start><date_finish>10232016</date_finish><priority>2</priority><enable_discussion>0</enable_discussion><enable_rewatching>1</enable_rewatching><comments>Should you say something?</comments><tags>test tag, 2nd tag</tags></entry>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<entry>
<foo>
<bar>
<baz>42</baz>
</bar>
</foo>
<episode>11</episode>
<status>watching</status>
<score>7</score>
<storage_type>1</storage_type>
<storage_value>2.5</storage_value>
<times_rewatched>1</times_rewatched>
<rewatch_value>3</rewatch_value>
<date_start>01152015</date_start>
<date_finish>10232016</date_finish>
<priority>2</priority>
<enable_discussion>0</enable_discussion>
<enable_rewatching>1</enable_rewatching>
<comments>Should you say something?</comments>
<tags>test tag, 2nd tag</tags>
</entry>