├── LICENSE.md
├── composer.json
└── src
├── Console
├── ArgumentParser.php
├── BaseApplication.php
├── Command
│ ├── Command.php
│ └── Exception
│ │ └── MissingCommandException.php
├── CommandRunner.php
├── ConsoleApplication.php
├── ConsoleHelpFormatter.php
├── ConsoleInput.php
├── ConsoleIo.php
├── ConsoleOutput.php
├── ErrorHandler.php
├── Exception
│ ├── ConsoleException.php
│ └── StopExecutionException.php
├── LICENSE.md
└── composer.json
├── Core
├── .preloadignore
├── Autoloader.php
├── Bag.php
├── BaseObject.php
├── CallbackRegistrationTrait.php
├── CallbacksTrait.php
├── Config.php
├── Debugger.php
├── Dot.php
├── Exception
│ ├── Exception.php
│ ├── FileNotFoundException.php
│ ├── InvalidArgumentException.php
│ ├── MissingClassException.php
│ ├── MissingPluginException.php
│ └── RouterException.php
├── HookTrait.php
├── InitializerTrait.php
├── LICENSE.md
├── LazyLoadContainer.php
├── ModelTrait.php
├── ObjectRegistry.php
├── PhpFile.php
├── Plugin.php
├── Preloader.php
├── Resolver.php
├── bootstrap.php
├── composer.json
└── functions.php
├── Http
├── BaseApplication.php
├── Controller
│ ├── Component
│ │ ├── AuthComponent.php
│ │ ├── Component.php
│ │ ├── ComponentRegistry.php
│ │ ├── CookieComponent.php
│ │ ├── Exception
│ │ │ └── MissingComponentException.php
│ │ ├── FlashComponent.php
│ │ ├── PaginatorComponent.php
│ │ └── SessionComponent.php
│ ├── Controller.php
│ └── Exception
│ │ ├── MissingControllerException.php
│ │ ├── MissingMethodException.php
│ │ └── PrivateMethodException.php
├── Cookie.php
├── Dispatcher.php
├── ErrorHandler.php
├── Exception
│ ├── BadRequestException.php
│ ├── ForbiddenException.php
│ ├── HttpException.php
│ ├── InternalErrorException.php
│ ├── MethodNotAllowedException.php
│ ├── NotFoundException.php
│ ├── NotImplementedException.php
│ ├── ServiceUnavailableException.php
│ └── UnauthorizedException.php
├── ExceptionRenderer.php
├── LICENSE.md
├── Middleware
│ ├── AccessLogMiddleware.php
│ ├── CsrfProtectionMiddleware.php
│ ├── DispatcherMiddleware.php
│ ├── Exception
│ │ ├── InvalidCsrfTokenException.php
│ │ └── MaintainenceModeException.php
│ ├── FirewallMiddleware.php
│ ├── IdsMiddleware.php
│ ├── MaintenanceModeMiddleware.php
│ ├── Middleware.php
│ ├── MiddlewareRunner.php
│ ├── MinifyMiddleware.php
│ ├── ProfilerMiddleware.php
│ ├── SessionMiddleware.php
│ └── ThrottleMiddleware.php
├── Request.php
├── Response.php
├── Router.php
├── Session.php
├── Session
│ ├── Engine
│ │ ├── ArrayEngine.php
│ │ ├── BaseEngine.php
│ │ ├── PhpEngine.php
│ │ └── RedisEngine.php
│ └── SessionEngineInterface.php
├── View
│ ├── Exception
│ │ ├── MissingHelperException.php
│ │ ├── MissingLayoutException.php
│ │ ├── MissingSharedViewException.php
│ │ ├── MissingViewException.php
│ │ └── NotFoundException.php
│ ├── Helper
│ │ ├── BundleHelper.php
│ │ ├── CookieHelper.php
│ │ ├── DateHelper.php
│ │ ├── FlashHelper.php
│ │ ├── FormHelper.php
│ │ ├── Helper.php
│ │ ├── HelperRegistry.php
│ │ ├── HtmlHelper.php
│ │ ├── IntlHelper.php
│ │ ├── NumberHelper.php
│ │ ├── PaginatorHelper.php
│ │ └── SessionHelper.php
│ ├── JsonView.php
│ ├── TemplateTrait.php
│ ├── Templater.php
│ ├── View.php
│ └── XmlView.php
└── composer.json
├── I18n
├── Date.php
├── Exception
│ └── LocaleNotAvailableException.php
├── I18n.php
├── LICENSE.md
├── Locale
│ └── empty
├── Number.php
├── composer.json
└── functions.php
├── Job
├── Engine
│ ├── BaseEngine.php
│ ├── DatabaseEngine.php
│ ├── RedisConnection.php
│ └── RedisEngine.php
├── Job.php
├── LICENSE.md
├── Model
│ └── Queue.php
├── Queue.php
└── composer.json
├── Lock
├── LICENSE.md
├── Lock.php
└── composer.json
├── Mailbox
├── .preloadignore
├── Job
│ ├── MailboxCleanJob.php
│ └── MailboxJob.php
├── LICENSE.md
├── Mail.php
├── MailFetcher.php
├── MailParser.php
├── Mailbox.php
├── Model
│ ├── ImapMessage.php
│ └── InboundEmail.php
├── Server.php
├── Service
│ └── MailboxDownloadService.php
├── composer.json
└── pipe.php
├── Mailer
├── EmailBuilder.php
├── Exception
│ └── MissingTemplateException.php
├── LICENSE.md
├── Mailer.php
├── MailerJob.php
├── Message.php
└── composer.json
├── Migration
├── Exception
│ └── IrreversibleMigrationException.php
├── LICENSE.md
├── Migration.php
├── Sql.php
└── composer.json
├── Model
├── Association.php
├── BaseEntity.php
├── Collection.php
├── Concern
│ ├── Cacheable.php
│ ├── CounterCacheable.php
│ ├── Delocalizable.php
│ └── Timestampable.php
├── Connection.php
├── ConnectionManager.php
├── Engine
│ ├── MysqlEngine.php
│ ├── PostgresEngine.php
│ └── SqliteEngine.php
├── Entity.php
├── Exception
│ ├── ConnectionException.php
│ ├── DatasourceException.php
│ ├── MissingDatasourceException.php
│ ├── MissingModelException.php
│ ├── QueryBuilderException.php
│ ├── RecordNotFoundException.php
│ ├── RecordSaveException.php
│ └── ValidatorException.php
├── Finder.php
├── LICENSE.md
├── Marshaller.php
├── Model.php
├── ModelRegistry.php
├── ModelValidator.php
├── Query.php
├── Query
│ ├── BatchInsertQuery.php
│ └── QueryObject.php
├── QueryBuilder.php
├── Record.php
├── Repository
│ └── Repository.php
├── Schema.php
├── Schema
│ ├── BaseSchema.php
│ ├── MysqlSchema.php
│ ├── PostgresSchema.php
│ ├── SqliteSchema.php
│ └── TableSchema.php
├── Seed.php
├── ValidationRuleSet.php
└── composer.json
├── Process
├── BackgroundProcess.php
├── BaseProcess.php
├── Exception
│ └── TimeoutException.php
├── LICENSE.md
├── Process.php
└── composer.json
├── Publisher
├── Exception
│ └── PublisherException.php
├── LICENSE.md
├── Listener.php
├── ListenerJob.php
├── Publisher.php
├── PublisherTrait.php
└── composer.json
├── Redis
├── Connection.php
├── LICENSE.md
├── Redis.php
└── composer.json
├── Schedule
├── Command
│ └── ScheduleRunCommand.php
├── CronExpression.php
├── Event.php
├── Exception
│ └── ScheduleException.php
├── Schedule.php
├── Task.php
├── bin
│ └── schedule:run
└── composer.json
├── Service
├── LICENSE.md
├── Result.php
├── Service.php
└── composer.json
├── Ssh
├── RemoteFile.php
├── Ssh.php
└── composer.json
├── TestSuite
├── ConsoleIntegrationTestTrait.php
├── Exception
│ └── ConsoleInputRequiredException.php
├── Fixture.php
├── FixtureManager.php
├── IntegrationTestTrait.php
├── JobTestTrait.php
├── LICENSE.md
├── OriginTestCase.php
├── OriginTestListener.php
├── Stub
│ ├── ConsoleInput.php
│ ├── ConsoleOutput.php
│ └── Request.php
├── TestTrait.php
└── composer.json
└── Utility
├── Date.php
├── LICENSE.md
├── Number.php
└── composer.json
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018-2021 Jamiel Sharief.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "originphp/framework",
3 | "description": "The OriginPHP framework",
4 | "type": "library",
5 | "keywords": [
6 | "originPHP",
7 | "framework",
8 | "mvc",
9 | "easy",
10 | "simple",
11 | "convention over configuration",
12 | "orm",
13 | "docker",
14 | "rapid"
15 | ],
16 | "homepage": "https://www.originphp.com",
17 | "license": "MIT",
18 | "authors": [
19 | {
20 | "name": "Jamiel Sharief",
21 | "email": "js@originphp.com"
22 | }
23 | ],
24 | "autoload": {
25 | "psr-4": {
26 | "Origin\\": "src/"
27 | },
28 | "files": [
29 | "src/Core/functions.php",
30 | "src/I18n/functions.php"
31 | ]
32 | },
33 | "autoload-dev": {
34 | "psr-4": {
35 | "Origin\\Test\\": "tests/"
36 | }
37 | },
38 | "require": {
39 | "php": ">=7.3.0",
40 | "originphp/defer": "^3.0",
41 | "originphp/configurable": "^1.0|^2.0",
42 | "originphp/inflector": "^1.0|^2.0",
43 | "originphp/security": "^1.0|^2.0",
44 | "originphp/cache": "^1.0|^2.0",
45 | "originphp/email": "^1.0|^2.0",
46 | "originphp/html": "^1.0|^2.0",
47 | "originphp/xml": "^1.0|^2.0",
48 | "originphp/log": "^1.0|^2.0",
49 | "originphp/validation": "^1.0|^2.0",
50 | "originphp/dotenv": "^1.0|^2.0",
51 | "ext-json": "*",
52 | "ext-mbstring": "*",
53 | "ext-openssl": "*",
54 | "ext-intl": "*"
55 | },
56 | "require-dev": {
57 | "phpunit/phpunit": "^9.2",
58 | "phpstan/phpstan": "^0.12.64"
59 | },
60 | "replace": {
61 | "originphp/console": "self.version",
62 | "originphp/core": "self.version",
63 | "originphp/http": "self.version",
64 | "originphp/i18n": "self.version",
65 | "originphp/job": "self.version",
66 | "originphp/lock": "self.version",
67 | "originphp/mailbox": "self.version",
68 | "originphp/mailer": "self.version",
69 | "originphp/migration": "self.version",
70 | "originphp/model": "self.version",
71 | "originphp/process": "self.version",
72 | "originphp/publisher": "self.version",
73 | "originphp/redis": "self.version",
74 | "originphp/schedule": "self.version",
75 | "originphp/service": "self.version",
76 | "originphp/ssh": "self.version",
77 | "originphp/test-suite": "self.version",
78 | "originphp/utility": "self.version"
79 | },
80 | "suggest": {
81 | "ext-redis": "Redis",
82 | "ext-imap": "Imap",
83 | "ext-mailparse": "Mailparse",
84 | "ext-ssh2": "SSH2 extension"
85 | },
86 | "minimum-stability": "dev",
87 | "prefer-stable": true,
88 | "config": {
89 | "sort-packages": true
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/Console/BaseApplication.php:
--------------------------------------------------------------------------------
1 | executeHook('initialize');
27 | }
28 |
29 | /**
30 | * Dispatches the command
31 | *
32 | * @return int
33 | */
34 | public function dispatch(array $arguments = []): int
35 | {
36 | $this->executeHook('startup');
37 | $exitCode = (new CommandRunner())->run($arguments);
38 | $this->executeHook('shutdown');
39 |
40 | return $exitCode;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/Console/Command/Exception/MissingCommandException.php:
--------------------------------------------------------------------------------
1 | stream = fopen($stream, 'r');
33 | }
34 |
35 | /**
36 | * Reads from the stream
37 | *
38 | * @return string|null
39 | */
40 | public function read(): ?string
41 | {
42 | $data = fgets($this->stream);
43 |
44 | return $data ? trim($data) : null;
45 | }
46 |
47 | /**
48 | * Closes the stream
49 | *
50 | * @return void
51 | */
52 | public function close(): void
53 | {
54 | if (is_resource($this->stream)) {
55 | fclose($this->stream);
56 | }
57 | }
58 |
59 | public function __destruct()
60 | {
61 | $this->close();
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/Console/Exception/ConsoleException.php:
--------------------------------------------------------------------------------
1 | =7.3.0",
24 | "originphp/core": "^3.0",
25 | "originphp/inflector": "^2.0",
26 | "originphp/log": "^2.0"
27 | },
28 | "minimum-stability": "dev",
29 | "prefer-stable": true
30 | }
31 |
--------------------------------------------------------------------------------
/src/Core/.preloadignore:
--------------------------------------------------------------------------------
1 | bootstrap.php
--------------------------------------------------------------------------------
/src/Core/BaseObject.php:
--------------------------------------------------------------------------------
1 | executeHook('initialize', func_get_args());
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/Core/Exception/Exception.php:
--------------------------------------------------------------------------------
1 | template !== null) {
29 | if (! is_array($message)) {
30 | $message = [$message];
31 | }
32 | $message = vsprintf($this->template, $message);
33 | }
34 | if ($this->defaultErrorCode !== null) {
35 | $code = $this->defaultErrorCode;
36 | }
37 |
38 | parent::__construct($message, $code);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/Core/Exception/FileNotFoundException.php:
--------------------------------------------------------------------------------
1 | classUses() as $trait) {
40 | list($namespace, $className) = namespaceSplit($trait);
41 |
42 | $method = $className;
43 | if (strpos($className, 'Trait') !== false) {
44 | $method = substr($className, 0, -5);
45 | }
46 |
47 | $method = 'initialize' . $method;
48 | if (method_exists($this, $method)) {
49 | $this->$method(...$args);
50 | }
51 | }
52 | }
53 |
54 | /**
55 | * Gets the traits used by this class
56 | *
57 | * @return array
58 | */
59 | private function classUses(): array
60 | {
61 | $class = $this;
62 |
63 | $traits = [];
64 | while ($class) {
65 | $traits = array_merge(class_uses($class), $traits);
66 | $class = get_parent_class($class);
67 | }
68 |
69 | return array_unique($traits);
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/Core/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018-2021 Jamiel Sharief.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/src/Core/LazyLoadContainer.php:
--------------------------------------------------------------------------------
1 | config[$alias] = ['className' => $className,'config' => $config];
45 | }
46 |
47 | /**
48 | * Returns true if this container can return an item for the entry
49 | *
50 | * @param string $alias
51 | * @return boolean
52 | */
53 | public function has(string $alias): bool
54 | {
55 | return isset($this->config[$alias]);
56 | }
57 |
58 | /**
59 | * Returns a list of items in this container
60 | *
61 | * @return array
62 | */
63 | public function list(): array
64 | {
65 | return array_keys($this->config);
66 | }
67 |
68 | /**
69 | * Gets an item from this container
70 | *
71 | * @param string $alias
72 | * @return mixed Entry
73 | */
74 | public function get(string $alias)
75 | {
76 | if ($this->has($alias)) {
77 | if (empty($this->objects[$alias])) {
78 | $className = $this->config[$alias]['className'];
79 | $this->objects[$alias] = new $className(...$this->config[$alias]['config']);
80 | }
81 |
82 | return $this->objects[$alias];
83 | }
84 | throw new Exception(sprintf('%s was not found', $alias));
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/Core/ModelTrait.php:
--------------------------------------------------------------------------------
1 | $alias)) {
44 | return $this->$alias;
45 | }
46 |
47 | return $this->$alias = $this->modelRegistryGet($model, $options);
48 | }
49 |
50 | /**
51 | * Loads a model, uses from registry or creates a new one.
52 | *
53 | * @param string $model User, MyPlugin.User, User::class
54 | * @param array $options
55 | * @return \Origin\Model\Model
56 | */
57 | private function modelRegistryGet(string $model, array $options = []): Model
58 | {
59 | $object = ModelRegistry::get($model, $options);
60 | if (! $object) {
61 | throw new MissingModelException($model);
62 | }
63 |
64 | return $object;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/Core/PhpFile.php:
--------------------------------------------------------------------------------
1 | false, 'short' => false,'before' => null, 'after' => null];
57 | $out = $options['short'] ? $this->varExport($data) : var_export($data, true);
58 | $out = ' \n"],
74 | ['[', "],\n", ' => '],
75 | $data
76 | );
77 | $data = preg_replace('/=>\s\s+\[/i', '=> [', $data);
78 | $data = preg_replace("/=> \[\s\s+\]/m", '=> []', $data);
79 |
80 | return substr($data, 0, -1).']';
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/Core/Resolver.php:
--------------------------------------------------------------------------------
1 | register();
32 | } else {
33 | ( new Origin\Http\ErrorHandler())->register();
34 | }
35 |
36 | /**
37 | * As of version 2.6 .env.php is the cached version of .env. Prior
38 | * to this config was set manually .env.php
39 | */
40 | $configFile = ROOT . '/config/.env.php';
41 | if (file_exists($configFile)) {
42 | $result = include $configFile;
43 | foreach ($result as $key => $value) {
44 | $_ENV[$key] = $value;
45 | }
46 | } elseif (file_exists(ROOT . '/config/.env')) {
47 | $vars = (new DotEnv())->load(ROOT. '/config');
48 | $header = [
49 | '# .env (cached version) - Do not edit, delete instead',
50 | '# Automatically generated ' . now(),
51 | ];
52 | if (env('APP_DEBUG') === false) {
53 | (new PhpFile())->write($configFile, $vars, ['short' => true,'before' => implode("\n", $header)]);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/Core/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "originphp/core",
3 | "description": "OriginPHP Core",
4 | "type": "library",
5 | "keywords": [
6 | "originPHP",
7 | "core"
8 | ],
9 | "homepage": "https://www.originphp.com/",
10 | "license": "MIT",
11 | "authors": [
12 | {
13 | "name": "Jamiel Sharief",
14 | "email": "js@originphp.com"
15 | }
16 | ],
17 | "autoload": {
18 | "psr-4": {
19 | "Origin\\Core\\": "."
20 | },
21 | "files": [
22 | "functions.php"
23 | ]
24 | },
25 | "require": {
26 | "php": ">=7.3.0",
27 | "originphp/inflector": "^2.0"
28 | },
29 | "suggest": {
30 | "originphp/dotenv": "If this package is used part of the framework and you will use bootstrap.php"
31 | },
32 | "minimum-stability": "dev",
33 | "prefer-stable": true
34 | }
35 |
--------------------------------------------------------------------------------
/src/Http/Controller/Component/Component.php:
--------------------------------------------------------------------------------
1 | controller = $controller;
46 |
47 | $this->config($config);
48 | $this->executeHook('initialize', [$config]);
49 | }
50 |
51 | /**
52 | * Loads a component, the component is not returned, but when you call it will be
53 | * lazy loaded
54 | *
55 | * examples:
56 | *
57 | * Session
58 | * MyPlugin.Session
59 | *
60 | * @param string $name
61 | * @param array $config
62 | * @return void
63 | */
64 | public function loadComponent(string $name, array $config = [])
65 | {
66 | list($plugin, $component) = pluginSplit($name);
67 | if (! isset($this->components[$component])) {
68 | $this->components[$component] = array_merge(['className' => $name . 'Component','enable' => false], $config);
69 | }
70 | }
71 |
72 | /**
73 | * Lazy loading
74 | */
75 | public function __get($name)
76 | {
77 | if (isset($this->components[$name])) {
78 | $this->$name = $this->controller->componentRegistry()->load($name, $this->components[$name]);
79 |
80 | if (isset($this->$name)) {
81 | return $this->$name;
82 | }
83 | }
84 |
85 | return null;
86 | }
87 |
88 | /**
89 | * Returns the controller
90 | * @return \Origin\Http\Controller\Controller
91 | */
92 | public function controller(): Controller
93 | {
94 | return $this->controller;
95 | }
96 |
97 | /**
98 | * Returns the request object
99 | *
100 | * @return \Origin\Http\Request
101 | */
102 | public function request(): Request
103 | {
104 | return $this->controller->request();
105 | }
106 |
107 | /**
108 | * Returns the response object
109 | *
110 | * @return \Origin\Http\Response
111 | */
112 | public function response(): Response
113 | {
114 | return $this->controller->response();
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/src/Http/Controller/Component/CookieComponent.php:
--------------------------------------------------------------------------------
1 | Cookie->doSomething
26 | *
27 | * Or you can read of the request and write on the response.
28 | */
29 |
30 | class CookieComponent extends Component
31 | {
32 |
33 | /**
34 | * Reads a value of a cookie from request
35 | *
36 | * @param string $name
37 | * @return string|array|null
38 | */
39 | public function read(string $name)
40 | {
41 | return $this->request()->cookies($name);
42 | }
43 |
44 | /**
45 | * Writes a cookie through response
46 | *
47 | * $cookie->write('key',$value);
48 | * $cookie->write('key',$value,['expires'=>'+1 month');
49 | *
50 | * @param string $name cookie name
51 | * @param mixed $value
52 | * @param array $options The options keys are:
53 | * - expires: default:'+1 month'. a strtotime string e.g. +5 days, 2019-01-01 10:23:55
54 | * - encrypt: default:true. encrypt value
55 | * - path: default:'/' . Path on server
56 | * - domain: domains cookie will be available on
57 | * - secure: default:false. only send if through https
58 | * - httpOnly: default:false. only available to HTTP protocol not to javascript
59 | * - sameSite: default:none can be lax, strict or none (requires secure)
60 | * @return void
61 | */
62 | public function write(string $name, $value, array $options = []): void
63 | {
64 | $this->response()->cookie($name, $value, $options);
65 | }
66 |
67 | /**
68 | * Deletes a cookie
69 | *
70 | * @param string $name
71 | * @return void
72 | */
73 | public function delete(string $name): void
74 | {
75 | $this->response()->cookie($name, '', ['expires' => '-60 minutes']);
76 | }
77 |
78 | /**
79 | * Checks if a cookie exists
80 | *
81 | * @param string $name
82 | * @return bool
83 | */
84 | public function exists(string $name): bool
85 | {
86 | $cookies = $this->request()->cookies();
87 |
88 | return isset($cookies[$name]);
89 | }
90 |
91 | /**
92 | * Deletes all cookies
93 | *
94 | * @return void
95 | */
96 | public function destroy(): void
97 | {
98 | unset($_COOKIE);
99 | $_COOKIE = [];
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/src/Http/Controller/Component/Exception/MissingComponentException.php:
--------------------------------------------------------------------------------
1 | loadComponent('Session');
25 | }
26 |
27 | public function error(string $message): void
28 | {
29 | $this->addMessage('error', $message);
30 | }
31 |
32 | public function success(string $message): void
33 | {
34 | $this->addMessage('success', $message);
35 | }
36 |
37 | public function warning(string $message): void
38 | {
39 | $this->addMessage('warning', $message);
40 | }
41 |
42 | public function info(string $message): void
43 | {
44 | $this->addMessage('info', $message);
45 | }
46 |
47 | public function addMessage(string $type, string $message): void
48 | {
49 | $messages = [];
50 |
51 | if ($this->Session->exists('Flash')) {
52 | $messages = $this->Session->read('Flash');
53 | }
54 | $messages[] = [
55 | 'template' => $type,
56 | 'message' => $message
57 | ];
58 | $this->Session->write('Flash', $messages);
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/Http/Controller/Component/SessionComponent.php:
--------------------------------------------------------------------------------
1 | session)) {
41 | $this->session = $this->request()->session();
42 | }
43 |
44 | return $this->session;
45 | }
46 | /**
47 | * Reads a value of a session
48 | *
49 | * @param string $name
50 | * @return mixed
51 | */
52 | public function read(string $name)
53 | {
54 | return $this->session()->read($name);
55 | }
56 |
57 | /**
58 | * Writes a session
59 | *
60 | * $session->write('key',$value);
61 | * $session->write('key',$value,strtotime('+1 day'));
62 | *
63 | * @param string $name
64 | * @param mixed $value
65 | * @return void
66 | */
67 | public function write(string $name, $value): void
68 | {
69 | $this->session()->write($name, $value);
70 | }
71 |
72 | /**
73 | * Deletes a session
74 | *
75 | * @param string $name
76 | * @return void
77 | */
78 | public function delete(string $name): void
79 | {
80 | $this->session()->delete($name);
81 | }
82 |
83 | /**
84 | * Checks if a session exists
85 | *
86 | * @param string $name
87 | * @return bool
88 | */
89 | public function exists(string $name): bool
90 | {
91 | return $this->session()->exists($name);
92 | }
93 |
94 | /**
95 | * Clears the session
96 | *
97 | * @return void
98 | */
99 | public function clear(): void
100 | {
101 | $this->session()->clear();
102 | }
103 |
104 | /**
105 | * Deletes all sessions
106 | *
107 | * @return void
108 | */
109 | public function destroy(): void
110 | {
111 | $this->session()->destroy();
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/src/Http/Controller/Exception/MissingControllerException.php:
--------------------------------------------------------------------------------
1 | params('controller')) {
84 | $class = $this->getClass($request->params('controller'), $request->params('plugin'), $request->params('prefix'));
85 | if (! class_exists($class)) {
86 | throw new MissingControllerException($request->params('controller'));
87 | }
88 |
89 | $this->controller = new $class($request, $response);
90 |
91 | return $this->controller->dispatch($request->params('action'));
92 | }
93 | throw new RouterException('No route found.', 404);
94 | }
95 |
96 | /**
97 | * Gets the controller
98 | *
99 | * @return \Origin\Http\Controller\Controller
100 | */
101 | public function controller(): Controller
102 | {
103 | return $this->controller;
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/src/Http/Exception/BadRequestException.php:
--------------------------------------------------------------------------------
1 | LOGS . '/access.log'
35 | ];
36 |
37 | /**
38 | * This PROCESSES the response. Use this to make changes to the response.
39 | *
40 | * @param \Origin\Http\Request $request
41 | * @param \Origin\Http\Response $response
42 | * @return void
43 | */
44 | public function process(Request $request, Response $response): void
45 | {
46 | file_put_contents($this->config['file'], $this->commonFormat($request, $response) . "\n", FILE_APPEND);
47 | }
48 |
49 | /**
50 | * Creates an access log using the Apache Common LOG format
51 | * @see https://httpd.apache.org/docs/2.4/logs.html#accesslog.
52 | *
53 | * @param \Origin\Http\Request $request
54 | * @param \Origin\Http\Response $response
55 | * @return string
56 | */
57 | private function commonFormat(Request $request, Response $response): string
58 | {
59 | return sprintf(
60 | '%s %s [%s] "%s %s %s" %d %d',
61 | $request->ip(),
62 | $request->session()->read('Auth.User.id') ?: '-',
63 | date('d/M/Y:H:i:s O'),
64 | $request->method(),
65 | $request->server('REQUEST_URI'),
66 | $request->server('SERVER_PROTOCOL'),
67 | $response->statusCode(),
68 | mb_strlen($response->body() ?? '')
69 | );
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/Http/Middleware/DispatcherMiddleware.php:
--------------------------------------------------------------------------------
1 | dispatch($request, $response);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/Http/Middleware/Exception/InvalidCsrfTokenException.php:
--------------------------------------------------------------------------------
1 | ip();
58 | if (! $ipAddress) {
59 | throw new ForbiddenException('Invalid IP address');
60 | }
61 |
62 | if (file_exists(CONFIG . '/blacklist.php')) {
63 | $this->blacklist = (new PhpFile())->read(CONFIG . '/blacklist.php');
64 | }
65 |
66 | if (file_exists(CONFIG . '/whitelist.php')) {
67 | $this->whitelist = (new PhpFile())->read(CONFIG . '/whitelist.php');
68 | }
69 |
70 | $this->checkLists($ipAddress);
71 |
72 | // Free mem
73 | $this->blacklist = $this->whitelist = null;
74 | }
75 |
76 | /**
77 | * Checks an IP address against blacklist and whitelists
78 | *
79 | * @param string $ip
80 | * @return void
81 | */
82 | protected function checkLists(string $ip): void
83 | {
84 | if ($this->whitelist) {
85 | if (! in_array($ip, $this->whitelist)) {
86 | throw new ForbiddenException('IP address is not allowed');
87 | }
88 | } elseif (in_array($ip, $this->blacklist)) {
89 | throw new ForbiddenException('IP address is blacklisted');
90 | }
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/src/Http/Middleware/MaintenanceModeMiddleware.php:
--------------------------------------------------------------------------------
1 | false
24 | ];
25 |
26 | /**
27 | * This HANDLES the request. Use this to make changes to the request.
28 | *
29 | * @param \Origin\Http\Request $request
30 | * @return void
31 | */
32 | public function handle(Request $request): void
33 | {
34 | if ($this->maintenanceMode()) {
35 | $data = json_decode(file_get_contents(tmp_path('maintenance.json')), true);
36 |
37 | // Check IP to see if its in allowed list
38 | if ($data['allowed'] && in_array($request->ip(), $data['allowed'])) {
39 | return;
40 | }
41 | // Send headers
42 | $this->sendHeader('Maintenance-Started: ' . $data['time']);
43 | $this->sendHeader('Retry-After: ' . ($data['retry'] ? ($data['time'] + $data['retry']) : null));
44 |
45 | if ($this->config('html')) {
46 | $this->sendHeader('Location: /maintenance.html');
47 | $this->exit();
48 | } else {
49 | throw new MaintainenceModeException(
50 | $data['message']
51 | );
52 | }
53 | }
54 | }
55 |
56 | /**
57 | * Wrapped for testing
58 | *
59 | * @codeCoverageIgnore
60 | *
61 | * @return void
62 | */
63 | protected function exit(): void
64 | {
65 | exit();
66 | }
67 |
68 | /**
69 | * Checks if maintenance is enabled
70 | *
71 | * @return boolean
72 | */
73 | protected function maintenanceMode(): bool
74 | {
75 | return file_exists(tmp_path('maintenance.json'));
76 | }
77 |
78 | /**
79 | * Sends a header for the exception
80 | *
81 | * @codeCoverageIgnore
82 | *
83 | * @param string $header
84 | * @return void
85 | */
86 | protected function sendHeader(string $header): void
87 | {
88 | header($header);
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/Http/Middleware/Middleware.php:
--------------------------------------------------------------------------------
1 | config($config);
33 | $this->executeHook('initialize', [$config]);
34 | }
35 |
36 | /**
37 | * This HANDLES the request.
38 | *
39 | * @param \Origin\Http\Request $request
40 | * @return void
41 | */
42 | public function handle(Request $request): void
43 | {
44 | }
45 | /**
46 | * This PROCESSES the response after all middleware requests have
47 | * been handled
48 | *
49 | * @param \Origin\Http\Request $request
50 | * @param \Origin\Http\Response $response
51 | * @return void
52 | */
53 | public function process(Request $request, Response $response): void
54 | {
55 | }
56 |
57 | /**
58 | * This is the magic method.
59 | *
60 | * @param \Origin\Http\Request $request
61 | * @param \Origin\Http\Response $response
62 | * @param callable $next
63 | * @return \Origin\Http\Response $response
64 | */
65 | public function __invoke(Request $request, Response $response, callable $next = null): Response
66 | {
67 | $this->executeHook('startup');
68 | $this->handle($request);
69 | if ($next) {
70 | $response = $next($request, $response);
71 | }
72 | $this->process($request, $response);
73 | $this->executeHook('shutdown');
74 |
75 | return $response;
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/Http/Middleware/MiddlewareRunner.php:
--------------------------------------------------------------------------------
1 | middlewareStack[] = $object;
44 | }
45 |
46 | /**
47 | * Adds a Middleware to the start of the queue
48 | *
49 | * @param Middleware $object
50 | * @return void
51 | */
52 | public function prepend(Middleware $object): void
53 | {
54 | array_unshift($this->middlewareStack, $object);
55 | }
56 |
57 | /**
58 | * Returns a list of the middleware added to the runner
59 | * @return array
60 | */
61 | public function list(): array
62 | {
63 | $out = [];
64 | foreach ($this->middlewareStack as $object) {
65 | $out[] = get_class($object);
66 | }
67 |
68 | return $out;
69 | }
70 |
71 | /**
72 | * Runs the middleware
73 | *
74 | * @param \Origin\Http\Request $request
75 | * @param \Origin\Http\Response $response
76 | * @return \Origin\Http\Response $response
77 | */
78 | public function run(Request $request, Response $response): Response
79 | {
80 | return $this->__invoke($request, $response);
81 | }
82 | /**
83 | * Magic Method
84 | *
85 | * @param \Origin\Http\Request $request
86 | * @param \Origin\Http\Response $response
87 | * @return \Origin\Http\Response $response
88 | */
89 | public function __invoke(Request $request, Response $response): Response
90 | {
91 | if (isset($this->middlewareStack[$this->current])) {
92 | $next = $this->middlewareStack[$this->current];
93 | if ($next) {
94 | $this->current ++;
95 |
96 | return $next($request, $response, $this);
97 | }
98 | }
99 |
100 | return $response;
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/src/Http/Middleware/MinifyMiddleware.php:
--------------------------------------------------------------------------------
1 | true,
33 | /**
34 | * Minifies inline Javascript
35 | */
36 | 'minifyJs' => true,
37 | /**
38 | * Minifies inline Styles
39 | */
40 | 'minifyCss' => true
41 | ];
42 |
43 | /**
44 | * @param \Origin\Http\Request $request
45 | * @param \Origin\Http\Response $response
46 | * @return void
47 | */
48 | public function process(Request $request, Response $response): void
49 | {
50 | if ($response->contentType() === 'text/html' && $response->body()) {
51 | $this->minifyBody($response);
52 | }
53 | }
54 |
55 | /**
56 | * Handles the minfication
57 | *
58 | * @param \Origin\Http\Response $response
59 | * @return void
60 | */
61 | private function minifyBody(Response $response): void
62 | {
63 | $response->body(
64 | Html::minify($response->body(), $this->config())
65 | );
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/Http/Middleware/ProfilerMiddleware.php:
--------------------------------------------------------------------------------
1 | LOGS . '/profile.log'
37 | ];
38 |
39 | /**
40 | * @var int
41 | */
42 | private $startTime;
43 |
44 | /**
45 | * @var \Origin\Http\Request
46 | */
47 | private $request;
48 |
49 | protected function initialize(): void
50 | {
51 | $this->startTime = microtime(true);
52 | }
53 |
54 | /**
55 | * This PROCESSES the response. Use this to make changes to the response.
56 | *
57 | * @param \Origin\Http\Request $request
58 | * @param \Origin\Http\Response $response
59 | * @return void
60 | */
61 | public function process(Request $request, Response $response): void
62 | {
63 | $this->request = $request;
64 | }
65 |
66 | /**
67 | * Using destruct to make sure that logging happens after all middlewares run
68 | * and processed. Always check request object exists first.
69 | */
70 | public function __destruct()
71 | {
72 | if ($this->request) {
73 | $profile = $this->logRequest($this->request);
74 | file_put_contents($this->config['log'], $profile . "\n", FILE_APPEND);
75 | }
76 | }
77 |
78 | private function logRequest(Request $request): string
79 | {
80 | return sprintf(
81 | '[%s] %s %s %s %s',
82 | date('Y-m-d H:i:s'),
83 | $request->method(),
84 | $request->url(),
85 | number_format(microtime(true) - $this->startTime, 4) . 's',
86 | $this->humanReadable(memory_get_peak_usage())
87 | );
88 | }
89 |
90 | /**
91 | * Gets the human readable
92 | *
93 | * @param integer $bytes
94 | * @return string
95 | */
96 | private function humanReadable(int $bytes): string
97 | {
98 | $size = ['b', 'kb', 'mb', 'gb'];
99 | $factor = floor((strlen((string) $bytes) - 1) / 3);
100 |
101 | return sprintf('%.2f', $bytes / pow(1024, $factor)) . $size[$factor];
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/src/Http/Middleware/SessionMiddleware.php:
--------------------------------------------------------------------------------
1 | session = $request->session();
44 | $this->name = $this->session->name();
45 |
46 | // gets the id from the cookie
47 | $this->id = $this->getSessionId($request);
48 |
49 | $this->session->id($this->id);
50 | $this->session->start();
51 |
52 | /**
53 | * This removes the cookie header set by PHP session extension, so we can write our own cookie
54 | * if this becomes problematic or confusing due to PHP.ini settings, then remove. Call here
55 | */
56 | if (! headers_sent()) {
57 | header_remove('Set-Cookie');
58 | }
59 | }
60 |
61 | /**
62 | * @param \Origin\Http\Request $request
63 | * @param \Origin\Http\Response $response
64 | * @return void
65 | */
66 | public function process(Request $request, Response $response): void
67 | {
68 | if (! $request->cookies($this->name) || $this->id !== $this->session->id()) {
69 | $this->addCookieToResponse($request, $response);
70 | }
71 |
72 | $this->session->close();
73 | }
74 |
75 | private function getSessionId(Request $request): ?string
76 | {
77 | return $request->cookies($this->name);
78 | }
79 |
80 | /**
81 | * PHP Session has its own settings and will add cookie to the header, so anything set here will
82 | * be ingored in that case. To get it work use header_remove('Set-Cookie') but this means PHP_INI settings
83 | * will be ignored as well, so I have to think about this.
84 | *
85 | * TODO: think if should ignore PHP session settings from PHP.ini
86 | *
87 | * @param \Origin\Http\Request $request
88 | * @param \Origin\Http\Response $response
89 | * @return void
90 | */
91 | private function addCookieToResponse(Request $request, Response $response): void
92 | {
93 | $response->cookie($this->name, $this->session->id(), [
94 | 'expires' => 0, // Cookie expires after browser is closed
95 | 'encrypt' => false, // Encryption helps identify system
96 | 'secure' => $request->server('HTTPS') !== null,
97 | 'httpOnly' => true,
98 | 'sameSite' => 'strict' // TODO: test in different senarios
99 | ]);
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/src/Http/Session/SessionEngineInterface.php:
--------------------------------------------------------------------------------
1 | request()->cookies($name);
33 | }
34 |
35 | /**
36 | * Writes a cookie through response
37 | *
38 | * $cookie->write('key',$value);
39 | * $cookie->write('key',$value,['expires'=>'+1 month');
40 | *
41 | * @param string $name
42 | * @param mixed $value
43 | * @param array $options The options keys are:
44 | * - expires: default:'+1 month'. a strtotime string e.g. +5 days, 2019-01-01 10:23:55
45 | * - encrypt: default:true. encrypt value
46 | * - path: default:'/' . Path on server
47 | * - domain: domains cookie will be available on
48 | * - secure: default:false. only send if through https
49 | * - httpOnly: default:false. only available to HTTP protocol not to javascript
50 | * @return void
51 | */
52 | public function write(string $name, $value, array $options = []): void
53 | {
54 | $this->response()->cookie($name, $value, $options);
55 | }
56 |
57 | /**
58 | * Deletes a cookie
59 | *
60 | * @param string $name
61 | * @return void
62 | */
63 | public function delete(string $name): void
64 | {
65 | $this->response()->cookie($name, '', ['expires' => '-60 minutes']);
66 | }
67 |
68 | /**
69 | * Checks if a cookie exists
70 | *
71 | * @param string $name
72 | * @return bool
73 | */
74 | public function exists(string $name): bool
75 | {
76 | $cookies = $this->request()->cookies();
77 |
78 | return isset($cookies[$name]);
79 | }
80 |
81 | /**
82 | * Deletes all cookies
83 | *
84 | * @return void
85 | */
86 | public function destroy(): void
87 | {
88 | unset($_COOKIE);
89 | $_COOKIE = [];
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/Http/View/Helper/DateHelper.php:
--------------------------------------------------------------------------------
1 | $now) {
63 | $isFuture = true;
64 | $startTime = $now;
65 | $endTime = $time;
66 | }
67 |
68 | $difference = $endTime - $startTime;
69 |
70 | if ($difference < 1) {
71 | return 'just now';
72 | }
73 |
74 | $conditions = [
75 | 31104000 => 'year', // 12 * 30 * 24 * 60 * 60
76 | 2592000 => 'month', // 30 * 24 * 60 * 60
77 | 86400 => 'day', // 24 * 60 * 60
78 | 3600 => 'hour', // 60 * 60
79 | 60 => 'minute',
80 | 1 => 'second',
81 | ];
82 |
83 | $result = null;
84 | foreach ($conditions as $seconds => $type) {
85 | $result = $difference / $seconds;
86 | if ($result >= 1) {
87 | $final = round($result);
88 | if ($final > 1) {
89 | $type .= 's'; // inflect
90 | }
91 | $result = "{$final} {$type}" . ($isFuture === false ? ' ago' : '');
92 | break;
93 | }
94 | }
95 |
96 | return $result;
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/src/Http/View/Helper/FlashHelper.php:
--------------------------------------------------------------------------------
1 | [
28 | 'error' => '
%s
',
29 | 'success' => '%s
',
30 | 'warning' => '%s
',
31 | 'info' => '%s
',
32 | ],
33 | ];
34 |
35 | public function initialize(array $config): void
36 | {
37 | $this->loadHelper('Session');
38 | }
39 |
40 | public function messages()
41 | {
42 | if (! $this->Session->exists('Flash')) {
43 | return null;
44 | }
45 | $output = '';
46 |
47 | foreach ($this->Session->read('Flash') as $message) {
48 | $template = $message['template'];
49 | $message = $message['message'];
50 | if (isset($this->config['templates'][$template])) {
51 | $output .= sprintf($this->config['templates'][$template], $message);
52 | }
53 | }
54 | $this->Session->delete('Flash');
55 |
56 | return $output;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/Http/View/Helper/HelperRegistry.php:
--------------------------------------------------------------------------------
1 | view = $view;
39 | }
40 |
41 | /**
42 | * Resolves the class name of a helper
43 | *
44 | * @param string $class
45 | * @return string|null $namespacedClass
46 | */
47 | protected function className(string $class): ?string
48 | {
49 | return Resolver::className($class, 'View/Helper', null, 'Http');
50 | }
51 |
52 | /**
53 | * Creates the object
54 | *
55 | * @param string $class
56 | * @param array $options
57 | * @return \Origin\Http\View\Helper\Helper
58 | */
59 | protected function createObject(string $class, array $options = []): Helper
60 | {
61 | return new $class($this->view, $options);
62 | }
63 |
64 | /**
65 | * Throws an exception
66 | *
67 | * @param string $object
68 | * @return void
69 | */
70 | protected function throwException(string $object): void
71 | {
72 | throw new MissingHelperException($object);
73 | }
74 |
75 | /**
76 | * Returns a view object
77 | *
78 | * @return View
79 | */
80 | public function view(): View
81 | {
82 | return $this->view;
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/Http/View/Helper/NumberHelper.php:
--------------------------------------------------------------------------------
1 | currency(1024,'USD'); // $1,024
25 | * $number->currency(1024.00,'USD'); // $1,024.00
26 | *
27 | * @param string|float|integer $value 1234567.43
28 | * @param string $currency USD|EUR|GBP|AUD etc.
29 | * @param array $options additional options
30 | * @return string
31 | */
32 | public function currency($value, string $currency = null, array $options = []): string
33 | {
34 | return Number::currency($value, $currency, $options);
35 | }
36 |
37 | /**
38 | * Formats a percent number
39 | *
40 | * $number->percent(50.55); // 50.55%
41 | *
42 | * @param string|int|float $value 1234567.43
43 | * @param integer $precision
44 | * @param array $options additional options
45 | * @return string
46 | */
47 | public function percent($value, int $precision = 2, array $options = []): string
48 | {
49 | return Number::percent($value, $precision, $options);
50 | }
51 |
52 | /**
53 | * Formats a number with a specified level of precision
54 | *
55 | * $number->precision(1024.10101010,4); // 1,024.1010
56 | *
57 | * @param string|int|float $value 1234567.43
58 | * @param int $precision max number of decimal places to show
59 | * @param array $options additional options
60 | * @return string
61 | */
62 | public function precision($value, int $precision = 2, array $options = []): string
63 | {
64 | return Number::precision($value, $precision, $options);
65 | }
66 | /**
67 | * Formats a number
68 | *
69 | * $number->format(1024.512); // 1,024.51
70 | *
71 | * @param string|int|float $value
72 | * @param array $options
73 | * - before: something to be shown before
74 | * - after: something to be added after
75 | * - thousands: the thousands seperator
76 | * - decimals: the decimals seperator
77 | * - places: how many decimal points to show
78 | * - negative: default:()
79 | * @return string
80 | */
81 | public function format($value, array $options = []): string
82 | {
83 | return Number::format($value, $options);
84 | }
85 |
86 | /**
87 | * Formats bytes to human readable size
88 | *
89 | * @param integer $bytes
90 | * @param array $options
91 | * - precision: default:2 the level of precision
92 | * @return string
93 | */
94 | public function readableSize(int $bytes, array $options = []): string
95 | {
96 | return Number::readableSize($bytes, $options);
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/src/Http/View/Helper/SessionHelper.php:
--------------------------------------------------------------------------------
1 | request()->session();
40 | }
41 |
42 | /**
43 | * Reads a value from the session
44 | *
45 | * @param string $name
46 | * @return mixed
47 | */
48 | public function read(string $name)
49 | {
50 | return $this->session()->read($name);
51 | }
52 |
53 | /**
54 | * Writes a session
55 | *
56 | * $session->write('key',$value);
57 | * $session->write('key',$value,strtotime('+1 day'));
58 | *
59 | * @param string $name
60 | * @param mixed $value
61 | * @return void
62 | */
63 | public function write(string $name, $value): void
64 | {
65 | $this->session()->write($name, $value);
66 | }
67 |
68 | /**
69 | * Deletes a session
70 | *
71 | * @param string $name
72 | * @return void
73 | */
74 | public function delete(string $name): void
75 | {
76 | $this->session()->delete($name);
77 | }
78 |
79 | /**
80 | * Checks if an item exists in session
81 | *
82 | * @param string $name
83 | * @return bool
84 | */
85 | public function exists(string $name): bool
86 | {
87 | return $this->session()->exists($name);
88 | }
89 |
90 | /**
91 | * Clears the session
92 | *
93 | * @return void
94 | */
95 | public function clear(): void
96 | {
97 | $this->session()->clear();
98 | }
99 |
100 | /**
101 | * Deletes all sessions
102 | *
103 | * @return void
104 | */
105 | public function destroy(): void
106 | {
107 | $this->session()->destroy();
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/src/Http/View/JsonView.php:
--------------------------------------------------------------------------------
1 | request = $controller->request();
51 | $this->response = $controller->response();
52 | $this->viewVars = $controller->viewVars();
53 | $this->serialize = $controller->serialize();
54 | }
55 |
56 | /**
57 | * Does the rendering
58 | *
59 | * @param mixed $data
60 | * @return string
61 | */
62 | public function render($data = null): string
63 | {
64 | /**
65 | * If user requests JSON and serialize is set then use that
66 | */
67 | if ($data === null && $this->request->respondAs() === 'json' && ! empty($this->serialize)) {
68 | $data = $this->serialize($this->serialize);
69 | }
70 |
71 | if (is_object($data) && method_exists($data, 'toJson')) {
72 | return $data->toJson();
73 | }
74 |
75 | return json_encode($data);
76 | }
77 |
78 | /**
79 | * Serializes the data
80 | *
81 | * @param string|array $serialize
82 | * @return array
83 | */
84 | private function serialize($serialize): array
85 | {
86 | $result = [];
87 |
88 | if (is_string($serialize)) {
89 | if (isset($this->viewVars[$serialize])) {
90 | $result = $this->toArray($this->viewVars[$serialize]);
91 | }
92 |
93 | return $result;
94 | }
95 |
96 | foreach ($serialize as $key) {
97 | if (isset($this->viewVars[$key])) {
98 | $result[$key] = $this->toArray($this->viewVars[$key]);
99 | }
100 | }
101 |
102 | return $result;
103 | }
104 |
105 | /**
106 | * Converts an object to an array
107 | *
108 | * @param mixed $mixed
109 | * @return mixed
110 | */
111 | private function toArray($mixed)
112 | {
113 | if (is_object($mixed) && method_exists($mixed, 'toArray')) {
114 | $mixed = $mixed->toArray();
115 | }
116 |
117 | return $mixed;
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/src/Http/View/TemplateTrait.php:
--------------------------------------------------------------------------------
1 | templates();
36 | * $this->templates(['input'=>'']);
37 | *
38 | * @param array|null $templates
39 | * @return string|array
40 | */
41 | public function templates($templates = null)
42 | {
43 | if (! is_array($templates)) {
44 | return $this->templater()->get($templates);
45 | }
46 | $this->templater()->set($templates);
47 |
48 | return $templates;
49 | }
50 |
51 | /**
52 | * Gets the templater object if it exists, or it will create one
53 | * if the templates key is a string, then it will fetch the default templates since they
54 | * were overwritten and load templates from file
55 | *
56 | * @return \Origin\Http\View\Templater
57 | */
58 | private function templater(): Templater
59 | {
60 | if (! isset($this->templater)) {
61 | $this->templater = new Templater();
62 | $templates = $this->config('templates');
63 | if (is_array($templates)) {
64 | $this->templater->set($templates);
65 | } else {
66 | $this->templater->set($this->defaultConfig['templates']);
67 | $this->templater->load($templates);
68 | }
69 | }
70 |
71 | return $this->templater;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/Http/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "originphp/http",
3 | "description": "OriginPHP Http Package, provides the Controller and View functionality.",
4 | "type": "library",
5 | "keywords": [],
6 | "homepage": "https://www.originphp.com/",
7 | "license": "MIT",
8 | "authors": [
9 | {
10 | "name": "Jamiel Sharief",
11 | "email": "js@originphp.com"
12 | }
13 | ],
14 | "autoload": {
15 | "psr-4": {
16 | "Origin\\Http\\": "."
17 | }
18 | },
19 | "require": {
20 | "php": ">=7.3.0",
21 | "originphp/cache": "^2.0",
22 | "originphp/configurable": "^2.0",
23 | "originphp/core": "^3.0",
24 | "originphp/defer": "^3.0",
25 | "originphp/i18n": "^3.0",
26 | "originphp/inflector": "^2.0",
27 | "originphp/log": "^2.0",
28 | "originphp/model": "^3.0",
29 | "originphp/security": "^2.0",
30 | "originphp/utility": "^3.0",
31 | "originphp/xml": "^2.0",
32 | "originphp/redis": "^3.0"
33 | },
34 | "suggest": {
35 | "originphp/model": "To use the Auth component"
36 | },
37 | "minimum-stability": "dev",
38 | "prefer-stable": true
39 | }
40 |
--------------------------------------------------------------------------------
/src/I18n/Exception/LocaleNotAvailableException.php:
--------------------------------------------------------------------------------
1 | =7.3.0",
27 | "originphp/core": "^3.0",
28 | "originphp/utility": "^3.0"
29 | },
30 | "minimum-stability": "dev",
31 | "prefer-stable": true
32 | }
33 |
--------------------------------------------------------------------------------
/src/I18n/functions.php:
--------------------------------------------------------------------------------
1 | $user->id,'name'=>$user->name]);
22 | * @param string $string
23 | * @param array $vars array of vars e.g ['id'=>$user->id,'name'=>$user->name]
24 | * @return string|null formatted
25 | */
26 | function __(string $string = null, array $vars = []): ?string
27 | {
28 | if ($string) {
29 | return I18n::translate($string, $vars);
30 | }
31 |
32 | return null;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/Job/Engine/BaseEngine.php:
--------------------------------------------------------------------------------
1 | config($config);
33 | $this->initialize($config);
34 | }
35 |
36 | public function initialize(array $config): void
37 | {
38 | }
39 | /**
40 | * Add a job to the queue
41 | *
42 | * @param \Origin\Job\Job $job
43 | * @param string $strtotime
44 | * @return bool
45 | */
46 | abstract public function add(Job $job, string $strtotime = 'now'): bool;
47 |
48 | /**
49 | * Get the next job from the queue
50 | *
51 | * @param string $queue
52 | * @return \Origin\Job\Job|null
53 | */
54 | abstract public function fetch(string $queue = 'default'): ?Job;
55 |
56 | /**
57 | * Deletes a job
58 | *
59 | * @param \Origin\Job\Job $job
60 | * @return bool
61 | */
62 | abstract public function delete(Job $job): bool;
63 |
64 | /**
65 | * Handles a failed job
66 | *
67 | * @param \Origin\Job\Job $job
68 | * @return bool
69 | */
70 | abstract public function fail(Job $job): bool;
71 |
72 | /**
73 | * Handles a successful job
74 | *
75 | * @param \Origin\Job\Job $job
76 | * @return bool
77 | */
78 | abstract public function success(Job $job): bool;
79 |
80 | /**
81 | * Retries a job
82 | *
83 | * @param \Origin\Job\Job $job
84 | * @param integer $tries
85 | * @param string $strtotime
86 | * @return bool
87 | */
88 | abstract public function retry(Job $job, int $tries, $strtotime = 'now'): bool;
89 |
90 | /**
91 | * Serializes a job
92 | *
93 | * @return string
94 | */
95 | public function serialize(Job $job): string
96 | {
97 | $serialized = json_encode($job->serialize());
98 |
99 | if (json_last_error() !== JSON_ERROR_NONE) {
100 | throw new Exception('JSON encoding data Error: ' . json_last_error());
101 | }
102 |
103 | return $serialized;
104 | }
105 |
106 | /**
107 | * Returns a new job instance using serialized data
108 | *
109 | * @param string $data
110 | * @return \Origin\Job\Job
111 | */
112 | public function deserialize(string $data): Job
113 | {
114 | $unserialized = json_decode($data, true);
115 |
116 | if (json_last_error() !== JSON_ERROR_NONE) {
117 | throw new Exception('JSON decoding data Error: ' . json_last_error());
118 | }
119 |
120 | $className = $unserialized['className'];
121 | $job = new $className();
122 | $job->deserialize($unserialized);
123 |
124 | return $job;
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/src/Job/Engine/RedisConnection.php:
--------------------------------------------------------------------------------
1 | > /etc/php/7.2/cli/php.ini
27 | */
28 |
29 | use Redis;
30 | use RedisException;
31 | use Origin\Core\Exception\Exception;
32 |
33 | class RedisConnection
34 | {
35 | /**
36 | * Connects to Redis
37 | *
38 | * @param array $config
39 | * @return Redis
40 | */
41 | public static function connect(array $config): Redis
42 | {
43 | deprecationWarning('RedisConnection has been deprecated used Redis::connect instead');
44 | $config += [
45 | 'host' => '127.0.0.1','port' => 6379,'password' => null,'timeout' => 0,'persistent' => true, // Faster!!!
46 | 'path' => null];
47 |
48 | if (! extension_loaded('redis')) {
49 | throw new Exception('Redis extension not loaded.');
50 | }
51 | $redis = new Redis();
52 | $result = false;
53 | try {
54 | if (! empty($config['path'])) {
55 | $result = $redis->connect($config['path']);
56 | } elseif (! empty($config['persistent'])) {
57 | $id = ($config['persistent'] === true)?'origin-php':(string)$config['persistent'];
58 | $result = $redis->pconnect($config['host'], $config['port'], $config['timeout'], $id);
59 | } else {
60 | $result = $redis->connect($config['host'], $config['port'], $config['timeout']);
61 | }
62 | if ($result && isset($config['password'])) {
63 | $result = $redis->auth($config['password']);
64 | }
65 | } catch (RedisException $e) {
66 | $result = false;
67 | }
68 |
69 | if (! $result) {
70 | throw new Exception('Error connecting to Redis server.');
71 | }
72 |
73 | return $redis;
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/Job/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018-2021 Jamiel Sharief.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/src/Job/Model/Queue.php:
--------------------------------------------------------------------------------
1 | =7.3.0",
26 | "originphp/configurable": "^2.0",
27 | "originphp/core": "^3.0",
28 | "originphp/log": "^2.0",
29 | "originphp/model": "^3.0",
30 | "originphp/redis": "^3.0",
31 | "originphp/security": "^2.0"
32 | },
33 | "minimum-stability": "dev",
34 | "prefer-stable": true
35 | }
36 |
--------------------------------------------------------------------------------
/src/Lock/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018-2021 Jamiel Sharief.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/src/Lock/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "originphp/lock",
3 | "description": "OriginPHP Lock",
4 | "type": "library",
5 | "keywords": [
6 | "lock"
7 | ],
8 | "homepage": "https://www.originphp.com/",
9 | "license": "MIT",
10 | "authors": [
11 | {
12 | "name": "Jamiel Sharief",
13 | "email": "js@originphp.com"
14 | }
15 | ],
16 | "autoload": {
17 | "psr-4": {
18 | "Origin\\Lock\\": "."
19 | }
20 | },
21 | "require": {
22 | "php": ">=7.3.0",
23 | "originphp/defer": "^3.0"
24 | },
25 | "minimum-stability": "dev",
26 | "prefer-stable": true
27 | }
28 |
--------------------------------------------------------------------------------
/src/Mailbox/.preloadignore:
--------------------------------------------------------------------------------
1 | pipe.php
--------------------------------------------------------------------------------
/src/Mailbox/Job/MailboxCleanJob.php:
--------------------------------------------------------------------------------
1 | loadModel('InboundEmail', ['className' => InboundEmail::class]);
37 | }
38 |
39 | protected function execute(Entity $message): void
40 | {
41 | $this->InboundEmail->delete($message);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/Mailbox/Job/MailboxJob.php:
--------------------------------------------------------------------------------
1 | loadModel('InboundEmail', ['className' => InboundEmail::class]);
39 | }
40 |
41 | protected function execute(Entity $inboundEmail): void
42 | {
43 | $mail = new Mail($inboundEmail->message);
44 | $mailbox = Mailbox::mailbox($mail->recipients());
45 |
46 | if ($mailbox) {
47 | (new $mailbox($inboundEmail))->dispatch();
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/Mailbox/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018-2021 Jamiel Sharief.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/src/Mailbox/Model/ImapMessage.php:
--------------------------------------------------------------------------------
1 | validate('account', 'notBlank');
34 | $this->validate('message_id', 'notBlank');
35 | }
36 |
37 | public function findByAccount(string $account)
38 | {
39 | return $this->select(['id','message_id'])
40 | ->where(['account' => $account])
41 | ->first();
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/Mailbox/Model/InboundEmail.php:
--------------------------------------------------------------------------------
1 | validate('message_id', 'notBlank');
36 | $this->validate('message', 'notBlank');
37 |
38 | # Register callbacks
39 | $this->afterCreate('scheduleJobs');
40 | }
41 |
42 | /**
43 | * Make sure the message has not already been saved
44 | *
45 | * @param \Origin\Model\Entity $inboundEmail
46 | * @return boolean
47 | */
48 | public function existsInDb(Entity $inboundEmail): bool
49 | {
50 | return ! $this->isUnique($inboundEmail, ['message_id','checksum']);
51 | }
52 |
53 | /**
54 | * This is a model callback
55 | *
56 | * @param \Origin\Model\Entity $inboundEmail
57 | * @param ArrayObject $options
58 | * @return void
59 | */
60 | protected function scheduleJobs(Entity $inboundEmail, ArrayObject $options): void
61 | {
62 | # Dispatch for Processing
63 | (new MailboxJob())->dispatch($inboundEmail);
64 |
65 | # Schedule the mailbox cleaner
66 |
67 | (new MailboxCleanJob())->schedule(Config::read('App.mailboxKeepEmails'))->dispatch();
68 | }
69 |
70 | /**
71 | * Creates a new entity from a message
72 | *
73 | * @param string $message
74 | * @return \Origin\Model\Entity
75 | */
76 | public function fromMessage(string $message): Entity
77 | {
78 | $mail = new Mail($message);
79 |
80 | return $this->new([
81 | 'message_id' => $mail->messageId,
82 | 'checksum' => Security::hash($message, ['type' => 'sha1']),
83 | 'message' => $message,
84 | 'status' => 'pending'
85 | ]);
86 | }
87 |
88 | /**
89 | * Sets the status of an inbound email
90 | *
91 | * @param integer $id
92 | * @param string $status The following statuses :
93 | * - pending: this is newly added
94 | * - processing: this is currently being run in a job and processed
95 | * - delivered: everything went okay
96 | * - bounced: this message was bounced
97 | * - failed: an error occured when processing
98 | * @return boolean
99 | */
100 | public function setStatus(int $id, string $status): bool
101 | {
102 | return $this->updateColumn($id, 'status', $status);
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/src/Mailbox/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "originphp/mailbox",
3 | "description": "OriginPHP Mailbox",
4 | "type": "library",
5 | "keywords": [
6 | "mailbox",
7 | "imap",
8 | "pop3"
9 | ],
10 | "homepage": "https://www.originphp.com/",
11 | "license": "MIT",
12 | "authors": [
13 | {
14 | "name": "Jamiel Sharief",
15 | "email": "js@originphp.com"
16 | }
17 | ],
18 | "autoload": {
19 | "psr-4": {
20 | "Origin\\Mailbox\\": "."
21 | }
22 | },
23 | "require": {
24 | "php": ">=7.3.0",
25 | "originphp/configurable": "^2.0",
26 | "originphp/core": "^3.0",
27 | "originphp/job": "^3.0",
28 | "originphp/log": "^2.0",
29 | "originphp/model": "^3.0",
30 | "originphp/security": "^2.0",
31 | "originphp/service-object": "^3.0"
32 | },
33 | "minimum-stability": "dev",
34 | "prefer-stable": true
35 | }
36 |
--------------------------------------------------------------------------------
/src/Mailbox/pipe.php:
--------------------------------------------------------------------------------
1 | #!/usr/bin/php -q
2 | dispatch();
31 |
--------------------------------------------------------------------------------
/src/Mailer/Exception/MissingTemplateException.php:
--------------------------------------------------------------------------------
1 | onError('errorHandler');
26 | }
27 |
28 | /**
29 | * Executes the MailerJob, the first param is class or object and then after that are arguments
30 | *
31 | * @return void
32 | */
33 | public function execute(): void
34 | {
35 | $arguments = func_get_args();
36 |
37 | /**
38 | * Temporary backwards comptability to prevent queued jobs from breaking
39 | * @deprecated this will be depcreated
40 | */
41 | if (isset($arguments[0]) && is_array($arguments[0])) {
42 | $mailer = $arguments['mailer'];
43 | $arguments = $arguments['arguments'];
44 | } else {
45 | $mailer = array_shift($arguments);
46 | if (! is_object($mailer)) {
47 | $mailer = new $mailer();
48 | }
49 | }
50 |
51 | $mailer->dispatch(...$arguments);
52 | }
53 |
54 | public function errorHandler(\Exception $exception): void
55 | {
56 | $this->retry(['wait' => '+30 minutes','limit' => 3]);
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/Mailer/Message.php:
--------------------------------------------------------------------------------
1 | header = $header;
25 | $this->body = $body;
26 | }
27 |
28 | /**
29 | * Gets the message header
30 | *
31 | * @return string
32 | */
33 | public function header(): string
34 | {
35 | return $this->header;
36 | }
37 |
38 | /**
39 | * Gets the message body
40 | *
41 | * @return string
42 | */
43 | public function body(): string
44 | {
45 | return $this->body;
46 | }
47 |
48 | /**
49 | * Returns the full message (header and body)
50 | *
51 | * @return string
52 | */
53 | public function message(): string
54 | {
55 | return $this->header . "\r\n\r\n" . $this->body;
56 | }
57 |
58 | public function __toString()
59 | {
60 | return $this->message();
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/Mailer/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "originphp/mailer",
3 | "description": "OriginPHP Mailer",
4 | "type": "library",
5 | "keywords": [
6 | "mailer",
7 | "smtp",
8 | "email"
9 | ],
10 | "homepage": "https://www.originphp.com/",
11 | "license": "MIT",
12 | "authors": [
13 | {
14 | "name": "Jamiel Sharief",
15 | "email": "js@originphp.com"
16 | }
17 | ],
18 | "autoload": {
19 | "psr-4": {
20 | "Origin\\Mailer\\": "."
21 | }
22 | },
23 | "require": {
24 | "php": ">=7.3.0",
25 | "originphp/core": "^3.0",
26 | "originphp/email": "^2.0",
27 | "originphp/html": "^2.0",
28 | "originphp/inflector": "^2.0",
29 | "originphp/job": "^3.0"
30 | },
31 | "minimum-stability": "dev",
32 | "prefer-stable": true
33 | }
34 |
--------------------------------------------------------------------------------
/src/Migration/Exception/IrreversibleMigrationException.php:
--------------------------------------------------------------------------------
1 | statements = array_filter((array) $mixed);
29 | }
30 |
31 | /**
32 | * Gets the statements for this
33 | *
34 | * @return array
35 | */
36 | public function statements(): array
37 | {
38 | return $this->statements;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/Migration/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "originphp/migration",
3 | "description": "OriginPHP Migration",
4 | "type": "library",
5 | "keywords": [
6 | "migration"
7 | ],
8 | "homepage": "https://www.originphp.com/",
9 | "license": "MIT",
10 | "authors": [
11 | {
12 | "name": "Jamiel Sharief",
13 | "email": "js@originphp.com"
14 | }
15 | ],
16 | "autoload": {
17 | "psr-4": {
18 | "Origin\\Migration\\": "."
19 | }
20 | },
21 | "require": {
22 | "php": ">=7.3.0",
23 | "originphp/core": "^3.0",
24 | "originphp/inflector": "^2.0",
25 | "originphp/model": "^3.0"
26 | },
27 | "minimum-stability": "dev",
28 | "prefer-stable": true
29 | }
30 |
--------------------------------------------------------------------------------
/src/Model/Concern/Delocalizable.php:
--------------------------------------------------------------------------------
1 | beforeValidate('delocalize');
31 | }
32 |
33 | /**
34 | * Delocalize the values in the entity
35 | * This is a beforeValidate callback, so it must return true;
36 | *
37 | * @param \Origin\Model\Entity $entity
38 | * @return bool
39 | */
40 | public function delocalize(Entity $entity): bool
41 | {
42 | $columns = $this->schema()['columns'];
43 | foreach ($entity->dirty() as $field) {
44 | $value = $entity->get($field);
45 | if ($value && isset($columns[$field])) {
46 | $value = $this->processField($columns[$field]['type'], $value);
47 |
48 | // Restore value incase of invalid value etc
49 | if ($value === null) {
50 | $value = $entity->get($field);
51 | }
52 | $entity->set($field, $value);
53 | }
54 | }
55 |
56 | return true;
57 | }
58 |
59 | /**
60 | * Parses values
61 | *
62 | * @param string $type
63 | * @param string $value
64 | * @return mixed
65 | */
66 | private function processField(string $type, $value)
67 | {
68 | if ($type === 'date') {
69 | return Date::parseDate($value);
70 | }
71 | if ($type === 'datetime') {
72 | return Date::parseDateTime($value);
73 | }
74 | if ($type === 'time') {
75 | $value = Date::parseTime($value);
76 | }
77 | if (in_array($type, ['decimal','integer','float','bigint'])) {
78 | return Number::parse($value);
79 | }
80 |
81 | return $value;
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/Model/Concern/Timestampable.php:
--------------------------------------------------------------------------------
1 | timestampConfig([
27 | * 'created' => 'created_at',
28 | * 'modified' => 'modified_at'
29 | * ]);
30 | */
31 | trait Timestampable
32 | {
33 | /**
34 | * @var string
35 | */
36 | private $timestamp;
37 |
38 | /**
39 | * @var string
40 | */
41 | private $createdField;
42 |
43 | /**
44 | * @var string
45 | */
46 | private $modifiedField;
47 |
48 | public function initializeTimestampable()
49 | {
50 | if (! isset($this->createdField)) {
51 | $this->createdField = 'created';
52 | }
53 | if (! isset($this->modifiedField)) {
54 | $this->modifiedField = 'modified';
55 | }
56 | $this->timestamp = date('Y-m-d H:i:s');
57 | $this->beforeCreate('timestambleBeforeCreate');
58 | $this->beforeSave('timestambleBeforeSave');
59 | }
60 |
61 | /**
62 | * Before create callback
63 | *
64 | * @param \Origin\Model\Entity $entity
65 | * @param ArrayObject $options
66 | * @return void
67 | */
68 | protected function timestambleBeforeCreate(Entity $entity, ArrayObject $options): void
69 | {
70 | $this->setTimestamp($entity, $this->createdField);
71 | }
72 |
73 | /**
74 | * Before save callback
75 | *
76 | * @param \Origin\Model\Entity $entity
77 | * @param ArrayObject $options
78 | * @return void
79 | */
80 | protected function timestambleBeforeSave(Entity $entity, ArrayObject $options): void
81 | {
82 | $this->setTimestamp($entity, $this->modifiedField);
83 | }
84 |
85 | /**
86 | * Sets the timestamp
87 | *
88 | * @param \Origin\Model\Entity $entity
89 | * @param string $field
90 | * @return void
91 | */
92 | private function setTimestamp(Entity $entity, string $field): void
93 | {
94 | if (! $this->hasField($field)) {
95 | return;
96 | }
97 | if (empty($entity->$field) || ! in_array($field, $entity->dirty())) {
98 | $entity->set($field, $this->timestamp);
99 | }
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/src/Model/Engine/MysqlEngine.php:
--------------------------------------------------------------------------------
1 | execute('SHOW TABLES;');
55 | $results = $this->fetchAll();
56 | if ($results) {
57 | foreach ($results as $value) {
58 | $tables[] = current($value);
59 | }
60 | }
61 |
62 | return $tables;
63 | }
64 |
65 | /**
66 | * Gets a list of tables
67 | *
68 | * @return array
69 | */
70 | public function databases(): array
71 | {
72 | $out = [];
73 | $this->execute('SHOW DATABASES;');
74 | $results = $this->fetchAll();
75 | if ($results) {
76 | foreach ($results as $value) {
77 | $out[] = current($value);
78 | }
79 | }
80 |
81 | return $out;
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/Model/Engine/PostgresEngine.php:
--------------------------------------------------------------------------------
1 | execute($sql)) {
60 | $list = $this->fetchList();
61 | if ($list) {
62 | $out = $list;
63 | }
64 | sort($out); // why sort with db server
65 | }
66 |
67 | return $out;
68 | }
69 |
70 | /**
71 | * Returns a list of databases
72 | *
73 | * @return array
74 | */
75 | public function databases(): array
76 | {
77 | $sql = 'SELECT datname FROM pg_database WHERE datistemplate = false;';
78 | $out = [];
79 | if ($this->execute($sql)) {
80 | $list = $this->fetchList();
81 | if ($list) {
82 | $out = $list;
83 | }
84 | }
85 |
86 | return $out;
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/src/Model/Engine/SqliteEngine.php:
--------------------------------------------------------------------------------
1 | execute('SELECT name from sqlite_master WHERE type = "table"');
57 | $results = $this->fetchList();
58 | if ($results) {
59 | sort($results);
60 | $key = array_search('sqlite_sequence', $results);
61 | unset($results[$key]);
62 | $results = array_values($results);
63 | }
64 |
65 | return $results ?? $tables;
66 | }
67 |
68 | /**
69 | * Gets a list of databases
70 | *
71 | * @return array
72 | */
73 | public function databases(): array
74 | {
75 | return [];
76 | }
77 |
78 | /**
79 | * Creates and handles a DB transaction with the option to disable foreign key constraints.
80 | *
81 | * @example
82 | *
83 | * $connection->transaction(function ($connection) use ($statements) {
84 | * $this->processStatements($connection,$statements);
85 | * });
86 | *
87 | * @param callable $callback
88 | * @param boolean $disbleForeignKeyConstraints
89 | * @return mixed
90 | */
91 | public function transaction(callable $callback, bool $disbleForeignKeyConstraints = false)
92 | {
93 | if ($disbleForeignKeyConstraints) {
94 | $this->disableForeignKeyConstraints();
95 | }
96 |
97 | $this->begin();
98 |
99 | try {
100 | $result = $callback($this);
101 | } catch (Exception $exception) {
102 | $this->rollback();
103 | if ($disbleForeignKeyConstraints) {
104 | $this->enableForeignKeyConstraints();
105 | }
106 |
107 | throw $exception;
108 | }
109 |
110 | if ($result === false) {
111 | $this->rollback();
112 | } else {
113 | $this->commit();
114 | }
115 |
116 | if ($disbleForeignKeyConstraints) {
117 | $this->enableForeignKeyConstraints();
118 | }
119 |
120 | return $result;
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/src/Model/Exception/ConnectionException.php:
--------------------------------------------------------------------------------
1 | entity = $entity;
30 |
31 | $message = $this->formatMessage($entity, $message);
32 |
33 | parent::__construct($message, $code);
34 | }
35 |
36 | /**
37 | * @return \Origin\Model\Entity
38 | */
39 | public function getEntity(): Entity
40 | {
41 | return $this->entity;
42 | }
43 |
44 | /**
45 | * @param \Origin\Model\Entity $entity
46 | * @param string $message
47 | * @return string
48 | */
49 | private function formatMessage(Entity $entity, string $message): string
50 | {
51 | $out = [];
52 | foreach ($entity->errors() as $field => $errors) {
53 | foreach ($errors as $error) {
54 | $out[] = "{$field}: {$error}";
55 | }
56 | }
57 |
58 | return sprintf(
59 | '%s %s failure. The following errors were found (%s).',
60 | $entity->name(),
61 | $message,
62 | implode(', ', $out),
63 | );
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/Model/Exception/ValidatorException.php:
--------------------------------------------------------------------------------
1 | Model = $model;
32 | }
33 |
34 | /**
35 | * Runs a batch insert query. Note there is a limit on number of placeholderes.
36 | *
37 | * @param array $records
38 | * @param array $options The following options keys are supported
39 | * - transactions: default true. To wrap insert in a transaction begin/commit
40 | * - table: default is the Model table.
41 | * @return bool|array|null
42 | */
43 |
44 | public function execute(array $records, array $options = [])
45 | {
46 | $options += ['transaction' => true,'table' => $this->Model->table()];
47 | $fields = $questionMarks = $values = $buffer = [];
48 |
49 | if (empty($records)) {
50 | throw new InvalidArgumentException('No records');
51 | }
52 |
53 | $firstKey = array_key_first($records);
54 |
55 | $fields = array_keys($records[$firstKey]);
56 | $questionMarks = array_fill(0, count($fields), '?');
57 |
58 | foreach ($records as $record) {
59 | $values = array_merge($values, array_values($record));
60 | $buffer[] = '(' . implode(', ', $questionMarks) . ')';
61 | }
62 |
63 | $fields = implode(', ', $fields);
64 | $buffer = implode(', ', $buffer);
65 |
66 | if ($options['transaction']) {
67 | $this->Model->beginTransaction();
68 | }
69 |
70 | $this->executeQuery("INSERT INTO {$options['table']} ({$fields}) VALUES {$buffer}", $values);
71 |
72 | if ($options['transaction']) {
73 | $this->Model->commitTransaction();
74 | }
75 |
76 | return true;
77 | }
78 |
79 | protected function executeQuery(string $query, array $values = [])
80 | {
81 | return $this->Model->query($query, $values);
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/Model/Query/QueryObject.php:
--------------------------------------------------------------------------------
1 | Article = $Article;
30 | * }
31 | *
32 | * public function execute() : Collection
33 | * {
34 | * ....
35 | * }
36 | * }
37 | *
38 | * Example
39 | *
40 | * $result = (new BooleanSearchQuery($this->Article))->execute('how to');
41 | *
42 | * @see https://www.martinfowler.com/eaaCatalog/queryObject.html
43 | */
44 | class QueryObject
45 | {
46 | use HookTrait;
47 |
48 | public function __construct()
49 | {
50 | $this->executeHook('initialize', func_get_args());
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/Model/Repository/Repository.php:
--------------------------------------------------------------------------------
1 | modelClass === null) {
41 | list($namespace, $class) = namespaceSplit(get_class($this));
42 | $this->modelClass = Inflector::singular(substr($class, 0, -10));
43 | }
44 | /**
45 | * Models are dependcies and should not be lazyloaded.
46 | */
47 | $this->loadModel($this->modelClass);
48 | $this->executeHook('initialize', func_get_args());
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/Model/Seed.php:
--------------------------------------------------------------------------------
1 | executeHook('initialize');
26 | }
27 | /**
28 | * Creates the SQL statements for inserting
29 | *
30 | * @param \Origin\Model\Connection $connection
31 | * @return array
32 | */
33 | public function insertSql(Connection $connection): array
34 | {
35 | $out = [];
36 | $properties = get_object_vars($this);
37 | foreach (array_keys($properties) as $table) {
38 | foreach ($this->$table as $record) {
39 | $builder = $connection->queryBuilder($table);
40 | $sql = $builder->insert($record)->write();
41 | $out[] = [$sql,$builder->getValues()];
42 | }
43 | }
44 |
45 | return $out;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/Model/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "originphp/model",
3 | "description": "OriginPHP ORM",
4 | "type": "library",
5 | "keywords": [
6 | "orm"
7 | ],
8 | "homepage": "https://www.originphp.com/",
9 | "license": "MIT",
10 | "authors": [
11 | {
12 | "name": "Jamiel Sharief",
13 | "email": "js@originphp.com"
14 | }
15 | ],
16 | "autoload": {
17 | "psr-4": {
18 | "Origin\\Model\\": "."
19 | }
20 | },
21 | "require": {
22 | "php": ">=7.3.0",
23 | "originphp/cache": "^2.0",
24 | "originphp/configurable": "^2.0",
25 | "originphp/core": "^3.0",
26 | "originphp/inflector": "^2.0",
27 | "originphp/log": "^2.0",
28 | "originphp/utility": "^3.0",
29 | "originphp/validation": "^2.0",
30 | "originphp/xml": "^2.0"
31 | },
32 | "minimum-stability": "dev",
33 | "prefer-stable": true
34 | }
35 |
--------------------------------------------------------------------------------
/src/Process/BaseProcess.php:
--------------------------------------------------------------------------------
1 | =7.3.0"
24 | },
25 | "minimum-stability": "dev",
26 | "prefer-stable": true
27 | }
28 |
--------------------------------------------------------------------------------
/src/Publisher/Exception/PublisherException.php:
--------------------------------------------------------------------------------
1 | executeHook('initialize');
27 | }
28 |
29 | /**
30 | * Dispatches a method
31 | *
32 | * @param string $method
33 | * @param array $arguments
34 | * @return boolean
35 | */
36 | public function dispatch(string $method, array $arguments = []): bool
37 | {
38 | $this->executeHook('startup');
39 | if ($this->executeHook($method, $arguments) === false) {
40 | return false;
41 | }
42 | $this->executeHook('shutdown');
43 |
44 | return true;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/Publisher/ListenerJob.php:
--------------------------------------------------------------------------------
1 | onError('errorHandler');
26 | }
27 |
28 | protected function execute(string $className, string $method, array $args = [])
29 | {
30 | ( new Publisher())->dispatch(new $className(), $method, $args);
31 | }
32 |
33 | protected function errorHandler(\Exception $exception): void
34 | {
35 | $this->retry();
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/Publisher/PublisherTrait.php:
--------------------------------------------------------------------------------
1 | publisherInstance)) {
32 | $this->publisherInstance = new Publisher();
33 | }
34 |
35 | return $this->publisherInstance;
36 | }
37 |
38 | /**
39 | * Subscribes an object
40 | *
41 | * @param object|string $object
42 | * @param array $options You can pass the following option keys
43 | * - on: an array of methods that this object that will listen to, by default it will listen to all
44 | * - queue: true or name of queue connection. All will go into
45 | * @return bool
46 | */
47 | public function subscribe($object, array $options = []): bool
48 | {
49 | return $this->getPublisher()->subscribe($object, $options);
50 | }
51 |
52 | /**
53 | * Publish an event with any number of arguments
54 | * Example:
55 | *
56 | * $this->publish('cancelCustomerOrder',$order, $user);
57 | *
58 | * @param string $event e.g. 'cancelCustomerOrder'
59 | * @param mixed ...$args argument or multiple arguments that will be passed to event
60 | * @return void
61 | */
62 | public function publish(string $event, ...$args): void
63 | {
64 | $this->getPublisher()->publish($event, ...$args);
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/Publisher/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "originphp/publisher",
3 | "description": "OriginPHP Publisher",
4 | "type": "library",
5 | "keywords": [
6 | "publisher",
7 | "subscribe",
8 | "pub-sub"
9 | ],
10 | "homepage": "https://www.originphp.com/",
11 | "license": "MIT",
12 | "authors": [
13 | {
14 | "name": "Jamiel Sharief",
15 | "email": "js@originphp.com"
16 | }
17 | ],
18 | "autoload": {
19 | "psr-4": {
20 | "Origin\\Publisher\\": "."
21 | }
22 | },
23 | "require": {
24 | "php": ">=7.3.0",
25 | "originphp/core": "^3.0"
26 | },
27 | "suggest": {
28 | "originphp/job": "If you are going to queue events"
29 | },
30 | "minimum-stability": "dev",
31 | "prefer-stable": true
32 | }
33 |
--------------------------------------------------------------------------------
/src/Redis/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018-2021 Jamiel Sharief.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/src/Redis/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "originphp/redis",
3 | "description": "OriginPHP Redis",
4 | "type": "library",
5 | "keywords": [],
6 | "homepage": "https://www.originphp.com/",
7 | "license": "MIT",
8 | "authors": [
9 | {
10 | "name": "Jamiel Sharief",
11 | "email": "js@originphp.com"
12 | }
13 | ],
14 | "autoload": {
15 | "psr-4": {
16 | "Origin\\Redis\\": "."
17 | }
18 | },
19 | "require": {
20 | "php": ">=7.3.0"
21 | },
22 | "minimum-stability": "dev",
23 | "prefer-stable": true
24 | }
25 |
--------------------------------------------------------------------------------
/src/Schedule/Command/ScheduleRunCommand.php:
--------------------------------------------------------------------------------
1 | addOption('directory', [
29 | 'description' => 'The directory where the tasks files are'
30 | ]);
31 |
32 | $this->addOption('id', [
33 | 'description' => 'A specific event ID that should be run'
34 | ]);
35 | }
36 |
37 | /**
38 | * @return void
39 | */
40 | protected function execute(): void
41 | {
42 | $path = $this->options('directory') ?: Schedule::config('path');
43 |
44 | if (is_null($path)) {
45 | $path = (defined('ROOT') ? ROOT : getcwd()) . '/app/Task';
46 | }
47 |
48 | try {
49 | Schedule::run($path, $this->options('id'));
50 | } catch (ScheduleException $exception) {
51 | $this->throwError($exception->getMessage());
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/Schedule/Exception/ScheduleException.php:
--------------------------------------------------------------------------------
1 | schedule = new Schedule($this);
45 |
46 | list($namespace, $name) = namespaceSplit(get_class($this));
47 | $this->name = $this->name ?? $name;
48 |
49 | $this->executeHook('initialize', func_get_args());
50 | }
51 |
52 | /**
53 | * Schedule your task here
54 | *
55 | * @param \Origin\Schedule\Schedule $schedule
56 | * @return void
57 | */
58 | abstract protected function handle(Schedule $schedule): void;
59 |
60 | /**
61 | * Invokes this task
62 | *
63 | * @return void
64 | */
65 | public function __invoke(): void
66 | {
67 | $this->handle($this->schedule);
68 | }
69 |
70 | /**
71 | * Dispatches the Task
72 | *
73 | * @return void
74 | */
75 | public function dispatch(): void
76 | {
77 | $this->executeHook('startup');
78 | $this->handle($this->schedule);
79 | $this->schedule->dispatch();
80 | $this->executeHook('shutdown');
81 | }
82 |
83 | /**
84 | * Gets the schedule object for this task
85 | *
86 | * @return \Origin\Schedule\Schedule
87 | */
88 | public function schedule(): Schedule
89 | {
90 | return $this->schedule;
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/src/Schedule/bin/schedule:run:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 | name('run');
37 | $app->description([
38 | 'Runs scheduled tasks'
39 | ]);
40 | $app->addCommand('run', ScheduleRunCommand::class);
41 | exit($app->run());
42 |
--------------------------------------------------------------------------------
/src/Schedule/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "originphp/schedule",
3 | "description": "OriginPHP Task Scheduler",
4 | "type": "library",
5 | "keywords": [
6 | "cron",
7 | "task",
8 | "schedule"
9 | ],
10 | "homepage": "https://www.originphp.com/",
11 | "license": "MIT",
12 | "authors": [
13 | {
14 | "name": "Jamiel Sharief",
15 | "email": "js@originphp.com"
16 | }
17 | ],
18 | "autoload": {
19 | "psr-4": {
20 | "Origin\\Schedule\\": "."
21 | }
22 | },
23 | "require": {
24 | "php": ">=7.3.0",
25 | "originphp/core": "^3.20",
26 | "originphp/configurable": "^2.0",
27 | "originphp/console": "^3.20",
28 | "originphp/process": "^3.20"
29 | },
30 | "suggest": {
31 | "originphp/job": "If you are going to queue events"
32 | },
33 | "minimum-stability": "dev",
34 | "prefer-stable": true,
35 | "bin": [
36 | "bin/schedule:run"
37 | ]
38 | }
39 |
--------------------------------------------------------------------------------
/src/Service/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018-2021 Jamiel Sharief.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/src/Service/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "originphp/service-object",
3 | "description": "OriginPHP Service Objects",
4 | "type": "library",
5 | "keywords": [
6 | "service",
7 | "services",
8 | "service object"
9 | ],
10 | "homepage": "https://www.originphp.com/docs/services/",
11 | "license": "MIT",
12 | "authors": [
13 | {
14 | "name": "Jamiel Sharief",
15 | "email": "js@originphp.com"
16 | }
17 | ],
18 | "autoload": {
19 | "psr-4": {
20 | "Origin\\Service\\": "."
21 | }
22 | },
23 | "require": {
24 | "php": ">=7.3.0",
25 | "originphp/core": "^3.0"
26 | },
27 | "minimum-stability": "dev",
28 | "prefer-stable": true
29 | }
30 |
--------------------------------------------------------------------------------
/src/Ssh/RemoteFile.php:
--------------------------------------------------------------------------------
1 | =7.3.0",
24 | "ext-ssh2": "*"
25 | },
26 | "minimum-stability": "dev",
27 | "prefer-stable": true
28 | }
29 |
--------------------------------------------------------------------------------
/src/TestSuite/Exception/ConsoleInputRequiredException.php:
--------------------------------------------------------------------------------
1 | input = $input;
29 | }
30 |
31 | public function read(): ?string
32 | {
33 | $index = $this->currentIndex();
34 |
35 | if (! isset($this->input[$index])) {
36 | throw new ConsoleInputRequiredException('Console input is requesting more input that what was provided');
37 | }
38 |
39 | return $this->input[$index];
40 | }
41 |
42 | private function currentIndex(): int
43 | {
44 | $this->current ++;
45 |
46 | return $this->current;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/TestSuite/Stub/ConsoleOutput.php:
--------------------------------------------------------------------------------
1 | level === self::QUIET || ($level === self::VERBOSE && $this->level === self::NORMAL)) {
32 | return strlen($buffer);
33 | }
34 |
35 | $this->buffer .= $buffer;
36 |
37 | return strlen($buffer);
38 | }
39 |
40 | public function read()
41 | {
42 | return $this->buffer;
43 | }
44 | }
45 |
46 | /*
47 | class ConsoleOutput extends BaseConsoleOutput
48 | {
49 | protected $mode = SELF::RAW;
50 |
51 | protected $buffer = '';
52 |
53 | protected function fwrite(string $data) : int
54 | {
55 | $this->buffer .= $data;
56 |
57 | return strlen($data);
58 | }
59 |
60 | public function read()
61 | {
62 | return $this->buffer;
63 | }
64 | }
65 |
66 | */
67 |
--------------------------------------------------------------------------------
/src/TestSuite/Stub/Request.php:
--------------------------------------------------------------------------------
1 | session = $session;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/TestSuite/TestTrait.php:
--------------------------------------------------------------------------------
1 | $method();
32 | }
33 |
34 | return call_user_func_array([$this, $method], $args);
35 | }
36 |
37 | public function getProperty(string $property)
38 | {
39 | if (isset($this->$property)) {
40 | return $this->$property;
41 | }
42 | }
43 |
44 | public function setProperty(string $property, $value)
45 | {
46 | $this->$property = $value;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/TestSuite/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "originphp/test-suite",
3 | "description": "OriginPHP Test Suite",
4 | "type": "library",
5 | "keywords": [
6 | "test suite",
7 | "integration testing"
8 | ],
9 | "homepage": "https://www.originphp.com/",
10 | "license": "MIT",
11 | "authors": [
12 | {
13 | "name": "Jamiel Sharief",
14 | "email": "js@originphp.com"
15 | }
16 | ],
17 | "autoload": {
18 | "psr-4": {
19 | "Origin\\TestSuite\\": "."
20 | }
21 | },
22 | "require": {
23 | "php": ">=7.3.0",
24 | "originphp/core": "^3.0",
25 | "originphp/inflector": "^2.0",
26 | "originphp/model": "^3.0",
27 | "phpunit/phpunit": "^9.2"
28 | },
29 | "suggest": {
30 | "originphp/http": "If you are going to use integration testing for web based applications",
31 | "originphp/console": "If you are going to use integration testing for console based commands",
32 | "originphp/job": "If you want to test queued jobs"
33 | },
34 | "minimum-stability": "dev",
35 | "prefer-stable": true
36 | }
37 |
--------------------------------------------------------------------------------
/src/Utility/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018-2021 Jamiel Sharief.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/src/Utility/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "originphp/utility",
3 | "description": "OriginPHP Utility",
4 | "type": "library",
5 | "keywords": [
6 | "date",
7 | "time"
8 | ],
9 | "homepage": "https://www.originphp.com/",
10 | "license": "MIT",
11 | "authors": [
12 | {
13 | "name": "Jamiel Sharief",
14 | "email": "js@originphp.com"
15 | }
16 | ],
17 | "autoload": {
18 | "psr-4": {
19 | "Origin\\Utility\\": "."
20 | }
21 | },
22 | "require": {
23 | "php": ">=7.3.0"
24 | },
25 | "minimum-stability": "dev",
26 | "prefer-stable": true
27 | }
28 |
--------------------------------------------------------------------------------