Compare commits

..

51 Commits

Author SHA1 Message Date
Simon Sessingø c5c63671ef Merge pull request #383 from skipperbent/v3-development
Development
2018-03-03 23:44:20 +01:00
Simon Sessingø 6e247f811f Merge pull request #381 from skipperbent/v3-development
Throw correct exception-types.
2018-02-27 09:04:57 +01:00
Simon Sessingø 8111de48fd Merge pull request #378 from skipperbent/v3-development
Fixed issue with PDO exception not returning correct type for error-code.
2018-02-27 08:36:43 +01:00
Simon Sessingø 0dbc4e6ba2 Merge pull request #376 from skipperbent/v3-development
Optimisations
2018-02-27 00:20:12 +01:00
Simon Sessingø a4dfa59a66 Merge pull request #374 from skipperbent/v3-development
Stop router from processing routes if no valid route is found.
2018-02-27 00:14:24 +01:00
Simon Sessingø 2c9d996437 Merge pull request #372 from skipperbent/v3-development
Fixed setUrl issue.
2018-02-26 23:48:45 +01:00
Simon Sessingø 98ce5f7635 Merge pull request #370 from skipperbent/v3-development
Development
2018-02-26 23:24:37 +01:00
Simon Sessingø 69bb570c73 Merge pull request #368 from skipperbent/v3-development
Version 3.5.0.0
2018-02-24 05:39:20 +01:00
Simon Sessingø c80b23e9d4 Merge pull request #365 from skipperbent/v3-development
Version 3.4.11.2
2018-02-19 23:07:02 +01:00
Simon Sessingø 9d88bf10d2 Merge pull request #363 from skipperbent/master
Sync
2018-02-19 16:37:04 +01:00
Simon Sessingø dfa4a9aa6c Merge pull request #362 from skipperbent/v3-development
Version 3.4.11.1
2018-02-19 16:36:27 +01:00
Simon Sessingø 7c789ea0f8 Merge pull request #361 from skipperbent/v3
V3
2018-02-14 12:39:31 +01:00
Simon Sessingø 3ba9dd01f0 Merge pull request #360 from skipperbent/v3-development
Version 3.4.11.0
2018-02-14 12:39:19 +01:00
Simon Sessingø 14360b6779 Merge pull request #353 from skipperbent/v3
V3
2018-01-14 15:54:49 +01:00
Simon Sessingø bbb81333b4 Merge pull request #352 from skipperbent/v3-development
Fixed Input::all when php://input is not available
2018-01-14 15:54:37 +01:00
Simon Sessingø 161fbf6ccf Merge pull request #351 from skipperbent/v3
V3
2018-01-06 03:33:23 +01:00
Simon Sessingø 9a7b598880 Merge pull request #350 from skipperbent/v3-development
Version 3.4.10.0
2018-01-06 03:33:13 +01:00
Simon Sessingø 1486095e9f Merge pull request #345 from skipperbent/v3
V3 sync
2017-12-17 10:41:58 +01:00
Simon Sessingø 2db20dce6b Merge pull request #344 from skipperbent/v3-development
Version 3.4.9.3
2017-12-17 10:41:22 +01:00
Simon Sessingø 7cb416cfc8 Merge pull request #342 from skipperbent/v3
V3
2017-12-17 09:53:49 +01:00
Simon Sessingø c6341960d7 Merge pull request #341 from skipperbent/v3-development
Version 3.4.9.2
2017-12-17 09:53:39 +01:00
Simon Sessingø a570322e25 Merge pull request #340 from skipperbent/v3
V3
2017-12-16 12:54:06 +01:00
Simon Sessingø 85cf925793 Merge pull request #339 from skipperbent/v3-development
Version 3.4.9.1
2017-12-16 12:53:56 +01:00
Simon Sessingø feb6c8bd41 Merge pull request #337 from skipperbent/v3
V3
2017-12-09 23:58:48 +01:00
Simon Sessingø 7c0a20115e Merge pull request #336 from skipperbent/v3-development
Version 3.4.9.0
2017-12-09 23:58:33 +01:00
Simon Sessingø 276f213ccc Merge pull request #335 from skipperbent/v3
V3
2017-12-06 19:06:20 +01:00
Simon Sessingø 877e0aa937 Merge pull request #334 from skipperbent/v3-development
Version 3.4.8.0
2017-12-06 19:06:09 +01:00
Simon Sessingø 56457448e4 Merge pull request #331 from skipperbent/v3
V3
2017-12-02 20:30:37 +01:00
Simon Sessingø 3e7767d978 Merge pull request #330 from skipperbent/v3-development
V3 development
2017-12-02 20:30:27 +01:00
Simon Sessingø 8ce1540771 Merge pull request #328 from skipperbent/v3
V3
2017-11-27 02:05:40 +01:00
Simon Sessingø 5ef9349b18 Merge pull request #327 from skipperbent/v3-development
Version 3.4.6.4
2017-11-27 02:05:17 +01:00
Simon Sessingø 3b305ceb00 Merge pull request #326 from skipperbent/v3
V3
2017-11-27 00:01:45 +01:00
Simon Sessingø 264f0a7b0f Merge pull request #325 from skipperbent/v3-development
Version 3.4.6.3
2017-11-27 00:01:30 +01:00
Simon Sessingø 1f00cf50e6 Merge pull request #324 from skipperbent/v3
V3
2017-11-26 23:44:17 +01:00
Simon Sessingø 5197ae2990 Merge pull request #323 from skipperbent/v3-development
Version 3.4.6.2
2017-11-26 23:44:06 +01:00
Simon Sessingø 32bc46be81 Merge pull request #322 from skipperbent/v3
V3
2017-11-26 18:46:25 +01:00
Simon Sessingø 9c701aabee Merge pull request #321 from skipperbent/v3-development
Fixed url parsing issues
2017-11-26 18:45:54 +01:00
Simon Sessingø 2b0821a557 Merge pull request #320 from skipperbent/v3-development
Fixed typo
2017-11-26 18:29:36 +01:00
Simon Sessingø 1ee71b9ec3 Merge pull request #319 from skipperbent/v3
V3
2017-11-26 18:08:36 +01:00
Simon Sessingø afc81d7005 Merge pull request #318 from skipperbent/v3-development
Version 3.4.6.0
2017-11-26 18:08:24 +01:00
Simon Sessingø 0b8931a2e1 Merge pull request #316 from skipperbent/v3
V3
2017-11-25 01:35:03 +01:00
Simon Sessingø 496d3e7182 Merge pull request #315 from skipperbent/v3-development
Version 3.4.5.5
2017-11-25 01:34:53 +01:00
Simon Sessingø 2472079642 Merge pull request #312 from skipperbent/v3
V3
2017-11-10 13:03:02 +01:00
Simon Sessingø 1fd13ed2aa Merge pull request #311 from skipperbent/v3-development
V3 development
2017-11-10 13:02:49 +01:00
Simon Sessingø 4409fbcf4e Merge pull request #309 from skipperbent/v3
V3
2017-11-10 08:25:22 +01:00
Simon Sessingø 9d5c4a2ed1 Merge pull request #308 from skipperbent/v3-development
3.4.5.4
2017-11-10 08:24:55 +01:00
Simon Sessingø b8634bcf79 Merge pull request #307 from skipperbent/revert-306-revert-305-v3-development
Revert "Revert "V3 development""
2017-11-08 04:11:50 +01:00
Simon Sessingø 6ad22a3816 Revert "Revert "V3 development"" 2017-11-08 04:11:40 +01:00
Simon Sessingø ed41cd55af Merge pull request #306 from skipperbent/revert-305-v3-development
Revert "V3 development"
2017-11-08 04:09:55 +01:00
Simon Sessingø ebeca952cf Revert "V3 development" 2017-11-08 04:09:41 +01:00
Simon Sessingø 0672e85fd7 Merge pull request #305 from skipperbent/v3-development
V3 development
2017-11-08 04:09:31 +01:00
89 changed files with 997 additions and 4377 deletions
-22
View File
@@ -1,22 +0,0 @@
engines:
phpmd:
enabled: true
checks:
Design/TooManyPublicMethods:
enabled: true
Naming/ShortVariable:
enabled: true
CleanCode/StaticAccess:
enabled: true
Controversial/CamelCaseMethodName:
enabled: true
fixme:
enabled: true
duplication:
enabled: true
config:
languages:
- php:
ratings:
paths:
- src/**
+2 -2
View File
@@ -1,3 +1,3 @@
.idea
composer.lock
vendor/
tests/tmp/*
vendor/
-5
View File
@@ -1,5 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Simon" />
</state>
</component>
-12
View File
@@ -1,12 +0,0 @@
<component name="ProjectDictionaryState">
<dictionary name="simon">
<words>
<w>bootmanager</w>
<w>bootmanagers</w>
<w>csrf</w>
<w>middlewares</w>
<w>pecee</w>
<w>urldecode</w>
</words>
</dictionary>
</component>
-72
View File
@@ -1,72 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MarkdownProjectSettings">
<PreviewSettings splitEditorLayout="SPLIT" splitEditorPreview="PREVIEW" useGrayscaleRendering="false" zoomFactor="1.25" maxImageWidth="0" showGitHubPageIfSynced="false" allowBrowsingInPreview="false" synchronizePreviewPosition="true" highlightPreviewType="NONE" highlightFadeOut="5" highlightOnTyping="true" synchronizeSourcePosition="true" verticallyAlignSourceAndPreviewSyncPosition="true" showSearchHighlightsInPreview="false" showSelectionInPreview="true">
<PanelProvider>
<provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.panel" providerName="Default - Swing" />
</PanelProvider>
</PreviewSettings>
<ParserSettings gitHubSyntaxChange="false">
<PegdownExtensions>
<option name="ABBREVIATIONS" value="false" />
<option name="ANCHORLINKS" value="true" />
<option name="ASIDE" value="false" />
<option name="ATXHEADERSPACE" value="true" />
<option name="AUTOLINKS" value="true" />
<option name="DEFINITIONS" value="false" />
<option name="DEFINITION_BREAK_DOUBLE_BLANK_LINE" value="false" />
<option name="FENCED_CODE_BLOCKS" value="true" />
<option name="FOOTNOTES" value="false" />
<option name="HARDWRAPS" value="false" />
<option name="HTML_DEEP_PARSER" value="false" />
<option name="INSERTED" value="false" />
<option name="QUOTES" value="false" />
<option name="RELAXEDHRULES" value="true" />
<option name="SMARTS" value="false" />
<option name="STRIKETHROUGH" value="true" />
<option name="SUBSCRIPT" value="false" />
<option name="SUPERSCRIPT" value="false" />
<option name="SUPPRESS_HTML_BLOCKS" value="false" />
<option name="SUPPRESS_INLINE_HTML" value="false" />
<option name="TABLES" value="true" />
<option name="TASKLISTITEMS" value="true" />
<option name="TOC" value="false" />
<option name="WIKILINKS" value="true" />
</PegdownExtensions>
<ParserOptions>
<option name="COMMONMARK_LISTS" value="true" />
<option name="DUMMY" value="false" />
<option name="EMOJI_SHORTCUTS" value="true" />
<option name="FLEXMARK_FRONT_MATTER" value="false" />
<option name="GFM_LOOSE_BLANK_LINE_AFTER_ITEM_PARA" value="false" />
<option name="GFM_TABLE_RENDERING" value="true" />
<option name="GITBOOK_URL_ENCODING" value="false" />
<option name="GITHUB_EMOJI_URL" value="false" />
<option name="GITHUB_LISTS" value="false" />
<option name="GITHUB_WIKI_LINKS" value="true" />
<option name="JEKYLL_FRONT_MATTER" value="false" />
<option name="SIM_TOC_BLANK_LINE_SPACER" value="true" />
</ParserOptions>
</ParserSettings>
<HtmlSettings headerTopEnabled="false" headerBottomEnabled="false" bodyTopEnabled="false" bodyBottomEnabled="false" embedUrlContent="false" addPageHeader="true">
<GeneratorProvider>
<provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.generator" providerName="Default Swing HTML Generator" />
</GeneratorProvider>
<headerTop />
<headerBottom />
<bodyTop />
<bodyBottom />
</HtmlSettings>
<CssSettings previewScheme="UI_SCHEME" cssUri="" isCssUriEnabled="false" isCssTextEnabled="false" isDynamicPageWidth="true">
<StylesheetProvider>
<provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.css" providerName="Default Swing Stylesheet" />
</StylesheetProvider>
<ScriptProviders />
<cssText />
</CssSettings>
<HtmlExportSettings updateOnSave="false" parentDir="$ProjectFileDir$" targetDir="$ProjectFileDir$" cssDir="" scriptDir="" plainHtml="false" imageDir="" copyLinkedImages="false" imageUniquifyType="0" targetExt="" useTargetExt="false" noCssNoScripts="false" linkToExportedHtml="true" exportOnSettingsChange="true" regenerateOnProjectOpen="false" />
<LinkMapSettings>
<textMaps />
</LinkMapSettings>
</component>
</project>
-3
View File
@@ -1,3 +0,0 @@
<component name="MarkdownNavigator.ProfileManager">
<settings default="" pdf-export="" />
</component>
-8
View File
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/simple-php-router.iml" filepath="$PROJECT_DIR$/.idea/simple-php-router.iml" />
</modules>
</component>
</project>
-14
View File
@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PhpTestFrameworkVersionCache">
<tools_cache>
<tool tool_name="PHPUnit">
<cache>
<versions>
<info id="Local" version="6.5.7" />
</versions>
</cache>
</tool>
</tools_cache>
</component>
</project>
Generated
-52
View File
@@ -1,52 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PhpIncludePathManager">
<include_path>
<path value="$PROJECT_DIR$/vendor/composer" />
<path value="$PROJECT_DIR$/vendor/phpdocumentor/reflection-common" />
<path value="$PROJECT_DIR$/vendor/phpunit/phpunit" />
<path value="$PROJECT_DIR$/vendor/phpdocumentor/type-resolver" />
<path value="$PROJECT_DIR$/vendor/phpdocumentor/reflection-docblock" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-code-coverage" />
<path value="$PROJECT_DIR$/vendor/webmozart/assert" />
<path value="$PROJECT_DIR$/vendor/phpunit/phpunit-mock-objects" />
<path value="$PROJECT_DIR$/vendor/sebastian/version" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-token-stream" />
<path value="$PROJECT_DIR$/vendor/sebastian/diff" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-text-template" />
<path value="$PROJECT_DIR$/vendor/sebastian/recursion-context" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-timer" />
<path value="$PROJECT_DIR$/vendor/sebastian/exporter" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-file-iterator" />
<path value="$PROJECT_DIR$/vendor/sebastian/environment" />
<path value="$PROJECT_DIR$/vendor/sebastian/comparator" />
<path value="$PROJECT_DIR$/vendor/sebastian/global-state" />
<path value="$PROJECT_DIR$/vendor/doctrine/instantiator" />
<path value="$PROJECT_DIR$/vendor/phpspec/prophecy" />
<path value="$PROJECT_DIR$/vendor/sebastian/resource-operations" />
<path value="$PROJECT_DIR$/vendor/sebastian/code-unit-reverse-lookup" />
<path value="$PROJECT_DIR$/vendor/sebastian/object-reflector" />
<path value="$PROJECT_DIR$/vendor/sebastian/object-enumerator" />
<path value="$PROJECT_DIR$/vendor/hamcrest/hamcrest-php" />
<path value="$PROJECT_DIR$/vendor/theseer/tokenizer" />
<path value="$PROJECT_DIR$/vendor/phar-io/version" />
<path value="$PROJECT_DIR$/vendor/phar-io/manifest" />
<path value="$PROJECT_DIR$/vendor/myclabs/deep-copy" />
<path value="$PROJECT_DIR$/vendor/mockery/mockery" />
<path value="$PROJECT_DIR$/vendor/jeremeamia/SuperClosure" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-util" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php56" />
<path value="$PROJECT_DIR$/vendor/php-di/invoker" />
<path value="$PROJECT_DIR$/vendor/php-di/phpdoc-reader" />
<path value="$PROJECT_DIR$/vendor/nikic/php-parser" />
<path value="$PROJECT_DIR$/vendor/psr/container" />
<path value="$PROJECT_DIR$/vendor/php-di/php-di" />
</include_path>
</component>
<component name="PhpProjectSharedConfiguration" php_language_level="7.1" />
<component name="PhpUnit">
<phpunit_settings>
<PhpUnitSettings load_method="CUSTOM_LOADER" configuration_file_path="$PROJECT_DIR$/phpunit.xml" custom_loader_path="$PROJECT_DIR$/vendor/autoload.php" phpunit_phar_path="" use_configuration_file="true" />
</phpunit_settings>
</component>
</project>
-49
View File
@@ -1,49 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/Pecee" isTestSource="false" packagePrefix="Pecee\" />
<excludeFolder url="file://$MODULE_DIR$/vendor/composer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/instantiator" />
<excludeFolder url="file://$MODULE_DIR$/vendor/hamcrest/hamcrest-php" />
<excludeFolder url="file://$MODULE_DIR$/vendor/jeremeamia/SuperClosure" />
<excludeFolder url="file://$MODULE_DIR$/vendor/mockery/mockery" />
<excludeFolder url="file://$MODULE_DIR$/vendor/myclabs/deep-copy" />
<excludeFolder url="file://$MODULE_DIR$/vendor/nikic/php-parser" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phar-io/manifest" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phar-io/version" />
<excludeFolder url="file://$MODULE_DIR$/vendor/php-di/invoker" />
<excludeFolder url="file://$MODULE_DIR$/vendor/php-di/php-di" />
<excludeFolder url="file://$MODULE_DIR$/vendor/php-di/phpdoc-reader" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpdocumentor/reflection-common" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpdocumentor/reflection-docblock" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpdocumentor/type-resolver" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpspec/prophecy" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-code-coverage" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-file-iterator" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-text-template" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-timer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-token-stream" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/phpunit" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/phpunit-mock-objects" />
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/container" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/code-unit-reverse-lookup" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/comparator" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/diff" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/environment" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/exporter" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/global-state" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/object-enumerator" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/object-reflector" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/recursion-context" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/resource-operations" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/version" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-php56" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-util" />
<excludeFolder url="file://$MODULE_DIR$/vendor/theseer/tokenizer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/webmozart/assert" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
Generated
-6
View File
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
-954
View File
@@ -1,954 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="a7058529-bdc4-40b4-a50d-c50564dc83f0" name="Default" comment="">
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/Pecee/SimpleRouter/Route/LoadableRoute.php" beforeDir="false" afterPath="$PROJECT_DIR$/src/Pecee/SimpleRouter/Route/LoadableRoute.php" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/Pecee/SimpleRouter/Route/Route.php" beforeDir="false" afterPath="$PROJECT_DIR$/src/Pecee/SimpleRouter/Route/Route.php" afterDir="false" />
</list>
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
<option name="TRACKING_ENABLED" value="true" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="ComposerSettings" doNotAsk="true" synchronizationState="SYNCHRONIZE">
<pharConfigPath>$PROJECT_DIR$/composer.json</pharConfigPath>
</component>
<component name="FileEditorManager">
<leaf SIDE_TABS_SIZE_LIMIT_KEY="375">
<file leaf-file-name="helpers.php" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/helpers.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="1340">
<caret line="70" column="5" selection-start-line="70" selection-start-column="5" selection-end-line="70" selection-end-column="5" />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="README.md" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/README.md">
<provider selected="true" editor-type-id="split-provider[text-editor;markdown-preview-editor]">
<state split_layout="SPLIT">
<first_editor relative-caret-position="619">
<caret line="370" column="1" selection-start-line="370" selection-start-column="1" selection-end-line="370" selection-end-column="1" />
</first_editor>
<second_editor />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="LoadableRoute.php" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/Pecee/SimpleRouter/Route/LoadableRoute.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="357">
<caret line="160" lean-forward="true" selection-start-line="160" selection-end-line="160" />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="ILoadableRoute.php" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/Pecee/SimpleRouter/Route/ILoadableRoute.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="900">
<caret line="46" column="20" selection-start-line="46" selection-start-column="20" selection-end-line="46" selection-end-column="20" />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="Route.php" pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/src/Pecee/SimpleRouter/Route/Route.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-2762">
<caret line="194" column="25" selection-start-line="194" selection-start-column="25" selection-end-line="194" selection-end-column="25" />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="InputHandler.php" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/Pecee/Http/Input/InputHandler.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="4460">
<caret line="224" column="80" selection-start-line="224" selection-start-column="80" selection-end-line="224" selection-end-column="80" />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="InputItem.php" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/Pecee/Http/Input/InputItem.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="80">
<caret line="4" column="37" selection-start-line="4" selection-start-column="37" selection-end-line="4" selection-end-column="37" />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="Url.php" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/Pecee/Http/Url.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="9100">
<caret line="455" column="20" selection-end-line="460" selection-end-column="1" />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="InputFile.php" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/Pecee/Http/Input/InputFile.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="180">
<caret line="9" column="17" selection-start-line="9" selection-start-column="17" selection-end-line="9" selection-end-column="17" />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="IInputItem.php" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/Pecee/Http/Input/IInputItem.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="380">
<caret line="19" column="40" selection-start-line="19" selection-start-column="40" selection-end-line="19" selection-end-column="40" />
</state>
</provider>
</entry>
</file>
</leaf>
</component>
<component name="FindInProjectRecents">
<findStrings>
<find>findRoute</find>
<find>-&gt;fireEvents</find>
<find>RENDER_MIDD</find>
<find>EVENT_RENDER_CSRF</find>
<find>RENDER_ROUTE</find>
<find>requirements</find>
<find># Advan</find>
<find># Feed</find>
<find>: void</find>
<find>call_user_func_array</find>
<find>loadClass</find>
<find>$this-&gt;</find>
<find>$this-&gt;result</find>
<find>$this-&gt;r</find>
<find>getInput</find>
<find>input()-&gt;get</find>
<find>getObject</find>
<find>helpers</find>
<find>group</find>
<find>addDefault</find>
<find>handleExc</find>
<find>function group</find>
<find>function parti</find>
<find>__toString</find>
<find>getValue</find>
<find>getError</find>
<find>(int)</find>
<find>setSize</find>
<find>helpers.php</find>
<find>getName</find>
</findStrings>
<dirStrings>
<dir>D:\Workspace\simple-php-router\src\Pecee\SimpleRouter\Route</dir>
<dir>D:\Workspace\simple-php-router\src</dir>
<dir>D:\Workspace\simple-php-router\tests\Pecee\SimpleRouter\Dummy</dir>
<dir>D:\Workspace\simple-php-router</dir>
<dir>E:\Workspace\simple-php-router\tests</dir>
<dir>E:\Workspace\simple-php-router\src\Pecee</dir>
<dir>E:\Workspace\simple-php-router</dir>
<dir>E:\Workspace\simple-php-router\src\Pecee\SimpleRouter</dir>
<dir>E:\Workspace\simple-php-router\tests\Pecee\SimpleRouter</dir>
<dir>E:\Workspace\simple-php-router\src</dir>
<dir>E:\Workspace\simple-php-router\src\Pecee\SimpleRouter\Route</dir>
</dirStrings>
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="IdeDocumentHistory">
<option name="CHANGED_PATHS">
<list>
<option value="$PROJECT_DIR$/tests/Pecee/SimpleRouter/Dummy/Handler/ExceptionHandlerFirst.php" />
<option value="$PROJECT_DIR$/tests/Pecee/SimpleRouter/Dummy/Handler/ExceptionHandlerSecond.php" />
<option value="$PROJECT_DIR$/tests/TestRouter.php" />
<option value="$PROJECT_DIR$/tests/Pecee/SimpleRouter/RouterUrlTest.php" />
<option value="$PROJECT_DIR$/src/Pecee/SimpleRouter/Event/IEventArgument.php" />
<option value="$PROJECT_DIR$/src/Pecee/SimpleRouter/IRouterBootManager.php" />
<option value="$PROJECT_DIR$/tests/Pecee/SimpleRouter/Dummy/Security/SilentTokenProvider.php" />
<option value="$PROJECT_DIR$/tests/Pecee/SimpleRouter/Dummy/Managers/TestBootManager.php" />
<option value="$PROJECT_DIR$/src/Pecee/Http/Middleware/BaseCsrfVerifier.php" />
<option value="$PROJECT_DIR$/src/Pecee/Http/Security/CookieTokenProvider.php" />
<option value="$PROJECT_DIR$/src/Pecee/Http/Security/ITokenProvider.php" />
<option value="$PROJECT_DIR$/src/Pecee/Http/Request.php" />
<option value="$PROJECT_DIR$/src/Pecee/Http/Response.php" />
<option value="$PROJECT_DIR$/src/Pecee/SimpleRouter/Route/ILoadableRoute.php" />
<option value="$PROJECT_DIR$/src/Pecee/SimpleRouter/Route/IRoute.php" />
<option value="$PROJECT_DIR$/src/Pecee/SimpleRouter/Route/RouteController.php" />
<option value="$PROJECT_DIR$/src/Pecee/SimpleRouter/Route/RouteGroup.php" />
<option value="$PROJECT_DIR$/src/Pecee/SimpleRouter/Route/RoutePartialGroup.php" />
<option value="$PROJECT_DIR$/src/Pecee/SimpleRouter/Route/RouteUrl.php" />
<option value="$PROJECT_DIR$/src/Pecee/SimpleRouter/Route/RouteResource.php" />
<option value="$PROJECT_DIR$/tests/Pecee/SimpleRouter/InputHandlerTest.php" />
<option value="$PROJECT_DIR$/tests/Pecee/SimpleRouter/EventHandlerTest.php" />
<option value="$PROJECT_DIR$/src/Pecee/SimpleRouter/Handlers/IEventHandler.php" />
<option value="$PROJECT_DIR$/src/Pecee/SimpleRouter/Handlers/DebugEventHandler.php" />
<option value="$PROJECT_DIR$/src/Pecee/SimpleRouter/Handlers/EventHandler.php" />
<option value="$PROJECT_DIR$/src/Pecee/SimpleRouter/Event/EventArgument.php" />
<option value="$PROJECT_DIR$/src/Pecee/SimpleRouter/Handlers/ClassHandler.php" />
<option value="$PROJECT_DIR$/src/Pecee/SimpleRouter/Handlers/ClassLoader.php" />
<option value="$PROJECT_DIR$/src/Pecee/SimpleRouter/ClassLoader.php" />
<option value="$PROJECT_DIR$/src/Pecee/SimpleRouter/ClassLoader/DIContainerBuilder.php" />
<option value="$PROJECT_DIR$/src/Pecee/SimpleRouter/ClassLoader/Containers/DIContainerBuilder.php" />
<option value="$PROJECT_DIR$/src/Pecee/SimpleRouter/ClassLoader/ContainerInterface.php" />
<option value="$PROJECT_DIR$/src/Pecee/SimpleRouter/ClassLoader/IContainer.php" />
<option value="$PROJECT_DIR$/src/Pecee/SimpleRouter/ClassLoader/IClassLoader.php" />
<option value="$PROJECT_DIR$/src/Pecee/SimpleRouter/ClassLoader/ClassLoader.php" />
<option value="$PROJECT_DIR$/composer.json" />
<option value="$PROJECT_DIR$/tests/Pecee/SimpleRouter/GroupTest.php" />
<option value="$PROJECT_DIR$/tests/Pecee/SimpleRouter/RouterRouteTest.php" />
<option value="$PROJECT_DIR$/tests/Pecee/SimpleRouter/DependencyInjectionTest.php" />
<option value="$PROJECT_DIR$/src/Pecee/SimpleRouter/Router.php" />
<option value="$PROJECT_DIR$/src/Pecee/SimpleRouter/SimpleRouter.php" />
<option value="$PROJECT_DIR$/src/Pecee/Http/Input/InputHandler.php" />
<option value="$PROJECT_DIR$/.gitignore" />
<option value="$PROJECT_DIR$/src/Pecee/Http/Input/IInputItem.php" />
<option value="$PROJECT_DIR$/src/Pecee/Http/Url.php" />
<option value="$PROJECT_DIR$/src/Pecee/Http/Input/InputItem.php" />
<option value="$PROJECT_DIR$/src/Pecee/Http/Input/InputFile.php" />
<option value="$PROJECT_DIR$/helpers.php" />
<option value="$PROJECT_DIR$/README.md" />
<option value="$PROJECT_DIR$/src/Pecee/SimpleRouter/Route/LoadableRoute.php" />
<option value="$PROJECT_DIR$/src/Pecee/SimpleRouter/Route/Route.php" />
</list>
</option>
</component>
<component name="JsBuildToolGruntFileManager" detection-done="true" sorting="DEFINITION_ORDER" />
<component name="JsBuildToolPackageJson" detection-done="true" sorting="DEFINITION_ORDER" />
<component name="JsFlowSettings">
<service-enabled>false</service-enabled>
<exe-path />
<annotation-enable>false</annotation-enable>
<other-services-enabled>false</other-services-enabled>
<auto-save>true</auto-save>
</component>
<component name="JsGulpfileManager">
<detection-done>true</detection-done>
<sorting>DEFINITION_ORDER</sorting>
</component>
<component name="PhpWorkspaceProjectConfiguration" interpreter_name="PHP 7.2">
<include_path>
<path value="$PROJECT_DIR$/vendor/composer" />
<path value="$PROJECT_DIR$/vendor/phpdocumentor/reflection-common" />
<path value="$PROJECT_DIR$/vendor/phpunit/phpunit" />
<path value="$PROJECT_DIR$/vendor/phpdocumentor/type-resolver" />
<path value="$PROJECT_DIR$/vendor/phpdocumentor/reflection-docblock" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-code-coverage" />
<path value="$PROJECT_DIR$/vendor/webmozart/assert" />
<path value="$PROJECT_DIR$/vendor/phpunit/phpunit-mock-objects" />
<path value="$PROJECT_DIR$/vendor/sebastian/version" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-token-stream" />
<path value="$PROJECT_DIR$/vendor/sebastian/diff" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-text-template" />
<path value="$PROJECT_DIR$/vendor/sebastian/recursion-context" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-timer" />
<path value="$PROJECT_DIR$/vendor/sebastian/exporter" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-file-iterator" />
<path value="$PROJECT_DIR$/vendor/sebastian/environment" />
<path value="$PROJECT_DIR$/vendor/sebastian/comparator" />
<path value="$PROJECT_DIR$/vendor/sebastian/global-state" />
<path value="$PROJECT_DIR$/vendor/doctrine/instantiator" />
<path value="$PROJECT_DIR$/vendor/phpspec/prophecy" />
<path value="$PROJECT_DIR$/vendor/sebastian/resource-operations" />
<path value="$PROJECT_DIR$/vendor/sebastian/code-unit-reverse-lookup" />
<path value="$PROJECT_DIR$/vendor/sebastian/object-reflector" />
<path value="$PROJECT_DIR$/vendor/sebastian/object-enumerator" />
<path value="$PROJECT_DIR$/vendor/hamcrest/hamcrest-php" />
<path value="$PROJECT_DIR$/vendor/theseer/tokenizer" />
<path value="$PROJECT_DIR$/vendor/phar-io/version" />
<path value="$PROJECT_DIR$/vendor/phar-io/manifest" />
<path value="$PROJECT_DIR$/vendor/myclabs/deep-copy" />
<path value="$PROJECT_DIR$/vendor/mockery/mockery" />
<path value="$PROJECT_DIR$/vendor/jeremeamia/SuperClosure" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-util" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php56" />
<path value="$PROJECT_DIR$/vendor/php-di/invoker" />
<path value="$PROJECT_DIR$/vendor/php-di/phpdoc-reader" />
<path value="$PROJECT_DIR$/vendor/nikic/php-parser" />
<path value="$PROJECT_DIR$/vendor/psr/container" />
<path value="$PROJECT_DIR$/vendor/php-di/php-di" />
</include_path>
</component>
<component name="ProjectFrameBounds" extendedState="6">
<option name="x" value="105" />
<option name="y" value="50" />
<option name="width" value="2295" />
<option name="height" value="1235" />
</component>
<component name="ProjectLevelVcsManager">
<ConfirmationsSetting value="2" id="Add" />
</component>
<component name="ProjectView">
<navigator proportions="" version="1">
<foldersAlwaysOnTop value="true" />
</navigator>
<panes>
<pane id="ProjectPane">
<subPane>
<expand>
<path>
<item name="simple-php-router" type="b2602c69:ProjectViewProjectNode" />
<item name="simple-php-router" type="2a2b976b:PhpTreeStructureProvider$1" />
</path>
<path>
<item name="simple-php-router" type="b2602c69:ProjectViewProjectNode" />
<item name="simple-php-router" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="src" type="2a2b976b:PhpTreeStructureProvider$1" />
</path>
<path>
<item name="simple-php-router" type="b2602c69:ProjectViewProjectNode" />
<item name="simple-php-router" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="src" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="Pecee" type="2a2b976b:PhpTreeStructureProvider$1" />
</path>
<path>
<item name="simple-php-router" type="b2602c69:ProjectViewProjectNode" />
<item name="simple-php-router" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="src" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="Pecee" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="Http" type="2a2b976b:PhpTreeStructureProvider$1" />
</path>
<path>
<item name="simple-php-router" type="b2602c69:ProjectViewProjectNode" />
<item name="simple-php-router" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="src" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="Pecee" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="Http" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="Input" type="2a2b976b:PhpTreeStructureProvider$1" />
</path>
<path>
<item name="simple-php-router" type="b2602c69:ProjectViewProjectNode" />
<item name="simple-php-router" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="src" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="Pecee" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="SimpleRouter" type="2a2b976b:PhpTreeStructureProvider$1" />
</path>
<path>
<item name="simple-php-router" type="b2602c69:ProjectViewProjectNode" />
<item name="simple-php-router" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="src" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="Pecee" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="SimpleRouter" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="ClassLoader" type="2a2b976b:PhpTreeStructureProvider$1" />
</path>
<path>
<item name="simple-php-router" type="b2602c69:ProjectViewProjectNode" />
<item name="simple-php-router" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="src" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="Pecee" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="SimpleRouter" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="Handlers" type="2a2b976b:PhpTreeStructureProvider$1" />
</path>
<path>
<item name="simple-php-router" type="b2602c69:ProjectViewProjectNode" />
<item name="simple-php-router" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="src" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="Pecee" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="SimpleRouter" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="Route" type="2a2b976b:PhpTreeStructureProvider$1" />
</path>
<path>
<item name="simple-php-router" type="b2602c69:ProjectViewProjectNode" />
<item name="simple-php-router" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="tests" type="2a2b976b:PhpTreeStructureProvider$1" />
</path>
<path>
<item name="simple-php-router" type="b2602c69:ProjectViewProjectNode" />
<item name="simple-php-router" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="tests" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="Pecee" type="2a2b976b:PhpTreeStructureProvider$1" />
</path>
<path>
<item name="simple-php-router" type="b2602c69:ProjectViewProjectNode" />
<item name="simple-php-router" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="tests" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="Pecee" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="SimpleRouter" type="2a2b976b:PhpTreeStructureProvider$1" />
</path>
</expand>
<select />
</subPane>
</pane>
<pane id="Scope" />
</panes>
</component>
<component name="PropertiesComponent">
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="last_opened_file_path" value="$PROJECT_DIR$/../dscuz-v1" />
<property name="node.js.detected.package.eslint" value="true" />
<property name="node.js.detected.package.standard" value="true" />
<property name="node.js.path.for.package.eslint" value="project" />
<property name="node.js.path.for.package.standard" value="project" />
<property name="node.js.selected.package.eslint" value="" />
<property name="node.js.selected.package.standard" value="" />
<property name="run.code.analysis.last.selected.profile" value="pProject Default" />
<property name="settings.editor.selected.configurable" value="reference.webide.settings.project.settings.php" />
</component>
<component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS">
<recent name="E:\Workspace\simple-php-router\tests\Pecee\SimpleRouter" />
<recent name="D:\Workspace\simple-php-router\tests" />
<recent name="D:\Workspace\simple-php-router" />
<recent name="D:\Workspace\simple-php-router\test" />
<recent name="D:\Workspace\simple-php-router\src\Pecee\SimpleRouter\Route" />
</key>
<key name="MoveFile.RECENT_KEYS">
<recent name="E:\Workspace\simple-php-router\src\Pecee\SimpleRouter\ClassLoader\Containers" />
<recent name="E:\Workspace\simple-php-router\src\Pecee\SimpleRouter\ClassLoader" />
<recent name="E:\Workspace\simple-php-router\src\Pecee\SimpleRouter" />
<recent name="E:\Workspace\simple-php-router\src\Pecee\SimpleRouter\Handler" />
<recent name="D:\Workspace\simple-php-router\tests" />
</key>
</component>
<component name="RunDashboard">
<option name="ruleStates">
<list>
<RuleState>
<option name="name" value="ConfigurationTypeDashboardGroupingRule" />
</RuleState>
<RuleState>
<option name="name" value="StatusDashboardGroupingRule" />
</RuleState>
</list>
</option>
</component>
<component name="RunManager" selected="PHPUnit.phpunit.xml">
<configuration name="RouterUrlTest" type="PHPUnitRunConfigurationType" factoryName="PHPUnit" temporary="true">
<TestRunner class="RouterUrlTest" file="$PROJECT_DIR$/tests/Pecee/SimpleRouter/RouterUrlTest.php" scope="Class" />
</configuration>
<configuration name="phpunit.xml" type="PHPUnitRunConfigurationType" factoryName="PHPUnit" temporary="true">
<TestRunner configuration_file="$PROJECT_DIR$/phpunit.xml" scope="XML" use_alternative_configuration_file="true" />
</configuration>
<configuration name="tests" type="PHPUnitRunConfigurationType" factoryName="PHPUnit" temporary="true">
<TestRunner directory="$PROJECT_DIR$/tests" />
</configuration>
<configuration name="debug.php" type="PhpLocalRunConfigurationType" factoryName="PHP Console" temporary="true" path="$PROJECT_DIR$/tests/debug.php" />
<list>
<item itemvalue="PHPUnit.tests" />
<item itemvalue="PHPUnit.RouterUrlTest" />
<item itemvalue="PHPUnit.phpunit.xml" />
<item itemvalue="PHP Script.debug.php" />
</list>
<recent_temporary>
<list>
<item itemvalue="PHPUnit.phpunit.xml" />
<item itemvalue="PHPUnit.tests" />
<item itemvalue="PHP Script.debug.php" />
<item itemvalue="PHPUnit.RouterUrlTest" />
</list>
</recent_temporary>
</component>
<component name="SvnConfiguration">
<configuration />
</component>
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="a7058529-bdc4-40b4-a50d-c50564dc83f0" name="Default" comment="" />
<created>1502498236860</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1502498236860</updated>
<workItem from="1502498238130" duration="495000" />
<workItem from="1502589327470" duration="1325000" />
<workItem from="1502643621164" duration="1124000" />
<workItem from="1502665379176" duration="1624000" />
<workItem from="1502669212357" duration="163000" />
<workItem from="1503009054866" duration="109000" />
<workItem from="1503143546207" duration="965000" />
<workItem from="1503146420259" duration="656000" />
<workItem from="1503148077591" duration="1223000" />
<workItem from="1503157038418" duration="7000" />
<workItem from="1503418539960" duration="475000" />
<workItem from="1503499434906" duration="6410000" />
<workItem from="1503519096046" duration="649000" />
<workItem from="1503520310378" duration="280000" />
<workItem from="1503521737747" duration="856000" />
<workItem from="1503524427576" duration="2573000" />
<workItem from="1503536487719" duration="1589000" />
<workItem from="1503542802083" duration="820000" />
<workItem from="1503585789014" duration="820000" />
<workItem from="1504176764746" duration="658000" />
<workItem from="1504283976613" duration="694000" />
<workItem from="1504448385820" duration="7834000" />
<workItem from="1504459201935" duration="83000" />
<workItem from="1504459311471" duration="1376000" />
<workItem from="1504486369526" duration="451000" />
<workItem from="1504917061077" duration="1291000" />
<workItem from="1507375921398" duration="131000" />
<workItem from="1508785846050" duration="916000" />
<workItem from="1508786969551" duration="615000" />
<workItem from="1508787603350" duration="1889000" />
<workItem from="1509491007644" duration="14000" />
<workItem from="1509491033605" duration="6000" />
<workItem from="1510192196700" duration="11000" />
<workItem from="1510192217149" duration="152000" />
<workItem from="1510193026656" duration="140000" />
<workItem from="1511567082879" duration="3024000" />
<workItem from="1511629790083" duration="1115000" />
<workItem from="1511632906778" duration="6000" />
<workItem from="1511709768816" duration="954000" />
<workItem from="1511710733832" duration="10000" />
<workItem from="1511710754848" duration="6388000" />
<workItem from="1511717327384" duration="1762000" />
<workItem from="1511736112440" duration="855000" />
<workItem from="1511741616771" duration="3149000" />
<workItem from="1512583258866" duration="985000" />
<workItem from="1512706044104" duration="1603000" />
<workItem from="1521506970558" duration="7811000" />
<workItem from="1522072655826" duration="1072000" />
<workItem from="1522073747209" duration="63000" />
<workItem from="1522073847648" duration="23574000" />
<workItem from="1522309434425" duration="745000" />
<workItem from="1522310203119" duration="120000" />
<workItem from="1522310337826" duration="117000" />
<workItem from="1522310475899" duration="12840000" />
<workItem from="1522325810130" duration="30260000" />
<workItem from="1522360506281" duration="168000" />
<workItem from="1522378435862" duration="2772000" />
<workItem from="1522385007533" duration="189000" />
</task>
<servers />
</component>
<component name="TestHistory">
<history-entry file="phpunit_xml - 2018.03.29 at 20h 47m 20s.xml">
<configuration name="phpunit.xml" configurationId="PHPUnitRunConfigurationType" />
</history-entry>
<history-entry file="phpunit_xml - 2018.03.29 at 20h 48m 57s.xml">
<configuration name="phpunit.xml" configurationId="PHPUnitRunConfigurationType" />
</history-entry>
<history-entry file="phpunit_xml - 2018.03.29 at 20h 49m 08s.xml">
<configuration name="phpunit.xml" configurationId="PHPUnitRunConfigurationType" />
</history-entry>
<history-entry file="phpunit_xml - 2018.03.29 at 20h 50m 04s.xml">
<configuration name="phpunit.xml" configurationId="PHPUnitRunConfigurationType" />
</history-entry>
<history-entry file="phpunit_xml - 2018.03.29 at 20h 50m 18s.xml">
<configuration name="phpunit.xml" configurationId="PHPUnitRunConfigurationType" />
</history-entry>
<history-entry file="phpunit_xml - 2018.03.29 at 20h 50m 23s.xml">
<configuration name="phpunit.xml" configurationId="PHPUnitRunConfigurationType" />
</history-entry>
<history-entry file="phpunit_xml - 2018.03.29 at 21h 12m 55s.xml">
<configuration name="phpunit.xml" configurationId="PHPUnitRunConfigurationType" />
</history-entry>
<history-entry file="phpunit_xml - 2018.03.29 at 23h 09m 02s.xml">
<configuration name="phpunit.xml" configurationId="PHPUnitRunConfigurationType" />
</history-entry>
<history-entry file="phpunit_xml - 2018.03.29 at 23h 09m 18s.xml">
<configuration name="phpunit.xml" configurationId="PHPUnitRunConfigurationType" />
</history-entry>
<history-entry file="phpunit_xml - 2018.03.29 at 23h 09m 37s.xml">
<configuration name="phpunit.xml" configurationId="PHPUnitRunConfigurationType" />
</history-entry>
</component>
<component name="TimeTrackingManager">
<option name="totallyTimeSpent" value="138006000" />
</component>
<component name="TodoView">
<todo-panel id="selected-file">
<is-autoscroll-to-source value="true" />
</todo-panel>
<todo-panel id="all">
<are-packages-shown value="true" />
<is-autoscroll-to-source value="true" />
</todo-panel>
</component>
<component name="ToolWindowManager">
<frame x="-7" y="-7" width="2062" height="1126" extended-state="6" />
<editor active="true" />
<layout>
<window_info anchor="bottom" id="TODO" order="10" weight="0.32983023" />
<window_info anchor="bottom" id="Event Log" order="6" sideWeight="0.50919265" side_tool="true" weight="0.32902184" />
<window_info anchor="bottom" id="Database Changes" order="11" show_stripe_button="false" />
<window_info anchor="bottom" id="Run" order="2" sideWeight="0.49080735" weight="0.327405" />
<window_info anchor="bottom" id="Version Control" order="11" weight="0.32902184" />
<window_info anchor="bottom" id="Terminal" order="9" sideWeight="0.49680257" visible="true" weight="0.28282827" />
<window_info active="true" content_ui="combo" id="Project" order="0" visible="true" weight="0.19430569" />
<window_info anchor="bottom" id="Docker" order="7" show_stripe_button="false" />
<window_info anchor="right" id="Database" order="3" />
<window_info anchor="bottom" id="Find" order="1" sideWeight="0.48880896" weight="0.3272727" />
<window_info id="Structure" order="1" side_tool="true" weight="0.25" />
<window_info anchor="bottom" id="Debug" order="3" weight="0.4" />
<window_info id="Favorites" order="2" side_tool="true" />
<window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
<window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
<window_info anchor="bottom" id="PHP-CGI Server" order="8" />
<window_info anchor="right" id="Commander" order="0" weight="0.4" />
<window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
<window_info anchor="bottom" id="Inspection Results" order="12" weight="0.32902184" />
<window_info anchor="bottom" id="Message" order="0" />
<window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
</layout>
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="1" />
</component>
<component name="VcsContentAnnotationSettings">
<option name="myLimit" value="2678400000" />
</component>
<component name="XDebuggerManager">
<breakpoint-manager>
<option name="time" value="3" />
</breakpoint-manager>
</component>
<component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/src/Pecee/Http/Input/InputItem.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="80">
<caret line="4" column="37" selection-start-line="4" selection-start-column="37" selection-end-line="4" selection-end-column="37" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Pecee/Http/Url.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="9100">
<caret line="455" column="20" selection-end-line="460" selection-end-column="1" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Pecee/Http/Input/InputFile.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="180">
<caret line="9" column="17" lean-forward="true" selection-start-line="9" selection-start-column="17" selection-end-line="9" selection-end-column="17" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Pecee/Http/Input/IInputItem.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="380">
<caret line="19" column="40" selection-start-line="19" selection-start-column="40" selection-end-line="19" selection-end-column="40" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/README.md">
<provider selected="true" editor-type-id="split-provider[text-editor;markdown-preview-editor]">
<state split_layout="SPLIT">
<first_editor relative-caret-position="7400">
<caret line="370" column="1" selection-start-line="370" selection-start-column="1" selection-end-line="370" selection-end-column="1" />
</first_editor>
<second_editor />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Pecee/SimpleRouter/Router.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="9860">
<caret line="509" column="45" selection-start-line="509" selection-start-column="45" selection-end-line="509" selection-end-column="45" />
<folding>
<element signature="e#38#84#0#PHP" expanded="true" />
<marker date="1522357776600" expanded="true" signature="1690:1698" ph=" List of loaded exception that has been loaded. ..." />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/helpers.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="1420">
<caret line="74" selection-end-line="87" selection-end-column="1" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Pecee/SimpleRouter/SimpleRouter.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="5160">
<caret line="283" column="39" selection-start-line="283" selection-start-column="39" selection-end-line="283" selection-end-column="39" />
<folding>
<element signature="e#302#319#0#PHP" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Pecee/Http/Input/InputHandler.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="4460">
<caret line="224" column="80" selection-start-line="224" selection-start-column="80" selection-end-line="224" selection-end-column="80" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Pecee/SimpleRouter/IRouterBootManager.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="264">
<caret line="11" column="28" selection-start-line="11" selection-start-column="28" selection-end-line="11" selection-end-column="28" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Pecee/SimpleRouter/Route/IGroupRoute.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-288" />
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Pecee/SimpleRouter/Handlers/IExceptionHandler.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="48">
<caret line="2" column="10" lean-forward="true" selection-start-line="2" selection-start-column="10" selection-end-line="2" selection-end-column="28" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Pecee/SimpleRouter/Route/IRoute.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="258">
<caret line="27" column="20" selection-start-line="27" selection-start-column="20" selection-end-line="27" selection-end-column="20" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Pecee/SimpleRouter/Handlers/DebugEventHandler.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="168">
<caret line="7" column="38" lean-forward="true" selection-start-line="7" selection-start-column="38" selection-end-line="7" selection-end-column="38" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Pecee/SimpleRouter/Handlers/IEventHandler.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="552">
<caret line="23" column="20" selection-start-line="23" selection-start-column="20" selection-end-line="23" selection-end-column="20" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Pecee/SimpleRouter/Handlers/EventHandler.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="436">
<caret line="107" column="38" selection-start-line="107" selection-start-column="38" selection-end-line="107" selection-end-column="38" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Pecee/SimpleRouter/Event/EventArgument.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="54">
<caret line="45" column="26" lean-forward="true" selection-start-line="45" selection-start-column="26" selection-end-line="45" selection-end-column="26" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/tests/Pecee/SimpleRouter/EventHandlerTest.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="258">
<caret line="16" column="36" lean-forward="true" selection-end-line="80" selection-end-column="1" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Pecee/SimpleRouter/Handlers/CallbackExceptionHandler.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="48">
<caret line="2" selection-start-line="2" selection-end-line="2" selection-end-column="38" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/vendor/php-di/php-di/src/ContainerBuilder.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="210">
<caret line="121" column="21" selection-start-line="121" selection-start-column="21" selection-end-line="121" selection-end-column="21" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Pecee/SimpleRouter/ClassLoader/Containers/IContainer.php" />
<entry file="file://$PROJECT_DIR$/src/Pecee/SimpleRouter/ClassLoader/Containers/DIContainerBuilder.php" />
<entry file="file://$PROJECT_DIR$/vendor/php-di/php-di/src/FactoryInterface.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="267">
<caret line="14" column="10" selection-start-line="14" selection-start-column="10" selection-end-line="14" selection-end-column="10" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/vendor/php-di/invoker/src/InvokerInterface.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="264">
<caret line="13" column="10" selection-start-line="13" selection-start-column="10" selection-end-line="13" selection-end-column="10" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/vendor/psr/container/src/ContainerInterface.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="192">
<caret line="10" column="10" selection-start-line="10" selection-start-column="10" selection-end-line="10" selection-end-column="10" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Pecee/SimpleRouter/ClassLoader/IContainer.php" />
<entry file="file://$PROJECT_DIR$/vendor/mockery/mockery/library/Mockery/Container.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-3360">
<caret line="26" column="6" selection-start-line="26" selection-start-column="6" selection-end-line="26" selection-end-column="6" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/vendor/php-di/php-di/src/Container.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-21">
<caret line="266" column="20" selection-start-line="266" selection-start-column="20" selection-end-line="266" selection-end-column="20" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Pecee/SimpleRouter/ClassLoader/IClassLoader.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="144">
<caret line="6" selection-start-line="6" selection-end-line="6" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/tmp/CompiledContainer.php" />
<entry file="file://$PROJECT_DIR$/tests/TestRouter.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="474">
<caret line="24" column="30" selection-start-line="24" selection-start-column="30" selection-end-line="24" selection-end-column="30" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/composer.json">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="370">
<caret line="30" column="27" selection-start-line="30" selection-start-column="27" selection-end-line="30" selection-end-column="27" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Pecee/SimpleRouter/ClassLoader/ClassLoader.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="384">
<caret line="34" column="47" selection-start-line="34" selection-start-column="47" selection-end-line="34" selection-end-column="47" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/tests/Pecee/SimpleRouter/GroupTest.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="258">
<caret line="21" column="8" selection-start-line="21" selection-start-column="8" selection-end-line="21" selection-end-column="8" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/tests/Pecee/SimpleRouter/InputHandlerTest.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="267">
<caret line="16" column="8" selection-start-line="16" selection-start-column="8" selection-end-line="16" selection-end-column="8" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/tests/Pecee/SimpleRouter/RouterRouteTest.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="572">
<caret line="105" column="33" selection-start-line="105" selection-start-column="33" selection-end-line="105" selection-end-column="33" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/tests/Pecee/SimpleRouter/Dummy/Exception/ResponseException.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="192">
<caret line="8" column="8" selection-start-line="8" selection-start-column="8" selection-end-line="8" selection-end-column="8" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/tests/Pecee/SimpleRouter/DependencyInjectionTest.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="696">
<caret line="29" column="38" selection-start-line="29" selection-start-column="38" selection-end-line="29" selection-end-column="38" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Pecee/Http/Request.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="316">
<caret line="223" column="5" selection-start-line="223" selection-start-column="5" selection-end-line="223" selection-end-column="5" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Pecee/SimpleRouter/Router.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="9860">
<caret line="509" column="45" selection-start-line="509" selection-start-column="45" selection-end-line="509" selection-end-column="45" />
<folding>
<element signature="e#38#84#0#PHP" expanded="true" />
<marker date="1522357776600" expanded="true" signature="1690:1698" ph=" List of loaded exception that has been loaded. ..." />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Pecee/SimpleRouter/SimpleRouter.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="5160">
<caret line="283" column="39" selection-start-line="283" selection-start-column="39" selection-end-line="283" selection-end-column="39" />
<folding>
<element signature="e#302#319#0#PHP" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Pecee/Http/Input/InputHandler.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="4460">
<caret line="224" column="80" selection-start-line="224" selection-start-column="80" selection-end-line="224" selection-end-column="80" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Pecee/Http/Input/IInputItem.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="380">
<caret line="19" column="40" selection-start-line="19" selection-start-column="40" selection-end-line="19" selection-end-column="40" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Pecee/Http/Url.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="9100">
<caret line="455" column="20" selection-end-line="460" selection-end-column="1" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Pecee/Http/Input/InputItem.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="80">
<caret line="4" column="37" selection-start-line="4" selection-start-column="37" selection-end-line="4" selection-end-column="37" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Pecee/Http/Input/InputFile.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="180">
<caret line="9" column="17" selection-start-line="9" selection-start-column="17" selection-end-line="9" selection-end-column="17" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/helpers.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="1340">
<caret line="70" column="5" selection-start-line="70" selection-start-column="5" selection-end-line="70" selection-end-column="5" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/README.md">
<provider selected="true" editor-type-id="split-provider[text-editor;markdown-preview-editor]">
<state split_layout="SPLIT">
<first_editor relative-caret-position="619">
<caret line="370" column="1" selection-start-line="370" selection-start-column="1" selection-end-line="370" selection-end-column="1" />
</first_editor>
<second_editor />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Pecee/SimpleRouter/Route/LoadableRoute.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="357">
<caret line="160" lean-forward="true" selection-start-line="160" selection-end-line="160" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Pecee/SimpleRouter/Route/ILoadableRoute.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="900">
<caret line="46" column="20" selection-start-line="46" selection-start-column="20" selection-end-line="46" selection-end-column="20" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Pecee/SimpleRouter/Route/Route.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-2762">
<caret line="194" column="25" selection-start-line="194" selection-start-column="25" selection-end-line="194" selection-end-column="25" />
</state>
</provider>
</entry>
</component>
</project>
-13
View File
@@ -1,13 +0,0 @@
build:
tests:
override:
-
command: './vendor/bin/phpunit --coverage-clover=coverage.clover'
coverage:
file: 'coverage.clover'
format: 'clover'
checks:
php:
code_rating: true
duplication: true
-13
View File
@@ -1,13 +0,0 @@
sudo: false
language: php
php:
- 7.1
before_script:
- curl -sS http://getcomposer.org/installer | php
- php composer.phar install --prefer-source --no-interaction
script:
- ./vendor/bin/phpunit
+108 -614
View File
@@ -1,20 +1,18 @@
# simple-router
# Simple PHP router
Simple, fast and yet powerful PHP router that is easy to get integrated and in any project. Heavily inspired by the way Laravel handles routing, with both simplicity and expandability in mind.
Simple, fast and yet powerful PHP router that is easy to get integrated and in any project.
Heavily inspired by the way Laravel handles routing, with both simplicity and expand-ability in mind.
**Please note that this documentation is currently work-in-progress. Feel free to contribute.**
### Support the project
If you like simple-router and wish to see the continued development and maintenance of the project,
please consider showing your support by buying me a coffee. Supporters will be listed under the credits section of this documentation.
You can donate any amount of your choice by [clicking here](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=NNX4D2RUSALCN).
---
## Table of Contents
- [Getting started](#getting-started)
- [Notes](#notes-1)
- [Requirements](#requirements)
- [Feedback and development](#feedback-and-development)
- [Issues guidelines](#issues-guidelines)
- [Contribution development guidelines](#contribution-development-guidelines)
- [Features](#features)
- [Installation](#installation)
- [Setting up Apache](#setting-up-apache)
@@ -42,39 +40,35 @@ You can donate any amount of your choice by [clicking here](https://www.paypal.c
- [Partial groups](#partial-groups)
- [Form Method Spoofing](#form-method-spoofing)
- [Accessing The Current Route](#accessing-the-current-route)
- [Dependency injection](#dependency-injection)
- [Enabling dependency injection](#enabling-dependency-injection)
- [More reading](#more-reading)
- [Other examples](#other-examples)
- [CSRF-protection](#csrf-protection)
- [Adding CSRF-verifier](#adding-csrf-verifier)
- [Getting CSRF-token](#getting-csrf-token)
- [Custom CSRF-verifier](#custom-csrf-verifier)
- [Custom Token-provider](#custom-token-provider)
- [Middlewares](#middlewares)
- [Example](#example-1)
- [Example](#example)
- [ExceptionHandlers](#exceptionhandlers)
- [Handling 404, 403 and other errors](#handling-404-403-and-other-errors)
- [Using custom exception handlers](#using-custom-exception-handlers)
- [Urls](#urls)
- [Get the current url](#get-the-current-url)
- [Get by name (single route)](#get-by-name-single-route)
- [Get by name (controller route)](#get-by-name-controller-route)
- [Get by class](#get-by-class)
- [Using custom names for methods on a controller/resource route](#using-custom-names-for-methods-on-a-controllerresource-route)
- [Get by custom names for methods on a controller/resource route](#using-custom-names-for-methods-on-a-controllerresource-route)
- [Getting REST/resource controller urls](#getting-restresource-controller-urls)
- [Manipulating url](#manipulating-url)
- [Useful url tricks](#useful-url-tricks)
- [Get the current url](#get-the-current-url)
- [Input & parameters](#input--parameters)
- [Using the Input class to manage parameters](#using-the-input-class-to-manage-parameters)
- [Get single parameter value](#get-single-parameter-value)
- [Get parameter object](#get-parameter-object)
- [Managing files](#managing-files)
- [Get all parameters](#get-all-parameters)
- [Events](#events)
- [Available events](#available-events)
- [Registering new event](#registering-new-event)
- [Custom EventHandlers](#custom-eventhandlers)
- [Advanced](#advanced)
- [Url rewriting](#url-rewriting)
- [Changing current route](#changing-current-route)
@@ -82,17 +76,7 @@ You can donate any amount of your choice by [clicking here](https://www.paypal.c
- [Adding routes manually](#adding-routes-manually)
- [Parameters](#parameters)
- [Extending](#extending)
- [Help and support](#help-and-support)
- [Common issues and fixes](#common-issues-and-fixes)
- [Debugging](#debugging)
- [Creating unit-tests](#creating-unit-tests)
- [Debug information](#debug-information)
- [Benchmark and log-info](#benchmark-and-log-info)
- [Reporting a new issue](#reporting-a-new-issue)
- [Procedure for reporting a new issue](#procedure-for-reporting-a-new-issue)
- [Issue template](#issue-template)
- [Feedback and development](#feedback-and-development)
- [Contribution development guidelines](#contribution-development-guidelines)
- [Credits](#credits)
- [Sites](#sites)
- [License](#license)
@@ -100,8 +84,7 @@ You can donate any amount of your choice by [clicking here](https://www.paypal.c
___
# Getting started
Add the latest version of the simple-router project running this command.
Add the latest version of Simple PHP Router running this command.
```
composer require pecee/simple-router
@@ -131,7 +114,33 @@ You can find the demo-project here: [https://github.com/skipperbent/simple-route
## Requirements
- PHP 7.1 or greater (version 3.x and below supports PHP 5.5+)
- PHP 5.5 or greater
### Feedback and development
If you are missing a feature, experience problems or have ideas or feedback that you want us to hear, please feel free to create an issue.
###### Issues guidelines
- Please be as detailed as possible in the description when creating a new issue. This will help others to more easily understand- and solve your issue.
For example: if you are experiencing issues, you should provide the necessary steps to reproduce the error within your description.
- We love to hear out any ideas or feedback to the library.
[Create a new issue here](https://github.com/skipperbent/simple-php-router/issues/new)
###### Contribution development guidelines
- Please try to follow the PSR-2 codestyle guidelines.
- Please create your pull requests to the development base that matches the version number you want to change.
For example when pushing changes to version 3, the pull request should use the `v3-development` base/branch.
- Create detailed descriptions for your commits, as these will be used in the changelog for new releases.
- When changing existing functionality, please ensure that the unit-tests working.
- When adding new stuff, please remember to add new unit-tests for the functionality.
## Features
@@ -197,7 +206,7 @@ Below is an example of an working `web.config` file used by simple-php-router.
Simply create a new `web.config` file in your projects `public` directory and paste the contents below in your newly created file. This will redirect all requests to your `index.php` file (see Configuration section below). If the `web.config` file already exists, add the `<rewrite>` section inside the `<system.webServer>` branch.
```xml
```
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
@@ -281,12 +290,7 @@ We recommend that you add these helper functions to your project. These will all
To implement the functions below, simply copy the code to a new file and require the file before initializing the router or copy the `helpers.php` we've included in this library.
```php
<?php
use Pecee\SimpleRouter\SimpleRouter as Router;
use Pecee\Http\Url;
use Pecee\Http\Response;
use Pecee\Http\Request;
/**
* Get url for a route by using either name/alias, class or method name.
@@ -303,10 +307,9 @@ use Pecee\Http\Request;
* @param string|null $name
* @param string|array|null $parameters
* @param array|null $getParams
* @return \Pecee\Http\Url
* @throws \InvalidArgumentException
* @return string
*/
function url(?string $name = null, $parameters = null, ?array $getParams = null): Url
function url($name = null, $parameters = null, $getParams = null)
{
return Router::getUrl($name, $parameters, $getParams);
}
@@ -314,7 +317,7 @@ function url(?string $name = null, $parameters = null, ?array $getParams = null)
/**
* @return \Pecee\Http\Response
*/
function response(): Response
function response()
{
return Router::response();
}
@@ -322,7 +325,7 @@ function response(): Response
/**
* @return \Pecee\Http\Request
*/
function request(): Request
function request()
{
return Router::request();
}
@@ -331,23 +334,19 @@ function request(): Request
* Get input class
* @param string|null $index Parameter index name
* @param string|null $defaultValue Default return value
* @param array ...$methods Default methods
* @return \Pecee\Http\Input\InputHandler|string
* @param string|array|null $methods Default method
* @return \Pecee\Http\Input\Input|string
*/
function input($index = null, $defaultValue = null, ...$methods)
function input($index = null, $defaultValue = null, $methods = null)
{
if ($index !== null) {
return request()->getInputHandler()->getValue($index, $defaultValue, ...$methods);
return request()->getInput()->get($index, $defaultValue, $methods);
}
return request()->getInputHandler();
return request()->getInput();
}
/**
* @param string $url
* @param int|null $code
*/
function redirect(string $url, ?int $code = null): void
function redirect($url, $code = null)
{
if ($code !== null) {
response()->httpCode($code);
@@ -360,11 +359,11 @@ function redirect(string $url, ?int $code = null): void
* Get current csrf-token
* @return string|null
*/
function csrf_token(): ?string
function csrf_token()
{
$baseVerifier = Router::router()->getCsrfVerifier();
if ($baseVerifier !== null) {
return $baseVerifier->getTokenProvider()->getToken();
return $baseVerifier->getToken();
}
return null;
@@ -662,88 +661,6 @@ SimpleRouter::request()->getLoadedRoute();
request()->getLoadedRoute();
```
## Dependency injection
simple-router supports dependency injection using the [`php-di`](http://php-di.org/) library.
Dependency injection allows the framework to automatically "inject" (load) classes added as parameters. This can simplify your code, as you can avoid creating new instances of objects you are using often in your `Controllers` etc.
Here's a basic example of a controller class using dependency injection:
```php
namespace Demo\Controllers;
class DefaultController {
public function login(User $user): string
{
// ...
}
}
```
The example above will automatically create a new instance of the `User` from the `$user` parameter. This means that the `$user` class contains a new instance of the `User` class and we won't need to create a new instance our self.
**WARNING:** dependency injection can have some negative impact in performance. If you experience any performance issues, we recommend disabling this functionality.
### Enabling dependency injection
Dependency injection is disabled per default to avoid any performance issues.
Before enabling dependency injection, we recommend that you read the [Container configuration](http://php-di.org/doc/container-configuration.html) section of the php-di documentation. This section covers how to configure php-di to different environments and speed-up the performance.
#### Enabling for development environment
The example below should ONLY be used on a development environment.
```php
// Create our new php-di container
$container = (new \DI\ContainerBuilder())
->useAutowiring(true)
->build();
// Add our container to simple-router and enable dependency injection
SimpleRouter::enableDependencyInjection($container);
```
Please check the [More reading](#more-reading) section of the documentation for useful php-di links and tutorials.
#### Enabling for production environment
The example below compiles the injections, which can help speed up performance.
**Note:** You should change the `$cacheDir` to a cache-storage within your project.
```php
// Cache directory
$cacheDir = sys_get_temp_dir('simple-router');
// Create our new php-di container
$container = (new \DI\ContainerBuilder())
->enableCompilation($cacheDir)
->writeProxiesToFile(true, $cacheDir . '/proxies')
->useAutowiring(true)
->build();
// Add our container to simple-router and enable dependency injection
SimpleRouter::enableDependencyInjection($container);
```
Please check the [More reading](#more-reading) section of the documentation for useful php-di links and tutorials.
### More reading
For more information about dependency injection, configuration and settings - we recommend that you check the php-di documentation or some of the useful links we've gathered below.
#### Useful links
- [php-di documentation](http://php-di.org/doc/)
- [Understanding dependency injection](http://php-di.org/doc/understanding-di.html)
- [Best practices guide](http://php-di.org/doc/best-practices.html)
- [Configuring the container](http://php-di.org/doc/container-configuration.html)
- [Definitions](http://php-di.org/doc/definition.html)
## Other examples
You can find many more examples in the `routes.php` example-file below:
@@ -874,7 +791,7 @@ class SessionTokenProvider implements ITokenProvider
/**
* Refresh existing token
*/
public function refresh(): void
public function refresh()
{
// Implement your own functionality here...
}
@@ -885,18 +802,7 @@ class SessionTokenProvider implements ITokenProvider
* @param string $token
* @return bool
*/
public function validate($token): bool
{
// Implement your own functionality here...
}
/**
* Get token token
*
* @param string|null $defaultValue
* @return string|null
*/
public function getToken(?string $defaultValue = null): ?string
public function validate($token)
{
// Implement your own functionality here...
}
@@ -927,17 +833,17 @@ namespace Demo\Middlewares;
use Pecee\Http\Middleware\IMiddleware;
use Pecee\Http\Request;
class CustomMiddleware implements IMiddleware {
class CustomMiddleware implements Middleware {
public function handle(Request $request) {
public function handle(Request $request): void
{
// Authenticate user, will be available using request()->user
$request->user = User::authenticate();
// If authentication failed, redirect request to user-login page.
if($request->user === null) {
$request->setRewriteUrl(url('user.login'));
return $request;
}
}
@@ -963,11 +869,9 @@ The code should be placed in the file that contains your routes.
Router::get('/not-found', 'PageController@notFound');
Router::error(function(Request $request, \Exception $exception) {
if($exception instanceof NotFoundHttpException && $exception->getCode() === 404) {
if($exception instanceof NotFoundHttpException && $exception->getCode() == 404) {
response()->redirect('/not-found');
}
});
```
@@ -978,18 +882,18 @@ This is a basic example of an ExceptionHandler implementation (please see "[Easi
```php
namespace Demo\Handlers;
use Pecee\Handlers\IExceptionHandler;
use Pecee\Http\Request;
use Pecee\SimpleRouter\Handlers\IExceptionHandler;
use Pecee\SimpleRouter\Exceptions\NotFoundHttpException;
class CustomExceptionHandler implements IExceptionHandler
{
public function handleError(Request $request, \Exception $error): void
public function handleError(Request $request, \Exception $error)
{
/* You can use the exception handler to format errors depending on the request and type. */
if ($request->getUrl()->contains('/api')) {
if (stripos($request->getUrl()->getPath(), '/api') !== false) {
response()->json([
'error' => $error->getMessage(),
@@ -1002,9 +906,10 @@ class CustomExceptionHandler implements IExceptionHandler
if($error instanceof NotFoundHttpException) {
// Render custom 404-page
$request->setRewriteCallback('Demo\Controllers\PageController@notFound');
return;
return $request;
}
throw $error;
@@ -1020,33 +925,17 @@ class CustomExceptionHandler implements IExceptionHandler
By default all controller and resource routes will use a simplified version of their url as name.
You easily use the `url()` shortcut helper function to retrieve urls for your routes or manipulate the current url.
`url()` will return a `Url` object which will return a `string` when rendered, so it can be used safely in templates etc. but
contains all the useful helpers methods in the `Url` class like `contains`, `indexOf` etc.
Check the [Useful url tricks](#useful-url-tricks) below.
### Get the current url
It has never been easier to get and/or manipulate the current url.
The example below shows you how to get the current url:
```php
# output: /current-url
url();
```
### Get by name (single route)
```php
SimpleRouter::get('/product-view/{id}', 'ProductsController@show', ['as' => 'product']);
# output: /product-view/22/?category=shoes
url('product', ['id' => 22], ['category' => 'shoes']);
# output: /product-view/?category=shoes
url('product', null, ['category' => 'shoes']);
# output
# /product-view/22/?category=shoes
# /product-view/?category=shoes
```
### Get by name (controller route)
@@ -1054,14 +943,14 @@ url('product', null, ['category' => 'shoes']);
```php
SimpleRouter::controller('/images', ImagesController::class, ['as' => 'picture']);
# output: /images/view/?category=shows
url('picture@getView', null, ['category' => 'shoes']);
# output: /images/view/?category=shows
url('picture', 'getView', ['category' => 'shoes']);
# output: /images/view/
url('picture', 'view');
# output
# /images/view/?category=shows
# /images/view/?category=shows
# /images/view/
```
### Get by class
@@ -1070,11 +959,12 @@ url('picture', 'view');
SimpleRouter::get('/product-view/{id}', 'ProductsController@show', ['as' => 'product']);
SimpleRouter::controller('/images', 'ImagesController');
# output: /product-view/22/?category=shoes
url('ProductsController@show', ['id' => 22], ['category' => 'shoes']);
# output: /images/image/?id=22
url('ImagesController@getImage', null, ['id' => 22]);
# output
# /product-view/22/?category=shoes
# /images/image/?id=22
```
### Using custom names for methods on a controller/resource route
@@ -1093,67 +983,30 @@ url('gadgets.iphone');
```php
SimpleRouter::resource('/phones', PhonesController::class);
# output: /phones/
url('phones');
# output: /phones/
url('phones.index');
# output: /phones/create/
url('phones.create');
# output: /phones/edit/
url('phones.edit');
// etc..
# output
# /phones/
# /phones/create/
# /phones/edit/
```
### Manipulating url
You can easily manipulate the query-strings, by adding your get param arguments.
### Get the current url
```php
# output: /current-url?q=cars
url();
url(null, null, ['q' => 'cars']);
# output
# /CURRENT-URL/
# /CURRENT-URL/?q=cars
```
You can remove a query-string parameter by setting the value to `null`.
The example below will remove any query-string parameter named `q` from the url but keep all others query-string parameters:
```php
$url = url()->removeParam('q');
```
For more information please check the [Useful url tricks](#useful-url-tricks) section of the documentation.
### Useful url tricks
Calling `url` will always return a `Url` object. Upon rendered it will return a `string` of the relative `url`, so it's safe to use in templates etc.
However this allow us to use the useful methods on the `Url` object like `indexOf` and `contains` or retrieve specific parts of the url like the path, querystring parameters, host etc. You can also manipulate the url like removing- or adding parameters, changing host and more.
In the example below, we check if the current url contains the `/api` part.
```php
if(url()->contains('/api')) {
// ... do stuff
}
```
As mentioned earlier, you can also use the `Url` object to show specific parts of the url or control what part of the url you want.
```php
# Grab the query-string parameter id from the current-url.
$id = url()->getParam('id');
# Get the absolute url for the current url.
$absoluteUrl = url()->getAbsoluteUrl();
```
For more available methods please check the `Pecee\Http\Url` class.
# Input & parameters
## Using the Input class to manage parameters
@@ -1172,16 +1025,18 @@ $value = input($index, $defaultValue, $methods);
### Get parameter object
The example below will return an instance of `InputItem` or `InputFile` depending on the type.
Will return an instance of `InputItem` or `InputFile` depending on the type.
You can use this in your html as it will render the value of the item.
If you want to compare value in your if statements, you have to use the `getValue` or use the `input()` helper function instead.
However if you want to compare value in your if statements, you have to use
the `getValue` or use the `input()` instead.
If items is grouped in the html, it will return an array of items.
**Note:** `getObject` will only return `$defaultValue` if the item doesn't exist. If you want `$defaultValue` to be returned if the item is empty, please use `input()` instead.
```php
$object = input()->get($index, $defaultValue = null, $methods = null);
$object = input()->getObject($index, $defaultValue = null, $methods = null);
```
### Return specific GET parameter (where name is the name of your parameter):
@@ -1195,7 +1050,7 @@ $object = input()->get($index, $defaultValue = null, $methods = null);
* $defaultValue is returned if the value is empty.
*/
$id = input()->getValue($index, $defaultValue, $method);
$id = input()->get($index, $defaultValue, $method);
# -- shortcut to above --
@@ -1203,19 +1058,15 @@ $id = input($index, $defaultValue, $method);
# -- match specific --
$value = input($index, $defaultValue, 'get');
$value = input($index, $defaultValue, 'post');
$value = input($index, $defaultValue, 'file');
$object = input($index, $defaultValue, 'get');
$object = input($index, $defaultValue, 'post');
$object = input($index, $defaultValue, 'file');
# -- or --
$object = input()->findGet($index, $defaultValue);
$object = input()->findPost($index, $defaultValue);
$object = input()->findFile($index, $defaultValue);
# -- get the full object --
$object = input()->get($index, 'post', 'get');
```
### Managing files
@@ -1280,141 +1131,6 @@ $siteId = input('site_id', 2, ['post', 'get']);
---
# Events
This section will help you understand how to register your own callbacks to events in the router.
It will also cover the basics of event-handlers; how to use the handlers provided with the router and how to create your own custom event-handlers.
## Available events
This section contains all available events that can be registered using the `EventHandler`.
All event callbacks will retrieve a `EventArgument` object as parameter. This object contains easy access to event-name, router- and request instance and any special event-arguments related to the given event. You can see what special event arguments each event returns in the list below.
| Name | Special arguments | Description |
| ------------- |----------- | ---- |
| `EVENT_ALL` | - | Fires when a event is triggered. |
| `EVENT_INIT` | - | Fires when router is initializing and before routes are loaded. |
| `EVENT_LOAD` | `loadedRoutes` | Fires when all routes has been loaded and rendered, just before the output is returned. |
| `EVENT_REWRITE` | `rewriteUrl`<br>`rewriteRoute` | Fires when a url-rewrite is and just before the routes are re-initialized. |
| `EVENT_BOOT` | `bootmanagers` | Fires when the router is booting. This happens just before boot-managers are rendered and before any routes has been loaded. |
| `EVENT_RENDER_BOOTMANAGER` | `bootmanagers`<br>`bootmanager` | Fires before a boot-manager is rendered. |
| `EVENT_LOAD_ROUTES` | `routes` | Fires when the router is about to load all routes. |
| `EVENT_FIND_ROUTE` | `name` | Fires whenever the `findRoute` method is called within the `Router`. This usually happens when the router tries to find routes that contains a certain url, usually after the `EventHandler::EVENT_GET_URL` event. |
| `EVENT_GET_URL` | `name`<br>`parameters`<br>`getParams` | Fires whenever the `Router::getUrl` method or `url`-helper function is called and the router tries to find the route. |
| `EVENT_MATCH_ROUTE` | `route` | Fires when a route is matched and valid (correct request-type etc). and before the route is rendered. |
| `EVENT_RENDER_ROUTE` | `route` | Fires before a route is rendered. |
| `EVENT_LOAD_EXCEPTIONS` | `exception`<br>`exceptionHandlers` | Fires when the router is loading exception-handlers. |
| `EVENT_RENDER_EXCEPTION` | `exception`<br>`exceptionHandler`<br>`exceptionHandlers` | Fires before the router is rendering a exception-handler. |
| `EVENT_RENDER_MIDDLEWARES` | `route`<br>`middlewares` | Fires before middlewares for a route is rendered. |
| `EVENT_RENDER_CSRF` | `csrfVerifier` | Fires before the CSRF-verifier is rendered. |
## Registering new event
To register a new event you need to create a new instance of the `EventHandler` object. On this object you can add as many callbacks as you like by calling the `registerEvent` method.
When you've registered events, make sure to add it to the router by calling
`SimpleRouter::addEventHandler()`. We recommend that you add your event-handlers within your `routes.php`.
**Example:**
```php
use Pecee\SimpleRouter\Handlers\EventHandler;
use Pecee\SimpleRouter\Event\EventArgument;
// --- your routes goes here ---
$eventHandler = new EventHandler();
// Add event that fires when a route is rendered
$eventHandler->register(EventHandler::EVENT_RENDER_ROUTE, function(EventArgument $argument) {
// Get the route by using the special argument for this event.
$route = $argument->route;
// DO STUFF...
});
SimpleRouter::addEventHandler($eventHandler);
```
## Custom EventHandlers
`EventHandler` is the class that manages events and must inherit from the `IEventHandler` interface. The handler knows how to handle events for the given handler-type.
Most of the time the basic `\Pecee\SimpleRouter\Handler\EventHandler` class will be more than enough for most people as you simply register an event which fires when triggered.
Let's go over how to create your very own event-handler class.
Below is a basic example of a custom event-handler called `DatabaseDebugHandler`. The idea of the sample below is to logs all events to the database when triggered. Hopefully it will be enough to give you an idea on how the event-handlers work.
```php
namespace Demo\Handlers;
use Pecee\SimpleRouter\Event\EventArgument;
use Pecee\SimpleRouter\Router;
class DatabaseDebugHandler implements IEventHandler
{
/**
* Debug callback
* @var \Closure
*/
protected $callback;
public function __construct()
{
$this->callback = function (EventArgument $argument) {
// todo: store log in database
};
}
/**
* Get events.
*
* @param string|null $name Filter events by name.
* @return array
*/
public function getEvents(?string $name): array
{
return [
$name => [
$this->callback,
],
];
}
/**
* Fires any events registered with given event-name
*
* @param Router $router Router instance
* @param string $name Event name
* @param array ...$eventArgs Event arguments
*/
public function fireEvents(Router $router, string $name, ...$eventArgs): void
{
$callback = $this->callback;
$callback(new EventArgument($router, $eventArgs));
}
/**
* Set debug callback
*
* @param \Closure $event
*/
public function setCallback(\Closure $event): void
{
$this->callback = $event;
}
}
```
---
# Advanced
## Url rewriting
@@ -1445,19 +1161,10 @@ To interfere with the router, we create a class that implements the ```IRouterBo
```php
use Pecee\Http\Request;
use Pecee\SimpleRouter\IRouterBootManager;
use Pecee\SimpleRouter\Router;
class CustomRouterRules implement IRouterBootManager
{
class CustomRouterRules implement IRouterBootManager {
/**
* Called when router is booting and before the routes is loaded.
*
* @param \Pecee\SimpleRouter\Router $router
* @param \Pecee\Http\Request $request
*/
public function boot(\Pecee\SimpleRouter\Router $router, \Pecee\Http\Request $request): void
{
public function boot(Request $request) {
$rewriteRules = [
'/my-cat-is-beatiful' => '/article/view/1',
@@ -1551,219 +1258,6 @@ class Router extends SimpleRouter {
---
# Help and support
This section will go into details on how to debug the router and answer some of the commonly asked questions- and issues.
## Common issues and fixes
This section will go over common issues and how to resolve them.
## Debugging
This section will show you how to write unit-tests for the router, view useful debugging information and answer some of the frequently asked questions.
It will also covers how to report any issue you might encounter.
### Creating unit-tests
The easiest and fastest way to debug any issues with the router, is to create a unit-test that represents the issue you are experiencing.
Unit-tests use a special `TestRouter` class, which simulates a request-method and requested url of a browser.
The `TestRouter` class can return the output directly or render a route silently.
```php
public function testUnicodeCharacters()
{
// Add route containing two optional paramters with special spanish characters like "í".
TestRouter::get('/cursos/listado/{listado?}/{category?}', 'DummyController@method1', ['defaultParameterRegex' => '[\w\p{L}\s-]+']);
// Start the routing and simulate the url "/cursos/listado/especialidad/cirugía local".
TestRouter::debugNoReset('/cursos/listado/especialidad/cirugía local', 'GET');
// Verify that the url for the loaded route matches the expected route.
$this->assertEquals('/cursos/listado/{listado?}/{category?}/', TestRouter::router()->getRequest()->getLoadedRoute()->getUrl());
// Start the routing and simulate the url "/test/Dermatología" using "GET" as request-method.
TestRouter::debugNoReset('/test/Dermatología', 'GET');
// Another route containing one parameter with special spanish characters like "í".
TestRouter::get('/test/{param}', 'DummyController@method1', ['defaultParameterRegex' => '[\w\p{L}\s-\í]+']);
// Get all parameters parsed by the loaded route.
$parameters = TestRouter::request()->getLoadedRoute()->getParameters();
// Check that the parameter named "param" matches the exspected value.
$this->assertEquals('Dermatología', $parameters['param']);
// Add route testing danish special characters like "ø".
TestRouter::get('/category/økse', 'DummyController@method1', ['defaultParameterRegex' => '[\w\ø]+']);
// Start the routing and simulate the url "/kategory/økse" using "GET" as request-method.
TestRouter::debugNoReset('/category/økse', 'GET');
// Validate that the URL of the loaded-route matches the expected url.
$this->assertEquals('/category/økse/', TestRouter::router()->getRequest()->getLoadedRoute()->getUrl());
// Reset the router, so other tests wont inherit settings or the routes we've added.
TestRouter::router()->reset();
}
```
#### Using the TestRouter helper
Depending on your test, you can use the methods below when rendering routes in your unit-tests.
| Method | Description |
| ------------- |-------------|
| ```TestRouter::debug($url, $method)``` | Will render the route without returning anything. Exceptions will be thrown and the router will be reset automatically. |
| ```TestRouter::debugOutput($url, $method)``` | Will render the route and return any value that the route might output. Manual reset required by calling `TestRouter::router()->reset()`. |
| ```TestRouter::debugNoReset($url, $method);``` | Will render the route without resetting the router. Useful if you need to get loaded route, parameters etc. from the router. Manual reset required by calling `TestRouter::router()->reset()`. |
### Debug information
The library can output debug-information, which contains information like loaded routes, the parsed request-url etc. It also contains info which are important when reporting a new issue like PHP-version, library version, server-variables, router debug log etc.
You can activate the debug-information by calling the alternative start-method.
The example below will start the routing an return array with debugging-information
**Example:**
```php
$debugInfo = SimpleRouter::startDebug();
echo sprintf('<pre>%s</pre>', var_export($debugInfo));
exit;
```
**The example above will provide you with an output containing:**
| Key | Description |
| ------------- |------------- |
| `url` | The parsed request-uri. This url should match the url in the browser.|
| `method` | The browsers request method (example: `GET`, `POST`, `PUT`, `PATCH`, `DELETE` etc).|
| `host` | The website host (example: `domain.com`).|
| `loaded_routes` | List of all the routes that matched the `url` and that has been rendered/loaded. |
| `all_routes` | All available routes |
| `boot_managers` | All available BootManagers |
| `csrf_verifier` | CsrfVerifier class |
| `log` | List of debug messages/log from the router. |
| `router_output` | The rendered callback output from the router. |
| `library_version` | The version of simple-php-router you are using. |
| `php_version` | The version of PHP you are using. |
| `server_params` | List of all `$_SERVER` variables/headers. |
#### Benchmark and logging
You can activate benchmark debugging/logging by calling `setDebugEnabled` method on the `Router` instance.
You have to enable debugging BEFORE starting the routing.
**Example:**
```php
SimpleRouter::router()->setDebugEnabled(true);
SimpleRouter::start();
```
When the routing is complete, you can get the debug-log by calling the `getDebugLog()` on the `Router` instance. This will return an `array` of log-messages each containing execution time, trace info and debug-message.
**Example:**
```php
$messages = SimpleRouter::router()->getDebugLog();
```
## Reporting a new issue
**Before reporting your issue, make sure that the issue you are experiencing aren't already answered in the [Common errors](#common-errors) section or by searching the [closed issues](https://github.com/skipperbent/simple-php-router/issues?q=is%3Aissue+is%3Aclosed) page on GitHub.**
To avoid confusion and to help you resolve your issue as quickly as possible, you should provide a detailed explanation of the problem you are experiencing.
### Procedure for reporting a new issue
1. Go to [this page](https://github.com/skipperbent/simple-php-router/issues/new) to create a new issue.
2. Add a title that describes your problems in as few words as possible.
3. Copy and paste the template below in the description of your issue and replace each step with your own information. If the step is not relevant for your issue you can delete it.
### Issue template
Copy and paste the template below into the description of your new issue and replace it with your own information.
You can check the [Debug information](#debug-information) section to see how to generate the debug-info.
<pre>
### Description
The library fails to render the route `/user/æsel` which contains one parameter using a custom regular expression for matching special foreign characters. Routes without special characters like `/user/tom` renders correctly.
### Steps to reproduce the error
1. Add the following route:
```php
SimpleRouter::get('/user/{name}', 'UserController@show')->where(['name' => '[\w]+']);
```
2. Navigate to `/user/æsel` in browser.
3. `NotFoundHttpException` is thrown by library.
### Route and/or callback for failing route
*Route:*
```php
SimpleRouter::get('/user/{name}', 'UserController@show')->where(['name' => '[\w]+']);
```
*Callback:*
```php
public function show($username) {
return sprintf('Username is: %s', $username);
}
```
### Debug info
```php
[PASTE YOUR DEBUG-INFO HERE]
```
</pre>
Remember that a more detailed issue- description and debug-info might suck to write, but it will help others understand- and resolve your issue without asking for the information.
**Note:** please be as detailed as possible in the description when creating a new issue. This will help others to more easily understand- and solve your issue. Providing the necessary steps to reproduce the error within your description, adding useful debugging info etc. will help others quickly resolve the issue you are reporting.
## Feedback and development
If the library is missing a feature that you need in your project or if you have feedback, we'd love to hear from you.
Feel free to leave us feedback by [creating a new issue](https://github.com/skipperbent/simple-php-router/issues/new).
**Experiencing an issue?**
Please refer to our [Help and support](#help-and-support) section in the documentation before reporting a new issue.
### Contribution development guidelines
- Please try to follow the PSR-2 codestyle guidelines.
- Please create your pull requests to the development base that matches the version number you want to change.
For example when pushing changes to version 3, the pull request should use the `v3-development` base/branch.
- Create detailed descriptions for your commits, as these will be used in the changelog for new releases.
- When changing existing functionality, please ensure that the unit-tests working.
- When adding new stuff, please remember to add new unit-tests for the functionality.
---
# Credits
## Sites
+3 -5
View File
@@ -27,16 +27,14 @@
}
],
"require": {
"php": ">=7.1",
"php-di/php-di": "^6.0"
"php": ">=5.4.0"
},
"require-dev": {
"phpunit/phpunit": "^6.0",
"mockery/mockery": "^1"
"phpunit/phpunit": "4.7.7"
},
"autoload": {
"psr-4": {
"Pecee\\": "src/Pecee/"
}
}
}
}
+11 -18
View File
@@ -1,9 +1,6 @@
<?php
use Pecee\SimpleRouter\SimpleRouter as Router;
use Pecee\Http\Url;
use Pecee\Http\Response;
use Pecee\Http\Request;
/**
* Get url for a route by using either name/alias, class or method name.
@@ -20,10 +17,10 @@ use Pecee\Http\Request;
* @param string|null $name
* @param string|array|null $parameters
* @param array|null $getParams
* @return \Pecee\Http\Url
* @return string
* @throws \InvalidArgumentException
*/
function url(?string $name = null, $parameters = null, ?array $getParams = null): Url
function url($name = null, $parameters = null, $getParams = null)
{
return Router::getUrl($name, $parameters, $getParams);
}
@@ -31,7 +28,7 @@ function url(?string $name = null, $parameters = null, ?array $getParams = null)
/**
* @return \Pecee\Http\Response
*/
function response(): Response
function response()
{
return Router::response();
}
@@ -39,7 +36,7 @@ function response(): Response
/**
* @return \Pecee\Http\Request
*/
function request(): Request
function request()
{
return Router::request();
}
@@ -48,23 +45,19 @@ function request(): Request
* Get input class
* @param string|null $index Parameter index name
* @param string|null $defaultValue Default return value
* @param array ...$methods Default methods
* @return \Pecee\Http\Input\InputHandler|string
* @param string|array|null $methods Default method
* @return \Pecee\Http\Input\Input|string
*/
function input($index = null, $defaultValue = null, ...$methods)
function input($index = null, $defaultValue = null, $methods = null)
{
if ($index !== null) {
return request()->getInputHandler()->getValue($index, $defaultValue, ...$methods);
return request()->getInput()->get($index, $defaultValue, $methods);
}
return request()->getInputHandler();
return request()->getInput();
}
/**
* @param string $url
* @param int|null $code
*/
function redirect(string $url, ?int $code = null): void
function redirect($url, $code = null)
{
if ($code !== null) {
response()->httpCode($code);
@@ -77,7 +70,7 @@ function redirect(string $url, ?int $code = null): void
* Get current csrf-token
* @return string|null
*/
function csrf_token(): ?string
function csrf_token()
{
$baseVerifier = Router::router()->getCsrfVerifier();
if ($baseVerifier !== null) {
-24
View File
@@ -1,24 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
backupGlobals="false"
backupStaticAttributes="false"
colors="true"
bootstrap="tests/bootstrap.php"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false">
<testsuites>
<testsuite name="SimpleRouter Test Suite">
<directory>tests/Pecee/SimpleRouter/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">src</directory>
</whitelist>
</filter>
</phpunit>
+14 -15
View File
@@ -1,48 +1,47 @@
<?php
namespace Pecee\Controllers;
interface IResourceController
{
/**
* @return string|null
* @return void
*/
public function index(): ?string;
public function index();
/**
* @param mixed $id
* @return string|null
* @return void
*/
public function show($id): ?string;
public function show($id);
/**
* @return string|null
* @return void
*/
public function store(): ?string;
public function store();
/**
* @return string|null
* @return void
*/
public function create(): ?string;
public function create();
/**
* View
* @param mixed $id
* @return string|null
* @return void
*/
public function edit($id): ?string;
public function edit($id);
/**
* @param mixed $id
* @return string|null
* @return void
*/
public function update($id): ?string;
public function update($id);
/**
* @param mixed $id
* @return string|null
* @return void
*/
public function destroy($id): ?string;
public function destroy($id);
}
@@ -1,8 +1,6 @@
<?php
namespace Pecee\Exceptions;
class InvalidArgumentException extends \InvalidArgumentException
{
class InvalidArgumentException extends \InvalidArgumentException {
}
@@ -1,6 +1,6 @@
<?php
namespace Pecee\SimpleRouter\Handlers;
namespace Pecee\Handlers;
use Pecee\Http\Request;
@@ -10,7 +10,7 @@ use Pecee\Http\Request;
* Class is used to create callbacks which are fired when an exception is reached.
* This allows for easy handling 404-exception etc. without creating an custom ExceptionHandler.
*
* @package \Pecee\SimpleRouter\Handlers
* @package Pecee\Handlers
*/
class CallbackExceptionHandler implements IExceptionHandler
{
@@ -25,11 +25,12 @@ class CallbackExceptionHandler implements IExceptionHandler
/**
* @param Request $request
* @param \Exception $error
* @return Request|null
*/
public function handleError(Request $request, \Exception $error): void
public function handleError(Request $request, \Exception $error)
{
/* Fire exceptions */
\call_user_func($this->callback,
return call_user_func($this->callback,
$request,
$error
);
@@ -1,6 +1,5 @@
<?php
namespace Pecee\SimpleRouter\Handlers;
namespace Pecee\Handlers;
use Pecee\Http\Request;
@@ -9,7 +8,8 @@ interface IExceptionHandler
/**
* @param Request $request
* @param \Exception $error
* @return Request|null
*/
public function handleError(Request $request, \Exception $error): void;
public function handleError(Request $request, \Exception $error);
}
+7 -7
View File
@@ -5,18 +5,18 @@ namespace Pecee\Http\Input;
interface IInputItem
{
public function getIndex(): string;
public function getIndex();
public function setIndex(string $index): self;
public function setIndex($index);
public function getName(): ?string;
public function getName();
public function setName(string $name): self;
public function setName($name);
public function getValue(): ?string;
public function getValue();
public function setValue(string $value): self;
public function setValue($value);
public function __toString(): string;
public function __toString();
}
@@ -5,7 +5,7 @@ namespace Pecee\Http\Input;
use Pecee\Exceptions\InvalidArgumentException;
use Pecee\Http\Request;
class InputHandler
class Input
{
/**
* @var array
@@ -42,26 +42,26 @@ class InputHandler
* Parse input values
*
*/
public function parseInputs(): void
public function parseInputs()
{
/* Parse get requests */
if (\count($_GET) !== 0) {
if (count($_GET) !== 0) {
$this->get = $this->handleGetPost($_GET);
}
/* Parse post requests */
$postVars = $_POST;
if (\in_array($this->request->getMethod(), ['put', 'patch', 'delete'], false) === true) {
if (in_array($this->request->getMethod(), ['put', 'patch', 'delete'], false) === true) {
parse_str(file_get_contents('php://input'), $postVars);
}
if (\count($postVars) !== 0) {
if (count($postVars) !== 0) {
$this->post = $this->handleGetPost($postVars);
}
/* Parse get requests */
if (\count($_FILES) !== 0) {
if (count($_FILES) !== 0) {
$this->file = $this->parseFiles();
}
}
@@ -69,24 +69,25 @@ class InputHandler
/**
* @return array
*/
public function parseFiles(): array
public function parseFiles()
{
$list = [];
foreach ((array)$_FILES as $key => $value) {
// Handle array input
if (\is_array($value['name']) === false) {
if (is_array($value['name']) === false) {
$values['index'] = $key;
try {
$list[$key] = InputFile::createFromArray($values + $value);
} catch (InvalidArgumentException $e) {
} catch(InvalidArgumentException $e ){
}
continue;
}
$keys = [$key];
$files = $this->rearrangeFiles($value['name'], $keys, $value);
if (isset($list[$key]) === true) {
@@ -100,7 +101,7 @@ class InputHandler
return $list;
}
protected function rearrangeFiles(array $values, &$index, $original): array
protected function rearrangeFiles(array $values, &$index, $original)
{
$originalIndex = $index[0];
@@ -110,7 +111,7 @@ class InputHandler
foreach ($values as $key => $value) {
if (\is_array($original['name'][$key]) === false) {
if (is_array($original['name'][$key]) === false) {
try {
@@ -131,7 +132,7 @@ class InputHandler
$output[$key] = $file;
continue;
} catch (InvalidArgumentException $e) {
} catch(InvalidArgumentException $e) {
}
}
@@ -151,14 +152,14 @@ class InputHandler
return $output;
}
protected function handleGetPost(array $array): array
protected function handleGetPost(array $array)
{
$list = [];
foreach ($array as $key => $value) {
// Handle array input
if (\is_array($value) === false) {
if (is_array($value) === false) {
$list[$key] = new InputItem($key, $value);
continue;
}
@@ -178,9 +179,9 @@ class InputHandler
* @param string|null $defaultValue
* @return InputItem|string
*/
public function findPost(string $index, ?string $defaultValue = null)
public function findPost($index, $defaultValue = null)
{
return $this->post[$index] ?? $defaultValue;
return isset($this->post[$index]) ? $this->post[$index] : $defaultValue;
}
/**
@@ -190,9 +191,9 @@ class InputHandler
* @param string|null $defaultValue
* @return InputFile|string
*/
public function findFile(string $index, ?string $defaultValue = null)
public function findFile($index, $defaultValue = null)
{
return $this->file[$index] ?? $defaultValue;
return isset($this->file[$index]) ? $this->file[$index] : $defaultValue;
}
/**
@@ -202,35 +203,40 @@ class InputHandler
* @param string|null $defaultValue
* @return InputItem|string
*/
public function findGet(string $index, ?string $defaultValue = null)
public function findGet($index, $defaultValue = null)
{
return $this->get[$index] ?? $defaultValue;
return isset($this->get[$index]) ? $this->get[$index] : $defaultValue;
}
/**
* Get input object
*
* @param string $index
* @param array ...$methods
* @return IInputItem|null
* @param string|null $defaultValue
* @param array|string|null $methods
* @return IInputItem|string
*/
public function get(string $index, ...$methods): ?IInputItem
public function getObject($index, $defaultValue = null, $methods = null)
{
if ($methods !== null && is_string($methods) === true) {
$methods = [$methods];
}
$element = null;
if (\count($methods) === 0 || \in_array('get', $methods, true) === true) {
if ($methods === null || in_array('get', $methods, false) === true) {
$element = $this->findGet($index);
}
if (($element === null && \count($methods) === 0) || (\count($methods) !== 0 && \in_array('post', $methods, true) === true)) {
if (($element === null && $methods === null) || ($methods !== null && in_array('post', $methods, false) === true)) {
$element = $this->findPost($index);
}
if (($element === null && \count($methods) === 0) || (\count($methods) !== 0 && \in_array('file', $methods, true) === true)) {
if (($element === null && $methods === null) || ($methods !== null && in_array('file', $methods, false) === true)) {
$element = $this->findFile($index);
}
return $element;
return ($element !== null) ? $element : $defaultValue;
}
/**
@@ -238,25 +244,29 @@ class InputHandler
*
* @param string $index
* @param string|null $defaultValue
* @param array ...$methods
* @return string
* @param array|string|null $methods
* @return InputItem|string
*/
public function getValue(string $index, ?string $defaultValue = null, ...$methods): ?string
public function get($index, $defaultValue = null, $methods = null)
{
$input = $this->get($index, ...$methods);
return ($input === null || ($input !== null && trim($input->getValue()) === '')) ? $defaultValue : $input->getValue();
$input = $this->getObject($index, $defaultValue, $methods);
if ($input instanceof InputItem) {
return (trim($input->getValue()) === '') ? $defaultValue : $input->getValue();
}
return $input;
}
/**
* Check if a input-item exist
*
* @param string $index
* @param array ...$method
* @return bool
*/
public function exists(string $index, ...$method): bool
public function exists($index)
{
return $this->get($index, $method) !== null;
return ($this->getObject($index) !== null);
}
/**
@@ -264,18 +274,14 @@ class InputHandler
* @param array|null $filter Only take items in filter
* @return array
*/
public function all(array $filter = null): array
public function all(array $filter = null)
{
$output = $_GET;
$output = $_GET + $_POST;
if ($this->request->getMethod() === 'post') {
// Append POST data
$output += $_POST;
$contents = file_get_contents('php://input');
// Append any PHP-input json
if (strpos(trim($contents), '{') === 0) {
$post = json_decode($contents, true);
if ($post !== false) {
+36 -36
View File
@@ -14,7 +14,7 @@ class InputFile implements IInputItem
public $errors;
public $tmpName;
public function __construct(string $index)
public function __construct($index)
{
$this->index = $index;
@@ -31,7 +31,7 @@ class InputFile implements IInputItem
* @throws InvalidArgumentException
* @return static
*/
public static function createFromArray(array $values): self
public static function createFromArray(array $values)
{
if (isset($values['index']) === false) {
throw new InvalidArgumentException('Index key is required');
@@ -48,8 +48,8 @@ class InputFile implements IInputItem
];
return (new static($values['index']))
->setSize((int)$values['size'])
->setError((int)$values['error'])
->setSize($values['size'])
->setError($values['error'])
->setType($values['type'])
->setTmpName($values['tmp_name'])
->setFilename($values['name']);
@@ -59,7 +59,7 @@ class InputFile implements IInputItem
/**
* @return string
*/
public function getIndex(): string
public function getIndex()
{
return $this->index;
}
@@ -67,9 +67,9 @@ class InputFile implements IInputItem
/**
* Set input index
* @param string $index
* @return static
* @return static $this
*/
public function setIndex(string $index): IInputItem
public function setIndex($index)
{
$this->index = $index;
@@ -79,7 +79,7 @@ class InputFile implements IInputItem
/**
* @return string
*/
public function getSize(): string
public function getSize()
{
return $this->size;
}
@@ -87,9 +87,9 @@ class InputFile implements IInputItem
/**
* Set file size
* @param int $size
* @return static
* @return static $this
*/
public function setSize(int $size): IInputItem
public function setSize($size)
{
$this->size = $size;
@@ -100,7 +100,7 @@ class InputFile implements IInputItem
* Get mime-type of file
* @return string
*/
public function getMime(): string
public function getMime()
{
return $this->getType();
}
@@ -108,7 +108,7 @@ class InputFile implements IInputItem
/**
* @return string
*/
public function getType(): string
public function getType()
{
return $this->type;
}
@@ -116,9 +116,9 @@ class InputFile implements IInputItem
/**
* Set type
* @param string $type
* @return static
* @return static $this
*/
public function setType(string $type): IInputItem
public function setType($type)
{
$this->type = $type;
@@ -130,7 +130,7 @@ class InputFile implements IInputItem
*
* @return string
*/
public function getExtension(): string
public function getExtension()
{
return pathinfo($this->getFilename(), PATHINFO_EXTENSION);
}
@@ -140,7 +140,7 @@ class InputFile implements IInputItem
*
* @return string
*/
public function getName(): ?string
public function getName()
{
return $this->name;
}
@@ -150,9 +150,9 @@ class InputFile implements IInputItem
* Useful for adding validation etc.
*
* @param string $name
* @return static
* @return static $this
*/
public function setName(string $name): IInputItem
public function setName($name)
{
$this->name = $name;
@@ -163,9 +163,9 @@ class InputFile implements IInputItem
* Set filename
*
* @param string $name
* @return static
* @return static $this
*/
public function setFilename($name): IInputItem
public function setFilename($name)
{
$this->filename = $name;
@@ -177,7 +177,7 @@ class InputFile implements IInputItem
*
* @return string mixed
*/
public function getFilename(): ?string
public function getFilename()
{
return $this->filename;
}
@@ -188,7 +188,7 @@ class InputFile implements IInputItem
* @param string $destination
* @return bool
*/
public function move($destination): bool
public function move($destination)
{
return move_uploaded_file($this->tmpName, $destination);
}
@@ -198,7 +198,7 @@ class InputFile implements IInputItem
*
* @return string
*/
public function getContents(): string
public function getContents()
{
return file_get_contents($this->tmpName);
}
@@ -208,7 +208,7 @@ class InputFile implements IInputItem
*
* @return bool
*/
public function hasError(): bool
public function hasError()
{
return ($this->getError() !== 0);
}
@@ -216,20 +216,20 @@ class InputFile implements IInputItem
/**
* Get upload-error code.
*
* @return int
* @return string
*/
public function getError(): int
public function getError()
{
return (int)$this->errors;
return $this->errors;
}
/**
* Set error
*
* @param int $error
* @return static
* @return static $this
*/
public function setError($error): IInputItem
public function setError($error)
{
$this->errors = (int)$error;
@@ -239,7 +239,7 @@ class InputFile implements IInputItem
/**
* @return string
*/
public function getTmpName(): string
public function getTmpName()
{
return $this->tmpName;
}
@@ -247,21 +247,21 @@ class InputFile implements IInputItem
/**
* Set file temp. name
* @param string $name
* @return static
* @return static $this
*/
public function setTmpName($name): IInputItem
public function setTmpName($name)
{
$this->tmpName = $name;
return $this;
}
public function __toString(): string
public function __toString()
{
return $this->getTmpName();
}
public function getValue(): ?string
public function getValue()
{
return $this->getFilename();
}
@@ -270,14 +270,14 @@ class InputFile implements IInputItem
* @param string $value
* @return static
*/
public function setValue(string $value): IInputItem
public function setValue($value)
{
$this->filename = $value;
return $this;
}
public function toArray(): array
public function toArray()
{
return [
'tmp_name' => $this->tmpName,
+10 -10
View File
@@ -8,7 +8,7 @@ class InputItem implements IInputItem
public $name;
public $value;
public function __construct(string $index, ?string $value = null)
public function __construct($index, $value = null)
{
$this->index = $index;
$this->value = $value;
@@ -20,12 +20,12 @@ class InputItem implements IInputItem
/**
* @return string
*/
public function getIndex(): string
public function getIndex()
{
return $this->index;
}
public function setIndex(string $index): IInputItem
public function setIndex($index)
{
$this->index = $index;
@@ -35,7 +35,7 @@ class InputItem implements IInputItem
/**
* @return string
*/
public function getName(): ?string
public function getName()
{
return $this->name;
}
@@ -43,9 +43,9 @@ class InputItem implements IInputItem
/**
* Set input name
* @param string $name
* @return static
* @return static $this
*/
public function setName(string $name): IInputItem
public function setName($name)
{
$this->name = $name;
@@ -55,7 +55,7 @@ class InputItem implements IInputItem
/**
* @return string
*/
public function getValue(): ?string
public function getValue()
{
return $this->value;
}
@@ -63,16 +63,16 @@ class InputItem implements IInputItem
/**
* Set input value
* @param string $value
* @return static
* @return static $this
*/
public function setValue(string $value): IInputItem
public function setValue($value)
{
$this->value = $value;
return $this;
}
public function __toString(): string
public function __toString()
{
return (string)$this->value;
}
+18 -17
View File
@@ -9,8 +9,8 @@ use Pecee\Http\Security\ITokenProvider;
class BaseCsrfVerifier implements IMiddleware
{
public const POST_KEY = 'csrf-token';
public const HEADER_KEY = 'X-CSRF-TOKEN';
const POST_KEY = 'csrf-token';
const HEADER_KEY = 'X-CSRF-TOKEN';
protected $except;
protected $tokenProvider;
@@ -29,21 +29,21 @@ class BaseCsrfVerifier implements IMiddleware
* @param Request $request
* @return bool
*/
protected function skip(Request $request): bool
protected function skip(Request $request)
{
if ($this->except === null || \count($this->except) === 0) {
if ($this->except === null || count($this->except) === 0) {
return false;
}
$max = \count($this->except) - 1;
$max = count($this->except) - 1;
for ($i = $max; $i >= 0; $i--) {
$url = $this->except[$i];
$url = rtrim($url, '/');
if ($url[\strlen($url) - 1] === '*') {
if ($url[strlen($url) - 1] === '*') {
$url = rtrim($url, '*');
$skip = $request->getUrl()->contains($url);
$skip = (stripos($request->getUrl()->getOriginalUrl(), $url) === 0);
} else {
$skip = ($url === $request->getUrl()->getOriginalUrl());
}
@@ -62,18 +62,19 @@ class BaseCsrfVerifier implements IMiddleware
* @param Request $request
* @throws TokenMismatchException
*/
public function handle(Request $request): void
public function handle(Request $request)
{
if ($this->skip($request) === false && \in_array($request->getMethod(), ['post', 'put', 'delete'], true) === true) {
if ($this->skip($request) === false && in_array($request->getMethod(), ['post', 'put', 'delete'], false) === true) {
$token = $request->getInputHandler()->getValue(
static::POST_KEY,
$request->getHeader(static::HEADER_KEY),
'post'
);
$token = $request->getInput()->get(static::POST_KEY, null, 'post');
if ($this->tokenProvider->validate((string)$token) === false) {
// If the token is not posted, check headers for valid x-csrf-token
if ($token === null) {
$token = $request->getHeader(static::HEADER_KEY);
}
if ($this->tokenProvider->validate($token) === false) {
throw new TokenMismatchException('Invalid CSRF-token.');
}
@@ -84,7 +85,7 @@ class BaseCsrfVerifier implements IMiddleware
}
public function getTokenProvider(): ITokenProvider
public function getTokenProvider()
{
return $this->tokenProvider;
}
@@ -93,7 +94,7 @@ class BaseCsrfVerifier implements IMiddleware
* Set token provider
* @param ITokenProvider $provider
*/
public function setTokenProvider(ITokenProvider $provider): void
public function setTokenProvider(ITokenProvider $provider)
{
$this->tokenProvider = $provider;
}
@@ -1,5 +1,4 @@
<?php
namespace Pecee\Http\Middleware\Exceptions;
class TokenMismatchException extends \Exception
+2 -2
View File
@@ -1,5 +1,4 @@
<?php
namespace Pecee\Http\Middleware;
use Pecee\Http\Request;
@@ -8,7 +7,8 @@ interface IMiddleware
{
/**
* @param Request $request
* @return Request|null
*/
public function handle(Request $request): void;
public function handle(Request $request);
}
+80 -155
View File
@@ -2,94 +2,61 @@
namespace Pecee\Http;
use Pecee\Http\Exceptions\MalformedUrlException;
use Pecee\Http\Input\InputHandler;
use Pecee\Http\Input\Input;
use Pecee\SimpleRouter\Route\ILoadableRoute;
use Pecee\SimpleRouter\Route\RouteUrl;
use Pecee\SimpleRouter\SimpleRouter;
class Request
{
/**
* Additional data
*
* @var array
*/
private $data = [];
/**
* Server headers
* @var array
*/
protected $headers = [];
/**
* Request host
* @var string
*/
protected $headers;
protected $host;
/**
* Current request url
* @var Url
*/
protected $url;
/**
* Request method
* @var string
*/
protected $method;
protected $input;
/**
* Input handler
* @var InputHandler
*/
protected $inputHandler;
/**
* Defines if request has pending rewrite
* @var bool
*/
protected $hasPendingRewrite = false;
protected $hasRewrite = false;
/**
* @var ILoadableRoute|null
*/
protected $rewriteRoute;
/**
* Rewrite url
* @var string|null
*/
protected $rewriteUrl;
/**
* @var array
* @var ILoadableRoute|null
*/
protected $loadedRoutes = [];
protected $loadedRoute;
/**
* Request constructor.
* @throws MalformedUrlException
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public function __construct()
{
$this->parseHeaders();
$this->setHost($this->getHeader('http-host'));
// Check if special IIS header exist, otherwise use default.
$this->setUrl($this->getHeader('unencoded-url', $this->getHeader('request-uri')));
$this->input = new Input($this);
$this->method = strtolower($this->input->get('_method', $this->getHeader('request-method')));
}
protected function parseHeaders()
{
$this->headers = [];
foreach ($_SERVER as $key => $value) {
$this->headers[strtolower($key)] = $value;
$this->headers[strtolower(str_replace('_', '-', $key))] = $value;
}
$this->setHost($this->getHeader('http-host'));
// Check if special IIS header exist, otherwise use default.
$this->setUrl(new Url($this->getHeader('unencoded-url', $this->getHeader('request-uri'))));
$this->inputHandler = new InputHandler($this);
$this->method = strtolower($this->inputHandler->getValue('_method', $this->getHeader('request-method')));
}
public function isSecure(): bool
public function isSecure()
{
return $this->getHeader('http-x-forwarded-proto') === 'https' || $this->getHeader('https') !== null || $this->getHeader('server-port') === 443;
}
@@ -97,33 +64,23 @@ class Request
/**
* @return Url
*/
public function getUrl(): Url
public function getUrl()
{
return $this->url;
}
/**
* Copy url object
*
* @return Url
* @return string
*/
public function getUrlCopy(): Url
{
return clone $this->url;
}
/**
* @return string|null
*/
public function getHost(): ?string
public function getHost()
{
return $this->host;
}
/**
* @return string|null
* @return string
*/
public function getMethod(): ?string
public function getMethod()
{
return $this->method;
}
@@ -132,7 +89,7 @@ class Request
* Get http basic auth user
* @return string|null
*/
public function getUser(): ?string
public function getUser()
{
return $this->getHeader('php-auth-user');
}
@@ -141,7 +98,7 @@ class Request
* Get http basic auth password
* @return string|null
*/
public function getPassword(): ?string
public function getPassword()
{
return $this->getHeader('php-auth-pw');
}
@@ -150,16 +107,16 @@ class Request
* Get all headers
* @return array
*/
public function getHeaders(): array
public function getHeaders()
{
return $this->headers;
}
/**
* Get id address
* @return string|null
* @return string
*/
public function getIp(): ?string
public function getIp()
{
if ($this->getHeader('http-cf-connecting-ip') !== null) {
return $this->getHeader('http-cf-connecting-ip');
@@ -176,27 +133,27 @@ class Request
* Get remote address/ip
*
* @alias static::getIp
* @return string|null
* @return string
*/
public function getRemoteAddr(): ?string
public function getRemoteAddr()
{
return $this->getIp();
}
/**
* Get referer
* @return string|null
* @return string
*/
public function getReferer(): ?string
public function getReferer()
{
return $this->getHeader('http-referer');
}
/**
* Get user agent
* @return string|null
* @return string
*/
public function getUserAgent(): ?string
public function getUserAgent()
{
return $this->getHeader('http-user-agent');
}
@@ -209,18 +166,18 @@ class Request
*
* @return string|null
*/
public function getHeader($name, $defaultValue = null): ?string
public function getHeader($name, $defaultValue = null)
{
return $this->headers[strtolower($name)] ?? $defaultValue;
return isset($this->headers[strtolower($name)]) ? $this->headers[strtolower($name)] : $defaultValue;
}
/**
* Get input class
* @return InputHandler
* @return Input
*/
public function getInputHandler(): InputHandler
public function getInput()
{
return $this->inputHandler;
return $this->input;
}
/**
@@ -230,9 +187,9 @@ class Request
*
* @return bool
*/
public function isFormatAccepted($format): bool
public function isFormatAccepted($format)
{
return ($this->getHeader('http-accept') !== null && stripos($this->getHeader('http-accept'), $format) !== false);
return ($this->getHeader('http-accept') !== null && stripos($this->getHeader('http-accept'), $format) > -1);
}
/**
@@ -240,7 +197,7 @@ class Request
*
* @return bool
*/
public function isAjax(): bool
public function isAjax()
{
return (strtolower($this->getHeader('http-x-requested-with')) === 'xmlhttprequest');
}
@@ -249,27 +206,24 @@ class Request
* Get accept formats
* @return array
*/
public function getAcceptFormats(): array
public function getAcceptFormats()
{
return explode(',', $this->getHeader('http-accept'));
}
/**
* @param Url $url
* @param string|Url $url
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public function setUrl(Url $url): void
public function setUrl($url)
{
$this->url = $url;
if ($this->url->getHost() === null) {
$this->url->setHost((string)$this->getHost());
}
$this->url = ($url instanceof Url) ? $url : new Url($url);
}
/**
* @param string|null $host
* @param string $host
*/
public function setHost(?string $host): void
public function setHost($host)
{
$this->host = $host;
}
@@ -277,7 +231,7 @@ class Request
/**
* @param string $method
*/
public function setMethod(string $method): void
public function setMethod($method)
{
$this->method = $method;
}
@@ -288,9 +242,9 @@ class Request
* @param ILoadableRoute $route
* @return static
*/
public function setRewriteRoute(ILoadableRoute $route): self
public function setRewriteRoute(ILoadableRoute $route)
{
$this->hasPendingRewrite = true;
$this->hasRewrite = true;
$this->rewriteRoute = SimpleRouter::addDefaultNamespace($route);
return $this;
@@ -301,7 +255,7 @@ class Request
*
* @return ILoadableRoute|null
*/
public function getRewriteRoute(): ?ILoadableRoute
public function getRewriteRoute()
{
return $this->rewriteRoute;
}
@@ -309,9 +263,9 @@ class Request
/**
* Get rewrite url
*
* @return string|null
* @return string
*/
public function getRewriteUrl(): ?string
public function getRewriteUrl()
{
return $this->rewriteUrl;
}
@@ -322,9 +276,9 @@ class Request
* @param string $rewriteUrl
* @return static
*/
public function setRewriteUrl(string $rewriteUrl): self
public function setRewriteUrl($rewriteUrl)
{
$this->hasPendingRewrite = true;
$this->hasRewrite = true;
$this->rewriteUrl = rtrim($rewriteUrl, '/') . '/';
return $this;
@@ -332,12 +286,12 @@ class Request
/**
* Set rewrite callback
* @param string|\Closure $callback
* @param string $callback
* @return static
*/
public function setRewriteCallback($callback): self
public function setRewriteCallback($callback)
{
$this->hasPendingRewrite = true;
$this->hasRewrite = true;
return $this->setRewriteRoute(new RouteUrl($this->getUrl()->getPath(), $callback));
}
@@ -346,73 +300,44 @@ class Request
* Get loaded route
* @return ILoadableRoute|null
*/
public function getLoadedRoute(): ?ILoadableRoute
public function getLoadedRoute()
{
return (\count($this->loadedRoutes) > 0) ? end($this->loadedRoutes) : null;
return $this->loadedRoute;
}
/**
* Get all loaded routes
*
* @return array
*/
public function getLoadedRoutes(): array
{
return $this->loadedRoutes;
}
/**
* Set loaded routes
*
* @param array $routes
* @return static
*/
public function setLoadedRoutes(array $routes): self
{
$this->loadedRoutes = $routes;
return $this;
}
/**
* Added loaded route
* Set loaded route
*
* @param ILoadableRoute $route
* @return static
*/
public function addLoadedRoute(ILoadableRoute $route): self
public function setLoadedRoute(ILoadableRoute $route)
{
$this->loadedRoutes[] = $route;
$this->loadedRoute = $route;
return $this;
}
/**
* Returns true if the request contains a rewrite
*
* @return bool
*/
public function hasPendingRewrite(): bool
public function hasRewrite()
{
return $this->hasPendingRewrite;
return $this->hasRewrite;
}
/**
* Defines if the current request contains a rewrite.
*
* @param bool $boolean
* @return Request
*/
public function setHasPendingRewrite(bool $boolean): self
public function setHasRewrite($value)
{
$this->hasPendingRewrite = $boolean;
$this->hasRewrite = $value;
return $this;
}
public function isRewrite($url)
{
return ($this->rewriteUrl === $url);
}
public function __isset($name)
{
return array_key_exists($name, $this->data) === true;
return array_key_exists($name, $this->data);
}
public function __set($name, $value = null)
@@ -422,7 +347,7 @@ class Request
public function __get($name)
{
return $this->data[$name] ?? null;
return isset($this->data[$name]) ? $this->data[$name] : null;
}
}
+14 -13
View File
@@ -19,7 +19,7 @@ class Response
* @param int $code
* @return static
*/
public function httpCode(int $code): self
public function httpCode($code)
{
http_response_code($code);
@@ -32,7 +32,7 @@ class Response
* @param string $url
* @param int $httpCode
*/
public function redirect(string $url, ?int $httpCode = null): void
public function redirect($url, $httpCode = null)
{
if ($httpCode !== null) {
$this->httpCode($httpCode);
@@ -42,7 +42,7 @@ class Response
exit(0);
}
public function refresh(): void
public function refresh()
{
$this->redirect($this->request->getUrl()->getOriginalUrl());
}
@@ -52,7 +52,7 @@ class Response
* @param string $name
* @return static
*/
public function auth(string $name = ''): self
public function auth($name = '')
{
$this->headers([
'WWW-Authenticate: Basic realm="' . $name . '"',
@@ -62,22 +62,23 @@ class Response
return $this;
}
public function cache(string $eTag, int $lastModifiedTime = 2592000): self
public function cache($eTag, $lastModified = 2592000)
{
$this->headers([
'Cache-Control: public',
sprintf('Last-Modified: %s GMT', gmdate('D, d M Y H:i:s', $lastModifiedTime)),
sprintf('Etag: %s', $eTag),
'Last-Modified: ' . gmdate('D, d M Y H:i:s', $lastModified) . ' GMT',
'Etag: ' . $eTag,
]);
$httpModified = $this->request->getHeader('http-if-modified-since');
$httpIfNoneMatch = $this->request->getHeader('http-if-none-match');
if (($httpIfNoneMatch !== null && $httpIfNoneMatch === $eTag) || ($httpModified !== null && strtotime($httpModified) === $lastModifiedTime)) {
if (($httpIfNoneMatch !== null && $httpIfNoneMatch === $eTag) || ($httpModified !== null && strtotime($httpModified) === $lastModified)) {
$this->header('HTTP/1.1 304 Not Modified');
exit(0);
exit();
}
return $this;
@@ -90,9 +91,9 @@ class Response
* @param int $dept JSON debt.
* @throws InvalidArgumentException
*/
public function json($value, ?int $options = null, int $dept = 512): void
public function json($value, $options = null, $dept = 512)
{
if (($value instanceof \JsonSerializable) === false && \is_array($value) === false) {
if (($value instanceof \JsonSerializable) === false && is_array($value) === false) {
throw new InvalidArgumentException('Invalid type for parameter "value". Must be of type array or object implementing the \JsonSerializable interface.');
}
@@ -106,7 +107,7 @@ class Response
* @param string $value
* @return static
*/
public function header(string $value): self
public function header($value)
{
header($value);
@@ -118,7 +119,7 @@ class Response
* @param array $headers
* @return static
*/
public function headers(array $headers): self
public function headers(array $headers)
{
foreach ($headers as $header) {
$this->header($header);
+28 -17
View File
@@ -6,7 +6,7 @@ use Pecee\Http\Security\Exceptions\SecurityException;
class CookieTokenProvider implements ITokenProvider
{
public const CSRF_KEY = 'CSRF-TOKEN';
const CSRF_KEY = 'CSRF-TOKEN';
protected $token;
protected $cookieTimeoutMinutes = 120;
@@ -30,13 +30,24 @@ class CookieTokenProvider implements ITokenProvider
* @return string
* @throws SecurityException
*/
public function generateToken(): string
public function generateToken()
{
try {
return bin2hex(random_bytes(32));
} catch (\Exception $e) {
throw new SecurityException($e->getMessage(), (int)$e->getCode(), $e->getPrevious());
if (function_exists('random_bytes') === true) {
try {
return bin2hex(random_bytes(32));
} catch(\Exception $e) {
throw new SecurityException($e->getMessage(), (int)$e->getCode(), $e->getPrevious());
}
}
$isSourceStrong = false;
$random = openssl_random_pseudo_bytes(32, $isSourceStrong);
if ($isSourceStrong === false || $random === false) {
throw new SecurityException('IV generation failed');
}
return $random;
}
/**
@@ -45,9 +56,9 @@ class CookieTokenProvider implements ITokenProvider
* @param string $token
* @return bool
*/
public function validate(string $token): bool
public function validate($token)
{
if ($this->getToken() !== null) {
if ($token !== null && $this->getToken() !== null) {
return hash_equals($token, $this->getToken());
}
@@ -60,10 +71,10 @@ class CookieTokenProvider implements ITokenProvider
*
* @param string $token
*/
public function setToken(string $token): void
public function setToken($token)
{
$this->token = $token;
setcookie(static::CSRF_KEY, $token, (int)((time() + 60) * $this->cookieTimeoutMinutes), '/', ini_get('session.cookie_domain'), ini_get('session.cookie_secure'), ini_get('session.cookie_httponly'));
setcookie(static::CSRF_KEY, $token, time() + 60 * $this->cookieTimeoutMinutes, '/');
}
/**
@@ -71,17 +82,17 @@ class CookieTokenProvider implements ITokenProvider
* @param string|null $defaultValue
* @return string|null
*/
public function getToken(?string $defaultValue = null): ?string
public function getToken($defaultValue = null)
{
$this->token = ($this->hasToken() === true) ? $_COOKIE[static::CSRF_KEY] : null;
return $this->token ?? $defaultValue;
return ($this->token !== null) ? $this->token : $defaultValue;
}
/**
* Refresh existing token
*/
public function refresh(): void
public function refresh()
{
if ($this->token !== null) {
$this->setToken($this->token);
@@ -92,7 +103,7 @@ class CookieTokenProvider implements ITokenProvider
* Returns whether the csrf token has been defined
* @return bool
*/
public function hasToken(): bool
public function hasToken()
{
return isset($_COOKIE[static::CSRF_KEY]);
}
@@ -101,16 +112,16 @@ class CookieTokenProvider implements ITokenProvider
* Get timeout for cookie in minutes
* @return int
*/
public function getCookieTimeoutMinutes(): int
public function getCookieTimeoutMinutes()
{
return $this->cookieTimeoutMinutes;
}
/**
* Set cookie timeout in minutes
* @param int $minutes
* @param $minutes
*/
public function setCookieTimeoutMinutes(int $minutes): void
public function setCookieTimeoutMinutes($minutes)
{
$this->cookieTimeoutMinutes = $minutes;
}
@@ -1,8 +1,6 @@
<?php
namespace Pecee\Http\Security\Exceptions;
class SecurityException extends \Exception
{
class SecurityException extends \Exception {
}
+2 -10
View File
@@ -8,7 +8,7 @@ interface ITokenProvider
/**
* Refresh existing token
*/
public function refresh(): void;
public function refresh();
/**
* Validate valid CSRF token
@@ -16,14 +16,6 @@ interface ITokenProvider
* @param string $token
* @return bool
*/
public function validate(string $token): bool;
/**
* Get token token
*
* @param string|null $defaultValue
* @return string|null
*/
public function getToken(?string $defaultValue = null): ?string;
public function validate($token);
}
+46 -332
View File
@@ -4,369 +4,142 @@ namespace Pecee\Http;
use Pecee\Http\Exceptions\MalformedUrlException;
class Url implements \JsonSerializable
class Url
{
private $originalUrl;
private $scheme;
private $host;
private $port;
private $username;
private $password;
private $path;
private $params;
private $fragment;
private $data = [
'scheme' => null,
'host' => null,
'port' => null,
'user' => null,
'pass' => null,
'path' => null,
'query' => null,
'fragment' => null,
];
/**
* Url constructor.
*
* @param string $url
* @throws MalformedUrlException
*/
public function __construct(?string $url)
public function __construct($url)
{
$this->originalUrl = $url;
$this->data = $this->parseUrl($url) + $this->data;
if ($url !== null && $url !== '/') {
$data = $this->parseUrl($url);
$this->scheme = $data['scheme'] ?? null;
$this->host = $data['host'] ?? null;
$this->port = $data['port'] ?? null;
$this->username = $data['user'] ?? null;
$this->password = $data['pass'] ?? null;
if (isset($data['path']) === true) {
$this->setPath($data['path']);
}
$this->fragment = $data['fragment'] ?? null;
if (isset($data['query']) === true) {
$params = [];
parse_str($data['query'], $params);
$this->setParams($params);
}
if (isset($this->data['path']) === true && $this->data['path'] !== '/') {
$this->data['path'] = rtrim($this->data['path'], '/') . '/';
}
}
/**
* Check if url is using a secure protocol like https
*
* @return bool
*/
public function isSecure(): bool
public function isSecure()
{
return (strtolower($this->getScheme()) === 'https');
}
/**
* Checks if url is relative
*
* @return bool
*/
public function isRelative(): bool
public function isRelative()
{
return ($this->getHost() === null);
}
/**
* Get url scheme
*
* @return string|null
*/
public function getScheme(): ?string
public function getScheme()
{
return $this->scheme;
}
/**
* Set the scheme of the url
*
* @param string $scheme
* @return static
*/
public function setScheme(string $scheme): self
{
$this->scheme = $scheme;
return $this;
return $this->data['scheme'];
}
/**
* Get url host
*
* @return string|null
*/
public function getHost(): ?string
public function getHost()
{
return $this->host;
}
/**
* Set the host of the url
*
* @param string $host
* @return static
*/
public function setHost(string $host): self
{
$this->host = $host;
return $this;
return $this->data['host'];
}
/**
* Get url port
*
* @return int|null
*/
public function getPort(): ?int
public function getPort()
{
return ($this->port !== null) ? (int)$this->port : null;
}
/**
* Set the port of the url
*
* @param int $port
* @return static
*/
public function setPort(int $port): self
{
$this->port = $port;
return $this;
return ($this->data['port'] !== null) ? (int)$this->data['port'] : null;
}
/**
* Parse username from url
*
* @return string|null
*/
public function getUsername(): ?string
public function getUserName()
{
return $this->username;
}
/**
* Set the username of the url
*
* @param string $username
* @return static
*/
public function setUsername(string $username): self
{
$this->username = $username;
return $this;
return $this->data['user'];
}
/**
* Parse password from url
* @return string|null
*/
public function getPassword(): ?string
public function getPassword()
{
return $this->password;
}
/**
* Set the url password
*
* @param string $password
* @return static
*/
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
return $this->data['pass'];
}
/**
* Get path from url
* @return string
*/
public function getPath(): ?string
public function getPath()
{
return $this->path ?? '/';
return $this->data['path'];
}
/**
* Set the url path
*
* @param string $path
* @return static
* Get querystring from url
* @return string|null
*/
public function setPath(string $path): self
public function getQueryString()
{
$this->path = rtrim($path, '/') . '/';
return $this;
}
/**
* Get query-string from url
*
* @return array
*/
public function getParams(): array
{
return $this->params;
}
/**
* Merge parameters array
*
* @param array $params
* @return static
*/
public function mergeParams(array $params): self
{
return $this->setParams(array_merge($this->getParams(), $params));
}
/**
* Set the url params
*
* @param array $params
* @return static
*/
public function setParams(array $params): self
{
$this->params = $params;
return $this;
}
/**
* Get query-string params as string
*
* @return string
*/
public function getQueryString(): string
{
return static::arrayToParams($this->getParams());
return $this->data['query'];
}
/**
* Get fragment from url (everything after #)
*
* @return string|null
*/
public function getFragment(): ?string
public function getFragment()
{
return $this->fragment;
}
/**
* Set url fragment
*
* @param string $fragment
* @return static
*/
public function setFragment(string $fragment): self
{
$this->fragment = $fragment;
return $this;
return $this->data['fragment'];
}
/**
* @return string
*/
public function getOriginalUrl(): string
public function getOriginalUrl()
{
return $this->originalUrl;
}
/**
* Get position of value.
* Returns -1 on failure.
*
* @param string $value
* @return int
*/
public function indexOf(string $value): int
{
$index = stripos($this->getOriginalUrl(), $value);
return ($index === false) ? -1 : $index;
}
/**
* Check if url contains value.
*
* @param string $value
* @return bool
*/
public function contains(string $value): bool
{
return (stripos($this->getOriginalUrl(), $value) !== false);
}
/**
* Check if url contains parameter/query string.
*
* @param string $name
* @return bool
*/
public function hasParam(string $name): bool
{
return \in_array($name, $this->getParams(), true);
}
/**
* Removes parameter from query-string
*
* @param string $name
*/
public function removeParam(string $name): void
{
if ($this->hasParam($name) === true) {
$params = $this->getParams();
$key = \array_search($name, $params, true);
if ($key === true) {
unset($params[$key]);
$this->setParams($params);
}
}
}
/**
* Get parameter by name.
* Returns parameter value or default value.
*
* @param string $name
* @param string|null $defaultValue
* @return string|null
*/
public function getParam(string $name, ?string $defaultValue = null): ?string
{
$output = null;
if ($this->hasParam($name) === true) {
$params = $this->getParams();
$key = \array_search($name, $params, true);
if ($key === true) {
$output = $params[$key];
}
}
return $output ?? $defaultValue;
}
/**
* UTF-8 aware parse_url() replacement.
* @param string $url
* @param int $component
* @return array
* @throws MalformedUrlException
* @return array
*/
public function parseUrl(string $url, int $component = -1): array
public function parseUrl($url, $component = -1)
{
$encodedUrl = preg_replace_callback(
'/[^:\/@?&=#]+/u',
@@ -379,83 +152,24 @@ class Url implements \JsonSerializable
$parts = parse_url($encodedUrl, $component);
if ($parts === false) {
throw new MalformedUrlException(sprintf('Failed to parse url: "%s"', $url));
throw new MalformedUrlException('Malformed URL: ' . $url);
}
return array_map('urldecode', $parts);
}
/**
* Convert array to query-string params
*
* @param array $getParams
* @param bool $includeEmpty
* @return string
* Returns data array with information about the url
* @return array
*/
public static function arrayToParams(array $getParams = [], bool $includeEmpty = true): string
public function getData()
{
if (\count($getParams) !== 0) {
if ($includeEmpty === false) {
$getParams = array_filter($getParams, function ($item) {
return (trim($item) !== '');
});
}
return http_build_query($getParams);
}
return '';
return $this->data;
}
/**
* Returns the relative url
*
* @return string
*/
public function getRelativeUrl(): string
public function __toString()
{
$params = $this->getQueryString();
$path = $this->path ?? '';
$query = $params !== '' ? '?' . $params : '';
$fragment = $this->fragment !== null ? '#' . $this->fragment : '';
return $path . $query . $fragment;
}
/**
* Returns the absolute url
*
* @return string
*/
public function getAbsoluteUrl(): string
{
$scheme = $this->scheme !== null ? $this->scheme . '://' : '';
$host = $this->host ?? '';
$port = $this->port !== null ? ':' . $this->port : '';
$user = $this->username ?? '';
$pass = $this->password !== null ? ':' . $this->password : '';
$pass = ($user || $pass) ? $pass . '@' : '';
return $scheme . $user . $pass . $host . $port . $this->getRelativeUrl();
}
/**
* Specify data which should be serialized to JSON
* @link http://php.net/manual/en/jsonserializable.jsonserialize.php
* @return mixed data which can be serialized by <b>json_encode</b>,
* which is a value of any type other than a resource.
* @since 5.4.0
*/
public function jsonSerialize(): string
{
return $this->getRelativeUrl();
}
public function __toString(): string
{
return $this->getRelativeUrl();
return $this->getOriginalUrl();
}
}
@@ -1,118 +0,0 @@
<?php
namespace Pecee\SimpleRouter\ClassLoader;
use DI\Container;
use Pecee\SimpleRouter\Exceptions\NotFoundHttpException;
class ClassLoader implements IClassLoader
{
/**
* Dependency injection enabled
* @var bool
*/
protected $useDependencyInjection = false;
/**
* @var Container|null
*/
protected $container;
/**
* Load class
*
* @param string $class
* @return mixed
* @throws NotFoundHttpException
*/
public function loadClass(string $class)
{
if (class_exists($class) === false) {
throw new NotFoundHttpException(sprintf('Class "%s" does not exist', $class), 404);
}
if ($this->useDependencyInjection === true) {
$container = $this->getContainer();
if ($container !== null) {
try {
return $container->get($class);
} catch (\Exception $e) {
throw new NotFoundHttpException($e->getMessage(), (int)$e->getCode(), $e->getPrevious());
}
}
}
return new $class();
}
/**
* Load closure
*
* @param \Closure $closure
* @param array $parameters
* @return mixed
* @throws NotFoundHttpException
*/
public function loadClosure(\Closure $closure, array $parameters)
{
if ($this->useDependencyInjection === true) {
$container = $this->getContainer();
if ($container !== null) {
try {
return $container->call($closure, $parameters);
} catch (\Exception $e) {
throw new NotFoundHttpException($e->getMessage(), (int)$e->getCode(), $e->getPrevious());
}
}
}
return \call_user_func_array($closure, $parameters);
}
/**
* Get dependency injector container.
*
* @return Container|null
*/
public function getContainer(): ?Container
{
return $this->container;
}
/**
* Set the dependency-injector container.
*
* @param Container $container
* @return ClassLoader
*/
public function setContainer(Container $container): self
{
$this->container = $container;
return $this;
}
/**
* Enable or disable dependency injection.
*
* @param bool $enabled
* @return static
*/
public function useDependencyInjection(bool $enabled): self
{
$this->useDependencyInjection = $enabled;
return $this;
}
/**
* Return true if dependency injection is enabled.
*
* @return bool
*/
public function isDependencyInjectionEnabled(): bool
{
return $this->useDependencyInjection;
}
}
@@ -1,12 +0,0 @@
<?php
namespace Pecee\SimpleRouter\ClassLoader;
interface IClassLoader
{
public function loadClass(string $class);
public function loadClosure(\Closure $closure, array $parameters);
}
@@ -1,111 +0,0 @@
<?php
namespace Pecee\SimpleRouter\Event;
use Pecee\Http\Request;
use Pecee\SimpleRouter\Router;
class EventArgument implements IEventArgument
{
/**
* Event name
* @var string
*/
protected $eventName;
/**
* @var Router
*/
protected $router;
/**
* @var array
*/
protected $arguments = [];
public function __construct($eventName, $router, array $arguments = [])
{
$this->eventName = $eventName;
$this->router = $router;
$this->arguments = $arguments;
}
/**
* Get event name
*
* @return string
*/
public function getEventName(): string
{
return $this->eventName;
}
/**
* Set the event name
*
* @param string $name
*/
public function setEventName(string $name): void
{
$this->eventName = $name;
}
/**
* Get the router instance
*
* @return Router
*/
public function getRouter(): Router
{
return $this->router;
}
/**
* Get the request instance
*
* @return Request
*/
public function getRequest(): Request
{
return $this->getRouter()->getRequest();
}
/**
* @param string $name
* @return mixed
*/
public function __get($name)
{
return $this->arguments[$name] ?? null;
}
/**
* @param string $name
* @return bool
*/
public function __isset($name)
{
return array_key_exists($name, $this->arguments);
}
/**
* @param string $name
* @param mixed $value
* @throws \InvalidArgumentException
*/
public function __set($name, $value)
{
throw new \InvalidArgumentException('Not supported');
}
/**
* Get arguments
*
* @return array
*/
public function getArguments(): array
{
return $this->arguments;
}
}
@@ -1,46 +0,0 @@
<?php
namespace Pecee\SimpleRouter\Event;
use Pecee\Http\Request;
use Pecee\SimpleRouter\Router;
interface IEventArgument
{
/**
* Get event name
*
* @return string
*/
public function getEventName(): string;
/**
* Set event name
*
* @param string $name
*/
public function setEventName(string $name): void;
/**
* Get router instance
*
* @return Router
*/
public function getRouter(): Router;
/**
* Get request instance
*
* @return Request
*/
public function getRequest(): Request;
/**
* Get all event arguments
*
* @return array
*/
public function getArguments(): array;
}
@@ -1,5 +1,4 @@
<?php
namespace Pecee\SimpleRouter\Exceptions;
class HttpException extends \Exception
@@ -1,5 +1,4 @@
<?php
namespace Pecee\SimpleRouter\Exceptions;
class NotFoundHttpException extends HttpException
@@ -1,62 +0,0 @@
<?php
namespace Pecee\SimpleRouter\Handlers;
use Pecee\SimpleRouter\Event\EventArgument;
use Pecee\SimpleRouter\Router;
class DebugEventHandler implements IEventHandler
{
/**
* Debug callback
* @var \Closure
*/
protected $callback;
public function __construct()
{
$this->callback = function (EventArgument $argument) {
// todo: log in database
};
}
/**
* Get events.
*
* @param string|null $name Filter events by name.
* @return array
*/
public function getEvents(?string $name): array
{
return [
$name => [
$this->callback,
],
];
}
/**
* Fires any events registered with given event-name
*
* @param Router $router Router instance
* @param string $name Event name
* @param array $eventArgs Event arguments
*/
public function fireEvents(Router $router, string $name, array $eventArgs = []): void
{
$callback = $this->callback;
$callback(new EventArgument($router, $eventArgs));
}
/**
* Set debug callback
*
* @param \Closure $event
*/
public function setCallback(\Closure $event): void
{
$this->callback = $event;
}
}
@@ -1,178 +0,0 @@
<?php
namespace Pecee\SimpleRouter\Handlers;
use Pecee\SimpleRouter\Event\EventArgument;
use Pecee\SimpleRouter\Router;
class EventHandler implements IEventHandler
{
/**
* Fires when a event is triggered.
*/
public const EVENT_ALL = '*';
/**
* Fires when router is initializing and before routes are loaded.
*/
public const EVENT_INIT = 'onInit';
/**
* Fires when all routes has been loaded and rendered, just before the output is returned.
*/
public const EVENT_LOAD = 'onLoad';
/**
* Fires when a url-rewrite is and just before the routes are re-initialized.
*/
public const EVENT_REWRITE = 'onRewrite';
/**
* Fires when the router is booting.
* This happens just before boot-managers are rendered and before any routes has been loaded.
*/
public const EVENT_BOOT = 'onBoot';
/**
* Fires before a boot-manager is rendered.
*/
public const EVENT_RENDER_BOOTMANAGER = 'onRenderBootManager';
/**
* Fires when the router is about to load all routes.
*/
public const EVENT_LOAD_ROUTES = 'onLoadRoutes';
/**
* Fires whenever the `findRoute` method is called within the `Router`.
* This usually happens when the router tries to find routes that
* contains a certain url, usually after the EventHandler::EVENT_GET_URL event.
*/
public const EVENT_FIND_ROUTE = 'onFindRoute';
/**
* Fires whenever the `Router::getUrl` method or `url`-helper function
* is called and the router tries to find the route.
*/
public const EVENT_GET_URL = 'onGetUrl';
/**
* Fires when a route is matched and valid (correct request-type etc).
* and before the route is rendered.
*/
public const EVENT_MATCH_ROUTE = 'onMatchRoute';
/**
* Fires before a route is rendered.
*/
public const EVENT_RENDER_ROUTE = 'onRenderRoute';
/**
* Fires when the router is loading exception-handlers.
*/
public const EVENT_LOAD_EXCEPTIONS = 'onLoadExceptions';
/**
* Fires before the router is rendering a exception-handler.
*/
public const EVENT_RENDER_EXCEPTION = 'onRenderException';
/**
* Fires before a middleware is rendered.
*/
public const EVENT_RENDER_MIDDLEWARES = 'onRenderMiddlewares';
/**
* Fires before the CSRF-verifier is rendered.
*/
public const EVENT_RENDER_CSRF = 'onRenderCsrfVerifier';
/**
* All available events
* @var array
*/
public static $events = [
self::EVENT_ALL,
self::EVENT_INIT,
self::EVENT_LOAD,
self::EVENT_REWRITE,
self::EVENT_BOOT,
self::EVENT_RENDER_BOOTMANAGER,
self::EVENT_LOAD_ROUTES,
self::EVENT_FIND_ROUTE,
self::EVENT_GET_URL,
self::EVENT_MATCH_ROUTE,
self::EVENT_RENDER_ROUTE,
self::EVENT_LOAD_EXCEPTIONS,
self::EVENT_RENDER_EXCEPTION,
self::EVENT_RENDER_MIDDLEWARES,
self::EVENT_RENDER_CSRF,
];
/**
* List of all registered events
* @var array
*/
private $registeredEvents = [];
/**
* Register new event
*
* @param string $name
* @param \Closure $callback
* @return static
*/
public function register(string $name, \Closure $callback): IEventHandler
{
if (isset($this->registeredEvents[$name]) === true) {
$this->registeredEvents[$name][] = $callback;
} else {
$this->registeredEvents[$name] = [$callback];
}
return $this;
}
/**
* Get events.
*
* @param string|null $name Filter events by name.
* @param array ...$names Add multiple names...
* @return array
*/
public function getEvents(?string $name, ...$names): array
{
if ($name === null) {
return $this->registeredEvents;
}
$names[] = $name;
$events = [];
foreach ($names as $eventName) {
if (isset($this->registeredEvents[$eventName]) === true) {
$events += $this->registeredEvents[$eventName];
}
}
return $events;
}
/**
* Fires any events registered with given event-name
*
* @param Router $router Router instance
* @param string $name Event name
* @param array $eventArgs Event arguments
*/
public function fireEvents(Router $router, string $name, array $eventArgs = []): void
{
$events = $this->getEvents(static::EVENT_ALL, $name);
/* @var $event \Closure */
foreach ($events as $event) {
$event(new EventArgument($name, $router, $eventArgs));
}
}
}
@@ -1,27 +0,0 @@
<?php
namespace Pecee\SimpleRouter\Handlers;
use Pecee\SimpleRouter\Router;
interface IEventHandler
{
/**
* Get events.
*
* @param string|null $name Filter events by name.
* @return array
*/
public function getEvents(?string $name): array;
/**
* Fires any events registered with given event-name
*
* @param Router $router Router instance
* @param string $name Event name
* @param array $eventArgs Event arguments
*/
public function fireEvents(Router $router, string $name, array $eventArgs = []): void;
}
@@ -1,5 +1,4 @@
<?php
namespace Pecee\SimpleRouter;
use Pecee\Http\Request;
@@ -9,8 +8,8 @@ interface IRouterBootManager
/**
* Called when router loads it's routes
*
* @param Router $router
* @param Request $request
* @return Request
*/
public function boot(Router $router, Request $request): void;
public function boot(Request $request);
}
@@ -1,5 +1,4 @@
<?php
namespace Pecee\SimpleRouter\Route;
interface IControllerRoute extends IRoute
@@ -9,7 +8,7 @@ interface IControllerRoute extends IRoute
*
* @return string
*/
public function getController(): string;
public function getController();
/**
* Set controller class-name
@@ -17,6 +16,21 @@ interface IControllerRoute extends IRoute
* @param string $controller
* @return static
*/
public function setController(string $controller): self;
public function setController($controller);
/**
* Return active method
*
* @return string
*/
public function getMethod();
/**
* Set active method
*
* @param string $method
* @return static
*/
public function setMethod($method);
}
+13 -13
View File
@@ -2,8 +2,8 @@
namespace Pecee\SimpleRouter\Route;
use Pecee\Handlers\IExceptionHandler;
use Pecee\Http\Request;
use Pecee\SimpleRouter\Handlers\IExceptionHandler;
interface IGroupRoute extends IRoute
{
@@ -13,21 +13,21 @@ interface IGroupRoute extends IRoute
* @param Request $request
* @return bool
*/
public function matchDomain(Request $request): bool;
public function matchDomain(Request $request);
/**
* Add exception handler
*
* @param IExceptionHandler|string $handler
* @return static
* @return static $this;
*/
public function addExceptionHandler($handler): self;
public function addExceptionHandler($handler);
/**
* Set exception-handlers for group
*
* @param array $handlers
* @return static
* @return static $this
*/
public function setExceptionHandlers(array $handlers);
@@ -36,35 +36,35 @@ interface IGroupRoute extends IRoute
*
* @return array
*/
public function getExceptionHandlers(): array;
public function getExceptionHandlers();
/**
* Get domains for domain.
*
* @return array
*/
public function getDomains(): array;
public function getDomains();
/**
* Set allowed domains for group.
*
* @param array $domains
* @return static
* @return $this
*/
public function setDomains(array $domains): self;
public function setDomains(array $domains);
/**
* Set prefix that child-routes will inherit.
*
* @param string $prefix
* @return static
* @return string
*/
public function setPrefix($prefix): self;
public function setPrefix($prefix);
/**
* Get prefix.
*
* @return string|null
* @return string
*/
public function getPrefix(): ?string;
public function getPrefix();
}
+13 -25
View File
@@ -1,9 +1,7 @@
<?php
namespace Pecee\SimpleRouter\Route;
use Pecee\Http\Request;
use Pecee\SimpleRouter\Router;
interface ILoadableRoute extends IRoute
{
@@ -12,39 +10,29 @@ interface ILoadableRoute extends IRoute
* Used when calling the url() helper.
*
* @param string|null $method
* @param array|string|null $parameters
* @param array|null $parameters
* @param string|null $name
* @return string
*/
public function findUrl(?string $method = null, $parameters = null, ?string $name = null): string;
public function findUrl($method = null, $parameters = null, $name = null);
/**
* Loads and renders middleware-classes
* Loads and renders middlewares-classes
*
* @param Request $request
* @param Router $router
*/
public function loadMiddleware(Request $request, Router $router): void;
public function loadMiddleware(Request $request);
/**
* Get url
* @return string
*/
public function getUrl(): string;
public function getUrl();
/**
* Set url
* @param string $url
* @return static
*/
public function setUrl(string $url): self;
public function setUrl($url);
/**
* Returns the provided name for the router.
*
* @return string|null
* @return string
*/
public function getName(): ?string;
public function getName();
/**
* Check if route has given name.
@@ -52,22 +40,22 @@ interface ILoadableRoute extends IRoute
* @param string $name
* @return bool
*/
public function hasName(string $name): bool;
public function hasName($name);
/**
* Sets the router name, which makes it easier to obtain the url or router at a later point.
*
* @param string $name
* @return static
* @return static $this
*/
public function setName(string $name): self;
public function setName($name);
/**
* Get regular expression match used for matching route (if defined).
*
* @return string
*/
public function getMatch(): ?string;
public function getMatch();
/**
* Add regular expression match for the entire route.
@@ -75,6 +63,6 @@ interface ILoadableRoute extends IRoute
* @param string $regex
* @return static
*/
public function setMatch($regex): self;
public function setMatch($regex);
}
+36 -58
View File
@@ -3,7 +3,6 @@
namespace Pecee\SimpleRouter\Route;
use Pecee\Http\Request;
use Pecee\SimpleRouter\Router;
interface IRoute
{
@@ -14,18 +13,17 @@ interface IRoute
* @param Request $request
* @return bool
*/
public function matchRoute($route, Request $request): bool;
public function matchRoute($route, Request $request);
/**
* Called when route is matched.
* Returns class to be rendered.
*
* @param Request $request
* @param Router $router
* @throws \Pecee\SimpleRouter\Exceptions\NotFoundHttpException
* @return string
*/
public function renderRoute(Request $request, Router $router): ?string;
public function renderRoute(Request $request);
/**
* Returns callback name/identifier for the current route based on the callback.
@@ -34,50 +32,50 @@ interface IRoute
*
* @return string
*/
public function getIdentifier(): string;
public function getIdentifier();
/**
* Set allowed request methods
*
* @param array $methods
* @return static
* @return static $this
*/
public function setRequestMethods(array $methods): self;
public function setRequestMethods(array $methods);
/**
* Get allowed request methods
*
* @return array
*/
public function getRequestMethods(): array;
public function getRequestMethods();
/**
* @return IRoute|null
*/
public function getParent(): ?IRoute;
public function getParent();
/**
* Get the group for the route.
*
* @return IGroupRoute|null
*/
public function getGroup(): ?IGroupRoute;
public function getGroup();
/**
* Set group
*
* @param IGroupRoute $group
* @return static
* @return static $this
*/
public function setGroup(IGroupRoute $group): self;
public function setGroup(IGroupRoute $group);
/**
* Set parent route
*
* @param IRoute $parent
* @return static
* @return static $this
*/
public function setParent(IRoute $parent): self;
public function setParent(IRoute $parent);
/**
* Set callback
@@ -85,64 +83,44 @@ interface IRoute
* @param string $callback
* @return static
*/
public function setCallback($callback): self;
public function setCallback($callback);
/**
* @return string|callable
* @return string
*/
public function getCallback();
/**
* Return active method
*
* @return string|null
*/
public function getMethod(): ?string;
public function getMethod();
/**
* Set active method
*
* @param string $method
* @return static
*/
public function setMethod(string $method): self;
public function getClass();
/**
* Get class
*
* @return string|null
*/
public function getClass(): ?string;
public function setMethod($method);
/**
* @param string $namespace
* @return static
* @return static $this
*/
public function setNamespace(string $namespace): self;
public function setNamespace($namespace);
/**
* @return string|null
* @return string
*/
public function getNamespace(): ?string;
public function getNamespace();
/**
* @param string $namespace
* @return static
* @return static $this
*/
public function setDefaultNamespace($namespace): IRoute;
public function setDefaultNamespace($namespace);
/**
* Get default namespace
* @return string|null
*/
public function getDefaultNamespace(): ?string;
public function getDefaultNamespace();
/**
* Get parameter names.
*
* @return array
*/
public function getWhere(): array;
public function getWhere();
/**
* Set parameter names.
@@ -150,45 +128,45 @@ interface IRoute
* @param array $options
* @return static
*/
public function setWhere(array $options): self;
public function setWhere(array $options);
/**
* Get parameters
*
* @return array
*/
public function getParameters(): array;
public function getParameters();
/**
* Get parameters
*
* @param array $parameters
* @return static
* @return static $this
*/
public function setParameters(array $parameters): self;
public function setParameters(array $parameters);
/**
* Merge with information from another route.
*
* @param array $settings
* @param bool $merge
* @return static
* @return static $this
*/
public function setSettings(array $settings, bool $merge = false): self;
public function setSettings(array $settings, $merge = false);
/**
* Export route settings to array so they can be merged with another route.
*
* @return array
*/
public function toArray(): array;
public function toArray();
/**
* Get middlewares array
*
* @return array
*/
public function getMiddlewares(): array;
public function getMiddlewares();
/**
* Set middleware class-name
@@ -196,14 +174,14 @@ interface IRoute
* @param string $middleware
* @return static
*/
public function addMiddleware($middleware): self;
public function addMiddleware($middleware);
/**
* Set middlewares array
*
* @param array $middlewares
* @return static
* @return $this
*/
public function setMiddlewares(array $middlewares): self;
public function setMiddlewares(array $middlewares);
}
+18 -28
View File
@@ -5,7 +5,6 @@ namespace Pecee\SimpleRouter\Route;
use Pecee\Http\Middleware\IMiddleware;
use Pecee\Http\Request;
use Pecee\SimpleRouter\Exceptions\HttpException;
use Pecee\SimpleRouter\Router;
abstract class LoadableRoute extends Route implements ILoadableRoute
{
@@ -25,34 +24,25 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
* Loads and renders middlewares-classes
*
* @param Request $request
* @param Router $router
* @throws HttpException
*/
public function loadMiddleware(Request $request, Router $router): void
public function loadMiddleware(Request $request)
{
$router->debug('Loading middlewares');
foreach ($this->getMiddlewares() as $middleware) {
if (\is_object($middleware) === false) {
$middleware = $router->getClassLoader()->loadClass($middleware);
if (is_object($middleware) === false) {
$middleware = $this->loadClass($middleware);
}
if (($middleware instanceof IMiddleware) === false) {
throw new HttpException($middleware . ' must be inherit the IMiddleware interface');
}
$className = \get_class($middleware);
$router->debug('Loading middleware "%s"', $className);
$middleware->handle($request);
$router->debug('Finished loading middleware "%s"', $className);
}
$router->debug('Finished loading middlewares');
}
public function matchRegex(Request $request, $url): ?bool
public function matchRegex(Request $request, $url)
{
/* Match on custom defined regular expression */
@@ -69,7 +59,7 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
* @param string $url
* @return static
*/
public function setUrl(string $url): ILoadableRoute
public function setUrl($url)
{
$this->url = ($url === '/') ? '/' : '/' . trim($url, '/') . '/';
@@ -85,7 +75,7 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
return $this;
}
public function getUrl(): string
public function getUrl()
{
return $this->url;
}
@@ -99,13 +89,13 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
* @param string|null $name
* @return string
*/
public function findUrl(?string $method = null, $parameters = null, ?string $name = null): string
public function findUrl($method = null, $parameters = null, $name = null)
{
$url = $this->getUrl();
$group = $this->getGroup();
if ($group !== null && \count($group->getDomains()) !== 0) {
if ($group !== null && count($group->getDomains()) !== 0) {
$url = '//' . $group->getDomains()[0] . $url;
}
@@ -124,7 +114,7 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
foreach (array_keys($params) as $param) {
if ($parameters === '' || (\is_array($parameters) === true && \count($parameters) === 0)) {
if ($parameters === '' || (is_array($parameters) === true && count($parameters) === 0)) {
$value = '';
} else {
$p = (array)$parameters;
@@ -154,7 +144,7 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
*
* @return string
*/
public function getName(): ?string
public function getName()
{
return $this->name;
}
@@ -165,9 +155,9 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
* @param string $name
* @return bool
*/
public function hasName(string $name): bool
public function hasName($name)
{
return strtolower($this->name) === strtolower($name);
return (strtolower($this->name) === strtolower($name));
}
/**
@@ -176,7 +166,7 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
* @param string $regex
* @return static
*/
public function setMatch($regex): ILoadableRoute
public function setMatch($regex)
{
$this->regex = $regex;
@@ -188,7 +178,7 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
*
* @return string
*/
public function getMatch(): string
public function getMatch()
{
return $this->regex;
}
@@ -201,7 +191,7 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
* @param string|array $name
* @return static
*/
public function name($name): ILoadableRoute
public function name($name)
{
return $this->setName($name);
}
@@ -210,9 +200,9 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
* Sets the router name, which makes it easier to obtain the url or router at a later point.
*
* @param string $name
* @return static
* @return static $this
*/
public function setName(string $name): ILoadableRoute
public function setName($name)
{
$this->name = $name;
@@ -226,7 +216,7 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
* @param bool $merge
* @return static
*/
public function setSettings(array $values, bool $merge = false): IRoute
public function setSettings(array $values, $merge = false)
{
if (isset($values['as']) === true) {
+80 -77
View File
@@ -5,19 +5,18 @@ namespace Pecee\SimpleRouter\Route;
use Pecee\Http\Middleware\IMiddleware;
use Pecee\Http\Request;
use Pecee\SimpleRouter\Exceptions\NotFoundHttpException;
use Pecee\SimpleRouter\Router;
abstract class Route implements IRoute
{
protected const PARAMETERS_REGEX_FORMAT = '%s([\w]+)(\%s?)%s';
protected const PARAMETERS_DEFAULT_REGEX = '[\w]+';
const PARAMETERS_REGEX_FORMAT = '%s([\w]+)(\%s?)%s';
const PARAMETERS_DEFAULT_REGEX = '[\w]+';
public const REQUEST_TYPE_GET = 'get';
public const REQUEST_TYPE_POST = 'post';
public const REQUEST_TYPE_PUT = 'put';
public const REQUEST_TYPE_PATCH = 'patch';
public const REQUEST_TYPE_OPTIONS = 'options';
public const REQUEST_TYPE_DELETE = 'delete';
const REQUEST_TYPE_GET = 'get';
const REQUEST_TYPE_POST = 'post';
const REQUEST_TYPE_PUT = 'put';
const REQUEST_TYPE_PATCH = 'patch';
const REQUEST_TYPE_OPTIONS = 'options';
const REQUEST_TYPE_DELETE = 'delete';
public static $requestTypes = [
self::REQUEST_TYPE_GET,
@@ -57,29 +56,40 @@ abstract class Route implements IRoute
protected $originalParameters = [];
protected $middlewares = [];
/**
* Load class by name
* @param string $name
* @return mixed
* @throws NotFoundHttpException
*/
protected function loadClass($name)
{
if (class_exists($name) === false) {
throw new NotFoundHttpException(sprintf('Class "%s" does not exist', $name), 404);
}
return new $name();
}
/**
* Render route
*
* @param Request $request
* @param Router $router
* @return string|null
* @return string|mixed
* @throws NotFoundHttpException
*/
public function renderRoute(Request $request, Router $router): ?string
public function renderRoute(Request $request)
{
$router->debug('Starting rendering route "%s"', \get_class($this));
$callback = $this->getCallback();
if ($callback === null) {
return null;
}
$router->debug('Parsing parameters');
$parameters = $this->getParameters();
$router->debug('Finished parsing parameters');
/* Filter parameters with null-value */
if ($this->filterEmptyParams === true) {
$parameters = array_filter($parameters, function ($var) {
return ($var !== null);
@@ -87,12 +97,9 @@ abstract class Route implements IRoute
}
/* Render callback function */
if (\is_callable($callback) === true) {
$router->debug('Executing callback');
if (is_callable($callback) === true) {
/* When the callback is a function */
return $router->getClassLoader()->loadClosure($callback, $parameters);
return call_user_func_array($callback, $parameters);
}
/* When the callback is a class + method */
@@ -102,18 +109,14 @@ abstract class Route implements IRoute
$className = ($namespace !== null && $controller[0][0] !== '\\') ? $namespace . '\\' . $controller[0] : $controller[0];
$router->debug('Loading class %s', $className);
$class = $router->getClassLoader()->loadClass($className);
$class = $this->loadClass($className);
$method = $controller[1];
if (method_exists($class, $method) === false) {
throw new NotFoundHttpException(sprintf('Method "%s" does not exist in class "%s"', $method, $className), 404);
}
$router->debug('Executing callback');
return \call_user_func_array([$class, $method], $parameters);
return call_user_func_array([$class, $method], $parameters);
}
protected function parseParameters($route, $url, $parameterRegex = null)
@@ -122,7 +125,7 @@ abstract class Route implements IRoute
$parameters = [];
// Ensures that host names/domains will work with parameters
// Ensures that hostnames/domains will work with parameters
$url = '/' . ltrim($url, '/');
if ((bool)preg_match_all('/' . $regex . '/u', $route, $parameters) === false) {
@@ -135,7 +138,7 @@ abstract class Route implements IRoute
$regex = '';
if ($key < \count($parameters[1])) {
if ($key < count($parameters[1])) {
$name = $parameters[1][$key];
@@ -148,7 +151,7 @@ abstract class Route implements IRoute
if ($parameterRegex !== null) {
$regex = $parameterRegex;
} else {
$regex = $this->defaultParameterRegex ?? static::PARAMETERS_DEFAULT_REGEX;
$regex = ($this->defaultParameterRegex === null) ? static::PARAMETERS_DEFAULT_REGEX : $this->defaultParameterRegex;
}
}
@@ -186,22 +189,22 @@ abstract class Route implements IRoute
*
* @return string
*/
public function getIdentifier(): string
public function getIdentifier()
{
if (\is_string($this->callback) === true && strpos($this->callback, '@') !== false) {
if (is_string($this->callback) === true && strpos($this->callback, '@') !== false) {
return $this->callback;
}
return 'function:' . md5($this->callback);
return 'function_' . md5($this->callback);
}
/**
* Set allowed request methods
*
* @param array $methods
* @return static
* @return static $this
*/
public function setRequestMethods(array $methods): IRoute
public function setRequestMethods(array $methods)
{
$this->requestMethods = $methods;
@@ -213,7 +216,7 @@ abstract class Route implements IRoute
*
* @return array
*/
public function getRequestMethods(): array
public function getRequestMethods()
{
return $this->requestMethods;
}
@@ -221,7 +224,7 @@ abstract class Route implements IRoute
/**
* @return IRoute|null
*/
public function getParent(): ?IRoute
public function getParent()
{
return $this->parent;
}
@@ -231,7 +234,7 @@ abstract class Route implements IRoute
*
* @return IGroupRoute|null
*/
public function getGroup(): ?IGroupRoute
public function getGroup()
{
return $this->group;
}
@@ -240,9 +243,9 @@ abstract class Route implements IRoute
* Set group
*
* @param IGroupRoute $group
* @return static
* @return static $this
*/
public function setGroup(IGroupRoute $group): IRoute
public function setGroup(IGroupRoute $group)
{
$this->group = $group;
@@ -256,9 +259,9 @@ abstract class Route implements IRoute
* Set parent route
*
* @param IRoute $parent
* @return static
* @return static $this
*/
public function setParent(IRoute $parent): IRoute
public function setParent(IRoute $parent)
{
$this->parent = $parent;
@@ -271,7 +274,7 @@ abstract class Route implements IRoute
* @param string $callback
* @return static
*/
public function setCallback($callback): IRoute
public function setCallback($callback)
{
$this->callback = $callback;
@@ -279,16 +282,16 @@ abstract class Route implements IRoute
}
/**
* @return string|callable
* @return string
*/
public function getCallback()
{
return $this->callback;
}
public function getMethod(): ?string
public function getMethod()
{
if (\is_string($this->callback) === true && strpos($this->callback, '@') !== false) {
if (is_string($this->callback) === true && strpos($this->callback, '@') !== false) {
$tmp = explode('@', $this->callback);
return $tmp[1];
@@ -297,9 +300,9 @@ abstract class Route implements IRoute
return null;
}
public function getClass(): ?string
public function getClass()
{
if (\is_string($this->callback) === true && strpos($this->callback, '@') !== false) {
if (is_string($this->callback) === true && strpos($this->callback, '@') !== false) {
$tmp = explode('@', $this->callback);
return $tmp[0];
@@ -308,14 +311,14 @@ abstract class Route implements IRoute
return null;
}
public function setMethod(string $method): IRoute
public function setMethod($method)
{
$this->callback = sprintf('%s@%s', $this->getClass(), $method);
return $this;
}
public function setClass(string $class): IRoute
public function setClass($class)
{
$this->callback = sprintf('%s@%s', $class, $this->getMethod());
@@ -324,9 +327,9 @@ abstract class Route implements IRoute
/**
* @param string $namespace
* @return static
* @return static $this
*/
public function setNamespace(string $namespace): IRoute
public function setNamespace($namespace)
{
$this->namespace = $namespace;
@@ -335,26 +338,26 @@ abstract class Route implements IRoute
/**
* @param string $namespace
* @return static
* @return static $this
*/
public function setDefaultNamespace($namespace): IRoute
public function setDefaultNamespace($namespace)
{
$this->defaultNamespace = $namespace;
return $this;
}
public function getDefaultNamespace(): ?string
public function getDefaultNamespace()
{
return $this->defaultNamespace;
}
/**
* @return string|null
* @return string
*/
public function getNamespace(): ?string
public function getNamespace()
{
return $this->namespace ?? $this->defaultNamespace;
return ($this->namespace === null) ? $this->defaultNamespace : $this->namespace;
}
/**
@@ -362,7 +365,7 @@ abstract class Route implements IRoute
*
* @return array
*/
public function toArray(): array
public function toArray()
{
$values = [];
@@ -370,15 +373,15 @@ abstract class Route implements IRoute
$values['namespace'] = $this->namespace;
}
if (\count($this->requestMethods) !== 0) {
if (count($this->requestMethods) !== 0) {
$values['method'] = $this->requestMethods;
}
if (\count($this->where) !== 0) {
if (count($this->where) !== 0) {
$values['where'] = $this->where;
}
if (\count($this->middlewares) !== 0) {
if (count($this->middlewares) !== 0) {
$values['middleware'] = $this->middlewares;
}
@@ -394,9 +397,9 @@ abstract class Route implements IRoute
*
* @param array $values
* @param bool $merge
* @return static
* @return static $this
*/
public function setSettings(array $values, bool $merge = false): IRoute
public function setSettings(array $values, $merge = false)
{
if ($this->namespace === null && isset($values['namespace']) === true) {
$this->setNamespace($values['namespace']);
@@ -431,7 +434,7 @@ abstract class Route implements IRoute
*
* @return array
*/
public function getWhere(): array
public function getWhere()
{
return $this->where;
}
@@ -442,7 +445,7 @@ abstract class Route implements IRoute
* @param array $options
* @return static
*/
public function setWhere(array $options): IRoute
public function setWhere(array $options)
{
$this->where = $options;
@@ -467,12 +470,12 @@ abstract class Route implements IRoute
*
* @return array
*/
public function getParameters(): array
public function getParameters()
{
/* Sort the parameters after the user-defined param order, if any */
$parameters = [];
if (\count($this->originalParameters) !== 0) {
if (count($this->originalParameters) !== 0) {
$parameters = $this->originalParameters;
}
@@ -483,15 +486,15 @@ abstract class Route implements IRoute
* Get parameters
*
* @param array $parameters
* @return static
* @return static $this
*/
public function setParameters(array $parameters): IRoute
public function setParameters(array $parameters)
{
/*
* If this is the first time setting parameters we store them so we
* later can organize the array, in case somebody tried to sort the array.
*/
if (\count($parameters) !== 0 && \count($this->originalParameters) === 0) {
if (count($parameters) !== 0 && count($this->originalParameters) === 0) {
$this->originalParameters = $parameters;
}
@@ -520,7 +523,7 @@ abstract class Route implements IRoute
* @param IMiddleware|string $middleware
* @return static
*/
public function addMiddleware($middleware): IRoute
public function addMiddleware($middleware)
{
$this->middlewares[] = $middleware;
@@ -531,9 +534,9 @@ abstract class Route implements IRoute
* Set middlewares array
*
* @param array $middlewares
* @return static
* @return $this
*/
public function setMiddlewares(array $middlewares): IRoute
public function setMiddlewares(array $middlewares)
{
$this->middlewares = $middlewares;
@@ -543,7 +546,7 @@ abstract class Route implements IRoute
/**
* @return array
*/
public function getMiddlewares(): array
public function getMiddlewares()
{
return $this->middlewares;
}
@@ -553,7 +556,7 @@ abstract class Route implements IRoute
* This is used when no custom parameter regex is found.
*
* @param string $regex
* @return static
* @return static $this
*/
public function setDefaultParameterRegex($regex)
{
@@ -567,7 +570,7 @@ abstract class Route implements IRoute
*
* @return string
*/
public function getDefaultParameterRegex(): string
public function getDefaultParameterRegex()
{
return $this->defaultParameterRegex;
}
@@ -24,7 +24,7 @@ class RouteController extends LoadableRoute implements IControllerRoute
* @param string $name
* @return bool
*/
public function hasName(string $name): bool
public function hasName($name)
{
if ($this->name === null) {
return false;
@@ -35,7 +35,7 @@ class RouteController extends LoadableRoute implements IControllerRoute
$method = substr($name, strrpos($name, '.') + 1);
$newName = substr($name, 0, strrpos($name, '.'));
if (\in_array($method, $this->names, true) === true && strtolower($this->name) === strtolower($newName)) {
if (in_array($method, $this->names, false) === true && strtolower($this->name) === strtolower($newName)) {
return true;
}
}
@@ -49,7 +49,7 @@ class RouteController extends LoadableRoute implements IControllerRoute
* @param string|null $name
* @return string
*/
public function findUrl(?string $method = null, $parameters = null, ?string $name = null): string
public function findUrl($method = null, $parameters = null, $name = null)
{
if (strpos($name, '.') !== false) {
$found = array_search(substr($name, strrpos($name, '.') + 1), $this->names, false);
@@ -67,7 +67,7 @@ class RouteController extends LoadableRoute implements IControllerRoute
foreach (static::$requestTypes as $requestType) {
if (stripos($method, $requestType) === 0) {
$method = (string)substr($method, \strlen($requestType));
$method = (string)substr($method, strlen($requestType));
break;
}
}
@@ -77,7 +77,7 @@ class RouteController extends LoadableRoute implements IControllerRoute
$group = $this->getGroup();
if ($group !== null && \count($group->getDomains()) !== 0) {
if ($group !== null && count($group->getDomains()) !== 0) {
$url .= '//' . $group->getDomains()[0];
}
@@ -86,9 +86,9 @@ class RouteController extends LoadableRoute implements IControllerRoute
return '/' . trim($url, '/') . '/';
}
public function matchRoute($url, Request $request): bool
public function matchRoute($url, Request $request)
{
if ($this->getGroup() !== null && $this->getGroup()->matchRoute($url, $request) === false) {
if($this->getGroup() !== null && $this->getGroup()->matchRoute($url, $request) === false) {
return false;
}
@@ -102,12 +102,12 @@ class RouteController extends LoadableRoute implements IControllerRoute
$strippedUrl = trim(str_ireplace($this->url, '/', $url), '/');
$path = explode('/', $strippedUrl);
if (\count($path) !== 0) {
if (count($path) !== 0) {
$method = (isset($path[0]) === false || trim($path[0]) === '') ? $this->defaultMethod : $path[0];
$this->method = $request->getMethod() . ucfirst($method);
$this->parameters = \array_slice($path, 1);
$this->parameters = array_slice($path, 1);
// Set callback
$this->setCallback($this->controller . '@' . $this->method);
@@ -123,7 +123,7 @@ class RouteController extends LoadableRoute implements IControllerRoute
*
* @return string
*/
public function getController(): string
public function getController()
{
return $this->controller;
}
@@ -134,7 +134,7 @@ class RouteController extends LoadableRoute implements IControllerRoute
* @param string $controller
* @return static
*/
public function setController(string $controller): IControllerRoute
public function setController($controller)
{
$this->controller = $controller;
@@ -144,9 +144,9 @@ class RouteController extends LoadableRoute implements IControllerRoute
/**
* Return active method
*
* @return string|null
* @return string
*/
public function getMethod(): ?string
public function getMethod()
{
return $this->method;
}
@@ -157,7 +157,7 @@ class RouteController extends LoadableRoute implements IControllerRoute
* @param string $method
* @return static
*/
public function setMethod(string $method): IRoute
public function setMethod($method)
{
$this->method = $method;
@@ -171,7 +171,7 @@ class RouteController extends LoadableRoute implements IControllerRoute
* @param bool $merge
* @return static
*/
public function setSettings(array $values, bool $merge = false): IRoute
public function setSettings(array $values, $merge = false)
{
if (isset($values['names']) === true) {
$this->names = $values['names'];
+20 -20
View File
@@ -2,8 +2,8 @@
namespace Pecee\SimpleRouter\Route;
use Pecee\Handlers\IExceptionHandler;
use Pecee\Http\Request;
use Pecee\SimpleRouter\Handlers\IExceptionHandler;
class RouteGroup extends Route implements IGroupRoute
{
@@ -18,9 +18,9 @@ class RouteGroup extends Route implements IGroupRoute
* @param Request $request
* @return bool
*/
public function matchDomain(Request $request): bool
public function matchDomain(Request $request)
{
if ($this->domains === null || \count($this->domains) === 0) {
if ($this->domains === null || count($this->domains) === 0) {
return true;
}
@@ -28,7 +28,7 @@ class RouteGroup extends Route implements IGroupRoute
$parameters = $this->parseParameters($domain, $request->getHost(), '.*');
if ($parameters !== null && \count($parameters) !== 0) {
if ($parameters !== null && count($parameters) !== 0) {
$this->parameters = $parameters;
@@ -46,9 +46,9 @@ class RouteGroup extends Route implements IGroupRoute
* @param Request $request
* @return bool
*/
public function matchRoute($url, Request $request): bool
public function matchRoute($url, Request $request)
{
if ($this->getGroup() !== null && $this->getGroup()->matchRoute($url, $request) === false) {
if($this->getGroup() !== null && $this->getGroup()->matchRoute($url, $request) === false) {
return false;
}
@@ -64,9 +64,9 @@ class RouteGroup extends Route implements IGroupRoute
* Add exception handler
*
* @param IExceptionHandler|string $handler
* @return static
* @return static $this
*/
public function addExceptionHandler($handler): IGroupRoute
public function addExceptionHandler($handler)
{
$this->exceptionHandlers[] = $handler;
@@ -77,9 +77,9 @@ class RouteGroup extends Route implements IGroupRoute
* Set exception-handlers for group
*
* @param array $handlers
* @return static
* @return static $this
*/
public function setExceptionHandlers(array $handlers): IGroupRoute
public function setExceptionHandlers(array $handlers)
{
$this->exceptionHandlers = $handlers;
@@ -91,7 +91,7 @@ class RouteGroup extends Route implements IGroupRoute
*
* @return array
*/
public function getExceptionHandlers(): array
public function getExceptionHandlers()
{
return $this->exceptionHandlers;
}
@@ -101,7 +101,7 @@ class RouteGroup extends Route implements IGroupRoute
*
* @return array
*/
public function getDomains(): array
public function getDomains()
{
return $this->domains;
}
@@ -110,9 +110,9 @@ class RouteGroup extends Route implements IGroupRoute
* Set allowed domains for group.
*
* @param array $domains
* @return static
* @return $this
*/
public function setDomains(array $domains): IGroupRoute
public function setDomains(array $domains)
{
$this->domains = $domains;
@@ -123,7 +123,7 @@ class RouteGroup extends Route implements IGroupRoute
* @param string $prefix
* @return static
*/
public function setPrefix($prefix): IGroupRoute
public function setPrefix($prefix)
{
$this->prefix = '/' . trim($prefix, '/');
@@ -133,9 +133,9 @@ class RouteGroup extends Route implements IGroupRoute
/**
* Set prefix that child-routes will inherit.
*
* @return string|null
* @return string
*/
public function getPrefix(): ?string
public function getPrefix()
{
return $this->prefix;
}
@@ -147,7 +147,7 @@ class RouteGroup extends Route implements IGroupRoute
* @param bool $merge
* @return static
*/
public function setSettings(array $values, bool $merge = false): IRoute
public function setSettings(array $values, $merge = false)
{
if (isset($values['prefix']) === true) {
@@ -183,7 +183,7 @@ class RouteGroup extends Route implements IGroupRoute
*
* @return array
*/
public function toArray(): array
public function toArray()
{
$values = [];
@@ -195,7 +195,7 @@ class RouteGroup extends Route implements IGroupRoute
$values['as'] = $this->name;
}
if (\count($this->parameters) !== 0) {
if (count($this->parameters) !== 0) {
$values['parameters'] = $this->parameters;
}
@@ -6,14 +6,7 @@ use Pecee\Http\Request;
class RoutePartialGroup extends RouteGroup implements IPartialGroupRoute
{
/**
* RoutePartialGroup constructor.
*/
public function __construct()
{
$this->urlRegex = '/^%s\/?/u';
}
protected $urlRegex = '/^%s\/?/u';
/**
* Method called to check if route matches
@@ -22,12 +15,12 @@ class RoutePartialGroup extends RouteGroup implements IPartialGroupRoute
* @param Request $request
* @return bool
*/
public function matchRoute($url, Request $request): bool
public function matchRoute($url, Request $request)
{
if ($this->getGroup() !== null && $this->getGroup()->matchRoute($url, $request) === false) {
if($this->getGroup() !== null && $this->getGroup()->matchRoute($url, $request) === false) {
return false;
}
if ($this->prefix !== null) {
/* Parse parameters from current route */
$parameters = $this->parseParameters($this->prefix, $url);
+11 -17
View File
@@ -42,7 +42,7 @@ class RouteResource extends LoadableRoute implements IControllerRoute
* @param string $name
* @return bool
*/
public function hasName(string $name): bool
public function hasName($name)
{
if ($this->name === null) {
return false;
@@ -60,13 +60,7 @@ class RouteResource extends LoadableRoute implements IControllerRoute
return (strtolower($this->name) === strtolower($name));
}
/**
* @param string|null $method
* @param array|string|null $parameters
* @param string|null $name
* @return string
*/
public function findUrl(?string $method = null, $parameters = null, ?string $name = null): string
public function findUrl($method = null, $parameters = null, $name = null)
{
$url = array_search($name, $this->names, false);
if ($url !== false) {
@@ -83,9 +77,9 @@ class RouteResource extends LoadableRoute implements IControllerRoute
return true;
}
public function matchRoute($url, Request $request): bool
public function matchRoute($url, Request $request)
{
if ($this->getGroup() !== null && $this->getGroup()->matchRoute($url, $request) === false) {
if($this->getGroup() !== null && $this->getGroup()->matchRoute($url, $request) === false) {
return false;
}
@@ -120,7 +114,7 @@ class RouteResource extends LoadableRoute implements IControllerRoute
}
// Update
if ($id !== null && \in_array($method, [static::REQUEST_TYPE_PATCH, static::REQUEST_TYPE_PUT], true) === true) {
if ($id !== null && in_array($method, [static::REQUEST_TYPE_PATCH, static::REQUEST_TYPE_PUT], false) === true) {
return $this->call($this->methodNames['update']);
}
@@ -151,7 +145,7 @@ class RouteResource extends LoadableRoute implements IControllerRoute
/**
* @return string
*/
public function getController(): string
public function getController()
{
return $this->controller;
}
@@ -160,14 +154,14 @@ class RouteResource extends LoadableRoute implements IControllerRoute
* @param string $controller
* @return static
*/
public function setController(string $controller): IControllerRoute
public function setController($controller)
{
$this->controller = $controller;
return $this;
}
public function setName(string $name): ILoadableRoute
public function setName($name)
{
$this->name = $name;
@@ -200,9 +194,9 @@ class RouteResource extends LoadableRoute implements IControllerRoute
/**
* Get method names
*
* @return array
* @return array $this
*/
public function getMethodNames(): array
public function getMethodNames()
{
return $this->methodNames;
}
@@ -214,7 +208,7 @@ class RouteResource extends LoadableRoute implements IControllerRoute
* @param bool $merge
* @return static
*/
public function setSettings(array $values, bool $merge = false): IRoute
public function setSettings(array $values, $merge = false)
{
if (isset($values['names']) === true) {
$this->names = $values['names'];
+2 -2
View File
@@ -12,9 +12,9 @@ class RouteUrl extends LoadableRoute
$this->setCallback($callback);
}
public function matchRoute($url, Request $request): bool
public function matchRoute($url, Request $request)
{
if ($this->getGroup() !== null && $this->getGroup()->matchRoute($url, $request) === false) {
if($this->getGroup() !== null && $this->getGroup()->matchRoute($url, $request) === false) {
return false;
}
+137 -453
View File
@@ -3,17 +3,11 @@
namespace Pecee\SimpleRouter;
use Pecee\Exceptions\InvalidArgumentException;
use Pecee\Http\Exceptions\MalformedUrlException;
use Pecee\Handlers\IExceptionHandler;
use Pecee\Http\Middleware\BaseCsrfVerifier;
use Pecee\Http\Request;
use Pecee\Http\Url;
use Pecee\SimpleRouter\ClassLoader\ClassLoader;
use Pecee\SimpleRouter\ClassLoader\IClassLoader;
use Pecee\SimpleRouter\Exceptions\HttpException;
use Pecee\SimpleRouter\Exceptions\NotFoundHttpException;
use Pecee\SimpleRouter\Handlers\EventHandler;
use Pecee\SimpleRouter\Handlers\IEventHandler;
use Pecee\SimpleRouter\Handlers\IExceptionHandler;
use Pecee\SimpleRouter\Route\IControllerRoute;
use Pecee\SimpleRouter\Route\IGroupRoute;
use Pecee\SimpleRouter\Route\ILoadableRoute;
@@ -33,32 +27,32 @@ class Router
* Defines if a route is currently being processed.
* @var bool
*/
protected $isProcessingRoute;
protected $processingRoute;
/**
* All added routes
* @var array
*/
protected $routes = [];
protected $routes;
/**
* List of processed routes
* @var array
*/
protected $processedRoutes = [];
protected $processedRoutes;
/**
* Stack of routes used to keep track of sub-routes added
* when a route is being processed.
* @var array
*/
protected $routeStack = [];
protected $routeStack;
/**
* List of added bootmanagers
* @var array
*/
protected $bootManagers = [];
protected $bootManagers;
/**
* Csrf verifier class
@@ -70,48 +64,11 @@ class Router
* Get exception handlers
* @var array
*/
protected $exceptionHandlers = [];
/**
* List of loaded exception that has been loaded.
* Used to ensure that exception-handlers aren't loaded twice when rewriting route.
*
* @var array
*/
protected $loadedExceptionHandlers = [];
/**
* Enable or disabled debugging
* @var bool
*/
protected $debugEnabled = false;
/**
* The start time used when debugging is enabled
* @var float
*/
protected $debugStartTime;
/**
* List containing all debug messages
* @var array
*/
protected $debugList = [];
/**
* Contains any registered event-handler.
* @var array
*/
protected $eventHandlers = [];
/**
* Class loader instance
* @var ClassLoader
*/
protected $classLoader;
protected $exceptionHandlers;
/**
* Router constructor.
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public function __construct()
{
@@ -119,29 +76,17 @@ class Router
}
/**
* Resets the router by reloading request and clearing all routes and data.
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public function reset(): void
public function reset()
{
$this->debugStartTime = microtime(true);
$this->isProcessingRoute = false;
try {
$this->request = new Request();
} catch (MalformedUrlException $e) {
$this->debug(sprintf('Invalid request-uri url: %s', $e->getMessage()));
}
$this->processingRoute = false;
$this->request = new Request();
$this->routes = [];
$this->bootManagers = [];
$this->routeStack = [];
$this->processedRoutes = [];
$this->exceptionHandlers = [];
$this->loadedExceptionHandlers = [];
$this->eventHandlers = [];
$this->debugList = [];
$this->csrfVerifier = null;
$this->classLoader = new ClassLoader();
}
/**
@@ -149,20 +94,18 @@ class Router
* @param IRoute $route
* @return IRoute
*/
public function addRoute(IRoute $route): IRoute
public function addRoute(IRoute $route)
{
/*
* If a route is currently being processed, that means that the route being added are rendered from the parent
* routes callback, so we add them to the stack instead.
*/
if ($this->isProcessingRoute === true) {
if ($this->processingRoute === true) {
$this->routeStack[] = $route;
return $route;
}
$this->routes[] = $route;
return $route;
}
@@ -172,14 +115,13 @@ class Router
* @param IRoute $route
* @throws NotFoundHttpException
*/
protected function renderAndProcess(IRoute $route): void
{
protected function renderAndProcess(IRoute $route) {
$this->isProcessingRoute = true;
$route->renderRoute($this->request, $this);
$this->isProcessingRoute = false;
$this->processingRoute = true;
$route->renderRoute($this->request);
$this->processingRoute = false;
if (\count($this->routeStack) !== 0) {
if (count($this->routeStack) !== 0) {
/* Pop and grab the routes added when executing group callback earlier */
$stack = $this->routeStack;
@@ -197,27 +139,21 @@ class Router
* @param IGroupRoute|null $group
* @throws NotFoundHttpException
*/
protected function processRoutes(array $routes, ?IGroupRoute $group = null): void
protected function processRoutes(array $routes, IGroupRoute $group = null)
{
$this->debug('Processing routes');
// Loop through each route-request
$exceptionHandlers = [];
// Stop processing routes if no valid route is found.
if ($this->request->getRewriteRoute() === null && $this->request->getUrl() === null) {
$this->debug('Halted route-processing as no valid route was found');
if($this->request->getRewriteRoute() === null && $this->request->getUrl() === null) {
return;
}
$url = $this->request->getRewriteUrl() ?? $this->request->getUrl()->getPath();
$url = ($this->request->getRewriteUrl() !== null) ? $this->request->getRewriteUrl() : $this->request->getUrl()->getPath();
/* @var $route IRoute */
foreach ($routes as $route) {
$this->debug('Processing route "%s"', \get_class($route));
if ($group !== null) {
/* Add the parent group */
$route->setGroup($group);
@@ -229,7 +165,7 @@ class Router
if ($route->matchRoute($url, $this->request) === true) {
/* Add exception handlers */
if (\count($route->getExceptionHandlers()) !== 0) {
if (count($route->getExceptionHandlers()) !== 0) {
/** @noinspection AdditionOperationOnArraysInspection */
$exceptionHandlers += $route->getExceptionHandlers();
}
@@ -263,143 +199,81 @@ class Router
* @throws NotFoundHttpException
* @return void
*/
public function loadRoutes(): void
public function loadRoutes()
{
$this->debug('Loading routes');
$this->fireEvents(EventHandler::EVENT_BOOT, [
'bootmanagers' => $this->bootManagers,
]);
/* Initialize boot-managers */
/* @var $manager IRouterBootManager */
foreach ($this->bootManagers as $manager) {
$className = \get_class($manager);
$this->debug('Rendering bootmanager "%s"', $className);
$this->fireEvents(EventHandler::EVENT_RENDER_BOOTMANAGER, [
'bootmanagers' => $this->bootManagers,
'bootmanager' => $manager,
]);
/* Render bootmanager */
$manager->boot($this, $this->request);
$this->debug('Finished rendering bootmanager "%s"', $className);
$manager->boot($this->request);
}
$this->fireEvents(EventHandler::EVENT_LOAD_ROUTES, [
'routes' => $this->routes,
]);
/* Loop through each route-request */
$this->processRoutes($this->routes);
$this->debug('Finished loading routes');
}
/**
* Start the routing
*
* @return string|null
* @throws \Pecee\SimpleRouter\Exceptions\NotFoundHttpException
* @throws \Pecee\Http\Middleware\Exceptions\TokenMismatchException
* @throws HttpException
* @throws \Exception
*/
public function start(): ?string
{
$this->debug('Router starting');
$this->fireEvents(EventHandler::EVENT_INIT);
$this->loadRoutes();
if ($this->csrfVerifier !== null) {
$this->fireEvents(EventHandler::EVENT_RENDER_CSRF, [
'csrfVerifier' => $this->csrfVerifier,
]);
/* Verify csrf token for request */
$this->csrfVerifier->handle($this->request);
}
$output = $this->routeRequest();
$this->fireEvents(EventHandler::EVENT_LOAD, [
'loadedRoutes' => $this->getRequest()->getLoadedRoutes(),
]);
$this->debug('Routing complete');
return $output;
}
/**
* Routes the request
*
* @return string|null
* @param bool $rewrite
* @return string|mixed
* @throws HttpException
* @throws \Exception
*/
public function routeRequest(): ?string
public function routeRequest($rewrite = false)
{
$this->debug('Routing request');
$methodNotAllowed = false;
$routeNotAllowed = false;
try {
$url = $this->request->getRewriteUrl() ?? $this->request->getUrl()->getPath();
if ($rewrite === false) {
$this->loadRoutes();
if ($this->csrfVerifier !== null) {
/* Verify csrf token for request */
$this->csrfVerifier->handle($this->request);
}
} else {
$this->request->setHasRewrite(false);
}
$url = ($this->request->getRewriteUrl() !== null) ? $this->request->getRewriteUrl() : $this->request->getUrl()->getPath();
/* @var $route ILoadableRoute */
foreach ($this->processedRoutes as $key => $route) {
$this->debug('Matching route "%s"', \get_class($route));
/* If the route matches */
if ($route->matchRoute($url, $this->request) === true) {
$this->fireEvents(EventHandler::EVENT_MATCH_ROUTE, [
'route' => $route,
]);
/* Check if request method matches */
if (\count($route->getRequestMethods()) !== 0 && \in_array($this->request->getMethod(), $route->getRequestMethods(), true) === false) {
$this->debug('Method "%s" not allowed', $this->request->getMethod());
$methodNotAllowed = true;
if (count($route->getRequestMethods()) !== 0 && in_array($this->request->getMethod(), $route->getRequestMethods(), false) === false) {
$routeNotAllowed = true;
continue;
}
$this->fireEvents(EventHandler::EVENT_RENDER_MIDDLEWARES, [
'route' => $route,
'middlewares' => $route->getMiddlewares(),
]);
$route->loadMiddleware($this->request);
$route->loadMiddleware($this->request, $this);
if ($this->hasRewrite($url) === true) {
unset($this->processedRoutes[$key]);
return $this->routeRequest(true);
}
/* Render route */
$routeNotAllowed = false;
$this->request->setLoadedRoute($route);
$output = $route->renderRoute($this->request);
$output = $this->handleRouteRewrite($key, $url);
if ($output !== null) {
return $output;
}
$methodNotAllowed = false;
if ($this->hasRewrite($url) === true) {
unset($this->processedRoutes[$key]);
$this->request->addLoadedRoute($route);
$this->fireEvents(EventHandler::EVENT_RENDER_ROUTE, [
'route' => $route,
]);
$output = $route->renderRoute($this->request, $this);
if ($output !== null) {
return $output;
}
$output = $this->handleRouteRewrite($key, $url);
if ($output !== null) {
return $output;
return $this->routeRequest(true);
}
}
}
@@ -408,12 +282,12 @@ class Router
$this->handleException($e);
}
if ($methodNotAllowed === true) {
if ($routeNotAllowed === true) {
$message = sprintf('Route "%s" or method "%s" not allowed.', $this->request->getUrl()->getPath(), $this->request->getMethod());
$this->handleException(new HttpException($message, 403));
}
if (\count($this->request->getLoadedRoutes()) === 0) {
if ($this->request->getLoadedRoute() === null) {
$rewriteUrl = $this->request->getRewriteUrl();
@@ -423,185 +297,136 @@ class Router
$message = sprintf('Route not found: "%s"', $this->request->getUrl()->getPath());
}
$this->debug($message);
return $this->handleException(new NotFoundHttpException($message, 404));
$this->handleException(new NotFoundHttpException($message, 404));
}
return null;
}
/**
* Handle route-rewrite
*
* @param string $key
* @param string $url
* @return string|null
* @throws HttpException
* @throws \Exception
*/
protected function handleRouteRewrite($key, string $url): ?string
protected function hasRewrite($url)
{
/* If the request has changed */
if ($this->request->hasPendingRewrite() === false) {
return null;
if ($this->request->hasRewrite() === true) {
if ($this->request->getRewriteRoute() !== null) {
/* Render rewrite-route */
$this->processedRoutes[] = $this->request->getRewriteRoute();
return true;
}
if ($this->request->isRewrite($url) === false) {
/* Render rewrite-url */
$this->processedRoutes = array_values($this->processedRoutes);
return true;
}
}
$route = $this->request->getRewriteRoute();
if ($route !== null) {
/* Add rewrite route */
$this->processedRoutes[] = $route;
}
if ($this->request->getRewriteUrl() !== $url) {
unset($this->processedRoutes[$key]);
$this->request->setHasPendingRewrite(false);
$this->fireEvents(EventHandler::EVENT_REWRITE, [
'rewriteUrl' => $this->request->getRewriteUrl(),
'rewriteRoute' => $this->request->getRewriteRoute(),
]);
return $this->routeRequest();
}
return null;
return false;
}
/**
* @param \Exception $e
* @throws HttpException
* @throws \Exception
* @return string|null
* @return string
*/
protected function handleException(\Exception $e): ?string
protected function handleException(\Exception $e)
{
$this->debug('Starting exception handling for "%s"', \get_class($e));
$this->fireEvents(EventHandler::EVENT_LOAD_EXCEPTIONS, [
'exception' => $e,
'exceptionHandlers' => $this->exceptionHandlers,
]);
/* @var $handler IExceptionHandler */
foreach ($this->exceptionHandlers as $key => $handler) {
if (\is_object($handler) === false) {
if (is_object($handler) === false) {
$handler = new $handler();
}
$this->fireEvents(EventHandler::EVENT_RENDER_EXCEPTION, [
'exception' => $e,
'exceptionHandler' => $handler,
'exceptionHandlers' => $this->exceptionHandlers,
]);
$this->debug('Processing exception-handler "%s"', \get_class($handler));
if (($handler instanceof IExceptionHandler) === false) {
throw new HttpException('Exception handler must implement the IExceptionHandler interface.', 500);
}
try {
$this->debug('Start rendering exception handler');
$handler->handleError($this->request, $e);
$this->debug('Finished rendering exception-handler');
if (isset($this->loadedExceptionHandlers[$key]) === false && $this->request->hasPendingRewrite() === true) {
if ($this->request->hasRewrite() === true) {
unset($this->exceptionHandlers[$key]);
$this->exceptionHandlers = array_values($this->exceptionHandlers);
$this->loadedExceptionHandlers[$key] = $handler;
$this->debug('Exception handler contains rewrite, reloading routes');
$this->fireEvents(EventHandler::EVENT_REWRITE, [
'rewriteUrl' => $this->request->getRewriteUrl(),
'rewriteRoute' => $this->request->getRewriteRoute(),
]);
if ($this->request->getRewriteRoute() !== null) {
$this->processedRoutes[] = $this->request->getRewriteRoute();
}
return $this->routeRequest();
return $this->routeRequest(true);
}
} catch (\Exception $e) {
}
$this->debug('Finished processing');
}
$this->debug('Finished exception handling - exception not handled, throwing');
throw $e;
}
public function arrayToParams(array $getParams = [], $includeEmpty = true)
{
if (count($getParams) !== 0) {
if ($includeEmpty === false) {
$getParams = array_filter($getParams, function ($item) {
return (trim($item) !== '');
});
}
return '?' . http_build_query($getParams);
}
return '';
}
/**
* Find route by alias, class, callback or method.
*
* @param string $name
* @return ILoadableRoute|null
*/
public function findRoute(string $name): ?ILoadableRoute
public function findRoute($name)
{
$this->debug('Finding route by name "%s"', $name);
$this->fireEvents(EventHandler::EVENT_FIND_ROUTE, [
'name' => $name,
]);
/* @var $route ILoadableRoute */
foreach ($this->processedRoutes as $route) {
/* Check if the name matches with a name on the route. Should match either router alias or controller alias. */
if ($route->hasName($name) === true) {
$this->debug('Found route "%s" by name "%s"', $route->getUrl(), $name);
if ($route->hasName($name)) {
return $route;
}
/* Direct match to controller */
if ($route instanceof IControllerRoute && strtolower($route->getController()) === strtolower($name)) {
$this->debug('Found route "%s" by controller "%s"', $route->getUrl(), $name);
return $route;
}
/* Using @ is most definitely a controller@method or alias@method */
if (\is_string($name) === true && strpos($name, '@') !== false) {
[$controller, $method] = array_map('strtolower', explode('@', $name));
if (is_string($name) === true && strpos($name, '@') !== false) {
list($controller, $method) = array_map('strtolower', explode('@', $name));
if ($controller === strtolower($route->getClass()) && $method === strtolower($route->getMethod())) {
$this->debug('Found route "%s" by controller "%s" and method "%s"', $route->getUrl(), $controller, $method);
return $route;
}
}
/* Check if callback matches (if it's not a function) */
$callback = $route->getCallback();
if (\is_string($name) === true && \is_string($callback) === true && strpos($name, '@') !== false && strpos($callback, '@') !== false && \is_callable($callback) === false) {
if (is_string($name) === true && is_string($route->getCallback()) && strpos($name, '@') !== false && strpos($route->getCallback(), '@') !== false && is_callable($route->getCallback()) === false) {
/* Check if the entire callback is matching */
if (strpos($callback, $name) === 0 || strtolower($callback) === strtolower($name)) {
$this->debug('Found route "%s" by callback "%s"', $route->getUrl(), $name);
if (strpos($route->getCallback(), $name) === 0 || strtolower($route->getCallback()) === strtolower($name)) {
return $route;
}
/* Check if the class part of the callback matches (class@method) */
if (strtolower($name) === strtolower($route->getClass())) {
$this->debug('Found route "%s" by class "%s"', $route->getUrl(), $name);
return $route;
}
}
}
$this->debug('Route not found');
return null;
}
@@ -620,26 +445,17 @@ class Router
* @param string|null $name
* @param string|array|null $parameters
* @param array|null $getParams
* @return Url
* @throws InvalidArgumentException
* @throws \Pecee\Http\Exceptions\MalformedUrlException
* @return string
*/
public function getUrl(?string $name = null, $parameters = null, ?array $getParams = null): Url
public function getUrl($name = null, $parameters = null, $getParams = null)
{
$this->debug('Finding url', \func_get_args());
$this->fireEvents(EventHandler::EVENT_GET_URL, [
'name' => $name,
'parameters' => $parameters,
'getParams' => $getParams,
]);
if ($getParams !== null && \is_array($getParams) === false) {
if ($getParams !== null && is_array($getParams) === false) {
throw new InvalidArgumentException('Invalid type for getParams. Must be array or null');
}
if ($name === '' && $parameters === '') {
return new Url('/');
return '/';
}
/* Only merge $_GET when all parameters are null */
@@ -651,34 +467,26 @@ class Router
/* Return current route if no options has been specified */
if ($name === null && $parameters === null) {
return $this->request
->getUrlCopy()
->setParams($getParams);
return $this->request->getUrl()->getPath() . $this->arrayToParams($getParams);
}
$loadedRoute = $this->request->getLoadedRoute();
/* If nothing is defined and a route is loaded we use that */
if ($name === null && $loadedRoute !== null) {
return $this->request
->getUrlCopy()
->setPath($loadedRoute->findUrl($loadedRoute->getMethod(), $parameters, $name))
->setParams($getParams);
return $loadedRoute->findUrl($loadedRoute->getMethod(), $parameters, $name) . $this->arrayToParams($getParams);
}
/* We try to find a match on the given name */
$route = $this->findRoute($name);
if ($route !== null) {
return $this->request
->getUrlCopy()
->setPath($route->findUrl($route->getMethod(), $parameters, $name))
->setParams($getParams);
return $route->findUrl($route->getMethod(), $parameters, $name) . $this->arrayToParams($getParams);
}
/* Using @ is most definitely a controller@method or alias@method */
if (\is_string($name) === true && strpos($name, '@') !== false) {
[$controller, $method] = explode('@', $name);
if (is_string($name) === true && strpos($name, '@') !== false) {
list($controller, $method) = explode('@', $name);
/* Loop through all the routes to see if we can find a match */
@@ -687,18 +495,12 @@ class Router
/* Check if the route contains the name/alias */
if ($route->hasName($controller) === true) {
return $this->request
->getUrlCopy()
->setPath($route->findUrl($method, $parameters, $name))
->setParams($getParams);
return $route->findUrl($method, $parameters, $name) . $this->arrayToParams($getParams);
}
/* Check if the route controller is equal to the name */
if ($route instanceof IControllerRoute && strtolower($route->getController()) === strtolower($controller)) {
return $this->request
->getUrlCopy()
->setPath($route->findUrl($method, $parameters, $name))
->setParams($getParams);
return $route->findUrl($method, $parameters, $name) . $this->arrayToParams($getParams);
}
}
@@ -706,47 +508,35 @@ class Router
/* No result so we assume that someone is using a hardcoded url and join everything together. */
$url = trim(implode('/', array_merge((array)$name, (array)$parameters)), '/');
$url = (($url === '') ? '/' : '/' . $url . '/');
return $this->request
->getUrlCopy()
->setPath($url)
->setParams($getParams);
return (($url === '') ? '/' : '/' . $url . '/') . $this->arrayToParams($getParams);
}
/**
* Get BootManagers
* Get bootmanagers
* @return array
*/
public function getBootManagers(): array
public function getBootManagers()
{
return $this->bootManagers;
}
/**
* Set BootManagers
*
* Set bootmanagers
* @param array $bootManagers
* @return static
*/
public function setBootManagers(array $bootManagers): self
public function setBootManagers(array $bootManagers)
{
$this->bootManagers = $bootManagers;
return $this;
}
/**
* Add BootManager
*
* Add bootmanager
* @param IRouterBootManager $bootManager
* @return static
*/
public function addBootManager(IRouterBootManager $bootManager): self
public function addBootManager(IRouterBootManager $bootManager)
{
$this->bootManagers[] = $bootManager;
return $this;
}
/**
@@ -754,7 +544,7 @@ class Router
*
* @return array
*/
public function getProcessedRoutes(): array
public function getProcessedRoutes()
{
return $this->processedRoutes;
}
@@ -762,7 +552,7 @@ class Router
/**
* @return array
*/
public function getRoutes(): array
public function getRoutes()
{
return $this->routes;
}
@@ -771,9 +561,9 @@ class Router
* Set routes
*
* @param array $routes
* @return static
* @return static $this
*/
public function setRoutes(array $routes): self
public function setRoutes(array $routes)
{
$this->routes = $routes;
@@ -785,7 +575,7 @@ class Router
*
* @return Request
*/
public function getRequest(): Request
public function getRequest()
{
return $this->request;
}
@@ -794,7 +584,7 @@ class Router
* Get csrf verifier class
* @return BaseCsrfVerifier
*/
public function getCsrfVerifier(): ?BaseCsrfVerifier
public function getCsrfVerifier()
{
return $this->csrfVerifier;
}
@@ -805,117 +595,11 @@ class Router
* @param BaseCsrfVerifier $csrfVerifier
* @return static
*/
public function setCsrfVerifier(BaseCsrfVerifier $csrfVerifier): self
public function setCsrfVerifier(BaseCsrfVerifier $csrfVerifier)
{
$this->csrfVerifier = $csrfVerifier;
return $this;
}
/**
* Set class loader
*
* @param IClassLoader $loader
* @return static
*/
public function setClassLoader(IClassLoader $loader)
{
$this->classLoader = $loader;
return $this;
}
/**
* Get class loader
*
* @return ClassLoader
*/
public function getClassLoader(): IClassLoader
{
return $this->classLoader;
}
/**
* Register event handler
*
* @param IEventHandler $handler
* @return static
*/
public function addEventHandler(IEventHandler $handler): self
{
$this->eventHandlers[] = $handler;
return $this;
}
/**
* Get registered event-handler.
*
* @return array
*/
public function getEventHandlers(): array
{
return $this->eventHandlers;
}
/**
* Fire event in event-handler.
*
* @param string $name
* @param array $arguments
*/
protected function fireEvents($name, array $arguments = []): void
{
if (\count($this->eventHandlers) === 0) {
return;
}
/* @var IEventHandler $eventHandler */
foreach ($this->eventHandlers as $eventHandler) {
$eventHandler->fireEvents($this, $name, $arguments);
}
}
/**
* Add new debug message
* @param string $message
* @param array $args
*/
public function debug(string $message, ...$args): void
{
if ($this->debugEnabled === false) {
return;
}
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
$this->debugList[] = [
'message' => vsprintf($message, $args),
'time' => number_format(microtime(true) - $this->debugStartTime, 10),
'trace' => end($trace),
];
}
/**
* Enable or disables debugging
*
* @param bool $enabled
* @return static
*/
public function setDebugEnabled(bool $enabled): self
{
$this->debugEnabled = $enabled;
return $this;
}
/**
* Get the list containing all debug messages.
*
* @return array
*/
public function getDebugLog(): array
{
return $this->debugList;
}
}
+58 -138
View File
@@ -10,23 +10,15 @@
namespace Pecee\SimpleRouter;
use DI\Container;
use Pecee\Exceptions\InvalidArgumentException;
use Pecee\Http\Exceptions\MalformedUrlException;
use Pecee\Handlers\CallbackExceptionHandler;
use Pecee\Http\Middleware\BaseCsrfVerifier;
use Pecee\Http\Request;
use Pecee\Http\Response;
use Pecee\Http\Url;
use Pecee\SimpleRouter\ClassLoader\IClassLoader;
use Pecee\SimpleRouter\Exceptions\HttpException;
use Pecee\SimpleRouter\Handlers\CallbackExceptionHandler;
use Pecee\SimpleRouter\Handlers\IEventHandler;
use Pecee\SimpleRouter\Route\IGroupRoute;
use Pecee\SimpleRouter\Route\IPartialGroupRoute;
use Pecee\SimpleRouter\Route\IRoute;
use Pecee\SimpleRouter\Route\RoutePartialGroup;
use Pecee\SimpleRouter\Route\RouteController;
use Pecee\SimpleRouter\Route\RouteGroup;
use Pecee\SimpleRouter\Route\RoutePartialGroup;
use Pecee\SimpleRouter\Route\RouteResource;
use Pecee\SimpleRouter\Route\RouteUrl;
@@ -34,7 +26,7 @@ class SimpleRouter
{
/**
* Default namespace added to all routes
* @var string|null
* @var string
*/
protected static $defaultNamespace;
@@ -51,72 +43,13 @@ class SimpleRouter
protected static $router;
/**
* Start routing
*
* @throws \Pecee\SimpleRouter\Exceptions\NotFoundHttpException
* @throws \Pecee\Http\Middleware\Exceptions\TokenMismatchException
* @throws \Pecee\Http\Exceptions\MalformedUrlException
* @throws HttpException
* @throws \Exception
*/
public static function start(): void
public static function start()
{
echo static::router()->start();
}
/**
* Start the routing an return array with debugging-information
*
* @return array
*/
public static function startDebug(): array
{
$routerOutput = null;
try {
ob_start();
static::router()->setDebugEnabled(true);
static::start();
$routerOutput = ob_get_contents();
ob_end_clean();
} catch (\Exception $e) {
}
// Try to parse library version
$composerFile = \dirname(__DIR__, 3) . '/composer.lock';
$version = false;
if (is_file($composerFile) === true) {
$composerInfo = json_decode(file_get_contents($composerFile), true);
if (isset($composerInfo['packages']) === true && \is_array($composerInfo['packages']) === true) {
foreach ($composerInfo['packages'] as $package) {
if (isset($package['name']) === true && strtolower($package['name']) === 'pecee/simple-router') {
$version = $package['version'];
break;
}
}
}
}
$request = static::request();
$router = static::router();
return [
'url' => $request->getUrl(),
'method' => $request->getMethod(),
'host' => $request->getHost(),
'loaded_routes' => $request->getLoadedRoutes(),
'all_routes' => $router->getRoutes(),
'boot_managers' => $router->getBootManagers(),
'csrf_verifier' => $router->getCsrfVerifier(),
'log' => $router->getDebugLog(),
'event_handlers' => $router->getEventHandlers(),
'router_output' => $routerOutput,
'library_version' => $version,
'php_version' => PHP_VERSION,
'server_params' => $request->getHeaders(),
];
echo static::router()->routeRequest();
}
/**
@@ -124,7 +57,7 @@ class SimpleRouter
*
* @param string $defaultNamespace
*/
public static function setDefaultNamespace(string $defaultNamespace): void
public static function setDefaultNamespace($defaultNamespace)
{
static::$defaultNamespace = $defaultNamespace;
}
@@ -133,29 +66,21 @@ class SimpleRouter
* Base CSRF verifier
*
* @param BaseCsrfVerifier $baseCsrfVerifier
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function csrfVerifier(BaseCsrfVerifier $baseCsrfVerifier): void
public static function csrfVerifier(BaseCsrfVerifier $baseCsrfVerifier)
{
static::router()->setCsrfVerifier($baseCsrfVerifier);
}
/**
* Add new event handler to the router
*
* @param IEventHandler $eventHandler
*/
public static function addEventHandler(IEventHandler $eventHandler): void
{
static::router()->addEventHandler($eventHandler);
}
/**
* Boot managers allows you to alter the routes before the routing occurs.
* Perfect if you want to load pretty-urls from a file or database.
*
* @param IRouterBootManager $bootManager
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function addBootManager(IRouterBootManager $bootManager): void
public static function addBootManager(IRouterBootManager $bootManager)
{
static::router()->addBootManager($bootManager);
}
@@ -168,8 +93,9 @@ class SimpleRouter
* @param array|null $settings
*
* @return RouteUrl
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function get(string $url, $callback, array $settings = null): IRoute
public static function get($url, $callback, array $settings = null)
{
return static::match(['get'], $url, $callback, $settings);
}
@@ -181,8 +107,9 @@ class SimpleRouter
* @param string|\Closure $callback
* @param array|null $settings
* @return RouteUrl
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function post(string $url, $callback, array $settings = null): IRoute
public static function post($url, $callback, array $settings = null)
{
return static::match(['post'], $url, $callback, $settings);
}
@@ -194,8 +121,9 @@ class SimpleRouter
* @param string|\Closure $callback
* @param array|null $settings
* @return RouteUrl
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function put(string $url, $callback, array $settings = null): IRoute
public static function put($url, $callback, array $settings = null)
{
return static::match(['put'], $url, $callback, $settings);
}
@@ -207,8 +135,9 @@ class SimpleRouter
* @param string|\Closure $callback
* @param array|null $settings
* @return RouteUrl
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function patch(string $url, $callback, array $settings = null): IRoute
public static function patch($url, $callback, array $settings = null)
{
return static::match(['patch'], $url, $callback, $settings);
}
@@ -220,8 +149,9 @@ class SimpleRouter
* @param string|\Closure $callback
* @param array|null $settings
* @return RouteUrl
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function options(string $url, $callback, array $settings = null): IRoute
public static function options($url, $callback, array $settings = null)
{
return static::match(['options'], $url, $callback, $settings);
}
@@ -233,8 +163,9 @@ class SimpleRouter
* @param string|\Closure $callback
* @param array|null $settings
* @return RouteUrl
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function delete(string $url, $callback, array $settings = null): IRoute
public static function delete($url, $callback, array $settings = null)
{
return static::match(['delete'], $url, $callback, $settings);
}
@@ -245,11 +176,12 @@ class SimpleRouter
* @param array $settings
* @param \Closure $callback
* @return RouteGroup
* @throws \Pecee\Http\Exceptions\MalformedUrlException
* @throws InvalidArgumentException
*/
public static function group(array $settings = [], \Closure $callback): IGroupRoute
public static function group(array $settings = [], \Closure $callback)
{
if (\is_callable($callback) === false) {
if (is_callable($callback) === false) {
throw new InvalidArgumentException('Invalid callback provided. Only functions or methods supported');
}
@@ -270,11 +202,12 @@ class SimpleRouter
* @param \Closure $callback
* @param array $settings
* @return RoutePartialGroup
* @throws \Pecee\Http\Exceptions\MalformedUrlException
* @throws InvalidArgumentException
*/
public static function partialGroup(string $url, \Closure $callback, array $settings = []): IPartialGroupRoute
public static function partialGroup($url, \Closure $callback, array $settings = [])
{
if (\is_callable($callback) === false) {
if (is_callable($callback) === false) {
throw new InvalidArgumentException('Invalid callback provided. Only functions or methods supported');
}
@@ -297,8 +230,9 @@ class SimpleRouter
* @param array|null $settings
* @see SimpleRouter::form
* @return RouteUrl
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function basic(string $url, $callback, array $settings = null): IRoute
public static function basic($url, $callback, array $settings = null)
{
return static::match(['get', 'post'], $url, $callback, $settings);
}
@@ -312,8 +246,9 @@ class SimpleRouter
* @param array|null $settings
* @see SimpleRouter::form
* @return RouteUrl
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function form(string $url, $callback, array $settings = null): IRoute
public static function form($url, $callback, array $settings = null)
{
return static::match(['get', 'post'], $url, $callback, $settings);
}
@@ -326,8 +261,9 @@ class SimpleRouter
* @param string|\Closure $callback
* @param array|null $settings
* @return RouteUrl|IRoute
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function match(array $requestMethods, string $url, $callback, array $settings = null)
public static function match(array $requestMethods, $url, $callback, array $settings = null)
{
$route = new RouteUrl($url, $callback);
$route->setRequestMethods($requestMethods);
@@ -349,8 +285,9 @@ class SimpleRouter
* @param string|\Closure $callback
* @param array|null $settings
* @return RouteUrl|IRoute
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function all(string $url, $callback, array $settings = null)
public static function all($url, $callback, array $settings = null)
{
$route = new RouteUrl($url, $callback);
$route = static::addDefaultNamespace($route);
@@ -371,8 +308,9 @@ class SimpleRouter
* @param string $controller
* @param array|null $settings
* @return RouteController|IRoute
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function controller(string $url, $controller, array $settings = null)
public static function controller($url, $controller, array $settings = null)
{
$route = new RouteController($url, $controller);
$route = static::addDefaultNamespace($route);
@@ -393,8 +331,9 @@ class SimpleRouter
* @param string $controller
* @param array|null $settings
* @return RouteResource|IRoute
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function resource(string $url, $controller, array $settings = null)
public static function resource($url, $controller, array $settings = null)
{
$route = new RouteResource($url, $controller);
$route = static::addDefaultNamespace($route);
@@ -413,8 +352,9 @@ class SimpleRouter
*
* @param \Closure $callback
* @return CallbackExceptionHandler $callbackHandler
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function error(\Closure $callback): CallbackExceptionHandler
public static function error(\Closure $callback)
{
$routes = static::router()->getRoutes();
@@ -445,30 +385,22 @@ class SimpleRouter
* @param string|null $name
* @param string|array|null $parameters
* @param array|null $getParams
* @return Url
* @throws \Pecee\Exceptions\InvalidArgumentException
* @return string
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function getUrl(?string $name = null, $parameters = null, $getParams = null): Url
public static function getUrl($name = null, $parameters = null, $getParams = null)
{
try {
return static::router()->getUrl($name, $parameters, $getParams);
} catch (\Exception $e) {
try {
return new Url('/');
} catch (MalformedUrlException $e) {
}
}
// This will never happen...
return null;
return static::router()->getUrl($name, $parameters, $getParams);
}
/**
* Get the request
*
* @return \Pecee\Http\Request
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function request(): Request
public static function request()
{
return static::router()->getRequest();
}
@@ -477,8 +409,9 @@ class SimpleRouter
* Get the response object
*
* @return Response
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function response(): Response
public static function response()
{
if (static::$response === null) {
static::$response = new Response(static::request());
@@ -491,8 +424,9 @@ class SimpleRouter
* Returns the router instance
*
* @return Router
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function router(): Router
public static function router()
{
if (static::$router === null) {
static::$router = new Router();
@@ -507,14 +441,14 @@ class SimpleRouter
* @param IRoute $route
* @return IRoute
*/
public static function addDefaultNamespace(IRoute $route): IRoute
public static function addDefaultNamespace(IRoute $route)
{
if (static::$defaultNamespace !== null) {
$callback = $route->getCallback();
/* Only add default namespace on relative callbacks */
if ($callback === null || (\is_string($callback) === true && $callback[0] !== '\\')) {
if ($callback === null || (is_string($callback) === true && $callback[0] !== '\\')) {
$namespace = static::$defaultNamespace;
@@ -532,25 +466,11 @@ class SimpleRouter
return $route;
}
/**
* Enable or disable dependency injection
*
* @param Container $container
* @return IClassLoader
*/
public static function enableDependencyInjection(Container $container): IClassLoader
{
return static::router()
->getClassLoader()
->useDependencyInjection(true)
->setContainer($container);
}
/**
* Get default namespace
* @return string|null
* @return string
*/
public static function getDefaultNamespace(): ?string
public static function getDefaultNamespace()
{
return static::$defaultNamespace;
}
@@ -1,11 +1,11 @@
<?php
require_once 'Exception/MiddlewareLoadedException.php';
require_once 'Exceptions/MiddlewareLoadedException.php';
use Pecee\Http\Request;
class DummyMiddleware implements \Pecee\Http\Middleware\IMiddleware
{
public function handle(Request $request) : void
public function handle(Request $request)
{
throw new MiddlewareLoadedException('Middleware loaded!');
}
@@ -1,5 +1,4 @@
<?php
class ExceptionHandlerException extends \Exception
{
}
@@ -1,8 +1,8 @@
<?php
class ExceptionHandler implements \Pecee\SimpleRouter\Handlers\IExceptionHandler
class ExceptionHandler implements \Pecee\Handlers\IExceptionHandler
{
public function handleError(\Pecee\Http\Request $request, \Exception $error) : void
public function handleError(\Pecee\Http\Request $request, \Exception $error)
{
echo $error->getMessage();
}
@@ -0,0 +1,14 @@
<?php
class ExceptionHandlerFirst implements \Pecee\Handlers\IExceptionHandler
{
public function handleError(\Pecee\Http\Request $request, \Exception $error)
{
global $stack;
$stack[] = static::class;
$request->setUrl('/');
return $request;
}
}
@@ -0,0 +1,14 @@
<?php
class ExceptionHandlerSecond implements \Pecee\Handlers\IExceptionHandler
{
public function handleError(\Pecee\Http\Request $request, \Exception $error)
{
global $stack;
$stack[] = static::class;
$request->setUrl('/');
return $request;
}
}
@@ -1,8 +1,8 @@
<?php
class ExceptionHandlerThird implements \Pecee\SimpleRouter\Handlers\IExceptionHandler
class ExceptionHandlerThird implements \Pecee\Handlers\IExceptionHandler
{
public function handleError(\Pecee\Http\Request $request, \Exception $error) : void
public function handleError(\Pecee\Http\Request $request, \Exception $error)
{
global $stack;
$stack[] = static::class;
@@ -5,7 +5,7 @@ use Pecee\Http\Request;
class RewriteMiddleware implements IMiddleware {
public function handle(Request $request) : void {
public function handle(Request $request) {
$request->setRewriteCallback(function() {
return 'ok';
+39
View File
@@ -0,0 +1,39 @@
<?php
class ResourceController implements \Pecee\Controllers\IResourceController
{
public function index()
{
echo 'index';
}
public function show($id)
{
echo 'show ' . $id;
}
public function store()
{
echo 'store';
}
public function create()
{
echo 'create';
}
public function edit($id)
{
echo 'edit ' . $id;
}
public function update($id)
{
echo 'update ' . $id;
}
public function destroy($id)
{
echo 'destroy ' . $id;
}
}
@@ -2,16 +2,18 @@
require_once 'Dummy/DummyMiddleware.php';
require_once 'Dummy/DummyController.php';
require_once 'Helpers/TestRouter.php';
class GroupTest extends \PHPUnit\Framework\TestCase
class GroupTest extends PHPUnit_Framework_TestCase
{
protected $result;
public function testGroupLoad()
{
$result = false;
$this->result = false;
TestRouter::group(['prefix' => '/group'], function () use(&$result) {
$result = true;
TestRouter::group(['prefix' => '/group'], function () {
$this->result = true;
});
try {
@@ -19,7 +21,7 @@ class GroupTest extends \PHPUnit\Framework\TestCase
} catch(\Exception $e) {
}
$this->assertTrue($result);
$this->assertTrue($this->result);
}
public function testNestedGroup()
@@ -35,7 +37,6 @@ class GroupTest extends \PHPUnit\Framework\TestCase
TestRouter::debug('/api/v1/test', 'get');
$this->assertTrue(true);
}
public function testMultipleRoutes()
@@ -60,8 +61,6 @@ class GroupTest extends \PHPUnit\Framework\TestCase
});
TestRouter::debug('/my/match', 'get');
$this->assertTrue(true);
}
public function testUrls()
@@ -5,10 +5,8 @@ class TestRouter extends \Pecee\SimpleRouter\SimpleRouter
public static function debugNoReset($testUrl, $testMethod = 'get')
{
$request = static::request();
$request->setUrl((new \Pecee\Http\Url($testUrl))->setHost('local.unitTest'));
$request->setMethod($testMethod);
static::request()->setUrl($testUrl);
static::request()->setMethod($testMethod);
static::start();
}
@@ -3,12 +3,13 @@
require_once 'Dummy/DummyMiddleware.php';
require_once 'Dummy/DummyController.php';
require_once 'Dummy/Handler/ExceptionHandler.php';
require_once 'Helpers/TestRouter.php';
class MiddlewareTest extends \PHPUnit\Framework\TestCase
class MiddlewareTest extends PHPUnit_Framework_TestCase
{
public function testMiddlewareFound()
{
$this->expectException(MiddlewareLoadedException::class);
$this->setExpectedException(MiddlewareLoadedException::class);
TestRouter::group(['exceptionHandler' => 'ExceptionHandler'], function () {
TestRouter::get('/my/test/url', 'DummyController@method1', ['middleware' => 'DummyMiddleware']);
@@ -28,8 +29,6 @@ class MiddlewareTest extends \PHPUnit\Framework\TestCase
TestRouter::get('/my/test/url', 'DummyController@method1');
TestRouter::debug('/my/test/url', 'get');
$this->assertTrue(true);
}
}
@@ -2,14 +2,15 @@
require_once 'Dummy/DummyMiddleware.php';
require_once 'Dummy/DummyController.php';
require_once 'Dummy/Exception/ExceptionHandlerException.php';
require_once 'Dummy/Exceptions/ExceptionHandlerException.php';
require_once 'Helpers/TestRouter.php';
class RouterCallbackExceptionHandlerTest extends \PHPUnit\Framework\TestCase
class RouterCallbackExceptionHandlerTest extends PHPUnit_Framework_TestCase
{
public function testCallbackExceptionHandler()
{
$this->expectException(ExceptionHandlerException::class);
$this->setExpectedException(ExceptionHandlerException::class);
// Match normal route on alias
TestRouter::get('/my-new-url', 'DummyController@method2');
@@ -21,8 +22,6 @@ class RouterCallbackExceptionHandlerTest extends \PHPUnit\Framework\TestCase
TestRouter::debugNoReset('/404-url', 'get');
TestRouter::router()->reset();
$this->assertTrue(true);
}
}
@@ -1,8 +1,9 @@
<?php
require_once 'Dummy/DummyController.php';
require_once 'Helpers/TestRouter.php';
class RouterControllerTest extends \PHPUnit\Framework\TestCase
class RouterControllerTest extends PHPUnit_Framework_TestCase
{
public function testGet()
@@ -3,8 +3,9 @@
require_once 'Dummy/DummyMiddleware.php';
require_once 'Dummy/DummyController.php';
require_once 'Dummy/Handler/ExceptionHandler.php';
require_once 'Helpers/TestRouter.php';
class RouterPartialGroupTest extends \PHPUnit\Framework\TestCase
class RouterPartialGroupTest extends PHPUnit_Framework_TestCase
{
public function testParameters()
@@ -1,8 +1,9 @@
<?php
require_once 'Dummy/ResourceController.php';
require_once 'Helpers/TestRouter.php';
class RouterResourceTest extends \PHPUnit\Framework\TestCase
class RouterResourceTest extends PHPUnit_Framework_TestCase
{
public function testResourceStore()
@@ -1,12 +1,13 @@
<?php
require_once 'Dummy/DummyController.php';
require_once 'Dummy/Exception/ResponseException.php';
require_once 'Dummy/Exceptions/ResponseException.php';
require_once 'Dummy/Handler/ExceptionHandlerFirst.php';
require_once 'Dummy/Handler/ExceptionHandlerSecond.php';
require_once 'Dummy/Handler/ExceptionHandlerThird.php';
require_once 'Dummy/Middleware/RewriteMiddleware.php';
require_once 'Helpers/TestRouter.php';
require_once 'Dummy/Middlewares/RewriteMiddleware.php';
class RouteRewriteTest extends \PHPUnit\Framework\TestCase
class RouteRewriteTest extends PHPUnit_Framework_TestCase
{
/**
@@ -60,7 +61,7 @@ class RouteRewriteTest extends \PHPUnit\Framework\TestCase
public function testRewriteExceptionMessage()
{
$this->expectException(\Pecee\SimpleRouter\Exceptions\NotFoundHttpException::class);
$this->setExpectedException(\Pecee\SimpleRouter\Exceptions\NotFoundHttpException::class);
TestRouter::error(function (\Pecee\Http\Request $request, \Exception $error) {
@@ -2,30 +2,32 @@
require_once 'Dummy/DummyMiddleware.php';
require_once 'Dummy/DummyController.php';
require_once 'Dummy/Exception/ExceptionHandlerException.php';
require_once 'Dummy/Exceptions/ExceptionHandlerException.php';
require_once 'Helpers/TestRouter.php';
class RouterRouteTest extends \PHPUnit\Framework\TestCase
class RouterRouteTest extends PHPUnit_Framework_TestCase
{
protected $result = false;
public function testMultiParam()
{
$result = false;
TestRouter::get('/test-{param1}-{param2}', function ($param1, $param2) use(&$result) {
TestRouter::get('/test-{param1}-{param2}', function ($param1, $param2) {
if ($param1 === 'param1' && $param2 === 'param2') {
$result = true;
$this->result = true;
}
});
TestRouter::debug('/test-param1-param2', 'get');
$this->assertTrue($result);
$this->assertTrue($this->result);
}
public function testNotFound()
{
$this->expectException('\Pecee\SimpleRouter\Exceptions\NotFoundHttpException');
$this->setExpectedException('\Pecee\SimpleRouter\Exceptions\NotFoundHttpException');
TestRouter::get('/non-existing-path', 'DummyController@method1');
TestRouter::debug('/test-param1-param2', 'post');
}
@@ -34,32 +36,24 @@ class RouterRouteTest extends \PHPUnit\Framework\TestCase
{
TestRouter::get('/my/test/url', 'DummyController@method1');
TestRouter::debug('/my/test/url', 'get');
$this->assertTrue(true);
}
public function testPost()
{
TestRouter::post('/my/test/url', 'DummyController@method1');
TestRouter::debug('/my/test/url', 'post');
$this->assertTrue(true);
}
public function testPut()
{
TestRouter::put('/my/test/url', 'DummyController@method1');
TestRouter::debug('/my/test/url', 'put');
$this->assertTrue(true);
}
public function testDelete()
{
TestRouter::delete('/my/test/url', 'DummyController@method1');
TestRouter::debug('/my/test/url', 'delete');
$this->assertTrue(true);
}
public function testMethodNotAllowed()
@@ -91,37 +85,37 @@ class RouterRouteTest extends \PHPUnit\Framework\TestCase
public function testDomainAllowedRoute()
{
$result = false;
TestRouter::request()->setHost('hello.world.com');
$this->result = false;
TestRouter::group(['domain' => '{subdomain}.world.com'], function () use(&$result) {
TestRouter::get('/test', function ($subdomain = null) use(&$result) {
$result = ($subdomain === 'hello');
TestRouter::group(['domain' => '{subdomain}.world.com'], function () {
TestRouter::get('/test', function ($subdomain = null) {
$this->result = ($subdomain === 'hello');
});
});
TestRouter::request()->setHost('hello.world.com');
TestRouter::debug('/test', 'get');
$this->assertTrue($result);
$this->assertTrue($this->result);
}
public function testDomainNotAllowedRoute()
{
TestRouter::request()->setHost('other.world.com');
$this->result = false;
$result = false;
TestRouter::group(['domain' => '{subdomain}.world.com'], function () use(&$result) {
TestRouter::get('/test', function ($subdomain = null) use(&$result) {
$result = ($subdomain === 'hello');
TestRouter::group(['domain' => '{subdomain}.world.com'], function () {
TestRouter::get('/test', function ($subdomain = null) {
$this->result = ($subdomain === 'hello');
});
});
TestRouter::request()->setHost('other.world.com');
TestRouter::debug('/test', 'get');
$this->assertFalse($result);
$this->assertFalse($this->result);
}
@@ -129,8 +123,6 @@ class RouterRouteTest extends \PHPUnit\Framework\TestCase
{
TestRouter::get('/my/{path}', 'DummyController@method1')->where(['path' => '[a-zA-Z\-]+']);
TestRouter::debug('/my/custom-path', 'get');
$this->assertTrue(true);
}
public function testParameterDefaultValue() {
@@ -3,8 +3,9 @@
require_once 'Dummy/DummyMiddleware.php';
require_once 'Dummy/DummyController.php';
require_once 'Dummy/Handler/ExceptionHandler.php';
require_once 'Helpers/TestRouter.php';
class RouterUrlTest extends \PHPUnit\Framework\TestCase
class RouterUrlTest extends PHPUnit_Framework_TestCase
{
public function testIssue253()
@@ -31,22 +32,21 @@ class RouterUrlTest extends \PHPUnit\Framework\TestCase
{
// Test spanish characters
TestRouter::get('/cursos/listado/{listado?}/{category?}', 'DummyController@method1', ['defaultParameterRegex' => '[\w\p{L}\s-]+']);
TestRouter::get('/test/{param}', 'DummyController@method1', ['defaultParameterRegex' => '[\w\p{L}\s-\í]+']);
TestRouter::debugNoReset('/cursos/listado/especialidad/cirugía local', 'get');
$this->assertEquals('/cursos/listado/{listado?}/{category?}/', TestRouter::router()->getRequest()->getLoadedRoute()->getUrl());
TestRouter::debugNoReset('/test/Dermatología');
$parameters = TestRouter::request()->getLoadedRoute()->getParameters();
$this->assertEquals('Dermatología', $parameters['param']);
// Test danish characters
TestRouter::get('/kategori/økse', 'DummyController@method1', ['defaultParameterRegex' => '[\w\ø]+']);
TestRouter::debugNoReset('/kategori/økse', 'get');
$this->assertEquals('/kategori/økse/', TestRouter::router()->getRequest()->getLoadedRoute()->getUrl());
TestRouter::get('/test/{param}', 'DummyController@method1', ['defaultParameterRegex' => '[\w\p{L}\s-\í]+']);
TestRouter::debugNoReset('/test/Dermatología');
$parameters = TestRouter::request()->getLoadedRoute()->getParameters();
$this->assertEquals('Dermatología', $parameters['param']);
TestRouter::router()->reset();
}
@@ -1,53 +0,0 @@
<?php
require_once 'Dummy/DummyMiddleware.php';
class DependencyInjectionTest extends \PHPUnit\Framework\TestCase
{
public function testDependencyInjectionDevelopment()
{
$builder = new \DI\ContainerBuilder();
$container = $builder
->useAutowiring(true)
->ignorePhpDocErrors(true)
->build();
TestRouter::enableDependencyInjection($container);
$className = null;
TestRouter::get('/', function (DummyMiddleware $url) use (&$className) {
$className = \get_class($url);
});
TestRouter::debug('/');
$this->assertEquals(DummyMiddleware::class, $className);
}
public function testDependencyInjectionProduction()
{
$cacheDir = dirname(__DIR__, 2) . '/tmp';
$builder = new \DI\ContainerBuilder();
$builder
->enableCompilation($cacheDir)
->writeProxiesToFile(true, $cacheDir . '/proxies')
->ignorePhpDocErrors(true)
->useAutowiring(true);
$container = $builder->build();
TestRouter::enableDependencyInjection($container);
$className = null;
TestRouter::get('/', function (DummyMiddleware $url) use (&$className) {
$className = \get_class($url);
});
TestRouter::debug('/');
$this->assertEquals(DummyMiddleware::class, $className);
}
}
@@ -1,13 +0,0 @@
<?php
class ExceptionHandlerFirst implements \Pecee\SimpleRouter\Handlers\IExceptionHandler
{
public function handleError(\Pecee\Http\Request $request, \Exception $error) : void
{
global $stack;
$stack[] = static::class;
$request->setUrl(new \Pecee\Http\Url('/'));
}
}
@@ -1,13 +0,0 @@
<?php
class ExceptionHandlerSecond implements \Pecee\SimpleRouter\Handlers\IExceptionHandler
{
public function handleError(\Pecee\Http\Request $request, \Exception $error) : void
{
global $stack;
$stack[] = static::class;
$request->setUrl(new \Pecee\Http\Url('/'));
}
}
@@ -1,32 +0,0 @@
<?php
class TestBootManager implements \Pecee\SimpleRouter\IRouterBootManager
{
protected $routes;
protected $aliasUrl;
public function __construct(array $routes, string $aliasUrl)
{
$this->routes = $routes;
$this->aliasUrl = $aliasUrl;
}
/**
* Called when router loads it's routes
*
* @param \Pecee\SimpleRouter\Router $router
* @param \Pecee\Http\Request $request
*/
public function boot(\Pecee\SimpleRouter\Router $router, \Pecee\Http\Request $request): void
{
foreach ($this->routes as $url) {
// If the current url matches the rewrite url, we use our custom route
if ($request->getUrl()->contains($url) === true) {
$request->setRewriteUrl($this->aliasUrl);
}
}
}
}
@@ -1,46 +0,0 @@
<?php
class ResourceController implements \Pecee\Controllers\IResourceController
{
public function index() : ?string
{
echo 'index';
return null;
}
public function show($id) : ?string
{
echo 'show ' . $id;
return null;
}
public function store() : ?string
{
echo 'store';
return null;
}
public function create() : ?string
{
echo 'create';
return null;
}
public function edit($id) : ?string
{
echo 'edit ' . $id;
return null;
}
public function update($id) : ?string
{
echo 'update ' . $id;
return null;
}
public function destroy($id) : ?string
{
echo 'destroy ' . $id;
return null;
}
}
@@ -1,41 +0,0 @@
<?php
class SilentTokenProvider implements \Pecee\Http\Security\ITokenProvider {
protected $token;
public function __construct()
{
$this->refresh();
}
/**
* Refresh existing token
*/
public function refresh(): void
{
$this->token = uniqid('', false);
}
/**
* Validate valid CSRF token
*
* @param string $token
* @return bool
*/
public function validate(string $token): bool
{
return ($token === $this->token);
}
/**
* Get token token
*
* @param string|null $defaultValue
* @return string|null
*/
public function getToken(?string $defaultValue = null): ?string
{
return $this->token ?? $defaultValue;
}
}
@@ -1,81 +0,0 @@
<?php
require_once 'Dummy/DummyMiddleware.php';
require_once 'Dummy/DummyController.php';
require_once 'Dummy/Handler/ExceptionHandler.php';
require_once 'Dummy/Security/SilentTokenProvider.php';
require_once 'Dummy/Managers/TestBootManager.php';
use \Pecee\SimpleRouter\Handlers\EventHandler;
use \Pecee\SimpleRouter\Event\EventArgument;
class EventHandlerTest extends \PHPUnit\Framework\TestCase
{
public function testAllEventTriggered()
{
$events = EventHandler::$events;
// Remove the all event
unset($events[\array_search(EventHandler::EVENT_ALL, $events, true)]);
$eventHandler = new EventHandler();
$eventHandler->register(EventHandler::EVENT_ALL, function (EventArgument $arg) use (&$events) {
$key = \array_search($arg->getEventName(), $events, true);
unset($events[$key]);
});
TestRouter::addEventHandler($eventHandler);
// Add rewrite
TestRouter::error(function (\Pecee\Http\Request $request, \Exception $error) {
// Trigger rewrite
$request->setRewriteUrl('/');
});
TestRouter::get('/', 'DummyController@method1')->name('home');
// Trigger findRoute
TestRouter::router()->findRoute('home');
// Trigger getUrl
TestRouter::router()->getUrl('home');
// Add csrf-verifier
$csrfVerifier = new \Pecee\Http\Middleware\BaseCsrfVerifier();
$csrfVerifier->setTokenProvider(new SilentTokenProvider());
TestRouter::csrfVerifier($csrfVerifier);
// Add boot-manager
TestRouter::addBootManager(new TestBootManager([
'/test',
], '/'));
// Start router
TestRouter::debug('/non-existing');
$this->assertEquals($events, []);
}
public function testAllEvent()
{
$status = false;
$eventHandler = new EventHandler();
$eventHandler->register(EventHandler::EVENT_ALL, function (EventArgument $arg) use (&$status) {
$status = true;
});
TestRouter::addEventHandler($eventHandler);
TestRouter::get('/', 'DummyController@method1');
TestRouter::debug('/');
// All event should fire for each other event
$this->assertEquals(true, $status);
}
}
@@ -1,35 +0,0 @@
<?php
require_once 'Dummy/DummyMiddleware.php';
require_once 'Dummy/DummyController.php';
require_once 'Dummy/Handler/ExceptionHandler.php';
class InputHandlerTest extends \PHPUnit\Framework\TestCase
{
public function testGet()
{
$this->assertEquals(true, true);
}
public function testPost()
{
$this->assertEquals(true, true);
}
public function testFile()
{
$this->assertEquals(true, true);
}
public function testFiles()
{
$this->assertEquals(true, true);
}
public function testAll()
{
$this->assertEquals(true, true);
}
}
-4
View File
@@ -1,4 +0,0 @@
<?php
require_once dirname(__DIR__) . '/vendor/autoload.php';
require_once 'TestRouter.php';
-9
View File
@@ -1,9 +0,0 @@
<?php
require_once dirname(__DIR__) . '/vendor/autoload.php';
use \Pecee\SimpleRouter\SimpleRouter;
SimpleRouter::get('/user/{name}', 'UserController@show')->where(['name' => '[\w]+']);
$debugInfo = SimpleRouter::startDebug();
echo sprintf('<pre>%s</pre>', var_export($debugInfo, true));
exit;