Singleton added

This commit is contained in:
Yevhen Odynets 2025-07-03 12:02:19 +03:00
commit 91f8ded888
31 changed files with 5025 additions and 0 deletions

180
.gitignore vendored Normal file
View File

@ -0,0 +1,180 @@
### PhpStorm+all template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# AWS User-specific
.idea/**/aws.xml
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# SonarLint plugin
.idea/sonarlint/
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### PhpStorm+iml template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
# AWS User-specific
# Generated files
# Sensitive or high-churn files
# Gradle
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
# Mongo Explorer plugin
# File-based project format
# IntelliJ
# mpeltonen/sbt-idea plugin
# JIRA plugin
# Cursive Clojure plugin
# SonarLint plugin
# Crashlytics plugin (for Android Studio and IntelliJ)
# Editor-based Rest Client
# Android studio 3.1+ serialized cache file
### PhpStorm template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
# AWS User-specific
# Generated files
# Sensitive or high-churn files
# Gradle
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
# Mongo Explorer plugin
# File-based project format
# IntelliJ
# mpeltonen/sbt-idea plugin
# JIRA plugin
# Cursive Clojure plugin
# SonarLint plugin
# Crashlytics plugin (for Android Studio and IntelliJ)
# Editor-based Rest Client
# Android studio 3.1+ serialized cache file
/vendor/
/storage/**/*.zip
/storage/logs/**/*.*

8
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View File

@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>

View File

