From c27bbab97692da7d6ee525b99adc2348d93143fa Mon Sep 17 00:00:00 2001 From: webbrain-one <295484252+webbrain-one@users.noreply.github.com> Date: Fri, 11 Sep 2026 06:32:49 +0300 Subject: [PATCH 01/12] docs: improve README --- readme.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index f447c23..582ca08 100644 --- a/readme.md +++ b/readme.md @@ -1,3 +1,5 @@ + + # Cooked - A Modern and Customizable Recipe Plugin for WordPress Cooked is the absolute best way to create & display recipes with WordPress. SEO optimized (rich snippets), galleries, cooking timers, printable recipes and much more. @@ -125,7 +127,7 @@ bun run lint-fix # auto-fix violations **PHPUnit** — Run the test suite (14 test classes covering CSV import, recipes, settings, SEO, and more): ``` bash -bun run test +bun run test:php ``` Tests are in `tests/phpunit/` with CSV fixtures in `tests/test_data/`. Requires a running wp-env or DDEV environment. From e11887b7aa93e87426c58e315728f9dc8374ac0e Mon Sep 17 00:00:00 2001 From: mgiannopoulos24 <79588074+mgiannopoulos24@users.noreply.github.com> Date: Fri, 11 Sep 2026 23:14:59 +0300 Subject: [PATCH 02/12] Package updates and PHPCS fixes. --- .wp-env.json | 4 +- bun.lock | 76 ++++++------ package.json | 12 +- phpcs.xml | 2 +- templates/admin/import.php | 124 +++++++++++--------- templates/admin/pro.php | 64 ++++++---- templates/admin/settings.php | 218 +++++++++++++++++++---------------- templates/admin/welcome.php | 97 +++++++++------- 8 files changed, 335 insertions(+), 262 deletions(-) diff --git a/.wp-env.json b/.wp-env.json index b2b9780..51f19a3 100644 --- a/.wp-env.json +++ b/.wp-env.json @@ -1,6 +1,6 @@ { "core": null, - "phpVersion": "7.4", + "phpVersion": "8.1", "themes": ["WordPress/twentytwentyfive"], "plugins": [ "https://downloads.wordpress.org/plugin/plugin-check.zip" @@ -19,6 +19,6 @@ "DISALLOW_FILE_EDIT": false }, "lifecycleScripts": { - "afterStart": "wp-env run cli bash -c 'curl -fsSL -o /tmp/wp-cli.phar https://github.com/wp-cli/builds/raw/gh-pages/phar/wp-cli.phar && chmod +x /tmp/wp-cli.phar && sudo cp /tmp/wp-cli.phar /usr/local/bin/wp && sudo chmod +x /usr/local/bin/wp'" + "afterStart": "wp-env run cli wp plugin activate cooked" } } diff --git a/bun.lock b/bun.lock index c228ee1..661f34e 100644 --- a/bun.lock +++ b/bun.lock @@ -7,11 +7,11 @@ "devDependencies": { "@axe-core/playwright": "^4.13.0", "@playwright/test": "^1.63.0", - "@types/node": "^26.4.1", + "@types/node": "^26.5.1", "@wordpress/e2e-test-utils-playwright": "^1.54.0", - "@wordpress/env": "^11.14.0", + "@wordpress/env": "^11.15.0", "backstopjs": "^6.3.25", - "bestzip": "^3.0.3", + "bestzip": "^3.1.0", "dotenv": "^17.4.2", "gulp": "^5.0.1", "gulp-clean-css": "^4.3.0", @@ -228,41 +228,41 @@ "@paulirish/trace_engine": ["@paulirish/trace_engine@0.0.59", "", { "dependencies": { "legacy-javascript": "latest", "third-party-web": "latest" } }, "sha512-439NUzQGmH+9Y017/xCchBP9571J4bzhpcNhrxorf7r37wcyJZkgUfrUsRL3xl+JDcZ6ORhoFCzCw98c6S3YHw=="], - "@php-wasm/cli-util": ["@php-wasm/cli-util@3.1.52", "", { "dependencies": { "@php-wasm/util": "3.1.52", "fast-xml-parser": "^5.8.0", "jsonc-parser": "3.3.1" } }, "sha512-/YP0JqY+l5SjB/kn3yeOe/Kdo88xUkIis3xbhtMivuARTBtxYC7tdHpW1uxJiw6dkmHR89tVFxiPA9PiZdS0/g=="], + "@php-wasm/cli-util": ["@php-wasm/cli-util@3.1.53", "", { "dependencies": { "@php-wasm/util": "3.1.53", "fast-xml-parser": "^5.8.0", "jsonc-parser": "3.3.1" } }, "sha512-Q1o/whl3Om1TnvNfslDprgGhuPjdLP8mNcc2cgHXA44fvb0zea9tKYikkTsZJAUNiWrbzTUJit6lhByqQ9/Jpw=="], - "@php-wasm/logger": ["@php-wasm/logger@3.1.52", "", {}, "sha512-Hr/pKVE4HPjQP4rwvAlZm0DvcEHlVFesHgAvASEc5LgOaKbULy7SVYvtozuuh1e+24Hg1n6CoxA0fKL+nsp+Dg=="], + "@php-wasm/logger": ["@php-wasm/logger@3.1.53", "", {}, "sha512-0qzKmxKlkjPwEXrOuy00Q3gsHxljrrgXbrsGMj0tqKmu4B8gTJnQB8BbDZA93C3fEDc0gXyxeKvask8FseKfZw=="], - "@php-wasm/node": ["@php-wasm/node@3.1.52", "", { "dependencies": { "@php-wasm/cli-util": "3.1.52", "@php-wasm/logger": "3.1.52", "@php-wasm/node-5-2": "3.1.52", "@php-wasm/node-7-4": "3.1.52", "@php-wasm/node-8-0": "3.1.52", "@php-wasm/node-8-1": "3.1.52", "@php-wasm/node-8-2": "3.1.52", "@php-wasm/node-8-3": "3.1.52", "@php-wasm/node-8-4": "3.1.52", "@php-wasm/node-8-5": "3.1.52", "@php-wasm/universal": "3.1.52", "@php-wasm/util": "3.1.52", "fs-ext-extra-prebuilt": "2.2.7", "wasm-feature-detect": "1.8.0", "ws": "8.21.0" } }, "sha512-5fRw4dMvLGfRKHLZ7iGANVNQ8eGcq8Of91NcKo6qW8TorAIwAhTz+RQHuFtjI2zC7bq21E3IHxLa2I8338yX5A=="], + "@php-wasm/node": ["@php-wasm/node@3.1.53", "", { "dependencies": { "@php-wasm/cli-util": "3.1.53", "@php-wasm/logger": "3.1.53", "@php-wasm/node-5-2": "3.1.53", "@php-wasm/node-7-4": "3.1.53", "@php-wasm/node-8-0": "3.1.53", "@php-wasm/node-8-1": "3.1.53", "@php-wasm/node-8-2": "3.1.53", "@php-wasm/node-8-3": "3.1.53", "@php-wasm/node-8-4": "3.1.53", "@php-wasm/node-8-5": "3.1.53", "@php-wasm/universal": "3.1.53", "@php-wasm/util": "3.1.53", "fs-ext-extra-prebuilt": "2.2.7", "wasm-feature-detect": "1.8.0", "ws": "8.21.0" } }, "sha512-43dbVxcq2N0f9DXE0i54WjLYGPySHzfz+IQwZVSLVSDCskKrgUTqhxOfko9LtIVNMZTa+2aVrvjvrp1ZzlJ4vw=="], - "@php-wasm/node-5-2": ["@php-wasm/node-5-2@3.1.52", "", { "dependencies": { "@php-wasm/universal": "3.1.52", "wasm-feature-detect": "1.8.0" } }, "sha512-z/RzVUr9NPPIe/41VWyJJ5YETEbHwkbq9Jk5fLgc9xhkBDh8EmKRz3MptgvcQyF1IZyuPW4ADe3AZ+R24LrjQw=="], + "@php-wasm/node-5-2": ["@php-wasm/node-5-2@3.1.53", "", { "dependencies": { "@php-wasm/universal": "3.1.53", "wasm-feature-detect": "1.8.0" } }, "sha512-Wbn1Zue5SlC26ejaDTQnFS96SCYFqq8NHH60QB8YAFIRTCUev3gYN14n/v7eZkbD1NyylAJum6RwBtBr6ksdcA=="], - "@php-wasm/node-7-4": ["@php-wasm/node-7-4@3.1.52", "", { "dependencies": { "@php-wasm/universal": "3.1.52", "wasm-feature-detect": "1.8.0" } }, "sha512-e31adpo6SOl7mlptVpHCJwtlDNZWbP/KvPVmkYubs5wtstAzY8YeGzYWndGDUh43SqBr+zxiB9CH2B77IgAyIg=="], + "@php-wasm/node-7-4": ["@php-wasm/node-7-4@3.1.53", "", { "dependencies": { "@php-wasm/universal": "3.1.53", "wasm-feature-detect": "1.8.0" } }, "sha512-4ffIMlXy6vZnHfkJsBKgm2rQqtiYoWMBZ0D/J1jYaybStZYYLnzqn03kyqgZLfuJfOeuCzfWMDnBUtjpP6JqIA=="], - "@php-wasm/node-8-0": ["@php-wasm/node-8-0@3.1.52", "", { "dependencies": { "@php-wasm/universal": "3.1.52", "wasm-feature-detect": "1.8.0" } }, "sha512-+Po4d45fSqxgbPPeYRP7XNdc1oCGOWbuxluB0jJthA60LaTtLC4JEQ2B02BhE07gB2W+Nmvvf+HHY3e05JrvQw=="], + "@php-wasm/node-8-0": ["@php-wasm/node-8-0@3.1.53", "", { "dependencies": { "@php-wasm/universal": "3.1.53", "wasm-feature-detect": "1.8.0" } }, "sha512-Ua3VfQWSjhZFXHK5RdVVxgYTQGHIjaLd004jbQh54jDlTcSTOUjRYTRmr06Bqxy7hb34C49J8C/TNuhjAbJiHQ=="], - "@php-wasm/node-8-1": ["@php-wasm/node-8-1@3.1.52", "", { "dependencies": { "@php-wasm/universal": "3.1.52", "wasm-feature-detect": "1.8.0" } }, "sha512-H6wh4NDRTvDanVnumhN5dpSCUsKqBujW/84hHQcyZURGTS36frp1Runr5mmapRF/ZpyH7q+uG1kFzYEYkZIlaQ=="], + "@php-wasm/node-8-1": ["@php-wasm/node-8-1@3.1.53", "", { "dependencies": { "@php-wasm/universal": "3.1.53", "wasm-feature-detect": "1.8.0" } }, "sha512-Tz/xqTFfWmFBMpak8ij8sWlxDOcywkVAr2sG/4RqZmKXDN0AxVk835n2NSFgywweml8y61KyWArA604HTZzswQ=="], - "@php-wasm/node-8-2": ["@php-wasm/node-8-2@3.1.52", "", { "dependencies": { "@php-wasm/universal": "3.1.52", "wasm-feature-detect": "1.8.0" } }, "sha512-+PIiU8whNov93e3VnojZik0dDciRkqwd+j2+nm4VDcXfHD9SewHP+k3chaUipTAhDDx8Q6fWYWa1CSGp5jrAtg=="], + "@php-wasm/node-8-2": ["@php-wasm/node-8-2@3.1.53", "", { "dependencies": { "@php-wasm/universal": "3.1.53", "wasm-feature-detect": "1.8.0" } }, "sha512-jBymMkweHA4lcZoGLbHeslofVu3xAvna3t/zhHvqsgouDWLpjCP+a2xXVgGDmy5vCnqNbqF8ygQQaUg9yQITjg=="], - "@php-wasm/node-8-3": ["@php-wasm/node-8-3@3.1.52", "", { "dependencies": { "@php-wasm/universal": "3.1.52", "wasm-feature-detect": "1.8.0" } }, "sha512-UNkxXw7qUfeS6jG0luztYGosZHZaVMiziaPwY6FFUH0FnHwhrtFpYLI86ksfOZMnS9BjDf7bryIrdr0160tIJQ=="], + "@php-wasm/node-8-3": ["@php-wasm/node-8-3@3.1.53", "", { "dependencies": { "@php-wasm/universal": "3.1.53", "wasm-feature-detect": "1.8.0" } }, "sha512-u1R4U58uvnjisVfCiFXX909XHE+PIs7bU1NfyuAk9RxRb07T1UgWEgZKQCjT63KUnm1NS+5eMCKiuL+8kbADIw=="], - "@php-wasm/node-8-4": ["@php-wasm/node-8-4@3.1.52", "", { "dependencies": { "@php-wasm/universal": "3.1.52", "wasm-feature-detect": "1.8.0" } }, "sha512-M7L3lU0co6dPPi3PHs3agG6eeOHAszyJfUq/KmrmRReBJNHyviEcHpaGKextGJArJLfMvAAZjrhGOWVMBrQc/w=="], + "@php-wasm/node-8-4": ["@php-wasm/node-8-4@3.1.53", "", { "dependencies": { "@php-wasm/universal": "3.1.53", "wasm-feature-detect": "1.8.0" } }, "sha512-/6jNdg2NL6TAKXAcsWXOimOx2t+VODQc0OduDQhNCP3Q96ycU6AXSMgberHFFtSoXpWMC5dfz89kRaUMzjoAgQ=="], - "@php-wasm/node-8-5": ["@php-wasm/node-8-5@3.1.52", "", { "dependencies": { "@php-wasm/universal": "3.1.52", "wasm-feature-detect": "1.8.0" } }, "sha512-7Y6EkujT5tUTiZKZYVsG8L7cAlLvpl6X5TX+SP1C7YZnxnpZBafX4j/4reQGrYTKdvrK/8NklRH73BQkXhYWhg=="], + "@php-wasm/node-8-5": ["@php-wasm/node-8-5@3.1.53", "", { "dependencies": { "@php-wasm/universal": "3.1.53", "wasm-feature-detect": "1.8.0" } }, "sha512-ZLr5UB5vXJ04zIdbmlwAzKKmRa5fjpSUtA34r99oJC/GsyitCGLYeec2mcPhMxTcT9JpIHwaYdCyFE1f3pQ8fw=="], - "@php-wasm/progress": ["@php-wasm/progress@3.1.52", "", { "dependencies": { "@php-wasm/logger": "3.1.52" } }, "sha512-Zr4pHQDyX+OhkiLm830x0nt38L6ZRK3cWJMJNYSxvhlN7YKEmTHoA8hifchIE7OfgpF++s0rORXoBvEX5MmteA=="], + "@php-wasm/progress": ["@php-wasm/progress@3.1.53", "", { "dependencies": { "@php-wasm/logger": "3.1.53" } }, "sha512-5JD0rohXr8wGW6SJ00hcsEhMzd1Q0nx8iv/TWwbCFVLAWUVg6/KnE09B2rIfbiLAum0g4ojuuSQMedhPBlpWdw=="], - "@php-wasm/scopes": ["@php-wasm/scopes@3.1.52", "", {}, "sha512-1+f6czXaQVtO+LT8Bx9gORg/dQ+L5M7Kkp1Bk69RJE9nde6ZO/ex/wLymCx0nORHN01k6csqG2j/Nnew4KLRLg=="], + "@php-wasm/scopes": ["@php-wasm/scopes@3.1.53", "", {}, "sha512-Jl3h5Gew6OUgeDyzh/d0vplhTmkuwW1e8TDB5sTvLgbY1cHWNaT11M09x4Ec/im5v8BLNB/UPkBYP8gl35JuhA=="], - "@php-wasm/stream-compression": ["@php-wasm/stream-compression@3.1.52", "", { "dependencies": { "@php-wasm/util": "3.1.52" } }, "sha512-RpCCUpF/BwPLbqhUWxHz4utRtu5gSM66SaCFQkxdjAGI5yitaptsu1W6Z7Wp2UDabF3g1qfKfDog0JQ3D9azcw=="], + "@php-wasm/stream-compression": ["@php-wasm/stream-compression@3.1.53", "", { "dependencies": { "@php-wasm/util": "3.1.53" } }, "sha512-nJ95ja4L6mC40A6p0zZeYEiUe2PGecLxdbfFVsdSvIcv4mOQ2btPhzitHphBYfBOpl+tYbPWZ9i2M+3jqxffPA=="], - "@php-wasm/universal": ["@php-wasm/universal@3.1.52", "", { "dependencies": { "@php-wasm/logger": "3.1.52", "@php-wasm/progress": "3.1.52", "@php-wasm/stream-compression": "3.1.52", "@php-wasm/util": "3.1.52", "ini": "4.1.2" } }, "sha512-vgEV73SfpECzcCuTmr8+tGEzK6syk0p2I6E5CX2kJaE1/prCc4x5DyZtQ0dwhnzcEGrbhKDL2mpxxgl4B9fQOA=="], + "@php-wasm/universal": ["@php-wasm/universal@3.1.53", "", { "dependencies": { "@php-wasm/logger": "3.1.53", "@php-wasm/progress": "3.1.53", "@php-wasm/stream-compression": "3.1.53", "@php-wasm/util": "3.1.53", "ini": "4.1.2" } }, "sha512-pQIBdxJWmkOkQLRqSL/F1LYZB9aqIVGc6ZEUDo7fLY3dlqzoYgo579ji3gdt+jiCs7DzdWiW57v7f7SbjnW/Ow=="], - "@php-wasm/util": ["@php-wasm/util@3.1.52", "", {}, "sha512-lwxtwyIXEO8537eCv5iBfx1WW+DhSYc6obgtTQ6Up85GbHCE050n0RbOWva4XBu7T3Y5PfQshPoPccM/l14chA=="], + "@php-wasm/util": ["@php-wasm/util@3.1.53", "", {}, "sha512-80k5Xpv6GBfYymKFtRWBG66Y/rblHQQiaJZrj0JcGQNLR3z9uO4OIFhTyXCzyAgR82qEfhHPrv8tUchYGfoI4w=="], - "@php-wasm/web-service-worker": ["@php-wasm/web-service-worker@3.1.52", "", { "dependencies": { "@php-wasm/scopes": "3.1.52", "@php-wasm/universal": "3.1.52" } }, "sha512-jEajg31JjVEdLX9yeQ1pa34dtztfMiz6I5y20/LZ3NADO9NrSvcAPsjYf2NkN4cpUDz4mKs6hkOskA6gd1CVxw=="], + "@php-wasm/web-service-worker": ["@php-wasm/web-service-worker@3.1.53", "", { "dependencies": { "@php-wasm/scopes": "3.1.53", "@php-wasm/universal": "3.1.53" } }, "sha512-Tq+vsMBVLEIU9Rv/io9M3KqBv52KO9S18bweGslLd47Jh55GIWq8y+1pCPzp8XZsrQHPu7ry5cwuWqTdRp6C8A=="], - "@php-wasm/xdebug-bridge": ["@php-wasm/xdebug-bridge@3.1.52", "", { "dependencies": { "@php-wasm/logger": "3.1.52", "@php-wasm/universal": "3.1.52", "ws": "8.21.0", "xml2js": "0.6.2", "yargs": "17.7.2" }, "bin": { "xdebug-bridge": "xdebug-bridge.js" } }, "sha512-I5yMzjRe+Ivh6N2e5QSh8Fy3VN9WIv7YFhqFOlN3eq0UKCt3gDERCOtt96VMulWYH2m8qmYvpcX20h6p3T2Hyw=="], + "@php-wasm/xdebug-bridge": ["@php-wasm/xdebug-bridge@3.1.53", "", { "dependencies": { "@php-wasm/logger": "3.1.53", "@php-wasm/universal": "3.1.53", "ws": "8.21.0", "xml2js": "0.6.2", "yargs": "17.7.2" }, "bin": { "xdebug-bridge": "xdebug-bridge.js" } }, "sha512-k8r6MwsOdIDko47wTVQJK2nJK7XTGDMJzCWb6MqP8qSsi6/ug2odaijvD1qkZwkMPv71XhCYXuznM80N1xgLMQ=="], "@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="], @@ -308,7 +308,7 @@ "@types/mysql": ["@types/mysql@2.15.26", "", { "dependencies": { "@types/node": "*" } }, "sha512-DSLCOXhkvfS5WNNPbfn2KdICAmk8lLc+/PNvnPnF7gOdMZCxopXduqv0OQ13y/yA/zXTSikZZqVgybUxOEg6YQ=="], - "@types/node": ["@types/node@26.4.1", "", { "dependencies": { "undici-types": "~8.3.0" } }, "sha512-k97ENvZWtvA6yqz5/FS6a7duDgOPEeOQOc2iKS/nY6mX6qJUKtLnWzQS+Xj6tXweyj6ZcTAK2Qecetnvi9nCLA=="], + "@types/node": ["@types/node@26.5.1", "", { "dependencies": { "undici-types": "~8.9.0" } }, "sha512-CzNm2FezW4VR/LjG6yUdiEgLE/rAQ9Slj5gCu/C2VrdcW7I0ahNZ8DRbHT7zOZ6r3ONgd/bsQIeSaoDGrd1C6g=="], "@types/pg": ["@types/pg@8.6.1", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^2.2.0" } }, "sha512-1Kc4oAGzAl7uqUStZCDvaLFqZrW9qWSjXOmBfdgyBP5La7Us6Mg4GBvRlSoaZMhQF/zSj1C8CtKMBkoiT8eL8w=="], @@ -324,19 +324,19 @@ "@wordpress/e2e-test-utils-playwright": ["@wordpress/e2e-test-utils-playwright@1.54.0", "", { "dependencies": { "change-case": "^4.1.2", "get-port": "^5.1.1", "lighthouse": "^12.2.2", "mime": "^3.0.0", "web-vitals": "^4.2.1" }, "peerDependencies": { "@playwright/test": ">=1", "@types/node": "^20.17.10" } }, "sha512-xpsb5c8T8VXBBrYfr98OqK2yevtiHVwpVE+u0vqYBYgWNiqQJj8Eyq7geRdY6v4SctbAVe8vGFVV+DfPaEhvRg=="], - "@wordpress/env": ["@wordpress/env@11.14.0", "", { "dependencies": { "@inquirer/prompts": "^7.2.0", "@wp-playground/cli": "^3.0.48", "adm-zip": "^0.6.0", "chalk": "^4.1.1", "copy-dir": "^1.3.0", "cross-spawn": "^7.0.6", "docker-compose": "^0.24.3", "got": "^11.8.5", "js-yaml": "^3.15.0", "ora": "^4.0.2", "rimraf": "^5.0.10", "simple-git": "^3.32.3", "yargs": "^17.3.0" }, "bin": { "wp-env": "bin/wp-env" } }, "sha512-Q/XUhGjFJtlfybw/mq+7H5MsF2u3zWH5YxNR5y473+CeIjZx20wt5Dx0RDHAJcG2ICTky4pJevNlIq/EFnUwIQ=="], + "@wordpress/env": ["@wordpress/env@11.15.0", "", { "dependencies": { "@inquirer/prompts": "^7.2.0", "@wp-playground/cli": "^3.0.48", "adm-zip": "^0.6.0", "chalk": "^4.1.1", "copy-dir": "^1.3.0", "cross-spawn": "^7.0.6", "docker-compose": "^0.24.3", "got": "^11.8.5", "js-yaml": "^3.15.0", "ora": "^4.0.2", "rimraf": "^5.0.10", "simple-git": "^3.32.3", "yargs": "^17.3.0" }, "bin": { "wp-env": "bin/wp-env" } }, "sha512-FZq3eMDXBlZVZU8jVSX/4XoexgiBM4ZBqk69Mh23pz+1MMeQ13l7g5v7zKAAnyA3F9eHd+1sWsUpQnuS1f1T6Q=="], - "@wp-playground/blueprints": ["@wp-playground/blueprints@3.1.52", "", { "dependencies": { "@php-wasm/logger": "3.1.52", "@php-wasm/progress": "3.1.52", "@php-wasm/stream-compression": "3.1.52", "@php-wasm/universal": "3.1.52", "@php-wasm/util": "3.1.52", "@php-wasm/web-service-worker": "3.1.52", "@wp-playground/common": "3.1.52", "@wp-playground/storage": "3.1.52", "@wp-playground/wordpress": "3.1.52", "ajv": "8.18.0" } }, "sha512-K4QieiesG8MgZnKQerObS7dON4ngZCDt32aqnYLeaTiSJ2jFXqMcfBXH8MjFO3KVncJsTfU2euh8OtDV1fKkqA=="], + "@wp-playground/blueprints": ["@wp-playground/blueprints@3.1.53", "", { "dependencies": { "@php-wasm/logger": "3.1.53", "@php-wasm/progress": "3.1.53", "@php-wasm/stream-compression": "3.1.53", "@php-wasm/universal": "3.1.53", "@php-wasm/util": "3.1.53", "@php-wasm/web-service-worker": "3.1.53", "@wp-playground/common": "3.1.53", "@wp-playground/storage": "3.1.53", "@wp-playground/wordpress": "3.1.53", "ajv": "8.18.0" } }, "sha512-sUsfBj6UfBkWV9hs+BWiFeSp3Zm2vNy7uQbBDAz8LvmsWrGaObmp16IBZNAt2oB5PMIMfDlq5lHLk9rxhm/OkQ=="], - "@wp-playground/cli": ["@wp-playground/cli@3.1.52", "", { "dependencies": { "@php-wasm/cli-util": "3.1.52", "@php-wasm/logger": "3.1.52", "@php-wasm/node": "3.1.52", "@php-wasm/progress": "3.1.52", "@php-wasm/universal": "3.1.52", "@php-wasm/util": "3.1.52", "@php-wasm/xdebug-bridge": "3.1.52", "@wp-playground/blueprints": "3.1.52", "@wp-playground/common": "3.1.52", "@wp-playground/storage": "3.1.52", "@wp-playground/tools": "3.1.52", "@wp-playground/wordpress": "3.1.52", "express": "4.22.2", "fs-extra": "11.1.1", "tmp-promise": "3.0.3", "wasm-feature-detect": "1.8.0", "yargs": "17.7.2" }, "bin": { "wp-playground-cli": "wp-playground.js" } }, "sha512-NXApYcnZwKGOL/E6rdAwHKXbyPFMRIBKF9SX/TlxH9TOgBef0eblwjylnxnYzdAuiOzdJT7PhO4gJw2WSFTZAw=="], + "@wp-playground/cli": ["@wp-playground/cli@3.1.53", "", { "dependencies": { "@php-wasm/cli-util": "3.1.53", "@php-wasm/logger": "3.1.53", "@php-wasm/node": "3.1.53", "@php-wasm/progress": "3.1.53", "@php-wasm/universal": "3.1.53", "@php-wasm/util": "3.1.53", "@php-wasm/xdebug-bridge": "3.1.53", "@wp-playground/blueprints": "3.1.53", "@wp-playground/common": "3.1.53", "@wp-playground/storage": "3.1.53", "@wp-playground/tools": "3.1.53", "@wp-playground/wordpress": "3.1.53", "express": "4.22.2", "fs-extra": "11.1.1", "tmp-promise": "3.0.3", "wasm-feature-detect": "1.8.0", "yargs": "17.7.2" }, "bin": { "wp-playground-cli": "wp-playground.js" } }, "sha512-LgbHzPt2MJqv1wZ4LQyknTcKzN+c9p0dd4Yi4rD30vu+Zl9faEFVjZMcvc3VtEMWxlCKsHgvp8hV5d8Yn+5gjw=="], - "@wp-playground/common": ["@wp-playground/common@3.1.52", "", { "dependencies": { "@php-wasm/universal": "3.1.52", "@php-wasm/util": "3.1.52" } }, "sha512-QGE8CdykgfVEjqRKMXMFsXOwh3MV26FkXJ4c/HzsKKAaRt+zwp7BAK2s6jht40iz9TVDR3ZPcpBrSltfmjIshQ=="], + "@wp-playground/common": ["@wp-playground/common@3.1.53", "", { "dependencies": { "@php-wasm/universal": "3.1.53", "@php-wasm/util": "3.1.53" } }, "sha512-zfrlP4od2eOlqDMDshAjcaRuvbi8WjL8GB9NyI7QGsjg92jZ3bUWa2ORw717SHi5xNF24Ta/huw6Kzj9gWgDYA=="], - "@wp-playground/storage": ["@wp-playground/storage@3.1.52", "", { "dependencies": { "@php-wasm/stream-compression": "3.1.52", "@php-wasm/universal": "3.1.52", "@php-wasm/util": "3.1.52", "@zip.js/zip.js": "2.7.57", "isomorphic-git": "1.37.6", "octokit": "3.1.2", "pako": "^1.0.10", "sha.js": "2.4.12" } }, "sha512-hUQLdZ5iSC8Y01o06aMK/m9DZmMjo2cgl52MvXxR8Cuma+xgrMnlC+G1n7lnjaT+5Wbo58KaawxjZJxUpgcvxw=="], + "@wp-playground/storage": ["@wp-playground/storage@3.1.53", "", { "dependencies": { "@php-wasm/stream-compression": "3.1.53", "@php-wasm/universal": "3.1.53", "@php-wasm/util": "3.1.53", "@zip.js/zip.js": "2.7.57", "isomorphic-git": "1.37.6", "octokit": "3.1.2", "pako": "^1.0.10", "sha.js": "2.4.12" } }, "sha512-USiXqwDIV3YWtvs/33y5pwky20fIoKEyp0UPO6Y7wCKJVhg9LwIuQzDyUy5euQOWdfr8d00yT1lH3x3yjQTf7g=="], - "@wp-playground/tools": ["@wp-playground/tools@3.1.52", "", { "dependencies": { "@php-wasm/util": "3.1.52", "@wp-playground/blueprints": "3.1.52" } }, "sha512-rn604x/fH2VFW6rYw3mN5idaMh03sKIbxoeBDPZsh6Ca1Hv9oyheiQFEy0Y3Kzli4B58YwbRUcC0wlv3laT3hw=="], + "@wp-playground/tools": ["@wp-playground/tools@3.1.53", "", { "dependencies": { "@php-wasm/util": "3.1.53", "@wp-playground/blueprints": "3.1.53" } }, "sha512-KB5YOuSp7AnCIge5HKEwvRWaSjM4A0Oc4JqUKh0aEn6htfbAqKBN4b2KSo5nc14U5wMfq+e2ch9Y0mtXIHm4LA=="], - "@wp-playground/wordpress": ["@wp-playground/wordpress@3.1.52", "", { "dependencies": { "@php-wasm/logger": "3.1.52", "@php-wasm/universal": "3.1.52", "@php-wasm/util": "3.1.52", "@wp-playground/common": "3.1.52", "zstddec": "^0.2.0" } }, "sha512-vXvgrN33y3zvxWxVjtEEb4L4ZNfgBRPlvVe6wXHB19Dbiu32ZLkrlUpEkpKvft7wnrXnWvbDJqbEBfU2rKJtqw=="], + "@wp-playground/wordpress": ["@wp-playground/wordpress@3.1.53", "", { "dependencies": { "@php-wasm/logger": "3.1.53", "@php-wasm/universal": "3.1.53", "@php-wasm/util": "3.1.53", "@wp-playground/common": "3.1.53", "zstddec": "^0.2.0" } }, "sha512-za4KMQDgp/gN6Y14fL5e/+UOJBdin0kFBBnVhPWs/mMvQ469XDWruwZJuFYwMIpusSCZ5KBGdsiGuWrl8sWooQ=="], "@zip.js/zip.js": ["@zip.js/zip.js@2.7.57", "", {}, "sha512-BtonQ1/jDnGiMed6OkV6rZYW78gLmLswkHOzyMrMb+CAR7CZO8phOHO6c2qw6qb1g1betN7kwEHhhZk30dv+NA=="], @@ -348,7 +348,7 @@ "acorn-import-attributes": ["acorn-import-attributes@1.9.5", "", { "peerDependencies": { "acorn": "^8" } }, "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ=="], - "adm-zip": ["adm-zip@0.6.0", "", {}, "sha512-XleryMhbuksdKtofnWZ9Sk+4CUTbms4Mb/EU32SZwToAyZ5RgVos/ki8n+yr0LWHOGKuakbXTuuYNHLQjhddgg=="], + "adm-zip": ["adm-zip@0.6.1", "", {}, "sha512-Xwrja8nx9e5o2N1my4DsKCeKpdrnACyr1wtbPxBDgGzKzKyE9kRtBFA8mWldI+RVlD7CBZNWY/wQ2+ydwOR6kQ=="], "agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="], @@ -424,13 +424,13 @@ "before-after-hook": ["before-after-hook@2.2.3", "", {}, "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ=="], - "bestzip": ["bestzip@3.0.3", "", { "dependencies": { "archiver": "^8.0.0", "glob": "^13.0.6", "which": "^6.0.1", "yargs": "^16.2.0" }, "bin": { "bestzip": "bin/cli.js" } }, "sha512-3UpGCm+bn1uGuPD0ro2d+jFL7wG+632Lo710L6VmJVubxsw3ED0QrDqH+jxktPg8b+0e92cYO6J2zC5FJ2gyvw=="], + "bestzip": ["bestzip@3.1.0", "", { "dependencies": { "archiver": "^8.0.0", "glob": "^13.0.6", "which": "^6.0.1", "yargs": "^16.2.0" }, "bin": { "bestzip": "bin/cli.js" } }, "sha512-ujFDdpMDJnE6BgnpqPa45uHUkuPqLaOEsKuBQdQOEb0p7n2u9aSDmyZb93xC+c1Jj21a8F0XMZ6jaEMuACATsQ=="], "binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="], "bl": ["bl@5.1.0", "", { "dependencies": { "buffer": "^6.0.3", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ=="], - "body-parser": ["body-parser@1.20.6", "", { "dependencies": { "bytes": "~3.1.2", "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "~1.2.0", "http-errors": "~2.0.1", "iconv-lite": "~0.4.24", "on-finished": "~2.4.1", "qs": "~6.15.1", "raw-body": "~2.5.3", "type-is": "~1.6.18", "unpipe": "~1.0.0" } }, "sha512-p5tAzS57i5MV9fZFDj9LeIiTZEufbSe2eDozP+ElheSUq1m74CRq1jI4mYNDdVs9vQztXFLuk/Gd6BWTdwRJ5g=="], + "body-parser": ["body-parser@1.20.8", "", { "dependencies": { "bytes": "~3.1.2", "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "~1.2.0", "http-errors": "~2.0.1", "iconv-lite": "~0.4.24", "on-finished": "~2.4.1", "qs": "~6.16.0", "raw-body": "~2.5.3", "type-is": "~1.6.18", "unpipe": "~1.0.0" } }, "sha512-JNcyFQ64OiijEkPzUBTCe+hyPXUD/3LEldGQ6iF5LR1w00mx9o7xtDWHXBY2iItjdCFGoilOLNQbH943ut7pHA=="], "bottleneck": ["bottleneck@2.19.5", "", {}, "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw=="], @@ -1088,7 +1088,7 @@ "playwright": ["playwright@1.63.0", "", { "dependencies": { "playwright-core": "1.63.0" }, "bin": { "playwright": "cli.js" } }, "sha512-+7ziBLidS4NaNCdt57SUDT+wYmmd5fmiQejUic/kb+YsYSCPyOOE9sebzMjNmQrsnNpDJqd4WHvV/8lfKfUDUg=="], - "playwright-core": ["playwright-core@1.62.1", "", { "bin": { "playwright-core": "cli.js" } }, "sha512-wPYSwEBJY9GHraISXqyqtx0na0LpO3XEX7jNDhntbex7tzUS7kLnZsOlFruFJB4Hi/rhDMjXGqHewDZ68nYZVw=="], + "playwright-core": ["playwright-core@1.63.0", "", { "bin": { "playwright-core": "cli.js" } }, "sha512-rYCsBF/M5HjUch52bbtVONEFjv6Xu8sm8h72dNlR5bzIE1fvC/bxgspzkjSfU+MweEMmPM8KJebG6nnyxo5mCg=="], "plugin-error": ["plugin-error@1.0.1", "", { "dependencies": { "ansi-colors": "^1.0.1", "arr-diff": "^4.0.0", "arr-union": "^3.1.0", "extend-shallow": "^3.0.2" } }, "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA=="], @@ -1284,9 +1284,9 @@ "through2": ["through2@3.0.1", "", { "dependencies": { "readable-stream": "2 || 3" } }, "sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww=="], - "tldts-core": ["tldts-core@7.4.11", "", {}, "sha512-CW3WN2rIIE/Of21mulhgnGOwoDyEFNygyIBOONSdyAuSATgMMUCpLeUlB+E8sAwA5xRV9hYPl+kyZ9citHCaKg=="], + "tldts-core": ["tldts-core@7.4.12", "", {}, "sha512-nYNzS2WRf4QJmjzFFgAxLOBjyBxAGRbCy9PVBPaglcYyYajh40VBn+v5Ngr96ZMc7oM0+aCJdtQnNejvdBnXMQ=="], - "tldts-icann": ["tldts-icann@7.4.11", "", { "dependencies": { "tldts-core": "^7.4.11" } }, "sha512-1p+NDJ7FUYCliESmsQl9EW5Um8JIyFheiy6Y6ZoHho27d+TLAGFa0gMf1VOVy02vNY1aQo6xeKiaGj45+7P+PA=="], + "tldts-icann": ["tldts-icann@7.4.12", "", { "dependencies": { "tldts-core": "^7.4.12" } }, "sha512-KYMFombFttNwGKI9GhqlHBn/+QROOk2bvh5p+aVmRSF8VH+YYVS9fEq0ux099jzw0JXmk2yRErCiviveSL/QhA=="], "tmp": ["tmp@0.2.7", "", {}, "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw=="], @@ -1320,7 +1320,7 @@ "undertaker-registry": ["undertaker-registry@2.0.0", "", {}, "sha512-+hhVICbnp+rlzZMgxXenpvTxpuvA67Bfgtt+O9WOE5jo7w/dyiF1VmoZVIHvP2EkUjsyKyTwYKlLhA+j47m1Ew=="], - "undici-types": ["undici-types@8.3.0", "", {}, "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ=="], + "undici-types": ["undici-types@8.9.0", "", {}, "sha512-KTDyRTYX8sWmKXAikPHHSyc63CRPETMctyjKFupcC6OBLXT3xsN0e9aF7m+mIXutFWpUXuedtowG7iLOzp0kQg=="], "universal-github-app-jwt": ["universal-github-app-jwt@1.2.0", "", { "dependencies": { "@types/jsonwebtoken": "^9.0.0", "jsonwebtoken": "^9.0.2" } }, "sha512-dncpMpnsKBk0eetwfN8D8OUHGfiDhhJ+mtsbMl+7PfW7mYjiH8LIcqRmYMtzYLgSh47HjfdBtrBwIQ/gizKR3g=="], @@ -1486,6 +1486,8 @@ "body-parser/iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="], + "body-parser/qs": ["qs@6.16.0", "", { "dependencies": { "es-define-property": "^1.0.1", "side-channel": "^1.1.1" } }, "sha512-h6fhOIaRrID2CbEY2fqs+7t+UXZo+MLAnU5gRIq85uFtdiUPCdsApMlHhXogKVM4HM2DVbIjGNTTYH2OcmP1vA=="], + "chrome-launcher/is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="], "clone-response/mimic-response": ["mimic-response@1.0.1", "", {}, "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ=="], @@ -1536,8 +1538,6 @@ "pixelmatch/pngjs": ["pngjs@3.4.0", "", {}, "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w=="], - "playwright/playwright-core": ["playwright-core@1.63.0", "", { "bin": { "playwright-core": "cli.js" } }, "sha512-rYCsBF/M5HjUch52bbtVONEFjv6Xu8sm8h72dNlR5bzIE1fvC/bxgspzkjSfU+MweEMmPM8KJebG6nnyxo5mCg=="], - "proxy-agent/lru-cache": ["lru-cache@7.18.3", "", {}, "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="], "puppeteer/devtools-protocol": ["devtools-protocol@0.0.1312386", "", {}, "sha512-DPnhUXvmvKT2dFA/j7B+riVLUt9Q6RKJlcppojL5CoRywJJKLDYnRlw0gTFKfgDPHP5E04UoB71SxoJlVZy8FA=="], diff --git a/package.json b/package.json index 407b674..9501879 100644 --- a/package.json +++ b/package.json @@ -20,10 +20,10 @@ "destroy:ddev": "ddev delete -O && rm -rf wordpress && rm -rf .ddev", "init:ddev": "if [ -f wordpress/wp-load.php ]; then echo 'DDEV project is already initialized. Use \"run launch:ddev\" to start it or \"run destroy:ddev\" then \"run init:ddev\" to start fresh.'; exit 0; fi && ddev config --project-type=wordpress --project-name=cooked --php-version=7.4 --docroot=wordpress && printf 'services:\\n web:\\n volumes:\\n - ../:/var/www/html/wordpress/wp-content/plugins/cooked:rw\\n' > .ddev/docker-compose.cooked.yaml && mkdir -p wordpress/wp-content/plugins && ddev start && ddev wp core download && ddev wp core install --url=cooked.ddev.site --title=Cooked --admin_user=admin --admin_password=password --admin_email=admin@example.com && ddev wp plugin activate cooked && echo \"Admin username: admin, Admin password: password\" && echo \"Admin URL: cooked.ddev.site/wp-admin/\"", "launch:ddev": "ddev launch wp-admin/", - "i18n:make-pot": "if [ -d .ddev ]; then ddev wp i18n make-pot wordpress/wp-content/plugins/cooked/ wordpress/wp-content/plugins/cooked/languages/cooked.pot; elif [ -d ../../../.ddev ]; then ddev wp i18n make-pot /var/www/html/wp-content/plugins/cooked/ /var/www/html/wp-content/plugins/cooked/languages/cooked.pot; else wp-env run cli wp i18n make-pot wp-content/plugins/cooked/ wp-content/plugins/cooked/languages/cooked.pot; fi", - "i18n:update-po": "if [ -d .ddev ]; then ddev wp i18n update-po wordpress/wp-content/plugins/cooked/languages/cooked.pot wordpress/wp-content/plugins/cooked/languages/; elif [ -d ../../../.ddev ]; then ddev wp i18n update-po /var/www/html/wp-content/plugins/cooked/languages/cooked.pot /var/www/html/wp-content/plugins/cooked/languages/; else wp-env run cli wp i18n update-po wp-content/plugins/cooked/languages/cooked.pot wp-content/plugins/cooked/languages/; fi", + "i18n:make-pot": "if [ -d .ddev ]; then ddev wp i18n make-pot wordpress/wp-content/plugins/cooked/ wordpress/wp-content/plugins/cooked/languages/cooked.pot; else wp-env run cli -- wp i18n make-pot wp-content/plugins/cooked/ wp-content/plugins/cooked/languages/cooked.pot; fi", + "i18n:update-po": "if [ -d .ddev ]; then ddev wp i18n update-po wordpress/wp-content/plugins/cooked/languages/cooked.pot wordpress/wp-content/plugins/cooked/languages/; else wp-env run cli -- wp i18n update-po wp-content/plugins/cooked/languages/cooked.pot wp-content/plugins/cooked/languages/; fi", "i18n:apply-fr": "python3 bin/fix-fr-translations.py", - "i18n:make-mo": "if [ -d .ddev ]; then ddev wp i18n make-mo wordpress/wp-content/plugins/cooked/languages/; elif [ -d ../../../.ddev ]; then ddev wp i18n make-mo /var/www/html/wp-content/plugins/cooked/languages/; else wp-env run cli wp i18n make-mo wp-content/plugins/cooked/languages/; fi", + "i18n:make-mo": "if [ -d .ddev ]; then ddev wp i18n make-mo wordpress/wp-content/plugins/cooked/languages/; else wp-env run cli -- wp i18n make-mo wp-content/plugins/cooked/languages/; fi", "i18n": "bun run i18n:make-pot && bun run i18n:update-po && bun run i18n:apply-fr && bun run i18n:make-mo", "lint": "./vendor/bin/phpcs --standard=phpcs.xml .", "lint-fix": "./vendor/bin/phpcbf --standard=phpcs.xml .", @@ -63,11 +63,11 @@ "devDependencies": { "@axe-core/playwright": "^4.13.0", "@playwright/test": "^1.63.0", - "@types/node": "^26.4.1", + "@types/node": "^26.5.1", "@wordpress/e2e-test-utils-playwright": "^1.54.0", - "@wordpress/env": "^11.14.0", + "@wordpress/env": "^11.15.0", "backstopjs": "^6.3.25", - "bestzip": "^3.0.3", + "bestzip": "^3.1.0", "dotenv": "^17.4.2", "gulp": "^5.0.1", "gulp-clean-css": "^4.3.0", diff --git a/phpcs.xml b/phpcs.xml index 12fad7d..bb9e507 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -76,7 +76,7 @@ - cooked.php + *.php diff --git a/templates/admin/import.php b/templates/admin/import.php index b946f21..0a219f0 100644 --- a/templates/admin/import.php +++ b/templates/admin/import.php @@ -1,11 +1,22 @@ +
-    +   
-
+ tabs_fields(); $tab_counter = 1; echo ''; - ?> + ?> @@ -35,75 +46,82 @@
$tab ): + foreach ( $cooked_settings_tabs_fields as $tab_slug => $tab ) : echo '
'; // Add a hidden H2 tag for the messages, if any, to show up below it. - if ($tab_counter == 1): echo '

