├── tests
├── Yaml
│ ├── Fixtures
│ │ ├── embededPhp.yml
│ │ ├── sfObjects.yml
│ │ ├── index.yml
│ │ ├── YtsErrorTests.yml
│ │ ├── sfQuotes.yml
│ │ ├── YtsNullsAndEmpties.yml
│ │ ├── YtsAnchorAlias.yml
│ │ ├── YtsBlockMapping.yml
│ │ ├── sfMergeKey.yml
│ │ ├── unindentedCollections.yml
│ │ ├── sfComments.yml
│ │ ├── YtsFlowCollections.yml
│ │ ├── YtsDocumentSeparator.yml
│ │ ├── escapedCharacters.yml
│ │ ├── sfTests.yml
│ │ ├── sfCompact.yml
│ │ ├── YtsBasicTests.yml
│ │ ├── YtsFoldedScalars.yml
│ │ └── YtsTypeTransfers.yml
│ ├── LICENSE-Apache
│ ├── LICENSE-MIT
│ ├── DummyClass.php
│ └── ParseExceptionTest.php
└── Security
│ └── HashTest.php
├── contributors.md
├── .gitignore
├── .travis.yml
├── sonar-project.properties
├── src
├── Router
│ ├── Notes.txt
│ ├── LICENSE-Apache
│ ├── LICENSE-Flask
│ └── Router.php
├── Loader
│ ├── LICENSE-Apache
│ ├── Notes.txt
│ └── LICENSE-MIT
├── Yaml
│ ├── LICENSE-Apache
│ ├── Notes.txt
│ ├── LICENSE-MIT
│ ├── ParseException.php
│ └── Dumper.php
├── Views
│ ├── ViewGenerator.php
│ ├── ViewEngineBase.php
│ └── Views.php
├── Facades
│ └── FacadeBase.php
├── Interfaces
│ ├── IInterface.php
│ ├── WebPage.php
│ └── Console.php
├── Tasks
│ ├── TaskBase.php
│ └── Tasks.php
├── Containers
│ ├── SingletonContainer.php
│ ├── IocContainer.php
│ └── BindableContainer.php
├── Framework
│ ├── Tasks
│ │ ├── HelpTask.php
│ │ ├── ConsoleTask.php
│ │ ├── CleanTask.php
│ │ └── ServeTask.php
│ └── ApplicationBase.php
├── Generators
│ ├── GeneratorBase.php
│ ├── GeneratorRegistry.php
│ └── GenerateTask.php
├── Events
│ ├── Events.php
│ ├── EventGenerator.php
│ └── Delegate.php
├── Helpers
│ └── Runtime.php
├── Config
│ ├── ConfigGenerator.php
│ └── Config.php
├── Mvc
│ └── Controller.php
├── Testing
│ ├── TestsTask.php
│ └── Testing.php
├── Documentor
│ └── DocumentGenerator.php
├── Code
│ ├── CompileGenerator.php
│ ├── Minifier.php
│ ├── AnnotationManager.php
│ └── TokenStream.php
├── Objects
│ ├── FormHandler.php
│ ├── Binder.php
│ ├── BufferedUpdateCollection.php
│ └── CommandInterpreter.php
└── Cli
│ └── Application.php
├── LICENSE
├── composer.json
├── unittests.php
└── README.md
/tests/Yaml/Fixtures/embededPhp.yml:
--------------------------------------------------------------------------------
1 | value:
2 |
--------------------------------------------------------------------------------
/contributors.md:
--------------------------------------------------------------------------------
1 | # Contributors
2 |
3 | * Eser Ozvataf (Framework and Lead Developer, http://eser.ozvataf.com/)
4 | * Savas Koc
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## PHPStorm
2 | .idea/
3 |
4 | ## Windows
5 | Thumbs.db
6 | Desktop.ini
7 |
8 | ## Mac OS X
9 | .DS_Store
10 |
11 | ## Vim
12 | .*.sw?
13 |
--------------------------------------------------------------------------------
/tests/Yaml/Fixtures/sfObjects.yml:
--------------------------------------------------------------------------------
1 | --- %YAML:1.0
2 | test: Objects
3 | brief: >
4 | Comments at the end of a line
5 | yaml: |
6 | ex1: "foo # bar"
7 | ex2: "foo # bar" # comment
8 | ex3: 'foo # bar' # comment
9 | ex4: foo # comment
10 | php: |
11 | array('ex1' => 'foo # bar', 'ex2' => 'foo # bar', 'ex3' => 'foo # bar', 'ex4' => 'foo')
12 |
--------------------------------------------------------------------------------
/tests/Yaml/Fixtures/index.yml:
--------------------------------------------------------------------------------
1 | - escapedCharacters
2 | - sfComments
3 | - sfCompact
4 | - sfTests
5 | - sfObjects
6 | - sfMergeKey
7 | - sfQuotes
8 | - YtsAnchorAlias
9 | - YtsBasicTests
10 | - YtsBlockMapping
11 | - YtsDocumentSeparator
12 | - YtsErrorTests
13 | - YtsFlowCollections
14 | - YtsFoldedScalars
15 | - YtsNullsAndEmpties
16 | - YtsSpecificationExamples
17 | - YtsTypeTransfers
18 | - unindentedCollections
19 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 |
3 | php:
4 | - 5.6
5 | - hhvm
6 |
7 | before_install:
8 | - pyrus install pear/PHP_CodeSniffer
9 | - phpenv rehash
10 |
11 | script:
12 | - php unittests.php
13 | # - phpcs --standard=PSR2 --report=info .
14 | - output=$(phpcs --standard=PSR2 --report=emacs .); if [[ $output ]]; then while read -r line; do echo -e "\e[00;31m$line\e[00m"; done <<< "$output"; false; fi;
15 |
16 | matrix:
17 | allow_failures:
18 | - php: hhvm
19 |
--------------------------------------------------------------------------------
/sonar-project.properties:
--------------------------------------------------------------------------------
1 | # Required metadata
2 | sonar.projectKey=org.codehaus.sonar:scabbiafw
3 | sonar.projectName=Scabbia2 PHP Framework
4 | sonar.projectVersion=2.0
5 |
6 | # Comma-separated paths to directories with sources (required)
7 | sonar.sources=src
8 |
9 | # Language
10 | sonar.language=php
11 | sonar.phpCodesniffer.standardArgument=psr2
12 |
13 | # To deactivate features related to unit tests execution and coverage
14 | sonar.dynamicAnalysis=false
15 |
16 | # Encoding of the source files
17 | sonar.sourceEncoding=UTF-8
18 |
--------------------------------------------------------------------------------
/src/Router/Notes.txt:
--------------------------------------------------------------------------------
1 | Some parts of this code are taken from FastRoute under the Flask license (modified version of BSD-3-Clause).
2 |
3 | (c) Nikita Popov
4 |
5 | For the full copyright and license information, please view the LICENSE-Flask
6 | file that was distributed with this source code.
7 |
8 | Modifications made:
9 | - Scabbia Framework code styles applied.
10 | - Completely implemented to Scabbia2's own generator-based system.
11 |
12 | Latest commit applied:
13 | https://github.com/nikic/FastRoute/commit/7dc9a43cb856debc22fe158a1144018e16f7a637
14 | 7dc9a43cb856debc22fe158a1144018e16f7a637
15 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Copyright 2014 Scabbia Framework Organization
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
--------------------------------------------------------------------------------
/src/Loader/LICENSE-Apache:
--------------------------------------------------------------------------------
1 |
2 | Copyright 2013 Scabbia Framework Organization
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
--------------------------------------------------------------------------------
/src/Router/LICENSE-Apache:
--------------------------------------------------------------------------------
1 |
2 | Copyright 2013 Scabbia Framework Organization
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
--------------------------------------------------------------------------------
/src/Yaml/LICENSE-Apache:
--------------------------------------------------------------------------------
1 |
2 | Copyright 2013 Scabbia Framework Organization
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
--------------------------------------------------------------------------------
/tests/Yaml/LICENSE-Apache:
--------------------------------------------------------------------------------
1 |
2 | Copyright 2013 Scabbia Framework Organization
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
--------------------------------------------------------------------------------
/src/Yaml/Notes.txt:
--------------------------------------------------------------------------------
1 | Some parts of this code are taken from Symfony YAML Component under the MIT license.
2 |
3 | (c) Fabien Potencier
4 |
5 | For the full copyright and license information, please view the LICENSE-MIT
6 | file that was distributed with this source code.
7 |
8 | Modifications made:
9 | - Scabbia Framework code styles applied.
10 | - All dump methods are moved under Dumper class.
11 | - Redundant classes removed.
12 | - Namespace changed.
13 | - Tests ported to Scabbia2.
14 | - Encoding checks removed.
15 |
16 | Latest commit applied:
17 | https://github.com/symfony/Yaml/commit/6db64aa92ce2b2aa35a72a0d0508de4d60c70b20
18 | 6db64aa92ce2b2aa35a72a0d0508de4d60c70b20
19 |
--------------------------------------------------------------------------------
/tests/Yaml/Fixtures/YtsErrorTests.yml:
--------------------------------------------------------------------------------
1 | ---
2 | test: Missing value for hash item
3 | todo: true
4 | brief: |
5 | Third item in this hash doesn't have a value
6 | yaml: |
7 | okay: value
8 | also okay: ~
9 | causes error because no value specified
10 | last key: value okay here too
11 | python-error: causes error because no value specified
12 |
13 | ---
14 | test: Not indenting enough
15 | brief: |
16 | There was a bug in PyYaml where it was off by one
17 | in the indentation check. It was allowing the YAML
18 | below.
19 | # This is actually valid YAML now. Someone should tell showell.
20 | yaml: |
21 | foo:
22 | firstline: 1
23 | secondline: 2
24 | php: |
25 | array('foo' => null, 'firstline' => 1, 'secondline' => 2)
26 |
--------------------------------------------------------------------------------
/src/Loader/Notes.txt:
--------------------------------------------------------------------------------
1 | Some parts of this code are taken from Composer under the MIT license.
2 |
3 | (c) Nils Adermann
4 | (c) Jordi Boggiano
5 |
6 | For the full copyright and license information, please view the LICENSE-MIT
7 | file that was distributed with this source code.
8 |
9 | Modifications made:
10 | - Scabbia Framework code styles applied.
11 | - Added push/pop configuration.
12 | - Loading/Importing composer files are now optional.
13 | - Finding resources with extensions is now possible.
14 | - Added prepended paths for overriding vendor resources.
15 |
16 | Latest commit applied:
17 | https://github.com/composer/composer/commit/d79f2b0fd33ee9b89f3d9f1969f43dc3d570a33a
18 | d79f2b0fd33ee9b89f3d9f1969f43dc3d570a33a
19 |
--------------------------------------------------------------------------------
/tests/Yaml/Fixtures/sfQuotes.yml:
--------------------------------------------------------------------------------
1 | --- %YAML:1.0
2 | test: Some characters at the beginning of a string must be escaped
3 | brief: >
4 | Some characters at the beginning of a string must be escaped
5 | yaml: |
6 | foo: | bar
7 | php: |
8 | array('foo' => '| bar')
9 | ---
10 | test: A key can be a quoted string
11 | brief: >
12 | A key can be a quoted string
13 | yaml: |
14 | "foo1": bar
15 | 'foo2': bar
16 | "foo \" bar": bar
17 | 'foo '' bar': bar
18 | 'foo3: ': bar
19 | "foo4: ": bar
20 | foo5: { "foo \" bar: ": bar, 'foo '' bar: ': bar }
21 | php: |
22 | array(
23 | 'foo1' => 'bar',
24 | 'foo2' => 'bar',
25 | 'foo " bar' => 'bar',
26 | 'foo \' bar' => 'bar',
27 | 'foo3: ' => 'bar',
28 | 'foo4: ' => 'bar',
29 | 'foo5' => array(
30 | 'foo " bar: ' => 'bar',
31 | 'foo \' bar: ' => 'bar',
32 | ),
33 | )
34 |
--------------------------------------------------------------------------------
/tests/Yaml/Fixtures/YtsNullsAndEmpties.yml:
--------------------------------------------------------------------------------
1 | --- %YAML:1.0
2 | test: Empty Sequence
3 | brief: >
4 | You can represent the empty sequence
5 | with an empty inline sequence.
6 | yaml: |
7 | empty: []
8 | php: |
9 | array('empty' => array())
10 | ---
11 | test: Empty Mapping
12 | brief: >
13 | You can represent the empty mapping
14 | with an empty inline mapping.
15 | yaml: |
16 | empty: {}
17 | php: |
18 | array('empty' => array())
19 | ---
20 | test: Empty Sequence as Entire Document
21 | yaml: |
22 | []
23 | php: |
24 | array()
25 | ---
26 | test: Empty Mapping as Entire Document
27 | yaml: |
28 | {}
29 | php: |
30 | array()
31 | ---
32 | test: Null as Document
33 | yaml: |
34 | ~
35 | php: |
36 | null
37 | ---
38 | test: Empty String
39 | brief: >
40 | You can represent an empty string
41 | with a pair of quotes.
42 | yaml: |
43 | ''
44 | php: |
45 | ''
46 |
--------------------------------------------------------------------------------
/tests/Yaml/Fixtures/YtsAnchorAlias.yml:
--------------------------------------------------------------------------------
1 | --- %YAML:1.0
2 | test: Simple Alias Example
3 | brief: >
4 | If you need to refer to the same item of data twice,
5 | you can give that item an alias. The alias is a plain
6 | string, starting with an ampersand. The item may then
7 | be referred to by the alias throughout your document
8 | by using an asterisk before the name of the alias.
9 | This is called an anchor.
10 | yaml: |
11 | - &showell Steve
12 | - Clark
13 | - Brian
14 | - Oren
15 | - *showell
16 | php: |
17 | array('Steve', 'Clark', 'Brian', 'Oren', 'Steve')
18 |
19 | ---
20 | test: Alias of a Mapping
21 | brief: >
22 | An alias can be used on any item of data, including
23 | sequences, mappings, and other complex data types.
24 | yaml: |
25 | - &hello
26 | Meat: pork
27 | Starch: potato
28 | - banana
29 | - *hello
30 | php: |
31 | array(array('Meat'=>'pork', 'Starch'=>'potato'), 'banana', array('Meat'=>'pork', 'Starch'=>'potato'))
32 |
--------------------------------------------------------------------------------
/src/Yaml/LICENSE-MIT:
--------------------------------------------------------------------------------
1 | Copyright (c) 2004-2014 Fabien Potencier
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is furnished
8 | to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/tests/Yaml/LICENSE-MIT:
--------------------------------------------------------------------------------
1 | Copyright (c) 2004-2013 Fabien Potencier
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is furnished
8 | to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/src/Loader/LICENSE-MIT:
--------------------------------------------------------------------------------
1 | Copyright (c) 2011 Nils Adermann, Jordi Boggiano
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is furnished
8 | to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
--------------------------------------------------------------------------------
/tests/Yaml/Fixtures/YtsBlockMapping.yml:
--------------------------------------------------------------------------------
1 | ---
2 | test: One Element Mapping
3 | brief: |
4 | A mapping with one key/value pair
5 | yaml: |
6 | foo: bar
7 | php: |
8 | array('foo' => 'bar')
9 | ---
10 | test: Multi Element Mapping
11 | brief: |
12 | More than one key/value pair
13 | yaml: |
14 | red: baron
15 | white: walls
16 | blue: berries
17 | php: |
18 | array(
19 | 'red' => 'baron',
20 | 'white' => 'walls',
21 | 'blue' => 'berries',
22 | )
23 | ---
24 | test: Values aligned
25 | brief: |
26 | Often times human editors of documents will align the values even
27 | though YAML emitters generally don't.
28 | yaml: |
29 | red: baron
30 | white: walls
31 | blue: berries
32 | php: |
33 | array(
34 | 'red' => 'baron',
35 | 'white' => 'walls',
36 | 'blue' => 'berries',
37 | )
38 | ---
39 | test: Colons aligned
40 | brief: |
41 | Spaces can come before the ': ' key/value separator.
42 | yaml: |
43 | red : baron
44 | white : walls
45 | blue : berries
46 | php: |
47 | array(
48 | 'red' => 'baron',
49 | 'white' => 'walls',
50 | 'blue' => 'berries',
51 | )
52 |
--------------------------------------------------------------------------------
/tests/Yaml/Fixtures/sfMergeKey.yml:
--------------------------------------------------------------------------------
1 | --- %YAML:1.0
2 | test: Simple In Place Substitution
3 | brief: >
4 | If you want to reuse an entire alias, only overwriting what is different
5 | you can use a << in place substitution. This is not part of the official
6 | YAML spec, but a widely implemented extension. See the following URL for
7 | details: http://yaml.org/type/merge.html
8 | yaml: |
9 | foo: &foo
10 | a: Steve
11 | b: Clark
12 | c: Brian
13 | bar: &bar
14 | <<: *foo
15 | x: Oren
16 | foo2: &foo2
17 | a: Ballmer
18 | ding: &dong [ fi, fei, fo, fam]
19 | check:
20 | <<:
21 | - *foo
22 | - *dong
23 | isit: tested
24 | head:
25 | <<: [ *foo , *dong , *foo2 ]
26 | php: |
27 | array('foo' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian'), 'bar' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'x' => 'Oren'), 'foo2' => array('a' => 'Ballmer'), 'ding' => array('fi', 'fei', 'fo', 'fam'), 'check' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'fi', 'fei', 'fo', 'fam', 'isit' => 'tested'), 'head' => array('a' => 'Ballmer', 'b' => 'Clark', 'c' => 'Brian', 'fi', 'fei', 'fo', 'fam'))
28 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "scabbiafw/scabbia2-fw",
3 | "description": "Scabbia2 PHP Framework Code",
4 | "type": "library",
5 | "minimum-stability": "dev",
6 | "prefer-stable": true,
7 | "keywords": [
8 | "larukedi",
9 | "scabbia",
10 | "scabbia2",
11 | "scabbiafw",
12 | "framework",
13 | "lightstack",
14 | "stack"
15 | ],
16 | "homepage": "http://www.scabbiafw.com/",
17 | "license": "Apache-2.0",
18 | "authors": [
19 | {
20 | "name": "Scabbia Framework Organization",
21 | "email": "contact@scabbiafw.com"
22 | }
23 | ],
24 | "require": {
25 | "php": ">=5.6.0",
26 | "psr/log": "1.0.0",
27 | "scabbiafw/scabbia2-lightstack": "dev-master"
28 | },
29 | "suggest": {
30 | "ext-curl": "ext/curl for http communication",
31 | "ext-mbstring": "ext/mbstring for multibyte string manipulation",
32 | "ext-tokenizer": "ext/tokenizer for lexical analysis"
33 | },
34 | "autoload": {
35 | "psr-4": {
36 | "Scabbia\\": [ "src/" ]
37 | }
38 | },
39 | "autoload-dev": {
40 | "psr-4": {
41 | "Scabbia\\Tests\\": [ "tests/" ]
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/unittests.php:
--------------------------------------------------------------------------------
1 | register(true);
20 |
21 | // register the base directories for the namespace prefix
22 | $tLoader->addPsr4("Scabbia\\", __DIR__ . "/src/");
23 | $tLoader->addPsr4("Scabbia\\Tests\\", __DIR__ . "/tests/");
24 |
25 | use Scabbia\Interfaces\Console;
26 | use Scabbia\Testing\TestsTask;
27 |
28 | $tConfig = [
29 | "fixtures" => [
30 | "Scabbia\\Tests\\Yaml\\ParserTest",
31 | "Scabbia\\Tests\\Yaml\\InlineTest",
32 | "Scabbia\\Tests\\Security\\HashTest"
33 | ]
34 | ];
35 |
36 | $tInterface = new Console();
37 | $tTestTask = new TestsTask($tConfig, $tInterface);
38 | $tExitCode = $tTestTask->executeTask([]);
39 |
40 | exit($tExitCode);
41 |
--------------------------------------------------------------------------------
/tests/Yaml/DummyClass.php:
--------------------------------------------------------------------------------
1 |
17 | *
18 | * For the full copyright and license information, please view the LICENSE-MIT
19 | * file that was distributed with this source code.
20 | *
21 | * Modifications made:
22 | * - Scabbia Framework code styles applied.
23 | * - All dump methods are moved under Dumper class.
24 | * - Redundant classes removed.
25 | * - Namespace changed.
26 | * - Tests ported to Scabbia2.
27 | * - Encoding checks removed.
28 | */
29 |
30 | namespace Scabbia\Tests\Yaml;
31 |
32 | /**
33 | * A dummy class for serialization tests
34 | *
35 | * @package Scabbia\Tests\Yaml
36 | * @since 2.0.0
37 | */
38 | class DummyClass
39 | {
40 | /** @type string $b a dummy member */
41 | public $b = "foo";
42 | }
43 |
--------------------------------------------------------------------------------
/src/Router/LICENSE-Flask:
--------------------------------------------------------------------------------
1 | Copyright (c) 2013 by Nikita Popov.
2 |
3 | Some rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are
7 | met:
8 |
9 | * Redistributions of source code must retain the above copyright
10 | notice, this list of conditions and the following disclaimer.
11 |
12 | * Redistributions in binary form must reproduce the above
13 | copyright notice, this list of conditions and the following
14 | disclaimer in the documentation and/or other materials provided
15 | with the distribution.
16 |
17 | * The names of the contributors may not be used to endorse or
18 | promote products derived from this software without specific
19 | prior written permission.
20 |
21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
/tests/Yaml/Fixtures/unindentedCollections.yml:
--------------------------------------------------------------------------------
1 | --- %YAML:1.0
2 | test: Unindented collection
3 | brief: >
4 | Unindented collection
5 | yaml: |
6 | collection:
7 | - item1
8 | - item2
9 | - item3
10 | php: |
11 | array('collection' => array('item1', 'item2', 'item3'))
12 | ---
13 | test: Nested unindented collection (two levels)
14 | brief: >
15 | Nested unindented collection
16 | yaml: |
17 | collection:
18 | key:
19 | - a
20 | - b
21 | - c
22 | php: |
23 | array('collection' => array('key' => array('a', 'b', 'c')))
24 | ---
25 | test: Nested unindented collection (three levels)
26 | brief: >
27 | Nested unindented collection
28 | yaml: |
29 | collection:
30 | key:
31 | subkey:
32 | - one
33 | - two
34 | - three
35 | php: |
36 | array('collection' => array('key' => array('subkey' => array('one', 'two', 'three'))))
37 | ---
38 | test: Key/value after unindented collection (1)
39 | brief: >
40 | Key/value after unindented collection (1)
41 | yaml: |
42 | collection:
43 | key:
44 | - a
45 | - b
46 | - c
47 | foo: bar
48 | php: |
49 | array('collection' => array('key' => array('a', 'b', 'c')), 'foo' => 'bar')
50 | ---
51 | test: Key/value after unindented collection (at the same level)
52 | brief: >
53 | Key/value after unindented collection
54 | yaml: |
55 | collection:
56 | key:
57 | - a
58 | - b
59 | - c
60 | foo: bar
61 | php: |
62 | array('collection' => array('key' => array('a', 'b', 'c'), 'foo' => 'bar'))
63 |
--------------------------------------------------------------------------------
/src/Views/ViewGenerator.php:
--------------------------------------------------------------------------------
1 |
25 | * @since 2.0.0
26 | *
27 | * @scabbia-generator
28 | */
29 | class ViewGenerator extends GeneratorBase
30 | {
31 | /**
32 | * Processes a file
33 | *
34 | * @param string $uPath file path
35 | * @param string $uFileContents contents of file
36 | * @param TokenStream $uTokenStream extracted tokens wrapped with tokenstream
37 | *
38 | * @return void
39 | */
40 | public function processFile($uPath, $uFileContents, TokenStream $uTokenStream)
41 | {
42 | $tViewEngine = Views::findViewEngine($uPath);
43 |
44 | if ($tViewEngine === null) {
45 | return;
46 | }
47 |
48 | // TODO compile view
49 | $tViewEngineClass = get_class($tViewEngine);
50 | echo sprintf("View %s => %s\n", $uPath, $tViewEngineClass);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/Facades/FacadeBase.php:
--------------------------------------------------------------------------------
1 |
24 | * @since 2.0.0
25 | */
26 | abstract class FacadeBase
27 | {
28 | /** @type array $callbackMap map for callbacks */
29 | public static $callbackMap;
30 |
31 |
32 | /**
33 | * Handles static method calls to the class definition
34 | *
35 | * @param string $uMethod method name
36 | * @param array $uParameters parameters
37 | *
38 | * @throws UnexpectedValueException if mapped method not found
39 | * @return mixed
40 | */
41 | public static function __callStatic($uMethod, $uParameters)
42 | {
43 | if (isset(static::$callbackMap[$uMethod])) {
44 | return call_user_func(
45 | Runtime::callbacks(static::$callbackMap[$uMethod]),
46 | ...$uParameters
47 | );
48 | }
49 |
50 | // TODO exception
51 | throw new UnexpectedValueException("");
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/Interfaces/IInterface.php:
--------------------------------------------------------------------------------
1 |
21 | * @since 2.0.0
22 | */
23 | interface IInterface
24 | {
25 | /**
26 | * Writes given message in header format
27 | *
28 | * @param int $uHeading size
29 | * @param string $uMessage message
30 | *
31 | * @return void
32 | */
33 | public function writeHeader($uHeading, $uMessage);
34 |
35 | /**
36 | * Writes given message in specified color
37 | *
38 | * @param string $uColor color
39 | * @param string $uMessage message
40 | *
41 | * @return void
42 | */
43 | public function writeColor($uColor, $uMessage);
44 |
45 | /**
46 | * Writes given message
47 | *
48 | * @param string $uMessage message
49 | *
50 | * @return void
51 | */
52 | public function write($uMessage);
53 |
54 | /**
55 | * Outputs the array in specified representation
56 | *
57 | * @param array $uArray Target array will be printed
58 | *
59 | * @return void
60 | */
61 | public function writeArray(array $uArray);
62 | }
63 |
--------------------------------------------------------------------------------
/tests/Yaml/Fixtures/sfComments.yml:
--------------------------------------------------------------------------------
1 | --- %YAML:1.0
2 | test: Comments at the end of a line
3 | brief: >
4 | Comments at the end of a line
5 | yaml: |
6 | ex1: "foo # bar"
7 | ex2: "foo # bar" # comment
8 | ex3: 'foo # bar' # comment
9 | ex4: foo # comment
10 | php: |
11 | array('ex1' => 'foo # bar', 'ex2' => 'foo # bar', 'ex3' => 'foo # bar', 'ex4' => 'foo')
12 | ---
13 | test: Comments in the middle
14 | brief: >
15 | Comments in the middle
16 | yaml: |
17 | foo:
18 | # some comment
19 | # some comment
20 | bar: foo
21 | # some comment
22 | # some comment
23 | php: |
24 | array('foo' => array('bar' => 'foo'))
25 | ---
26 | test: Comments on a hash line
27 | brief: >
28 | Comments on a hash line
29 | yaml: |
30 | foo: # a comment
31 | foo: bar # a comment
32 | php: |
33 | array('foo' => array('foo' => 'bar'))
34 | ---
35 | test: 'Value starting with a #'
36 | brief: >
37 | 'Value starting with a #'
38 | yaml: |
39 | foo: '#bar'
40 | php: |
41 | array('foo' => '#bar')
42 | ---
43 | test: Document starting with a comment and a separator
44 | brief: >
45 | Commenting before document start is allowed
46 | yaml: |
47 | # document comment
48 | ---
49 | foo: bar # a comment
50 | php: |
51 | array('foo' => 'bar')
52 | ---
53 | test: Comment containing a colon on a hash line
54 | brief: >
55 | Comment containing a colon on a scalar line
56 | yaml: 'foo # comment: this is also part of the comment'
57 | php: |
58 | 'foo'
59 | ---
60 | test: 'Hash key containing a #'
61 | brief: >
62 | 'Hash key containing a #'
63 | yaml: 'foo#bar: baz'
64 | php: |
65 | array('foo#bar' => 'baz')
66 | ---
67 | test: 'Hash key ending with a space and a #'
68 | brief: >
69 | 'Hash key ending with a space and a #'
70 | yaml: |
71 | 'foo #': baz
72 | php: |
73 | array('foo #' => 'baz')
--------------------------------------------------------------------------------
/tests/Yaml/Fixtures/YtsFlowCollections.yml:
--------------------------------------------------------------------------------
1 | ---
2 | test: Simple Inline Array
3 | brief: >
4 | Sequences can be contained on a
5 | single line, using the inline syntax.
6 | Separate each entry with commas and
7 | enclose in square brackets.
8 | yaml: |
9 | seq: [ a, b, c ]
10 | php: |
11 | array('seq' => array('a', 'b', 'c'))
12 | ---
13 | test: Simple Inline Hash
14 | brief: >
15 | Mapping can also be contained on
16 | a single line, using the inline
17 | syntax. Each key-value pair is
18 | separated by a colon, with a comma
19 | between each entry in the mapping.
20 | Enclose with curly braces.
21 | yaml: |
22 | hash: { name: Steve, foo: bar }
23 | php: |
24 | array('hash' => array('name' => 'Steve', 'foo' => 'bar'))
25 | ---
26 | test: Multi-line Inline Collections
27 | todo: true
28 | brief: >
29 | Both inline sequences and inline mappings
30 | can span multiple lines, provided that you
31 | indent the additional lines.
32 | yaml: |
33 | languages: [ Ruby,
34 | Perl,
35 | Python ]
36 | websites: { YAML: yaml.org,
37 | Ruby: ruby-lang.org,
38 | Python: python.org,
39 | Perl: use.perl.org }
40 | php: |
41 | array(
42 | 'languages' => array('Ruby', 'Perl', 'Python'),
43 | 'websites' => array(
44 | 'YAML' => 'yaml.org',
45 | 'Ruby' => 'ruby-lang.org',
46 | 'Python' => 'python.org',
47 | 'Perl' => 'use.perl.org'
48 | )
49 | )
50 | ---
51 | test: Commas in Values (not in the spec!)
52 | todo: true
53 | brief: >
54 | List items in collections are delimited by commas, but
55 | there must be a space after each comma. This allows you
56 | to add numbers without quoting.
57 | yaml: |
58 | attendances: [ 45,123, 70,000, 17,222 ]
59 | php: |
60 | array('attendances' => array(45123, 70000, 17222))
61 |
--------------------------------------------------------------------------------
/tests/Yaml/ParseExceptionTest.php:
--------------------------------------------------------------------------------
1 |
17 | *
18 | * For the full copyright and license information, please view the LICENSE-MIT
19 | * file that was distributed with this source code.
20 | *
21 | * Modifications made:
22 | * - Scabbia Framework code styles applied.
23 | * - All dump methods are moved under Dumper class.
24 | * - Redundant classes removed.
25 | * - Namespace changed.
26 | * - Tests ported to Scabbia2.
27 | * - Encoding checks removed.
28 | */
29 |
30 | namespace Scabbia\Tests\Yaml;
31 |
32 | use Scabbia\Testing\UnitTestFixture;
33 | use Scabbia\Yaml\ParseException;
34 |
35 | /**
36 | * Tests of ParseException class
37 | *
38 | * @package Scabbia\Tests\Yaml
39 | * @since 2.0.0
40 | */
41 | class ParseExceptionTest extends UnitTestFixture
42 | {
43 | /**
44 | * Gets data form specifications
45 | *
46 | * @return array
47 | */
48 | public function getDataFormSpecifications()
49 | {
50 | $tException = new ParseException("Error message", 42, "foo: bar", "/var/www/app/config.yml");
51 |
52 | $this->assertEquals(
53 | "Error message in \"/var/www/app/config.yml\" at line 42 (near \"foo: bar\")",
54 | $tException->getMessage()
55 | );
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/tests/Yaml/Fixtures/YtsDocumentSeparator.yml:
--------------------------------------------------------------------------------
1 | --- %YAML:1.0
2 | test: Trailing Document Separator
3 | todo: true
4 | brief: >
5 | You can separate YAML documents
6 | with a string of three dashes.
7 | yaml: |
8 | - foo: 1
9 | bar: 2
10 | ---
11 | more: stuff
12 | python: |
13 | [
14 | [ { 'foo': 1, 'bar': 2 } ],
15 | { 'more': 'stuff' }
16 | ]
17 | ruby: |
18 | [ { 'foo' => 1, 'bar' => 2 } ]
19 |
20 | ---
21 | test: Leading Document Separator
22 | todo: true
23 | brief: >
24 | You can explicity give an opening
25 | document separator to your YAML stream.
26 | yaml: |
27 | ---
28 | - foo: 1
29 | bar: 2
30 | ---
31 | more: stuff
32 | python: |
33 | [
34 | [ {'foo': 1, 'bar': 2}],
35 | {'more': 'stuff'}
36 | ]
37 | ruby: |
38 | [ { 'foo' => 1, 'bar' => 2 } ]
39 |
40 | ---
41 | test: YAML Header
42 | todo: true
43 | brief: >
44 | The opening separator can contain directives
45 | to the YAML parser, such as the version
46 | number.
47 | yaml: |
48 | --- %YAML:1.0
49 | foo: 1
50 | bar: 2
51 | php: |
52 | array('foo' => 1, 'bar' => 2)
53 | documents: 1
54 |
55 | ---
56 | test: Red Herring Document Separator
57 | brief: >
58 | Separators included in blocks or strings
59 | are treated as blocks or strings, as the
60 | document separator should have no indentation
61 | preceding it.
62 | yaml: |
63 | foo: |
64 | ---
65 | php: |
66 | array('foo' => "---\n")
67 |
68 | ---
69 | test: Multiple Document Separators in Block
70 | brief: >
71 | This technique allows you to embed other YAML
72 | documents within literal blocks.
73 | yaml: |
74 | foo: |
75 | ---
76 | foo: bar
77 | ---
78 | yo: baz
79 | bar: |
80 | fooness
81 | php: |
82 | array(
83 | 'foo' => "---\nfoo: bar\n---\nyo: baz\n",
84 | 'bar' => "fooness\n"
85 | )
86 |
--------------------------------------------------------------------------------
/src/Views/ViewEngineBase.php:
--------------------------------------------------------------------------------
1 |
21 | * @since 2.0.0
22 | *
23 | * @todo compile
24 | * @todo sections
25 | */
26 | class ViewEngineBase
27 | {
28 | /** @type mixed $model model for the current view */
29 | public $model;
30 | /** @type object|null $controller controller for the current view */
31 | public $controller;
32 |
33 | /**
34 | * Initializes a view engine
35 | *
36 | * @return ViewEngineBase
37 | */
38 | public function __construct()
39 | {
40 | }
41 |
42 | /**
43 | * Renders plain PHP file for using them as a template format
44 | *
45 | * @param string $tTemplatePath path of the template file
46 | * @param string $tTemplateFile filename of the template file
47 | * @param mixed $uModel model object
48 | * @param mixed $uController controller instance
49 | *
50 | * @return void
51 | */
52 | public function render($tTemplatePath, $tTemplateFile, $uModel = null, $uController = null)
53 | {
54 | $this->model = $uModel;
55 | $this->controller = $uController;
56 |
57 | if ($uModel !== null && is_array($uModel)) {
58 | extract($uModel, EXTR_SKIP | EXTR_REFS);
59 | }
60 |
61 | include "{$tTemplatePath}{$tTemplateFile}";
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/Tasks/TaskBase.php:
--------------------------------------------------------------------------------
1 |
23 | * @since 2.0.0
24 | *
25 | * @todo "scabbia help " task
26 | */
27 | abstract class TaskBase
28 | {
29 | /** @type mixed $config task configuration */
30 | public $config;
31 | /** @type IInterface $interface output class */
32 | public $interface;
33 |
34 |
35 | /**
36 | * Registers the tasks itself to a command interpreter instance
37 | *
38 | * @param CommandInterpreter $uCommandInterpreter interpreter to be registered at
39 | *
40 | * @return void
41 | */
42 | public static function registerToCommandInterpreter(CommandInterpreter $uCommandInterpreter)
43 | {
44 | }
45 |
46 | /**
47 | * Initializes a task
48 | *
49 | * @param mixed $uConfig configuration
50 | * @param IInterface $uInterface interface class
51 | *
52 | * @return TaskBase
53 | */
54 | public function __construct($uConfig, $uInterface)
55 | {
56 | $this->config = $uConfig;
57 | $this->interface = $uInterface;
58 | }
59 |
60 | /**
61 | * Executes the task
62 | *
63 | * @param array $uParameters parameters
64 | *
65 | * @return int exit code
66 | */
67 | abstract public function executeTask(array $uParameters);
68 | }
69 |
--------------------------------------------------------------------------------
/src/Containers/SingletonContainer.php:
--------------------------------------------------------------------------------
1 |
23 | * @since 2.0.0
24 | */
25 | trait SingletonContainer
26 | {
27 | /** @type object $instance singleton object */
28 | public static $instance = null;
29 |
30 |
31 | /**
32 | * Gets the singleton object
33 | *
34 | * @return object class instance
35 | */
36 | public static function getInstance()
37 | {
38 | if (static::$instance === null) {
39 | static::$instance = new static();
40 | }
41 |
42 | return static::$instance;
43 | }
44 |
45 | /**
46 | * Sets the class instance as singleton object
47 | *
48 | * @return void
49 | */
50 | public function setDefaultInstance()
51 | {
52 | static::$instance = $this;
53 | }
54 |
55 | /**
56 | * Constructor to prevent new instances of this class
57 | *
58 | * @return SingletonContainer
59 | */
60 | final private function __construct()
61 | {
62 | }
63 |
64 | /**
65 | * Clone method to prevent duplication of this class
66 | *
67 | * @return SingletonContainer
68 | */
69 | final private function __clone()
70 | {
71 | }
72 |
73 | /**
74 | * Unserialization method to prevent restoration of this class
75 | *
76 | * @return SingletonContainer
77 | */
78 | final private function __wakeup()
79 | {
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/Framework/Tasks/HelpTask.php:
--------------------------------------------------------------------------------
1 |
26 | * @since 2.0.0
27 | *
28 | * @scabbia-task help
29 | */
30 | class HelpTask extends TaskBase
31 | {
32 | /**
33 | * Registers the tasks itself to a command interpreter instance
34 | *
35 | * @param CommandInterpreter $uCommandInterpreter interpreter to be registered at
36 | *
37 | * @return void
38 | */
39 | public static function registerToCommandInterpreter(CommandInterpreter $uCommandInterpreter)
40 | {
41 | $uCommandInterpreter->addCommand(
42 | "help",
43 | "Displays this help",
44 | []
45 | );
46 | }
47 |
48 | /**
49 | * Initializes the serve task
50 | *
51 | * @param mixed $uConfig configuration
52 | * @param IInterface $uInterface interface class
53 | *
54 | * @return HelpTask
55 | */
56 | public function __construct($uConfig, $uInterface)
57 | {
58 | parent::__construct($uConfig, $uInterface);
59 | }
60 |
61 | /**
62 | * Executes the task
63 | *
64 | * @param array $uParameters parameters
65 | *
66 | * @return int exit code
67 | */
68 | public function executeTask(array $uParameters)
69 | {
70 | // TODO call interpreter->help();
71 | return 0;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/Generators/GeneratorBase.php:
--------------------------------------------------------------------------------
1 |
25 | * @since 2.0.0
26 | */
27 | abstract class GeneratorBase
28 | {
29 | /** @type GeneratorRegistry $generatorRegistry generator registry */
30 | public $generatorRegistry;
31 |
32 |
33 | /**
34 | * Initializes a generator
35 | *
36 | * @param GeneratorRegistry $uGeneratorRegistry generator registry
37 | *
38 | * @return GeneratorBase
39 | */
40 | public function __construct(GeneratorRegistry $uGeneratorRegistry)
41 | {
42 | $this->generatorRegistry = $uGeneratorRegistry;
43 | }
44 |
45 | /**
46 | * Processes a file
47 | *
48 | * @param string $uPath file path
49 | * @param string $uFileContents contents of file
50 | * @param TokenStream $uTokenStream extracted tokens wrapped with tokenstream
51 | *
52 | * @return void
53 | */
54 | public function processFile($uPath, $uFileContents, TokenStream $uTokenStream)
55 | {
56 | }
57 |
58 | /**
59 | * Processes set of annotations
60 | *
61 | * @return void
62 | */
63 | public function processAnnotations()
64 | {
65 | }
66 |
67 | /**
68 | * Finalizes generator process
69 | *
70 | * @return void
71 | */
72 | public function finalize()
73 | {
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/Framework/Tasks/ConsoleTask.php:
--------------------------------------------------------------------------------
1 |
25 | * @since 2.0.0
26 | *
27 | * @scabbia-task console
28 | * @todo only pass annotations requested by generator
29 | */
30 | class ConsoleTask extends TaskBase
31 | {
32 | /**
33 | * Registers the tasks itself to a command interpreter instance
34 | *
35 | * @param CommandInterpreter $uCommandInterpreter interpreter to be registered at
36 | *
37 | * @return void
38 | */
39 | public static function registerToCommandInterpreter(CommandInterpreter $uCommandInterpreter)
40 | {
41 | $uCommandInterpreter->addCommand(
42 | "console",
43 | "Launches a REPL command interface",
44 | []
45 | );
46 | }
47 |
48 | /**
49 | * Initializes the console task
50 | *
51 | * @param mixed $uConfig configuration
52 | * @param IInterface $uInterface interface class
53 | *
54 | * @return ConsoleTask
55 | */
56 | public function __construct($uConfig, $uInterface)
57 | {
58 | parent::__construct($uConfig, $uInterface);
59 | }
60 |
61 | /**
62 | * Executes the task
63 | *
64 | * @param array $uParameters parameters
65 | *
66 | * @return int exit code
67 | */
68 | public function executeTask(array $uParameters)
69 | {
70 | $tBoris = new Boris("scabbia> ");
71 | $tBoris->start();
72 |
73 | return 0;
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/Framework/Tasks/CleanTask.php:
--------------------------------------------------------------------------------
1 |
26 | * @since 2.0.0
27 | *
28 | * @scabbia-task clean
29 | */
30 | class CleanTask extends TaskBase
31 | {
32 | /**
33 | * Registers the tasks itself to a command interpreter instance
34 | *
35 | * @param CommandInterpreter $uCommandInterpreter interpreter to be registered at
36 | *
37 | * @return void
38 | */
39 | public static function registerToCommandInterpreter(CommandInterpreter $uCommandInterpreter)
40 | {
41 | $uCommandInterpreter->addCommand(
42 | "clean",
43 | "Cleans the writable cache",
44 | []
45 | );
46 | }
47 |
48 | /**
49 | * Initializes the clean task
50 | *
51 | * @param mixed $uConfig configuration
52 | * @param IInterface $uInterface interface class
53 | *
54 | * @return CleanTask
55 | */
56 | public function __construct($uConfig, $uInterface)
57 | {
58 | parent::__construct($uConfig, $uInterface);
59 | }
60 |
61 | /**
62 | * Executes the task
63 | *
64 | * @param array $uParameters parameters
65 | *
66 | * @return int exit code
67 | */
68 | public function executeTask(array $uParameters)
69 | {
70 | $tPath = Core::$loader->basepath . "/var/cache";
71 | FileSystem::garbageCollect($tPath, ["dotFiles" => false]);
72 |
73 | $this->interface->writeColor("yellow", "done.");
74 |
75 | return 0;
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/Events/Events.php:
--------------------------------------------------------------------------------
1 |
23 | * @since 1.0.0
24 | */
25 | class Events
26 | {
27 | /** @type array event subscribers */
28 | public $events = [];
29 | /** @type array event depth */
30 | public $eventDepth = [];
31 | /** @type bool indicates the event manager is currently disabled or not */
32 | public $disabled = false;
33 |
34 |
35 | /**
36 | * Invokes an event
37 | *
38 | * @param string $uEvent name of the event
39 | * @param null|array $uEventArgs arguments for the event
40 | *
41 | * @return bool whether the event is invoked or not
42 | */
43 | public function invoke($uEvent, $uEventArgs = null)
44 | {
45 | if ($this->disabled) {
46 | return null;
47 | }
48 |
49 | if (!isset($this->events[$uEvent])) {
50 | return null;
51 | }
52 |
53 | $this->eventDepth[] = [$uEvent, $uEventArgs];
54 | $tReturn = $this->events[$uEvent]->invoke($uEventArgs);
55 | array_pop($this->eventDepth);
56 |
57 | return $tReturn;
58 | }
59 |
60 | /**
61 | * Makes a callback method subscribed to specified event
62 | *
63 | * @param string $uEvent event
64 | * @param callable $uCallback callback
65 | * @param mixed $uState state object
66 | * @param null|int $uPriority priority
67 | *
68 | * @return void
69 | */
70 | public function register($uEvent, $uCallback, $uState, $uPriority = null)
71 | {
72 | if (!isset($this->events[$uEvent])) {
73 | $this->events[$uEvent] = new Delegate();
74 | }
75 |
76 | $this->events[$uEvent]->add($uCallback, $uState, $uPriority);
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/Helpers/Runtime.php:
--------------------------------------------------------------------------------
1 |
21 | * @since 2.0.0
22 | *
23 | * @scabbia-compile
24 | */
25 | class Runtime
26 | {
27 | /**
28 | * Default variables for runtime hacks
29 | *
30 | * @type array $defaults array of default variables
31 | */
32 | public static $defaults = [
33 | ];
34 |
35 |
36 | /**
37 | * Constructor to prevent new instances of Runtime class
38 | *
39 | * @return Runtime
40 | */
41 | final private function __construct()
42 | {
43 | }
44 |
45 | /**
46 | * Clone method to prevent duplication of Runtime class
47 | *
48 | * @return Runtime
49 | */
50 | final private function __clone()
51 | {
52 | }
53 |
54 | /**
55 | * Unserialization method to prevent restoration of Runtime class
56 | *
57 | * @return Runtime
58 | */
59 | final private function __wakeup()
60 | {
61 | }
62 |
63 | /**
64 | * Sets the default variables
65 | *
66 | * @param array $uDefaults variables to be set
67 | *
68 | * @return void
69 | */
70 | public static function setDefaults($uDefaults)
71 | {
72 | self::$defaults = $uDefaults + self::$defaults;
73 | }
74 |
75 | /**
76 | * Allows on-the-fly construction of classes
77 | *
78 | * @param mixed $uCallback callback
79 | *
80 | * @return mixed callback
81 | */
82 | public static function callbacks($uCallback)
83 | {
84 | if (is_string($uCallback) && ($tPos = strrpos($uCallback, "@")) !== false) {
85 | $tClassName = substr($uCallback, 0, $tPos);
86 | $uCallback = [new $tClassName (), substr($uCallback, $tPos + 1)];
87 | }
88 |
89 | return $uCallback;
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/Config/ConfigGenerator.php:
--------------------------------------------------------------------------------
1 |
28 | * @since 2.0.0
29 | *
30 | * @scabbia-generator
31 | *
32 | * @todo FIXME include application configuration from project.yml ?
33 | */
34 | class ConfigGenerator extends GeneratorBase
35 | {
36 | /** @type Config $unifiedConfig unified configuration */
37 | public $unifiedConfig;
38 |
39 |
40 | /**
41 | * Initializes a generator
42 | *
43 | * @param GeneratorRegistry $uGeneratorRegistry generator registry
44 | *
45 | * @return GeneratorBase
46 | */
47 | public function __construct(GeneratorRegistry $uGeneratorRegistry)
48 | {
49 | parent::__construct($uGeneratorRegistry);
50 |
51 | $this->unifiedConfig = new Config();
52 | }
53 |
54 | /**
55 | * Processes a file
56 | *
57 | * @param string $uPath file path
58 | * @param string $uFileContents contents of file
59 | * @param TokenStream $uTokenStream extracted tokens wrapped with tokenstream
60 | *
61 | * @return void
62 | */
63 | public function processFile($uPath, $uFileContents, TokenStream $uTokenStream)
64 | {
65 | if (substr($uPath, -11) !== ".config.yml") {
66 | return;
67 | }
68 |
69 | $this->unifiedConfig->add($uPath);
70 | echo "Config {$uPath}\n";
71 | }
72 |
73 | /**
74 | * Finalizes generator process
75 | *
76 | * @return void
77 | */
78 | public function finalize()
79 | {
80 | $this->generatorRegistry->saveFile(
81 | "unified-config.php",
82 | $this->unifiedConfig->get(),
83 | true
84 | );
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/Mvc/Controller.php:
--------------------------------------------------------------------------------
1 |
27 | * @since 1.0.0
28 | */
29 | abstract class Controller
30 | {
31 | use BindableContainer;
32 |
33 | /** @type array $routeInfo routing information */
34 | public $routeInfo;
35 | /** @type ApplicationBase $application application */
36 | public $application;
37 | /** @type mixed $moduleConfig module configuration */
38 | public $moduleConfig;
39 | /** @type Collection $vars variables */
40 | public $vars;
41 | /** @type Delegate $prerender prerender hook */
42 | public $prerender;
43 | /** @type Delegate $postrender postrender hook */
44 | public $postrender;
45 |
46 |
47 | /**
48 | * Initializes a Controller class instance
49 | *
50 | * @return Controller
51 | */
52 | public function __construct()
53 | {
54 | $this->vars = new Collection();
55 | $this->prerender = new Delegate();
56 | $this->postrender = new Delegate();
57 | }
58 |
59 | /**
60 | * Renders a view
61 | *
62 | * @param string $uView view file
63 | * @param mixed $uModel view model
64 | * @param mixed $uController controller instance
65 | *
66 | * @return void
67 | */
68 | public function view($uView, $uModel = null, $uController = null)
69 | {
70 | if ($uModel === null) {
71 | $uModel = $this->vars->toArray();
72 | }
73 |
74 | if (strncmp($uView, "\\", 1) === 0) {
75 | Views::viewFile($uView, $uModel, $this);
76 | } else {
77 | $tNamespace = $this->application->config["modules"][$this->routeInfo["module"]]["namespace"];
78 | Views::viewFile("{$tNamespace}\\Views\\{$uView}", $uModel, $this);
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/Testing/TestsTask.php:
--------------------------------------------------------------------------------
1 |
25 | * @since 2.0.0
26 | *
27 | * @scabbia-task tests
28 | */
29 | class TestsTask extends TaskBase
30 | {
31 | /**
32 | * Registers the tasks itself to a command interpreter instance
33 | *
34 | * @param CommandInterpreter $uCommandInterpreter interpreter to be registered at
35 | *
36 | * @return void
37 | */
38 | public static function registerToCommandInterpreter(CommandInterpreter $uCommandInterpreter)
39 | {
40 | $uCommandInterpreter->addCommand(
41 | "tests",
42 | "Starts unit tests",
43 | []
44 | );
45 | }
46 |
47 | /**
48 | * Initializes the tests task
49 | *
50 | * @param mixed $uConfig configuration
51 | * @param IInterface $uInterface interface class
52 | *
53 | * @return TestsTask
54 | */
55 | public function __construct($uConfig, $uInterface)
56 | {
57 | parent::__construct($uConfig, $uInterface);
58 | }
59 |
60 | /**
61 | * Executes the task
62 | *
63 | * @param array $uParameters parameters
64 | *
65 | * @return int exit code
66 | */
67 | public function executeTask(array $uParameters)
68 | {
69 | Testing::coverageStart();
70 | $tExitCode = Testing::runUnitTests($this->config["fixtures"], $this->interface);
71 | $tCoverageReport = Testing::coverageStop();
72 |
73 | if ($tCoverageReport !== null) {
74 | $tCoverage = round($tCoverageReport["total"]["percentage"], 2) . "%";
75 | } else {
76 | $tCoverage = "unknown";
77 | }
78 |
79 | $this->interface->writeColor("green", sprintf("Code Coverage = %s", $tCoverage));
80 | $this->interface->writeColor("yellow", "done.");
81 |
82 | return $tExitCode;
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/Events/EventGenerator.php:
--------------------------------------------------------------------------------
1 |
29 | * @since 2.0.0
30 | *
31 | * @scabbia-generator
32 | */
33 | class EventGenerator extends GeneratorBase
34 | {
35 | /** @type Events $events set of events */
36 | public $events;
37 |
38 |
39 | /**
40 | * Initializes a generator
41 | *
42 | * @param GeneratorRegistry $uGeneratorRegistry generator registry
43 | *
44 | * @return GeneratorBase
45 | */
46 | public function __construct(GeneratorRegistry $uGeneratorRegistry)
47 | {
48 | parent::__construct($uGeneratorRegistry);
49 |
50 | $this->events = new Events();
51 | }
52 |
53 | /**
54 | * Processes set of annotations
55 | *
56 | * @return void
57 | */
58 | public function processAnnotations()
59 | {
60 | foreach ($this->generatorRegistry->annotationManager->get("event", true) as $tScanResult) {
61 | if ($tScanResult[AnnotationManager::LEVEL] !== "staticMethods") {
62 | continue;
63 | }
64 |
65 | foreach ($tScanResult[AnnotationManager::VALUE] as $tEvent) {
66 | $this->events->register(
67 | $tEvent["on"],
68 | [$tScanResult[AnnotationManager::SOURCE], $tScanResult[AnnotationManager::MEMBER]],
69 | null,
70 | isset($tEvent["priority"]) ? $tEvent["priority"] : null
71 | );
72 | }
73 | }
74 | }
75 |
76 | /**
77 | * Finalizes generator process
78 | *
79 | * @return void
80 | */
81 | public function finalize()
82 | {
83 | $this->generatorRegistry->saveFile(
84 | "events.php",
85 | $this->events->events,
86 | true
87 | );
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/Framework/Tasks/ServeTask.php:
--------------------------------------------------------------------------------
1 |
25 | * @since 2.0.0
26 | *
27 | * @scabbia-task serve
28 | */
29 | class ServeTask extends TaskBase
30 | {
31 | /**
32 | * Registers the tasks itself to a command interpreter instance
33 | *
34 | * @param CommandInterpreter $uCommandInterpreter interpreter to be registered at
35 | *
36 | * @return void
37 | */
38 | public static function registerToCommandInterpreter(CommandInterpreter $uCommandInterpreter)
39 | {
40 | $uCommandInterpreter->addCommand(
41 | "serve",
42 | "Runs built-in PHP server",
43 | [
44 | // type, name, description
45 | [Console::OPTION, "--host", "Binding host address"],
46 | [Console::OPTION, "--port", "Binding port number"]
47 | ]
48 | );
49 | }
50 |
51 | /**
52 | * Initializes the serve task
53 | *
54 | * @param mixed $uConfig configuration
55 | * @param IInterface $uInterface interface class
56 | *
57 | * @return ServeTask
58 | */
59 | public function __construct($uConfig, $uInterface)
60 | {
61 | parent::__construct($uConfig, $uInterface);
62 | }
63 |
64 | /**
65 | * Executes the task
66 | *
67 | * @param array $uParameters parameters
68 | *
69 | * @return int exit code
70 | */
71 | public function executeTask(array $uParameters)
72 | {
73 | $tPort = 1984;
74 |
75 | $this->interface->writeColor("yellow", sprintf("Built-in server started on port %d.", $tPort));
76 | $this->interface->writeColor("yellow", sprintf("Navigate to http://localhost:%d/\n", $tPort));
77 | $this->interface->write("Ctrl-C to stop.");
78 | passthru("\"" . PHP_BINARY . "\" -S localhost:{$tPort} -t \"" . Core::$loader->basepath . "\" index.php");
79 |
80 | return 0;
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/Documentor/DocumentGenerator.php:
--------------------------------------------------------------------------------
1 |
26 | * @since 2.0.0
27 | *
28 | * @scabbia-generator
29 | */
30 | class DocumentGenerator extends GeneratorBase
31 | {
32 | /** @type array $files set of files */
33 | public $files = [];
34 |
35 |
36 | /**
37 | * Processes a file
38 | *
39 | * @param string $uPath file path
40 | * @param string $uFileContents contents of file
41 | * @param TokenStream $uTokenStream extracted tokens wrapped with tokenstream
42 | *
43 | * @return void
44 | */
45 | public function processFile($uPath, $uFileContents, TokenStream $uTokenStream)
46 | {
47 | $tDocLines = [];
48 | $tRelativePath = substr($uPath, strlen(Core::$loader->basepath) + 1);
49 | $tDocTitle = $tRelativePath;
50 |
51 | foreach ($uTokenStream as $tToken) {
52 | if ($tToken[0] === T_COMMENT) {
53 | if (strncmp($tToken[1], "// MD-TITLE ", 12) === 0) {
54 | $tDocTitle = substr($tToken[1], 12);
55 | continue;
56 | }
57 |
58 | if (strncmp($tToken[1], "// MD ", 6) === 0) {
59 | $tDocLines[] = substr($tToken[1], 6);
60 | continue;
61 | }
62 | }
63 | }
64 |
65 | if (count($tDocLines) > 0) {
66 | $this->files[$tRelativePath] = [$tDocTitle, $tDocLines];
67 | }
68 | }
69 |
70 | /**
71 | * Finalizes generator process
72 | *
73 | * @return void
74 | */
75 | public function finalize()
76 | {
77 | $tContent = "";
78 | foreach ($this->files as $tFileKey => $tFileContent) {
79 | $tContent .= "# {$tFileContent[0]}\n";
80 |
81 | foreach ($tFileContent[1] as $tLine) {
82 | $tContent .= $tLine;
83 | }
84 |
85 | $tContent .= "\n\n";
86 | }
87 |
88 | $this->generatorRegistry->saveFile("documentor.md", $tContent);
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/tests/Yaml/Fixtures/escapedCharacters.yml:
--------------------------------------------------------------------------------
1 | test: outside double quotes
2 | yaml: |
3 | \0 \ \a \b \n
4 | php: |
5 | "\\0 \\ \\a \\b \\n"
6 | ---
7 | test: null
8 | yaml: |
9 | "\0"
10 | php: |
11 | "\x00"
12 | ---
13 | test: bell
14 | yaml: |
15 | "\a"
16 | php: |
17 | "\x07"
18 | ---
19 | test: backspace
20 | yaml: |
21 | "\b"
22 | php: |
23 | "\x08"
24 | ---
25 | test: horizontal tab (1)
26 | yaml: |
27 | "\t"
28 | php: |
29 | "\x09"
30 | ---
31 | test: horizontal tab (2)
32 | yaml: |
33 | "\ "
34 | php: |
35 | "\x09"
36 | ---
37 | test: line feed
38 | yaml: |
39 | "\n"
40 | php: |
41 | "\x0a"
42 | ---
43 | test: vertical tab
44 | yaml: |
45 | "\v"
46 | php: |
47 | "\x0b"
48 | ---
49 | test: form feed
50 | yaml: |
51 | "\f"
52 | php: |
53 | "\x0c"
54 | ---
55 | test: carriage return
56 | yaml: |
57 | "\r"
58 | php: |
59 | "\x0d"
60 | ---
61 | test: escape
62 | yaml: |
63 | "\e"
64 | php: |
65 | "\x1b"
66 | ---
67 | test: space
68 | yaml: |
69 | "\ "
70 | php: |
71 | "\x20"
72 | ---
73 | test: slash
74 | yaml: |
75 | "\/"
76 | php: |
77 | "\x2f"
78 | ---
79 | test: backslash
80 | yaml: |
81 | "\\"
82 | php: |
83 | "\\"
84 | ---
85 | test: Unicode next line
86 | yaml: |
87 | "\N"
88 | php: |
89 | "\xc2\x85"
90 | ---
91 | test: Unicode non-breaking space
92 | yaml: |
93 | "\_"
94 | php: |
95 | "\xc2\xa0"
96 | ---
97 | test: Unicode line separator
98 | yaml: |
99 | "\L"
100 | php: |
101 | "\xe2\x80\xa8"
102 | ---
103 | test: Unicode paragraph separator
104 | yaml: |
105 | "\P"
106 | php: |
107 | "\xe2\x80\xa9"
108 | ---
109 | test: Escaped 8-bit Unicode
110 | yaml: |
111 | "\x42"
112 | php: |
113 | "B"
114 | ---
115 | test: Escaped 16-bit Unicode
116 | yaml: |
117 | "\u20ac"
118 | php: |
119 | "\xe2\x82\xac"
120 | ---
121 | test: Escaped 32-bit Unicode
122 | yaml: |
123 | "\U00000043"
124 | php: |
125 | "C"
126 | ---
127 | test: Example 5.13 Escaped Characters
128 | note: |
129 | Currently throws an error parsing first line. Maybe Symfony Yaml doesn't support
130 | continuation of string across multiple lines? Keeping test here but disabled.
131 | todo: true
132 | yaml: |
133 | "Fun with \\
134 | \" \a \b \e \f \
135 | \n \r \t \v \0 \
136 | \ \_ \N \L \P \
137 | \x41 \u0041 \U00000041"
138 | php: |
139 | "Fun with \x5C\n\x22 \x07 \x08 \x1B \x0C\n\x0A \x0D \x09 \x0B \x00\n\x20 \xA0 \x85 \xe2\x80\xa8 \xe2\x80\xa9\nA A A"
140 | ---
141 | test: Double quotes with a line feed
142 | yaml: |
143 | { double: "some value\n \"some quoted string\" and 'some single quotes one'" }
144 | php: |
145 | array(
146 | 'double' => "some value\n \"some quoted string\" and 'some single quotes one'"
147 | )
148 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Scabbia2 PHP Framework Code
2 |
3 | **Scabbia2** is an open source PHP framework project which is currently on planning stage. Keep visiting [project homepage](http://scabbiafw.com/) and [repositories](https://github.com/scabbiafw/) for further updates.
4 |
5 | [This repository](https://github.com/scabbiafw/scabbia2-fw/) contains the files of Scabbia2 PHP Framework Code which is required for Scabbia2 packages to run.
6 |
7 | [](https://travis-ci.org/scabbiafw/scabbia2-fw)
8 | [](http://hhvm.h4cc.de/package/scabbiafw/scabbia2-fw)
9 | [](https://scrutinizer-ci.com/g/scabbiafw/scabbia2-fw/)
10 | [](http://squizlabs.github.io/PHP_CodeSniffer/analysis/scabbiafw/scabbia2-fw)
11 | [](https://packagist.org/packages/scabbiafw/scabbia2-fw)
12 | [](https://packagist.org/packages/scabbiafw/scabbia2-fw)
13 |
14 | ## History
15 |
16 | This project derived from [Scabbia Framework](https://github.com/larukedi/Scabbia-Framework/) with taken advantage of modern software tools. Since we don't have active GitHub users and online continous integration tools for free when we started 3 years ago, we think it's time to create a new branch of the existing framework idea/brand for a reset.
17 |
18 | 1.x versions had been under development by [Eser Ozvataf](http://eser.ozvataf.com/) for 2 years and reached version 1.5 on stable branch. You can take a look to the repository of [Scabbia 1.x](https://github.com/larukedi/Scabbia-Framework/). It's active development is frozen but small bugfixes will be available in time.
19 |
20 |
21 | ## Links
22 | - [Documentation](http://scabbiafw.com/docs/)
23 | - [Book](https://www.gitbook.io/book/larukedi/scabbia2-book) (in Turkish)
24 | - [Twitter](https://twitter.com/scabbiafw)
25 | - [Contributor List](contributors.md)
26 | - [License Information](LICENSE)
27 |
28 |
29 | ## Contributing
30 | It is publicly open for any contribution. Bugfixes, new features and extra modules are welcome. All contributions should be filed on the [scabbiafw/scabbia2-fw](http://github.com/scabbiafw/scabbia2-fw) repository.
31 |
32 | * To contribute to code: Fork the repo, push your changes to your fork, and submit a pull request.
33 | * To report a bug: If something does not work, please report it using GitHub issues.
34 | * To support: [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=BXNMWG56V6LYS)
35 |
--------------------------------------------------------------------------------
/src/Code/CompileGenerator.php:
--------------------------------------------------------------------------------
1 |
31 | * @since 2.0.0
32 | *
33 | * @scabbia-generator
34 | */
35 | class CompileGenerator extends GeneratorBase
36 | {
37 | /** @type array $classes set of classes */
38 | public $classes = [];
39 |
40 |
41 | /**
42 | * Processes set of annotations
43 | *
44 | * @return void
45 | */
46 | public function processAnnotations()
47 | {
48 | foreach ($this->generatorRegistry->annotationManager->get("scabbia-compile") as $tScanResult) {
49 | if ($tScanResult[AnnotationManager::LEVEL] !== "class") {
50 | continue;
51 | }
52 |
53 | $this->classes[] = $tScanResult[AnnotationManager::SOURCE];
54 | }
55 | }
56 |
57 | /**
58 | * Finalizes generator process
59 | *
60 | * @return void
61 | */
62 | public function finalize()
63 | {
64 | $tMinifier = new Minifier();
65 |
66 | $tBinder = new Binder();
67 | $tBinder->addFilter(
68 | "application/x-httpd-php",
69 | function ($uInput) use ($tMinifier) {
70 | $tTokenStream = TokenStream::fromString($uInput);
71 | return $tMinifier->minifyPhpSource($tTokenStream);
72 | }
73 | );
74 |
75 | foreach ($this->classes as $tClass) {
76 | $tFilePath = Core::$loader->findFile($tClass);
77 | if ($tFilePath === false) {
78 | // TODO exception
79 | throw new RuntimeException("");
80 | }
81 |
82 | // $tBinder->addContent("<" . "?php if (!class_exists(\"{$tClass}\", false)) { ?" . ">");
83 | $tBinder->addFile($tFilePath);
84 | // $tBinder->addContent("<" . "?php } ?" . ">");
85 | }
86 |
87 | $tContent = str_replace(" ?" . "><" . "?php ", " ", $tBinder->compile());
88 |
89 | $this->generatorRegistry->saveFile("compiled.php", $tContent);
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/tests/Yaml/Fixtures/sfTests.yml:
--------------------------------------------------------------------------------
1 | --- %YAML:1.0
2 | test: Multiple quoted string on one line
3 | brief: >
4 | Multiple quoted string on one line
5 | yaml: |
6 | stripped_title: { name: "foo bar", help: "bar foo" }
7 | php: |
8 | array('stripped_title' => array('name' => 'foo bar', 'help' => 'bar foo'))
9 | ---
10 | test: Empty sequence
11 | yaml: |
12 | foo: [ ]
13 | php: |
14 | array('foo' => array())
15 | ---
16 | test: Empty value
17 | yaml: |
18 | foo:
19 | php: |
20 | array('foo' => null)
21 | ---
22 | test: Inline string parsing
23 | brief: >
24 | Inline string parsing
25 | yaml: |
26 | test: ['complex: string', 'another [string]']
27 | php: |
28 | array('test' => array('complex: string', 'another [string]'))
29 | ---
30 | test: Boolean
31 | brief: >
32 | Boolean
33 | yaml: |
34 | - false
35 | - true
36 | - null
37 | - ~
38 | - 'false'
39 | - 'true'
40 | - 'null'
41 | - '~'
42 | php: |
43 | array(
44 | false,
45 | true,
46 | null,
47 | null,
48 | 'false',
49 | 'true',
50 | 'null',
51 | '~',
52 | )
53 | ---
54 | test: Empty lines in folded blocks
55 | brief: >
56 | Empty lines in folded blocks
57 | yaml: |
58 | foo:
59 | bar: |
60 | foo
61 |
62 |
63 |
64 | bar
65 | php: |
66 | array('foo' => array('bar' => "foo\n\n\n \nbar\n"))
67 | ---
68 | test: IP addresses
69 | brief: >
70 | IP addresses
71 | yaml: |
72 | foo: 10.0.0.2
73 | php: |
74 | array('foo' => '10.0.0.2')
75 | ---
76 | test: A sequence with an embedded mapping
77 | brief: >
78 | A sequence with an embedded mapping
79 | yaml: |
80 | - foo
81 | - bar: { bar: foo }
82 | php: |
83 | array('foo', array('bar' => array('bar' => 'foo')))
84 | ---
85 | test: A sequence with an unordered array
86 | brief: >
87 | A sequence with an unordered array
88 | yaml: |
89 | 1: foo
90 | 0: bar
91 | php: |
92 | array(1 => 'foo', 0 => 'bar')
93 | ---
94 | test: Octal
95 | brief: as in spec example 2.19, octal value is converted
96 | yaml: |
97 | foo: 0123
98 | php: |
99 | array('foo' => 83)
100 | ---
101 | test: Octal strings
102 | brief: Octal notation in a string must remain a string
103 | yaml: |
104 | foo: "0123"
105 | php: |
106 | array('foo' => '0123')
107 | ---
108 | test: Octal strings
109 | brief: Octal notation in a string must remain a string
110 | yaml: |
111 | foo: '0123'
112 | php: |
113 | array('foo' => '0123')
114 | ---
115 | test: Octal strings
116 | brief: Octal notation in a string must remain a string
117 | yaml: |
118 | foo: |
119 | 0123
120 | php: |
121 | array('foo' => "0123\n")
122 | ---
123 | test: Document as a simple hash
124 | brief: Document as a simple hash
125 | yaml: |
126 | { foo: bar }
127 | php: |
128 | array('foo' => 'bar')
129 | ---
130 | test: Document as a simple array
131 | brief: Document as a simple array
132 | yaml: |
133 | [ foo, bar ]
134 | php: |
135 | array('foo', 'bar')
136 |
--------------------------------------------------------------------------------
/src/Objects/FormHandler.php:
--------------------------------------------------------------------------------
1 |
23 | * @since 1.5.0
24 | */
25 | class FormHandler
26 | {
27 | /** @type array records */
28 | public $records = [];
29 |
30 |
31 | /**
32 | * @ignore
33 | */
34 | public static function getFromRequest($uChangeField, array $uFields, array $uPostData = null)
35 | {
36 | if ($uPostData === null) {
37 | $uPostData = $_POST;
38 | }
39 |
40 | $tNewInstance = new static();
41 | if (isset($uPostData[$uChangeField])) {
42 | $tChangedRecords = $uPostData[$uChangeField];
43 | } else {
44 | $tChangedRecords = [];
45 | }
46 |
47 | $tFieldValues = [];
48 | foreach ($uFields as $tField) {
49 | $tFieldValues[$tField] = $uPostData[$tField];
50 | }
51 |
52 | foreach ($tChangedRecords as $tIndex => $tChangedRecord) {
53 | $tRecord = [
54 | "index" => $tIndex,
55 | "changed" => $tChangedRecord
56 | ];
57 | foreach ($uFields as $tField) {
58 | $tRecord[$tField] = isset($tFieldValues[$tField][$tIndex]) ? $tFieldValues[$tField][$tIndex] : null;
59 | }
60 |
61 | $tNewInstance->records[] = $tRecord;
62 | }
63 |
64 | return $tNewInstance;
65 | }
66 |
67 | /**
68 | * @ignore
69 | */
70 | public function getInserted()
71 | {
72 | return Arrays::getRows($this->records, "changed", "insert");
73 | }
74 |
75 | /**
76 | * @ignore
77 | */
78 | public function getUpdated()
79 | {
80 | return Arrays::getRows($this->records, "changed", "update");
81 | }
82 |
83 | /**
84 | * @ignore
85 | */
86 | public function getDeleted()
87 | {
88 | return Arrays::getRows($this->records, "changed", "delete");
89 | }
90 |
91 | /**
92 | * @ignore
93 | */
94 | public function getNotModified()
95 | {
96 | return Arrays::getRows($this->records, "changed", "none");
97 | }
98 |
99 | /**
100 | * @ignore
101 | */
102 | public function getButDeleted()
103 | {
104 | return Arrays::getRowsBut($this->records, "changed", "delete");
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/src/Views/Views.php:
--------------------------------------------------------------------------------
1 |
24 | * @since 1.0.0
25 | */
26 | class Views
27 | {
28 | /** @type array $engines set of engines */
29 | public static $engines = [
30 | ".view.php" => ["Scabbia\\Views\\ViewEngineBase", null]
31 | ];
32 |
33 |
34 | /**
35 | * Constructor to prevent new instances of Views class
36 | *
37 | * @return Views
38 | */
39 | final private function __construct()
40 | {
41 | }
42 |
43 | /**
44 | * Clone method to prevent duplication of Views class
45 | *
46 | * @return Views
47 | */
48 | final private function __clone()
49 | {
50 | }
51 |
52 | /**
53 | * Unserialization method to prevent restoration of views class
54 | *
55 | * @return Views
56 | */
57 | final private function __wakeup()
58 | {
59 | }
60 |
61 | /**
62 | * Finds the associated view engine for a filename
63 | *
64 | * @param string $uFilename filename
65 | *
66 | * @return object|null the instance for the view engine
67 | */
68 | public static function findViewEngine($uFilename)
69 | {
70 | foreach (self::$engines as $tEngineKey => &$tEngine) {
71 | if (substr($uFilename, -strlen($tEngineKey)) === $tEngineKey) {
72 | if ($tEngine[1] === null) {
73 | $tEngine[1] = new $tEngine[0] ();
74 | }
75 |
76 | return $tEngine[1];
77 | }
78 | }
79 |
80 | return null;
81 | }
82 |
83 | /**
84 | * Renders a view
85 | *
86 | * @param string $uView view file
87 | * @param mixed $uModel view model
88 | * @param mixed $uController controller instance
89 | *
90 | * @throws UnexpectedValueException if any render engine is not associated with the extension
91 | * @return void
92 | */
93 | public static function viewFile($uView, $uModel = null, $uController = null)
94 | {
95 | $tViewFilePath = Core::findResource($uView);
96 | $tViewFileInfo = pathinfo($tViewFilePath);
97 |
98 | $tViewEngine = self::findViewEngine($tViewFilePath);
99 |
100 | if ($tViewEngine === null) {
101 | // TODO exception
102 | throw new UnexpectedValueException("");
103 | }
104 |
105 | $tViewEngine->render("{$tViewFileInfo["dirname"]}/", $tViewFileInfo["basename"], $uModel, $uController);
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/src/Interfaces/WebPage.php:
--------------------------------------------------------------------------------
1 |
23 | * @since 2.0.0
24 | */
25 | class WebPage implements IInterface
26 | {
27 | /**
28 | * Writes given message in header format
29 | *
30 | * @param int $uHeading size
31 | * @param string $uMessage message
32 | *
33 | * @return void
34 | */
35 | public function writeHeader($uHeading, $uMessage)
36 | {
37 | echo "{$uMessage}";
38 | }
39 |
40 | /**
41 | * Writes given message in specified color
42 | *
43 | * @param string $uColor color
44 | * @param string $uMessage message
45 | *
46 | * @return void
47 | */
48 | public function writeColor($uColor, $uMessage)
49 | {
50 | echo "{$uMessage}
";
51 | }
52 |
53 | /**
54 | * Writes given message
55 | *
56 | * @param string $uMessage message
57 | *
58 | * @return void
59 | */
60 | public function write($uMessage)
61 | {
62 | echo "{$uMessage}
";
63 | }
64 |
65 | /**
66 | * Outputs the array in HTML representation
67 | *
68 | * @param array $uArray Target array will be printed
69 | *
70 | * @return void
71 | */
72 | public function writeArray(array $uArray)
73 | {
74 | /** @type string $tEntryKey */
75 | /** @type array $tEntry */
76 | foreach ($uArray as $tEntryKey => $tEntry) {
77 | echo "";
78 | echo "{$tEntryKey}:
";
79 | echo "
";
80 |
81 | $tPassed = true;
82 | /** @type array $tTest */
83 | foreach ($tEntry as $tTest) {
84 | if ($tTest["failed"]) {
85 | $tPassed = false;
86 | $tColor = "red";
87 | } else {
88 | $tColor = "green";
89 | }
90 |
91 | echo "- ";
92 | echo "{$tTest["operation"]}";
93 | if ($tTest["message"] !== null) {
94 | echo ": {$tTest["message"]}";
95 | }
96 | echo "
";
97 | }
98 |
99 | echo "
";
100 |
101 | if (!$tPassed) {
102 | echo "FAILED";
103 | } else {
104 | echo "PASSED";
105 | }
106 |
107 | echo "
";
108 | }
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/tests/Security/HashTest.php:
--------------------------------------------------------------------------------
1 |
17 | *
18 | * The homepage URL for this framework is:
19 | * http://www.openwall.com/phpass/
20 | *
21 | * Modifications made:
22 | * - Scabbia Framework code styles applied.
23 | */
24 |
25 | namespace Scabbia\Tests\Security;
26 |
27 | use Scabbia\Testing\UnitTestFixture;
28 | use Scabbia\Security\Hash;
29 |
30 | /**
31 | * Tests of Hash class
32 | *
33 | * @package Scabbia\Tests\Yaml
34 | * @since 2.0.0
35 | */
36 | class HashTest extends UnitTestFixture
37 | {
38 | /**
39 | * Test fixture setup method
40 | *
41 | * @return void
42 | */
43 | protected function setUp()
44 | {
45 | }
46 |
47 | /**
48 | * Test fixture teardown method
49 | *
50 | * @return void
51 | */
52 | protected function tearDown()
53 | {
54 | }
55 |
56 | /**
57 | * Tests hashPassword and checkPassword couple
58 | *
59 | * @return void
60 | */
61 | public function testHashPassword()
62 | {
63 | $tHash = new Hash(8, false);
64 |
65 | $tPassword = "test12345";
66 | $tHashedPassword = $tHash->hashPassword($tPassword);
67 |
68 | $tCheck = $tHash->checkPassword($tPassword, $tHashedPassword);
69 | $this->assertFalse($tCheck);
70 |
71 | $tCheck = $tHash->checkPassword("test12346", $tHashedPassword);
72 | $this->assertTrue($tCheck);
73 | }
74 |
75 | /**
76 | * Tests hashPassword and checkPassword couple with weaker
77 | * portable hashes
78 | *
79 | * @return void
80 | */
81 | public function testWeakHashPassword()
82 | {
83 | $tHash = new Hash(8, true);
84 |
85 | $tPassword = "test12345";
86 | $tHashedPassword = $tHash->hashPassword($tPassword);
87 |
88 | $tCheck = $tHash->checkPassword($tPassword, $tHashedPassword);
89 | $this->assertFalse($tCheck);
90 |
91 | $tCheck = $tHash->checkPassword("test12346", $tHashedPassword);
92 | $this->assertTrue($tCheck);
93 | }
94 |
95 |
96 | /**
97 | * Tests portable hash integrity and checkPassword method
98 | *
99 | * @return void
100 | */
101 | public function testPortableHash()
102 | {
103 | $tHash = new Hash();
104 |
105 | $tPassword = "test12345";
106 | $tHashedPassword = "\$P$9IQRaTwmfeRo7ud9Fh4E2PdI0S3r.L0";
107 |
108 | $tCheck = $tHash->checkPassword($tPassword, $tHashedPassword);
109 | $this->assertFalse($tCheck);
110 |
111 | $tCheck = $tHash->checkPassword("test12346", $tHashedPassword);
112 | $this->assertTrue($tCheck);
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/src/Cli/Application.php:
--------------------------------------------------------------------------------
1 |
24 | * @since 2.0.0
25 | */
26 | class Application extends ApplicationBase
27 | {
28 | /**
29 | * Initializes an application
30 | *
31 | * @param mixed $uConfig application config
32 | * @param string $uWritablePath writable output folder
33 | *
34 | * @return Application
35 | */
36 | public function __construct($uConfig, $uWritablePath)
37 | {
38 | parent::__construct($uConfig, $uWritablePath);
39 | }
40 |
41 | /**
42 | * Gets request method
43 | *
44 | * @return array
45 | */
46 | public function getRequestMethod()
47 | {
48 | return "GET";
49 | }
50 |
51 | /**
52 | * Gets request path info
53 | *
54 | * @return array
55 | */
56 | public function getRequestPathInfo()
57 | {
58 | return "/";
59 | }
60 |
61 | /**
62 | * Gets query parameters
63 | *
64 | * @return array
65 | */
66 | public function getQueryParameters()
67 | {
68 | return [];
69 | }
70 |
71 | /**
72 | * Gets post parameters
73 | *
74 | * @return array
75 | */
76 | public function getPostParameters()
77 | {
78 | return [];
79 | }
80 |
81 | /**
82 | * Generates request
83 | *
84 | * @param string $uMethod method
85 | * @param string $uPathInfo pathinfo
86 | * @param array $uQueryParameters query parameters
87 | *
88 | * @return RequestInterface request object
89 | */
90 | public function generateRequest($uMethod, $uPathInfo, array $uQueryParameters)
91 | {
92 | // TODO get command line arguments
93 | // TODO determine module
94 | // TODO fire begin events
95 | // TODO execute application
96 | // TODO fire end events
97 | }
98 |
99 | /**
100 | * Generates request from globals
101 | *
102 | * @return RequestInterface request object
103 | */
104 | public function generateRequestFromGlobals()
105 | {
106 | return $this->generateRequest(
107 | $this->getRequestMethod(),
108 | $this->getRequestPathInfo(),
109 | $this->getQueryParameters()
110 | );
111 | }
112 |
113 | /**
114 | * Handles a request
115 | *
116 | * @param RequestInterface $uRequest request object
117 | * @param bool $uIsSubRequest whether is a sub-request or not
118 | *
119 | * @return ResponseInterface response object
120 | */
121 | public function handleRequest(RequestInterface $uRequest, $uIsSubRequest)
122 | {
123 | // TODO move generate request code here
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/src/Code/Minifier.php:
--------------------------------------------------------------------------------
1 |
25 | * @since 2.0.0
26 | */
27 | class Minifier
28 | {
29 | /**
30 | * Returns a minified php source
31 | *
32 | * @param TokenStream $uTokenStream extracted tokens wrapped with tokenstream
33 | *
34 | * @return string the minified file content
35 | */
36 | public function minifyPhpSource(TokenStream $uTokenStream)
37 | {
38 | $tReturn = "";
39 | $tLastToken = -1;
40 | $tOpenStack = [];
41 |
42 | foreach ($uTokenStream as $tToken) {
43 | // $tReturn .= PHP_EOL . token_name($tToken[0]) . PHP_EOL;
44 | if ($tToken[0] === T_OPEN_TAG) {
45 | $tReturn .= "<" . "?php ";
46 | $tOpenStack[] = $tToken[0];
47 | } elseif ($tToken[0] === T_OPEN_TAG_WITH_ECHO) {
48 | $tReturn .= "<" . "?php echo ";
49 | $tOpenStack[] = $tToken[0];
50 | } elseif ($tToken[0] === T_CLOSE_TAG) {
51 | $tLastOpen = array_pop($tOpenStack);
52 |
53 | if ($tLastOpen === T_OPEN_TAG_WITH_ECHO) {
54 | $tReturn .= "; ";
55 | } else {
56 | if ($tLastToken !== T_WHITESPACE) {
57 | $tReturn .= " ";
58 | }
59 | }
60 |
61 | $tReturn .= "?" . ">";
62 | } elseif ($tToken[0] === T_COMMENT || $tToken[0] === T_DOC_COMMENT) {
63 | // skip comments
64 | } elseif ($tToken[0] === T_WHITESPACE) {
65 | if ($tLastToken !== T_WHITESPACE &&
66 | $tLastToken !== T_OPEN_TAG &&
67 | $tLastToken !== T_OPEN_TAG_WITH_ECHO &&
68 | $tLastToken !== T_COMMENT &&
69 | $tLastToken !== T_DOC_COMMENT
70 | ) {
71 | $tReturn .= " ";
72 | }
73 | } elseif ($tToken[0] === null) {
74 | $tReturn .= $tToken[1];
75 | if ($tLastToken === T_END_HEREDOC) {
76 | $tReturn .= "\n";
77 | $tToken[0] = T_WHITESPACE;
78 | }
79 | } else {
80 | $tReturn .= $tToken[1];
81 | }
82 |
83 | $tLastToken = $tToken[0];
84 | }
85 |
86 | while (count($tOpenStack) > 0) {
87 | $tLastOpen = array_pop($tOpenStack);
88 | if ($tLastOpen === T_OPEN_TAG_WITH_ECHO) {
89 | $tReturn .= "; ";
90 | } else {
91 | if ($tLastToken !== T_WHITESPACE) {
92 | $tReturn .= " ";
93 | }
94 | }
95 |
96 | $tReturn .= "?" . ">";
97 | }
98 |
99 | return $tReturn;
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/src/Containers/IocContainer.php:
--------------------------------------------------------------------------------
1 |
23 | * @since 2.0.0
24 | */
25 | trait IocContainer
26 | {
27 | /** @type array $serviceParameters service parameters */
28 | public $serviceParameters = [];
29 | /** @type array $serviceDefinitions ioc definitions */
30 | protected $serviceDefinitions = [];
31 | /** @type array $serviceInstances shared service objects */
32 | protected $serviceInstances = [];
33 |
34 |
35 | /**
36 | * Sets a service definition
37 | *
38 | * @param string|array $uName name of the service
39 | * @param callable $uCallback callback
40 | * @param bool $uIsSharedInstance is it a shared instance
41 | *
42 | * @return void
43 | */
44 | public function setService($uName, /* callable */ $uCallback, $uIsSharedInstance = true)
45 | {
46 | foreach ((array)$tNames as $tName) {
47 | $this->serviceDefinitions[$tName] = [$uCallback, $uIsSharedInstance ? $tNames : false];
48 | }
49 | }
50 |
51 | /**
52 | * Sets a shared service object
53 | *
54 | * @param string|array $uName name of the service
55 | * @param mixed $uObject object instance
56 | *
57 | * @return void
58 | */
59 | public function setServiceInstance($uName, $uObject)
60 | {
61 | foreach ((array)$uName as $tName) {
62 | $this->serviceInstances[$uName] = $uObject;
63 | }
64 | }
65 |
66 | /**
67 | * Checks if service is defined
68 | *
69 | * @param string $uName name of the service
70 | *
71 | * @return bool
72 | */
73 | public function hasService($uName)
74 | {
75 | return isset($this->serviceInstances[$uName]) || isset($this->serviceDefinitions[$tName]);
76 | }
77 |
78 | /**
79 | * Gets the service instance if there is one, otherwise creates a service
80 | * and returns it
81 | *
82 | * @param string $uName name of the service
83 | *
84 | * @return mixed the service instance
85 | */
86 | public function getService($uName)
87 | {
88 | if (array_key_exists($uName, $this->serviceInstances)) {
89 | return $this->serviceInstances[$uName];
90 | }
91 |
92 | $tService = $this->serviceDefinitions[$uName];
93 | if (is_a($tService[0], "Closure")) {
94 | $tReturn = call_user_func($tService[0], $this->serviceParameters);
95 | } else {
96 | $tReturn = new $tService[0] (...$this->serviceParameters);
97 | }
98 |
99 | if ($tService[1] !== false) {
100 | foreach ($tService[1] as $tName) {
101 | $this->serviceInstances[$tName] = $tReturn;
102 | }
103 | }
104 |
105 | return $tReturn;
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/src/Framework/ApplicationBase.php:
--------------------------------------------------------------------------------
1 |
26 | * @since 2.0.0
27 | */
28 | abstract class ApplicationBase implements ApplicationInterface
29 | {
30 | /** @type ApplicationBase $current current application instance */
31 | public static $current = null;
32 | /** @type mixed $config application configuration */
33 | public $config;
34 | /** @type Events $events events */
35 | public $events;
36 | /** @type string $writablePath writable output folder */
37 | public $writablePath;
38 | /** @type bool $development the development flag of application is on or off */
39 | public $development;
40 |
41 |
42 | /**
43 | * Initializes an application
44 | *
45 | * @param mixed $uConfig application config
46 | * @param string $uWritablePath writable output folder
47 | *
48 | * @return ApplicationBase
49 | */
50 | public function __construct($uConfig, $uWritablePath)
51 | {
52 | $this->writablePath = $uWritablePath;
53 |
54 | $this->config = $uConfig;
55 | $this->development = $uConfig["development"];
56 |
57 | $this->events = new Events();
58 | if (file_exists($tFile = "{$this->writablePath}/events.php")) {
59 | $this->events->events = require $tFile;
60 | }
61 |
62 | // TODO initialize the proper environment
63 | if ($this->development) {
64 | error_reporting(-1);
65 | } else {
66 | error_reporting(0);
67 | }
68 |
69 | // TODO set exception handler
70 | // TODO instantiate application with variables (environment and its config [development, disableCaches])
71 | // TODO load modules
72 | // TODO execute autoexecs
73 | }
74 |
75 | /**
76 | * Generates request
77 | *
78 | * @param string $uMethod method
79 | * @param string $uPathInfo pathinfo
80 | * @param array $uQueryParameters query parameters
81 | *
82 | * @return RequestInterface request object
83 | */
84 | abstract public function generateRequest($uMethod, $uPathInfo, array $uQueryParameters);
85 |
86 | /**
87 | * Generates request from globals
88 | *
89 | * @return RequestInterface request object
90 | */
91 | abstract public function generateRequestFromGlobals();
92 |
93 | /**
94 | * Handles a request
95 | *
96 | * @param RequestInterface $uRequest request object
97 | * @param bool $uIsSubRequest whether is a sub-request or not
98 | *
99 | * @return ResponseInterface response object
100 | */
101 | abstract public function handleRequest(RequestInterface $uRequest, $uIsSubRequest);
102 | }
103 |
--------------------------------------------------------------------------------
/tests/Yaml/Fixtures/sfCompact.yml:
--------------------------------------------------------------------------------
1 | --- %YAML:1.0
2 | test: Compact notation
3 | brief: |
4 | Compact notation for sets of mappings with single element
5 | yaml: |
6 | ---
7 | # products purchased
8 | - item : Super Hoop
9 | - item : Basketball
10 | quantity: 1
11 | - item:
12 | name: Big Shoes
13 | nick: Biggies
14 | quantity: 1
15 | php: |
16 | array (
17 | array (
18 | 'item' => 'Super Hoop',
19 | ),
20 | array (
21 | 'item' => 'Basketball',
22 | 'quantity' => 1,
23 | ),
24 | array (
25 | 'item' => array(
26 | 'name' => 'Big Shoes',
27 | 'nick' => 'Biggies'
28 | ),
29 | 'quantity' => 1
30 | )
31 | )
32 | ---
33 | test: Compact notation combined with inline notation
34 | brief: |
35 | Combinations of compact and inline notation are allowed
36 | yaml: |
37 | ---
38 | items:
39 | - { item: Super Hoop, quantity: 1 }
40 | - [ Basketball, Big Shoes ]
41 | php: |
42 | array (
43 | 'items' => array (
44 | array (
45 | 'item' => 'Super Hoop',
46 | 'quantity' => 1,
47 | ),
48 | array (
49 | 'Basketball',
50 | 'Big Shoes'
51 | )
52 | )
53 | )
54 | --- %YAML:1.0
55 | test: Compact notation
56 | brief: |
57 | Compact notation for sets of mappings with single element
58 | yaml: |
59 | ---
60 | # products purchased
61 | - item : Super Hoop
62 | - item : Basketball
63 | quantity: 1
64 | - item:
65 | name: Big Shoes
66 | nick: Biggies
67 | quantity: 1
68 | php: |
69 | array (
70 | array (
71 | 'item' => 'Super Hoop',
72 | ),
73 | array (
74 | 'item' => 'Basketball',
75 | 'quantity' => 1,
76 | ),
77 | array (
78 | 'item' => array(
79 | 'name' => 'Big Shoes',
80 | 'nick' => 'Biggies'
81 | ),
82 | 'quantity' => 1
83 | )
84 | )
85 | ---
86 | test: Compact notation combined with inline notation
87 | brief: |
88 | Combinations of compact and inline notation are allowed
89 | yaml: |
90 | ---
91 | items:
92 | - { item: Super Hoop, quantity: 1 }
93 | - [ Basketball, Big Shoes ]
94 | php: |
95 | array (
96 | 'items' => array (
97 | array (
98 | 'item' => 'Super Hoop',
99 | 'quantity' => 1,
100 | ),
101 | array (
102 | 'Basketball',
103 | 'Big Shoes'
104 | )
105 | )
106 | )
107 | --- %YAML:1.0
108 | test: Compact notation
109 | brief: |
110 | Compact notation for sets of mappings with single element
111 | yaml: |
112 | ---
113 | # products purchased
114 | - item : Super Hoop
115 | - item : Basketball
116 | quantity: 1
117 | - item:
118 | name: Big Shoes
119 | nick: Biggies
120 | quantity: 1
121 | php: |
122 | array (
123 | array (
124 | 'item' => 'Super Hoop',
125 | ),
126 | array (
127 | 'item' => 'Basketball',
128 | 'quantity' => 1,
129 | ),
130 | array (
131 | 'item' => array(
132 | 'name' => 'Big Shoes',
133 | 'nick' => 'Biggies'
134 | ),
135 | 'quantity' => 1
136 | )
137 | )
138 | ---
139 | test: Compact notation combined with inline notation
140 | brief: |
141 | Combinations of compact and inline notation are allowed
142 | yaml: |
143 | ---
144 | items:
145 | - { item: Super Hoop, quantity: 1 }
146 | - [ Basketball, Big Shoes ]
147 | php: |
148 | array (
149 | 'items' => array (
150 | array (
151 | 'item' => 'Super Hoop',
152 | 'quantity' => 1,
153 | ),
154 | array (
155 | 'Basketball',
156 | 'Big Shoes'
157 | )
158 | )
159 | )
160 |
--------------------------------------------------------------------------------
/src/Containers/BindableContainer.php:
--------------------------------------------------------------------------------
1 |
23 | * @since 2.0.0
24 | */
25 | trait BindableContainer
26 | {
27 | /** @type array $loadedObjects loaded objects */
28 | public static $loadedObjects = [];
29 | /** @type array $sharedBindings shared bindings registry */
30 | public static $sharedBindings = [];
31 |
32 |
33 | /**
34 | * Loads and stores a class
35 | *
36 | * @param string|object $uClass object or class name
37 | * @param array $uParameters parameters
38 | *
39 | * @return object class instance
40 | */
41 | public static function load($uClass, array $uParameters = [])
42 | {
43 | if (is_object($uClass)) {
44 | $tClassName = get_class($uClass);
45 |
46 | if (!isset(BindableContainer::$loadedObjects[$tClassName])) {
47 | BindableContainer::$loadedObjects[$tClassName] = $uClass;
48 | }
49 |
50 | return BindableContainer::$loadedObjects[$tClassName];
51 | }
52 |
53 | if (!isset(BindableContainer::$loadedObjects[$uClass])) {
54 | BindableContainer::$loadedObjects[$uClass] = new $uClass (...$uParameters);
55 | }
56 |
57 | return BindableContainer::$loadedObjects[$uClass];
58 | }
59 |
60 | /**
61 | * Binds a class instance to current context of the class
62 | *
63 | * @param string|object $uClass class
64 | * @param string|null $uMemberName member name
65 | * @param array $uParameters parameters
66 | *
67 | * @return void
68 | */
69 | public function bind($uClass, $uMemberName = null, array $uParameters = [])
70 | {
71 | if ($uMemberName === null) {
72 | if (is_object($uClass)) {
73 | $tClassName = get_class($uClass);
74 | } else {
75 | $tClassName = $uClass;
76 | }
77 |
78 | if (($tPos = strrpos($tClassName, "\\")) !== false) {
79 | $uMemberName = lcfirst(substr($tClassName, $tPos + 1));
80 | } else {
81 | $uMemberName = lcfirst($tClassName);
82 | }
83 | }
84 |
85 | $this->{$uMemberName} = BindableContainer::load($uClass, $uParameters);
86 | }
87 |
88 | /**
89 | * Magic method for bindable containers
90 | *
91 | * @param string $uName name of the shared object
92 | *
93 | * @return mixed the shared object
94 | */
95 | public function __get($uName)
96 | {
97 | if (!array_key_exists($uName, static::$sharedBindings)) {
98 | return null;
99 | }
100 |
101 | $tSharedBinding = (array)static::$sharedBindings[$uName];
102 |
103 | if (count($tSharedBinding) === 1) {
104 | $tReturn = BindableContainer::load($tSharedBinding[0]);
105 | } else {
106 | $tReturn = BindableContainer::load($tSharedBinding[0], $tSharedBinding[1]);
107 | }
108 |
109 | $this->{$uName} = $tReturn;
110 |
111 | return $tReturn;
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/src/Generators/GeneratorRegistry.php:
--------------------------------------------------------------------------------
1 |
26 | * @since 2.0.0
27 | */
28 | class GeneratorRegistry
29 | {
30 | /** @type mixed $applicationConfig application config */
31 | public $applicationConfig;
32 | /** @type string $applicationWritablePath application writable path */
33 | public $applicationWritablePath;
34 | /** @type array $generators set of generators */
35 | public $generators = [];
36 | /** @type AnnotationManager|null $annotationManager annotation manager */
37 | public $annotationManager = null;
38 |
39 |
40 | /**
41 | * Initializes a generator registry
42 | *
43 | * @param mixed $uApplicationConfig application config
44 | * @param string $uApplicationWritablePath application writable path
45 | *
46 | * @return GeneratorRegistry
47 | */
48 | public function __construct($uApplicationConfig, $uApplicationWritablePath)
49 | {
50 | $this->applicationConfig = $uApplicationConfig;
51 | $this->applicationWritablePath = $uApplicationWritablePath;
52 | }
53 |
54 | /**
55 | * Executes available generators
56 | *
57 | * @return void
58 | */
59 | public function execute()
60 | {
61 | $this->annotationManager = new AnnotationManager($this->applicationWritablePath);
62 | $this->annotationManager->load();
63 |
64 | foreach ($this->annotationManager->get("scabbia-generator") as $tScanResult) {
65 | if ($tScanResult[1] !== "class") {
66 | continue;
67 | }
68 |
69 | $this->generators[$tScanResult[0]] = new $tScanResult[0] ($this);
70 | }
71 |
72 | foreach ($this->generators as $tGenerator) {
73 | $tGenerator->processAnnotations();
74 | }
75 |
76 | // TODO processFile
77 | // $tGenerator->processFile($uPath, $uFileContents, TokenStream $uTokenStream);
78 |
79 | foreach ($this->generators as $tGenerator) {
80 | $tGenerator->finalize();
81 | }
82 | }
83 |
84 | /**
85 | * Saves a file into writable folder
86 | *
87 | * @param string $uFilename filename
88 | * @param mixed $uContent file content to be written
89 | * @param bool $uSaveAsPHP saves file contents as php file if it is true
90 | *
91 | * @return void
92 | */
93 | public function saveFile($uFilename, $uContent, $uSaveAsPHP = false)
94 | {
95 | if ($uSaveAsPHP) {
96 | FileSystem::writePhpFile(
97 | Core::translateVariables($this->applicationWritablePath . "/{$uFilename}"),
98 | $uContent
99 | );
100 |
101 | return;
102 | }
103 |
104 | FileSystem::write(
105 | Core::translateVariables($this->applicationWritablePath . "/{$uFilename}"),
106 | $uContent
107 | );
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/src/Objects/Binder.php:
--------------------------------------------------------------------------------
1 |
23 | * @since 1.5.0
24 | */
25 | class Binder
26 | {
27 | /** @type array filters */
28 | public $filters = [];
29 |
30 | /** @type array contents */
31 | public $contents = [];
32 |
33 | /** @type string output */
34 | public $output;
35 |
36 |
37 | /**
38 | * Adds a content
39 | *
40 | * @param string $uContent content
41 | * @param string $uMimeType mimetype of content
42 | *
43 | * @return void
44 | */
45 | public function addContent($uContent, $uMimeType = "text/plain")
46 | {
47 | $this->contents[] = ["direct", $uMimeType, $uContent];
48 | }
49 |
50 | /**
51 | * Adds a callback
52 | *
53 | * @param callable $uCallback callback
54 | * @param string $uMimeType mimetype of content
55 | *
56 | * @return void
57 | */
58 | public function addCallback($uCallback, $uMimeType = "text/plain")
59 | {
60 | $this->contents[] = ["callback", $uMimeType, $uCallback];
61 | }
62 |
63 | /**
64 | * Adds a file
65 | *
66 | * @param string $uPath path of the content
67 | *
68 | * @return void
69 | */
70 | public function addFile($uPath)
71 | {
72 | $tExtension = pathinfo($uPath, PATHINFO_EXTENSION);
73 | $this->contents[] = ["file", FileSystem::getMimetype($tExtension), $uPath];
74 | }
75 |
76 | /**
77 | * Adds a callback
78 | *
79 | * @param string $uMimeType mimetype to be registered
80 | * @param callable $uCallback callback
81 | *
82 | * @return void
83 | */
84 | public function addFilter($uMimeType, $uCallback)
85 | {
86 | $this->filters[$uMimeType] = $uCallback;
87 | }
88 |
89 | /**
90 | * Compiles given configuration files into single configuration
91 | *
92 | * @param null|string $uMimeTypeFilter only compiles filtered mimetypes
93 | *
94 | * @return void
95 | */
96 | public function compile($uMimeTypeFilter = null)
97 | {
98 | if (count($this->contents) > 0) {
99 | $this->output = "";
100 |
101 | foreach ($this->contents as $tContent) {
102 | if ($uMimeTypeFilter !== null && $uMimeTypeFilter !== $tContent[1]) {
103 | continue;
104 | }
105 |
106 | if ($tContent[0] === "direct") {
107 | $tOutput = $tContent[2];
108 | } elseif ($tContent[0] === "callback") {
109 | $tOutput = call_user_func($tContent[2]);
110 | } elseif ($tContent[0] === "file") {
111 | $tOutput = FileSystem::read($tContent[2]);
112 | }
113 |
114 | if (isset($this->filters[$tContent[1]])) {
115 | $tOutput = call_user_func($this->filters[$tContent[1]], $tOutput);
116 | }
117 |
118 | $this->output .= $tOutput;
119 | }
120 |
121 | $this->contents = [];
122 | }
123 |
124 | return $this->output;
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/src/Interfaces/Console.php:
--------------------------------------------------------------------------------
1 |
23 | * @since 2.0.0
24 | *
25 | * @todo add stdin features
26 | */
27 | class Console implements IInterface
28 | {
29 | /**
30 | * Writes given message in header format
31 | *
32 | * @param int $uHeading size
33 | * @param string $uMessage message
34 | *
35 | * @return void
36 | */
37 | public function writeHeader($uHeading, $uMessage)
38 | {
39 | if ($uHeading === 1) {
40 | $tChar = "=";
41 | } else {
42 | $tChar = "-";
43 | }
44 |
45 | echo $uMessage, PHP_EOL, str_repeat($tChar, strlen($uMessage)), PHP_EOL;
46 |
47 | if ($uHeading === 1) {
48 | echo PHP_EOL;
49 | }
50 | }
51 |
52 | /**
53 | * Writes given message in specified color
54 | *
55 | * @param string $uColor color
56 | * @param string $uMessage message
57 | *
58 | * @return void
59 | */
60 | public function writeColor($uColor, $uMessage)
61 | {
62 | if (strncasecmp(PHP_OS, "WIN", 3) === 0) {
63 | echo $uMessage, PHP_EOL;
64 | return;
65 | }
66 |
67 | if ($uColor === "black") {
68 | $tColor = "[0;30m";
69 | } elseif ($uColor === "darkgray") {
70 | $tColor = "[1;30m";
71 | } elseif ($uColor === "blue") {
72 | $tColor = "[0;34m";
73 | } elseif ($uColor === "lightblue") {
74 | $tColor = "[1;34m";
75 | } elseif ($uColor === "green") {
76 | $tColor = "[0;32m";
77 | } elseif ($uColor === "lightgreen") {
78 | $tColor = "[1;32m";
79 | } elseif ($uColor === "cyan") {
80 | $tColor = "[0;36m";
81 | } elseif ($uColor === "lightcyan") {
82 | $tColor = "[1;36m";
83 | } elseif ($uColor === "red") {
84 | $tColor = "[0;31m";
85 | } elseif ($uColor === "lightred") {
86 | $tColor = "[1;31m";
87 | } elseif ($uColor === "purple") {
88 | $tColor = "[0;35m";
89 | } elseif ($uColor === "lightpurple") {
90 | $tColor = "[1;35m";
91 | } elseif ($uColor === "brown") {
92 | $tColor = "[0;33m";
93 | } elseif ($uColor === "yellow") {
94 | $tColor = "[1;33m";
95 | } elseif ($uColor === "white") {
96 | $tColor = "[1;37m";
97 | } else /* if ($uColor === "lightgray") */ {
98 | $tColor = "[0;37m";
99 | }
100 |
101 | echo "\033", $tColor, $uMessage, "\033[0m", PHP_EOL;
102 | }
103 |
104 | /**
105 | * Writes given message
106 | *
107 | * @param string $uMessage message
108 | *
109 | * @return void
110 | */
111 | public function write($uMessage)
112 | {
113 | echo $uMessage, PHP_EOL;
114 | }
115 |
116 | /**
117 | * Outputs the array to console
118 | *
119 | * @param array $uArray Target array will be printed
120 | *
121 | * @return void
122 | */
123 | public function writeArray(array $uArray)
124 | {
125 | print_r($uArray);
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/src/Objects/BufferedUpdateCollection.php:
--------------------------------------------------------------------------------
1 |
21 | * @since 1.5.0
22 | */
23 | class BufferedUpdateCollection
24 | {
25 | /** @type array items */
26 | public $items;
27 | /** @type array queue */
28 | public $queue;
29 | /** @type callable update function */
30 | public $updateFunc;
31 |
32 |
33 | /**
34 | * Initializes a BufferedUpdateCollection class instance
35 | *
36 | * @param callable $uUpdateFunc update function
37 | * @param array $uArray initial items
38 | *
39 | * @return BufferedUpdateCollection
40 | */
41 | public function __construct(/* callable */ $uUpdateFunc, array $uArray = [])
42 | {
43 | $this->updateFunc = $uUpdateFunc;
44 | $this->items = $uArray;
45 | $this->queue = [];
46 | }
47 |
48 | /**
49 | * Enqueues given keys into collection to get all elements at the same time
50 | *
51 | * @param string $uKey key for element
52 | *
53 | * @return void
54 | */
55 | public function enqueue($uKey)
56 | {
57 | foreach ((array)$uKey as $tKey) {
58 | if (in_array($tKey, $this->queue, true) || $this->keyExists($tKey)) {
59 | continue;
60 | }
61 |
62 | $this->queue[] = $tKey;
63 | }
64 | }
65 |
66 | /**
67 | * Updates the collection by executing update function
68 | *
69 | * @return void
70 | */
71 | public function update()
72 | {
73 | if ($this->updateFunc === null) {
74 | return;
75 | }
76 |
77 | if (count($this->queue) === 0) {
78 | return;
79 | }
80 |
81 | $this->items += call_user_func($this->updateFunc, $this->queue);
82 | $this->queue = [];
83 | }
84 |
85 | /**
86 | * Gets the specified element in the collection
87 | *
88 | * @param mixed $uKey key for element
89 | * @param mixed $uDefault default value if the key does not exist
90 | *
91 | * @return mixed the element or the default
92 | */
93 | public function get($uKey, $uDefault = null)
94 | {
95 | if (in_array($uKey, $this->queue, true)) {
96 | $this->update();
97 | }
98 |
99 | if (array_key_exists($uKey, $this->items)) {
100 | return $this->items[$uKey];
101 | }
102 |
103 | return $uDefault;
104 | }
105 |
106 | /**
107 | * Gets the set of specified elements in the collection
108 | *
109 | * @param mixed $uKeys keys for elements
110 | *
111 | * @return mixed the set of elements
112 | */
113 | public function getRange(array $uKeys)
114 | {
115 | $tItems = [];
116 |
117 | foreach ($uKeys as $tKey) {
118 | if (in_array($tKey, $this->queue, true)) {
119 | $this->update();
120 | }
121 |
122 | if (array_key_exists($tKey, $this->items)) {
123 | $tItems[$tKey] = $this->items[$tKey];
124 | }
125 | }
126 |
127 | return $tItems;
128 | }
129 |
130 | /**
131 | * Enqueues the keys then updates the collection in order
132 | * to get requested elements back
133 | *
134 | * @param mixed $uKeys keys for elements
135 | *
136 | * @return mixed the set of elements
137 | */
138 | public function enqueueAndGetRange(array $uKeys)
139 | {
140 | $this->enqueue($uKeys);
141 | return $this->getRange($uKeys);
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/src/Events/Delegate.php:
--------------------------------------------------------------------------------
1 |
24 | * @since 2.0.0
25 | */
26 | class Delegate
27 | {
28 | /** @type array list of callbacks */
29 | public $callbacks = null;
30 | /** @type mixed expected return value for interruption */
31 | public $expectedReturn;
32 |
33 |
34 | /**
35 | * Constructs a new delegate in order to assign it to a member
36 | *
37 | * @param mixed $uExpectedReturn Expected return value for interruption
38 | *
39 | * @return Delegate a delegate
40 | */
41 | public static function assign($uExpectedReturn = false)
42 | {
43 | $tNewInstance = new static($uExpectedReturn);
44 |
45 | return function (/* callable */ $uCallback = null, $uState = null, $uPriority = 10) use ($tNewInstance) {
46 | if ($uCallback !== null) {
47 | $tNewInstance->add($uCallback, $uState, $uPriority);
48 | }
49 |
50 | return $tNewInstance;
51 | };
52 | }
53 |
54 | // @codingStandardsIgnoreStart
55 | /**
56 | * Unserializes an instance of delegate
57 | *
58 | * @param array $uPropertyBag properties set of unserialized object
59 | *
60 | * @return Delegate a delegate
61 | */
62 | public static function __set_state(array $uPropertyBag)
63 | {
64 | $tNewInstance = new static($uPropertyBag["expectedReturn"]);
65 | $tNewInstance->callbacks = $uPropertyBag["callbacks"];
66 |
67 | return $tNewInstance;
68 | }
69 | // @codingStandardsIgnoreEnd
70 |
71 | /**
72 | * Constructs a new instance of delegate
73 | *
74 | * @param mixed $uExpectedReturn Expected return value for interruption
75 | *
76 | * @return Delegate
77 | */
78 | public function __construct($uExpectedReturn = false)
79 | {
80 | $this->expectedReturn = $uExpectedReturn;
81 | }
82 |
83 | /**
84 | * Adds a callback to delegate
85 | *
86 | * @param callback $uCallback callback method
87 | * @param mixed $uState state object
88 | * @param null|int $uPriority priority level
89 | *
90 | * @return void
91 | */
92 | public function add(/* callable */ $uCallback, $uState = null, $uPriority = null)
93 | {
94 | // TODO SplPriorityQueue has a problem with serialization
95 | /*
96 | if ($this->callbacks === null) {
97 | $this->callbacks = new SplPriorityQueue();
98 | }
99 |
100 | if ($uPriority === null) {
101 | $uPriority = 10;
102 | }
103 |
104 | $this->callbacks->insert([$uCallback, $uState], $uPriority);
105 | */
106 |
107 | if ($this->callbacks === null) {
108 | $this->callbacks = [];
109 | }
110 |
111 | $this->callbacks[] = [$uCallback, $uState];
112 | }
113 |
114 | /**
115 | * Invokes the event-chain execution
116 | *
117 | * @param array $uArgs arguments
118 | *
119 | * @return bool whether the execution is broken or not
120 | */
121 | public function invoke(...$uArgs)
122 | {
123 | if ($this->callbacks !== null) {
124 | foreach ($this->callbacks as $tCallback) {
125 | // array_unshift($tEventArgs, $tCallback[1]);
126 |
127 | if (call_user_func($tCallback[0], ...$uArgs) === $this->expectedReturn) {
128 | return false;
129 | }
130 | }
131 | }
132 |
133 | return true;
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/src/Testing/Testing.php:
--------------------------------------------------------------------------------
1 |
27 | * @since 2.0.0
28 | */
29 | class Testing
30 | {
31 | /**
32 | * Runs given unit tests
33 | *
34 | * @param array $uTestClasses set of unit test classes
35 | * @param IInterface $uInterface interface class
36 | *
37 | * @return int exit code
38 | */
39 | public static function runUnitTests(array $uTestClasses, $uInterface = null)
40 | {
41 | if ($uInterface === null) {
42 | if (PHP_SAPI === "cli") {
43 | $uInterface = new Console();
44 | } else {
45 | $uInterface = new WebPage();
46 | }
47 | }
48 |
49 | $tIsEverFailed = false;
50 |
51 | $uInterface->writeHeader(1, "Unit Tests");
52 |
53 | /** @type string $tTestClass */
54 | foreach ($uTestClasses as $tTestClass) {
55 | $uInterface->writeHeader(2, $tTestClass);
56 |
57 | $tInstance = new $tTestClass ();
58 | $tInstance->test();
59 |
60 | if ($tInstance->isFailed) {
61 | $tIsEverFailed = true;
62 | }
63 |
64 | // $uInterface->writeArray($tInstance->testReport);
65 | foreach ($tInstance->testReport as $tTestName => $tTest) {
66 | $tFails = [];
67 | foreach ($tTest as $tTestCase) {
68 | if ($tTestCase["failed"]) {
69 | $tFails[] = [
70 | "operation" => $tTestCase["operation"],
71 | "message" => $tTestCase["message"]
72 | ];
73 | }
74 | }
75 |
76 | if (count($tFails) === 0) {
77 | $uInterface->write(sprintf("[OK] %s", $tTestName));
78 | } else {
79 | $uInterface->writeColor("red", sprintf("[FAIL] %s", $tTestName));
80 | $uInterface->writeArray($tFails);
81 | }
82 | }
83 | }
84 |
85 | if ($tIsEverFailed) {
86 | return 1;
87 | }
88 |
89 | return 0;
90 | }
91 |
92 | /**
93 | * Starts the code coverage
94 | *
95 | * @return void
96 | */
97 | public static function coverageStart()
98 | {
99 | if (!extension_loaded("xdebug")) {
100 | return;
101 | }
102 |
103 | xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE);
104 | }
105 |
106 | /**
107 | * Stops the code coverage
108 | *
109 | * @return array results
110 | */
111 | public static function coverageStop()
112 | {
113 | if (!extension_loaded("xdebug")) {
114 | return null;
115 | }
116 |
117 | $tCoverageData = xdebug_get_code_coverage();
118 | xdebug_stop_code_coverage();
119 |
120 | $tFinal = [
121 | "files" => [],
122 | "total" => [ "coveredLines" => 0, "totalLines" => 0 ]
123 | ];
124 |
125 | foreach ($tCoverageData as $tPath => $tLines) {
126 | $tFileCoverage = [
127 | "path" => $tPath,
128 | "coveredLines" => array_keys($tLines),
129 | "totalLines" => FileSystem::getFileLineCount($tPath)
130 | ];
131 |
132 | $tFinal["files"][] = $tFileCoverage;
133 | $tFinal["total"]["coveredLines"] += count($tFileCoverage["coveredLines"]);
134 | $tFinal["total"]["totalLines"] += $tFileCoverage["totalLines"];
135 | }
136 |
137 | $tFinal["total"]["percentage"] = ($tFinal["total"]["coveredLines"] * 100) / $tFinal["total"]["totalLines"];
138 |
139 | return $tFinal;
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/tests/Yaml/Fixtures/YtsBasicTests.yml:
--------------------------------------------------------------------------------
1 | --- %YAML:1.0
2 | test: Simple Sequence
3 | brief: |
4 | You can specify a list in YAML by placing each
5 | member of the list on a new line with an opening
6 | dash. These lists are called sequences.
7 | yaml: |
8 | - apple
9 | - banana
10 | - carrot
11 | php: |
12 | array('apple', 'banana', 'carrot')
13 | ---
14 | test: Nested Sequences
15 | brief: |
16 | You can include a sequence within another
17 | sequence by giving the sequence an empty
18 | dash, followed by an indented list.
19 | yaml: |
20 | -
21 | - foo
22 | - bar
23 | - baz
24 | php: |
25 | array(array('foo', 'bar', 'baz'))
26 | ---
27 | test: Mixed Sequences
28 | brief: |
29 | Sequences can contain any YAML data,
30 | including strings and other sequences.
31 | yaml: |
32 | - apple
33 | -
34 | - foo
35 | - bar
36 | - x123
37 | - banana
38 | - carrot
39 | php: |
40 | array('apple', array('foo', 'bar', 'x123'), 'banana', 'carrot')
41 | ---
42 | test: Deeply Nested Sequences
43 | brief: |
44 | Sequences can be nested even deeper, with each
45 | level of indentation representing a level of
46 | depth.
47 | yaml: |
48 | -
49 | -
50 | - uno
51 | - dos
52 | php: |
53 | array(array(array('uno', 'dos')))
54 | ---
55 | test: Simple Mapping
56 | brief: |
57 | You can add a keyed list (also known as a dictionary or
58 | hash) to your document by placing each member of the
59 | list on a new line, with a colon separating the key
60 | from its value. In YAML, this type of list is called
61 | a mapping.
62 | yaml: |
63 | foo: whatever
64 | bar: stuff
65 | php: |
66 | array('foo' => 'whatever', 'bar' => 'stuff')
67 | ---
68 | test: Sequence in a Mapping
69 | brief: |
70 | A value in a mapping can be a sequence.
71 | yaml: |
72 | foo: whatever
73 | bar:
74 | - uno
75 | - dos
76 | php: |
77 | array('foo' => 'whatever', 'bar' => array('uno', 'dos'))
78 | ---
79 | test: Nested Mappings
80 | brief: |
81 | A value in a mapping can be another mapping.
82 | yaml: |
83 | foo: whatever
84 | bar:
85 | fruit: apple
86 | name: steve
87 | sport: baseball
88 | php: |
89 | array(
90 | 'foo' => 'whatever',
91 | 'bar' => array(
92 | 'fruit' => 'apple',
93 | 'name' => 'steve',
94 | 'sport' => 'baseball'
95 | )
96 | )
97 | ---
98 | test: Mixed Mapping
99 | brief: |
100 | A mapping can contain any assortment
101 | of mappings and sequences as values.
102 | yaml: |
103 | foo: whatever
104 | bar:
105 | -
106 | fruit: apple
107 | name: steve
108 | sport: baseball
109 | - more
110 | -
111 | python: rocks
112 | perl: papers
113 | ruby: scissorses
114 | php: |
115 | array(
116 | 'foo' => 'whatever',
117 | 'bar' => array(
118 | array(
119 | 'fruit' => 'apple',
120 | 'name' => 'steve',
121 | 'sport' => 'baseball'
122 | ),
123 | 'more',
124 | array(
125 | 'python' => 'rocks',
126 | 'perl' => 'papers',
127 | 'ruby' => 'scissorses'
128 | )
129 | )
130 | )
131 | ---
132 | test: Mapping-in-Sequence Shortcut
133 | todo: true
134 | brief: |
135 | If you are adding a mapping to a sequence, you
136 | can place the mapping on the same line as the
137 | dash as a shortcut.
138 | yaml: |
139 | - work on YAML.py:
140 | - work on Store
141 | php: |
142 | array(array('work on YAML.py' => array('work on Store')))
143 | ---
144 | test: Sequence-in-Mapping Shortcut
145 | todo: true
146 | brief: |
147 | The dash in a sequence counts as indentation, so
148 | you can add a sequence inside of a mapping without
149 | needing spaces as indentation.
150 | yaml: |
151 | allow:
152 | - 'localhost'
153 | - '%.sourceforge.net'
154 | - '%.freepan.org'
155 | php: |
156 | array('allow' => array('localhost', '%.sourceforge.net', '%.freepan.org'))
157 | ---
158 | todo: true
159 | test: Merge key
160 | brief: |
161 | A merge key ('<<') can be used in a mapping to insert other mappings. If
162 | the value associated with the merge key is a mapping, each of its key/value
163 | pairs is inserted into the current mapping.
164 | yaml: |
165 | mapping:
166 | name: Joe
167 | job: Accountant
168 | <<:
169 | age: 38
170 | php: |
171 | array(
172 | 'mapping' =>
173 | array(
174 | 'name' => 'Joe',
175 | 'job' => 'Accountant',
176 | 'age' => 38
177 | )
178 | )
179 |
--------------------------------------------------------------------------------
/tests/Yaml/Fixtures/YtsFoldedScalars.yml:
--------------------------------------------------------------------------------
1 | --- %YAML:1.0
2 | test: Single ending newline
3 | brief: >
4 | A pipe character, followed by an indented
5 | block of text is treated as a literal
6 | block, in which newlines are preserved
7 | throughout the block, including the final
8 | newline.
9 | yaml: |
10 | ---
11 | this: |
12 | Foo
13 | Bar
14 | php: |
15 | array('this' => "Foo\nBar\n")
16 | ---
17 | test: The '+' indicator
18 | brief: >
19 | The '+' indicator says to keep newlines at the end of text
20 | blocks.
21 | yaml: |
22 | normal: |
23 | extra new lines not kept
24 |
25 | preserving: |+
26 | extra new lines are kept
27 |
28 |
29 | dummy: value
30 | php: |
31 | array(
32 | 'normal' => "extra new lines not kept\n",
33 | 'preserving' => "extra new lines are kept\n\n\n",
34 | 'dummy' => 'value'
35 | )
36 | ---
37 | test: Three trailing newlines in literals
38 | brief: >
39 | To give you more control over how space
40 | is preserved in text blocks, YAML has
41 | the keep '+' and chomp '-' indicators.
42 | The keep indicator will preserve all
43 | ending newlines, while the chomp indicator
44 | will strip all ending newlines.
45 | yaml: |
46 | clipped: |
47 | This has one newline.
48 |
49 |
50 |
51 | same as "clipped" above: "This has one newline.\n"
52 |
53 | stripped: |-
54 | This has no newline.
55 |
56 |
57 |
58 | same as "stripped" above: "This has no newline."
59 |
60 | kept: |+
61 | This has four newlines.
62 |
63 |
64 |
65 | same as "kept" above: "This has four newlines.\n\n\n\n"
66 | php: |
67 | array(
68 | 'clipped' => "This has one newline.\n",
69 | 'same as "clipped" above' => "This has one newline.\n",
70 | 'stripped' => 'This has no newline.',
71 | 'same as "stripped" above' => 'This has no newline.',
72 | 'kept' => "This has four newlines.\n\n\n\n",
73 | 'same as "kept" above' => "This has four newlines.\n\n\n\n"
74 | )
75 | ---
76 | test: Extra trailing newlines with spaces
77 | todo: true
78 | brief: >
79 | Normally, only a single newline is kept
80 | from the end of a literal block, unless the
81 | keep '+' character is used in combination
82 | with the pipe. The following example
83 | will preserve all ending whitespace
84 | since the last line of both literal blocks
85 | contains spaces which extend past the indentation
86 | level.
87 | yaml: |
88 | ---
89 | this: |
90 | Foo
91 |
92 |
93 | kept: |+
94 | Foo
95 |
96 |
97 | php: |
98 | array('this' => "Foo\n\n \n",
99 | 'kept' => "Foo\n\n \n" )
100 |
101 | ---
102 | test: Folded Block in a Sequence
103 | brief: >
104 | A greater-then character, followed by an indented
105 | block of text is treated as a folded block, in
106 | which lines of text separated by a single newline
107 | are concatenated as a single line.
108 | yaml: |
109 | ---
110 | - apple
111 | - banana
112 | - >
113 | can't you see
114 | the beauty of yaml?
115 | hmm
116 | - dog
117 | php: |
118 | array(
119 | 'apple',
120 | 'banana',
121 | "can't you see the beauty of yaml? hmm\n",
122 | 'dog'
123 | )
124 | ---
125 | test: Folded Block as a Mapping Value
126 | brief: >
127 | Both literal and folded blocks can be
128 | used in collections, as values in a
129 | sequence or a mapping.
130 | yaml: |
131 | ---
132 | quote: >
133 | Mark McGwire's
134 | year was crippled
135 | by a knee injury.
136 | source: espn
137 | php: |
138 | array(
139 | 'quote' => "Mark McGwire's year was crippled by a knee injury.\n",
140 | 'source' => 'espn'
141 | )
142 | ---
143 | test: Three trailing newlines in folded blocks
144 | brief: >
145 | The keep and chomp indicators can also
146 | be applied to folded blocks.
147 | yaml: |
148 | clipped: >
149 | This has one newline.
150 |
151 |
152 |
153 | same as "clipped" above: "This has one newline.\n"
154 |
155 | stripped: >-
156 | This has no newline.
157 |
158 |
159 |
160 | same as "stripped" above: "This has no newline."
161 |
162 | kept: >+
163 | This has four newlines.
164 |
165 |
166 |
167 | same as "kept" above: "This has four newlines.\n\n\n\n"
168 | php: |
169 | array(
170 | 'clipped' => "This has one newline.\n",
171 | 'same as "clipped" above' => "This has one newline.\n",
172 | 'stripped' => 'This has no newline.',
173 | 'same as "stripped" above' => 'This has no newline.',
174 | 'kept' => "This has four newlines.\n\n\n\n",
175 | 'same as "kept" above' => "This has four newlines.\n\n\n\n"
176 | )
177 |
--------------------------------------------------------------------------------
/src/Tasks/Tasks.php:
--------------------------------------------------------------------------------
1 |
29 | * @since 1.0.0
30 | */
31 | class Tasks
32 | {
33 | /** @type object $tasks the tasks read from tasks file */
34 | public static $tasks = [];
35 | /** @type array $config tasks configuration */
36 | public static $config = null;
37 |
38 |
39 | /**
40 | * Constructor to prevent new instances of Tasks class
41 | *
42 | * @return Tasks
43 | */
44 | final private function __construct()
45 | {
46 | }
47 |
48 | /**
49 | * Clone method to prevent duplication of Tasks class
50 | *
51 | * @return Tasks
52 | */
53 | final private function __clone()
54 | {
55 | }
56 |
57 | /**
58 | * Unserialization method to prevent restoration of Tasks class
59 | *
60 | * @return Tasks
61 | */
62 | final private function __wakeup()
63 | {
64 | }
65 |
66 | /**
67 | * Loads the tasks file.
68 | *
69 | * @param string $uTasksConfigPath The path of tasks configuration file
70 | *
71 | * @return void
72 | */
73 | public static function load($uTasksConfigPath)
74 | {
75 | // load tasks.yml
76 | $tTasksYamlPath = FileSystem::combinePaths(Core::$loader->basepath, Core::translateVariables($uTasksConfigPath));
77 | self::$config = Core::cachedRead(
78 | "file." . realpath($tTasksYamlPath),
79 | function () use ($tTasksYamlPath) {
80 | $tParser = new Parser();
81 | return $tParser->parse(FileSystem::read($tTasksYamlPath));
82 | },
83 | [
84 | "ttl" => 60 * 60
85 | ]
86 | );
87 |
88 | // register tasks
89 | foreach (self::$config["tasks"] as $tTaskKey => $tTask) {
90 | self::$tasks[$tTaskKey] = $tTask;
91 | }
92 | }
93 |
94 | /**
95 | * Executes given task.
96 | *
97 | * @param array $uTasks The set of task line arguments
98 | *
99 | * @throws RuntimeException if task is not found
100 | * @return int exit code
101 | */
102 | public static function execute(array $uTasks)
103 | {
104 | // TODO use interpreter
105 | // $tCommandInterpreter = new CommandInterpreter("Scabbia", "Scabbia Command Line Tool");
106 |
107 | $tTaskName = trim(array_shift($uTasks));
108 |
109 | if (isset(self::$tasks[$tTaskName])) {
110 | $tTask = self::$tasks[$tTaskName];
111 |
112 | if (isset($tTask["class"])) {
113 | $tClass = $tTask["class"];
114 | $tCallbacks = [];
115 | } else {
116 | $tClass = null;
117 | $tCallbacks = (array)$tTask["callback"];
118 | }
119 |
120 | if (isset($tTask["config"])) {
121 | $tConfig = $tTask["config"];
122 | } else {
123 | $tConfig = null;
124 | }
125 | } elseif (class_exists($tTaskName, true)) {
126 | $tClass = $tTaskName;
127 | $tCallbacks = [];
128 | $tConfig = null;
129 | } else {
130 | throw new RuntimeException("Task not found - " . $tTaskName . ".");
131 | }
132 |
133 | $tOutput = new Console();
134 |
135 | if ($tClass !== null) {
136 | $tInstance = new $tClass ($tConfig, $tOutput);
137 | $tReturnCode = $tInstance->executeTask($uTasks);
138 | } else {
139 | $tReturnCode = 0;
140 |
141 | foreach ($tCallbacks as $tCallback) {
142 | $tReturn = call_user_func(
143 | Runtime::callbacks($tCallback),
144 | ...$uTasks
145 | );
146 |
147 | if ($tReturn !== null && $tReturn !== 0) {
148 | $tReturnCode = $tReturn;
149 | break;
150 | }
151 | }
152 | }
153 |
154 | return $tReturnCode;
155 | }
156 | }
157 |
--------------------------------------------------------------------------------
/src/Yaml/ParseException.php:
--------------------------------------------------------------------------------
1 |
17 | *
18 | * For the full copyright and license information, please view the LICENSE-MIT
19 | * file that was distributed with this source code.
20 | *
21 | * Modifications made:
22 | * - Scabbia Framework code styles applied.
23 | * - All dump methods are moved under Dumper class.
24 | * - Redundant classes removed.
25 | * - Namespace changed.
26 | * - Tests ported to Scabbia2.
27 | * - Encoding checks removed.
28 | */
29 |
30 | namespace Scabbia\Yaml;
31 |
32 | use RuntimeException;
33 |
34 | /**
35 | * Exception class thrown when an error occurs during parsing
36 | *
37 | * @package Scabbia\Yaml
38 | * @author Fabien Potencier
39 | * @author Eser Ozvataf
40 | * @since 2.0.0
41 | */
42 | class ParseException extends RuntimeException
43 | {
44 | /** @type null|string $parsedFile The file name where the error occurred */
45 | protected $parsedFile;
46 | /** @type int $parsedLine The line where the error occurred */
47 | protected $parsedLine;
48 | /** @type int|null $snippet The snippet of code near the problem */
49 | protected $snippet;
50 | /** @type string $rawMessage The error message */
51 | protected $rawMessage;
52 |
53 |
54 | /**
55 | * Constructor
56 | *
57 | * @param string $message The error message
58 | * @param int $parsedLine The line where the error occurred
59 | * @param int $snippet The snippet of code near the problem
60 | * @param string $parsedFile The file name where the error occurred
61 | * @param \Exception $previous The previous exception
62 | *
63 | * @return ParseException
64 | */
65 | public function __construct(
66 | $message,
67 | $parsedLine = -1,
68 | $snippet = null,
69 | $parsedFile = null,
70 | \Exception $previous = null
71 | ) {
72 | $this->parsedFile = $parsedFile;
73 | $this->parsedLine = $parsedLine;
74 | $this->snippet = $snippet;
75 | $this->rawMessage = $message;
76 |
77 | $this->updateRepr();
78 |
79 | parent::__construct($this->message, 0, $previous);
80 | }
81 |
82 | /**
83 | * Gets the snippet of code near the error
84 | *
85 | * @return string The snippet of code
86 | */
87 | public function getSnippet()
88 | {
89 | return $this->snippet;
90 | }
91 |
92 | /**
93 | * Sets the snippet of code near the error
94 | *
95 | * @param string $snippet The code snippet
96 | *
97 | * @return void
98 | */
99 | public function setSnippet($snippet)
100 | {
101 | $this->snippet = $snippet;
102 |
103 | $this->updateRepr();
104 | }
105 |
106 | /**
107 | * Gets the filename where the error occurred
108 | *
109 | * This method returns null if a string is parsed.
110 | *
111 | * @return string The filename
112 | */
113 | public function getParsedFile()
114 | {
115 | return $this->parsedFile;
116 | }
117 |
118 | /**
119 | * Sets the filename where the error occurred
120 | *
121 | * @param string $parsedFile The filename
122 | *
123 | * @return void
124 | */
125 | public function setParsedFile($parsedFile)
126 | {
127 | $this->parsedFile = $parsedFile;
128 |
129 | $this->updateRepr();
130 | }
131 |
132 | /**
133 | * Gets the line where the error occurred
134 | *
135 | * @return int The file line
136 | */
137 | public function getParsedLine()
138 | {
139 | return $this->parsedLine;
140 | }
141 |
142 | /**
143 | * Sets the line where the error occurred
144 | *
145 | * @param int $parsedLine The file line
146 | */
147 | public function setParsedLine($parsedLine)
148 | {
149 | $this->parsedLine = $parsedLine;
150 |
151 | $this->updateRepr();
152 | }
153 |
154 | /**
155 | * Updates the generated message
156 | *
157 | * @return void
158 | */
159 | protected function updateRepr()
160 | {
161 | $this->message = $this->rawMessage;
162 |
163 | $dot = false;
164 | if (substr($this->message, -1) === ".") {
165 | $this->message = substr($this->message, 0, -1);
166 | $dot = true;
167 | }
168 |
169 | if ($this->parsedFile !== null) {
170 | $this->message .= sprintf(
171 | " in %s",
172 | json_encode($this->parsedFile, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)
173 | );
174 | }
175 |
176 | if ($this->parsedLine >= 0) {
177 | $this->message .= sprintf(" at line %d", $this->parsedLine);
178 | }
179 |
180 | if ($this->snippet) {
181 | $this->message .= sprintf(" (near \"%s\")", $this->snippet);
182 | }
183 |
184 | if ($dot) {
185 | $this->message .= ".";
186 | }
187 | }
188 | }
189 |
--------------------------------------------------------------------------------
/src/Yaml/Dumper.php:
--------------------------------------------------------------------------------
1 |
17 | *
18 | * For the full copyright and license information, please view the LICENSE-MIT
19 | * file that was distributed with this source code.
20 | *
21 | * Modifications made:
22 | * - Scabbia Framework code styles applied.
23 | * - All dump methods are moved under Dumper class.
24 | * - Redundant classes removed.
25 | * - Namespace changed.
26 | * - Tests ported to Scabbia2.
27 | * - Encoding checks removed.
28 | */
29 |
30 | namespace Scabbia\Yaml;
31 |
32 | use Scabbia\Yaml\Inline;
33 |
34 | /**
35 | * Dumper dumps PHP variables to YAML strings
36 | *
37 | * @package Scabbia\Yaml
38 | * @author Fabien Potencier
39 | * @author Eser Ozvataf
40 | * @since 2.0.0
41 | */
42 | class Dumper
43 | {
44 | /**
45 | * Dumps a PHP value to YAML
46 | *
47 | * @param mixed $input The PHP value
48 | * @param int $inline The level where you switch to inline YAML
49 | * @param int $indentation The level of indentation (used internally)
50 | *
51 | * @return string The YAML representation of the PHP value
52 | */
53 | public static function dump($input, $inline = 0, $indentation = 0)
54 | {
55 | $output = "";
56 | $prefix = $indentation ? str_repeat(" ", $indentation) : "";
57 |
58 | if ($inline <= 0 || !is_array($input) || count($input) === 0) {
59 | $output .= $prefix . self::dumpInline($input);
60 | } else {
61 | $isAHash = array_keys($input) !== range(0, count($input) - 1);
62 |
63 | foreach ($input as $key => $value) {
64 | $willBeInlined = (($inline - 1 <= 0) || !is_array($value) || count($value) === 0);
65 |
66 | $output .= $prefix .
67 | ($isAHash ? self::dumpInline($key) . ":" : "-") .
68 | ($willBeInlined ? " " : "\n") .
69 | self::dump($value, $inline - 1, ($willBeInlined ? 0 : $indentation)) .
70 | ($willBeInlined ? "\n" : "");
71 | }
72 | }
73 |
74 | return $output;
75 | }
76 |
77 | /**
78 | * Dumps a given PHP variable to a YAML string
79 | *
80 | * @param mixed $value The PHP variable to convert
81 | *
82 | * @return string The YAML string representing the PHP array
83 | */
84 | public static function dumpInline($value)
85 | {
86 | if (is_resource($value)) {
87 | return "null";
88 | } elseif (is_object($value)) {
89 | return "!!php/object:" . serialize($value);
90 | } elseif (is_array($value)) {
91 | return self::dumpInlineArray($value);
92 | } elseif ($value === null) {
93 | return "null";
94 | } elseif ($value === true) {
95 | return "true";
96 | } elseif ($value === false) {
97 | return "false";
98 | } elseif (ctype_digit($value)) {
99 | return is_string($value) ? "\"$value\"" : (int)$value;
100 | } elseif (is_numeric($value)) {
101 | $locale = setlocale(LC_NUMERIC, 0);
102 | if ($locale !== false) {
103 | setlocale(LC_NUMERIC, "C");
104 | }
105 | if (is_string($value)) {
106 | $repr = "'$value'";
107 | } elseif (is_infinite($value)) {
108 | $repr = str_ireplace("INF", ".Inf", strval($value));
109 | } else {
110 | $repr = strval($value);
111 | }
112 |
113 | if ($locale !== false) {
114 | setlocale(LC_NUMERIC, $locale);
115 | }
116 |
117 | return $repr;
118 | } elseif (Escaper::requiresDoubleQuoting($value)) {
119 | return Escaper::escapeWithDoubleQuotes($value);
120 | } elseif (Escaper::requiresSingleQuoting($value)) {
121 | return Escaper::escapeWithSingleQuotes($value);
122 | } elseif ($value === "") {
123 | return "''";
124 | } elseif (preg_match(Inline::getTimestampRegex(), $value) ||
125 | in_array(strtolower($value), ["null", "~", "true", "false"])
126 | ) {
127 | return "'$value'";
128 | } else {
129 | return $value;
130 | }
131 | }
132 |
133 | /**
134 | * Dumps a PHP array to a YAML string
135 | *
136 | * @param array $value The PHP array to dump
137 | *
138 | * @return string The YAML string representing the PHP array
139 | */
140 | protected static function dumpInlineArray(array $value)
141 | {
142 | // array
143 | $keys = array_keys($value);
144 | $func = function ($v, $w) {
145 | return (int)$v + $w;
146 | };
147 |
148 | if ((count($keys) === 1 && $keys[0] === "0") ||
149 | (count($keys) > 1 && array_reduce($keys, $func, 0) == count($keys) * (count($keys) - 1) / 2)
150 | ) {
151 | $output = [];
152 | foreach ($value as $val) {
153 | $output[] = self::dumpInline($val);
154 | }
155 |
156 | return "[" . implode(", ", $output) . "]";
157 | }
158 |
159 | // mapping
160 | $output = [];
161 | foreach ($value as $key => $val) {
162 | $output[] = self::dumpInline($key) . ": " . self::dumpInline($val);
163 | }
164 |
165 | return "{ " . implode(", ", $output) . " }";
166 | }
167 | }
168 |
--------------------------------------------------------------------------------
/src/Config/Config.php:
--------------------------------------------------------------------------------
1 |
27 | * @since 1.0.0
28 | */
29 | class Config
30 | {
31 | /** @type int NONE no flag */
32 | const NONE = 0;
33 | /** @type int OVERWRITE overwrite existing nodes by default */
34 | const OVERWRITE = 1;
35 | /** @type int FLATTEN flatten nodes by default */
36 | const FLATTEN = 2;
37 |
38 |
39 | /** @type array configuration paths */
40 | public $paths = [];
41 | /** @type array configuration content */
42 | public $content = [];
43 |
44 |
45 | /**
46 | * Loads a configuration file
47 | *
48 | * @param string|array $uPath path of configuration file to be loaded
49 | *
50 | * @return mixed
51 | */
52 | public static function load($uPath)
53 | {
54 | $tInstance = new static();
55 | foreach ((array)$uPath as $tPath) {
56 | $tInstance->add($tPath);
57 | }
58 |
59 | return $tInstance;
60 | }
61 |
62 | /**
63 | * Adds a file into configuration compilation
64 | *
65 | * @param string $uPath path of configuration file
66 | * @param int $uFlags loading flags
67 | *
68 | * @return void
69 | */
70 | public function add($uPath, $uFlags = self::NONE)
71 | {
72 | $this->paths[] = [$uPath, $uFlags];
73 | }
74 |
75 | /**
76 | * Compiles given configuration files into single configuration
77 | *
78 | * @return array final configuration
79 | */
80 | public function get()
81 | {
82 | // TODO mass caching with pathnames and flags
83 | foreach ($this->paths as $tPath) {
84 | $tConfigPath = Core::translateVariables($tPath[0]);
85 | $tConfigContent = Core::cachedRead(
86 | "file." . realpath($tConfigPath),
87 | function () use ($tConfigPath) {
88 | $tParser = new Parser();
89 | return $tParser->parse(FileSystem::read($tConfigPath));
90 | },
91 | [
92 | "ttl" => 60 * 60
93 | ]
94 | );
95 |
96 | $this->process($this->content, $tConfigContent, $tPath[1]);
97 | }
98 |
99 | return $this->content;
100 | }
101 |
102 | /**
103 | * Gets the YAML representation of configuration stack
104 | *
105 | * @return string YAML
106 | */
107 | public function dump()
108 | {
109 | return Dumper::dump($this->get(), 1);
110 | }
111 |
112 | /**
113 | * Processes the configuration file in order to simplify its accessibility
114 | *
115 | * @param mixed $uTarget target reference
116 | * @param mixed $uNode source object
117 | * @param int $uFlags loading flags
118 | *
119 | * @return void
120 | */
121 | public function process(&$uTarget, $uNode, $uFlags)
122 | {
123 | $tQueue = [
124 | [[], $uNode, $uFlags, &$uTarget, null, false]
125 | ];
126 |
127 | do {
128 | $tItem = array_pop($tQueue);
129 |
130 | if ($tItem[4] === null) {
131 | $tRef = &$tItem[3];
132 | } else {
133 | $tRef = &$tItem[3][$tItem[4]];
134 | }
135 |
136 | if (is_scalar($tItem[1]) || $tItem[1] === null) {
137 | if (!isset($tRef) || ($tItem[2] & self::OVERWRITE) === self::OVERWRITE) {
138 | $tRef = $tItem[1];
139 | }
140 |
141 | continue;
142 | }
143 |
144 | if (!is_array($tRef) || ($tItem[2] & self::OVERWRITE) === self::OVERWRITE) {
145 | $tRef = []; // initialize as an empty array
146 | }
147 |
148 | foreach ($tItem[1] as $tKey => $tSubnode) {
149 | $tFlags = $tItem[2];
150 | $tListNode = false;
151 |
152 | $tNodeParts = explode("|", $tKey);
153 | $tNodeKey = array_shift($tNodeParts);
154 |
155 | if ($tItem[5] && is_numeric($tNodeKey)) {
156 | $tNodeKey = count($tRef);
157 | }
158 |
159 | foreach ($tNodeParts as $tNodePart) {
160 | if ($tNodePart === "disabled") {
161 | continue 2;
162 | } elseif ($tNodePart === "development") {
163 | if (ApplicationBase::$current === null || !ApplicationBase::$current->development) {
164 | continue 2;
165 | }
166 | } elseif ($tNodePart === "list") {
167 | $tListNode = true;
168 | } elseif ($tNodePart === "important") {
169 | $tFlags |= self::OVERWRITE;
170 | } elseif ($tNodePart === "flat") {
171 | $tFlags |= self::FLATTEN;
172 | }
173 | }
174 |
175 | $tNewNodeKey = $tItem[0];
176 | if (($tFlags & self::FLATTEN) === self::FLATTEN) {
177 | $tNodeKey = ltrim("{$tItem[4]}/{$tNodeKey}", "/");
178 | $tNewNodeKey[] = $tNodeKey;
179 |
180 | $tQueue[] = [$tNewNodeKey, $tSubnode, $tFlags, &$tRef, $tNodeKey, $tListNode];
181 | } else {
182 | $tNewNodeKey[] = $tNodeKey;
183 | $tQueue[] = [$tNewNodeKey, $tSubnode, $tFlags, &$tRef[$tNodeKey], null, $tListNode];
184 | }
185 | }
186 | } while (count($tQueue) > 0);
187 | }
188 | }
189 |
--------------------------------------------------------------------------------
/src/Code/AnnotationManager.php:
--------------------------------------------------------------------------------
1 |
27 | * @since 2.0.0
28 | */
29 | class AnnotationManager
30 | {
31 | /** @type int SOURCE source */
32 | const SOURCE = 0;
33 | /** @type int LEVEL level */
34 | const LEVEL = 1;
35 | /** @type int MEMBER member */
36 | const MEMBER = 2;
37 | /** @type int VALUE value */
38 | const VALUE = 3;
39 |
40 |
41 | /** @type string $applicationWritablePath application writable path */
42 | public $applicationWritablePath;
43 | /** @type Parser|null $parser yaml parser */
44 | public $parser = null;
45 | /** @type AnnotationScanner|null $annotationScanner annotation scanner */
46 | public $annotationScanner = null;
47 | /** @type array $annotationMap annotation map */
48 | public $annotationMap = null;
49 |
50 |
51 | /**
52 | * Initializes an annotation manager
53 | *
54 | * @param string $uApplicationWritablePath application writable path
55 | *
56 | * @return AnnotationManager
57 | */
58 | public function __construct($uApplicationWritablePath)
59 | {
60 | $this->applicationWritablePath = $uApplicationWritablePath;
61 | }
62 |
63 | /**
64 | * Loads saved annotations or start over scanning
65 | *
66 | * @return void
67 | */
68 | public function load()
69 | {
70 | $tAnnotationMapPath = $this->applicationWritablePath . "/annotations.php";
71 |
72 | // TODO and not in development mode
73 | if (file_exists($tAnnotationMapPath)) {
74 | $this->annotationMap = require $tAnnotationMapPath;
75 | } else {
76 | $this->scan();
77 | // TODO if not in readonly mode
78 | FileSystem::writePhpFile($tAnnotationMapPath, $this->annotationMap);
79 | }
80 | }
81 |
82 | /**
83 | * Scans all files to find annotations
84 | *
85 | * @return void
86 | */
87 | public function scan()
88 | {
89 | // initialize annotation scanner
90 | $this->annotationScanner = new AnnotationScanner();
91 |
92 | // -- scan composer maps
93 | $tFolders = Core::$loader->getComposerFolders();
94 |
95 | foreach ($tFolders as $tPath) {
96 | if (file_exists($tPath[1])) {
97 | FileSystem::getFilesWalk(
98 | $tPath[1],
99 | "*.php",
100 | true,
101 | [$this, "scanFile"],
102 | $tPath[0]
103 | );
104 | }
105 | }
106 |
107 | $this->annotationMap = $this->annotationScanner->result;
108 | unset($this->annotationScanner);
109 | }
110 |
111 | /**
112 | * Scans given file to search for classes
113 | *
114 | * @param string $uFile file
115 | * @param string $uNamespacePrefix namespace prefix
116 | *
117 | * @return void
118 | */
119 | public function scanFile($uFile, $uNamespacePrefix)
120 | {
121 | $tFileContents = FileSystem::read($uFile);
122 | $tTokenStream = TokenStream::fromString($tFileContents);
123 |
124 | $this->annotationScanner->process($tTokenStream, $uNamespacePrefix);
125 | }
126 |
127 | /**
128 | * Gets annotations
129 | *
130 | * @param string $uAnnotation tag of the annotation
131 | * @param bool $uIsYaml whether is in yaml format or not
132 | *
133 | * @return Iterator annotations in [class, level, member, value]
134 | */
135 | public function get($uAnnotation, $uIsYaml = false)
136 | {
137 | return Core::cachedRead(
138 | "annotation.{$uAnnotation}.{$uIsYaml}",
139 | function () use ($uAnnotation, $uIsYaml) {
140 | $tResult = [];
141 |
142 | if ($uIsYaml && $this->parser === null) {
143 | $this->parser = new Parser();
144 | }
145 |
146 | foreach ($this->annotationMap as $tClass => $tAnnotationLevel) {
147 | if ($tAnnotationLevel === null) {
148 | continue;
149 | }
150 |
151 | foreach ($tAnnotationLevel as $tAnnotationLevelKey => $tMemberAnnotations) {
152 | foreach ($tMemberAnnotations as $tAnnotationMemberKey => $tAnnotations) {
153 | if (isset($tAnnotations[$uAnnotation])) {
154 | $tValue = $tAnnotations[$uAnnotation];
155 |
156 | if ($uIsYaml) {
157 | foreach ($tValue as &$tValueRef) {
158 | $tValueRef = $this->parser->parse($tValueRef);
159 | }
160 | }
161 |
162 | $tResult[] = [
163 | self::SOURCE => $tClass,
164 | self::LEVEL => $tAnnotationLevelKey,
165 | self::MEMBER => $tAnnotationMemberKey,
166 | self::VALUE => $tValue
167 | ];
168 | }
169 | }
170 | }
171 | }
172 |
173 | return $tResult;
174 | },
175 | [
176 | "ttl" => 60 * 60
177 | ]
178 | );
179 | }
180 | }
181 |
--------------------------------------------------------------------------------
/src/Code/TokenStream.php:
--------------------------------------------------------------------------------
1 |
27 | * @since 2.0.0
28 | */
29 | class TokenStream implements Countable, SeekableIterator
30 | {
31 | /** @type array $tokens set of tokens */
32 | public $tokens = [];
33 | /** @type int $position */
34 | public $position = 0;
35 |
36 |
37 | /**
38 | * Creates a new tokenstream instance from a code piece
39 | *
40 | * @param string $uCode the string consists of codes to turned into tokens
41 | *
42 | * @return TokenStream the new instance
43 | */
44 | public static function fromString($uCode)
45 | {
46 | return new static(token_get_all($uCode));
47 | }
48 |
49 | /**
50 | * Initializes a token stream
51 | *
52 | * @param array $uTokens set of tokens
53 | *
54 | * @return TokenStream
55 | */
56 | public function __construct(array $uTokens = [])
57 | {
58 | foreach ($uTokens as $tToken) {
59 | if (is_array($tToken)) {
60 | $this->tokens[] = [$tToken[0], $tToken[1]];
61 | } else {
62 | $this->tokens[] = [null, $tToken];
63 | }
64 | }
65 | }
66 |
67 | /**
68 | * Count elements of an object
69 | *
70 | * @return int the count as an integer
71 | */
72 | public function count()
73 | {
74 | return count($this->tokens);
75 | }
76 |
77 | /**
78 | * Seeks to a position
79 | *
80 | * @param int $uPosition the position to seek to
81 | *
82 | * @throws OutOfBoundsException
83 | * @return void
84 | */
85 | public function seek($uPosition)
86 | {
87 | if (!isset($this->tokens[$uPosition])) {
88 | throw new OutOfBoundsException("invalid seek position ({$uPosition})");
89 | }
90 |
91 | $this->position = $uPosition;
92 | }
93 |
94 | /**
95 | * Rewind the Iterator to the first element
96 | *
97 | * @return void
98 | */
99 | public function rewind()
100 | {
101 | $this->position = 0;
102 | }
103 |
104 | /**
105 | * Return the current element
106 | *
107 | * @return mixed
108 | */
109 | public function current()
110 | {
111 | return $this->tokens[$this->position];
112 | }
113 |
114 | /**
115 | * Return the key of the current element
116 | *
117 | * @return int
118 | */
119 | public function key()
120 | {
121 | return $this->position;
122 | }
123 |
124 | /**
125 | * Move forward to next element
126 | *
127 | * @return void
128 | */
129 | public function next()
130 | {
131 | $this->position++;
132 | }
133 |
134 | /**
135 | * Checks if current position is valid
136 | *
137 | * @return bool true on success or false on failure
138 | */
139 | public function valid()
140 | {
141 | return isset($this->tokens[$this->position]);
142 | }
143 |
144 | /**
145 | * Move back to previous element
146 | *
147 | * @return mixed
148 | */
149 | public function prev()
150 | {
151 | $this->position--;
152 | }
153 |
154 | /**
155 | * Gets next token if condition is true
156 | *
157 | * @param array|integer $uType
158 | * @param array|string|null $uValue
159 | *
160 | * @return bool
161 | */
162 | public function nextIf($uType, $uValue = null)
163 | {
164 | if ($this->test($uType, $uValue)) {
165 | $this->position++;
166 | return true;
167 | }
168 |
169 | return false;
170 | }
171 |
172 | /**
173 | * Advances until a token with the given type is found
174 | *
175 | * @param array|integer $uType
176 | * @param array|string|null $uValue
177 | *
178 | * @return mixed
179 | */
180 | public function nextUntil($uType, $uValue = null)
181 | {
182 | while (!$this->test($uType, $uValue)) {
183 | $this->position++;
184 |
185 | if (!isset($this->tokens[$this->position])) {
186 | return false;
187 | }
188 | }
189 |
190 | return true;
191 | }
192 |
193 | /**
194 | * Tests the current token for a condition
195 | *
196 | * @param array|integer $uType
197 | * @param array|string|null $uValue
198 | *
199 | * @return mixed
200 | */
201 | public function test($uType, $uValue = null)
202 | {
203 | $tToken = $this->tokens[$this->position];
204 |
205 | if ($uValue !== null) {
206 | if (is_array($uValue) && !in_array($tToken[1], $uValue)) {
207 | return false;
208 | }
209 |
210 | if ($tToken[1] !== $uValue) {
211 | return false;
212 | }
213 | }
214 |
215 | if ($tToken[0] !== $uType) {
216 | return false;
217 | }
218 |
219 | return true;
220 | }
221 |
222 | /**
223 | * Tests the current token for a condition or throws an exception otherwise
224 | *
225 | * @param array|integer $uType
226 | * @param array|string|null $uValue
227 | * @param string|null $uMessage
228 | *
229 | * @throws UnexpectedValueException
230 | * @return void
231 | */
232 | public function expect($uType, $uValue = null, $uMessage = null)
233 | {
234 | if (!$this->test($uType, $uValue)) {
235 | $tToken = $this->tokens[$this->position];
236 |
237 | throw new UnexpectedValueException(sprintf(
238 | "%sUnexpected token \"%s\" of value \"%s\" (\"%s\" expected%s)",
239 | $uMessage ? "{$uMessage}. " : "",
240 | token_name($tToken[0]),
241 | $tToken[1],
242 | token_name($uType),
243 | ($uValue ? sprintf(" with value \"%s\"", $uValue) : "")
244 | ));
245 | }
246 | }
247 | }
248 |
--------------------------------------------------------------------------------
/src/Router/Router.php:
--------------------------------------------------------------------------------
1 |
24 | * @since 2.0.0
25 | *
26 | * Routing related code based on the nikic's FastRoute solution:
27 | * http://nikic.github.io/2014/02/18/Fast-request-routing-using-regular-expressions.html
28 | */
29 | class Router
30 | {
31 | /** @type string VARIABLE_REGEX Regex expression of variables */
32 | const VARIABLE_REGEX = <<<'REGEX'
33 | ~\{
34 | \s* ([a-zA-Z][a-zA-Z0-9_]*) \s*
35 | (?:
36 | : \s* ([^{}]*(?:\{(?-1)\}[^{}*])*)
37 | )?
38 | \}~x
39 | REGEX;
40 |
41 | /** @type string DEFAULT_DISPATCH_REGEX Regex expression of default dispatch */
42 | const DEFAULT_DISPATCH_REGEX = "[^/]+";
43 |
44 | /** @type int FOUND route found */
45 | const FOUND = 0;
46 | /** @type int NOT_FOUND route not found */
47 | const NOT_FOUND = 1;
48 | /** @type int METHOD_NOT_ALLOWED route method is not allowed */
49 | const METHOD_NOT_ALLOWED = 2;
50 |
51 |
52 | /** @type null|array route definitions */
53 | public static $routes = null;
54 |
55 |
56 | /**
57 | * Constructor to prevent new instances of Router class
58 | *
59 | * @return Router
60 | */
61 | final private function __construct()
62 | {
63 | }
64 |
65 | /**
66 | * Clone method to prevent duplication of Router class
67 | *
68 | * @return Router
69 | */
70 | final private function __clone()
71 | {
72 | }
73 |
74 | /**
75 | * Unserialization method to prevent restoration of Router class
76 | *
77 | * @return Router
78 | */
79 | final private function __wakeup()
80 | {
81 | }
82 |
83 | /**
84 | * The dispatch method
85 | *
86 | * @param string $uMethod http method
87 | * @param string $uPathInfo path
88 | *
89 | * @return mixed
90 | */
91 | public static function dispatch($uMethod, $uPathInfo)
92 | {
93 | if (self::$routes === null) {
94 | $tRoutesFilePath = ApplicationBase::$current->writablePath . "/routes.php";
95 | self::$routes = require $tRoutesFilePath;
96 | }
97 |
98 | if (isset(self::$routes["static"][$uPathInfo])) {
99 | $tRoute = self::$routes["static"][$uPathInfo];
100 |
101 | if (isset($tRoute[$uMethod])) {
102 | return [
103 | "status" => self::FOUND,
104 | "callback" => $tRoute[$uMethod],
105 | "parameters" => []
106 | ];
107 | } elseif ($uMethod === "HEAD" && isset($tRoute["GET"])) {
108 | return [
109 | "status" => self::FOUND,
110 | "callback" => $tRoute["GET"],
111 | "parameters" => []
112 | ];
113 | } else {
114 | return [
115 | "status" => self::METHOD_NOT_ALLOWED,
116 | "methods" => array_keys($tRoute)
117 | ];
118 | }
119 | }
120 |
121 | foreach (self::$routes["variable"] as $tVariableRoute) {
122 | if (preg_match($tVariableRoute["regex"], $uPathInfo, $tMatches) !== 1) {
123 | continue;
124 | }
125 |
126 | $tRoute = $tVariableRoute["routeMap"][count($tMatches)];
127 | if (!isset($tRoute[$uMethod])) {
128 | if ($uMethod === "HEAD" && isset($tRoute["GET"])) {
129 | $uMethod = "GET";
130 | } else {
131 | return [
132 | "status" => self::METHOD_NOT_ALLOWED,
133 | "methods" => array_keys($tRoute)
134 | ];
135 | }
136 | }
137 |
138 | list($tCallback, $tVariableNames) = $tRoute[$uMethod];
139 |
140 | $tVariables = [];
141 | $tCount = 0;
142 | foreach ($tVariableNames as $tVariableName) {
143 | $tVariables[$tVariableName] = $tMatches[++$tCount];
144 | }
145 |
146 | return [
147 | "status" => self::FOUND,
148 | "callback" => $tCallback,
149 | "parameters" => $tVariables
150 | ];
151 | }
152 |
153 | return [
154 | "status" => self::NOT_FOUND
155 | ];
156 | }
157 |
158 | /**
159 | * Parses routes of the following form:
160 | * "/user/{name}/{id:[0-9]+}"
161 | *
162 | * @param string $uRoute route pattern
163 | *
164 | * @return array
165 | */
166 | public static function parse($uRoute)
167 | {
168 | if (!preg_match_all(self::VARIABLE_REGEX, $uRoute, $tMatches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER)) {
169 | return [$uRoute];
170 | }
171 |
172 | $tOffset = 0;
173 | $tRouteData = [];
174 | foreach ($tMatches as $tMatch) {
175 | if ($tMatch[0][1] > $tOffset) {
176 | $tRouteData[] = substr($uRoute, $tOffset, $tMatch[0][1] - $tOffset);
177 | }
178 |
179 | $tRouteData[] = [
180 | $tMatch[1][0],
181 | isset($tMatch[2]) ? trim($tMatch[2][0]) : self::DEFAULT_DISPATCH_REGEX
182 | ];
183 |
184 | $tOffset = $tMatch[0][1] + strlen($tMatch[0][0]);
185 | }
186 |
187 | if ($tOffset !== strlen($uRoute)) {
188 | $tRouteData[] = substr($uRoute, $tOffset);
189 | }
190 |
191 | return $tRouteData;
192 | }
193 |
194 | /**
195 | * Generates a path using named routes
196 | *
197 | * @param string $uName name of route
198 | * @param array $uParameters parameters
199 | *
200 | * @return false|string
201 | */
202 | public static function path($uName, array $uParameters = [])
203 | {
204 | if (self::$routes === null) {
205 | $tRoutesFilePath = ApplicationBase::$current->writablePath . "/routes.php";
206 | self::$routes = require $tRoutesFilePath;
207 | }
208 |
209 | if (!isset(self::$routes["named"][$uName])) {
210 | return false;
211 | }
212 |
213 | $tNamedRoute = self::$routes["named"][$uName];
214 | $tLink = $tNamedRoute[0];
215 | foreach ($tNamedRoute[1] as $tParameter) {
216 | if (isset($uParameters[$tParameter])) {
217 | $tValue = $uParameters[$tParameter];
218 | } else {
219 | $tValue = "";
220 | }
221 |
222 | $tLink = str_replace("{{$tParameter}}", $tValue, $tLink);
223 | }
224 |
225 | return $tLink;
226 | }
227 | }
228 |
--------------------------------------------------------------------------------
/src/Generators/GenerateTask.php:
--------------------------------------------------------------------------------
1 |
33 | * @since 2.0.0
34 | *
35 | * @todo only pass annotations requested by generator
36 | */
37 | class GenerateTask extends TaskBase
38 | {
39 | /** @type array $generators set of generators */
40 | public $generators = [];
41 | /** @type AnnotationScanner|null $annotationScanner annotation scanner */
42 | public $annotationScanner = null;
43 |
44 |
45 | /**
46 | * Registers the tasks itself to a command interpreter instance
47 | *
48 | * @param CommandInterpreter $uCommandInterpreter interpreter to be registered at
49 | *
50 | * @return void
51 | */
52 | public static function registerToCommandInterpreter(CommandInterpreter $uCommandInterpreter)
53 | {
54 | $uCommandInterpreter->addCommand(
55 | "generate",
56 | "Calls all generators registered to your project",
57 | [
58 | // type, name, description
59 | [Console::OPTION_FLAG, "--clean", ""]
60 | ]
61 | );
62 | }
63 |
64 | /**
65 | * Initializes the generate task
66 | *
67 | * @param mixed $uConfig configuration
68 | * @param IInterface $uInterface interface class
69 | *
70 | * @return GenerateTask
71 | */
72 | public function __construct($uConfig, $uInterface)
73 | {
74 | parent::__construct($uConfig, $uInterface);
75 | }
76 |
77 | /**
78 | * Executes the task
79 | *
80 | * @param array $uParameters parameters
81 | *
82 | * @throws RuntimeException if configuration is invalid
83 | * @return int exit code
84 | */
85 | public function executeTask(array $uParameters)
86 | {
87 | /*
88 | if (count($uParameters) === 0) {
89 | $tProjectFile = "etc/project.yml";
90 | $tApplicationKey = "default";
91 | } else {
92 | $tExploded = explode("/", $uParameters[0], 2);
93 | if (count($tExploded) === 1) {
94 | $tProjectFile = "etc/project.yml";
95 | $tApplicationKey = $tExploded[0];
96 | } else {
97 | $tProjectFile = $tExploded[0];
98 | $tApplicationKey = $tExploded[1];
99 | }
100 | }
101 |
102 | $tProjectFile = FileSystem::combinePaths(Core::$loader->basepath, Core::translateVariables($tProjectFile));
103 | $uApplicationConfig = Config::load($tProjectFile)->get();
104 |
105 | if (!isset($uApplicationConfig[$tApplicationKey])) {
106 | throw new RuntimeException(sprintf("invalid configuration - %s::%s", $tProjectFile, $tApplicationKey));
107 | }
108 |
109 | // TODO is sanitizing $tApplicationKey needed for paths?
110 | $tApplicationWritablePath = Core::$loader->basepath . "/var/generated/app.{$tApplicationKey}";
111 |
112 | if (!file_exists($tApplicationWritablePath)) {
113 | mkdir($tApplicationWritablePath, 0777, true);
114 | }
115 |
116 | // initialize annotation scanner
117 | $this->annotationScanner = new AnnotationScanner();
118 |
119 | // initialize generators read from configuration
120 | if (isset($this->config["generators"])) {
121 | foreach ($this->config["generators"] as $tTaskGeneratorClass) {
122 | $tInstance = new $tTaskGeneratorClass (
123 | $uApplicationConfig[$tApplicationKey],
124 | $tApplicationWritablePath
125 | );
126 |
127 | foreach ($tInstance->annotations as $tAnnotationKey => $tAnnotation) {
128 | $this->annotationScanner->annotations[$tAnnotationKey] = $tAnnotation;
129 | }
130 |
131 | $this->generators[$tTaskGeneratorClass] = $tInstance;
132 | }
133 | }
134 |
135 | // -- scan composer maps
136 | Core::pushSourcePaths($uApplicationConfig[$tApplicationKey]);
137 | $tFolders = iterator_to_array(Core::$loader->getComposerFolders(), false);
138 |
139 | $this->interface->writeColor("green", "Composer Maps:");
140 | foreach ($tFolders as $tFolder) {
141 | $this->interface->writeColor("white", sprintf("- [%s] \\%s => %s", $tFolder[2], $tFolder[0], $tFolder[1]));
142 | }
143 |
144 | foreach ($this->generators as $tGenerator) {
145 | $tGenerator->initialize();
146 | }
147 |
148 | // -- process files
149 | foreach ($tFolders as $tPath) {
150 | if (file_exists($tPath[1])) {
151 | FileSystem::getFilesWalk(
152 | $tPath[1],
153 | "*.*",
154 | true,
155 | [$this, "processFile"],
156 | $tPath[0]
157 | );
158 | }
159 | }
160 |
161 | foreach ($this->generators as $tGenerator) {
162 | $tGenerator->processAnnotations($this->annotationScanner->result);
163 | }
164 |
165 | foreach ($this->generators as $tGenerator) {
166 | $tGenerator->finalize();
167 | }
168 |
169 | foreach ($this->generators as $tGenerator) {
170 | $tGenerator->dump();
171 | }
172 |
173 | Core::popSourcePaths();
174 | */
175 |
176 | $tApplication = ApplicationBase::$current;
177 | $tGeneratorRegistry = new GeneratorRegistry($tApplication->config, $tApplication->writablePath);
178 | $tGeneratorRegistry->execute();
179 |
180 | $this->interface->writeColor("yellow", "done.");
181 |
182 | return 0;
183 | }
184 |
185 | /**
186 | * Processes given file to search for classes
187 | *
188 | * @param string $uFile file
189 | * @param string $uNamespacePrefix namespace prefix
190 | *
191 | * @return void
192 | */
193 | /*
194 | public function processFile($uFile, $uNamespacePrefix)
195 | {
196 | $tFileContents = FileSystem::read($uFile);
197 | $tTokenStream = TokenStream::fromString($tFileContents);
198 |
199 | foreach ($this->generators as $tGenerator) {
200 | $tGenerator->processFile($uFile, $tFileContents, $tTokenStream);
201 | }
202 |
203 | if (substr($uFile, -4) !== ".php") {
204 | return;
205 | }
206 |
207 | $this->annotationScanner->process($tTokenStream, $uNamespacePrefix);
208 | }
209 | */
210 | }
211 |
--------------------------------------------------------------------------------
/tests/Yaml/Fixtures/YtsTypeTransfers.yml:
--------------------------------------------------------------------------------
1 | --- %YAML:1.0
2 | test: Strings
3 | brief: >
4 | Any group of characters beginning with an
5 | alphabetic or numeric character is a string,
6 | unless it belongs to one of the groups below
7 | (such as an Integer or Time).
8 | yaml: |
9 | String
10 | php: |
11 | 'String'
12 | ---
13 | test: String characters
14 | brief: >
15 | A string can contain any alphabetic or
16 | numeric character, along with many
17 | punctuation characters, including the
18 | period, dash, space, quotes, exclamation, and
19 | question mark.
20 | yaml: |
21 | - What's Yaml?
22 | - It's for writing data structures in plain text.
23 | - And?
24 | - And what? That's not good enough for you?
25 | - No, I mean, "And what about Yaml?"
26 | - Oh, oh yeah. Uh.. Yaml for Ruby.
27 | php: |
28 | array(
29 | "What's Yaml?",
30 | "It's for writing data structures in plain text.",
31 | "And?",
32 | "And what? That's not good enough for you?",
33 | "No, I mean, \"And what about Yaml?\"",
34 | "Oh, oh yeah. Uh.. Yaml for Ruby."
35 | )
36 | ---
37 | test: Indicators in Strings
38 | brief: >
39 | Be careful using indicators in strings. In particular,
40 | the comma, colon, and pound sign must be used carefully.
41 | yaml: |
42 | the colon followed by space is an indicator: but is a string:right here
43 | same for the pound sign: here we have it#in a string
44 | the comma can, honestly, be used in most cases: [ but not in, inline collections ]
45 | php: |
46 | array(
47 | 'the colon followed by space is an indicator' => 'but is a string:right here',
48 | 'same for the pound sign' => 'here we have it#in a string',
49 | 'the comma can, honestly, be used in most cases' => array('but not in', 'inline collections')
50 | )
51 | ---
52 | test: Forcing Strings
53 | brief: >
54 | Any YAML type can be forced into a string using the
55 | explicit !str method.
56 | yaml: |
57 | date string: !str 2001-08-01
58 | number string: !str 192
59 | php: |
60 | array(
61 | 'date string' => '2001-08-01',
62 | 'number string' => '192'
63 | )
64 | ---
65 | test: Single-quoted Strings
66 | brief: >
67 | You can also enclose your strings within single quotes,
68 | which allows use of slashes, colons, and other indicators
69 | freely. Inside single quotes, you can represent a single
70 | quote in your string by using two single quotes next to
71 | each other.
72 | yaml: |
73 | all my favorite symbols: '#:!/%.)'
74 | a few i hate: '&(*'
75 | why do i hate them?: 'it''s very hard to explain'
76 | entities: '£ me'
77 | php: |
78 | array(
79 | 'all my favorite symbols' => '#:!/%.)',
80 | 'a few i hate' => '&(*',
81 | 'why do i hate them?' => 'it\'s very hard to explain',
82 | 'entities' => '£ me'
83 | )
84 | ---
85 | test: Double-quoted Strings
86 | brief: >
87 | Enclosing strings in double quotes allows you
88 | to use escapings to represent ASCII and
89 | Unicode characters.
90 | yaml: |
91 | i know where i want my line breaks: "one here\nand another here\n"
92 | php: |
93 | array(
94 | 'i know where i want my line breaks' => "one here\nand another here\n"
95 | )
96 | ---
97 | test: Multi-line Quoted Strings
98 | todo: true
99 | brief: >
100 | Both single- and double-quoted strings may be
101 | carried on to new lines in your YAML document.
102 | They must be indented a step and indentation
103 | is interpreted as a single space.
104 | yaml: |
105 | i want a long string: "so i'm going to
106 | let it go on and on to other lines
107 | until i end it with a quote."
108 | php: |
109 | array('i want a long string' => "so i'm going to ".
110 | "let it go on and on to other lines ".
111 | "until i end it with a quote."
112 | )
113 |
114 | ---
115 | test: Plain scalars
116 | todo: true
117 | brief: >
118 | Unquoted strings may also span multiple lines, if they
119 | are free of YAML space indicators and indented.
120 | yaml: |
121 | - My little toe is broken in two places;
122 | - I'm crazy to have skied this way;
123 | - I'm not the craziest he's seen, since there was always the German guy
124 | who skied for 3 hours on a broken shin bone (just below the kneecap);
125 | - Nevertheless, second place is respectable, and he doesn't
126 | recommend going for the record;
127 | - He's going to put my foot in plaster for a month;
128 | - This would impair my skiing ability somewhat for the
129 | duration, as can be imagined.
130 | php: |
131 | array(
132 | "My little toe is broken in two places;",
133 | "I'm crazy to have skied this way;",
134 | "I'm not the craziest he's seen, since there was always ".
135 | "the German guy who skied for 3 hours on a broken shin ".
136 | "bone (just below the kneecap);",
137 | "Nevertheless, second place is respectable, and he doesn't ".
138 | "recommend going for the record;",
139 | "He's going to put my foot in plaster for a month;",
140 | "This would impair my skiing ability somewhat for the duration, ".
141 | "as can be imagined."
142 | )
143 | ---
144 | test: 'Null'
145 | brief: >
146 | You can use the tilde '~' character for a null value.
147 | yaml: |
148 | name: Mr. Show
149 | hosted by: Bob and David
150 | date of next season: ~
151 | php: |
152 | array(
153 | 'name' => 'Mr. Show',
154 | 'hosted by' => 'Bob and David',
155 | 'date of next season' => null
156 | )
157 | ---
158 | test: Boolean
159 | brief: >
160 | You can use 'true' and 'false' for Boolean values.
161 | yaml: |
162 | Is Gus a Liar?: true
163 | Do I rely on Gus for Sustenance?: false
164 | php: |
165 | array(
166 | 'Is Gus a Liar?' => true,
167 | 'Do I rely on Gus for Sustenance?' => false
168 | )
169 | ---
170 | test: Integers
171 | dump_skip: true
172 | brief: >
173 | An integer is a series of numbers, optionally
174 | starting with a positive or negative sign. Integers
175 | may also contain commas for readability.
176 | yaml: |
177 | zero: 0
178 | simple: 12
179 | one-thousand: 1,000
180 | negative one-thousand: -1,000
181 | php: |
182 | array(
183 | 'zero' => 0,
184 | 'simple' => 12,
185 | 'one-thousand' => 1000,
186 | 'negative one-thousand' => -1000
187 | )
188 | ---
189 | test: Integers as Map Keys
190 | brief: >
191 | An integer can be used a dictionary key.
192 | yaml: |
193 | 1: one
194 | 2: two
195 | 3: three
196 | php: |
197 | array(
198 | 1 => 'one',
199 | 2 => 'two',
200 | 3 => 'three'
201 | )
202 | ---
203 | test: Floats
204 | dump_skip: true
205 | brief: >
206 | Floats are represented by numbers with decimals,
207 | allowing for scientific notation, as well as
208 | positive and negative infinity and "not a number."
209 | yaml: |
210 | a simple float: 2.00
211 | larger float: 1,000.09
212 | scientific notation: 1.00009e+3
213 | php: |
214 | array(
215 | 'a simple float' => 2.0,
216 | 'larger float' => 1000.09,
217 | 'scientific notation' => 1000.09
218 | )
219 | ---
220 | test: Time
221 | todo: true
222 | brief: >
223 | You can represent timestamps by using
224 | ISO8601 format, or a variation which
225 | allows spaces between the date, time and
226 | time zone.
227 | yaml: |
228 | iso8601: 2001-12-14t21:59:43.10-05:00
229 | space separated: 2001-12-14 21:59:43.10 -05:00
230 | php: |
231 | array(
232 | 'iso8601' => mktime( 2001, 12, 14, 21, 59, 43, 0.10, "-05:00" ),
233 | 'space separated' => mktime( 2001, 12, 14, 21, 59, 43, 0.10, "-05:00" )
234 | )
235 | ---
236 | test: Date
237 | todo: true
238 | brief: >
239 | A date can be represented by its year,
240 | month and day in ISO8601 order.
241 | yaml: |
242 | 1976-07-31
243 | php: |
244 | date( 1976, 7, 31 )
245 |
--------------------------------------------------------------------------------
/src/Objects/CommandInterpreter.php:
--------------------------------------------------------------------------------
1 |
24 | * @since 2.0.0
25 | */
26 | class CommandInterpreter
27 | {
28 | const PARAMETER = 0;
29 | const PARAMETER_REQUIRED = 1;
30 | const OPTION = 2;
31 | const OPTION_MULTIPLE = 3;
32 | const OPTION_FLAG = 4;
33 |
34 | protected $title;
35 | protected $description;
36 | protected $commands = [];
37 |
38 | /**
39 | * Initializes an interpreter
40 | *
41 | * @param string $uTitle title of interpreter
42 | * @param string $uDescription description for the interpreter
43 | *
44 | * @return CommandInterpreter
45 | */
46 | public function __construct($uTitle, $uDescription)
47 | {
48 | $this->title = $uTitle;
49 | $this->description = $uDescription;
50 | }
51 |
52 | /**
53 | * Adds a new command to interpreter
54 | *
55 | * @param string $uCommandName name of the command
56 | * @param string $uCommandDescription command description
57 | * @param array $uParameters parameters
58 | *
59 | * @return void
60 | */
61 | public function addCommand($uCommandName, $uCommandDescription, array $uParameters)
62 | {
63 | $this->commands[$uCommandName] = [$uCommandDescription, $uParameters];
64 | }
65 |
66 | /**
67 | * Displays the help
68 | *
69 | * @param IInterface $uInterface interface class
70 | *
71 | * @return void
72 | */
73 | public function help($uInterface)
74 | {
75 | $uInterface->write(sprintf("%s\n", $this->title));
76 | $uInterface->write(sprintf("%s\n", $this->description));
77 |
78 | foreach ($this->commands as $tCommandKey => $tCommand) {
79 | $uInterface->write(sprintf("- %s: %s\n", $tCommandKey, $tCommand[0]));
80 | }
81 | }
82 |
83 | /**
84 | * Parses and executes a command
85 | *
86 | * @param string $uCommandLine command and arguments
87 | *
88 | * @return array|null result of command execution
89 | */
90 | public function parse($uCommandLine)
91 | {
92 | $tParts = $this->split($uCommandLine);
93 | $tPartCommand = array_shift($tParts[0]);
94 |
95 | if (/* $tPartCommand !== false && */ !isset($this->commands[$tPartCommand])) {
96 | return null;
97 | }
98 |
99 | return $this->executeCommand($tPartCommand, $tParts[0], $tParts[1]);
100 | }
101 |
102 | /**
103 | * Splits a command into its components
104 | *
105 | * @param string $uInput the command
106 | *
107 | * @return array components of the given command
108 | */
109 | protected function split($uInput)
110 | {
111 | $tParts = [[], []];
112 | $tBuffer = "";
113 | $tQuote = false;
114 |
115 | for ($tPosition = 0, $tLen = strlen($uInput); $tPosition < $tLen; $tPosition++) {
116 | if ($uInput[$tPosition] === "\"") {
117 | $tQuote = !$tQuote;
118 | continue;
119 | } elseif (ctype_space($uInput[$tPosition])) {
120 | if (strlen($tBuffer) == 0) {
121 | continue;
122 | }
123 |
124 | if (!$tQuote) {
125 | if (strncmp($tBuffer, "--", 2) === 0) {
126 | $tParts[1][] = $tBuffer;
127 | } else {
128 | $tParts[0][] = $tBuffer;
129 | }
130 |
131 | $tBuffer = "";
132 | continue;
133 | }
134 | }
135 |
136 | $tBuffer .= $uInput[$tPosition];
137 | }
138 |
139 | if (strlen($tBuffer) > 0) {
140 | if (strncmp($tBuffer, "--", 2) === 0) {
141 | $tParts[1][] = $tBuffer;
142 | } else {
143 | $tParts[0][] = $tBuffer;
144 | }
145 | }
146 |
147 | return $tParts;
148 | }
149 |
150 | /**
151 | * Executes a command
152 | *
153 | * @param string $uCommandKey name of the command
154 | * @param array $uCommandParameters parameters
155 | * @param array $uCommandOptions options
156 | *
157 | * @throws UnexpectedValueException
158 | * @return array
159 | */
160 | protected function executeCommand($uCommandKey, array $uCommandParameters = [], array $uCommandOptions = [])
161 | {
162 | $tParameters = [];
163 |
164 | if (!isset($this->commands[$uCommandKey])) {
165 | throw new UnexpectedValueException(sprintf("command not found - %s", $uCommandKey));
166 | }
167 |
168 | foreach ($this->commands[$uCommandKey][1] as $tOption) {
169 | if ($tOption[0] === Console::PARAMETER) {
170 | $tParameters[$tOption[1]] = array_shift($uCommandParameters);
171 | } elseif ($tOption[0] === Console::PARAMETER_REQUIRED) {
172 | $tParameters[$tOption[1]] = array_shift($uCommandParameters);
173 | if ($tParameters[$tOption[1]] === false) {
174 | throw new UnexpectedValueException(sprintf("%s parameter required for command %s", $tOption[1], $uCommandKey));
175 | }
176 | } elseif ($tOption[0] === Console::OPTION ||
177 | $tOption[0] === Console::OPTION_MULTIPLE ||
178 | $tOption[0] === Console::OPTION_FLAG) {
179 | $tParameters[$tOption[1]] = $this->extractParameter($uCommandOptions, $tOption);
180 | }
181 | }
182 |
183 | if (count($uCommandOptions) > 0) {
184 | throw new UnexpectedValueException(sprintf("Invalid options used - %s", implode($uCommandOptions, ", ")));
185 | }
186 |
187 | return $tParameters;
188 | }
189 |
190 | /**
191 | * Extracts a parameter
192 | *
193 | * @param array $uCommandParameters set of command parameters
194 | * @param string $uOption name of the option
195 | * @param bool $uAssignment whether is it an assignment or not
196 | *
197 | * @return mixed extracted parameter
198 | */
199 | protected function extractParameter(&$uCommandParameters, $uOption, $uAssignment = false)
200 | {
201 | if ($uOption[0] === Console::OPTION) {
202 | $tReturn = null;
203 | $tOption = "{$uOption[1]}=";
204 | } elseif ($uOption[0] === Console::OPTION_MULTIPLE) {
205 | $tReturn = [];
206 | $tOption = "{$uOption[1]}=";
207 | } elseif ($uOption[0] === Console::OPTION_FLAG) {
208 | $tReturn = false;
209 | $tOption = $uOption[1];
210 | }
211 | $tOptionLength = strlen($tOption);
212 |
213 | $tUnsetKeys = [];
214 |
215 | foreach ($uCommandParameters as $tCommandParameterKey => $tCommandParameter) {
216 | if ($uOption[0] === Console::OPTION) {
217 | if (strncmp($tCommandParameter, $tOption, $tOptionLength) === 0) {
218 | $tUnsetKeys[] = $tCommandParameterKey;
219 | $tReturn = substr($tCommandParameter, $tOptionLength);
220 | }
221 | } elseif ($uOption[0] === Console::OPTION_MULTIPLE) {
222 | if (strncmp($tCommandParameter, $tOption, $tOptionLength) === 0) {
223 | $tUnsetKeys[] = $tCommandParameterKey;
224 | $tReturn[] = substr($tCommandParameter, $tOptionLength);
225 | }
226 | } elseif ($uOption[0] === Console::OPTION_FLAG) {
227 | if (strcmp($tCommandParameter, $tOption) === 0) {
228 | $tUnsetKeys[] = $tCommandParameterKey;
229 | $tReturn = true;
230 | }
231 | }
232 | }
233 |
234 | foreach ($tUnsetKeys as $tUnsetKey) {
235 | unset($uCommandParameters[$tUnsetKey]);
236 | }
237 |
238 | return $tReturn;
239 | }
240 | }
241 |
--------------------------------------------------------------------------------