@ -0,0 +1,129 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="ForgottenDebugOutputInspection" enabled="true" level="ERROR" enabled_by_default="true">
<option name="configuration">
<list>
<option value="\Codeception\Util\Debug::debug" />
<option value="\Codeception\Util\Debug::pause" />
<option value="\Doctrine\Common\Util\Debug::dump" />
<option value="\Doctrine\Common\Util\Debug::export" />
<option value="\Illuminate\Support\Debug\Dumper::dump" />
<option value="\Symfony\Component\Debug\Debug::enable" />
<option value="\Symfony\Component\Debug\DebugClassLoader::enable" />
<option value="\Symfony\Component\Debug\ErrorHandler::register" />
<option value="\Symfony\Component\Debug\ExceptionHandler::register" />
<option value="\TYPO3\CMS\Core\Utility\DebugUtility::debug" />
<option value="\Zend\Debug\Debug::dump" />
<option value="\Zend\Di\Display\Console::export" />
<option value="dd" />
<option value="debug_print_backtrace" />
<option value="debug_zval_dump" />
<option value="dpm" />
<option value="dpq" />
<option value="dsm" />
<option value="dump" />
<option value="dvm" />
<option value="error_log" />
<option value="kpr" />
<option value="phpinfo" />
<option value="print_r" />
<option value="trap" />
<option value="var_dump" />
<option value="var_export" />
<option value="wp_die" />
<option value="xdebug_break" />
<option value="xdebug_call_class" />
<option value="xdebug_call_file" />
<option value="xdebug_call_function" />
<option value="xdebug_call_line" />
<option value="xdebug_code_coverage_started" />
<option value="xdebug_debug_zval" />
<option value="xdebug_debug_zval_stdout" />
<option value="xdebug_dump_superglobals" />
<option value="xdebug_enable" />
<option value="xdebug_get_code_coverage" />
<option value="xdebug_get_collected_errors" />
<option value="xdebug_get_declared_vars" />
<option value="xdebug_get_function_stack" />
<option value="xdebug_get_headers" />
<option value="xdebug_get_monitored_functions" />
<option value="xdebug_get_profiler_filename" />
<option value="xdebug_get_stack_depth" />
<option value="xdebug_get_tracefile_name" />
<option value="xdebug_is_enabled" />
<option value="xdebug_memory_usage" />
<option value="xdebug_peak_memory_usage" />
<option value="xdebug_print_function_stack" />
<option value="xdebug_start_code_coverage" />
<option value="xdebug_start_error_collection" />
<option value="xdebug_start_function_monitor" />
<option value="xdebug_start_trace" />
<option value="xdebug_stop_code_coverage" />
<option value="xdebug_stop_error_collection" />
<option value="xdebug_stop_function_monitor" />
<option value="xdebug_stop_trace" />
<option value="xdebug_time_index" />
<option value="xdebug_var_dump" />
</list>
</option>
<option name="migratedIntoUserSpace" value="true" />
</inspection_tool>
<inspection_tool class="PhpCSFixerValidationInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="SecurityAdvisoriesInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="optionConfiguration">
<list>
<option value="barryvdh/laravel-debugbar" />
<option value="behat/behat" />
<option value="brianium/paratest" />
<option value="codeception/codeception" />
<option value="codedungeon/phpunit-result-printer" />
<option value="composer/composer" />
<option value="doctrine/coding-standard" />
<option value="filp/whoops" />
<option value="friendsofphp/php-cs-fixer" />
<option value="humbug/humbug" />
<option value="infection/infection" />
<option value="jakub-onderka/php-parallel-lint" />
<option value="johnkary/phpunit-speedtrap" />
<option value="kalessil/production-dependencies-guard" />
<option value="mikey179/vfsStream" />
<option value="mockery/mockery" />
<option value="mybuilder/phpunit-accelerator" />
<option value="orchestra/testbench" />
<option value="pdepend/pdepend" />
<option value="phan/phan" />
<option value="phing/phing" />
<option value="phpcompatibility/php-compatibility" />
<option value="phpmd/phpmd" />
<option value="phpro/grumphp" />
<option value="phpspec/phpspec" />
<option value="phpspec/prophecy" />
<option value="phpstan/phpstan" />
<option value="phpunit/phpunit" />
<option value="povils/phpmnd" />
<option value="roave/security-advisories" />
<option value="satooshi/php-coveralls" />
<option value="sebastian/phpcpd" />
<option value="slevomat/coding-standard" />
<option value="spatie/phpunit-watcher" />
<option value="squizlabs/php_codesniffer" />
<option value="sstalle/php7cc" />
<option value="symfony/debug" />
<option value="symfony/maker-bundle" />
<option value="symfony/phpunit-bridge" />
<option value="symfony/var-dumper" />
<option value="vimeo/psalm" />
<option value="wimg/php-compatibility" />
<option value="wp-coding-standards/wpcs" />
<option value="yiisoft/yii2-coding-standards" />
<option value="yiisoft/yii2-debug" />
<option value="yiisoft/yii2-gii" />
<option value="zendframework/zend-coding-standard" />
<option value="zendframework/zend-debug" />
<option value="zendframework/zend-test" />
</list>
</option>
</inspection_tool>
</profile>
</component>

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/patterns.iml" filepath="$PROJECT_DIR$/.idea/patterns.iml" />
</modules>
</component>
</project>

43
.idea/patterns.iml Normal file
View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/vendor/clue/ndjson-react" />
<excludeFolder url="file://$MODULE_DIR$/vendor/composer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/evenement/evenement" />
<excludeFolder url="file://$MODULE_DIR$/vendor/fidry/cpu-core-counter" />
<excludeFolder url="file://$MODULE_DIR$/vendor/friendsofphp/php-cs-fixer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/container" />
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/event-dispatcher" />
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/log" />
<excludeFolder url="file://$MODULE_DIR$/vendor/react/cache" />
<excludeFolder url="file://$MODULE_DIR$/vendor/react/child-process" />
<excludeFolder url="file://$MODULE_DIR$/vendor/react/dns" />
<excludeFolder url="file://$MODULE_DIR$/vendor/react/event-loop" />
<excludeFolder url="file://$MODULE_DIR$/vendor/react/promise" />
<excludeFolder url="file://$MODULE_DIR$/vendor/react/socket" />
<excludeFolder url="file://$MODULE_DIR$/vendor/react/stream" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/diff" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/console" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/deprecation-contracts" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/event-dispatcher" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/event-dispatcher-contracts" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/filesystem" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/finder" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/options-resolver" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-ctype" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-intl-grapheme" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-intl-normalizer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-mbstring" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-php80" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-php81" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/process" />
<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" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