'; endif; - foreach ( $tab['fields'] as $name => $field ): - $notitle = false; - $conditional_requirement = ''; - - $class = isset($field['class']) ? ' ' . $field['class'] : ''; - $current_val = isset($_cooked_settings[$name]) ? $_cooked_settings[$name] : null; - $field_type = 'field_' . esc_attr( $field['type'] ); - $field_options = isset($field['options']) ? $field['options'] : false; - $field_options = !$field_options ? ( isset($field['placeholder']) ? $field['placeholder'] : $field_options ) : $field_options; - $color = isset($field['color']) && $field['color'] ? $field['color'] : false; - - if ( method_exists ( $Cooked_Import, $field_type ) ): - - if ( $field['type'] == 'misc_button' || $field['type'] == 'nonce' ): - $notitle = true; - $field_options = isset($field['title']) ? $field['title'] : false; + if ( 1 === $tab_counter ) : + echo '

'; + endif; + foreach ( $tab['fields'] as $name => $field ) : + $notitle = false; + $conditional_requirement = ''; + + $class = isset( $field['class'] ) ? ' ' . $field['class'] : ''; + $current_val = isset( $_cooked_settings[ $name ] ) ? $_cooked_settings[ $name ] : null; + $field_type = 'field_' . esc_attr( $field['type'] ); + $field_options = isset( $field['options'] ) ? $field['options'] : false; + $field_options = ! $field_options ? ( isset( $field['placeholder'] ) ? $field['placeholder'] : $field_options ) : $field_options; + $color = isset( $field['color'] ) && $field['color'] ? $field['color'] : false; + + if ( method_exists( $Cooked_Import, $field_type ) ) : + + if ( 'misc_button' === $field['type'] || 'nonce' === $field['type'] ) : + $notitle = true; + $field_options = isset( $field['title'] ) ? $field['title'] : false; endif; - if ( isset($field['conditional_requirement']) && $field['conditional_requirement'] ): - if ( is_array($field['conditional_requirement']) ): - $conditional_requirement = ' v-show="' . implode( ' && ', $field['conditional_requirement'] ) . '"'; - else: - $conditional_requirement = ' v-show="' . esc_attr($field['conditional_requirement']) . '"'; + if ( isset( $field['conditional_requirement'] ) && $field['conditional_requirement'] ) : + if ( is_array( $field['conditional_requirement'] ) ) : + $conditional_requirement = ' v-show="' . implode( ' && ', $field['conditional_requirement'] ) . '"'; + else : + $conditional_requirement = ' v-show="' . esc_attr( $field['conditional_requirement'] ) . '"'; endif; endif; - echo $conditional_requirement ? '' : ''; - echo ''; - echo !$notitle ? '

