made some refactoring
This commit is contained in:
parent
f76eb08fe0
commit
38676bc9fd
9
.env
Normal file
9
.env
Normal file
@ -0,0 +1,9 @@
|
||||
APP_NAME=Project
|
||||
APP_ENV=local
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=db
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=laraspace
|
||||
DB_USERNAME=laraspace
|
||||
DB_PASSWORD="👨🍳🥚🧂🥛=🍽️💪"
|
@ -2,8 +2,9 @@
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/spec" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" packagePrefix="App\Tests\" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" packagePrefix="Tests\" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/clue/ndjson-react" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/composer" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/evenement/evenement" />
|
||||
@ -37,16 +38,21 @@
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/service-contracts" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/stopwatch" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/string" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/carbonphp/carbon-doctrine-types" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/myclabs/deep-copy" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/nesbot/carbon" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/nikic/php-parser" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phar-io/manifest" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phar-io/version" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phpfui/orm" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phpfui/translation" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-code-coverage" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-file-iterator" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-invoker" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-text-template" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-timer" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/phpunit" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/clock" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/cli-parser" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/comparator" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/complexity" />
|
||||
@ -60,6 +66,10 @@
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/type" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/version" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/staabm/side-effects-detector" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/clock" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-php83" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/translation" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/translation-contracts" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/theseer/tokenizer" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
|
@ -95,6 +95,15 @@
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/comparator" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/exporter" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/environment" />
|
||||
<path value="$PROJECT_DIR$/vendor/phpfui/orm" />
|
||||
<path value="$PROJECT_DIR$/vendor/phpfui/translation" />
|
||||
<path value="$PROJECT_DIR$/vendor/psr/clock" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/clock" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php83" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/translation-contracts" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/translation" />
|
||||
<path value="$PROJECT_DIR$/vendor/carbonphp/carbon-doctrine-types" />
|
||||
<path value="$PROJECT_DIR$/vendor/nesbot/carbon" />
|
||||
</include_path>
|
||||
</component>
|
||||
<component name="PhpProjectSharedConfiguration" php_language_level="8.3" />
|
||||
|
@ -4,11 +4,11 @@ declare(strict_types = 1);
|
||||
|
||||
use PhpCsFixer\{Config, Finder, Runner\Parallel\ParallelConfigFactory};
|
||||
|
||||
$finder = (new Finder())->in([
|
||||
$finder = (new Finder)->in([
|
||||
__DIR__ . '/src',
|
||||
])->exclude(['vendor'])->name('*.php')->ignoreDotFiles(true);
|
||||
|
||||
return (new Config())->setRules([
|
||||
return (new Config)->setRules([
|
||||
'@PSR12' => true,
|
||||
'declare_equal_normalize' => [
|
||||
'space' => 'single',
|
||||
@ -21,6 +21,9 @@ return (new Config())->setRules([
|
||||
'=>' => null,
|
||||
],
|
||||
],
|
||||
'new_with_parentheses' => [
|
||||
'named_class' => false,
|
||||
]
|
||||
])->setParallelConfig(ParallelConfigFactory::detect())->setUsingCache(true)->setRiskyAllowed(true)->setFinder(
|
||||
$finder
|
||||
)->setIndent(' ')->setLineEnding("\n");
|
||||
|
@ -1,42 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-03
|
||||
* @time: 20:20
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
use Pattern\Creational\AbstractFactory\{NovapostDeliveryFactory, UkrpostDeliveryFactory};
|
||||
use Pattern\Creational\AbstractFactory\{JustinDeliveryFactory, MeestDeliveryFactory};
|
||||
|
||||
/**
|
||||
* @param array $factories
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function delivery(array $factories): void
|
||||
{
|
||||
foreach ($factories as $factory) {
|
||||
// getting the delivery service
|
||||
$deliveryService = $factory->createDeliveryService();
|
||||
// getting the parcel
|
||||
$package = $factory->createPackage();
|
||||
// checking the parcel
|
||||
$package->getConsist();
|
||||
// sending the parcel
|
||||
$deliveryService->sendPackage($package);
|
||||
echo '<hr/>' . PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
$factories = [
|
||||
new MeestDeliveryFactory(),
|
||||
new NovapostDeliveryFactory(),
|
||||
new JustinDeliveryFactory(),
|
||||
new UkrpostDeliveryFactory(),
|
||||
];
|
||||
|
||||
delivery($factories);
|
@ -7,7 +7,7 @@
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"App\\Tests\\": "tests/"
|
||||
"Tests\\": "tests/"
|
||||
}
|
||||
},
|
||||
"authors": [
|
||||
@ -18,9 +18,13 @@
|
||||
],
|
||||
"require": {
|
||||
"php": "8.3.*",
|
||||
"ext-simplexml": "*"
|
||||
"ext-pdo": "*",
|
||||
"ext-simplexml": "*",
|
||||
"phpfui/orm": "^2.0",
|
||||
"nesbot/carbon": "^3.10"
|
||||
},
|
||||
"require-dev": {
|
||||
"roave/security-advisories": "dev-latest",
|
||||
"friendsofphp/php-cs-fixer": "^3.76",
|
||||
"phpunit/phpunit": "^12.2"
|
||||
},
|
||||
|
2037
composer.lock
generated
2037
composer.lock
generated
File diff suppressed because it is too large
Load Diff
11
config/database.php
Normal file
11
config/database.php
Normal file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-06
|
||||
* @time: 18:03
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@ -2,6 +2,7 @@
|
||||
$time_start = microtime(true);
|
||||
require '../vendor/autoload.php';
|
||||
require '../src/helpers.php';
|
||||
(new \Controller\DotEnvEnvironment())->load(__DIR__ . '/../');
|
||||
?><!doctype html>
|
||||
<html lang="uk">
|
||||
<head>
|
||||
|
39
resources/view/patterns/abstract-factory.php
Normal file
39
resources/view/patterns/abstract-factory.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-03
|
||||
* @time: 20:20
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
use Pattern\Creational\AbstractFactory\{ParcelSender, ProvidersEnum as PostProvider};
|
||||
|
||||
/**
|
||||
* @param array $parcels
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function doDeliver(array $parcels): void
|
||||
{
|
||||
foreach ($parcels as $parcel) {
|
||||
['provider' => $provider, 'destination_address' => $address] = $parcel;
|
||||
$result = (new ParcelSender($provider, $address))->send();
|
||||
|
||||
echo $result ? "✔️ Sent successfully\n" : "❌ Sending failed\n";
|
||||
}
|
||||
}
|
||||
|
||||
$parcels = [
|
||||
['provider' => PostProvider::NovaPost, 'destination_address' => "02020,\r\nм. Щастя, р-н ХТЗ"],
|
||||
[
|
||||
'provider' => PostProvider::UkrPost,
|
||||
'destination_address' => "Голобородько Семен Юхимович,\r\nn02020, Львівська обл.,\r\nм. Городок, вул. Головна, буд. 1, кв. 50",
|
||||
],
|
||||
['provider' => PostProvider::Meest, 'destination_address' => "Адреса 3"],
|
||||
['provider' => PostProvider::Justin, 'destination_address' => "Відділення 777"],
|
||||
];
|
||||
|
||||
doDeliver($parcels);
|
34
resources/view/patterns/observer.php
Normal file
34
resources/view/patterns/observer.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-06
|
||||
* @time: 15:35
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
use Pattern\Behavioral\Observer\User;
|
||||
use Pattern\Behavioral\Observer\UserObserver;
|
||||
|
||||
$user = new User();
|
||||
|
||||
/** These names will be skipped and not be added to the log of names */
|
||||
$user->setName("Just a name");
|
||||
$user->setName("Some new name");
|
||||
|
||||
$userObserver = new UserObserver();
|
||||
$user->attach($userObserver);
|
||||
|
||||
$user->setName("Another new name");
|
||||
$user->setName("Once again new name");
|
||||
$user->setName("Possibly other new name");
|
||||
|
||||
/** @noinspection ForgottenDebugOutputInspection */
|
||||
dump(
|
||||
getenv('APP_ENV'),
|
||||
["Another new name", "Once again new name", "Possibly other new name"],
|
||||
$userObserver->getNamesLog(),
|
||||
["Another new name", "Once again new name", "Possibly other new name"] === $userObserver->getNamesLog()
|
||||
);
|
14
resources/view/principles/liskov-substitution.php
Normal file
14
resources/view/principles/liskov-substitution.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-07
|
||||
* @time: 08:36
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
use Pattern\SOLID\LiskovSubstitution\Bird;
|
||||
|
||||
$bird = new Bird;
|
23
resources/view/principles/open-closed.php
Normal file
23
resources/view/principles/open-closed.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-07
|
||||
* @time: 05:52
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
// Separate extensible behaviour behind an interface, and flip the dependencies
|
||||
|
||||
use Pattern\SOLID\OpenClosed\Figures\AreaCalculator;
|
||||
use Pattern\SOLID\OpenClosed\Figures\Circle;
|
||||
use Pattern\SOLID\OpenClosed\Figures\Square;
|
||||
|
||||
$circle = new Circle(3);
|
||||
$square = new Square(2, 5);
|
||||
$areaCalculator = new AreaCalculator;
|
||||
|
||||
/** @noinspection ForgottenDebugOutputInspection */
|
||||
dump('Circle(3)', $areaCalculator->calculate([$circle, $square]));
|
22
resources/view/principles/solid-single-responsibility.php
Normal file
22
resources/view/principles/solid-single-responsibility.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-07
|
||||
* @time: 00:04
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Pattern\SOLID\SingleResponsibility\HtmlOutput;
|
||||
use Pattern\SOLID\SingleResponsibility\SalesReporter;
|
||||
use Pattern\SOLID\SingleResponsibility\SalesRepository;
|
||||
|
||||
$now = Carbon::now();
|
||||
$report = new SalesReporter(new SalesRepository);
|
||||
|
||||
$output = $report->between($now->clone()->subDays(10)->format('Y-m-d'), $now->format('Y-m-d'), new HtmlOutput);
|
||||
|
||||
echo($output);
|
32
resources/view/tools/itterate.php
Normal file
32
resources/view/tools/itterate.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-07
|
||||
* @time: 02:48
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
$c = 0;
|
||||
$ite = new RecursiveDirectoryIterator('k:\tmp\faker_dir');
|
||||
//$ite = new RecursiveDirectoryIterator('c:\tmp\Laracasts\Languages');
|
||||
//$ite = new RecursiveDirectoryIterator('w:\tmp\Laracasts\Languages\PHP');
|
||||
|
||||
foreach (new RecursiveIteratorIterator($ite) as $filename => $cur) {
|
||||
$pathInfo = pathinfo($filename);
|
||||
|
||||
if ($pathInfo['extension'] !== 'mp4') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$lnkFile = $filename . '.LNK';
|
||||
if (! file_exists($lnkFile)) {
|
||||
symlink($filename, $lnkFile);
|
||||
}
|
||||
|
||||
if (file_exists($lnkFile)) {
|
||||
echo "<p>deleted $filename</p>";
|
||||
//unlink($filename);
|
||||
}
|
||||
}
|
34
src/Controller/DotEnvEnvironment.php
Normal file
34
src/Controller/DotEnvEnvironment.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-06
|
||||
* @time: 16:23
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Controller;
|
||||
|
||||
class DotEnvEnvironment
|
||||
{
|
||||
public function load($path): void
|
||||
{
|
||||
$lines = file($path . '/.env');
|
||||
foreach ($lines as $line) {
|
||||
$split_line = explode('=', $line, 2);
|
||||
if (count($split_line) !== 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
[$key, $value] = $split_line;
|
||||
$key = trim($key);
|
||||
$value = trim($value);
|
||||
|
||||
putenv(sprintf('%s=%s', $key, $value));
|
||||
$_ENV[$key] = $value;
|
||||
$_SERVER[$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
148
src/Database/Adapter/PDO.php
Normal file
148
src/Database/Adapter/PDO.php
Normal file
@ -0,0 +1,148 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Database\Adapter;
|
||||
|
||||
use PDOException;
|
||||
use RuntimeException;
|
||||
use stdClass;
|
||||
|
||||
final class PDO
|
||||
{
|
||||
private ?\PDO $connection = null;
|
||||
private $statement = null;
|
||||
|
||||
public function __construct(
|
||||
string $hostname,
|
||||
string $username,
|
||||
string $password,
|
||||
string $database,
|
||||
string $port = '3306'
|
||||
) {
|
||||
try {
|
||||
$this->connection = new \PDO(
|
||||
"mysql:host=" . $hostname . ";port=" . $port . ";dbname=" . $database,
|
||||
$username,
|
||||
$password,
|
||||
[\PDO::ATTR_PERSISTENT => true]
|
||||
);
|
||||
} catch (PDOException $e) {
|
||||
throw new RuntimeException('Failed to connect to database. Reason: \'' . $e->getMessage() . '\'');
|
||||
}
|
||||
|
||||
$this->connection->exec("SET NAMES 'utf8'");
|
||||
$this->connection->exec("SET CHARACTER SET utf8");
|
||||
$this->connection->exec("SET CHARACTER_SET_CONNECTION=utf8");
|
||||
$this->connection->exec("SET SQL_MODE = ''");
|
||||
}
|
||||
|
||||
public function bindParam($parameter, $variable, $data_type = \PDO::PARAM_STR, $length = 0): void
|
||||
{
|
||||
if ($length) {
|
||||
$this->statement->bindParam($parameter, $variable, $data_type, $length);
|
||||
} else {
|
||||
$this->statement->bindParam($parameter, $variable, $data_type);
|
||||
}
|
||||
}
|
||||
|
||||
public function query($sql, $params = []): stdClass
|
||||
{
|
||||
$this->statement = $this->connection->prepare($sql);
|
||||
|
||||
$result = false;
|
||||
|
||||
try {
|
||||
if ($this->statement && $this->statement->execute($params)) {
|
||||
$data = [];
|
||||
|
||||
while ($row = $this->statement->fetch(\PDO::FETCH_ASSOC)) {
|
||||
$data[] = $row;
|
||||
}
|
||||
|
||||
$result = new stdClass();
|
||||
$result->row = ($data[0] ?? []);
|
||||
$result->rows = $data;
|
||||
$result->num_rows = $this->statement->rowCount();
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
throw new RuntimeException(
|
||||
'Error: ' . $e->getMessage() . ' Error Code : ' . $e->getCode() . ' <br />' . $sql
|
||||
);
|
||||
}
|
||||
|
||||
if ($result) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$result = new stdClass();
|
||||
$result->row = [];
|
||||
$result->rows = [];
|
||||
$result->num_rows = 0;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function prepare($sql): void
|
||||
{
|
||||
$this->statement = $this->connection->prepare($sql);
|
||||
}
|
||||
|
||||
public function execute(): void
|
||||
{
|
||||
try {
|
||||
if ($this->statement && $this->statement->execute()) {
|
||||
$data = [];
|
||||
|
||||
while ($row = $this->statement->fetch(\PDO::FETCH_ASSOC)) {
|
||||
$data[] = $row;
|
||||
}
|
||||
|
||||
/** @noinspection PhpObjectFieldsAreOnlyWrittenInspection */
|
||||
$result = new stdClass();
|
||||
$result->row = $data[0] ?? [];
|
||||
$result->rows = $data;
|
||||
$result->num_rows = $this->statement->rowCount();
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
throw new RuntimeException('Error: ' . $e->getMessage() . ' Error Code : ' . $e->getCode());
|
||||
}
|
||||
}
|
||||
|
||||
public function escape($value): array|string
|
||||
{
|
||||
return str_replace(
|
||||
["\\", "\0", "\n", "\r", "\x1a", "'", '"'],
|
||||
["\\\\", "\\0", "\\n", "\\r", "\Z", "\'", '\"'],
|
||||
$value
|
||||
);
|
||||
}
|
||||
|
||||
public function countAffected(): int
|
||||
{
|
||||
if ($this->statement) {
|
||||
return $this->statement->rowCount();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public function getLastId(): false|string
|
||||
{
|
||||
return $this->connection->lastInsertId();
|
||||
}
|
||||
|
||||
public function isConnected(): bool
|
||||
{
|
||||
if ($this->connection) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
$this->connection = null;
|
||||
}
|
||||
}
|
BIN
src/Database/Adapter/db.zip
Normal file
BIN
src/Database/Adapter/db.zip
Normal file
Binary file not shown.
105
src/Database/DB.php
Normal file
105
src/Database/DB.php
Normal file
@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package OpenCart
|
||||
* @author Daniel Kerr
|
||||
* @copyright Copyright (c) 2005 - 2017, OpenCart, Ltd. (https://www.opencart.com/)
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.opencart.com
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Database;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* DB class
|
||||
*/
|
||||
class DB
|
||||
{
|
||||
private mixed $adaptor;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $adaptor
|
||||
* @param string $hostname
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @param string $database
|
||||
* @param int|null $port
|
||||
*
|
||||
*/
|
||||
public function __construct(
|
||||
string $adaptor,
|
||||
string $hostname,
|
||||
string $username,
|
||||
string $password,
|
||||
string $database,
|
||||
int $port = null
|
||||
) {
|
||||
$class = 'DB\\' . $adaptor;
|
||||
|
||||
if (class_exists($class)) {
|
||||
$this->adaptor = new $class($hostname, $username, $password, $database, $port);
|
||||
} else {
|
||||
throw new RuntimeException('Error: Could not load database adaptor ' . $adaptor . '!');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param string $sql
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function query(string $sql): array
|
||||
{
|
||||
return $this->adaptor->query($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function escape(string $value): string
|
||||
{
|
||||
return $this->adaptor->escape($value);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function countAffected(): int
|
||||
{
|
||||
return $this->adaptor->countAffected();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getLastId(): int
|
||||
{
|
||||
return $this->adaptor->getLastId();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function connected(): bool
|
||||
{
|
||||
return $this->adaptor->connected();
|
||||
}
|
||||
}
|
15
src/FileSystem/ItterateFiles.php
Normal file
15
src/FileSystem/ItterateFiles.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-07
|
||||
* @time: 02:47
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FileSystem;
|
||||
|
||||
class ItterateFiles {
|
||||
}
|
@ -75,7 +75,6 @@ class User implements SplSubject
|
||||
{
|
||||
/** @var SplObserver $observer */
|
||||
foreach ($this->observers as $observer) {
|
||||
var_dump($observer);
|
||||
$observer->update($this);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @parcel: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-03
|
||||
* @time: 20:07
|
||||
@ -19,7 +19,7 @@ interface AbstractFactoryInterface
|
||||
public function createDeliveryService(): DeliveryServiceInterface;
|
||||
|
||||
/**
|
||||
* @return PackageInterface
|
||||
* @return ParcelInterface
|
||||
*/
|
||||
public function createPackage(): PackageInterface;
|
||||
public function createParcel(): ParcelInterface;
|
||||
}
|
||||
|
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @parcel: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-08
|
||||
* @time: 10:59
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Pattern\Creational\AbstractFactory;
|
||||
|
||||
class DeliveryServiceFactory
|
||||
{
|
||||
public static function create(ProvidersEnum $provider): AbstractFactoryInterface
|
||||
{
|
||||
return $provider->getService();
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @parcel: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-03
|
||||
* @time: 20:02
|
||||
@ -13,5 +13,5 @@ namespace Pattern\Creational\AbstractFactory;
|
||||
|
||||
interface DeliveryServiceInterface
|
||||
{
|
||||
public function sendPackage(PackageInterface $package): void;
|
||||
public function sendParcel(ParcelInterface $parcel): bool;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @parcel: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-03
|
||||
* @time: 20:15
|
||||
@ -18,8 +18,8 @@ class JustinDeliveryFactory implements AbstractFactoryInterface
|
||||
return new JustinDeliveryService();
|
||||
}
|
||||
|
||||
public function createPackage(): PackageInterface
|
||||
public function createParcel(): ParcelInterface
|
||||
{
|
||||
return new JustinPackage();
|
||||
return new JustinParcel();
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @parcel: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-03
|
||||
* @time: 19:57
|
||||
@ -13,9 +13,11 @@ namespace Pattern\Creational\AbstractFactory;
|
||||
|
||||
class JustinDeliveryService implements DeliveryServiceInterface
|
||||
{
|
||||
public function sendPackage(PackageInterface $package): void
|
||||
public function sendParcel(ParcelInterface $parcel): bool
|
||||
{
|
||||
/** @noinspection ForgottenDebugOutputInspection */
|
||||
dump("Sending package via Justin...");
|
||||
dump("Sending parcel via Justin...");
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @parcel: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-03
|
||||
* @time: 20:00
|
||||
@ -11,11 +11,18 @@ declare(strict_types = 1);
|
||||
|
||||
namespace Pattern\Creational\AbstractFactory;
|
||||
|
||||
class JustinPackage implements PackageInterface
|
||||
class JustinParcel implements ParcelInterface
|
||||
{
|
||||
public function getConsist(): void
|
||||
{
|
||||
/** @noinspection ForgottenDebugOutputInspection */
|
||||
dump('Checking package from Justin...');
|
||||
dump('Checking parcel from Justin...');
|
||||
}
|
||||
|
||||
public function setDestination(string $destination): static
|
||||
{
|
||||
echo "<pre>$destination</pre></<br>>";
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @parcel: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-03
|
||||
* @time: 20:15
|
||||
@ -18,8 +18,8 @@ class MeestDeliveryFactory implements AbstractFactoryInterface
|
||||
return new MeestDeliveryService();
|
||||
}
|
||||
|
||||
public function createPackage(): PackageInterface
|
||||
public function createParcel(): ParcelInterface
|
||||
{
|
||||
return new MeestPackage();
|
||||
return new MeestParcel();
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @parcel: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-03
|
||||
* @time: 19:57
|
||||
@ -14,9 +14,11 @@ namespace Pattern\Creational\AbstractFactory;
|
||||
|
||||
class MeestDeliveryService implements DeliveryServiceInterface
|
||||
{
|
||||
public function sendPackage(PackageInterface $package): void
|
||||
public function sendParcel(ParcelInterface $parcel): bool
|
||||
{
|
||||
/** @noinspection ForgottenDebugOutputInspection */
|
||||
dump("Sending package via Meest...");
|
||||
dump("Sending parcel via Meest...");
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-03
|
||||
* @time: 20:00
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Pattern\Creational\AbstractFactory;
|
||||
|
||||
class MeestPackage implements PackageInterface
|
||||
{
|
||||
public function getConsist(): void
|
||||
{
|
||||
/** @noinspection ForgottenDebugOutputInspection */
|
||||
dump('Checking package from Meest...');
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @parcel: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-03
|
||||
* @time: 20:00
|
||||
@ -11,11 +11,18 @@ declare(strict_types = 1);
|
||||
|
||||
namespace Pattern\Creational\AbstractFactory;
|
||||
|
||||
class UkrpostPackage implements PackageInterface
|
||||
class MeestParcel implements ParcelInterface
|
||||
{
|
||||
public function getConsist(): void
|
||||
{
|
||||
/** @noinspection ForgottenDebugOutputInspection */
|
||||
dump('Checking package from Ukrpost...');
|
||||
dump('Checking parcel from Meest...');
|
||||
}
|
||||
|
||||
public function setDestination(string $destination): static
|
||||
{
|
||||
echo "<pre>$destination</pre></<br>";
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @parcel: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-03
|
||||
* @time: 20:15
|
||||
@ -15,11 +15,11 @@ class NovapostDeliveryFactory implements AbstractFactoryInterface
|
||||
{
|
||||
public function createDeliveryService(): DeliveryServiceInterface
|
||||
{
|
||||
return new NovapostDeliveryService();
|
||||
return new NovapostDeliveryService;
|
||||
}
|
||||
|
||||
public function createPackage(): PackageInterface
|
||||
public function createParcel(): ParcelInterface
|
||||
{
|
||||
return new NovapostPackage();
|
||||
return new NovapostParcel;
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @parcel: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-03
|
||||
* @time: 19:57
|
||||
@ -13,9 +13,11 @@ namespace Pattern\Creational\AbstractFactory;
|
||||
|
||||
class NovapostDeliveryService implements DeliveryServiceInterface
|
||||
{
|
||||
public function sendPackage(PackageInterface $package): void
|
||||
public function sendParcel(ParcelInterface $parcel): true
|
||||
{
|
||||
/** @noinspection ForgottenDebugOutputInspection */
|
||||
dump("Sending package via Novapost...");
|
||||
dump("Sending parcel via Novapost...");
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-03
|
||||
* @time: 20:00
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Pattern\Creational\AbstractFactory;
|
||||
|
||||
class NovapostPackage implements PackageInterface
|
||||
{
|
||||
public function getConsist(): void
|
||||
{
|
||||
/** @noinspection ForgottenDebugOutputInspection */
|
||||
dump('Checking package from Novapost...');
|
||||
}
|
||||
}
|
33
src/Pattern/Creational/AbstractFactory/NovapostParcel.php
Normal file
33
src/Pattern/Creational/AbstractFactory/NovapostParcel.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @parcel: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-03
|
||||
* @time: 20:00
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Pattern\Creational\AbstractFactory;
|
||||
|
||||
class NovapostParcel implements ParcelInterface
|
||||
{
|
||||
public function getConsist(): void
|
||||
{
|
||||
/** @noinspection ForgottenDebugOutputInspection */
|
||||
dump('Checking parcel from Novapost...');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $destination
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setDestination(string $destination): static
|
||||
{
|
||||
echo "<pre>$destination</pre></<br>";
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-03
|
||||
* @time: 19:59
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Pattern\Creational\AbstractFactory;
|
||||
|
||||
interface PackageInterface
|
||||
{
|
||||
public function getConsist(): void;
|
||||
}
|
27
src/Pattern/Creational/AbstractFactory/ParcelInterface.php
Normal file
27
src/Pattern/Creational/AbstractFactory/ParcelInterface.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @parcel: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-03
|
||||
* @time: 19:59
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Pattern\Creational\AbstractFactory;
|
||||
|
||||
interface ParcelInterface
|
||||
{
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function getConsist(): void;
|
||||
|
||||
/**
|
||||
* @param string $destination
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setDestination(string $destination): static;
|
||||
}
|
41
src/Pattern/Creational/AbstractFactory/ParcelSender.php
Normal file
41
src/Pattern/Creational/AbstractFactory/ParcelSender.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-08
|
||||
* @time: 11:14
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Pattern\Creational\AbstractFactory;
|
||||
|
||||
readonly class ParcelSender
|
||||
{
|
||||
private AbstractFactoryInterface $service;
|
||||
|
||||
public function __construct(
|
||||
private ProvidersEnum $provider,
|
||||
private string $destinationAddress,
|
||||
) {
|
||||
$this->service = DeliveryServiceFactory::create($this->provider);
|
||||
}
|
||||
|
||||
public function send(): bool
|
||||
{
|
||||
// getting the delivery service
|
||||
$deliveryService = $this->service->createDeliveryService();
|
||||
|
||||
// getting the parcel
|
||||
$parcel = $this->service->createParcel();
|
||||
|
||||
// setting up address & checking the parcel
|
||||
$parcel->setDestination($this->destinationAddress)->getConsist();
|
||||
|
||||
// sending the parcel
|
||||
$deliveryService->sendParcel($parcel);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
30
src/Pattern/Creational/AbstractFactory/ProvidersEnum.php
Normal file
30
src/Pattern/Creational/AbstractFactory/ProvidersEnum.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @parcel: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-08
|
||||
* @time: 10:20
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Pattern\Creational\AbstractFactory;
|
||||
|
||||
enum ProvidersEnum
|
||||
{
|
||||
case NovaPost;
|
||||
case UkrPost;
|
||||
case Meest;
|
||||
case Justin;
|
||||
|
||||
public function getService(): AbstractFactoryInterface
|
||||
{
|
||||
return match ($this) {
|
||||
self::NovaPost => new NovapostDeliveryFactory,
|
||||
self::UkrPost => new UkrpostDeliveryFactory,
|
||||
self::Meest => new MeestDeliveryFactory,
|
||||
self::Justin => new JustinDeliveryFactory,
|
||||
};
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @parcel: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-03
|
||||
* @time: 20:15
|
||||
@ -18,8 +18,8 @@ class UkrpostDeliveryFactory implements AbstractFactoryInterface
|
||||
return new UkrpostDeliveryService();
|
||||
}
|
||||
|
||||
public function createPackage(): PackageInterface
|
||||
public function createParcel(): ParcelInterface
|
||||
{
|
||||
return new UkrpostPackage();
|
||||
return new UkrpostParcel();
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @parcel: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-03
|
||||
* @time: 19:57
|
||||
@ -13,9 +13,11 @@ namespace Pattern\Creational\AbstractFactory;
|
||||
|
||||
class UkrpostDeliveryService implements DeliveryServiceInterface
|
||||
{
|
||||
public function sendPackage(PackageInterface $package): void
|
||||
public function sendParcel(ParcelInterface $parcel): bool
|
||||
{
|
||||
/** @noinspection ForgottenDebugOutputInspection */
|
||||
dump("Sending package via Ukrpost...");
|
||||
dump("Sending parcel via Ukrpost...");
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
34
src/Pattern/Creational/AbstractFactory/UkrpostParcel.php
Normal file
34
src/Pattern/Creational/AbstractFactory/UkrpostParcel.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @parcel: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-03
|
||||
* @time: 20:00
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Pattern\Creational\AbstractFactory;
|
||||
|
||||
class UkrpostParcel implements ParcelInterface
|
||||
{
|
||||
public function getConsist(): void
|
||||
{
|
||||
/** @noinspection ForgottenDebugOutputInspection */
|
||||
dump('Checking parcel from Ukrpost...');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $destination
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setDestination(string $destination): static
|
||||
{
|
||||
echo "<pre>$destination</pre></<br>";
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
22
src/Pattern/Creational/AbstractFactory/info.md
Normal file
22
src/Pattern/Creational/AbstractFactory/info.md
Normal file
@ -0,0 +1,22 @@
|
||||
🧠 **Переваги цієї архітектури**
|
||||
|
||||
✅ Легко додати нову службу доставки
|
||||
✅ Не потрібно змінювати існуючий код (принцип Open/Closed)
|
||||
✅ Клієнтський код не залежить від реалізацій
|
||||
✅ Можна легко замінювати служби в тестах (Mock)
|
||||
|
||||
|
||||
🧩 **Структура оновленого коду:**
|
||||
DeliveryServiceInterface — інтерфейс
|
||||
|
||||
{Justin|Meest|NovaPost|UkrPost}DeliveryService — реалізація
|
||||
|
||||
|
||||
DeliveryServiceFactory — фабрика
|
||||
|
||||
ParcelSender — клієнтська логіка
|
||||
|
||||
index.php — приклад використання
|
||||
|
||||
|
||||
Надай приклад реалізації патерну Singleton на мові програмування PHP
|
@ -53,7 +53,7 @@ class Singleton
|
||||
dump(trim($message . ': ' . $cls, ' :'));
|
||||
|
||||
if (!isset(self::$instances[$cls])) {
|
||||
self::$instances[$cls] = new static();
|
||||
self::$instances[$cls] = new static;
|
||||
}
|
||||
|
||||
return self::$instances[$cls];
|
||||
|
20
src/Pattern/SOLID/LiskovSubstitution/Bird.php
Normal file
20
src/Pattern/SOLID/LiskovSubstitution/Bird.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-07
|
||||
* @time: 08:35
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Pattern\SOLID\LiskovSubstitution;
|
||||
|
||||
class Bird
|
||||
{
|
||||
public function fly(): int
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
}
|
28
src/Pattern/SOLID/LiskovSubstitution/BirdRun.php
Normal file
28
src/Pattern/SOLID/LiskovSubstitution/BirdRun.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-07
|
||||
* @time: 08:30
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Pattern\SOLID\LiskovSubstitution;
|
||||
|
||||
/**
|
||||
* Let q(x) be a property provable about objects x of type T.
|
||||
* Then q(y) should be provable for objects y of type S where S is a subtype of T.
|
||||
*
|
||||
* Derived classes must be substitutable for their base classes.
|
||||
*/
|
||||
readonly class BirdRun
|
||||
{
|
||||
public function __construct(private Bird $bird) {}
|
||||
|
||||
public function run(): void
|
||||
{
|
||||
$flySpeed = $this->bird->fly();
|
||||
}
|
||||
}
|
30
src/Pattern/SOLID/LiskovSubstitution/Duck.php
Normal file
30
src/Pattern/SOLID/LiskovSubstitution/Duck.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-07
|
||||
* @time: 09:35
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Pattern\SOLID\LiskovSubstitution;
|
||||
|
||||
class Duck extends Bird
|
||||
{
|
||||
public function fly(): int
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
|
||||
public function swim(): int
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
public function run(): int
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
}
|
27
src/Pattern/SOLID/LiskovSubstitution/Ostrich.php
Normal file
27
src/Pattern/SOLID/LiskovSubstitution/Ostrich.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-07
|
||||
* @time: 09:39
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Pattern\SOLID\LiskovSubstitution;
|
||||
|
||||
use Pattern\SOLID\LiskovSubstitution\Bird;
|
||||
|
||||
class Ostrich extends Bird
|
||||
{
|
||||
public function fly(): int
|
||||
{
|
||||
return 0; //I am not able to fly
|
||||
}
|
||||
|
||||
public function swim(): int
|
||||
{
|
||||
return 12;
|
||||
}
|
||||
}
|
33
src/Pattern/SOLID/OpenClosed/Figures/AreaCalculator.php
Normal file
33
src/Pattern/SOLID/OpenClosed/Figures/AreaCalculator.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-07
|
||||
* @time: 05:28
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Pattern\SOLID\OpenClosed\Figures;
|
||||
|
||||
class AreaCalculator
|
||||
{
|
||||
/**
|
||||
* @param array $shapes
|
||||
*
|
||||
* @return int|float
|
||||
*/
|
||||
public function calculate(array $shapes, int $round_precision = 2): int|float
|
||||
{
|
||||
$area = [];
|
||||
|
||||
foreach ($shapes as $shape) {
|
||||
$area[] = $shape->area();
|
||||
}
|
||||
|
||||
$result = array_sum($area);
|
||||
|
||||
return is_int($result) ? $result : round($result, $round_precision, PHP_ROUND_HALF_UP);
|
||||
}
|
||||
}
|
25
src/Pattern/SOLID/OpenClosed/Figures/Circle.php
Normal file
25
src/Pattern/SOLID/OpenClosed/Figures/Circle.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-07
|
||||
* @time: 05:32
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Pattern\SOLID\OpenClosed\Figures;
|
||||
|
||||
class Circle implements ShapeInterface
|
||||
{
|
||||
public function __construct(public int|float $radius) {}
|
||||
|
||||
/**
|
||||
* @return int|float
|
||||
*/
|
||||
public function area(): int|float
|
||||
{
|
||||
return M_PI * ($this->radius ** 2);
|
||||
}
|
||||
}
|
17
src/Pattern/SOLID/OpenClosed/Figures/ShapeInterface.php
Normal file
17
src/Pattern/SOLID/OpenClosed/Figures/ShapeInterface.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-07
|
||||
* @time: 05:55
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Pattern\SOLID\OpenClosed\Figures;
|
||||
|
||||
interface ShapeInterface
|
||||
{
|
||||
public function area(): int|float;
|
||||
}
|
25
src/Pattern/SOLID/OpenClosed/Figures/Square.php
Normal file
25
src/Pattern/SOLID/OpenClosed/Figures/Square.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-07
|
||||
* @time: 05:27
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Pattern\SOLID\OpenClosed\Figures;
|
||||
|
||||
class Square implements ShapeInterface
|
||||
{
|
||||
public function __construct(public int|float $width, public int|float $height) {}
|
||||
|
||||
/**
|
||||
* @return int|float
|
||||
*/
|
||||
public function area(): int|float
|
||||
{
|
||||
return $this->width * $this->height;
|
||||
}
|
||||
}
|
20
src/Pattern/SOLID/OpenClosed/Payments/CashPaymentMethod.php
Normal file
20
src/Pattern/SOLID/OpenClosed/Payments/CashPaymentMethod.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-07
|
||||
* @time: 06:20
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Pattern\SOLID\OpenClosed\Payments;
|
||||
|
||||
class CashPaymentMethod implements PaymentMethodInterface
|
||||
{
|
||||
public function acceptPayment($receipt)
|
||||
{
|
||||
// TODO: Implement acceptPayment() method.
|
||||
}
|
||||
}
|
20
src/Pattern/SOLID/OpenClosed/Payments/Checkout.php
Normal file
20
src/Pattern/SOLID/OpenClosed/Payments/Checkout.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-07
|
||||
* @time: 06:19
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Pattern\SOLID\OpenClosed\Payments;
|
||||
|
||||
class Checkout
|
||||
{
|
||||
public function begin(Receipt $receipt, PaymentMethodInterface $payment): void
|
||||
{
|
||||
$payment->acceptPayment($receipt);
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-07
|
||||
* @time: 06:20
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Pattern\SOLID\OpenClosed\Payments;
|
||||
|
||||
interface PaymentMethodInterface
|
||||
{
|
||||
public function acceptPayment($receipt);
|
||||
}
|
14
src/Pattern/SOLID/OpenClosed/Payments/Receipt.php
Normal file
14
src/Pattern/SOLID/OpenClosed/Payments/Receipt.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-07
|
||||
* @time: 06:24
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Pattern\SOLID\OpenClosed\Payments;
|
||||
|
||||
class Receipt {}
|
27
src/Pattern/SOLID/SingleResponsibility/HtmlOutput.php
Normal file
27
src/Pattern/SOLID/SingleResponsibility/HtmlOutput.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-07
|
||||
* @time: 03:51
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Pattern\SOLID\SingleResponsibility;
|
||||
?>
|
||||
<style>
|
||||
span {
|
||||
color: green;
|
||||
}
|
||||
</style>
|
||||
<?php
|
||||
|
||||
class HtmlOutput implements SalesReportOutputInterface
|
||||
{
|
||||
public function output($sales): string
|
||||
{
|
||||
return "<h2>Sales: <span>$" . number_format($sales, 2) . "</span>></h2>";
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-07
|
||||
* @time: 03:50
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Pattern\SOLID\SingleResponsibility;
|
||||
|
||||
interface SalesReportOutputInterface
|
||||
{
|
||||
public function output($sales): string;
|
||||
}
|
26
src/Pattern/SOLID/SingleResponsibility/SalesReporter.php
Normal file
26
src/Pattern/SOLID/SingleResponsibility/SalesReporter.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-06
|
||||
* @time: 23:22
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Pattern\SOLID\SingleResponsibility;
|
||||
|
||||
use Carbon\Carbon;
|
||||
|
||||
final readonly class SalesReporter
|
||||
{
|
||||
public function __construct(private SalesRepository $repository) {}
|
||||
|
||||
public function between(string|Carbon $startDate, string|Carbon $endDate, SalesReportOutputInterface $formatter): string
|
||||
{
|
||||
$sales = $this->repository->between($startDate, $endDate);
|
||||
|
||||
return $formatter->output($sales);
|
||||
}
|
||||
}
|
31
src/Pattern/SOLID/SingleResponsibility/SalesRepository.php
Normal file
31
src/Pattern/SOLID/SingleResponsibility/SalesRepository.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package: patterns
|
||||
* @author: Yevhen Odynets
|
||||
* @date: 2025-07-07
|
||||
* @time: 03:45
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Pattern\SOLID\SingleResponsibility;
|
||||
|
||||
class SalesRepository
|
||||
{
|
||||
/**
|
||||
* Just emulate db query
|
||||
*
|
||||
* @param $startDate
|
||||
* @param $endDate
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function between($startDate, $endDate): float
|
||||
{
|
||||
/** @noinspection ForgottenDebugOutputInspection */
|
||||
dump($startDate, $endDate);
|
||||
|
||||
return 192_273_221 / 100;
|
||||
}
|
||||
}
|
@ -44,3 +44,54 @@ function getFloatRange(): float
|
||||
{
|
||||
return (float)random_int(1000, 999999) / 100;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flatten a multi-dimensional associative array with dots.
|
||||
*
|
||||
* @param iterable $array
|
||||
* @param string $prepend
|
||||
*
|
||||
* @return array
|
||||
* @throws RandomException
|
||||
*/
|
||||
//function array_dot(iterable $array, string $prepend = ''): array
|
||||
//{
|
||||
// $results = [];
|
||||
//
|
||||
// $flatten = static function ($data, $prefix) use (&$results, &$flatten): void {
|
||||
// foreach ($data as $key => $value) {
|
||||
// $newKey = $prefix.$key;
|
||||
//
|
||||
// if (is_array($value) && ! empty($value)) {
|
||||
// $flatten($value, $newKey.'.');
|
||||
// } else {
|
||||
// $results[$newKey] = $value;
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// $flatten($array, $prepend);
|
||||
//
|
||||
// return $results;
|
||||
//}
|
||||
|
||||
function abord(int $code): void
|
||||
{
|
||||
$response_message = $_SERVER['SERVER_PROTOCOL'];
|
||||
|
||||
switch ($code) {
|
||||
case 404:
|
||||
$response_message .= $code . ' Not Found';
|
||||
break;
|
||||
case 500:
|
||||
$response_message .= $code . ' Internal Server Error';
|
||||
break;
|
||||
default:
|
||||
$response_message .= ' 501 Not Implemented';
|
||||
throw new RandomException($response_message, $code);
|
||||
}
|
||||
|
||||
header($response_message);
|
||||
http_response_code($code);
|
||||
print($response_message);
|
||||
}
|
@ -9,8 +9,36 @@
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
preg_match('/^\/patterns\/([a-z0-9-]+)/', $_SERVER["REQUEST_URI"], $patterns);
|
||||
$request_uri = $_SERVER["REQUEST_URI"];
|
||||
const DIR_VIEW = '../resources/view';
|
||||
|
||||
if (isset($patterns[1]) && file_exists('../code/' . $patterns[1] . '.php')) {
|
||||
require '../code/' . $patterns[1] . '.php';
|
||||
$slugs = ['patterns', 'principles', 'tools'];
|
||||
$regex_pattern = '/^\/(' . implode('|', $slugs) . ')\/([a-z0-9-]+)/';
|
||||
|
||||
if (preg_match($regex_pattern, $request_uri, $matches) && isset($matches[1])) {
|
||||
|
||||
[$uri, $controller, $view] = $matches;
|
||||
$filepath = realpath(DIR_VIEW . $uri . '.php');
|
||||
if (file_exists($filepath)) {
|
||||
require $filepath;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*if (preg_match($regex_pattern, $request_uri, $matches)) {
|
||||
$filepath = DIR_VIEW . "$slug/" . $matches[1] . '.php';
|
||||
|
||||
if (isset($matches[1]) && file_exists($filepath)) {
|
||||
require $filepath;
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
abord(404);
|
||||
} catch (RandomException $e) {
|
||||
/** @noinspection ForgottenDebugOutputInspection */
|
||||
// dump($e->getMessage());
|
||||
///}
|
||||
//}*/
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace App\Tests;
|
||||
namespace Tests;
|
||||
|
||||
use Pattern\Behavioral\Observer\User;
|
||||
use Pattern\Behavioral\Observer\UserObserver;
|
||||
@ -19,6 +19,7 @@ class ObserverTest extends TestCase
|
||||
{
|
||||
public function testObserver(): void
|
||||
{
|
||||
|
||||
$user = new User();
|
||||
|
||||
/** These names will be skipped and not be added to the log of names */
|
||||
|
Loading…
Reference in New Issue
Block a user