93
.idea/php.xml Normal file
View File

@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="LaravelPint">
<laravel_pint_settings>
<laravel_pint_by_interpreter asDefaultInterpreter="true" interpreter_id="6adcaaf8-6d8b-41cc-8523-d95f7e166ea1">
<option name="timeout" value="30000" />
</laravel_pint_by_interpreter>
</laravel_pint_settings>
</component>
<component name="MessDetector">
<phpmd_settings>
<phpmd_by_interpreter asDefaultInterpreter="true" interpreter_id="6adcaaf8-6d8b-41cc-8523-d95f7e166ea1" timeout="30000" />
</phpmd_settings>
</component>
<component name="MessDetectorOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PHPCSFixerOptionsConfiguration">
<option name="allowRiskyRules" value="true" />
<option name="codingStandard" value="Custom" />
<option name="rulesetPath" value="$PROJECT_DIR$/.php-cs-fixer.php" />
<option name="transferred" value="true" />
</component>
<component name="PHPCodeSnifferOptionsConfiguration">
<option name="highlightLevel" value="WARNING" />
<option name="transferred" value="true" />
</component>
<component name="PhpCSFixer">
<phpcsfixer_settings>
<phpcs_fixer_by_interpreter asDefaultInterpreter="true" interpreter_id="6adcaaf8-6d8b-41cc-8523-d95f7e166ea1" standards="PSR1;PSR2;Symfony;DoctrineAnnotation;PHP70Migration;PHP71Migration" tool_path="W:/devel/turorials/patterns/vendor/bin/php-cs-fixer" timeout="30000" />
<PhpCSFixerConfiguration tool_path="$PROJECT_DIR$/vendor/bin/php-cs-fixer" />
</phpcsfixer_settings>
</component>
<component name="PhpCodeSniffer">
<phpcs_settings>
<phpcs_by_interpreter asDefaultInterpreter="true" interpreter_id="6adcaaf8-6d8b-41cc-8523-d95f7e166ea1" timeout="30000" />
</phpcs_settings>
</component>
<component name="PhpIncludePathManager">
<include_path>
<path value="$PROJECT_DIR$/vendor/symfony/console" />
<path value="$PROJECT_DIR$/vendor/symfony/deprecation-contracts" />
<path value="$PROJECT_DIR$/vendor/symfony/event-dispatcher" />
<path value="$PROJECT_DIR$/vendor/symfony/event-dispatcher-contracts" />
<path value="$PROJECT_DIR$/vendor/symfony/filesystem" />
<path value="$PROJECT_DIR$/vendor/symfony/finder" />
<path value="$PROJECT_DIR$/vendor/composer" />
<path value="$PROJECT_DIR$/vendor/symfony/options-resolver" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-ctype" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-grapheme" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-normalizer" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-mbstring" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php80" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php81" />
<path value="$PROJECT_DIR$/vendor/symfony/process" />
<path value="$PROJECT_DIR$/vendor/symfony/service-contracts" />
<path value="$PROJECT_DIR$/vendor/symfony/stopwatch" />
<path value="$PROJECT_DIR$/vendor/symfony/string" />
<path value="$PROJECT_DIR$/vendor/clue/ndjson-react" />
<path value="$PROJECT_DIR$/vendor/evenement/evenement" />
<path value="$PROJECT_DIR$/vendor/psr/container" />
<path value="$PROJECT_DIR$/vendor/react/cache" />
<path value="$PROJECT_DIR$/vendor/psr/event-dispatcher" />
<path value="$PROJECT_DIR$/vendor/react/child-process" />
<path value="$PROJECT_DIR$/vendor/psr/log" />
<path value="$PROJECT_DIR$/vendor/react/dns" />
<path value="$PROJECT_DIR$/vendor/react/event-loop" />
<path value="$PROJECT_DIR$/vendor/react/promise" />
<path value="$PROJECT_DIR$/vendor/sebastian/diff" />
<path value="$PROJECT_DIR$/vendor/react/socket" />
<path value="$PROJECT_DIR$/vendor/friendsofphp/php-cs-fixer" />
<path value="$PROJECT_DIR$/vendor/react/stream" />
<path value="$PROJECT_DIR$/vendor/fidry/cpu-core-counter" />
</include_path>
</component>
<component name="PhpProjectSharedConfiguration" php_language_level="8.3" />
<component name="PhpStan">
<PhpStan_settings>
<phpstan_by_interpreter asDefaultInterpreter="true" interpreter_id="6adcaaf8-6d8b-41cc-8523-d95f7e166ea1" timeout="60000" />
</PhpStan_settings>
</component>
<component name="PhpStanOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="Psalm">
<Psalm_settings>
<psalm_fixer_by_interpreter asDefaultInterpreter="true" interpreter_id="6adcaaf8-6d8b-41cc-8523-d95f7e166ea1" timeout="60000" />
</Psalm_settings>
</component>
<component name="PsalmOptionsConfiguration">
<option name="transferred" value="true" />
</component>
</project>

