diff --git a/README.md b/README.md index ced835c..675a40a 100644 --- a/README.md +++ b/README.md @@ -51,9 +51,7 @@ After changing `post_status`, follow the same steps: re-run `bin/doctrine-fixtur Copy an existing set of these three files in the same category as a starting point, to match the established structure (FAQ block matching the `FAQPage` entries, etc.). -If the article body uses images (via `asset('uploads/article/' ~ article.id ~ '/filename.png')` in the `.html.twig`), just drop the image file anywhere under `public/uploads` - `bin/create-uploads-dir` (step 4) finds it by filename and copies it to the right place. No manual path/folder creation needed. - -Markdown articles reference images with a literal path instead, e.g. `![](/uploads/article/{post-id}/filename.png)` - `{post-id}` there is just a placeholder for whatever UUID the `Post` has when you write the file. `bin/create-uploads-dir` also scans `.md` files: it resolves the real `Post` by slug and, if the UUID hardcoded in the file doesn't match the post's actual current UUID (which happens whenever fixtures assign it a new one, e.g. in a fresh environment), rewrites the file to the real UUID and copies the image into the correct directory. +If the article body uses images (via `asset('uploads/article/filename.png')` in the `.html.twig`, or `![](/uploads/article/filename.png)` in the `.md`), just drop the image file anywhere under `public/uploads` - `bin/create-uploads-dir` (step 4) finds it by filename and copies it into the flat `public/uploads/article/` directory if it isn't already there. No per-article subfolder or post ID/UUID involved - every article image lives directly under `public/uploads/article/filename.png`, so the same literal path works across environments without drifting. ## 3. At deploy - run in this order @@ -62,8 +60,8 @@ php bin/doctrine-fixtures php bin/create-uploads-dir ``` -- `bin/doctrine-fixtures` loads `articles_cleaned.json` into the database, creating the `Post` entity (with its database-generated UUID) for the new article. -- `bin/create-uploads-dir` must run *after* it - it resolves the post by slug to get that UUID, creates `public/uploads/article/{post-id}/`, and copies each image referenced in the `.html.twig` there from wherever it already lives under `public/uploads`. It does the same for `.md` files, additionally correcting the UUID hardcoded in the file if it no longer matches the post's real one. +- `bin/doctrine-fixtures` loads `articles_cleaned.json` into the database, creating the `Post` entity for the new article. +- `bin/create-uploads-dir` scans every `.md` file under `public/md-articles/` for `/uploads/article/filename.ext` references and, for any that aren't already present in `public/uploads/article/`, copies the file there from wherever it already lives under `public/uploads` (matched by filename). It doesn't touch the database. ## 4. Regenerate the public artifacts - any order @@ -93,7 +91,7 @@ Steps to edit an existing article (change its status, text, or both) and get the - `public/md-articles/{category-slug}/{article-slug}.md` - `src/Blog/templates/page/blog-resource/{category-slug}/{article-slug}.html.twig` - `src/Blog/templates/page/JSON-LD/{category-slug}/{article-slug}.jsonld.twig` (only if it has hardcoded text outside of `article.*`/`meta.*` variables — most of its fields pull straight from the database and update automatically) -3. **Re-run the same commands as step 3 and step 4 above** (`bin/doctrine-fixtures`, then `bin/generate-feed` / `bin/sitemap` / `bin/generate-llms-full`) so the database and the generated artifacts reflect the change. `bin/create-uploads-dir` only needs to run again if you added a new image - it's also safe (and cheap) to run any time you suspect a `.md` file's hardcoded UUID has drifted from the post's real one. +3. **Re-run the same commands as step 3 and step 4 above** (`bin/doctrine-fixtures`, then `bin/generate-feed` / `bin/sitemap` / `bin/generate-llms-full`) so the database and the generated artifacts reflect the change. `bin/create-uploads-dir` only needs to run again if you added a new image. ## How to move an article to a different category diff --git a/bin/create-uploads-dir b/bin/create-uploads-dir index 03cc96b..ebddcd0 100755 --- a/bin/create-uploads-dir +++ b/bin/create-uploads-dir @@ -3,40 +3,26 @@ declare(strict_types=1); -use Doctrine\ORM\EntityManager; -use Light\Blog\Entity\Post; - chdir(__DIR__ . '/../'); -require 'vendor/autoload.php'; - -$templatesDir = 'src/Blog/templates/page/blog-resource'; -$publicDir = 'public'; -$uploadsDir = $publicDir . '/uploads'; -$articleDir = $uploadsDir . '/article'; -$limit = null; +$publicDir = 'public'; +$mdArticlesDir = $publicDir . '/md-articles'; +$articleDir = $publicDir . '/uploads/article'; -if (isset($argv[1])) { - if (! ctype_digit($argv[1]) || (int) $argv[1] < 1) { - fwrite(STDERR, sprintf("Invalid file limit '%s'. Expected a positive integer.%s", $argv[1], PHP_EOL)); - exit(1); - } - $limit = (int) $argv[1]; +if (! is_dir($mdArticlesDir)) { + fwrite(STDERR, sprintf("Directory '%s' not found%s", $mdArticlesDir, PHP_EOL)); + exit(1); } -if (! is_dir($templatesDir)) { - fwrite(STDERR, sprintf("Directory '%s' not found%s", $templatesDir, PHP_EOL)); +if (! is_dir($articleDir) && ! mkdir($articleDir, 0775, true) && ! is_dir($articleDir)) { + fwrite(STDERR, sprintf("Failed to create directory '%s'%s", $articleDir, PHP_EOL)); exit(1); } -$container = require 'config/container.php'; -$entityManager = $container->get(EntityManager::class); -$postRepository = $entityManager->getRepository(Post::class); - /** * @return array */ -function indexUploadSources(string $publicDir): array +function indexUploadSources(string $publicDir, string $articleDir): array { $index = []; @@ -49,9 +35,14 @@ function indexUploadSources(string $publicDir): array continue; } + $pathname = $file->getPathname(); + if (str_starts_with($pathname, $articleDir . '/')) { + continue; + } + $basename = $file->getFilename(); if (! isset($index[$basename])) { - $index[$basename] = $file->getPathname(); + $index[$basename] = $pathname; } } @@ -59,93 +50,52 @@ function indexUploadSources(string $publicDir): array } /** - * @return list + * @return list */ -function extractArticleImageRefs(string $contents): array +function extractArticleImageFilenames(string $contents): array { - $pattern = '/uploads\/article\/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\/([^)\]\s"\']+)/i'; - - preg_match_all($pattern, $contents, $matches, PREG_SET_ORDER); + $pattern = '/uploads\/article\/([^\/)\]\s"\']+)/i'; - $seen = []; - $refs = []; - - foreach ($matches as $match) { - $uuid = strtolower($match[1]); - $filename = $match[2]; - $key = $uuid . '/' . $filename; - - if (isset($seen[$key])) { - continue; - } - - $seen[$key] = true; - $refs[] = ['uuid' => $uuid, 'filename' => $filename]; - } + preg_match_all($pattern, $contents, $matches); - return $refs; + return array_values(array_unique($matches[1])); } -$sourceIndex = indexUploadSources($publicDir); +$sourceIndex = indexUploadSources($publicDir, $articleDir); -$pattern = '/~\s*article\.id\s*~\s*\'\/([^\']+)\'/'; - -$filesProcessed = 0; -$dirsCreated = 0; -$imagesCopied = 0; -$imagesMissing = 0; +$mdFilesProcessed = 0; +$imagesCopied = 0; +$imagesMissing = 0; -$templateIterator = new RecursiveIteratorIterator( - new RecursiveDirectoryIterator($templatesDir, FilesystemIterator::SKIP_DOTS) +$mdIterator = new RecursiveIteratorIterator( + new RecursiveDirectoryIterator($mdArticlesDir, FilesystemIterator::SKIP_DOTS) ); -foreach ($templateIterator as $file) { - if ($limit !== null && $filesProcessed >= $limit) { - break; - } - - if (! $file->isFile() || $file->getExtension() !== 'twig') { +foreach ($mdIterator as $file) { + if (! $file->isFile() || $file->getExtension() !== 'md') { continue; } - $path = $file->getPathname(); - $slug = preg_replace('/\.html\.twig$/', '', $file->getFilename()); - $contents = file_get_contents($path); + $contents = file_get_contents($file->getPathname()); if ($contents === false) { continue; } - preg_match_all($pattern, $contents, $matches); - $filenames = array_unique($matches[1] ?? []); + $filenames = extractArticleImageFilenames($contents); if ($filenames === []) { continue; } - $post = $postRepository->findOneBy(['slug' => $slug]); - if ($post === null) { - printf("No Post found for slug '%s' (%s), skipping%s", $slug, $path, PHP_EOL); - continue; - } - - $filesProcessed++; - - $targetDir = $articleDir . '/' . $post->getId()->toString(); - if (! is_dir($targetDir)) { - if (! mkdir($targetDir, 0775, true) && ! is_dir($targetDir)) { - fwrite(STDERR, sprintf("Failed to create directory '%s'%s", $targetDir, PHP_EOL)); - continue; - } - $dirsCreated++; - } + $mdFilesProcessed++; foreach ($filenames as $filename) { - $targetPath = $targetDir . '/' . $filename; + $targetPath = $articleDir . '/' . $filename; if (file_exists($targetPath)) { continue; } if (! isset($sourceIndex[$filename])) { - printf("Source image '%s' not found for %s%s", $filename, $path, PHP_EOL); + printf("Source image '%s' not found for %s%s", $filename, $file->getPathname(), PHP_EOL); $imagesMissing++; continue; } @@ -159,139 +109,12 @@ foreach ($templateIterator as $file) { } } -$mdArticlesDir = 'public/md-articles'; - -$mdFilesProcessed = 0; -$uuidsFixed = 0; -$mdDirsCreated = 0; -$mdImagesCopied = 0; -$mdImagesMissing = 0; - -if (is_dir($mdArticlesDir)) { - $mdIterator = new RecursiveIteratorIterator( - new RecursiveDirectoryIterator($mdArticlesDir, FilesystemIterator::SKIP_DOTS) - ); - - foreach ($mdIterator as $file) { - if (! $file->isFile() || $file->getExtension() !== 'md') { - continue; - } - - $path = $file->getPathname(); - $relative = ltrim(substr($path, strlen($mdArticlesDir)), '/'); - if (substr_count($relative, '/') !== 1) { - continue; - } - - $slug = preg_replace('/\.md$/', '', $file->getFilename()); - $contents = file_get_contents($path); - if ($contents === false) { - continue; - } - - $refs = extractArticleImageRefs($contents); - if ($refs === []) { - continue; - } - - $post = $postRepository->findOneBy(['slug' => $slug]); - if ($post === null) { - printf("No Post found for slug '%s' (%s), skipping%s", $slug, $path, PHP_EOL); - continue; - } - - $mdFilesProcessed++; - - $realUuid = $post->getId()->toString(); - $staleUuids = []; - - foreach ($refs as $ref) { - $refUuid = $ref['uuid']; - $filename = $ref['filename']; - - if ($refUuid !== $realUuid) { - $staleUuids[$refUuid] = true; - } - - $targetDir = $articleDir . '/' . $realUuid; - $targetPath = $targetDir . '/' . $filename; - - if (file_exists($targetPath)) { - continue; - } - - if (! is_dir($targetDir)) { - if (! mkdir($targetDir, 0775, true) && ! is_dir($targetDir)) { - fwrite(STDERR, sprintf("Failed to create directory '%s'%s", $targetDir, PHP_EOL)); - continue; - } - $mdDirsCreated++; - } - - $sourcePath = null; - if ($refUuid !== $realUuid) { - $stalePath = $articleDir . '/' . $refUuid . '/' . $filename; - if (file_exists($stalePath)) { - $sourcePath = $stalePath; - } - } - - if ($sourcePath === null && isset($sourceIndex[$filename])) { - $sourcePath = $sourceIndex[$filename]; - } - - if ($sourcePath === null) { - printf("Source image '%s' not found for %s%s", $filename, $path, PHP_EOL); - $mdImagesMissing++; - continue; - } - - if (! copy($sourcePath, $targetPath)) { - fwrite(STDERR, sprintf("Failed to copy '%s' to '%s'%s", $sourcePath, $targetPath, PHP_EOL)); - continue; - } - - $mdImagesCopied++; - } - - if ($staleUuids !== []) { - $updated = $contents; - foreach (array_keys($staleUuids) as $staleUuid) { - $updated = str_replace($staleUuid, $realUuid, $updated); - } - - if ($updated !== $contents) { - if (file_put_contents($path, $updated) === false) { - fwrite(STDERR, sprintf("Failed to update '%s'%s", $path, PHP_EOL)); - } else { - $uuidsFixed++; - printf("Corrected UUID in '%s'%s", $path, PHP_EOL); - } - } - } - } -} - printf( - "Done. %d twig template%s processed, %d director%s created, %d image%s copied, %d missing.%s" - . " %d markdown file%s processed, %d UUID%s corrected, %d director%s created," - . " %d image%s copied, %d missing.%s", - $filesProcessed, - $filesProcessed === 1 ? '' : 's', - $dirsCreated, - $dirsCreated === 1 ? 'y' : 'ies', + "Done. %d markdown file%s processed, %d image%s copied, %d missing.%s", + $mdFilesProcessed, + $mdFilesProcessed === 1 ? '' : 's', $imagesCopied, $imagesCopied === 1 ? '' : 's', $imagesMissing, - PHP_EOL, - $mdFilesProcessed, - $mdFilesProcessed === 1 ? '' : 's', - $uuidsFixed, - $uuidsFixed === 1 ? '' : 's', - $mdDirsCreated, - $mdDirsCreated === 1 ? 'y' : 'ies', - $mdImagesCopied, - $mdImagesCopied === 1 ? '' : 's', - $mdImagesMissing, PHP_EOL ); diff --git a/public/md-articles/architecture/configprovider-bootstrap-modern-php-applications.md b/public/md-articles/architecture/configprovider-bootstrap-modern-php-applications.md index 992aca4..b40342e 100644 --- a/public/md-articles/architecture/configprovider-bootstrap-modern-php-applications.md +++ b/public/md-articles/architecture/configprovider-bootstrap-modern-php-applications.md @@ -81,7 +81,7 @@ The ConfigProvider is automatically picked up by the framework during applicatio Below you can see how Mezzio and Dotkernel merge and use ConfigProviders to build the middleware pipeline and dependencies. -![](/uploads/article/019f8a80-cc92-7277-92c8-c0e68d81615f/ConfigProvider2.png) +![](/uploads/article/ConfigProvider2.png) ## Benefits diff --git a/public/md-articles/best-practice/aptana-set-svn-keywords.md b/public/md-articles/best-practice/aptana-set-svn-keywords.md index f9e55a1..64317cd 100644 --- a/public/md-articles/best-practice/aptana-set-svn-keywords.md +++ b/public/md-articles/best-practice/aptana-set-svn-keywords.md @@ -16,19 +16,19 @@ For example if you want to set the svn keyword property ***Id***: 1. In the file where you want to add the svn keyword property write **$Id$** -![](/uploads/article/019f8a80-cc86-73d9-a427-0621b2a55777/id-file-300x235.gif) +![](/uploads/article/id-file-300x235.gif) 2. Right click on the file, then follow Team -> Set Property...**Note**: *Set Property...* will not be active if you haven't first added the file to SVN: *Team*->*Add to Version Controller* -![](/uploads/article/019f8a80-cc86-73d9-a427-0621b2a55777/set-property-300x152.gif) +![](/uploads/article/set-property-300x152.gif) 3. Select **svn:keywords**, and write **Id** in the text field -![](/uploads/article/019f8a80-cc86-73d9-a427-0621b2a55777/svn-keywords-300x298.gif) +![](/uploads/article/svn-keywords-300x298.gif) When you make the SVN commit of the file, the *$Id$* keyword will be replaced with text in the format shown below: -![](/uploads/article/019f8a80-cc86-73d9-a427-0621b2a55777/id-file-svn-300x141.gif) +![](/uploads/article/id-file-svn-300x141.gif) ## FAQ diff --git a/public/md-articles/best-practice/svn-keywords-setup-in-php-ide-zend-studio.md b/public/md-articles/best-practice/svn-keywords-setup-in-php-ide-zend-studio.md index 3b39e34..aa8f135 100644 --- a/public/md-articles/best-practice/svn-keywords-setup-in-php-ide-zend-studio.md +++ b/public/md-articles/best-practice/svn-keywords-setup-in-php-ide-zend-studio.md @@ -62,7 +62,7 @@ For **above** Proprieties , apply **only** to project folder, **NOT** recursive 2. Select **All resources**. 3. Check the **Use filtration by the resource name** and add **Mask:** *.php. -[![svn-add](/uploads/article/019f8a80-cc87-71b3-80b8-478826d88044/svn-add.jpg)](/uploads/2013/02/svn-add.jpg) +[![svn-add](/uploads/article/svn-add.jpg)](/uploads/2013/02/svn-add.jpg) ## FAQ diff --git a/public/md-articles/design-pattern/naming-pattern-for-psr-15-handlers-in-dotkernel-applications.md b/public/md-articles/design-pattern/naming-pattern-for-psr-15-handlers-in-dotkernel-applications.md index 1c90737..fa5b415 100644 --- a/public/md-articles/design-pattern/naming-pattern-for-psr-15-handlers-in-dotkernel-applications.md +++ b/public/md-articles/design-pattern/naming-pattern-for-psr-15-handlers-in-dotkernel-applications.md @@ -61,7 +61,7 @@ We have chosen this wording for the performed actions (or CRUD): The image below contains the full list of handlers used in Dotkernel Admin. -![Dotkernel Naming Convention](https://www.dotkernel.com/wp-content/uploads/2025/05/naming-convention-1024x767.png) +![Dotkernel Naming Convention](/uploads/article/naming-convention-1024x767.png) ## A practical example diff --git a/public/md-articles/dotkernel/adding-a-cors-implementation-to-zend-expressive.md b/public/md-articles/dotkernel/adding-a-cors-implementation-to-zend-expressive.md index 7a55e4f..229a80f 100644 --- a/public/md-articles/dotkernel/adding-a-cors-implementation-to-zend-expressive.md +++ b/public/md-articles/dotkernel/adding-a-cors-implementation-to-zend-expressive.md @@ -26,7 +26,7 @@ This issue is most common when trying to get data (usually JSON) that you want t The error looks similar to the image below: -![](/uploads/article/019f8a80-cc4d-71e9-9af2-595b3eb4c793/Screenshot-2019-04-06-at-15.03.21-1024x165-1-1024x165.png) +![](/uploads/article/Screenshot-2019-04-06-at-15.03.21-1024x165-1-1024x165.png) ## The solution diff --git a/public/md-articles/dotkernel/adding-windows-10-os-and-browser-detection-in-dotkernel-projects.md b/public/md-articles/dotkernel/adding-windows-10-os-and-browser-detection-in-dotkernel-projects.md index 70cc5c1..dfab753 100644 --- a/public/md-articles/dotkernel/adding-windows-10-os-and-browser-detection-in-dotkernel-projects.md +++ b/public/md-articles/dotkernel/adding-windows-10-os-and-browser-detection-in-dotkernel-projects.md @@ -16,7 +16,7 @@ This article is the upgrade guide for applying that icon patch. ## Upgrade steps -![Icons Patch](/uploads/article/019f8a80-cc47-710e-9ef1-b2257262e376/icons.png) +![Icons Patch](/uploads/article/icons.png) *The new Icons listed in User and Admin Logins* 1. Make sure your project is running version **1.5.0** or **newer**. diff --git a/public/md-articles/dotkernel/doctrine-cache-using-symfony-cache.md b/public/md-articles/dotkernel/doctrine-cache-using-symfony-cache.md index 0e653cf..0c8ddcf 100644 --- a/public/md-articles/dotkernel/doctrine-cache-using-symfony-cache.md +++ b/public/md-articles/dotkernel/doctrine-cache-using-symfony-cache.md @@ -29,7 +29,7 @@ This reduces the time it takes to serve the content to the user because accessin > This article is a follow-up to the [previous article](https://www.dotkernel.com/how-to/doctrine-cache-in-mezzio-and-dotkernel/) where we tackled the caching topic. -![](/uploads/article/019f8a80-cc52-73f7-afe5-9255a3bb4681/sdasdadsa.drawio.png) +![](/uploads/article/sdasdadsa.drawio.png) In this article our focus will be on enabling the [dot-cache](https://packagist.org/packages/dotkernel/dot-cache) component and effectively implementing caching in [Dotkernel Admin](https://github.com/dotkernel/admin/). diff --git a/public/md-articles/dotkernel/highcharts-integration-in-dotkernel-1-6-0.md b/public/md-articles/dotkernel/highcharts-integration-in-dotkernel-1-6-0.md index e585e51..e2ce319 100644 --- a/public/md-articles/dotkernel/highcharts-integration-in-dotkernel-1-6-0.md +++ b/public/md-articles/dotkernel/highcharts-integration-in-dotkernel-1-6-0.md @@ -23,7 +23,7 @@ The admin includes samples built with Highcharts: - A column chart - A line chart -[![](/uploads/article/019f8a80-cc3b-71e4-913b-5c28321fc438/highcharts-1024x651.png)](/uploads/2012/05/highcharts.png) +[![](/uploads/article/highcharts-1024x651.png)](/uploads/2012/05/highcharts.png) The Highcharts library itself can be found in the **externals** directory of the project. diff --git a/public/md-articles/dotkernel/test-article.md b/public/md-articles/dotkernel/test-article.md index 722fa09..21ad1e4 100644 --- a/public/md-articles/dotkernel/test-article.md +++ b/public/md-articles/dotkernel/test-article.md @@ -16,7 +16,7 @@ This is a test article added to the dotkernel category for testing purposes. Thi ## Overview -![](/uploads/article/019fd6ae-4ce6-71cc-99aa-33741b77758c/test-article.png) +![](/uploads/article/test-article.png) This is a test article used for fixture and testing purposes. This article is now updated. diff --git a/public/md-articles/dotkernel/using-dotkernel-with-composer-dependencies.md b/public/md-articles/dotkernel/using-dotkernel-with-composer-dependencies.md index 3244bf8..a5130f8 100644 --- a/public/md-articles/dotkernel/using-dotkernel-with-composer-dependencies.md +++ b/public/md-articles/dotkernel/using-dotkernel-with-composer-dependencies.md @@ -76,7 +76,7 @@ Barcode::factory( Both examples render the same barcode. -[![Resulting barcode.](/uploads/article/019f8a80-cc48-70bf-ba9f-ddc6d1436f1a/zend.barcode.introduction.example-1.png)](/uploads/2016/04/zend.barcode.introduction.example-1.png) +[![Resulting barcode.](/uploads/article/zend.barcode.introduction.example-1.png)](/uploads/2016/04/zend.barcode.introduction.example-1.png) ### Tip diff --git a/public/md-articles/headless-platform/dotkernel-headless-platform-the-whats-hows-and-whys.md b/public/md-articles/headless-platform/dotkernel-headless-platform-the-whats-hows-and-whys.md index 337d468..b04e5f7 100644 --- a/public/md-articles/headless-platform/dotkernel-headless-platform-the-whats-hows-and-whys.md +++ b/public/md-articles/headless-platform/dotkernel-headless-platform-the-whats-hows-and-whys.md @@ -55,7 +55,7 @@ Using both API and Admin together brings several benefits: The file structure can be configured to use a **Core** module - a common code repository shared between API and Admin, ensuring entities and queries stay consistent. Entities (products, articles, etc.) are the building blocks of the application, and queries handle CRUD interactions with them. -![](/uploads/article/019f8a80-cc94-7123-80d3-9c21a30c19ea/Core2.png) +![](/uploads/article/Core2.png) ### Implement only the handlers you need @@ -68,9 +68,9 @@ API and Admin share a file structure, so becoming familiar with one makes the ot This means onboarding is easy and the applications can be maintained by fewer developers - potentially a single developer, at least initially. By contrast, an API+Angular approach often needs two developers working together to implement a new feature. -![](/uploads/article/019f8a80-cc94-7123-80d3-9c21a30c19ea/files-api.jpg) +![](/uploads/article/files-api.jpg) -![](/uploads/article/019f8a80-cc94-7123-80d3-9c21a30c19ea/files-admin-1.jpg) +![](/uploads/article/files-admin-1.jpg) ### Can satisfy any application size @@ -85,7 +85,7 @@ The Dotkernel architecture aims to support several architectural designs: - **Domain-Driven Design (DDD)** - the focus is on custom solutions for business logic; rather than building reusable services for a Service Oriented Architecture (SOA), only the specific components needed to satisfy requirements are implemented. - **Hexagonal Architecture** - divides a system into several loosely-coupled, interchangeable components (application core, database, user interface, test scripts, interfaces with other systems), as an alternative to traditional layered architecture. -![](/uploads/article/019f8a80-cc94-7123-80d3-9c21a30c19ea/Flow2.png) +![](/uploads/article/Flow2.png) ### Supported by an active community diff --git a/public/md-articles/headless-platform/dotkernel-queue-asynchronous-execution-in-dotkernel-headless-platform.md b/public/md-articles/headless-platform/dotkernel-queue-asynchronous-execution-in-dotkernel-headless-platform.md index 7b43665..2fbdf5f 100644 --- a/public/md-articles/headless-platform/dotkernel-queue-asynchronous-execution-in-dotkernel-headless-platform.md +++ b/public/md-articles/headless-platform/dotkernel-queue-asynchronous-execution-in-dotkernel-headless-platform.md @@ -67,7 +67,7 @@ The queue system has an active daemon that listens for TCP connections on a spec This supports a large number of requests per second without overloading. Operations are then scheduled for execution when resources are available, using the FIFO (First-In, First-Out) method, where the oldest request is processed first, followed by newer requests. -![](/uploads/article/019f8a80-cc97-70d1-a431-cb612f641c19/Queue-process2.png) +![](/uploads/article/Queue-process2.png) ## Main Features diff --git a/public/md-articles/headless-platform/implementing-time-based-one-time-password-totp-in-dotkernel.md b/public/md-articles/headless-platform/implementing-time-based-one-time-password-totp-in-dotkernel.md index 95c9a7c..55477de 100644 --- a/public/md-articles/headless-platform/implementing-time-based-one-time-password-totp-in-dotkernel.md +++ b/public/md-articles/headless-platform/implementing-time-based-one-time-password-totp-in-dotkernel.md @@ -62,7 +62,7 @@ Generates temporary, unique 6-digit codes that change every 30 seconds, via an A Below is a simplified flow for the 2FA with TOTP mechanism. -![](/uploads/article/019f8a80-cc99-7003-89fb-1a4493d92a4c/totp-flow.jpg) +![](/uploads/article/totp-flow.jpg) ## Installation steps @@ -121,18 +121,18 @@ The `_misc` folder in the code examples contains four required additions: 1. Navigate to the account profile (top-right image in Dotkernel Admin). A TOTP box with an "Enable TOTP" button is shown. -![](/uploads/article/019f8a80-cc99-7003-89fb-1a4493d92a4c/profile-totp-deactivated.jpg) +![](/uploads/article/profile-totp-deactivated.jpg) 2. Click "Enable TOTP". A QR code is displayed. An Authenticator app on a mobile device is required. -![](/uploads/article/019f8a80-cc99-7003-89fb-1a4493d92a4c/totp-activate-qr.jpg) +![](/uploads/article/totp-activate-qr.jpg) 3. Scan the QR code with the mobile device. 4. Enter the 6-digit code generated by the Authenticator app. The code refreshes every 30 seconds. 5. Save the recovery codes shown during activation in a secure location - each is usable only once. -![](/uploads/article/019f8a80-cc99-7003-89fb-1a4493d92a4c/totp-recovery-codes.jpg) +![](/uploads/article/totp-recovery-codes.jpg) 6. If the code is valid, the user is logged in and TOTP is activated for the account. @@ -141,7 +141,7 @@ A QR code is displayed. An Authenticator app on a mobile device is required. 1. Enter username and password as before. 2. Submit the current code from the Authenticator app, or alternatively a recovery code. -![](/uploads/article/019f8a80-cc99-7003-89fb-1a4493d92a4c/totp-ask-code.jpg) +![](/uploads/article/totp-ask-code.jpg) 3. On success, the user is logged in. diff --git a/public/md-articles/headless-platform/shared-core-submodule-in-dotkernel-headless-platform.md b/public/md-articles/headless-platform/shared-core-submodule-in-dotkernel-headless-platform.md index 7f0dbeb..948f99d 100644 --- a/public/md-articles/headless-platform/shared-core-submodule-in-dotkernel-headless-platform.md +++ b/public/md-articles/headless-platform/shared-core-submodule-in-dotkernel-headless-platform.md @@ -83,7 +83,7 @@ Once the shared Core submodule is separated and imported into each application, - Admin + Core - Queue + Core -![](/uploads/article/019f8a80-cc95-70fa-bdb7-28854eb6d673/core-queue2.png) +![](/uploads/article/core-queue2.png) > Each box in the image is a different Git repository. @@ -113,7 +113,7 @@ This design pattern ensures: As your platform expands, each new application connects to the Dotkernel Headless Platform via the central API which services everything the other applications require. This ensures consistency throughout your platform, while allowing any number of outside connections as requirements arise. -![](/uploads/article/019f8a80-cc95-70fa-bdb7-28854eb6d673/api-comms4-2.png) +![](/uploads/article/api-comms4-2.png) ## FAQ diff --git a/public/md-articles/php-development/database-seeding-doctrine-data-fixtures-vs-phinx.md b/public/md-articles/php-development/database-seeding-doctrine-data-fixtures-vs-phinx.md index 33e164c..912cbcb 100644 --- a/public/md-articles/php-development/database-seeding-doctrine-data-fixtures-vs-phinx.md +++ b/public/md-articles/php-development/database-seeding-doctrine-data-fixtures-vs-phinx.md @@ -102,7 +102,7 @@ php bin/console It should print out all the doctrine CLI commands available, including our fixtures commands. -![](/uploads/article/019f8a80-cc6c-71e3-a52c-9a9b1a204472/Screenshot-2022-08-30-at-19.14.14-1024x334.png) +![](/uploads/article/Screenshot-2022-08-30-at-19.14.14-1024x334.png) ## Usage @@ -112,7 +112,7 @@ It should print out all the doctrine CLI commands available, including our fixtu php bin/doctrine fixtures:list ``` -![](/uploads/article/019f8a80-cc6c-71e3-a52c-9a9b1a204472/Screenshot-2022-08-30-at-19.22.45-1024x147.png) +![](/uploads/article/Screenshot-2022-08-30-at-19.22.45-1024x147.png) By using this command you can check the execution order of your fixtures before executing them. @@ -276,7 +276,7 @@ Notice how `UserLoader.php` implements 2 interfaces, `FixtureInterface` and `Dep The method `getDependencies()` returns an array containing the dependencies (fixtures) that need to be executed prior to the current one. After running all the fixtures using `php bin/doctrine fixtures:execute` the output should look like this: -![](/uploads/article/019f8a80-cc6c-71e3-a52c-9a9b1a204472/Screenshot-2022-08-30-at-20.39.19.png) +![](/uploads/article/Screenshot-2022-08-30-at-20.39.19.png) `RoleLoader` was executed before `UserLoader` because `UserLoader` had `RoleLoader` as a dependency. diff --git a/public/md-articles/php-development/using-php-7-express-in-zend-studio-13.md b/public/md-articles/php-development/using-php-7-express-in-zend-studio-13.md index 45a4a6f..70b7b46 100644 --- a/public/md-articles/php-development/using-php-7-express-in-zend-studio-13.md +++ b/public/md-articles/php-development/using-php-7-express-in-zend-studio-13.md @@ -27,7 +27,7 @@ If you want to create a new project for testing instead of modifying the origina Choosing the PHP 7 option will hide the PHP 7 Express feature, because Zend Studio assumes a PHP 7 project doesn't need compatibility checks, but if the project is actually using a different version of PHP, compatibility issues might appear. Long story short: use the exact PHP version your project is using at project creation. -[![The New Local PHP Project dialog in Zend Studio 13](/uploads/article/019f8a80-cc69-7286-91c9-b075c0b9be59/Screenshot-2015-12-22-16.21.56.png)](/uploads/2015/12/Screenshot-2015-12-22-16.21.56.png) The "New Local PHP Project" dialog in Zend Studio 13 and the PHP version selection +[![The New Local PHP Project dialog in Zend Studio 13](/uploads/article/Screenshot-2015-12-22-16.21.56.png)](/uploads/2015/12/Screenshot-2015-12-22-16.21.56.png) The "New Local PHP Project" dialog in Zend Studio 13 and the PHP version selection ## The 'PHP Interpreter' Selection @@ -39,7 +39,7 @@ To check and modify the PHP Interpreter: - The PHP -> Interpreter option should show up. - If you only need a specific interpreter for a specific project, check "Enable Project specific settings" - this way you won't affect the other projects in the current workspace. -[![Zend Studio PHP Interpreter Dialog](/uploads/article/019f8a80-cc69-7286-91c9-b075c0b9be59/zftest.png)](/uploads/2015/12/zftest.png) Zend Studio PHP Interpreter Dialog +[![Zend Studio PHP Interpreter Dialog](/uploads/article/zftest.png)](/uploads/2015/12/zftest.png) Zend Studio PHP Interpreter Dialog The PHP 7 Express feature should now show up. @@ -64,7 +64,7 @@ Using PHP 7 Express is very easy: After the analysis is done, the PHP 7 Express view (or tab) appears in the bottom pane in Zend Studio, depending on the perspective. -[![Zend Framework 1 compatibility issues with PHP7](/uploads/article/019f8a80-cc69-7286-91c9-b075c0b9be59/php7errors.png)](/uploads/2015/12/php7errors.png) Zend Framework 1 compatibility issues with PHP7 +[![Zend Framework 1 compatibility issues with PHP7](/uploads/article/php7errors.png)](/uploads/2015/12/php7errors.png) Zend Framework 1 compatibility issues with PHP7 ## FAQ diff --git a/public/md-articles/php-development/version-control-ignore-patterns-in-zend-studio.md b/public/md-articles/php-development/version-control-ignore-patterns-in-zend-studio.md index 5f2f833..ede61f0 100644 --- a/public/md-articles/php-development/version-control-ignore-patterns-in-zend-studio.md +++ b/public/md-articles/php-development/version-control-ignore-patterns-in-zend-studio.md @@ -26,7 +26,7 @@ In order to globally manage the [Ignored Resources](https://www.dotkernel.com/be This is especially useful when you have both Git and SVN projects in your workspace, and also when you tend to be less careful about your code and workspace. Also, on each project, you can use either the global ignored patterns or specific ones. -[![ignore-patterns](/uploads/article/019f8a80-cc67-73be-b359-c0cc3c3adbed/ignore-patterns.png)](/uploads/2013/04/ignore-patterns.png) +[![ignore-patterns](/uploads/article/ignore-patterns.png)](/uploads/2013/04/ignore-patterns.png) ## FAQ diff --git a/public/md-articles/phpstorm/code-quality-how-to-setup-phpcs-in-phpstorm.md b/public/md-articles/phpstorm/code-quality-how-to-setup-phpcs-in-phpstorm.md index 3e31b3d..61eea5d 100644 --- a/public/md-articles/phpstorm/code-quality-how-to-setup-phpcs-in-phpstorm.md +++ b/public/md-articles/phpstorm/code-quality-how-to-setup-phpcs-in-phpstorm.md @@ -18,7 +18,7 @@ This article gives separate setup steps for a freshly cloned project versus an e PHP_CodeSniffer or phpcs is a tool that helps developers maintain a specific standard in the way they write code. In order to be able to provide relevant information, phpcs needs to be configured correctly in PHPStorm (see image). -![](/uploads/article/019f8a80-cc90-7160-853d-18cb7411b9ff/image.png) +![](/uploads/article/image.png) Whether you just cloned or you are already working on a project, follow the below guide on how to prepare your environment. @@ -43,19 +43,19 @@ There, if Coding standard is set to Custom and the field next to it contains the After you have the above configurations, you should start seeing information in the top-right corner of the editor. -![](/uploads/article/019f8a80-cc90-7160-853d-18cb7411b9ff/image-1-1024x83.png) +![](/uploads/article/image-1-1024x83.png) Once PHPStorm has finished analyzing the opened file, you should see either a green tick (meaning no errors) -![](/uploads/article/019f8a80-cc90-7160-853d-18cb7411b9ff/image-2-1024x66.png) +![](/uploads/article/image-2-1024x66.png) or a count of all the errors, warnings, and typos. -![](/uploads/article/019f8a80-cc90-7160-853d-18cb7411b9ff/image-3.png) +![](/uploads/article/image-3.png) Clicking on them will open a section where you get detailed information on each item, their location, and recommendations on how to fix them. -![](/uploads/article/019f8a80-cc90-7160-853d-18cb7411b9ff/image-5.png) +![](/uploads/article/image-5.png) ## FAQ diff --git a/public/uploads/article/019ee018-20e9-73f6-91a3-b4ed4a5f974b/ConfigProvider2.png b/public/uploads/article/ConfigProvider2.png similarity index 100% rename from public/uploads/article/019ee018-20e9-73f6-91a3-b4ed4a5f974b/ConfigProvider2.png rename to public/uploads/article/ConfigProvider2.png diff --git a/public/uploads/article/019ee018-20e9-73f6-91a3-b4ed4c13c510/Core2.png b/public/uploads/article/Core2.png similarity index 100% rename from public/uploads/article/019ee018-20e9-73f6-91a3-b4ed4c13c510/Core2.png rename to public/uploads/article/Core2.png diff --git a/public/uploads/article/019ee018-20e9-73f6-91a3-b4ed4c13c510/Flow2.png b/public/uploads/article/Flow2.png similarity index 100% rename from public/uploads/article/019ee018-20e9-73f6-91a3-b4ed4c13c510/Flow2.png rename to public/uploads/article/Flow2.png diff --git a/public/uploads/article/019ee018-20e9-73f6-91a3-b4ed4e5dec76/Queue-process2.png b/public/uploads/article/Queue-process2.png similarity index 100% rename from public/uploads/article/019ee018-20e9-73f6-91a3-b4ed4e5dec76/Queue-process2.png rename to public/uploads/article/Queue-process2.png diff --git a/public/uploads/article/019ee018-20e8-71a5-809d-1920a2ec15cf/Screenshot-2015-12-22-16.21.56.png b/public/uploads/article/Screenshot-2015-12-22-16.21.56.png similarity index 100% rename from public/uploads/article/019ee018-20e8-71a5-809d-1920a2ec15cf/Screenshot-2015-12-22-16.21.56.png rename to public/uploads/article/Screenshot-2015-12-22-16.21.56.png diff --git a/public/uploads/article/019ee018-20e8-71a5-809d-19209179e40a/Screenshot-2019-04-06-at-15.03.21-1024x165-1-1024x165.png b/public/uploads/article/Screenshot-2019-04-06-at-15.03.21-1024x165-1-1024x165.png similarity index 100% rename from public/uploads/article/019ee018-20e8-71a5-809d-19209179e40a/Screenshot-2019-04-06-at-15.03.21-1024x165-1-1024x165.png rename to public/uploads/article/Screenshot-2019-04-06-at-15.03.21-1024x165-1-1024x165.png diff --git a/public/uploads/article/019ee018-20e8-71a5-809d-1920a3b42652/Screenshot-2022-08-30-at-19.14.14-1024x334.png b/public/uploads/article/Screenshot-2022-08-30-at-19.14.14-1024x334.png similarity index 100% rename from public/uploads/article/019ee018-20e8-71a5-809d-1920a3b42652/Screenshot-2022-08-30-at-19.14.14-1024x334.png rename to public/uploads/article/Screenshot-2022-08-30-at-19.14.14-1024x334.png diff --git a/public/uploads/article/019ee018-20e8-71a5-809d-1920a3b42652/Screenshot-2022-08-30-at-19.22.45-1024x147.png b/public/uploads/article/Screenshot-2022-08-30-at-19.22.45-1024x147.png similarity index 100% rename from public/uploads/article/019ee018-20e8-71a5-809d-1920a3b42652/Screenshot-2022-08-30-at-19.22.45-1024x147.png rename to public/uploads/article/Screenshot-2022-08-30-at-19.22.45-1024x147.png diff --git a/public/uploads/article/019ee018-20e8-71a5-809d-1920a3b42652/Screenshot-2022-08-30-at-20.39.19.png b/public/uploads/article/Screenshot-2022-08-30-at-20.39.19.png similarity index 100% rename from public/uploads/article/019ee018-20e8-71a5-809d-1920a3b42652/Screenshot-2022-08-30-at-20.39.19.png rename to public/uploads/article/Screenshot-2022-08-30-at-20.39.19.png diff --git a/public/uploads/article/019ee018-20e9-73f6-91a3-b4ed4cc2fa78/api-comms4-2.png b/public/uploads/article/api-comms4-2.png similarity index 100% rename from public/uploads/article/019ee018-20e9-73f6-91a3-b4ed4cc2fa78/api-comms4-2.png rename to public/uploads/article/api-comms4-2.png diff --git a/public/uploads/article/019ee018-20e9-73f6-91a3-b4ed496208d1/bruno-vs-postman1-1024x683.jpg b/public/uploads/article/bruno-vs-postman1-1024x683.jpg similarity index 100% rename from public/uploads/article/019ee018-20e9-73f6-91a3-b4ed496208d1/bruno-vs-postman1-1024x683.jpg rename to public/uploads/article/bruno-vs-postman1-1024x683.jpg diff --git a/public/uploads/article/019ee018-20e9-73f6-91a3-b4ed4cc2fa78/core-queue2.png b/public/uploads/article/core-queue2.png similarity index 100% rename from public/uploads/article/019ee018-20e9-73f6-91a3-b4ed4cc2fa78/core-queue2.png rename to public/uploads/article/core-queue2.png diff --git a/public/uploads/article/019ee018-20e9-73f6-91a3-b4ed4c13c510/files-admin-1.jpg b/public/uploads/article/files-admin-1.jpg similarity index 100% rename from public/uploads/article/019ee018-20e9-73f6-91a3-b4ed4c13c510/files-admin-1.jpg rename to public/uploads/article/files-admin-1.jpg diff --git a/public/uploads/article/019ee018-20e9-73f6-91a3-b4ed4c13c510/files-api.jpg b/public/uploads/article/files-api.jpg similarity index 100% rename from public/uploads/article/019ee018-20e9-73f6-91a3-b4ed4c13c510/files-api.jpg rename to public/uploads/article/files-api.jpg diff --git a/public/uploads/article/019ee018-20e8-71a5-809d-1920835a6ebe/highcharts-1024x651.png b/public/uploads/article/highcharts-1024x651.png similarity index 100% rename from public/uploads/article/019ee018-20e8-71a5-809d-1920835a6ebe/highcharts-1024x651.png rename to public/uploads/article/highcharts-1024x651.png diff --git a/public/uploads/article/019ee018-20e8-71a5-809d-19208dbd32ae/icons.png b/public/uploads/article/icons.png similarity index 100% rename from public/uploads/article/019ee018-20e8-71a5-809d-19208dbd32ae/icons.png rename to public/uploads/article/icons.png diff --git a/public/uploads/article/019ee018-20e9-73f6-91a3-b4ed41711be1/id-file-300x235.gif b/public/uploads/article/id-file-300x235.gif similarity index 100% rename from public/uploads/article/019ee018-20e9-73f6-91a3-b4ed41711be1/id-file-300x235.gif rename to public/uploads/article/id-file-300x235.gif diff --git a/public/uploads/article/019ee018-20e9-73f6-91a3-b4ed41711be1/id-file-svn-300x141.gif b/public/uploads/article/id-file-svn-300x141.gif similarity index 100% rename from public/uploads/article/019ee018-20e9-73f6-91a3-b4ed41711be1/id-file-svn-300x141.gif rename to public/uploads/article/id-file-svn-300x141.gif diff --git a/public/uploads/article/019ee018-20e8-71a5-809d-1920a19231e2/ignore-patterns.png b/public/uploads/article/ignore-patterns.png similarity index 100% rename from public/uploads/article/019ee018-20e8-71a5-809d-1920a19231e2/ignore-patterns.png rename to public/uploads/article/ignore-patterns.png diff --git a/public/uploads/article/019ee018-20e9-73f6-91a3-b4ed4981a834/image-1-1024x83.png b/public/uploads/article/image-1-1024x83.png similarity index 100% rename from public/uploads/article/019ee018-20e9-73f6-91a3-b4ed4981a834/image-1-1024x83.png rename to public/uploads/article/image-1-1024x83.png diff --git a/public/uploads/article/019ee018-20e9-73f6-91a3-b4ed4981a834/image-2-1024x66.png b/public/uploads/article/image-2-1024x66.png similarity index 100% rename from public/uploads/article/019ee018-20e9-73f6-91a3-b4ed4981a834/image-2-1024x66.png rename to public/uploads/article/image-2-1024x66.png diff --git a/public/uploads/article/019ee018-20e9-73f6-91a3-b4ed4981a834/image-3.png b/public/uploads/article/image-3.png similarity index 100% rename from public/uploads/article/019ee018-20e9-73f6-91a3-b4ed4981a834/image-3.png rename to public/uploads/article/image-3.png diff --git a/public/uploads/article/019ee018-20e9-73f6-91a3-b4ed4981a834/image-5.png b/public/uploads/article/image-5.png similarity index 100% rename from public/uploads/article/019ee018-20e9-73f6-91a3-b4ed4981a834/image-5.png rename to public/uploads/article/image-5.png diff --git a/public/uploads/article/019ee018-20e9-73f6-91a3-b4ed4981a834/image.png b/public/uploads/article/image.png similarity index 100% rename from public/uploads/article/019ee018-20e9-73f6-91a3-b4ed4981a834/image.png rename to public/uploads/article/image.png diff --git a/public/uploads/article/naming-convention-1024x767.png b/public/uploads/article/naming-convention-1024x767.png new file mode 100644 index 0000000..987c41b Binary files /dev/null and b/public/uploads/article/naming-convention-1024x767.png differ diff --git a/public/uploads/article/019ee018-20e8-71a5-809d-1920a2ec15cf/php7errors.png b/public/uploads/article/php7errors.png similarity index 100% rename from public/uploads/article/019ee018-20e8-71a5-809d-1920a2ec15cf/php7errors.png rename to public/uploads/article/php7errors.png diff --git a/public/uploads/article/019ee018-20e9-73f6-91a3-b4ed502d938b/profile-totp-deactivated.jpg b/public/uploads/article/profile-totp-deactivated.jpg similarity index 100% rename from public/uploads/article/019ee018-20e9-73f6-91a3-b4ed502d938b/profile-totp-deactivated.jpg rename to public/uploads/article/profile-totp-deactivated.jpg diff --git a/public/uploads/article/019ee018-20e8-71a5-809d-192093bc5d00/sdasdadsa.drawio.png b/public/uploads/article/sdasdadsa.drawio.png similarity index 100% rename from public/uploads/article/019ee018-20e8-71a5-809d-192093bc5d00/sdasdadsa.drawio.png rename to public/uploads/article/sdasdadsa.drawio.png diff --git a/public/uploads/article/019ee018-20e9-73f6-91a3-b4ed41711be1/set-property-300x152.gif b/public/uploads/article/set-property-300x152.gif similarity index 100% rename from public/uploads/article/019ee018-20e9-73f6-91a3-b4ed41711be1/set-property-300x152.gif rename to public/uploads/article/set-property-300x152.gif diff --git a/public/uploads/article/019ee018-20e9-73f6-91a3-b4ed419efa79/svn-add.jpg b/public/uploads/article/svn-add.jpg similarity index 100% rename from public/uploads/article/019ee018-20e9-73f6-91a3-b4ed419efa79/svn-add.jpg rename to public/uploads/article/svn-add.jpg diff --git a/public/uploads/article/019ee018-20e9-73f6-91a3-b4ed41711be1/svn-keywords-300x298.gif b/public/uploads/article/svn-keywords-300x298.gif similarity index 100% rename from public/uploads/article/019ee018-20e9-73f6-91a3-b4ed41711be1/svn-keywords-300x298.gif rename to public/uploads/article/svn-keywords-300x298.gif diff --git a/public/uploads/test-article.jpg b/public/uploads/article/test-article.jpg similarity index 100% rename from public/uploads/test-article.jpg rename to public/uploads/article/test-article.jpg diff --git a/public/uploads/article/019ee018-20e9-73f6-91a3-b4ed502d938b/totp-activate-qr.jpg b/public/uploads/article/totp-activate-qr.jpg similarity index 100% rename from public/uploads/article/019ee018-20e9-73f6-91a3-b4ed502d938b/totp-activate-qr.jpg rename to public/uploads/article/totp-activate-qr.jpg diff --git a/public/uploads/article/019ee018-20e9-73f6-91a3-b4ed502d938b/totp-ask-code.jpg b/public/uploads/article/totp-ask-code.jpg similarity index 100% rename from public/uploads/article/019ee018-20e9-73f6-91a3-b4ed502d938b/totp-ask-code.jpg rename to public/uploads/article/totp-ask-code.jpg diff --git a/public/uploads/article/019ee018-20e9-73f6-91a3-b4ed502d938b/totp-flow.jpg b/public/uploads/article/totp-flow.jpg similarity index 100% rename from public/uploads/article/019ee018-20e9-73f6-91a3-b4ed502d938b/totp-flow.jpg rename to public/uploads/article/totp-flow.jpg diff --git a/public/uploads/article/019ee018-20e9-73f6-91a3-b4ed502d938b/totp-recovery-codes.jpg b/public/uploads/article/totp-recovery-codes.jpg similarity index 100% rename from public/uploads/article/019ee018-20e9-73f6-91a3-b4ed502d938b/totp-recovery-codes.jpg rename to public/uploads/article/totp-recovery-codes.jpg diff --git a/public/uploads/article/019ee018-20e8-71a5-809d-19208fa3cb37/zend.barcode.introduction.example-1.png b/public/uploads/article/zend.barcode.introduction.example-1.png similarity index 100% rename from public/uploads/article/019ee018-20e8-71a5-809d-19208fa3cb37/zend.barcode.introduction.example-1.png rename to public/uploads/article/zend.barcode.introduction.example-1.png diff --git a/public/uploads/article/019ee018-20e8-71a5-809d-1920a2ec15cf/zftest.png b/public/uploads/article/zftest.png similarity index 100% rename from public/uploads/article/019ee018-20e8-71a5-809d-1920a2ec15cf/zftest.png rename to public/uploads/article/zftest.png diff --git a/src/App/assets/uploads/article/ConfigProvider2.png b/src/App/assets/uploads/article/ConfigProvider2.png new file mode 100644 index 0000000..1f7a101 Binary files /dev/null and b/src/App/assets/uploads/article/ConfigProvider2.png differ diff --git a/src/App/assets/uploads/article/Core2.png b/src/App/assets/uploads/article/Core2.png new file mode 100644 index 0000000..19b9fbe Binary files /dev/null and b/src/App/assets/uploads/article/Core2.png differ diff --git a/src/App/assets/uploads/article/Flow2.png b/src/App/assets/uploads/article/Flow2.png new file mode 100644 index 0000000..d8d7ddc Binary files /dev/null and b/src/App/assets/uploads/article/Flow2.png differ diff --git a/src/App/assets/uploads/article/Queue-process2.png b/src/App/assets/uploads/article/Queue-process2.png new file mode 100644 index 0000000..834d9fc Binary files /dev/null and b/src/App/assets/uploads/article/Queue-process2.png differ diff --git a/src/App/assets/uploads/article/Screenshot-2015-12-22-16.21.56.png b/src/App/assets/uploads/article/Screenshot-2015-12-22-16.21.56.png new file mode 100644 index 0000000..58f39a5 Binary files /dev/null and b/src/App/assets/uploads/article/Screenshot-2015-12-22-16.21.56.png differ diff --git a/src/App/assets/uploads/article/Screenshot-2019-04-06-at-15.03.21-1024x165-1-1024x165.png b/src/App/assets/uploads/article/Screenshot-2019-04-06-at-15.03.21-1024x165-1-1024x165.png new file mode 100644 index 0000000..b2b41b6 Binary files /dev/null and b/src/App/assets/uploads/article/Screenshot-2019-04-06-at-15.03.21-1024x165-1-1024x165.png differ diff --git a/src/App/assets/uploads/article/Screenshot-2022-08-30-at-19.14.14-1024x334.png b/src/App/assets/uploads/article/Screenshot-2022-08-30-at-19.14.14-1024x334.png new file mode 100644 index 0000000..84c396a Binary files /dev/null and b/src/App/assets/uploads/article/Screenshot-2022-08-30-at-19.14.14-1024x334.png differ diff --git a/src/App/assets/uploads/article/Screenshot-2022-08-30-at-19.22.45-1024x147.png b/src/App/assets/uploads/article/Screenshot-2022-08-30-at-19.22.45-1024x147.png new file mode 100644 index 0000000..e6d1271 Binary files /dev/null and b/src/App/assets/uploads/article/Screenshot-2022-08-30-at-19.22.45-1024x147.png differ diff --git a/src/App/assets/uploads/article/Screenshot-2022-08-30-at-20.39.19.png b/src/App/assets/uploads/article/Screenshot-2022-08-30-at-20.39.19.png new file mode 100644 index 0000000..e57992d Binary files /dev/null and b/src/App/assets/uploads/article/Screenshot-2022-08-30-at-20.39.19.png differ diff --git a/src/App/assets/uploads/article/api-comms4-2.png b/src/App/assets/uploads/article/api-comms4-2.png new file mode 100644 index 0000000..f3f5edc Binary files /dev/null and b/src/App/assets/uploads/article/api-comms4-2.png differ diff --git a/src/App/assets/uploads/article/bruno-vs-postman1-1024x683.jpg b/src/App/assets/uploads/article/bruno-vs-postman1-1024x683.jpg new file mode 100644 index 0000000..de1d164 Binary files /dev/null and b/src/App/assets/uploads/article/bruno-vs-postman1-1024x683.jpg differ diff --git a/src/App/assets/uploads/article/core-queue2.png b/src/App/assets/uploads/article/core-queue2.png new file mode 100644 index 0000000..0c127ff Binary files /dev/null and b/src/App/assets/uploads/article/core-queue2.png differ diff --git a/src/App/assets/uploads/article/files-admin-1.jpg b/src/App/assets/uploads/article/files-admin-1.jpg new file mode 100644 index 0000000..f923945 Binary files /dev/null and b/src/App/assets/uploads/article/files-admin-1.jpg differ diff --git a/src/App/assets/uploads/article/files-api.jpg b/src/App/assets/uploads/article/files-api.jpg new file mode 100644 index 0000000..9d7e4a4 Binary files /dev/null and b/src/App/assets/uploads/article/files-api.jpg differ diff --git a/src/App/assets/uploads/article/highcharts-1024x651.png b/src/App/assets/uploads/article/highcharts-1024x651.png new file mode 100644 index 0000000..933aea5 Binary files /dev/null and b/src/App/assets/uploads/article/highcharts-1024x651.png differ diff --git a/src/App/assets/uploads/article/icons.png b/src/App/assets/uploads/article/icons.png new file mode 100644 index 0000000..e27b216 Binary files /dev/null and b/src/App/assets/uploads/article/icons.png differ diff --git a/src/App/assets/uploads/article/id-file-300x235.gif b/src/App/assets/uploads/article/id-file-300x235.gif new file mode 100644 index 0000000..9749e70 Binary files /dev/null and b/src/App/assets/uploads/article/id-file-300x235.gif differ diff --git a/src/App/assets/uploads/article/id-file-svn-300x141.gif b/src/App/assets/uploads/article/id-file-svn-300x141.gif new file mode 100644 index 0000000..e3cfb3c Binary files /dev/null and b/src/App/assets/uploads/article/id-file-svn-300x141.gif differ diff --git a/src/App/assets/uploads/article/ignore-patterns.png b/src/App/assets/uploads/article/ignore-patterns.png new file mode 100644 index 0000000..233585c Binary files /dev/null and b/src/App/assets/uploads/article/ignore-patterns.png differ diff --git a/src/App/assets/uploads/article/image-1-1024x83.png b/src/App/assets/uploads/article/image-1-1024x83.png new file mode 100644 index 0000000..000fab6 Binary files /dev/null and b/src/App/assets/uploads/article/image-1-1024x83.png differ diff --git a/src/App/assets/uploads/article/image-2-1024x66.png b/src/App/assets/uploads/article/image-2-1024x66.png new file mode 100644 index 0000000..896d5a2 Binary files /dev/null and b/src/App/assets/uploads/article/image-2-1024x66.png differ diff --git a/src/App/assets/uploads/article/image-3.png b/src/App/assets/uploads/article/image-3.png new file mode 100644 index 0000000..b3eacae Binary files /dev/null and b/src/App/assets/uploads/article/image-3.png differ diff --git a/src/App/assets/uploads/article/image-5.png b/src/App/assets/uploads/article/image-5.png new file mode 100644 index 0000000..9d2ed51 Binary files /dev/null and b/src/App/assets/uploads/article/image-5.png differ diff --git a/src/App/assets/uploads/article/image.png b/src/App/assets/uploads/article/image.png new file mode 100644 index 0000000..2316288 Binary files /dev/null and b/src/App/assets/uploads/article/image.png differ diff --git a/src/App/assets/uploads/article/naming-convention-1024x767.png b/src/App/assets/uploads/article/naming-convention-1024x767.png new file mode 100644 index 0000000..987c41b Binary files /dev/null and b/src/App/assets/uploads/article/naming-convention-1024x767.png differ diff --git a/src/App/assets/uploads/article/php7errors.png b/src/App/assets/uploads/article/php7errors.png new file mode 100644 index 0000000..825b32b Binary files /dev/null and b/src/App/assets/uploads/article/php7errors.png differ diff --git a/src/App/assets/uploads/article/profile-totp-deactivated.jpg b/src/App/assets/uploads/article/profile-totp-deactivated.jpg new file mode 100644 index 0000000..4b569b1 Binary files /dev/null and b/src/App/assets/uploads/article/profile-totp-deactivated.jpg differ diff --git a/src/App/assets/uploads/article/sdasdadsa.drawio.png b/src/App/assets/uploads/article/sdasdadsa.drawio.png new file mode 100644 index 0000000..9578501 Binary files /dev/null and b/src/App/assets/uploads/article/sdasdadsa.drawio.png differ diff --git a/src/App/assets/uploads/article/set-property-300x152.gif b/src/App/assets/uploads/article/set-property-300x152.gif new file mode 100644 index 0000000..f2174d4 Binary files /dev/null and b/src/App/assets/uploads/article/set-property-300x152.gif differ diff --git a/src/App/assets/uploads/article/svn-add.jpg b/src/App/assets/uploads/article/svn-add.jpg new file mode 100644 index 0000000..8173774 Binary files /dev/null and b/src/App/assets/uploads/article/svn-add.jpg differ diff --git a/src/App/assets/uploads/article/svn-keywords-300x298.gif b/src/App/assets/uploads/article/svn-keywords-300x298.gif new file mode 100644 index 0000000..9a0239f Binary files /dev/null and b/src/App/assets/uploads/article/svn-keywords-300x298.gif differ diff --git a/src/App/assets/uploads/article/test-article.jpg b/src/App/assets/uploads/article/test-article.jpg new file mode 100644 index 0000000..77e2d5c Binary files /dev/null and b/src/App/assets/uploads/article/test-article.jpg differ diff --git a/src/App/assets/uploads/article/totp-activate-qr.jpg b/src/App/assets/uploads/article/totp-activate-qr.jpg new file mode 100644 index 0000000..a5b7eb9 Binary files /dev/null and b/src/App/assets/uploads/article/totp-activate-qr.jpg differ diff --git a/src/App/assets/uploads/article/totp-ask-code.jpg b/src/App/assets/uploads/article/totp-ask-code.jpg new file mode 100644 index 0000000..6827443 Binary files /dev/null and b/src/App/assets/uploads/article/totp-ask-code.jpg differ diff --git a/src/App/assets/uploads/article/totp-flow.jpg b/src/App/assets/uploads/article/totp-flow.jpg new file mode 100644 index 0000000..f47478b Binary files /dev/null and b/src/App/assets/uploads/article/totp-flow.jpg differ diff --git a/src/App/assets/uploads/article/totp-recovery-codes.jpg b/src/App/assets/uploads/article/totp-recovery-codes.jpg new file mode 100644 index 0000000..ea45c66 Binary files /dev/null and b/src/App/assets/uploads/article/totp-recovery-codes.jpg differ diff --git a/public/uploads/article/019f7ea7-116b-72e2-ab4f-e90276d9b8a6/zend.barcode.introduction.example-1.png b/src/App/assets/uploads/article/zend.barcode.introduction.example-1.png similarity index 100% rename from public/uploads/article/019f7ea7-116b-72e2-ab4f-e90276d9b8a6/zend.barcode.introduction.example-1.png rename to src/App/assets/uploads/article/zend.barcode.introduction.example-1.png diff --git a/src/App/assets/uploads/article/zftest.png b/src/App/assets/uploads/article/zftest.png new file mode 100644 index 0000000..bf709fe Binary files /dev/null and b/src/App/assets/uploads/article/zftest.png differ