' . wp_kses_post( $field['title'] ) . '

' : ''; - echo isset($field['desc']) && $field['desc'] ? '

' . wp_kses_post( $field['desc'] ). '

' : ''; - $Cooked_Import->$field_type( $name, $field_options, $color, $field ); - echo '
'; - echo $conditional_requirement ? '' : ''; + echo $conditional_requirement ? '' : ''; + echo ''; + echo ! $notitle ? '

' . wp_kses_post( $field['title'] ) . '

' : ''; + echo isset( $field['desc'] ) && $field['desc'] ? '

' . wp_kses_post( $field['desc'] ) . '

' : ''; + $Cooked_Import->$field_type( $name, $field_options, $color, $field ); + echo '
'; + echo $conditional_requirement ? '' : ''; endif; endforeach; - $tab_counter++; + ++$tab_counter; echo '
'; - endforeach; ?> + endforeach; + ?>
- + endif; + ?> - + $array ): - foreach( $array as $name => $true_val ): - $val = isset( $_cooked_settings[$setting_name] ) && is_array( $_cooked_settings[$setting_name] ) && in_array( $true_val, $_cooked_settings[$setting_name] ) ? 'true' : 'false'; + foreach ( $conditions as $setting_name => $array ) : + foreach ( $array as $name => $true_val ) : + $val = isset( $_cooked_settings[ $setting_name ] ) && is_array( $_cooked_settings[ $setting_name ] ) && in_array( $true_val, $_cooked_settings[ $setting_name ], true ) ? 'true' : 'false'; $conditional_requirements_js[] = "'$name':$val"; endforeach; - endforeach; ?> + endforeach; + ?> - foreach ( $conditions as $setting_name => $array ): - foreach ( $array as $name => $true_val ): - $val = ( isset( $_cooked_settings[$setting_name] ) && is_array( $_cooked_settings[$setting_name] ) && in_array( $true_val, $_cooked_settings[$setting_name] ) ? 'true' : 'false' ); - $conditional_requirements_js[] = "'$name':$val"; - endforeach; - endforeach; ?> + + - var vm = new Vue({ - el: '#cooked-settings-panel', - data: { - - } - }); - - - - - \ No newline at end of file + endif; + + ?> + + + diff --git a/templates/admin/welcome.php b/templates/admin/welcome.php index 84e1327..998941d 100644 --- a/templates/admin/welcome.php +++ b/templates/admin/welcome.php @@ -1,48 +1,65 @@ +
-
-
+
+
- + -
-