6
.idea/symfony2.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Symfony2PluginSettings">
<option name="dismissEnableNotification" value="true" />
</component>
</project>

6
.idea/vcs.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

1
.php-cs-fixer.cache Normal file

File diff suppressed because one or more lines are too long

28
.php-cs-fixer.php Normal file
View File

@ -0,0 +1,28 @@
<?php
declare(strict_types = 1);
use PhpCsFixer\Config;
use PhpCsFixer\Finder;
use PhpCsFixer\Runner\Parallel\ParallelConfigFactory;
$finder = (new Finder())->in([
__DIR__ . '/src',
])->exclude(['vendor'])->name('*.php')->ignoreDotFiles(true);
return (new Config())->setRules([
'@PSR12' => true,
'declare_equal_normalize' => [
'space' => 'single',
],
'single_line_empty_body' => true,
// 'group_to_single_imports' => false,
'binary_operator_spaces' => [
'default' => 'single_space',
'operators' => [
'=>' => null,
],
],
])->setParallelConfig(ParallelConfigFactory::detect())->setUsingCache(true)->setRiskyAllowed(true)->setFinder(
$finder
)->setIndent(' ')->setLineEnding("\n");

1
.php-version Normal file
View File

@ -0,0 +1 @@
8.3

0
README.md Normal file
View File

48
code/singleton.php Normal file
View File

@ -0,0 +1,48 @@
<?php
/**
* @package: patterns
* @author: Yevhen Odynets
* @date: 2025-07-03
* @time: 08:39
*/
declare(strict_types = 1);
use Pattern\Creational\{Singleton, Sub\Single};
/**
* The client code.
*
* @noinspection ForgottenDebugOutputInspection
*/
function clientCode(): void
{
$output = [
'where' => trace(),
's1' => Singleton::getInstance('s1'),
's2' => Singleton::getInstance('s2'),
];
if ($output['s1'] === $output['s2']) {
$output['message'] = "Singleton works, both variables contain the same instance.";
} else {
$output['message'] = "Singleton failed, variables contain different instances.";
}
$output['s1']->setValue('value set from s1@Singleton::class');
dump($output['s1']->getValue());
$output['s2']->setValue('value set from s2@Singleton::class');
dump($output, $output['s1']->getValue(), $output['s2']->getValue());
}
clientCode();
$single = Single::getInstance('from subclass');
$single->setValue('value set from Single::class')->childish();
$singleton = Singleton::getInstance('from Singleton');
/** @noinspection ForgottenDebugOutputInspection */
dump($single->getValue(), $singleton->getValue());

