From 9944bfb67b36a91e79ff833acd37cf43a2585069 Mon Sep 17 00:00:00 2001 From: pratik-londhe4 Date: Thu, 21 May 2026 23:46:11 +0530 Subject: [PATCH 01/13] Refactor theme structure and update to use rtcamp/framework --- composer.json | 10 +- composer.lock | 457 +++++++++--------- inc/Autoloader.php | 11 +- inc/Core/Assets.php | 26 +- inc/Framework/README.md | 32 -- inc/Framework/Traits/AssetLoaderTrait.php | 123 ----- inc/Framework/Traits/AutoloaderTrait.php | 90 ---- inc/Framework/Traits/Singleton.php | 103 ---- inc/Main.php | 32 +- .../BlockExtensions/MediaTextInteractive.php | 17 +- inc/Post_Types/Portfolio.php | 56 +++ inc/Settings/Theme_Options.php | 116 +++++ inc/Shortcodes/Current_Year.php | 44 ++ inc/Taxonomies/Project_Type.php | 59 +++ phpstan-baseline.neon | 4 +- 15 files changed, 567 insertions(+), 613 deletions(-) delete mode 100644 inc/Framework/README.md delete mode 100644 inc/Framework/Traits/AssetLoaderTrait.php delete mode 100644 inc/Framework/Traits/AutoloaderTrait.php delete mode 100644 inc/Framework/Traits/Singleton.php create mode 100644 inc/Post_Types/Portfolio.php create mode 100644 inc/Settings/Theme_Options.php create mode 100644 inc/Shortcodes/Current_Year.php create mode 100644 inc/Taxonomies/Project_Type.php diff --git a/composer.json b/composer.json index e3417f82..e2c55a81 100644 --- a/composer.json +++ b/composer.json @@ -4,8 +4,16 @@ "type": "wordpress-theme", "homepage": "https://rtcamp.com/", "license": "GPL-2.0-or-later", + "repositories": [ + { + "type": "vcs", + "url": "https://github.com/rtCamp/wp-framework.git", + "no-api": true + } + ], "require": { - "php": ">=8.2" + "php": ">=8.2", + "rtcamp/wp-framework": "dev-framework" }, "require-dev": { "wp-coding-standards/wpcs": "^2.3", diff --git a/composer.lock b/composer.lock index 0c9d4e10..d0fb144b 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,73 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "9934fc21777ac929aeff9af41ee57eeb", - "packages": [], + "content-hash": "5c9d115741ba03076111d8506b4f0895", + "packages": [ + { + "name": "rtcamp/wp-framework", + "version": "dev-framework", + "source": { + "type": "git", + "url": "https://github.com/rtCamp/wp-framework.git", + "reference": "a9c8cefe967f8f05bf87560bc15a53501bec5c41" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/rtCamp/wp-framework/zipball/a9c8cefe967f8f05bf87560bc15a53501bec5c41", + "reference": "a9c8cefe967f8f05bf87560bc15a53501bec5c41", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "automattic/vipwpcs": "^3.0", + "dealerdirect/phpcodesniffer-composer-installer": "^1.0", + "phpcompatibility/phpcompatibility-wp": "^2.1", + "phpstan/phpstan": "^2.0", + "phpunit/phpunit": "^11.0", + "squizlabs/php_codesniffer": "^3.10", + "szepeviktor/phpstan-wordpress": "^2.0", + "wp-coding-standards/wpcs": "^3.1", + "yoast/phpunit-polyfills": "^4.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "rtCamp\\WPFramework\\": "inc/" + } + }, + "autoload-dev": { + "psr-4": { + "rtCamp\\WPFramework\\Tests\\": "tests/" + } + }, + "scripts": { + "lint": [ + "phpcs" + ], + "lint:fix": [ + "phpcbf" + ], + "analyse": [ + "phpstan analyse" + ], + "test": [ + "phpunit" + ], + "check": [ + "@lint", + "@analyse", + "@test" + ] + }, + "license": [ + "GPL-2.0-or-later" + ], + "description": "A reusable WordPress framework providing composable traits, abstract classes, and interfaces for plugins and themes.", + "time": "2026-05-21T18:00:59+00:00" + } + ], "packages-dev": [ { "name": "automattic/vipwpcs", @@ -158,30 +223,29 @@ }, { "name": "doctrine/instantiator", - "version": "2.0.0", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" + "reference": "23da848e1a2308728fe5fdddabf4be17ff9720c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", - "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/23da848e1a2308728fe5fdddabf4be17ff9720c7", + "reference": "23da848e1a2308728fe5fdddabf4be17ff9720c7", "shasum": "" }, "require": { - "php": "^8.1" + "php": "^8.4" }, "require-dev": { - "doctrine/coding-standard": "^11", + "doctrine/coding-standard": "^14", "ext-pdo": "*", "ext-phar": "*", "phpbench/phpbench": "^1.2", - "phpstan/phpstan": "^1.9.4", - "phpstan/phpstan-phpunit": "^1.3", - "phpunit/phpunit": "^9.5.27", - "vimeo/psalm": "^5.4" + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^10.5.58" }, "type": "library", "autoload": { @@ -208,7 +272,7 @@ ], "support": { "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/2.0.0" + "source": "https://github.com/doctrine/instantiator/tree/2.1.0" }, "funding": [ { @@ -224,7 +288,7 @@ "type": "tidelift" } ], - "time": "2022-12-30T00:23:10+00:00" + "time": "2026-01-05T06:47:08+00:00" }, { "name": "eftec/bladeone", @@ -367,16 +431,16 @@ }, { "name": "gettext/languages", - "version": "2.12.1", + "version": "2.12.2", "source": { "type": "git", "url": "https://github.com/php-gettext/Languages.git", - "reference": "0b0b0851c55168e1dfb14305735c64019732b5f1" + "reference": "079d6f4842cbcbf5673a70d8e93169a684e7aadd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-gettext/Languages/zipball/0b0b0851c55168e1dfb14305735c64019732b5f1", - "reference": "0b0b0851c55168e1dfb14305735c64019732b5f1", + "url": "https://api.github.com/repos/php-gettext/Languages/zipball/079d6f4842cbcbf5673a70d8e93169a684e7aadd", + "reference": "079d6f4842cbcbf5673a70d8e93169a684e7aadd", "shasum": "" }, "require": { @@ -426,7 +490,7 @@ ], "support": { "issues": "https://github.com/php-gettext/Languages/issues", - "source": "https://github.com/php-gettext/Languages/tree/2.12.1" + "source": "https://github.com/php-gettext/Languages/tree/2.12.2" }, "funding": [ { @@ -438,20 +502,20 @@ "type": "github" } ], - "time": "2025-03-19T11:14:02+00:00" + "time": "2026-02-23T14:05:50+00:00" }, { "name": "mck89/peast", - "version": "v1.17.4", + "version": "v1.17.6", "source": { "type": "git", "url": "https://github.com/mck89/peast.git", - "reference": "c6a63f32410d2e4ee2cd20fe94b35af147fb852d" + "reference": "b8b4184b1e6912669f9af155caef9050509d9f18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mck89/peast/zipball/c6a63f32410d2e4ee2cd20fe94b35af147fb852d", - "reference": "c6a63f32410d2e4ee2cd20fe94b35af147fb852d", + "url": "https://api.github.com/repos/mck89/peast/zipball/b8b4184b1e6912669f9af155caef9050509d9f18", + "reference": "b8b4184b1e6912669f9af155caef9050509d9f18", "shasum": "" }, "require": { @@ -464,7 +528,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.17.4-dev" + "dev-master": "1.17.6-dev" } }, "autoload": { @@ -485,9 +549,62 @@ "description": "Peast is PHP library that generates AST for JavaScript code", "support": { "issues": "https://github.com/mck89/peast/issues", - "source": "https://github.com/mck89/peast/tree/v1.17.4" + "source": "https://github.com/mck89/peast/tree/v1.17.6" + }, + "time": "2026-04-24T08:04:05+00:00" + }, + { + "name": "mustache/mustache", + "version": "v3.2.0", + "source": { + "type": "git", + "url": "https://github.com/bobthecow/mustache.php.git", + "reference": "bd4fb2e45ac2df0570c0f4da6898054a950d1ed0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/bobthecow/mustache.php/zipball/bd4fb2e45ac2df0570c0f4da6898054a950d1ed0", + "reference": "bd4fb2e45ac2df0570c0f4da6898054a950d1ed0", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "~2.19.3", + "yoast/phpunit-polyfills": "^2.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Mustache\\": "src/" + }, + "classmap": [ + "src/compat.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Justin Hileman", + "email": "justin@justinhileman.info", + "homepage": "http://justinhileman.com" + } + ], + "description": "A Mustache implementation in PHP.", + "homepage": "https://github.com/bobthecow/mustache.php", + "keywords": [ + "mustache", + "templating" + ], + "support": { + "issues": "https://github.com/bobthecow/mustache.php/issues", + "source": "https://github.com/bobthecow/mustache.php/tree/v3.2.0" }, - "time": "2025-10-10T12:53:17+00:00" + "time": "2026-05-10T04:13:08+00:00" }, { "name": "myclabs/deep-copy", @@ -885,16 +1002,16 @@ }, { "name": "phpcompatibility/phpcompatibility-paragonie", - "version": "1.3.3", + "version": "1.3.4", "source": { "type": "git", "url": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie.git", - "reference": "293975b465e0e709b571cbf0c957c6c0a7b9a2ac" + "reference": "244d7b04fc4bc2117c15f5abe23eb933b5f02bbf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityParagonie/zipball/293975b465e0e709b571cbf0c957c6c0a7b9a2ac", - "reference": "293975b465e0e709b571cbf0c957c6c0a7b9a2ac", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityParagonie/zipball/244d7b04fc4bc2117c15f5abe23eb933b5f02bbf", + "reference": "244d7b04fc4bc2117c15f5abe23eb933b5f02bbf", "shasum": "" }, "require": { @@ -951,27 +1068,32 @@ { "url": "https://opencollective.com/php_codesniffer", "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcompatibility", + "type": "thanks_dev" } ], - "time": "2024-04-24T21:30:46+00:00" + "time": "2025-09-19T17:43:28+00:00" }, { "name": "phpcompatibility/phpcompatibility-wp", - "version": "2.1.5", + "version": "2.1.8", "source": { "type": "git", "url": "https://github.com/PHPCompatibility/PHPCompatibilityWP.git", - "reference": "01c1ff2704a58e46f0cb1ca9d06aee07b3589082" + "reference": "7c8d18b4d90dac9e86b0869a608fa09158e168fa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityWP/zipball/01c1ff2704a58e46f0cb1ca9d06aee07b3589082", - "reference": "01c1ff2704a58e46f0cb1ca9d06aee07b3589082", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityWP/zipball/7c8d18b4d90dac9e86b0869a608fa09158e168fa", + "reference": "7c8d18b4d90dac9e86b0869a608fa09158e168fa", "shasum": "" }, "require": { "phpcompatibility/php-compatibility": "^9.0", - "phpcompatibility/phpcompatibility-paragonie": "^1.0" + "phpcompatibility/phpcompatibility-paragonie": "^1.0", + "squizlabs/php_codesniffer": "^3.3" }, "require-dev": { "dealerdirect/phpcodesniffer-composer-installer": "^1.0" @@ -1021,9 +1143,13 @@ { "url": "https://opencollective.com/php_codesniffer", "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcompatibility", + "type": "thanks_dev" } ], - "time": "2024-04-24T21:37:59+00:00" + "time": "2025-10-18T00:05:59+00:00" }, { "name": "phpstan/extension-installer", @@ -1075,11 +1201,11 @@ }, { "name": "phpstan/phpstan", - "version": "2.1.51", + "version": "2.1.55", "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/dc3b523c45e714c70de2ac5113b958223b55dc59", - "reference": "dc3b523c45e714c70de2ac5113b958223b55dc59", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/9eaac3826ed5e9b8427350a43cac825eeca3f566", + "reference": "9eaac3826ed5e9b8427350a43cac825eeca3f566", "shasum": "" }, "require": { @@ -1124,7 +1250,7 @@ "type": "github" } ], - "time": "2026-04-21T18:22:01+00:00" + "time": "2026-05-18T11:57:34+00:00" }, { "name": "phpstan/phpstan-phpunit", @@ -2625,28 +2751,27 @@ }, { "name": "sirbrillig/phpcs-variable-analysis", - "version": "v2.11.22", + "version": "v2.13.0", "source": { "type": "git", "url": "https://github.com/sirbrillig/phpcs-variable-analysis.git", - "reference": "ffb6f16c6033ec61ed84446b479a31d6529f0eb7" + "reference": "a15e970b8a0bf64cfa5e86d941f5e6b08855f369" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sirbrillig/phpcs-variable-analysis/zipball/ffb6f16c6033ec61ed84446b479a31d6529f0eb7", - "reference": "ffb6f16c6033ec61ed84446b479a31d6529f0eb7", + "url": "https://api.github.com/repos/sirbrillig/phpcs-variable-analysis/zipball/a15e970b8a0bf64cfa5e86d941f5e6b08855f369", + "reference": "a15e970b8a0bf64cfa5e86d941f5e6b08855f369", "shasum": "" }, "require": { "php": ">=5.4.0", - "squizlabs/php_codesniffer": "^3.5.6" + "squizlabs/php_codesniffer": "^3.5.7 || ^4.0.0" }, "require-dev": { "dealerdirect/phpcodesniffer-composer-installer": "^0.7 || ^1.0", - "phpcsstandards/phpcsdevcs": "^1.1", - "phpstan/phpstan": "^1.7", + "phpstan/phpstan": "^1.7 || ^2.0", "phpunit/phpunit": "^4.8.36 || ^5.7.21 || ^6.5 || ^7.0 || ^8.0 || ^9.0 || ^10.5.32 || ^11.3.3", - "vimeo/psalm": "^0.2 || ^0.3 || ^1.1 || ^4.24 || ^5.0" + "vimeo/psalm": "^0.2 || ^0.3 || ^1.1 || ^4.24 || ^5.0 || ^6.0 || ^7.0" }, "type": "phpcodesniffer-standard", "autoload": { @@ -2678,7 +2803,7 @@ "source": "https://github.com/sirbrillig/phpcs-variable-analysis", "wiki": "https://github.com/sirbrillig/phpcs-variable-analysis/wiki" }, - "time": "2025-01-06T17:54:24+00:00" + "time": "2025-09-30T22:22:48+00:00" }, { "name": "squizlabs/php_codesniffer", @@ -2759,74 +2884,6 @@ ], "time": "2025-11-04T16:30:35+00:00" }, - { - "name": "symfony/finder", - "version": "v7.4.3", - "source": { - "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "fffe05569336549b20a1be64250b40516d6e8d06" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/fffe05569336549b20a1be64250b40516d6e8d06", - "reference": "fffe05569336549b20a1be64250b40516d6e8d06", - "shasum": "" - }, - "require": { - "php": ">=8.2" - }, - "require-dev": { - "symfony/filesystem": "^6.4|^7.0|^8.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Finder\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Finds files and directories via an intuitive fluent interface", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/finder/tree/v7.4.3" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-12-23T14:50:43+00:00" - }, { "name": "szepeviktor/phpstan-wordpress", "version": "v2.0.3", @@ -2942,23 +2999,23 @@ }, { "name": "wp-cli/i18n-command", - "version": "v2.6.6", + "version": "v2.7.3", "source": { "type": "git", "url": "https://github.com/wp-cli/i18n-command.git", - "reference": "94f72ddc4be8919f2cea181ba39cd140dd480d64" + "reference": "a42366245fef8b11a5d895db3f38d3c606d21d06" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/i18n-command/zipball/94f72ddc4be8919f2cea181ba39cd140dd480d64", - "reference": "94f72ddc4be8919f2cea181ba39cd140dd480d64", + "url": "https://api.github.com/repos/wp-cli/i18n-command/zipball/a42366245fef8b11a5d895db3f38d3c606d21d06", + "reference": "a42366245fef8b11a5d895db3f38d3c606d21d06", "shasum": "" }, "require": { "eftec/bladeone": "3.52", "gettext/gettext": "^4.8", "mck89/peast": "^1.13.11", - "wp-cli/wp-cli": "^2.12" + "wp-cli/wp-cli": "^2.13" }, "require-dev": { "wp-cli/scaffold-command": "^1.2 || ^2", @@ -2973,6 +3030,7 @@ "bundled": true, "commands": [ "i18n", + "i18n audit", "i18n make-pot", "i18n make-json", "i18n make-mo", @@ -3005,74 +3063,22 @@ "homepage": "https://github.com/wp-cli/i18n-command", "support": { "issues": "https://github.com/wp-cli/i18n-command/issues", - "source": "https://github.com/wp-cli/i18n-command/tree/v2.6.6" - }, - "time": "2025-11-21T04:23:34+00:00" - }, - { - "name": "wp-cli/mustache", - "version": "v2.14.99", - "source": { - "type": "git", - "url": "https://github.com/wp-cli/mustache.php.git", - "reference": "ca23b97ac35fbe01c160549eb634396183d04a59" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/wp-cli/mustache.php/zipball/ca23b97ac35fbe01c160549eb634396183d04a59", - "reference": "ca23b97ac35fbe01c160549eb634396183d04a59", - "shasum": "" - }, - "require": { - "php": ">=5.6" - }, - "replace": { - "mustache/mustache": "^2.14.2" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "~2.19.3", - "yoast/phpunit-polyfills": "^2.0" - }, - "type": "library", - "autoload": { - "psr-0": { - "Mustache": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Justin Hileman", - "email": "justin@justinhileman.info", - "homepage": "http://justinhileman.com" - } - ], - "description": "A Mustache implementation in PHP.", - "homepage": "https://github.com/bobthecow/mustache.php", - "keywords": [ - "mustache", - "templating" - ], - "support": { - "source": "https://github.com/wp-cli/mustache.php/tree/v2.14.99" + "source": "https://github.com/wp-cli/i18n-command/tree/v2.7.3" }, - "time": "2025-05-06T16:15:37+00:00" + "time": "2026-04-28T13:55:33+00:00" }, { "name": "wp-cli/mustangostang-spyc", - "version": "0.6.3", + "version": "0.6.6", "source": { "type": "git", "url": "https://github.com/wp-cli/spyc.git", - "reference": "6aa0b4da69ce9e9a2c8402dab8d43cf32c581cc7" + "reference": "30f25baaaba939caaff1f4b8c7ed998632f59fe2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/spyc/zipball/6aa0b4da69ce9e9a2c8402dab8d43cf32c581cc7", - "reference": "6aa0b4da69ce9e9a2c8402dab8d43cf32c581cc7", + "url": "https://api.github.com/repos/wp-cli/spyc/zipball/30f25baaaba939caaff1f4b8c7ed998632f59fe2", + "reference": "30f25baaaba939caaff1f4b8c7ed998632f59fe2", "shasum": "" }, "require": { @@ -3108,22 +3114,22 @@ "description": "A simple YAML loader/dumper class for PHP (WP-CLI fork)", "homepage": "https://github.com/mustangostang/spyc/", "support": { - "source": "https://github.com/wp-cli/spyc/tree/autoload" + "source": "https://github.com/wp-cli/spyc/tree/0.6.6" }, - "time": "2017-04-25T11:26:20+00:00" + "time": "2026-03-12T12:30:41+00:00" }, { "name": "wp-cli/php-cli-tools", - "version": "v0.12.6", + "version": "v0.12.9", "source": { "type": "git", "url": "https://github.com/wp-cli/php-cli-tools.git", - "reference": "f12b650d3738e471baed6dd47982d53c5c0ab1c3" + "reference": "c3d25138ce46a66647ec0dc9b17bf300338494aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/php-cli-tools/zipball/f12b650d3738e471baed6dd47982d53c5c0ab1c3", - "reference": "f12b650d3738e471baed6dd47982d53c5c0ab1c3", + "url": "https://api.github.com/repos/wp-cli/php-cli-tools/zipball/c3d25138ce46a66647ec0dc9b17bf300338494aa", + "reference": "c3d25138ce46a66647ec0dc9b17bf300338494aa", "shasum": "" }, "require": { @@ -3136,7 +3142,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "0.12.x-dev" + "dev-main": "0.12.x-dev" } }, "autoload": { @@ -3171,51 +3177,66 @@ ], "support": { "issues": "https://github.com/wp-cli/php-cli-tools/issues", - "source": "https://github.com/wp-cli/php-cli-tools/tree/v0.12.6" + "source": "https://github.com/wp-cli/php-cli-tools/tree/v0.12.9" }, - "time": "2025-09-11T12:43:04+00:00" + "time": "2026-03-29T11:12:54+00:00" }, { "name": "wp-cli/wp-cli", - "version": "v2.12.0", + "version": "dev-main", "source": { "type": "git", "url": "https://github.com/wp-cli/wp-cli.git", - "reference": "03d30d4138d12b4bffd8b507b82e56e129e0523f" + "reference": "2ed4a7115b847de6f87c4bb06d22b2db693a4e09" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/wp-cli/zipball/03d30d4138d12b4bffd8b507b82e56e129e0523f", - "reference": "03d30d4138d12b4bffd8b507b82e56e129e0523f", + "url": "https://api.github.com/repos/wp-cli/wp-cli/zipball/2ed4a7115b847de6f87c4bb06d22b2db693a4e09", + "reference": "2ed4a7115b847de6f87c4bb06d22b2db693a4e09", "shasum": "" }, "require": { - "ext-curl": "*", - "php": "^5.6 || ^7.0 || ^8.0", - "symfony/finder": ">2.7", - "wp-cli/mustache": "^2.14.99", + "mustache/mustache": "^3.0.0", + "php": ">=7.2.24 || ^8.0", "wp-cli/mustangostang-spyc": "^0.6.3", - "wp-cli/php-cli-tools": "~0.12.4" + "wp-cli/php-cli-tools": "~0.12.7" }, "require-dev": { - "wp-cli/db-command": "^1.3 || ^2", - "wp-cli/entity-command": "^1.2 || ^2", - "wp-cli/extension-command": "^1.1 || ^2", - "wp-cli/package-command": "^1 || ^2", - "wp-cli/wp-cli-tests": "^4.3.10" + "justinrainbow/json-schema": "^6.3", + "roave/security-advisories": "dev-latest", + "wp-cli/db-command": "^2", + "wp-cli/entity-command": "^2", + "wp-cli/extension-command": "^2", + "wp-cli/package-command": "^2", + "wp-cli/wp-cli-tests": "^5" }, "suggest": { + "ext-curl": "For better performance when making HTTP requests", "ext-readline": "Include for a better --prompt implementation", "ext-zip": "Needed to support extraction of ZIP archives when doing downloads or updates" }, + "default-branch": true, "bin": [ "bin/wp", "bin/wp.bat" ], "type": "library", "extra": { + "commands": [ + "cli", + "cli alias", + "cli cache", + "cli check-update", + "cli cmd-dump", + "cli completions", + "cli has-command", + "cli info", + "cli param-dump", + "cli update", + "cli version" + ], "branch-alias": { - "dev-main": "2.12.x-dev" + "dev-main": "2.13.x-dev" } }, "autoload": { @@ -3242,7 +3263,7 @@ "issues": "https://github.com/wp-cli/wp-cli/issues", "source": "https://github.com/wp-cli/wp-cli" }, - "time": "2025-05-07T01:16:12+00:00" + "time": "2026-05-19T10:12:33+00:00" }, { "name": "wp-coding-standards/wpcs", @@ -3297,7 +3318,7 @@ }, { "name": "wp-phpunit/wp-phpunit", - "version": "6.9.1", + "version": "6.9.4", "source": { "type": "git", "url": "https://github.com/wp-phpunit/wp-phpunit.git", @@ -3345,16 +3366,16 @@ }, { "name": "yoast/phpunit-polyfills", - "version": "3.1.1", + "version": "3.1.2", "source": { "type": "git", "url": "https://github.com/Yoast/PHPUnit-Polyfills.git", - "reference": "e6381c62c4df51677b657fbac79b79dfce7acdab" + "reference": "9cf2ccd990eadfc4a1e390592d4731e590b2c618" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Yoast/PHPUnit-Polyfills/zipball/e6381c62c4df51677b657fbac79b79dfce7acdab", - "reference": "e6381c62c4df51677b657fbac79b79dfce7acdab", + "url": "https://api.github.com/repos/Yoast/PHPUnit-Polyfills/zipball/9cf2ccd990eadfc4a1e390592d4731e590b2c618", + "reference": "9cf2ccd990eadfc4a1e390592d4731e590b2c618", "shasum": "" }, "require": { @@ -3369,7 +3390,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.x-dev" + "dev-main": "4.x-dev" } }, "autoload": { @@ -3404,17 +3425,19 @@ "security": "https://github.com/Yoast/PHPUnit-Polyfills/security/policy", "source": "https://github.com/Yoast/PHPUnit-Polyfills" }, - "time": "2025-01-12T08:41:37+00:00" + "time": "2025-02-09T18:36:24+00:00" } ], "aliases": [], "minimum-stability": "dev", - "stability-flags": {}, + "stability-flags": { + "rtcamp/wp-framework": 20 + }, "prefer-stable": true, "prefer-lowest": false, "platform": { "php": ">=8.2" }, - "platform-dev": {}, - "plugin-api-version": "2.9.0" + "platform-dev": [], + "plugin-api-version": "2.6.0" } diff --git a/inc/Autoloader.php b/inc/Autoloader.php index 3356d0ad..dd86bdf3 100644 --- a/inc/Autoloader.php +++ b/inc/Autoloader.php @@ -1,6 +1,6 @@ setup_hooks(); + public function __construct() { + $this->plugin_dir = ELEMENTARY_THEME_TEMP_DIR . '/'; + $this->plugin_url = trailingslashit( get_template_directory_uri() ) . '/'; + $this->assets_dir = 'assets/build'; } /** - * Setup hooks. + * Register hooks. * * @since 1.0.0 */ - public function setup_hooks(): void { + public function register_hooks(): void { add_action( 'wp_enqueue_scripts', [ $this, 'register_assets' ] ); add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_assets' ] ); add_filter( 'render_block', [ $this, 'enqueue_block_specific_assets' ], 10, 2 ); @@ -49,9 +49,9 @@ public function setup_hooks(): void { * @action wp_enqueue_scripts */ public function register_assets(): void { - $this->register_script( 'core-navigation', 'js/frontend/core-navigation.js' ); - $this->register_style( 'core-navigation', 'css/frontend/core-navigation.css' ); - $this->register_style( 'elementary-theme-styles', 'css/frontend/styles.css' ); + $this->register_script( 'core-navigation', 'js/frontend/core-navigation' ); + $this->register_style( 'core-navigation', 'css/frontend/core-navigation' ); + $this->register_style( 'elementary-theme-styles', 'css/frontend/styles' ); } /** diff --git a/inc/Framework/README.md b/inc/Framework/README.md deleted file mode 100644 index d3028fd4..00000000 --- a/inc/Framework/README.md +++ /dev/null @@ -1,32 +0,0 @@ -# Framework Layer - -`inc/Framework/` is the upstream-owned base layer for this theme. -It contains shared contracts, traits, and utilities that downstream projects may extend, but should not edit directly. - -## What belongs here - -- Base traits -- Base interfaces or contracts -- Core utilities that define behaviour for the theme skeleton - -## What does not belong here - -- Project-specific customizations -- Theme-specific feature code -- Any code that would need direct modification for a downstream project - -## Why this exists - -This directory separates the skeleton internals from the theme implementation. -Without a clear boundary, downstream developers can accidentally modify base code and make it difficult to merge upstream improvements. - -## How to use it - -- Treat `inc/Framework/` as a vendored layer. -- Do not edit files inside `inc/Framework/` unless there is absolutely no other option. -- To override behaviour, extend the upstream class or override a method in a project-specific class under `inc/`. - -## Example - -If you need a custom singleton implementation or a different asset loader, do not modify `inc/Framework/Traits/Singleton.php`. -Instead, extend the base class or create a new class under `inc/`. diff --git a/inc/Framework/Traits/AssetLoaderTrait.php b/inc/Framework/Traits/AssetLoaderTrait.php deleted file mode 100644 index 3dd501c1..00000000 --- a/inc/Framework/Traits/AssetLoaderTrait.php +++ /dev/null @@ -1,123 +0,0 @@ - $deps Optional. An array of registered script handles this script depends on. Default empty array. - * @param string|bool|null $ver Optional. String specifying script version number, if not set, filetime will be used as version number. - * @param bool $in_footer Optional. Whether to enqueue the script before instead of in the . - * Default 'false'. - * - * @return bool Whether the script has been registered. True on success, false on failure. - * - * @since 1.0.0 - */ - private function register_script( string $handle, string $file, array $deps = [], string|bool|null $ver = false, bool $in_footer = true ): bool { - $file_path = sprintf( '%s/%s', ELEMENTARY_THEME_BUILD_DIR, $file ); - - if ( ! \file_exists( $file_path ) ) { - return false; - } - - $src = sprintf( ELEMENTARY_THEME_BUILD_URI . '/%s', $file ); - $asset_meta = $this->get_asset_meta( $file, $deps ); - - return wp_register_script( $handle, $src, $asset_meta['dependencies'], $asset_meta['version'], $in_footer ); - } - - /** - * Register a CSS stylesheet. - * - * @param string $handle Name of the stylesheet. Should be unique. - * @param string $file Style file, path of the script relative to the assets/build/ directory. - * @param array $deps Optional. An array of registered stylesheet handles this stylesheet depends on. Default empty array. - * @param string|bool|null $ver Optional. String specifying script version number, if not set, filetime will be used as version number. - * @param string $media Optional. The media for which this stylesheet has been defined. - * Default 'all'. Accepts media types like 'all', 'print' and 'screen', or media queries like - * '(orientation: portrait)' and '(max-width: 640px)'. - * - * @return bool Whether the style has been registered. True on success, false on failure. - * - * @since 1.0.0 - */ - private function register_style( string $handle, string $file, array $deps = [], string|bool|null $ver = false, string $media = 'all' ): bool { - $file_path = sprintf( '%s/%s', ELEMENTARY_THEME_BUILD_DIR, $file ); - - if ( ! \file_exists( $file_path ) ) { - return false; - } - - $src = sprintf( ELEMENTARY_THEME_BUILD_URI . '/%s', $file ); - $asset_meta = $this->get_asset_meta( $file, $deps ); - - return wp_register_style( $handle, $src, $asset_meta['dependencies'], $asset_meta['version'], $media ); - } - - /** - * Get asset dependencies and version info from a matching .asset.php file. - * - * @param string $file File path relative to assets/build/. - * @param array $deps Script dependencies to merge with. - * @param string|bool|null $ver Asset version string. - * - * @return array Asset meta information including dependencies and version. - * - * @since 1.0.0 - */ - private function get_asset_meta( string $file, array $deps = [], string|bool|null $ver = false ): array { - $normalized_file = ltrim( str_replace( '\\', '/', $file ), '/' ); - - // Strip the file extension. See: https://regex101.com. - $asset_meta_target = preg_replace( '/\.[^\/.]+$/', '', $normalized_file ); - $asset_meta_target = ! empty( $asset_meta_target ) ? $asset_meta_target : $normalized_file; - $asset_meta_file = sprintf( '%s/%s.asset.php', untrailingslashit( ELEMENTARY_THEME_BUILD_DIR ), $asset_meta_target ); - $asset_meta = is_readable( $asset_meta_file ) - ? require $asset_meta_file - : [ - 'dependencies' => [], - 'version' => $this->get_file_version( $file, $ver ), - ]; - - $asset_meta['dependencies'] = array_merge( $deps, $asset_meta['dependencies'] ); - - return $asset_meta; - } - - /** - * Get file version. - * - * @param string $file File path. - * @param string|bool|null $ver File version. - * - * @return int|string|bool File version based on file modification time or provided version. - * - * @since 1.0.0 - */ - private function get_file_version( string $file, string|bool|null $ver = false ): int|string|bool { - if ( ! empty( $ver ) ) { - return $ver; - } - - $file_path = sprintf( '%s/%s', ELEMENTARY_THEME_BUILD_DIR, $file ); - - return file_exists( $file_path ) ? (string) filemtime( $file_path ) : false; - } -} diff --git a/inc/Framework/Traits/AutoloaderTrait.php b/inc/Framework/Traits/AutoloaderTrait.php deleted file mode 100644 index 21c2e13d..00000000 --- a/inc/Framework/Traits/AutoloaderTrait.php +++ /dev/null @@ -1,90 +0,0 @@ - 'error', - 'dismiss' => false, - ] - ); - } else { - echo '

' . esc_html( $error_message ) . '

'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped - } - } - ); - } - } -} diff --git a/inc/Framework/Traits/Singleton.php b/inc/Framework/Traits/Singleton.php deleted file mode 100644 index 7066436e..00000000 --- a/inc/Framework/Traits/Singleton.php +++ /dev/null @@ -1,103 +0,0 @@ - - */ - static $instance = []; - - /** - * If this trait is implemented in a class which has multiple - * sub-classes then static::$_instance will be overwritten with the most recent - * sub-class instance. Thanks to late static binding - * we use get_called_class() to grab the called class name, and store - * a key=>value pair for each `classname => instance` in self::$_instance - * for each sub-class. - */ - $called_class = get_called_class(); - - if ( ! isset( $instance[ $called_class ] ) ) { - - $instance[ $called_class ] = new $called_class(); - - /** - * Dependent items can use the `elementary_theme_singleton_init_{$called_class}` hook to execute code - */ - do_action( sprintf( 'elementary_theme_singleton_init_%s', $called_class ) ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores, WordPress.NamingConventions.PrefixAllGlobals.DynamicHooknameFound - - } - - /** - * This assignment is necessary to make sure that the returned instance is of the correct type, - * as the $instance array is typed as array. - * - * @var static $singleton - */ - $singleton = $instance[ $called_class ]; - - return $singleton; - } -} diff --git a/inc/Main.php b/inc/Main.php index c931008f..da29ea69 100644 --- a/inc/Main.php +++ b/inc/Main.php @@ -9,9 +9,14 @@ namespace rtCamp\Theme\Elementary; -use rtCamp\Theme\Elementary\Modules\BlockExtensions\MediaTextInteractive; -use rtCamp\Theme\Elementary\Framework\Traits\Singleton; +use rtCamp\WPFramework\Contracts\Traits\Singleton; +use rtCamp\WPFramework\Contracts\Traits\Loader; use rtCamp\Theme\Elementary\Core\Assets; +use rtCamp\Theme\Elementary\Modules\BlockExtensions\MediaTextInteractive; +use rtCamp\Theme\Elementary\Post_Types\Portfolio; +use rtCamp\Theme\Elementary\Settings\Theme_Options; +use rtCamp\Theme\Elementary\Shortcodes\Current_Year; +use rtCamp\Theme\Elementary\Taxonomies\Project_Type; /** * Class Main @@ -21,17 +26,22 @@ class Main { use Singleton; + use Loader; /** * Constructor. */ protected function __construct() { - // Instantiate classes. - Assets::get_instance(); + $this->load( [ + Assets::class, + MediaTextInteractive::class, + Portfolio::class, + Project_Type::class, + Current_Year::class, + Theme_Options::class, + ] ); - // Setup hooks. $this->setup_hooks(); - $this->block_extensions(); } /** @@ -49,16 +59,6 @@ public function setup_hooks(): void { * @since 1.0.0 */ public function elementary_theme_support(): void { - // Add support for core block styles. add_theme_support( 'wp-block-styles' ); } - - /** - * Block extensions - * - * @since 1.0.0 - */ - public function block_extensions(): void { - MediaTextInteractive::get_instance(); - } } diff --git a/inc/Modules/BlockExtensions/MediaTextInteractive.php b/inc/Modules/BlockExtensions/MediaTextInteractive.php index 298dc508..49a58382 100644 --- a/inc/Modules/BlockExtensions/MediaTextInteractive.php +++ b/inc/Modules/BlockExtensions/MediaTextInteractive.php @@ -10,26 +10,17 @@ namespace rtCamp\Theme\Elementary\Modules\BlockExtensions; use WP_HTML_Tag_Processor; -use rtCamp\Theme\Elementary\Framework\Traits\Singleton; +use rtCamp\WPFramework\Contracts\Interfaces\Registrable; /** * Class MediaTextInteractive */ -class MediaTextInteractive { - - use Singleton; - - /** - * Constructor. - */ - protected function __construct() { - $this->setup_hooks(); - } +class MediaTextInteractive implements Registrable { /** - * Setup hooks. + * Register hooks. */ - public function setup_hooks(): void { + public function register_hooks(): void { add_filter( 'render_block_core/button', [ $this, 'render_block_core_button' ], 10, 2 ); add_filter( 'render_block_core/columns', [ $this, 'render_block_core_columns' ], 10, 2 ); add_filter( 'render_block_core/video', [ $this, 'render_block_core_video' ], 10, 2 ); diff --git a/inc/Post_Types/Portfolio.php b/inc/Post_Types/Portfolio.php new file mode 100644 index 00000000..faec94f2 --- /dev/null +++ b/inc/Post_Types/Portfolio.php @@ -0,0 +1,56 @@ +default_args(), + [ + 'label' => __( 'Portfolio', 'elementary-theme' ), + 'labels' => [ + 'name' => __( 'Portfolio', 'elementary-theme' ), + 'singular_name' => __( 'Portfolio Item', 'elementary-theme' ), + 'add_new' => __( 'Add New', 'elementary-theme' ), + 'add_new_item' => __( 'Add New Portfolio Item', 'elementary-theme' ), + 'edit_item' => __( 'Edit Portfolio Item', 'elementary-theme' ), + 'new_item' => __( 'New Portfolio Item', 'elementary-theme' ), + 'view_item' => __( 'View Portfolio Item', 'elementary-theme' ), + 'search_items' => __( 'Search Portfolio', 'elementary-theme' ), + 'not_found' => __( 'No portfolio items found', 'elementary-theme' ), + 'not_found_in_trash' => __( 'No portfolio items found in Trash', 'elementary-theme' ), + ], + 'menu_icon' => 'dashicons-portfolio', + 'rewrite' => [ 'slug' => 'portfolio' ], + 'supports' => [ 'title', 'editor', 'thumbnail', 'excerpt' ], + ] + ); + + register_post_type( static::get_slug(), $args ); + } +} diff --git a/inc/Settings/Theme_Options.php b/inc/Settings/Theme_Options.php new file mode 100644 index 00000000..90b947f3 --- /dev/null +++ b/inc/Settings/Theme_Options.php @@ -0,0 +1,116 @@ + [ + 'type' => 'boolean', + 'default' => true, + 'sanitize_callback' => 'rest_sanitize_boolean', + 'show_in_rest' => true, + ], + self::PREFIX . 'footer_text' => [ + 'type' => 'string', + 'default' => '', + 'sanitize_callback' => 'sanitize_text_field', + 'show_in_rest' => true, + ], + ]; + } + + #[Override] + protected function get_parent_slug(): ?string + { + return null; + } + + /** + * {@inheritDoc} + */ + public function render(): void { + ?> +
+

get_page_title() ); ?>

+
+ + + + + + + + + + +
+ + /> +
+ +
+ +
+
+ 'Y', + ]; + } + + /** + * {@inheritDoc} + */ + protected function render( array $atts, ?string $content ): string { + return esc_html( gmdate( $atts['format'] ) ); + } +} diff --git a/inc/Taxonomies/Project_Type.php b/inc/Taxonomies/Project_Type.php new file mode 100644 index 00000000..4bb25894 --- /dev/null +++ b/inc/Taxonomies/Project_Type.php @@ -0,0 +1,59 @@ +default_args(), + [ + 'hierarchical' => true, + 'labels' => [ + 'name' => __( 'Project Types', 'elementary-theme' ), + 'singular_name' => __( 'Project Type', 'elementary-theme' ), + 'search_items' => __( 'Search Project Types', 'elementary-theme' ), + 'all_items' => __( 'All Project Types', 'elementary-theme' ), + 'edit_item' => __( 'Edit Project Type', 'elementary-theme' ), + 'add_new_item' => __( 'Add New Project Type', 'elementary-theme' ), + ], + 'rewrite' => [ 'slug' => 'project-type' ], + ] + ); + + register_taxonomy( static::get_slug(), static::get_object_types(), $args ); + } +} diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index aab49911..46405cb0 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,2 +1,4 @@ parameters: - ignoreErrors: [] + ignoreErrors: + - identifier: booleanNot.alwaysTrue + path: inc/Core/Assets.php From e11cc5575c0a48262a54f5a02a21a086e3c529f3 Mon Sep 17 00:00:00 2001 From: pratik-londhe4 Date: Fri, 22 May 2026 00:27:50 +0530 Subject: [PATCH 02/13] Update lockfile to support php 8.2 platform --- composer.lock | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/composer.lock b/composer.lock index d0fb144b..0e372e5b 100644 --- a/composer.lock +++ b/composer.lock @@ -223,29 +223,30 @@ }, { "name": "doctrine/instantiator", - "version": "2.1.0", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "23da848e1a2308728fe5fdddabf4be17ff9720c7" + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/23da848e1a2308728fe5fdddabf4be17ff9720c7", - "reference": "23da848e1a2308728fe5fdddabf4be17ff9720c7", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", "shasum": "" }, "require": { - "php": "^8.4" + "php": "^8.1" }, "require-dev": { - "doctrine/coding-standard": "^14", + "doctrine/coding-standard": "^11", "ext-pdo": "*", "ext-phar": "*", "phpbench/phpbench": "^1.2", - "phpstan/phpstan": "^2.1", - "phpstan/phpstan-phpunit": "^2.0", - "phpunit/phpunit": "^10.5.58" + "phpstan/phpstan": "^1.9.4", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^9.5.27", + "vimeo/psalm": "^5.4" }, "type": "library", "autoload": { @@ -272,7 +273,7 @@ ], "support": { "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/2.1.0" + "source": "https://github.com/doctrine/instantiator/tree/2.0.0" }, "funding": [ { @@ -288,7 +289,7 @@ "type": "tidelift" } ], - "time": "2026-01-05T06:47:08+00:00" + "time": "2022-12-30T00:23:10+00:00" }, { "name": "eftec/bladeone", @@ -3438,6 +3439,6 @@ "platform": { "php": ">=8.2" }, - "platform-dev": [], + "platform-dev": {}, "plugin-api-version": "2.6.0" } From 9c580f7406dd20655d9a967f7861a51b9034ccb1 Mon Sep 17 00:00:00 2001 From: pratik-londhe4 Date: Fri, 22 May 2026 00:51:43 +0530 Subject: [PATCH 03/13] Add GITHUB_TOKEN config for setup-php action --- .github/workflows/test-measure.yml | 1 + composer.json | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-measure.yml b/.github/workflows/test-measure.yml index 7ade3296..9d037d2f 100644 --- a/.github/workflows/test-measure.yml +++ b/.github/workflows/test-measure.yml @@ -161,6 +161,7 @@ jobs: php-version: '8.2' coverage: none tools: cs2pr + github-token: ${{ secrets.GITHUB_TOKEN }} - name: Get Composer Cache Directory id: composer-cache diff --git a/composer.json b/composer.json index e2c55a81..8c8f0960 100644 --- a/composer.json +++ b/composer.json @@ -7,8 +7,7 @@ "repositories": [ { "type": "vcs", - "url": "https://github.com/rtCamp/wp-framework.git", - "no-api": true + "url": "https://github.com/rtCamp/wp-framework.git" } ], "require": { From 358f9b7885be86d8d70a512b14c48b99b06557fd Mon Sep 17 00:00:00 2001 From: pratik-londhe4 Date: Fri, 22 May 2026 00:58:44 +0530 Subject: [PATCH 04/13] Update workflow to use PAT instead of GH token --- .github/workflows/test-measure.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-measure.yml b/.github/workflows/test-measure.yml index 9d037d2f..4c2c5a22 100644 --- a/.github/workflows/test-measure.yml +++ b/.github/workflows/test-measure.yml @@ -161,7 +161,7 @@ jobs: php-version: '8.2' coverage: none tools: cs2pr - github-token: ${{ secrets.GITHUB_TOKEN }} + github-token: ${{ secrets.WP_FRAMEWORK_REPO_TEMP_TOKEN }} - name: Get Composer Cache Directory id: composer-cache From 0822aa9b044ed738777a215be2af5346b67c26b7 Mon Sep 17 00:00:00 2001 From: pratik-londhe4 Date: Fri, 22 May 2026 01:00:23 +0530 Subject: [PATCH 05/13] Update composer.lock file --- composer.lock | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/composer.lock b/composer.lock index 0e372e5b..9d45cadb 100644 --- a/composer.lock +++ b/composer.lock @@ -4,14 +4,14 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "5c9d115741ba03076111d8506b4f0895", + "content-hash": "c06d2133e4ca5db89754e6392a00aa00", "packages": [ { "name": "rtcamp/wp-framework", "version": "dev-framework", "source": { "type": "git", - "url": "https://github.com/rtCamp/wp-framework.git", + "url": "git@github.com:rtCamp/wp-framework.git", "reference": "a9c8cefe967f8f05bf87560bc15a53501bec5c41" }, "dist": { @@ -68,6 +68,10 @@ "GPL-2.0-or-later" ], "description": "A reusable WordPress framework providing composable traits, abstract classes, and interfaces for plugins and themes.", + "support": { + "source": "https://github.com/rtCamp/wp-framework/tree/framework", + "issues": "https://github.com/rtCamp/wp-framework/issues" + }, "time": "2026-05-21T18:00:59+00:00" } ], @@ -223,30 +227,29 @@ }, { "name": "doctrine/instantiator", - "version": "2.0.0", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" + "reference": "23da848e1a2308728fe5fdddabf4be17ff9720c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", - "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/23da848e1a2308728fe5fdddabf4be17ff9720c7", + "reference": "23da848e1a2308728fe5fdddabf4be17ff9720c7", "shasum": "" }, "require": { - "php": "^8.1" + "php": "^8.4" }, "require-dev": { - "doctrine/coding-standard": "^11", + "doctrine/coding-standard": "^14", "ext-pdo": "*", "ext-phar": "*", "phpbench/phpbench": "^1.2", - "phpstan/phpstan": "^1.9.4", - "phpstan/phpstan-phpunit": "^1.3", - "phpunit/phpunit": "^9.5.27", - "vimeo/psalm": "^5.4" + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^10.5.58" }, "type": "library", "autoload": { @@ -273,7 +276,7 @@ ], "support": { "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/2.0.0" + "source": "https://github.com/doctrine/instantiator/tree/2.1.0" }, "funding": [ { @@ -289,7 +292,7 @@ "type": "tidelift" } ], - "time": "2022-12-30T00:23:10+00:00" + "time": "2026-01-05T06:47:08+00:00" }, { "name": "eftec/bladeone", @@ -3439,6 +3442,6 @@ "platform": { "php": ">=8.2" }, - "platform-dev": {}, + "platform-dev": [], "plugin-api-version": "2.6.0" } From c1a8624682b75ee0afcc81e0c64ca1986fced0a1 Mon Sep 17 00:00:00 2001 From: pratik-londhe4 Date: Fri, 22 May 2026 01:15:32 +0530 Subject: [PATCH 06/13] Update composer packages --- composer.lock | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/composer.lock b/composer.lock index 9d45cadb..2bc4bf1d 100644 --- a/composer.lock +++ b/composer.lock @@ -227,29 +227,30 @@ }, { "name": "doctrine/instantiator", - "version": "2.1.0", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "23da848e1a2308728fe5fdddabf4be17ff9720c7" + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/23da848e1a2308728fe5fdddabf4be17ff9720c7", - "reference": "23da848e1a2308728fe5fdddabf4be17ff9720c7", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", "shasum": "" }, "require": { - "php": "^8.4" + "php": "^8.1" }, "require-dev": { - "doctrine/coding-standard": "^14", + "doctrine/coding-standard": "^11", "ext-pdo": "*", "ext-phar": "*", "phpbench/phpbench": "^1.2", - "phpstan/phpstan": "^2.1", - "phpstan/phpstan-phpunit": "^2.0", - "phpunit/phpunit": "^10.5.58" + "phpstan/phpstan": "^1.9.4", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^9.5.27", + "vimeo/psalm": "^5.4" }, "type": "library", "autoload": { @@ -276,7 +277,7 @@ ], "support": { "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/2.1.0" + "source": "https://github.com/doctrine/instantiator/tree/2.0.0" }, "funding": [ { @@ -292,7 +293,7 @@ "type": "tidelift" } ], - "time": "2026-01-05T06:47:08+00:00" + "time": "2022-12-30T00:23:10+00:00" }, { "name": "eftec/bladeone", @@ -3442,6 +3443,6 @@ "platform": { "php": ">=8.2" }, - "platform-dev": [], + "platform-dev": {}, "plugin-api-version": "2.6.0" } From 33217259c079301ddc21872958e533cd0f06972e Mon Sep 17 00:00:00 2001 From: pratik-londhe4 Date: Fri, 22 May 2026 01:42:38 +0530 Subject: [PATCH 07/13] Fix PHPCS warnings --- inc/Main.php | 23 +++----- inc/{ => Modules}/Settings/Theme_Options.php | 19 ++++--- inc/Post_Types/Portfolio.php | 56 ------------------- inc/Shortcodes/Current_Year.php | 44 --------------- inc/Taxonomies/Project_Type.php | 59 -------------------- 5 files changed, 19 insertions(+), 182 deletions(-) rename inc/{ => Modules}/Settings/Theme_Options.php (82%) delete mode 100644 inc/Post_Types/Portfolio.php delete mode 100644 inc/Shortcodes/Current_Year.php delete mode 100644 inc/Taxonomies/Project_Type.php diff --git a/inc/Main.php b/inc/Main.php index da29ea69..e1916a5f 100644 --- a/inc/Main.php +++ b/inc/Main.php @@ -9,14 +9,10 @@ namespace rtCamp\Theme\Elementary; -use rtCamp\WPFramework\Contracts\Traits\Singleton; -use rtCamp\WPFramework\Contracts\Traits\Loader; +use rtCamp\WPFramework\Contracts\Traits\{Singleton, Loader}; use rtCamp\Theme\Elementary\Core\Assets; use rtCamp\Theme\Elementary\Modules\BlockExtensions\MediaTextInteractive; -use rtCamp\Theme\Elementary\Post_Types\Portfolio; -use rtCamp\Theme\Elementary\Settings\Theme_Options; -use rtCamp\Theme\Elementary\Shortcodes\Current_Year; -use rtCamp\Theme\Elementary\Taxonomies\Project_Type; +use rtCamp\Theme\Elementary\Modules\Settings\Theme_Options; /** * Class Main @@ -32,14 +28,13 @@ class Main { * Constructor. */ protected function __construct() { - $this->load( [ - Assets::class, - MediaTextInteractive::class, - Portfolio::class, - Project_Type::class, - Current_Year::class, - Theme_Options::class, - ] ); + $this->load( + [ + Assets::class, + MediaTextInteractive::class, + Theme_Options::class, + ] + ); $this->setup_hooks(); } diff --git a/inc/Settings/Theme_Options.php b/inc/Modules/Settings/Theme_Options.php similarity index 82% rename from inc/Settings/Theme_Options.php rename to inc/Modules/Settings/Theme_Options.php index 90b947f3..2fcdb6fd 100644 --- a/inc/Settings/Theme_Options.php +++ b/inc/Modules/Settings/Theme_Options.php @@ -5,12 +5,12 @@ * Demonstrates how to use Abstract_Settings_Page from wp-framework. * Registers a settings page under Settings → Elementary with a few options. * - * @package rtCamp\Theme\Elementary + * @package rtCamp\Theme\Elementary\Modules\Settings */ declare( strict_types = 1 ); -namespace rtCamp\Theme\Elementary\Settings; +namespace rtCamp\Theme\Elementary\Modules\Settings; use Override; use rtCamp\WPFramework\Contracts\Abstracts\Abstract_Settings_Page; @@ -36,14 +36,14 @@ public static function get_slug(): string { * {@inheritDoc} */ protected function get_page_title(): string { - return __( 'Elementary Theme Settings', 'theme-elementary' ); + return __( 'Elementary Theme Settings', 'elementary-theme' ); } /** * {@inheritDoc} */ protected function get_menu_title(): string { - return __( 'Elementary', 'theme-elementary' ); + return __( 'Elementary', 'elementary-theme' ); } /** @@ -66,9 +66,10 @@ protected function get_settings(): array { ]; } - #[Override] - protected function get_parent_slug(): ?string - { + /** + * {@inheritDoc} + */ + protected function get_parent_slug(): ?string { return null; } @@ -86,7 +87,7 @@ public function render(): void { ?> - + - +
default_args(), - [ - 'label' => __( 'Portfolio', 'elementary-theme' ), - 'labels' => [ - 'name' => __( 'Portfolio', 'elementary-theme' ), - 'singular_name' => __( 'Portfolio Item', 'elementary-theme' ), - 'add_new' => __( 'Add New', 'elementary-theme' ), - 'add_new_item' => __( 'Add New Portfolio Item', 'elementary-theme' ), - 'edit_item' => __( 'Edit Portfolio Item', 'elementary-theme' ), - 'new_item' => __( 'New Portfolio Item', 'elementary-theme' ), - 'view_item' => __( 'View Portfolio Item', 'elementary-theme' ), - 'search_items' => __( 'Search Portfolio', 'elementary-theme' ), - 'not_found' => __( 'No portfolio items found', 'elementary-theme' ), - 'not_found_in_trash' => __( 'No portfolio items found in Trash', 'elementary-theme' ), - ], - 'menu_icon' => 'dashicons-portfolio', - 'rewrite' => [ 'slug' => 'portfolio' ], - 'supports' => [ 'title', 'editor', 'thumbnail', 'excerpt' ], - ] - ); - - register_post_type( static::get_slug(), $args ); - } -} diff --git a/inc/Shortcodes/Current_Year.php b/inc/Shortcodes/Current_Year.php deleted file mode 100644 index 02fda7f3..00000000 --- a/inc/Shortcodes/Current_Year.php +++ /dev/null @@ -1,44 +0,0 @@ - 'Y', - ]; - } - - /** - * {@inheritDoc} - */ - protected function render( array $atts, ?string $content ): string { - return esc_html( gmdate( $atts['format'] ) ); - } -} diff --git a/inc/Taxonomies/Project_Type.php b/inc/Taxonomies/Project_Type.php deleted file mode 100644 index 4bb25894..00000000 --- a/inc/Taxonomies/Project_Type.php +++ /dev/null @@ -1,59 +0,0 @@ -default_args(), - [ - 'hierarchical' => true, - 'labels' => [ - 'name' => __( 'Project Types', 'elementary-theme' ), - 'singular_name' => __( 'Project Type', 'elementary-theme' ), - 'search_items' => __( 'Search Project Types', 'elementary-theme' ), - 'all_items' => __( 'All Project Types', 'elementary-theme' ), - 'edit_item' => __( 'Edit Project Type', 'elementary-theme' ), - 'add_new_item' => __( 'Add New Project Type', 'elementary-theme' ), - ], - 'rewrite' => [ 'slug' => 'project-type' ], - ] - ); - - register_taxonomy( static::get_slug(), static::get_object_types(), $args ); - } -} From 35e70162801eaeffc759ae7571c8c22dfa6128f9 Mon Sep 17 00:00:00 2001 From: pratik-londhe4 Date: Fri, 22 May 2026 02:57:30 +0530 Subject: [PATCH 08/13] Refactor to use Pascal case instead of snake case --- composer.lock | 16 ++++++++-------- inc/Main.php | 4 ++-- .../{Theme_Options.php => ThemeOptions.php} | 12 +++++------- 3 files changed, 15 insertions(+), 17 deletions(-) rename inc/Modules/Settings/{Theme_Options.php => ThemeOptions.php} (89%) diff --git a/composer.lock b/composer.lock index 2bc4bf1d..2765f852 100644 --- a/composer.lock +++ b/composer.lock @@ -12,12 +12,12 @@ "source": { "type": "git", "url": "git@github.com:rtCamp/wp-framework.git", - "reference": "a9c8cefe967f8f05bf87560bc15a53501bec5c41" + "reference": "f90373b867266e4e12959b487b600c383b4c3328" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/rtCamp/wp-framework/zipball/a9c8cefe967f8f05bf87560bc15a53501bec5c41", - "reference": "a9c8cefe967f8f05bf87560bc15a53501bec5c41", + "url": "https://api.github.com/repos/rtCamp/wp-framework/zipball/f90373b867266e4e12959b487b600c383b4c3328", + "reference": "f90373b867266e4e12959b487b600c383b4c3328", "shasum": "" }, "require": { @@ -72,7 +72,7 @@ "source": "https://github.com/rtCamp/wp-framework/tree/framework", "issues": "https://github.com/rtCamp/wp-framework/issues" }, - "time": "2026-05-21T18:00:59+00:00" + "time": "2026-05-21T20:47:25+00:00" } ], "packages-dev": [ @@ -3192,12 +3192,12 @@ "source": { "type": "git", "url": "https://github.com/wp-cli/wp-cli.git", - "reference": "2ed4a7115b847de6f87c4bb06d22b2db693a4e09" + "reference": "4177cb58ca649407e390a264aa19577a4125fdfe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/wp-cli/zipball/2ed4a7115b847de6f87c4bb06d22b2db693a4e09", - "reference": "2ed4a7115b847de6f87c4bb06d22b2db693a4e09", + "url": "https://api.github.com/repos/wp-cli/wp-cli/zipball/4177cb58ca649407e390a264aa19577a4125fdfe", + "reference": "4177cb58ca649407e390a264aa19577a4125fdfe", "shasum": "" }, "require": { @@ -3268,7 +3268,7 @@ "issues": "https://github.com/wp-cli/wp-cli/issues", "source": "https://github.com/wp-cli/wp-cli" }, - "time": "2026-05-19T10:12:33+00:00" + "time": "2026-05-21T20:19:24+00:00" }, { "name": "wp-coding-standards/wpcs", diff --git a/inc/Main.php b/inc/Main.php index e1916a5f..1eade930 100644 --- a/inc/Main.php +++ b/inc/Main.php @@ -12,7 +12,7 @@ use rtCamp\WPFramework\Contracts\Traits\{Singleton, Loader}; use rtCamp\Theme\Elementary\Core\Assets; use rtCamp\Theme\Elementary\Modules\BlockExtensions\MediaTextInteractive; -use rtCamp\Theme\Elementary\Modules\Settings\Theme_Options; +use rtCamp\Theme\Elementary\Modules\Settings\ThemeOptions; /** * Class Main @@ -32,7 +32,7 @@ protected function __construct() { [ Assets::class, MediaTextInteractive::class, - Theme_Options::class, + ThemeOptions::class, ] ); diff --git a/inc/Modules/Settings/Theme_Options.php b/inc/Modules/Settings/ThemeOptions.php similarity index 89% rename from inc/Modules/Settings/Theme_Options.php rename to inc/Modules/Settings/ThemeOptions.php index 2fcdb6fd..691ade37 100644 --- a/inc/Modules/Settings/Theme_Options.php +++ b/inc/Modules/Settings/ThemeOptions.php @@ -2,7 +2,7 @@ /** * Example Settings Page: Theme Options. * - * Demonstrates how to use Abstract_Settings_Page from wp-framework. + * Demonstrates how to use AbstractSettingsPage from wp-framework. * Registers a settings page under Settings → Elementary with a few options. * * @package rtCamp\Theme\Elementary\Modules\Settings @@ -13,12 +13,12 @@ namespace rtCamp\Theme\Elementary\Modules\Settings; use Override; -use rtCamp\WPFramework\Contracts\Abstracts\Abstract_Settings_Page; +use rtCamp\WPFramework\Contracts\Abstracts\AbstractSettingsPage; /** - * Class Theme_Options + * Class ThemeOptions */ -class Theme_Options extends Abstract_Settings_Page { +class ThemeOptions extends AbstractSettingsPage { /** * Option key prefix. @@ -69,9 +69,7 @@ protected function get_settings(): array { /** * {@inheritDoc} */ - protected function get_parent_slug(): ?string { - return null; - } + /** * {@inheritDoc} From b927bfa0bdf78a065220c518d106acc900faebee Mon Sep 17 00:00:00 2001 From: pratik-londhe4 Date: Fri, 22 May 2026 04:54:59 +0530 Subject: [PATCH 09/13] Enhance ThemeOptions class with detailed documentation and improved settings registration --- composer.lock | 24 ++--- inc/Modules/Settings/ThemeOptions.php | 150 +++++++++++++++++++------- 2 files changed, 123 insertions(+), 51 deletions(-) diff --git a/composer.lock b/composer.lock index 2765f852..dd49ad42 100644 --- a/composer.lock +++ b/composer.lock @@ -12,12 +12,12 @@ "source": { "type": "git", "url": "git@github.com:rtCamp/wp-framework.git", - "reference": "f90373b867266e4e12959b487b600c383b4c3328" + "reference": "de18dff78d39b4a4cc5a6aaef39251db19751c32" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/rtCamp/wp-framework/zipball/f90373b867266e4e12959b487b600c383b4c3328", - "reference": "f90373b867266e4e12959b487b600c383b4c3328", + "url": "https://api.github.com/repos/rtCamp/wp-framework/zipball/de18dff78d39b4a4cc5a6aaef39251db19751c32", + "reference": "de18dff78d39b4a4cc5a6aaef39251db19751c32", "shasum": "" }, "require": { @@ -53,7 +53,7 @@ "phpcbf" ], "analyse": [ - "phpstan analyse" + "phpstan analyse --memory-limit=1G" ], "test": [ "phpunit" @@ -72,7 +72,7 @@ "source": "https://github.com/rtCamp/wp-framework/tree/framework", "issues": "https://github.com/rtCamp/wp-framework/issues" }, - "time": "2026-05-21T20:47:25+00:00" + "time": "2026-05-21T23:13:32+00:00" } ], "packages-dev": [ @@ -849,16 +849,16 @@ }, { "name": "php-stubs/wordpress-stubs", - "version": "v6.9.1", + "version": "v6.9.4", "source": { "type": "git", "url": "https://github.com/php-stubs/wordpress-stubs.git", - "reference": "f12220f303e0d7c0844c0e5e957b0c3cee48d2f7" + "reference": "90a9412826b9944f93b10bf41d795b5fe68abcd5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-stubs/wordpress-stubs/zipball/f12220f303e0d7c0844c0e5e957b0c3cee48d2f7", - "reference": "f12220f303e0d7c0844c0e5e957b0c3cee48d2f7", + "url": "https://api.github.com/repos/php-stubs/wordpress-stubs/zipball/90a9412826b9944f93b10bf41d795b5fe68abcd5", + "reference": "90a9412826b9944f93b10bf41d795b5fe68abcd5", "shasum": "" }, "conflict": { @@ -868,7 +868,7 @@ "dealerdirect/phpcodesniffer-composer-installer": "^1.0", "nikic/php-parser": "^5.5", "php": "^7.4 || ^8.0", - "php-stubs/generator": "^0.8.3", + "php-stubs/generator": "^0.8.6", "phpdocumentor/reflection-docblock": "^6.0", "phpstan/phpstan": "^2.1", "phpunit/phpunit": "^9.5", @@ -895,9 +895,9 @@ ], "support": { "issues": "https://github.com/php-stubs/wordpress-stubs/issues", - "source": "https://github.com/php-stubs/wordpress-stubs/tree/v6.9.1" + "source": "https://github.com/php-stubs/wordpress-stubs/tree/v6.9.4" }, - "time": "2026-02-03T19:29:21+00:00" + "time": "2026-05-01T20:36:01+00:00" }, { "name": "php-stubs/wp-cli-stubs", diff --git a/inc/Modules/Settings/ThemeOptions.php b/inc/Modules/Settings/ThemeOptions.php index 691ade37..4a5e8d55 100644 --- a/inc/Modules/Settings/ThemeOptions.php +++ b/inc/Modules/Settings/ThemeOptions.php @@ -2,8 +2,18 @@ /** * Example Settings Page: Theme Options. * - * Demonstrates how to use AbstractSettingsPage from wp-framework. - * Registers a settings page under Settings → Elementary with a few options. + * Demonstrates a clean, declarative settings page built on AbstractSettingsPage + * and the WordPress Settings API: + * + * - get_fields() is the single source of truth for every option on the + * page: option name, type, default, sanitize callback, REST exposure, + * plus the UI metadata (label, description). + * - register_settings() registers the options via the parent, then attaches + * a section + one field per entry via the Settings API. + * - render_field() is a generic input renderer — adding another field is a + * one-entry change in get_fields(), no HTML to touch. + * + * Copy this class as a starting point for any backend-driven settings page. * * @package rtCamp\Theme\Elementary\Modules\Settings */ @@ -12,7 +22,6 @@ namespace rtCamp\Theme\Elementary\Modules\Settings; -use Override; use rtCamp\WPFramework\Contracts\Abstracts\AbstractSettingsPage; /** @@ -21,10 +30,15 @@ class ThemeOptions extends AbstractSettingsPage { /** - * Option key prefix. + * Option key prefix — every option name on this page starts with it. */ private const PREFIX = 'elementary_'; + /** + * Settings section ID. Sections group fields visually on the page. + */ + private const SECTION = 'elementary_main_section'; + /** * {@inheritDoc} */ @@ -47,17 +61,26 @@ protected function get_menu_title(): string { } /** - * {@inheritDoc} + * Single source of truth for every field on this page. + * + * Combines register_setting() args (type, default, sanitize_callback, + * show_in_rest) with UI metadata (label, description) consumed by the + * Settings API field registration in register_settings(). + * + * @return array, + * }> */ - protected function get_settings(): array { + protected function get_fields(): array { return [ - self::PREFIX . 'enable_portfolio' => [ - 'type' => 'boolean', - 'default' => true, - 'sanitize_callback' => 'rest_sanitize_boolean', - 'show_in_rest' => true, - ], - self::PREFIX . 'footer_text' => [ + self::PREFIX . 'example_text' => [ + 'label' => __( 'Example Text', 'elementary-theme' ), + 'description' => __( 'A demo text field saved as a WordPress option.', 'elementary-theme' ), 'type' => 'string', 'default' => '', 'sanitize_callback' => 'sanitize_text_field', @@ -68,8 +91,81 @@ protected function get_settings(): array { /** * {@inheritDoc} + * + * Derives the register_setting() args from get_fields() by stripping + * the UI-only keys. + */ + protected function get_settings(): array { + $settings = []; + + foreach ( $this->get_fields() as $name => $field ) { + unset( $field['label'], $field['description'] ); + $settings[ $name ] = $field; + } + + return $settings; + } + + /** + * {@inheritDoc} + * + * Lets the parent register the options, then registers a settings + * section and one field per option for the UI. + */ + public function register_settings(): void { + parent::register_settings(); + + add_settings_section( + self::SECTION, + __( 'Theme Options', 'elementary-theme' ), + [ $this, 'render_section' ], + static::get_slug() + ); + + foreach ( $this->get_fields() as $name => $field ) { + add_settings_field( + $name, + $field['label'], + [ $this, 'render_field' ], + static::get_slug(), + self::SECTION, + [ + 'name' => $name, + 'default' => $field['default'] ?? '', + 'description' => $field['description'] ?? '', + 'label_for' => $name, + ] + ); + } + } + + /** + * Optional section blurb shown above the fields. */ - + public function render_section(): void { + echo '

' . esc_html__( 'Theme-wide options exposed to the editor and front-end.', 'elementary-theme' ) . '

'; + } + + /** + * Render a single text input. To support additional input types + * (checkbox, select, …), branch on a `type` arg here. + * + * @param array $args Field args passed via add_settings_field(). + */ + public function render_field( array $args ): void { + $name = $args['name']; + $value = get_option( $name, $args['default'] ); + + printf( + '', + esc_attr( $name ), + esc_attr( (string) $value ) + ); + + if ( '' !== $args['description'] ) { + printf( '

%s

', esc_html( $args['description'] ) ); + } + } /** * {@inheritDoc} @@ -82,32 +178,8 @@ public function render(): void { - - - - - - - - - -
- - /> -
- -
- Date: Fri, 22 May 2026 18:10:23 +0530 Subject: [PATCH 10/13] Refactor documentation for the theme --- DEVELOPMENT.md | 151 ++++++++++++++++++++----------- README.md | 29 ++++-- composer.json | 8 +- composer.lock | 8 +- inc/Helpers/Util.php | 30 ++++++ inc/helpers/custom-functions.php | 10 -- 6 files changed, 153 insertions(+), 83 deletions(-) create mode 100644 inc/Helpers/Util.php delete mode 100644 inc/helpers/custom-functions.php diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 076d4819..846a6079 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -1,86 +1,133 @@ # Development Guide -## PSR-4 Namespace Convention +## Architecture overview -All namespaced PHP classes live under `inc/` using the `rtCamp\Theme\Elementary\` root namespace. -The file path must map to the namespace and class name. +The theme is split into two layers: -Examples: +- **`vendor/rtcamp/wp-framework/`** — The upstream framework, installed as a Composer dependency. Provides reusable scaffolding (`Singleton`, `Loader`, `Container`, `AssetLoaderTrait`, `TemplateLoaderTrait`) and abstract base classes (`AbstractSettingsPage`, `AbstractPostType`, etc.). **Do not modify.** Changes belong in the framework repository. +- **`inc/`** — All theme-specific code. Extends framework abstracts, registers theme services, and bootstraps the theme. -- `inc/Main.php` → `rtCamp\Theme\Elementary\Main` -- `inc/Core/Assets.php` → `rtCamp\Theme\Elementary\Core\Assets` -- `inc/BlockExtensions/MediaTextInteractive.php` → `rtCamp\Theme\Elementary\Modules\BlockExtensions\MediaTextInteractive` -- `inc/Framework/Traits/Singleton.php` → `rtCamp\Theme\Elementary\Framework\Traits\Singleton` +The `vendor/` boundary enforces the rule by convention: editing files there gets blown away on every `composer install`. -## Directory tree +## PSR-4 namespace convention -The `inc/` directory follows a PSR-4 structure and is split into meaningful areas: +Single PSR-4 root, declared in `composer.json`: -- `inc/Framework/` - - Upstream-owned framework code. - - Base traits, contracts, and utilities. - - Do not modify in downstream themes unless there is no other option. -- `inc/Main.php` - - Theme bootstrap entry point. - - Defines the primary theme class under `rtCamp\Theme\Elementary`. -- `inc/Core/` - - Project-specific core classes. - - Example: asset loading, theme setup, shared services. -- `inc/BlockExtensions/` - - Project-specific block extension classes. - - Example: block render filters, block-specific integrations. -- `inc/helpers/` - - Non-namespaced helper files. - - Loaded via Composer `files` autoload and not subject to PSR-4 class name rules. +```json +"autoload": { + "psr-4": { + "rtCamp\\Theme\\Elementary\\": "inc/" + } +} +``` + +Directory segments map 1:1 to namespace segments. Files are PascalCase. -## Two-layer model +| Namespace | File | +|------------------------------------------------------------------------|-------------------------------------------------------| +| `rtCamp\Theme\Elementary\Main` | `inc/Main.php` | +| `rtCamp\Theme\Elementary\Autoloader` | `inc/Autoloader.php` | +| `rtCamp\Theme\Elementary\Core\Assets` | `inc/Core/Assets.php` | +| `rtCamp\Theme\Elementary\Modules\BlockExtensions\MediaTextInteractive` | `inc/Modules/BlockExtensions/MediaTextInteractive.php`| +| `rtCamp\Theme\Elementary\Modules\Settings\ThemeOptions` | `inc/Modules/Settings/ThemeOptions.php` | +| `rtCamp\Theme\Elementary\Helpers\Util` | `inc/Helpers/Util.php` | -The repository is split into two layers: +## Directory layout -- `inc/Framework/` — upstream-owned framework code. Do not modify in downstream projects. -- `inc/` (outside `Framework/`) — project-specific implementation and customizations. +``` +inc/ +├── Autoloader.php # Wraps vendor/autoload.php with graceful failure +├── Main.php # Theme bootstrap — loads services +├── Helpers/ # Stateless static utility classes (final, private __construct) +│ └── Util.php # General-purpose helpers (add static methods as needed) +├── Core/ # Theme-wide infrastructure +│ └── Assets.php # Asset registration (uses AssetLoaderTrait) +└── Modules/ # Feature areas + ├── BlockExtensions/ # Block render filters and integrations + │ └── MediaTextInteractive.php + └── Settings/ # Admin settings pages (extend AbstractSettingsPage) + └── ThemeOptions.php +``` -### `inc/Framework/` +## Helpers -This is the base layer. It should contain only reusable traits, interfaces, and low-level utilities. -Treat it like vendored code. If you need to change behavior, extend the framework class in `inc/` instead. +`inc/Helpers/` is the home for stateless utility classes — `final`, `private __construct()`, static methods only. Today it holds one class, `Util`, kept as a placeholder for theme-wide helpers that don't earn their own dedicated class. Add siblings (e.g. `Str`, `Cache`, `Url`) as cross-cutting helpers accumulate, rather than letting `Util` grow into a grab-bag. -### `inc/` +## Picking a base -This is the application layer for this theme. Add new feature classes, hooks, and theme-specific behavior here. +| Feature | Extends / implements | +|------------------------------------------|-------------------------------------| +| Settings page | `AbstractSettingsPage` | +| Admin (non-settings) page | `AbstractAdminPage` | +| Dynamic block (server-side render) | `AbstractBlock` | +| REST controller | `AbstractRESTController` | +| Shortcode | `AbstractShortcode` | +| Anything else that just wires hooks | `Registrable` interface | +| Same, but registration is conditional | `ConditionallyRegistrable` interface| ## Adding a new class -1. Create a new PHP file under `inc/` using PascalCase file names. -2. Use the matching namespace path. -3. Define the class name to match the filename exactly. -4. If the class belongs to a feature group, create a subdirectory and namespace that group. +1. Pick the right abstract or interface from the table above. +2. Drop the file in the matching `inc/Modules//` directory (or `inc/Core/` if it's theme-wide infrastructure). +3. Register it in `Main::__construct()`'s `$this->load( [ … ] )` call. +4. Run `composer dump-autoload`. Example: -`inc/Example/Feature.php` - ```php -namespace rtCamp\Theme\Elementary\Example; +// inc/Modules/Example/Feature.php +namespace rtCamp\Theme\Elementary\Modules\Example; + +use rtCamp\WPFramework\Contracts\Interfaces\Registrable; -class Feature { - // ... +final class Feature implements Registrable { + public function register_hooks(): void { + add_action( 'init', [ $this, 'do_something' ] ); + } + + public function do_something(): void { + // ... + } } ``` -## Existing non-namespaced file +Then in `Main::__construct()`: + +```php +$this->load( [ + Assets::class, + MediaTextInteractive::class, + ThemeOptions::class, + \rtCamp\Theme\Elementary\Modules\Example\Feature::class, +] ); +``` + +## Conditional registration -`inc/helpers/custom-functions.php` is intentionally not namespaced and remains loaded through Composer `files` autoload. +A class can opt out of registration at runtime by implementing `ConditionallyRegistrable` instead of `Registrable`: -## Running autoload generation +```php +final class DevToolbarExtension implements ConditionallyRegistrable { + public function can_register(): bool { + return defined( 'WP_DEBUG' ) && WP_DEBUG; + } + + public function register_hooks(): void { + // Wire dev-only hooks here. + } +} +``` + +The `Loader` calls `can_register()` first and skips `register_hooks()` when it returns false. -After moving or adding namespaced classes, regenerate Composer autoload files: +## Running Composer ```bash +# First-time setup +composer install + +# After adding, renaming, or moving a class composer dump-autoload ``` -## Notes - -- Do not use `classmap` autoloading for namespaced classes. -- Keep the `rtCamp\Theme\Elementary\` PSR-4 root aligned with `inc/`. +If `vendor/autoload.php` is missing at runtime, the theme shows an admin notice instead of fataling — see `inc/Autoloader.php` and `AutoloaderTrait` in the framework. diff --git a/README.md b/README.md index 1311e193..5e761bb2 100644 --- a/README.md +++ b/README.md @@ -4,13 +4,17 @@ A starter theme that facilitates a quick head start for developing new [block-based themes](https://developer.wordpress.org/block-editor/how-to-guides/themes/block-theme-overview/) along with a bunch of developer-friendly features. -- [Understand the Folder Structure](https://github.com/rtCamp/theme-elementary#understand-the-folder-structure-open_file_folder) -- [Get Started](https://github.com/rtCamp/theme-elementary#get-started-rocket) -- [Development](https://github.com/rtCamp/theme-elementary#development-computer) +Reusable scaffolding (singleton, autoloader, asset loader, template loader, and abstract base classes) ships separately as the `rtcamp/wp-framework` Composer package and is loaded from `vendor/`. + +> **Working on this theme?** See [DEVELOPMENT.md](DEVELOPMENT.md) for the architecture overview, the module pattern, and how to add new classes. + +- [Understand the Folder Structure](#understand-the-folder-structure-open_file_folder) +- [Get Started](#get-started-rocket) +- [Development](#development-computer) ## Understand the Folder Structure :open_file_folder: ``` - . +. ├── src (Frontend source) │ ├── css │ │ ├── frontend/ @@ -30,11 +34,14 @@ A starter theme that facilitates a quick head start for developing new [block-ba │ └── build (Compiled output) ├── bin (Holds scripts) ├── functions.php (PHP entry point) -├── inc -│ ├── Core/ (Project-specific core classes) -│ ├── BlockExtensions/ (Block extension classes) -│ ├── Framework/ (Upstream framework code) -│ └── helpers/ (Non-namespaced helpers) +├── inc (All project-specific PHP — PSR-4 root) +│ ├── Autoloader.php (Wraps vendor/autoload.php with graceful failure) +│ ├── Main.php (Theme bootstrap — loads services) +│ ├── Helpers/ (Stateless static utility classes) +│ ├── Core/ (Theme-wide infrastructure — assets, etc.) +│ └── Modules/ (Feature areas) +│ ├── BlockExtensions/ (Block render filters and integrations) +│ └── Settings/ (Admin settings pages — extend AbstractSettingsPage) ├── parts (Block Template Parts) ├── patterns (Block Patterns) ├── style.css @@ -42,8 +49,10 @@ A starter theme that facilitates a quick head start for developing new [block-ba ├── tests (Holds JS & PHP tests) │ ├── js/ │ └── php/ +├── vendor +│ └── rtcamp/wp-framework/ (Framework — do not modify; Composer-managed) +├── DEVELOPMENT.md └── theme.json - ``` ## Get Started :rocket: diff --git a/composer.json b/composer.json index 8c8f0960..c724b4d5 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,8 @@ "repositories": [ { "type": "vcs", - "url": "https://github.com/rtCamp/wp-framework.git" + "url": "https://github.com/rtCamp/wp-framework.git", + "no-api": true } ], "require": { @@ -41,10 +42,7 @@ "autoload": { "psr-4": { "rtCamp\\Theme\\Elementary\\": "inc/" - }, - "files": [ - "inc/helpers/custom-functions.php" - ] + } }, "autoload-dev": { "psr-4": { diff --git a/composer.lock b/composer.lock index dd49ad42..776e4b5e 100644 --- a/composer.lock +++ b/composer.lock @@ -4,14 +4,14 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "c06d2133e4ca5db89754e6392a00aa00", + "content-hash": "5c9d115741ba03076111d8506b4f0895", "packages": [ { "name": "rtcamp/wp-framework", "version": "dev-framework", "source": { "type": "git", - "url": "git@github.com:rtCamp/wp-framework.git", + "url": "https://github.com/rtCamp/wp-framework.git", "reference": "de18dff78d39b4a4cc5a6aaef39251db19751c32" }, "dist": { @@ -68,10 +68,6 @@ "GPL-2.0-or-later" ], "description": "A reusable WordPress framework providing composable traits, abstract classes, and interfaces for plugins and themes.", - "support": { - "source": "https://github.com/rtCamp/wp-framework/tree/framework", - "issues": "https://github.com/rtCamp/wp-framework/issues" - }, "time": "2026-05-21T23:13:32+00:00" } ], diff --git a/inc/Helpers/Util.php b/inc/Helpers/Util.php new file mode 100644 index 00000000..cd8b2924 --- /dev/null +++ b/inc/Helpers/Util.php @@ -0,0 +1,30 @@ + Date: Fri, 22 May 2026 18:44:11 +0530 Subject: [PATCH 11/13] Add check for git in CI --- .github/workflows/test-measure.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/test-measure.yml b/.github/workflows/test-measure.yml index 4c2c5a22..36dae896 100644 --- a/.github/workflows/test-measure.yml +++ b/.github/workflows/test-measure.yml @@ -175,6 +175,9 @@ jobs: restore-keys: | ${{ runner.os }}-composer- + - name: Ensure git is installed + run: which git || (sudo apt-get update && sudo apt-get install -y git) + - name: Install Composer dependencies run: composer install --prefer-dist --optimize-autoloader --no-progress --no-interaction --no-scripts From 4caa7cc66f1ef8409d14adc182d15f664d8e2b18 Mon Sep 17 00:00:00 2001 From: pratik-londhe4 Date: Fri, 22 May 2026 18:53:23 +0530 Subject: [PATCH 12/13] Update workflow to provide container access to token for Framework package --- .github/workflows/test-measure.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/test-measure.yml b/.github/workflows/test-measure.yml index 36dae896..81dcd42a 100644 --- a/.github/workflows/test-measure.yml +++ b/.github/workflows/test-measure.yml @@ -202,6 +202,14 @@ jobs: - name: Start WP environment run: npm run wp-env start + # The tests-cli container runs its own `composer install` before tests + # (via the pretest:php npm hook), so it needs the GitHub PAT configured + # inside the container — the host's auth isn't inherited. + - name: Configure Composer GitHub auth inside wp-env container + run: npx wp-env run tests-cli composer config --global --no-interaction github-oauth.github.com "$WP_FRAMEWORK_REPO_TOKEN" + env: + WP_FRAMEWORK_REPO_TOKEN: ${{ secrets.WP_FRAMEWORK_REPO_TEMP_TOKEN }} + - name: Run tests run: npm run test:php From 57f2c63fc9e3c87093d8ab1ce56aff6c0df01f3b Mon Sep 17 00:00:00 2001 From: pratik-londhe4 Date: Fri, 22 May 2026 19:00:46 +0530 Subject: [PATCH 13/13] Bring same workflow for theme as skeleton plugin --- .github/workflows/test-measure.yml | 28 +--------------------------- 1 file changed, 1 insertion(+), 27 deletions(-) diff --git a/.github/workflows/test-measure.yml b/.github/workflows/test-measure.yml index 81dcd42a..5f6e4f81 100644 --- a/.github/workflows/test-measure.yml +++ b/.github/workflows/test-measure.yml @@ -88,7 +88,7 @@ jobs: [[ "${{ steps.determine-file-counts.outputs.css-count }}" -le 0 ]] && SKIPPED+=("lint-css") [[ "${{ steps.determine-file-counts.outputs.js-count }}" -le 0 ]] && SKIPPED+=("lint-js" "unit-tests-js" "build-prod") - [[ "${{ steps.determine-file-counts.outputs.php-count }}" -le 0 ]] && SKIPPED+=("lint-php" "unit-test-php") + [[ "${{ steps.determine-file-counts.outputs.php-count }}" -le 0 ]] && SKIPPED+=("lint-php") if [[ ${#SKIPPED[@]} -gt 0 ]]; then echo "The following jobs will be skipped as no relevant files were changed:" @@ -187,32 +187,6 @@ jobs: - name: Detect coding standard violations (PHPCS) run: vendor/bin/phpcs -q --report=checkstyle --runtime-set ignore_errors_on_exit 1 --runtime-set ignore_warnings_on_exit 1 | cs2pr --graceful-warnings - unit-test-php: - needs: pre-run - if: needs.pre-run.outputs.changed-php-count > 0 - name: "PHP Unit test" - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v6 - - - name: Setup Node with cache - uses: ./.github/actions/setup-node-with-cache - - - name: Start WP environment - run: npm run wp-env start - - # The tests-cli container runs its own `composer install` before tests - # (via the pretest:php npm hook), so it needs the GitHub PAT configured - # inside the container — the host's auth isn't inherited. - - name: Configure Composer GitHub auth inside wp-env container - run: npx wp-env run tests-cli composer config --global --no-interaction github-oauth.github.com "$WP_FRAMEWORK_REPO_TOKEN" - env: - WP_FRAMEWORK_REPO_TOKEN: ${{ secrets.WP_FRAMEWORK_REPO_TEMP_TOKEN }} - - - name: Run tests - run: npm run test:php - build-prod: needs: pre-run if: needs.pre-run.outputs.changed-js-count > 0 || needs.pre-run.outputs.changed-css-count > 0