+
+

+ +

' . __( 'Settings', 'cooked' ) . '', - '' . __( 'documentation', 'cooked' ) . '' , - '' . __( 'Discord', 'cooked' ) . '' - ) - ) ); - ?> + echo wp_kses_post( + wpautop( + sprintf( + /* translators: 1: plugin name, 2: Settings link, 3: documentation link, 4: Discord link */ + __( 'If this is your first time using %1$s, head over to the %2$s page for some initial configuration. You can also check out the %3$s if you get stuck or contact me on %4$s. If you just recently updated, you can find out what\'s new below.', 'cooked' ), + 'Cooked', + '' . __( 'Settings', 'cooked' ) . '', + '' . __( 'documentation', 'cooked' ) . '', + '' . __( 'Discord', 'cooked' ) . '' + ) + ) + ); + ?>
-
-
-
-

-
    -
  •   
  • -
  •   
  • -
  •   
  • -
  •   
  • -
  •   
  • -
-
-
- - - -
-
-
+
+
+
+

+
    +
  •   
  • +
  •   
  • +
  •   
  • +
  •   
  • + +
  •   
  • +
+
+
+ + + +
+
+
-
-
+
+
From ab8983f3fc6cbe79923c7994f878bd6130001d94 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 13 Sep 2026 20:24:32 +0000 Subject: [PATCH 03/12] Bump @wordpress/e2e-test-utils-playwright from 1.54.0 to 2.0.0 Bumps [@wordpress/e2e-test-utils-playwright](https://github.com/WordPress/gutenberg/tree/HEAD/packages/e2e-test-utils-playwright) from 1.54.0 to 2.0.0. - [Release notes](https://github.com/WordPress/gutenberg/releases) - [Changelog](https://github.com/WordPress/gutenberg/blob/trunk/packages/e2e-test-utils-playwright/CHANGELOG.md) - [Commits](https://github.com/WordPress/gutenberg/commits/@wordpress/e2e-test-utils-playwright@2.0.0/packages/e2e-test-utils-playwright) --- updated-dependencies: - dependency-name: "@wordpress/e2e-test-utils-playwright" dependency-version: 2.0.0 dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 407b674..07d528e 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "@axe-core/playwright": "^4.13.0", "@playwright/test": "^1.63.0", "@types/node": "^26.4.1", - "@wordpress/e2e-test-utils-playwright": "^1.54.0", + "@wordpress/e2e-test-utils-playwright": "^2.0.0", "@wordpress/env": "^11.14.0", "backstopjs": "^6.3.25", "bestzip": "^3.0.3", From 01f4570f4597f29abcf420ad56301a079101098b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 13 Sep 2026 20:24:45 +0000 Subject: [PATCH 04/12] Bump bestzip from 3.1.0 to 4.0.0 Bumps [bestzip](https://github.com/nfriedly/node-bestzip) from 3.1.0 to 4.0.0. - [Changelog](https://github.com/nfriedly/node-bestzip/blob/master/CHANGELOG.md) - [Commits](https://github.com/nfriedly/node-bestzip/compare/v3.1.0...v4.0.0) --- updated-dependencies: - dependency-name: bestzip dependency-version: 4.0.0 dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 407b674..75ee65e 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,7 @@ "@wordpress/e2e-test-utils-playwright": "^1.54.0", "@wordpress/env": "^11.14.0", "backstopjs": "^6.3.25", - "bestzip": "^3.0.3", + "bestzip": "^4.0.0", "dotenv": "^17.4.2", "gulp": "^5.0.1", "gulp-clean-css": "^4.3.0", From 5541f535e2dd3147af4f91bf523e9a478ac6890b Mon Sep 17 00:00:00 2001 From: mgiannopoulos24 <79588074+mgiannopoulos24@users.noreply.github.com> Date: Thu, 17 Sep 2026 00:03:58 +0300 Subject: [PATCH 05/12] Change PHP version to 7.4 and update afterStart script --- .wp-env.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.wp-env.json b/.wp-env.json index 51f19a3..60fa3f1 100644 --- a/.wp-env.json +++ b/.wp-env.json @@ -1,6 +1,6 @@ { "core": null, - "phpVersion": "8.1", + "phpVersion": "7.4", "themes": ["WordPress/twentytwentyfive"], "plugins": [ "https://downloads.wordpress.org/plugin/plugin-check.zip" @@ -19,6 +19,6 @@ "DISALLOW_FILE_EDIT": false }, "lifecycleScripts": { - "afterStart": "wp-env run cli wp plugin activate cooked" + "afterStart": "wp-env run bash -c 'curl -fsSL -o /tmp/wp-cli.phar https://github.com/wp-cli/builds/raw/gh-pages/phar/wp-cli.phar && chmod +x /tmp/wp-cli.phar && sudo cp /tmp/wp-cli.phar /usr/local/bin/wp && sudo chmod +x /usr/local/bin/wp'" } } From 2d86951884cd1e76c14ceda8e0950f0dae9991c8 Mon Sep 17 00:00:00 2001 From: mgiannopoulos24 <79588074+mgiannopoulos24@users.noreply.github.com> Date: Thu, 17 Sep 2026 00:06:10 +0300 Subject: [PATCH 06/12] Update i18n scripts for compatibility with ddev --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 9501879..6ab4e98 100644 --- a/package.json +++ b/package.json @@ -20,10 +20,10 @@ "destroy:ddev": "ddev delete -O && rm -rf wordpress && rm -rf .ddev", "init:ddev": "if [ -f wordpress/wp-load.php ]; then echo 'DDEV project is already initialized. Use \"run launch:ddev\" to start it or \"run destroy:ddev\" then \"run init:ddev\" to start fresh.'; exit 0; fi && ddev config --project-type=wordpress --project-name=cooked --php-version=7.4 --docroot=wordpress && printf 'services:\\n web:\\n volumes:\\n - ../:/var/www/html/wordpress/wp-content/plugins/cooked:rw\\n' > .ddev/docker-compose.cooked.yaml && mkdir -p wordpress/wp-content/plugins && ddev start && ddev wp core download && ddev wp core install --url=cooked.ddev.site --title=Cooked --admin_user=admin --admin_password=password --admin_email=admin@example.com && ddev wp plugin activate cooked && echo \"Admin username: admin, Admin password: password\" && echo \"Admin URL: cooked.ddev.site/wp-admin/\"", "launch:ddev": "ddev launch wp-admin/", - "i18n:make-pot": "if [ -d .ddev ]; then ddev wp i18n make-pot wordpress/wp-content/plugins/cooked/ wordpress/wp-content/plugins/cooked/languages/cooked.pot; else wp-env run cli -- wp i18n make-pot wp-content/plugins/cooked/ wp-content/plugins/cooked/languages/cooked.pot; fi", - "i18n:update-po": "if [ -d .ddev ]; then ddev wp i18n update-po wordpress/wp-content/plugins/cooked/languages/cooked.pot wordpress/wp-content/plugins/cooked/languages/; else wp-env run cli -- wp i18n update-po wp-content/plugins/cooked/languages/cooked.pot wp-content/plugins/cooked/languages/; fi", + "i18n:make-pot": "if [ -d .ddev ]; then ddev wp i18n make-pot wordpress/wp-content/plugins/cooked/ wordpress/wp-content/plugins/cooked/languages/cooked.pot; elif [ -d ../../../.ddev ]; then ddev wp i18n make-pot /var/www/html/wp-content/plugins/cooked/ /var/www/html/wp-content/plugins/cooked/languages/cooked.pot; else wp-env run cli wp i18n make-pot wp-content/plugins/cooked/ wp-content/plugins/cooked/languages/cooked.pot; fi", + "i18n:update-po": "if [ -d .ddev ]; then ddev wp i18n update-po wordpress/wp-content/plugins/cooked/languages/cooked.pot wordpress/wp-content/plugins/cooked/languages/; elif [ -d ../../../.ddev ]; then ddev wp i18n update-po /var/www/html/wp-content/plugins/cooked/languages/cooked.pot /var/www/html/wp-content/plugins/cooked/languages/; else wp-env run cli wp i18n update-po wp-content/plugins/cooked/languages/cooked.pot wp-content/plugins/cooked/languages/; fi", "i18n:apply-fr": "python3 bin/fix-fr-translations.py", - "i18n:make-mo": "if [ -d .ddev ]; then ddev wp i18n make-mo wordpress/wp-content/plugins/cooked/languages/; else wp-env run cli -- wp i18n make-mo wp-content/plugins/cooked/languages/; fi", + "i18n:make-mo": "if [ -d .ddev ]; then ddev wp i18n make-mo wordpress/wp-content/plugins/cooked/languages/; elif [ -d ../../../.ddev ]; then ddev wp i18n make-mo /var/www/html/wp-content/plugins/cooked/languages/; else wp-env run cli wp i18n make-mo wp-content/plugins/cooked/languages/; fi", "i18n": "bun run i18n:make-pot && bun run i18n:update-po && bun run i18n:apply-fr && bun run i18n:make-mo", "lint": "./vendor/bin/phpcs --standard=phpcs.xml .", "lint-fix": "./vendor/bin/phpcbf --standard=phpcs.xml .", From b52e1c84d3d868b3af3db4f398cf80e852480bf6 Mon Sep 17 00:00:00 2001 From: mgiannopoulos24 <79588074+mgiannopoulos24@users.noreply.github.com> Date: Thu, 17 Sep 2026 00:06:53 +0300 Subject: [PATCH 07/12] Change afterStart script to use wp-env run cli --- .wp-env.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.wp-env.json b/.wp-env.json index 60fa3f1..b2b9780 100644 --- a/.wp-env.json +++ b/.wp-env.json @@ -19,6 +19,6 @@ "DISALLOW_FILE_EDIT": false }, "lifecycleScripts": { - "afterStart": "wp-env run bash -c 'curl -fsSL -o /tmp/wp-cli.phar https://github.com/wp-cli/builds/raw/gh-pages/phar/wp-cli.phar && chmod +x /tmp/wp-cli.phar && sudo cp /tmp/wp-cli.phar /usr/local/bin/wp && sudo chmod +x /usr/local/bin/wp'" + "afterStart": "wp-env run cli bash -c 'curl -fsSL -o /tmp/wp-cli.phar https://github.com/wp-cli/builds/raw/gh-pages/phar/wp-cli.phar && chmod +x /tmp/wp-cli.phar && sudo cp /tmp/wp-cli.phar /usr/local/bin/wp && sudo chmod +x /usr/local/bin/wp'" } } From 47787d23d7f76e21578032e6db37e92b80e943c1 Mon Sep 17 00:00:00 2001 From: Armand Tresova Date: Sun, 27 Sep 2026 15:00:48 -0400 Subject: [PATCH 08/12] Added include_ids to cooked-related-recipes shortcode Also fixed bug where if cooking time is a string a fetal error is thrown. --- includes/class.cooked-measurements.php | 28 +++++ includes/class.cooked-recipe-meta.php | 22 +++- includes/class.cooked-related-recipes.php | 127 ++++++++++++++-------- includes/class.cooked-seo.php | 4 +- includes/class.cooked-shortcodes.php | 16 +-- 5 files changed, 137 insertions(+), 60 deletions(-) diff --git a/includes/class.cooked-measurements.php b/includes/class.cooked-measurements.php index 06ea0ed..aa2d446 100644 --- a/includes/class.cooked-measurements.php +++ b/includes/class.cooked-measurements.php @@ -711,7 +711,35 @@ public function get_fraction_array() { return $fraction_array; } + /** + * Coerce a stored cook/prep/total time to minutes. + * + * @param mixed $value Raw time value. + * @return int|float Minutes, or 0. + */ + public static function normalize_minutes( $value ) { + if ( ! is_scalar( $value ) || is_bool( $value ) || '' === $value ) { + return 0; + } + + if ( is_numeric( $value ) ) { + $minutes = (float) $value; + } elseif ( is_string( $value ) && preg_match( '/-?\d+(?:[.,]\d+)?/', $value, $matches ) ) { + $minutes = (float) str_replace( ',', '.', $matches[0] ); + } else { + return 0; + } + + if ( $minutes < 0 ) { + return 0; + } + + return $minutes == (int) $minutes ? (int) $minutes : $minutes; + } + public static function time_format( $minutes, $format = 'default' ) { + $minutes = self::normalize_minutes( $minutes ); + ob_start(); if ( $minutes < 60 ): diff --git a/includes/class.cooked-recipe-meta.php b/includes/class.cooked-recipe-meta.php index 3d3aa59..89c5163 100644 --- a/includes/class.cooked-recipe-meta.php +++ b/includes/class.cooked-recipe-meta.php @@ -52,6 +52,9 @@ public static function meta_cleanup( $recipe_settings ) { } elseif ( $key === 'seo_description' ) { $decoded_val = wp_specialchars_decode( $val, ENT_QUOTES ); $_recipe_settings[ $key ] = wp_strip_all_tags( $decoded_val ); + } elseif ( in_array( $key, [ 'prep_time', 'cook_time', 'total_time' ], true ) ) { + $minutes = Cooked_Measurements::normalize_minutes( $val ); + $_recipe_settings[ $key ] = $minutes ? $minutes : ''; } else { if ($key === "post_title") { // Decode HTML entities first so wp_kses_post can see actual HTML tags @@ -1690,15 +1693,22 @@ function cooked_render_recipe_fields( $post_id ) {
-

"title"

-

+

"include_ids"

+

- +
+
+

"title"

+

+
+ +
+

"limit"

@@ -1706,6 +1716,9 @@ function cooked_render_recipe_fields( $post_id ) {
+ + +

"columns"

@@ -1758,6 +1771,7 @@ function cooked_render_recipe_fields( $post_id ) {

id ()
+ include_ids ()
title ()
limit ()
columns ()
@@ -1768,7 +1782,7 @@ function cooked_render_recipe_fields( $post_id ) {

- [cooked-related-recipes limit="4" columns="2" title="Related Recipes"] + [cooked-related-recipes include_ids="101,102" limit="4" columns="2" title="Related Recipes"]

diff --git a/includes/class.cooked-related-recipes.php b/includes/class.cooked-related-recipes.php index b2493a8..9f5f2db 100644 --- a/includes/class.cooked-related-recipes.php +++ b/includes/class.cooked-related-recipes.php @@ -31,6 +31,7 @@ class Cooked_Related_Recipes { public static function get_default_atts() { $default_atts = [ 'id' => false, + 'include_ids' => false, 'title' => __( 'Related Recipes', 'cooked' ), 'limit' => 4, 'columns' => 2, @@ -72,64 +73,68 @@ public static function get_related_recipes( $recipe_id, $atts ) { } /** - * Find related recipes: one WP_Query with tax_query (all taxonomies OR) and orderby rand. + * Find related recipes: pinned include_ids first, then one WP_Query with + * tax_query (all taxonomies OR) and orderby rand to fill remaining slots. * * @param array $source_recipe Source recipe data. * @param array $atts Shortcode attributes. * @return array [ ['id' => int], ... ] */ public static function find_related_recipes( $source_recipe, $atts ) { - $recipe_id = $source_recipe['id']; - $limit = isset( $atts['limit'] ) ? max( 1, (int) $atts['limit'] ) : 4; - - // Build OR clause for each taxonomy that is enabled via match_* and where the source recipe has terms. - $clauses = []; - $taxonomy_atts = [ - 'cp_recipe_category' => 'match_categories', - 'cp_recipe_cuisine' => 'match_cuisines', - 'cp_recipe_cooking_method' => 'match_cooking_methods', - 'cp_recipe_tags' => 'match_tags', - 'cp_recipe_diet' => 'match_diets', - ]; - foreach ( $taxonomy_atts as $taxonomy => $att_key ) { - if ( empty( $atts[ $att_key ] ) || $atts[ $att_key ] === 'false' ) { - continue; + $recipe_id = $source_recipe['id']; + $limit = isset( $atts['limit'] ) ? max( 1, (int) $atts['limit'] ) : 4; + $include_ids = array_slice( self::parse_include_ids( $atts, $recipe_id ), 0, $limit ); + $remaining = $limit - count( $include_ids ); + $related_ids = []; + + if ( $remaining > 0 ) { + $clauses = []; + $taxonomy_atts = [ + 'cp_recipe_category' => 'match_categories', + 'cp_recipe_cuisine' => 'match_cuisines', + 'cp_recipe_cooking_method' => 'match_cooking_methods', + 'cp_recipe_tags' => 'match_tags', + 'cp_recipe_diet' => 'match_diets', + ]; + foreach ( $taxonomy_atts as $taxonomy => $att_key ) { + if ( ! isset( $atts[ $att_key ] ) || ! wp_validate_boolean( $atts[ $att_key ] ) ) { + continue; + } + $terms = self::get_recipe_terms( $recipe_id, $taxonomy ); + if ( ! empty( $terms ) ) { + $clauses[] = [ 'taxonomy' => $taxonomy, 'field' => 'term_id', 'terms' => $terms ]; + } } - $terms = self::get_recipe_terms( $recipe_id, $taxonomy ); - if ( ! empty( $terms ) ) { - $clauses[] = [ 'taxonomy' => $taxonomy, 'field' => 'term_id', 'terms' => $terms ]; - } - } - - if ( empty( $clauses ) ) { - return []; - } - $tax_query = array_merge( [ 'relation' => 'OR' ], $clauses ); - - $query_args = [ - 'post_type' => 'cp_recipe', - 'post_status' => 'publish', - 'post__not_in' => [ $recipe_id ], - 'posts_per_page' => $limit, - 'orderby' => 'rand', - 'fields' => 'ids', - ]; - - $query_args['tax_query'] = $tax_query; + if ( empty( $clauses ) && empty( $include_ids ) ) { + return []; + } - $current_language = false; - if ( class_exists( 'Cooked_Multilingual' ) && Cooked_Multilingual::is_multilingual_active() ) { - $current_language = Cooked_Multilingual::get_current_language(); + if ( ! empty( $clauses ) ) { + $query_args = [ + 'post_type' => 'cp_recipe', + 'post_status' => 'publish', + 'post__not_in' => array_merge( [ $recipe_id ], $include_ids ), + 'posts_per_page' => $remaining, + 'orderby' => 'rand', + 'fields' => 'ids', + 'tax_query' => array_merge( [ 'relation' => 'OR' ], $clauses ), + ]; + + $current_language = false; + if ( class_exists( 'Cooked_Multilingual' ) && Cooked_Multilingual::is_multilingual_active() ) { + $current_language = Cooked_Multilingual::get_current_language(); + } + $query_args = apply_filters( 'cooked_related_recipes_query_args', $query_args, $current_language ); + + $query = new \WP_Query( $query_args ); + $related_ids = ! empty( $query->posts ) ? $query->posts : []; + wp_reset_postdata(); + } } - $query_args = apply_filters( 'cooked_related_recipes_query_args', $query_args, $current_language ); - - $query = new \WP_Query( $query_args ); - $ids = ! empty( $query->posts ) ? $query->posts : []; - wp_reset_postdata(); $result = []; - foreach ( $ids as $id ) { + foreach ( array_merge( $include_ids, $related_ids ) as $id ) { $result[] = [ 'id' => (int) $id ]; } @@ -145,6 +150,36 @@ public static function find_related_recipes( $source_recipe, $atts ) { return apply_filters( 'cooked_related_recipes_result', $result, $source_recipe, $atts ); } + /** + * Parse include_ids into unique positive IDs, excluding the source recipe. + * + * @param array $atts Shortcode attributes. + * @param int $recipe_id Source recipe ID. + * @return int[] + */ + private static function parse_include_ids( $atts, $recipe_id ) { + if ( empty( $atts['include_ids'] ) ) { + return []; + } + + $raw = $atts['include_ids']; + if ( ! is_array( $raw ) ) { + $raw = explode( ',', str_replace( ' ', '', (string) $raw ) ); + } + + $ids = []; + $recipe_id = (int) $recipe_id; + foreach ( $raw as $id ) { + $id = absint( $id ); + if ( ! $id || $id === $recipe_id || in_array( $id, $ids, true ) ) { + continue; + } + $ids[] = $id; + } + + return $ids; + } + /** * Get recipe term IDs for a taxonomy. * diff --git a/includes/class.cooked-seo.php b/includes/class.cooked-seo.php index 613048e..5fd7227 100644 --- a/includes/class.cooked-seo.php +++ b/includes/class.cooked-seo.php @@ -101,8 +101,8 @@ public static function schema_values( $recipe = false ) { endif; endif; - $cook_time = isset($recipe['cook_time']) && $recipe['cook_time'] ? esc_html( $recipe['cook_time'] ) : 0; - $prep_time = isset($recipe['prep_time']) && $recipe['prep_time'] ? esc_html( $recipe['prep_time'] ) : 0; + $cook_time = isset($recipe['cook_time']) ? Cooked_Measurements::normalize_minutes( $recipe['cook_time'] ) : 0; + $prep_time = isset($recipe['prep_time']) ? Cooked_Measurements::normalize_minutes( $recipe['prep_time'] ) : 0; $total_time = $cook_time + $prep_time; $unsaturatedFatAmount = (isset($recipe['nutrition']['monounsaturated_fat']) && $recipe['nutrition']['monounsaturated_fat'] ? $recipe['nutrition']['monounsaturated_fat'] : 0) + (isset($recipe['nutrition']['polyunsaturated_fat']) && $recipe['nutrition']['polyunsaturated_fat'] ? $recipe['nutrition']['polyunsaturated_fat'] : 0); diff --git a/includes/class.cooked-shortcodes.php b/includes/class.cooked-shortcodes.php index 42d9259..7c967ff 100644 --- a/includes/class.cooked-shortcodes.php +++ b/includes/class.cooked-shortcodes.php @@ -732,7 +732,7 @@ public static function cooked_info_prep_time( $recipe ) { global $_cooked_settings; if (!empty($_cooked_settings['recipe_info_display_options']) && in_array('timing_prep',$_cooked_settings['recipe_info_display_options'])) { - $prep_time = isset($recipe['prep_time']) ? esc_html( $recipe['prep_time'] ) : 0; + $prep_time = isset($recipe['prep_time']) ? Cooked_Measurements::normalize_minutes( $recipe['prep_time'] ) : 0; echo $prep_time ? '' . esc_html__('Prep Time','cooked') . '' . wp_kses_post( Cooked_Measurements::time_format( $prep_time ) ) . '' : ''; } } @@ -741,7 +741,7 @@ public static function cooked_info_cook_time( $recipe ) { global $_cooked_settings; if (!empty($_cooked_settings['recipe_info_display_options']) && in_array('timing_cook', $_cooked_settings['recipe_info_display_options'])) { - $cook_time = isset($recipe['cook_time']) ? esc_html( $recipe['cook_time'] ) : 0; + $cook_time = isset($recipe['cook_time']) ? Cooked_Measurements::normalize_minutes( $recipe['cook_time'] ) : 0; echo $cook_time ? '' . esc_html__('Cook Time','cooked') . '' . wp_kses_post( Cooked_Measurements::time_format( $cook_time ) ) . '' : ''; } } @@ -750,13 +750,13 @@ public static function cooked_info_total_time( $recipe ) { global $_cooked_settings; if (!empty($_cooked_settings['recipe_info_display_options']) && in_array('timing_total',$_cooked_settings['recipe_info_display_options'])) { - $total_time = isset($recipe['total_time']) ? esc_html( $recipe['total_time'] ) : 0; + $total_time = isset($recipe['total_time']) ? Cooked_Measurements::normalize_minutes( $recipe['total_time'] ) : 0; if ( $total_time ) { echo $total_time ? '' . esc_html__('Total Time','cooked') . '' . wp_kses_post( Cooked_Measurements::time_format( $total_time ) ) . '' : ''; } else { - $prep_time = isset($recipe['prep_time']) ? esc_html( $recipe['prep_time'] ) : 0; - $cook_time = isset($recipe['cook_time']) ? esc_html( $recipe['cook_time'] ) : 0; + $prep_time = isset($recipe['prep_time']) ? Cooked_Measurements::normalize_minutes( $recipe['prep_time'] ) : 0; + $cook_time = isset($recipe['cook_time']) ? Cooked_Measurements::normalize_minutes( $recipe['cook_time'] ) : 0; if ( $prep_time && $cook_time ) { $total_time = $prep_time + $cook_time; @@ -1245,9 +1245,9 @@ public function cooked_related_recipes_shortcode($atts, $content = null) { // Display recipes in grid $columns = intval($atts['columns']); - $hide_image = $atts['hide_image'] && $atts['hide_image'] !== 'false'; - $hide_excerpt = $atts['hide_excerpt'] && $atts['hide_excerpt'] !== 'false'; - $hide_author = $atts['hide_author'] && $atts['hide_author'] !== 'false'; + $hide_image = wp_validate_boolean( $atts['hide_image'] ); + $hide_excerpt = wp_validate_boolean( $atts['hide_excerpt'] ); + $hide_author = wp_validate_boolean( $atts['hide_author'] ); echo '