24
composer.json Normal file
View File

@ -0,0 +1,24 @@
{
"name": "the-amok/patterns",
"autoload": {
"psr-4": {
"": "src/"
}
},
"authors": [
{
"name": "Yevhen Odynets",
"email": "dev@amok.space"
}
],
"require": {
"php": "8.3.*"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.76"
},
"scripts": {
"cs": "php-cs-fixer --config=./.php-cs-fixer.php check -v",
"cs:fix": "php-cs-fixer --config=./.php-cs-fixer.php fix -v"
}
}

2550
composer.lock generated Normal file

File diff suppressed because it is too large Load Diff

127
public/assets/css/agate.css Normal file
View File

@ -0,0 +1,127 @@
pre code.hljs {
display: block;
overflow-x: auto;
padding: 1em
}
code.hljs {
padding: 3px 5px
}
/*!
Theme: Agate
Author: (c) Taufik Nurrohman <hi@taufik-nurrohman.com>
Maintainer: @taufik-nurrohman
Updated: 2021-04-24
#333
#62c8f3
#7bd694
#888
#a2fca2
#ade5fc
#b8d8a2
#c6b4f0
#d36363
#fc9b9b
#fcc28c
#ffa
#fff
*/
.hljs {
background: #333;
color: #fff
}
.hljs-doctag,
.hljs-meta-keyword,
.hljs-name,
.hljs-strong {
font-weight: bold
}
.hljs-code,
.hljs-emphasis {
font-style: italic
}
.hljs-section,
.hljs-tag {
color: #62c8f3
}
.hljs-selector-class,
.hljs-selector-id,
.hljs-template-variable,
.hljs-variable {
color: #ade5fc
}
.hljs-meta-string,
.hljs-string {
color: #a2fca2
}
.hljs-attr,
.hljs-quote,
.hljs-selector-attr {
color: #7bd694
}
.hljs-tag .hljs-attr {
color: inherit
}
.hljs-attribute,
.hljs-title,
.hljs-type {
color: #ffa
}
.hljs-number,
.hljs-symbol {
color: #d36363
}
.hljs-bullet,
.hljs-template-tag {
color: #b8d8a2
}
.hljs-built_in,
.hljs-keyword,
.hljs-literal,
.hljs-selector-tag {
color: #fcc28c
}
.hljs-code,
.hljs-comment,
.hljs-formula {
color: #888
}
.hljs-link,
.hljs-selector-pseudo,
.hljs-regexp {
color: #c6b4f0
}
.hljs-meta {
color: #fc9b9b
}
.hljs-deletion {
background: #fc9b9b;
color: #333
}
.hljs-addition {
background: #a2fca2;
color: #333
}
/* Purposely ignored */
.hljs-operator,
.hljs-params,
.hljs-property,
.hljs-punctuation {
}
.hljs-subst {
color: #fff
}
/* This applies only if HTML auto-merging plugin is enabled by user (#2889) */
.hljs a {
color: inherit
}
.hljs a:focus,
.hljs a:hover {
color: inherit;
text-decoration: underline
}
.hljs mark {
background: #555;
color: inherit
}

20
public/assets/css/agate.min.css vendored Normal file
View File

@ -0,0 +1,20 @@
pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}/*!
Theme: Agate
Author: (c) Taufik Nurrohman <hi@taufik-nurrohman.com>
Maintainer: @taufik-nurrohman
Updated: 2021-04-24
#333
#62c8f3
#7bd694
#888
#a2fca2
#ade5fc
#b8d8a2
#c6b4f0
#d36363
#fc9b9b
#fcc28c
#ffa
#fff
*/.hljs{background:#333;color:#fff}.hljs-doctag,.hljs-meta-keyword,.hljs-name,.hljs-strong{font-weight:700}.hljs-code,.hljs-emphasis{font-style:italic}.hljs-section,.hljs-tag{color:#62c8f3}.hljs-selector-class,.hljs-selector-id,.hljs-template-variable,.hljs-variable{color:#ade5fc}.hljs-meta-string,.hljs-string{color:#a2fca2}.hljs-attr,.hljs-quote,.hljs-selector-attr{color:#7bd694}.hljs-tag .hljs-attr{color:inherit}.hljs-attribute,.hljs-title,.hljs-type{color:#ffa}.hljs-number,.hljs-symbol{color:#d36363}.hljs-bullet,.hljs-template-tag{color:#b8d8a2}.hljs-built_in,.hljs-keyword,.hljs-literal,.hljs-selector-tag{color:#fcc28c}.hljs-code,.hljs-comment,.hljs-formula{color:#888}.hljs-link,.hljs-regexp,.hljs-selector-pseudo{color:#c6b4f0}.hljs-meta{color:#fc9b9b}.hljs-deletion{background:#fc9b9b;color:#333}.hljs-addition{background:#a2fca2;color:#333}.hljs-subst{color:#fff}.hljs a{color:inherit}.hljs a:focus,.hljs a:hover{color:inherit;text-decoration:underline}.hljs mark{background:#555;color:inherit}

View File

@ -0,0 +1,89 @@
pre code.hljs {
display: block;
overflow-x: auto;
padding: 1em
}
code.hljs {
padding: 3px 5px
}
/*
Theme: Srcery
Description: Srcery dark color scheme for highlight.js
Author: Chen Bin <chen.bin@gmail.com>
Maintainer: @redguardtoo
Website: https://srcery-colors.github.io/
Date: 2021-04-13
*/
.hljs {
background: #1C1B19;
/* Black */
color: #FCE8C3/* Bright White */
}
/* Bright White */
.hljs-subst,
.hljs-quote,
.hljs-literal {
color: #FCE8C3
}
/* Bright Blue */
.hljs-type,
.hljs-symbol {
color: #68A8E4
}
/* Red */
.hljs-keyword,
.hljs-deletion {
color: #EF2F27
}
/* Yellow */
.hljs-name,
.hljs-function,
.hljs-attribute,
.hljs-selector-attr,
.hljs-selector-id,
.hljs-selector-class,
.hljs-selector-pseudo,
.hljs-section,
.hljs-title {
color: #FBB829
}
/* Cyan */
.hljs-code,
.hljs-variable,
.hljs-property,
.hljs-template-variable,
.hljs-class {
color: #0AAEB3
}
/* Bright Green */
.hljs-string,
.hljs-regexp,
.hljs-bullet,
.hljs-addition {
color: #98BC37
}
/* Bright Magenta */
.hljs-built_in,
.hljs-params {
color: #FF5C8F
}
/* Blue */
.hljs-template-tag,
.hljs-selector-tag {
color: #2C78BF
}
/* Bright Black */
.hljs-link,
.hljs-number,
.hljs-comment,
.hljs-meta {
color: #918175
}
.hljs-emphasis {
font-style: italic
}
.hljs-strong {
font-weight: bold
}
/* @see https://github.com/srcery-colors/srcery-emacs for reference */

1
public/assets/css/srcery.min.css vendored Normal file
View File

@ -0,0 +1 @@
pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{background:#1c1b19;color:#fce8c3}.hljs-literal,.hljs-quote,.hljs-subst{color:#fce8c3}.hljs-symbol,.hljs-type{color:#68a8e4}.hljs-deletion,.hljs-keyword{color:#ef2f27}.hljs-attribute,.hljs-function,.hljs-name,.hljs-section,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id,.hljs-selector-pseudo,.hljs-title{color:#fbb829}.hljs-class,.hljs-code,.hljs-property,.hljs-template-variable,.hljs-variable{color:#0aaeb3}.hljs-addition,.hljs-bullet,.hljs-regexp,.hljs-string{color:#98bc37}.hljs-built_in,.hljs-params{color:#ff5c8f}.hljs-selector-tag,.hljs-template-tag{color:#2c78bf}.hljs-comment,.hljs-link,.hljs-meta,.hljs-number{color:#918175}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}

1244
public/assets/js/highlight.min.js vendored Normal file

File diff suppressed because one or more lines are too long

36
public/assets/js/stylus.min.js vendored Normal file

File diff suppressed because one or more lines are too long

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

42
public/index.php Normal file
View File

@ -0,0 +1,42 @@
<!doctype html>
<html lang="uk">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Патерни</title>
<link rel="stylesheet" href="assets/css/agate.min.css">
<script src="assets/js/highlight.min.js"></script>
<script src="assets/js/stylus.min.js"></script>
<style>
pre {
font-family: Consolas, monospace;
}
</style>
</head>
<body>
<main>
<?php
use Pattern\Creational\Singleton;
require '../vendor/autoload.php';
require '../src/helpers.php';
// Creational patterns
require '../code/singleton.php';
?>
</main>
<script>hljs.highlightAll();</script>
</body>
</html>

1
serve.bat Normal file
View File

@ -0,0 +1 @@
C:\Users\theAmok\.config\herd\bin\php83\php -S localhost:8008 -t public/

View File

@ -0,0 +1,17 @@
<?php
/**
* @package: patterns
* @author: Yevhen Odynets
* @date: 2025-07-03
* @time: 07:36
*/
declare(strict_types = 1);
namespace Contracts;
interface Loggable
{
public static function getInstance(): static;
}

View File

@ -0,0 +1,17 @@
<?php
/**
* @package: patterns
* @author: Yevhen Odynets
* @date: 2025-07-03
* @time: 10:58
*/
declare(strict_types = 1);
namespace Contracts;
interface SingleInterface
{
public function childish(): void;
}

View File

@ -0,0 +1,105 @@
<?php
/**
* @package: patterns
* @author: Yevhen Odynets
* @date: 2025-07-03
* @time: 07:00
*/
declare(strict_types = 1);
namespace Pattern\Creational;
use RuntimeException;
/**
* The Singleton class defines the `GetInstance` method that serves as an
* alternative to constructor and lets clients access the same instance of this
* class over and over.
*/
class Singleton
{
/**
* The Singleton's instance is stored in a static field. This field is an
* array, because we'll allow our Singleton to have subclasses. Each item in
* this array will be an instance of a specific Singleton's subclass. You'll
* see how this works in a moment.
*/
private static array $instances = [];
public ?string $value = null;
/**
* The Singleton's constructor should always be private to prevent direct
* construction calls with the `new` operator.
*/
protected function __construct() {}
/**
* This is the static method that controls the access to the singleton
* instance. On the first run, it creates a singleton object and places it
* into the static field. On subsequent runs, it returns the client existing
* object stored in the static field.
*
* This implementation lets you subclass the Singleton class while keeping
* just one instance of each subclass around.
*/
public static function getInstance(?string $message = null): Singleton
{
$cls = static::class;
/** @noinspection ForgottenDebugOutputInspection */
dump(trim($message . ': ' . $cls, ' :'));
if (!isset(self::$instances[$cls])) {
self::$instances[$cls] = new static();
}
return self::$instances[$cls];
}
/**
* Singletons should not be restorable from strings.
*/
public function __wakeup()
{
throw new RuntimeException("Cannot unserialize a singleton.");
}
/**
* Finally, any singleton should define some business logic, which can be
* executed on its instance.
*/
public function someBusinessLogic(): void
{
echo 'I AM SINGLETON: ' . date('H:i:s') . '<br>';
}
/**
* Singletons should not be cloneable.
*/
protected function __clone() {}
/**
* @return string|null
*/
public function getValue(): ?string
{
return $this->value;
}
/**
* @param string|null $value
*
* @return $this
*/
public function setValue(?string $value): static
{
$this->value = $value;
return $this;
}
}

View File

@ -0,0 +1,24 @@
<?php
/**
* @package: patterns
* @author: Yevhen Odynets
* @date: 2025-07-03
* @time: 10:22
*/
//phpcs:ignore
declare(strict_types = 1);
namespace Pattern\Creational\Sub;
use Contracts\SingleInterface;
use Pattern\Creational\Singleton;
class Single extends Singleton implements SingleInterface
{
public function childish(): void
{
/** @noinspection ForgottenDebugOutputInspection */
dump(__METHOD__);
}
}

136
src/Service/Logger.php Normal file
View File

@ -0,0 +1,136 @@
<?php
/**
* @package: patterns
*
* @author: Yevhen Odynets
*
* @date: 2025-07-02
*
* @time: 22:30
*/
declare(strict_types = 1);
namespace Service;
use Contracts\Loggable;
use Psr\Log\LoggerInterface;
use RuntimeException;
use function in_array;
use function sprintf;
use const FILE_APPEND;
use const PHP_EOL;
class Logger implements Loggable
{
public const string LOG_FILE = '../storage/logs/main.txt';
public const array ALLOWED_LOG_TYPES
= [
'file',
'error_log',
];
private static ?Logger $instance = null;
private ?string $logType = null;
private ?string $dateFormat = null;
private ?string $prefix = null;
private function __construct() {}
public static function getInstance(): static
{
if (self::$instance) {
self::$instance = new static();
}
return self::$instance;
}
public function getLogType(): string
{
if (! $this->logType) {
throw new RuntimeException('log type is null');
}
return $this->logType;
}
/**
* @return $this
*/
public function setLogType(string $logType): static
{
if (! in_array($logType, self::ALLOWED_LOG_TYPES)) {
throw new RuntimeException('undefined log type: ' . $logType);
}
$this->logType = $logType;
return $this;
}
public function log(string $data): void
{
$prefix = $this->getPrefix();
$message = sprintf(
'%s: %s%s',
date($this->getDateFormat()),
empty($prefix) ? '' : $prefix . ' ',
$data . PHP_EOL
);
if ('file' === $this->logType) {
file_put_contents(self::LOG_FILE, $message, FILE_APPEND);
} elseif ('error_log' === $this->logType) {
/* @noinspection ForgottenDebugOutputInspection */
error_log($message, 3, self::LOG_FILE);
}
}
public function getPrefix(): ?string
{
return $this->prefix;
}
/**
* @return $this
*/
public function setPrefix(?string $prefix): static
{
$this->prefix = $prefix;
return $this;
}
public function getDateFormat(): string
{
if (! $this->dateFormat) {
throw new RuntimeException('date format is null');
}
return $this->dateFormat;
}
/**
* @return $this
*/
public function setDateFormat(string $dateFormat): static
{
$this->dateFormat = $dateFormat;
return $this;
}
private function __clone() {}
}
///*$message = 'Message from delivery service';
//
//$logger = new Logger();
//$dateFormat = 'Y-m-d H:i:s' . (preg_match('/^win/i', PHP_OS) ? '' : '.u');
//$logger->setDateFormat($dateFormat)->setLogType('error_log');
//$logger->log($message);*/

36
src/helpers.php Normal file
View File

@ -0,0 +1,36 @@
<?php
/**
* @package: patterns
* @author: Yevhen Odynets
* @date: 2025-07-03
* @time: 09:07
*/
declare(strict_types = 1);
/**
* @param ...$vars
*
* @return void
*/
function dump(...$vars): void
{
echo '<pre><code class="language-stylus">';
var_dump(...$vars);
echo '</code></pre>';
}
/**
* @return string
*/
function trace(): string
{
$traced = debug_backtrace();
// Maybe this is useless, but anyway...
$offset = __FUNCTION__ === $traced[0]['function'] ? 1 : 0;
$traced = $traced[$offset];
return sprintf('%s@%s:%d', $traced['function'], $traced['file'], $traced['line']);
}