dirtsimple / postmark

Sync Wordpress Pages and Posts (even custom post types + fields) from static Markdown + YAML files
MIT License
30 stars 8 forks source link

PHP version upgrade: how to install on a modern PHP 8.1.2? #4

Closed vadimkantorov closed 1 month ago

vadimkantorov commented 10 months ago

I've tried installing postmark using wp-cli and got an error about the supported PHP version. Is it possible to use the postmark plugin with php 8.1.2? Thank you!

$ php wp-cli.phar package install dirtsimple/postmark

Installing package dirtsimple/postmark (dev-master)
Updating /home/vadimkantorov/.wp-cli/packages/composer.json to require the package...
Registering https://github.com/dirtsimple/postmark.git as a VCS repository...
Using Composer to install the package...
---
Loading composer repositories with package information
Found 403 package versions referenced in your dependency graph. 300 (74%) were optimized away.
Updating dependencies
Generating rules
Resolving dependencies through SAT
Looking at all rules.

Dependency resolution completed in 0.001 seconds
Your requirements could not be resolved to an installable set of packages.
Problem 1
    - Root composer.json requires dirtsimple/postmark dev-master -> satisfiable by dirtsimple/postmark[dev-master].
    - dirtsimple/postmark dev-master requires php ^7.1 -> your php version (8.1.2) does not satisfy that requirement.
Running update with --no-dev does not mean require-dev is ignored, it just means the packages will not be installed. If dev requirements are blocking the update you have to resolve those problems.
---
Error: Package installation failed (Composer return code 2).
Reverted composer.json.
vadimkantorov commented 10 months ago

What I did is I git clone https://github.com/dirtsimple/postmark/, then replaced composer.json by the following relaxed version:

{
    "name": "dirtsimple/postmark",
    "description": "Sync WP content from Markdown files",
    "type": "wp-cli-package",
    "homepage": "https://github.com/dirtsimple/postmark/",
    "license": "MIT",
    "authors": [
        {
            "name": "PJ Eby",
            "homepage": "https://github.com/pjeby"
        }
    ],
    "keywords": [
        "markdown",
        "wordpress",
        "wp",
        "wp-cli",
        "yaml",
        "front-matter",
        "content-management",
        "configuration-management",
        "static-site-generator",
        "yaml front matter"
    ],
    "minimum-stability": "dev",
    "prefer-stable": true,
    "autoload": {
        "files": [ "command.php" ],
        "psr-4": {
            "dirtsimple\\Postmark\\": "src/"
        }
    },
    "require": {
        "dirtsimple/clean-yaml": "^0.1",
        "dirtsimple/imposer": "dev-master",
        "wp-cli/wp-cli": "*",
        "wp-cli/entity-command": "*",
        "rarst/wpdatetime": "*",
        "league/commonmark": "*",
        "league/commonmark-ext-smartpunct": "*",
        "league/commonmark-ext-strikethrough": "*",
        "league/commonmark-ext-table": "*",
        "webuni/commonmark-attributes-extension": "*",
        "twig/twig": "*",
        "symfony/yaml": "*",
        "php" : "*"
    }
}

and then ran php wp-cli.phar package install ./postmark - which installed it successfully.

vadimkantorov commented 10 months ago

This printed:

Package league/commonmark-ext-smartpunct is abandoned, you should avoid using it. Use league/commonmark instead.
Package league/commonmark-ext-strikethrough is abandoned, you should avoid using it. Use league/commonmark instead.
Package league/commonmark-ext-table is abandoned, you should avoid using it. Use league/commonmark instead.
Package rarst/wpdatetime is abandoned, you should avoid using it. No replacement was suggested.
Package webuni/commonmark-attributes-extension is abandoned, you should avoid using it. Use league/commonmark instead.

suggesting that the league/commonmark-ext-table and other packages is deprecated:

vadimkantorov commented 10 months ago

When I run php wp-cli.phar postmark tree ./_posts, I get the following error suggesting that the Table extension is not available.

If postmark isn't updated enough, maybe could you suggest a replacement? Thank you very much!

PHP Fatal error:  Uncaught ReflectionException: Class "League\CommonMark\Ext\Table\TableExtension" does not exist in /mnt/c/Users/vadim/wpssg/postmark/src/Formatter.php:48
Stack trace:
#0 /mnt/c/Users/vadim/wpssg/postmark/src/Formatter.php(48): ReflectionClass->__construct()
#1 /mnt/c/Users/vadim/wpssg/postmark/src/Formatter.php(40): dirtsimple\Postmark\Formatter::addExtensions()
#2 /mnt/c/Users/vadim/wpssg/postmark/src/Formatter.php(16): dirtsimple\Postmark\Formatter::formatter()
#3 /mnt/c/Users/vadim/wpssg/postmark/src/MarkdownFile.php(97): dirtsimple\Postmark\Formatter::format()
#4 /mnt/c/Users/vadim/wpssg/postmark/src/PostImporter.php(88): dirtsimple\Postmark\MarkdownFile->html()
#5 /mnt/c/Users/vadim/wpssg/postmark/src/PostImporter.php(180): dirtsimple\Postmark\PostImporter->syncField()
#6 /mnt/c/Users/vadim/wpssg/postmark/src/PostImporter.php(108): dirtsimple\Postmark\PostImporter->_syncinfo_content()
#7 /mnt/c/Users/vadim/wpssg/postmark/src/PostImporter.php(28): dirtsimple\Postmark\PostImporter->sync()
#8 /mnt/c/Users/vadim/wpssg/postmark/src/Kind.php(83): dirtsimple\Postmark\PostImporter::sync_doc()
#9 [internal function]: dirtsimple\Postmark\KindImpl->import()
#10 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/WatchedPromise.php(62): Generator->current()
#11 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/WatchedPromise.php(83): dirtsimple\imposer\WatchedPromise->dirtsimple\imposer\{closure}()
#12 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/Promise.php(52): dirtsimple\imposer\WatchedPromise->spawn()
#13 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/Promise.php(28): dirtsimple\imposer\Promise::spawn()
#14 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/WatchedPromise.php(62): dirtsimple\imposer\Promise::interpret()
#15 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/WatchedPromise.php(83): dirtsimple\imposer\WatchedPromise->dirtsimple\imposer\{closure}()
#16 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/WatchedPromise.php(38): dirtsimple\imposer\WatchedPromise->spawn()
#17 /mnt/c/Users/vadim/wpssg/postmark/src/Database.php(42): dirtsimple\imposer\WatchedPromise->call()
#18 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/Pool.php(20): dirtsimple\Postmark\Database->dirtsimple\Postmark\{closure}()
#19 /mnt/c/Users/vadim/wpssg/postmark/src/Database.php(82): dirtsimple\imposer\Pool->offsetGet()
#20 /mnt/c/Users/vadim/wpssg/postmark/src/PostmarkCommand.php(241): dirtsimple\Postmark\Database->sync()
#21 [internal function]: dirtsimple\Postmark\PostmarkCommand->sync_docs()
#22 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/WatchedPromise.php(62): Generator->current()
#23 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/WatchedPromise.php(83): dirtsimple\imposer\WatchedPromise->dirtsimple\imposer\{closure}()
#24 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/Promise.php(52): dirtsimple\imposer\WatchedPromise->spawn()
#25 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/Promise.php(28): dirtsimple\imposer\Promise::spawn()
#26 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/WatchedPromise.php(62): dirtsimple\imposer\Promise::interpret()
#27 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/WatchedPromise.php(83): dirtsimple\imposer\WatchedPromise->dirtsimple\imposer\{closure}()
#28 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/Promise.php(52): dirtsimple\imposer\WatchedPromise->spawn()
#29 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/Promise.php(28): dirtsimple\imposer\Promise::spawn()
#30 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/Task.php(113): dirtsimple\imposer\Promise::interpret()
#31 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/Task.php(92): dirtsimple\imposer\Task->run_next_step()
#32 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/Scheduler.php(76): dirtsimple\imposer\Task->run()
#33 [internal function]: dirtsimple\imposer\Scheduler->run()
#34 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/Imposer.php(66): call_user_func_array()
#35 [internal function]: dirtsimple\imposer\Imposer->__call()
#36 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/Imposer.php(61): call_user_func_array()
#37 /mnt/c/Users/vadim/wpssg/postmark/src/PostmarkCommand.php(165): dirtsimple\imposer\Imposer::__callStatic()
#38 [internal function]: dirtsimple\Postmark\PostmarkCommand->tree()
#39 phar:///mnt/c/Users/vadim/wpssg/wp-cli.phar/vendor/wp-cli/wp-cli/php/WP_CLI/Dispatcher/CommandFactory.php(100): call_user_func()
#40 [internal function]: WP_CLI\Dispatcher\CommandFactory::WP_CLI\Dispatcher\{closure}()
#41 phar:///mnt/c/Users/vadim/wpssg/wp-cli.phar/vendor/wp-cli/wp-cli/php/WP_CLI/Dispatcher/Subcommand.php(488): call_user_func()
#42 phar:///mnt/c/Users/vadim/wpssg/wp-cli.phar/vendor/wp-cli/wp-cli/php/WP_CLI/Runner.php(436): WP_CLI\Dispatcher\Subcommand->invoke()
#43 phar:///mnt/c/Users/vadim/wpssg/wp-cli.phar/vendor/wp-cli/wp-cli/php/WP_CLI/Runner.php(459): WP_CLI\Runner->run_command()
#44 phar:///mnt/c/Users/vadim/wpssg/wp-cli.phar/vendor/wp-cli/wp-cli/php/WP_CLI/Runner.php(1284): WP_CLI\Runner->run_command_and_exit()
#45 phar:///mnt/c/Users/vadim/wpssg/wp-cli.phar/vendor/wp-cli/wp-cli/php/WP_CLI/Bootstrap/LaunchRunner.php(28): WP_CLI\Runner->start()
#46 phar:///mnt/c/Users/vadim/wpssg/wp-cli.phar/vendor/wp-cli/wp-cli/php/bootstrap.php(83): WP_CLI\Bootstrap\LaunchRunner->process()
#47 phar:///mnt/c/Users/vadim/wpssg/wp-cli.phar/vendor/wp-cli/wp-cli/php/wp-cli.php(32): WP_CLI\bootstrap()
#48 phar:///mnt/c/Users/vadim/wpssg/wp-cli.phar/php/boot-phar.php(20): include('...')
#49 /mnt/c/Users/vadim/wpssg/wp-cli.phar(4): include('...')
#50 {main}
  thrown in /mnt/c/Users/vadim/wpssg/postmark/src/Formatter.php on line 48
Fatal error: Uncaught ReflectionException: Class "League\CommonMark\Ext\Table\TableExtension" does not exist in /mnt/c/Users/vadim/wpssg/postmark/src/Formatter.php:48
Stack trace:
#0 /mnt/c/Users/vadim/wpssg/postmark/src/Formatter.php(48): ReflectionClass->__construct()
#1 /mnt/c/Users/vadim/wpssg/postmark/src/Formatter.php(40): dirtsimple\Postmark\Formatter::addExtensions()
#2 /mnt/c/Users/vadim/wpssg/postmark/src/Formatter.php(16): dirtsimple\Postmark\Formatter::formatter()
#3 /mnt/c/Users/vadim/wpssg/postmark/src/MarkdownFile.php(97): dirtsimple\Postmark\Formatter::format()
#4 /mnt/c/Users/vadim/wpssg/postmark/src/PostImporter.php(88): dirtsimple\Postmark\MarkdownFile->html()
#5 /mnt/c/Users/vadim/wpssg/postmark/src/PostImporter.php(180): dirtsimple\Postmark\PostImporter->syncField()
#6 /mnt/c/Users/vadim/wpssg/postmark/src/PostImporter.php(108): dirtsimple\Postmark\PostImporter->_syncinfo_content()
#7 /mnt/c/Users/vadim/wpssg/postmark/src/PostImporter.php(28): dirtsimple\Postmark\PostImporter->sync()
#8 /mnt/c/Users/vadim/wpssg/postmark/src/Kind.php(83): dirtsimple\Postmark\PostImporter::sync_doc()
#9 [internal function]: dirtsimple\Postmark\KindImpl->import()
#10 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/WatchedPromise.php(62): Generator->current()
#11 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/WatchedPromise.php(83): dirtsimple\imposer\WatchedPromise->dirtsimple\imposer\{closure}()
#12 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/Promise.php(52): dirtsimple\imposer\WatchedPromise->spawn()
#13 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/Promise.php(28): dirtsimple\imposer\Promise::spawn()
#14 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/WatchedPromise.php(62): dirtsimple\imposer\Promise::interpret()
#15 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/WatchedPromise.php(83): dirtsimple\imposer\WatchedPromise->dirtsimple\imposer\{closure}()
#16 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/WatchedPromise.php(38): dirtsimple\imposer\WatchedPromise->spawn()
#17 /mnt/c/Users/vadim/wpssg/postmark/src/Database.php(42): dirtsimple\imposer\WatchedPromise->call()
#18 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/Pool.php(20): dirtsimple\Postmark\Database->dirtsimple\Postmark\{closure}()
#19 /mnt/c/Users/vadim/wpssg/postmark/src/Database.php(82): dirtsimple\imposer\Pool->offsetGet()
#20 /mnt/c/Users/vadim/wpssg/postmark/src/PostmarkCommand.php(241): dirtsimple\Postmark\Database->sync()
#21 [internal function]: dirtsimple\Postmark\PostmarkCommand->sync_docs()
#22 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/WatchedPromise.php(62): Generator->current()
#23 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/WatchedPromise.php(83): dirtsimple\imposer\WatchedPromise->dirtsimple\imposer\{closure}()
#24 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/Promise.php(52): dirtsimple\imposer\WatchedPromise->spawn()
#25 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/Promise.php(28): dirtsimple\imposer\Promise::spawn()
#26 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/WatchedPromise.php(62): dirtsimple\imposer\Promise::interpret()
#27 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/WatchedPromise.php(83): dirtsimple\imposer\WatchedPromise->dirtsimple\imposer\{closure}()
#28 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/Promise.php(52): dirtsimple\imposer\WatchedPromise->spawn()
#29 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/Promise.php(28): dirtsimple\imposer\Promise::spawn()
#30 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/Task.php(113): dirtsimple\imposer\Promise::interpret()
#31 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/Task.php(92): dirtsimple\imposer\Task->run_next_step()
#32 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/Scheduler.php(76): dirtsimple\imposer\Task->run()
#33 [internal function]: dirtsimple\imposer\Scheduler->run()
#34 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/Imposer.php(66): call_user_func_array()
#35 [internal function]: dirtsimple\imposer\Imposer->__call()
#36 /home/vadimkantorov/.wp-cli/packages/vendor/dirtsimple/imposer/src/Imposer.php(61): call_user_func_array()
#37 /mnt/c/Users/vadim/wpssg/postmark/src/PostmarkCommand.php(165): dirtsimple\imposer\Imposer::__callStatic()
#38 [internal function]: dirtsimple\Postmark\PostmarkCommand->tree()
#39 phar:///mnt/c/Users/vadim/wpssg/wp-cli.phar/vendor/wp-cli/wp-cli/php/WP_CLI/Dispatcher/CommandFactory.php(100): call_user_func()
#40 [internal function]: WP_CLI\Dispatcher\CommandFactory::WP_CLI\Dispatcher\{closure}()
#41 phar:///mnt/c/Users/vadim/wpssg/wp-cli.phar/vendor/wp-cli/wp-cli/php/WP_CLI/Dispatcher/Subcommand.php(488): call_user_func()
#42 phar:///mnt/c/Users/vadim/wpssg/wp-cli.phar/vendor/wp-cli/wp-cli/php/WP_CLI/Runner.php(436): WP_CLI\Dispatcher\Subcommand->invoke()
#43 phar:///mnt/c/Users/vadim/wpssg/wp-cli.phar/vendor/wp-cli/wp-cli/php/WP_CLI/Runner.php(459): WP_CLI\Runner->run_command()
#44 phar:///mnt/c/Users/vadim/wpssg/wp-cli.phar/vendor/wp-cli/wp-cli/php/WP_CLI/Runner.php(1284): WP_CLI\Runner->run_command_and_exit()
#45 phar:///mnt/c/Users/vadim/wpssg/wp-cli.phar/vendor/wp-cli/wp-cli/php/WP_CLI/Bootstrap/LaunchRunner.php(28): WP_CLI\Runner->start()
#46 phar:///mnt/c/Users/vadim/wpssg/wp-cli.phar/vendor/wp-cli/wp-cli/php/bootstrap.php(83): WP_CLI\Bootstrap\LaunchRunner->process()
#47 phar:///mnt/c/Users/vadim/wpssg/wp-cli.phar/vendor/wp-cli/wp-cli/php/wp-cli.php(32): WP_CLI\bootstrap()
#48 phar:///mnt/c/Users/vadim/wpssg/wp-cli.phar/php/boot-phar.php(20): include('...')
#49 /mnt/c/Users/vadim/wpssg/wp-cli.phar(4): include('...')
#50 {main}
  thrown in /mnt/c/Users/vadim/wpssg/postmark/src/Formatter.php on line 48
Error: There has been a critical error on this website.Learn more about troubleshooting WordPress. There has been a critical error on this website.
pjeby commented 10 months ago

It looks like in the current league/commonmark, the extension namespace is League\CommonMark\Extension\Table. If you look at https://github.com/dirtsimple/postmark/blob/master/src/Formatter.php#L29 you'll see that the configuration used is passed through the postmark_formatter_config hook, so you can use that hook to change the extension paths.

If you visit the github repos of the various deprecated packages, they give the new paths for the extensions. I don't know if that will entirely fix your problem, but that would appear to be the next step.

At the moment, I am still supporting PHP 7.1 for some sites, so I can't really switch to the newer league/commonmark version yet as it requires 7.4 as a minimum. But patches to improve 8.x compatibility that don't break 7.1 (or older WP versions) are welcome. If something that's necessary is incompatible, I suppose I could make an alternate dev branch, but I'd prefer not to if possible.

pjeby commented 10 months ago

Also, it looks like you might be able to put back the requirement for league/commonmark to be 1.x, as the newer 1.x versions support both PHP 7.1 and 8.x, which means the result might be releasable on the master branch here. In general, I would suggest not using * versions but keeping the ones postmark specifies unless absolutely necessary to upgrade. In some cases (e.g. commonmark) you may be getting versions that postmark is just not compatible with.

vadimkantorov commented 10 months ago

Thanks for your feedback! I'll try to figure it out. I absolutely have no PHP experience though, so it might be a bit rough.

I've also tried keeping the commonmark-related packages intact. When I use

        "league/commonmark": "^1.0",
        "league/commonmark-ext-smartpunct": "^1.1",
        "league/commonmark-ext-strikethrough": "^1.0",
        "league/commonmark-ext-table": "^2.1",
        "webuni/commonmark-attributes-extension": "^1.0",

I get

Problem 1
    - league/commonmark-ext-smartpunct[v1.1.0, v1.2.0, 1.3.x-dev] require php ^7.1 -> your php version (8.1.2) does not satisfy that requirement.
    - dirtsimple/postmark dev-master requires league/commonmark-ext-smartpunct ^1.1 -> satisfiable by league/commonmark-ext-smartpunct[v1.1.0, v1.2.0, 1.3.x-dev].
    - Root composer.json requires dirtsimple/postmark dev-main || dev-master || dev-trunk -> satisfiable by dirtsimple/postmark[dev-master].

Indeed, the latest release of smartpunct before deprecation still requires php 7.1, as it was deprecated in 2020

vadimkantorov commented 10 months ago

I guess, the firs question might be: is it possible to build postmark without these commonmark extensions? E.g. it seems that smartpunct was upstreamed the main league/commmonmark repo

vadimkantorov commented 10 months ago

It appears that one now must use this https://commonmark.thephpleague.com/2.4/extensions/github-flavored-markdown/ instead of the legacy smartpunct/strikethrough/table extensions

vadimkantorov commented 10 months ago

And the attributes extension was also upstreamed to https://commonmark.thephpleague.com/2.4/extensions/attributes/

vadimkantorov commented 10 months ago

The mainline commonmark 2.4 supports "php": "^7.4 || ^8.0", https://github.com/thephpleague/commonmark/blob/2.4/composer.json#L24 - not sure if I could use on the newest php 8.1.2?

vadimkantorov commented 10 months ago

I commented out the e

you'll see that the configuration used is passed through the postmark_formatter_config hook, so you can use that hook to change the extension paths.

So far I just patched out this method and the sync command worked!

vadimkantorov commented 10 months ago

If you are interested, I'm documenting here https://github.com/vadimkantorov/wpssg commands to turn WordPress into a SSG and being able to run in in GitHub Actions, similar to Jekyll (this is useful for some porting scenarios of simple content-only blogs)

pjeby commented 10 months ago

I believe that all you really need to do is upgrade league/commonmark to 1.6, change the paths for the extensions, and change the PHP version required to be appropriate, and it would probably be compatible with PHP 7.1 - 8.1. I do plan to give that a try at some point myself, and if I do I will update the repo. Just not sure when I'll have the time to dive into it.

vadimkantorov commented 1 month ago

Hi! I'm back to trying to make a self-contained SSG example with Markdown and WordPress.

Now something in WordPress or wp-cli has changed (maybe some simple namespace renames?), getting a very hairy stack trace below. Would be very grateful of you could take a look when you have time and maybe suggest how to fix the error or at least how to simplify my installation commands

$ cat _posts/post.md

---
ID: urn:uuid:be65c90f-e294-40c8-8521-69cf3fb407ab
---
# My markdown post
Hello world

$ cat postmark_composer.json

{
    "name": "dirtsimple/postmark",
    "description": "Sync WP content from Markdown files",
    "type": "wp-cli-package",
    "homepage": "https://github.com/dirtsimple/postmark/",
    "license": "MIT",
    "authors": [
        {
            "name": "PJ Eby",
            "homepage": "https://github.com/pjeby"
        }
    ],
    "keywords": [
        "markdown",
        "wordpress",
        "wp",
        "wp-cli",
        "yaml",
        "front-matter",
        "content-management",
        "configuration-management",
        "static-site-generator",
        "yaml front matter"
    ],
    "minimum-stability": "dev",
    "prefer-stable": true,
    "autoload": {
        "files": [ "command.php" ],
        "psr-4": {
            "dirtsimple\\Postmark\\": "src/"
        }
    },
    "require": {
        "dirtsimple/clean-yaml": "^0.1",
        "dirtsimple/imposer": "dev-master",
        "wp-cli/wp-cli": "*",
        "wp-cli/entity-command": "*",
        "rarst/wpdatetime": "*",
        "league/commonmark": "^1.0",
        "twig/twig": "*",
        "symfony/yaml": "*",
        "php" : "*"
    }
}
# .github/workflows/test.yml
jobs:
  test:
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v4

      - name: Prerequisites
        run: |
          sudo apt install php-cli php-mysql php-dom mysql-server sqlite3
          curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
          curl -o composer.phar https://getcomposer.org/installer
          curl -O -L https://github.com/elementor/wp2static/archive/refs/tags/7.2.tar.gz
          git clone https://github.com/dirtsimple/postmark

      - name: Setup WordPress
        run: |
          sudo service mysql start
          sudo mysql -h 127.0.0.1 --user=root --password=root <<< "CREATE USER 'wpssguser'@'127.0.0.1' IDENTIFIED WITH mysql_native_password BY 'wpssgpass'; CREATE DATABASE wpssgdb; GRANT ALL PRIVILEGES ON wpssgdb.* TO 'wpssguser'@'127.0.0.1';"
          sudo mysql -h 127.0.0.1 --user=wpssguser --password=wpssgpass <<< "SHOW DATABASES"

          php ./wp-cli.phar core download --locale=en_US      --skip-content --force
          php ./wp-cli.phar config create --locale=en_US --dbuser=wpssguser --dbpass=wpssgpass --dbname=wpssgdb --dbhost=127.0.0.1
          #php ./wp-cli.phar db create
          php ./wp-cli.phar core install --url=localhost:8080 --title=wpcli --admin_user=wpcli --admin_password=wpcli --admin_email=info@wp-cli.org
          php ./wp-cli.phar option set permalink_structure '/%year%-%monthnum%-%day%-%postname%/'

      - name: Setup postmark
        run: |
          cp postmark_composer.json postmark/composer.json
          sed -i 's@League\\CommonMark\\Ext\\Table\\TableExtension@dirtsimple\\Postmark\\ShortcodeParser@g' ./postmark/src/Formatter.php
          sed -i 's@League\\CommonMark\\Ext\\Strikethrough\\StrikethroughExtension@dirtsimple\\Postmark\\ShortcodeParser@g' ./postmark/src/Formatter.php
          sed -i 's@League\\CommonMark\\Ext\\SmartPunct\\SmartPunctExtension@dirtsimple\\Postmark\\ShortcodeParser@g' ./postmark/src/Formatter.php
          sed -i 's@Webuni\\CommonMark\\AttributesExtension\\AttributesExtension@dirtsimple\\Postmark\\ShortcodeParser@g' ./postmark/src/Formatter.php
          php ./wp-cli.phar package install ./postmark
          php wp-cli.phar postmark tree _posts # This fails with a nasty stack trace:
PHP Fatal error:  Uncaught Error: Class "WP_CLI\Entity\RecursiveDataStructureTraverser" not found in /home/runner/.wp-cli/packages/vendor/dirtsimple/imposer/src/Scheduler.php:108
Stack trace:
#0 /home/runner/.wp-cli/packages/vendor/dirtsimple/imposer/src/Imposer.php([73](https://github.com/vadimkantorov/wpssg/actions/runs/11264795968/job/31325456191#step:5:74)): dirtsimple\imposer\Scheduler->__construct()
#1 /home/runner/.wp-cli/packages/vendor/dirtsimple/imposer/src/Imposer.php(53): dirtsimple\imposer\Imposer->__construct()
#2 /home/runner/.wp-cli/packages/vendor/dirtsimple/imposer/src/Imposer.php(61): dirtsimple\imposer\Imposer::instance()
#3 /home/runner/work/wpssg/wpssg/postmark/src/PostmarkCommand.php(149): dirtsimple\imposer\Imposer::__callStatic()
#4 [internal function]: dirtsimple\Postmark\PostmarkCommand->tree()
#5 phar:///home/runner/work/wpssg/wpssg/wp-cli.phar/vendor/wp-cli/wp-cli/php/WP_CLI/Dispatcher/CommandFactory.php(100): call_user_func()
#6 [internal function]: WP_CLI\Dispatcher\CommandFactory::WP_CLI\Dispatcher\{closure}()
#7 phar:///home/runner/work/wpssg/wpssg/wp-cli.phar/vendor/wp-cli/wp-cli/php/WP_CLI/Dispatcher/Subcommand.php(497): call_user_func()
#8 phar:///home/runner/work/wpssg/wpssg/wp-cli.phar/vendor/wp-cli/wp-cli/php/WP_CLI/Runner.php(441): WP_CLI\Dispatcher\Subcommand->invoke()
#9 phar:///home/runner/work/wpssg/wpssg/wp-cli.phar/vendor/wp-cli/wp-cli/php/WP_CLI/Runner.php(464): WP_CLI\Runner->run_command()
#10 phar:///home/runner/work/wpssg/wpssg/wp-cli.phar/vendor/wp-cli/wp-cli/php/WP_CLI/Runner.php(1296): WP_CLI\Runner->run_command_and_exit()
#11 phar:///home/runner/work/wpssg/wpssg/wp-cli.phar/vendor/wp-cli/wp-cli/php/WP_CLI/Bootstrap/LaunchRunner.php(28): WP_CLI\Runner->start()
#12 phar:///home/runner/work/wpssg/wpssg/wp-cli.phar/vendor/wp-cli/wp-cli/php/bootstrap.php([83](https://github.com/vadimkantorov/wpssg/actions/runs/11264795968/job/31325456191#step:5:84)): WP_CLI\Bootstrap\LaunchRunner->process()
#13 phar:///home/runner/work/wpssg/wpssg/wp-cli.phar/vendor/wp-cli/wp-cli/php/wp-cli.php(32): WP_CLI\bootstrap()
#14 phar:///home/runner/work/wpssg/wpssg/wp-cli.phar/php/boot-phar.php(20): include('...')
#15 /home/runner/work/wpssg/wpssg/wp-cli.phar(4): include('...')
#16 {main}
  thrown in /home/runner/.wp-cli/packages/vendor/dirtsimple/imposer/src/Scheduler.php on line 108
Error: There has been a critical error on this website.Learn more about troubleshooting WordPress. There has been a critical error on this website.
pjeby commented 1 month ago

Apparently late last year they moved WP_CLI\Entity\RecursiveDataStructureTraverser to WP_CLI\Traverser\RecursiveDataStructureTraverser, so you might need another sed. :wink:

As far as simplifying installation, I'm not sure why you don't just fork this repo and check in your changes, since then you wouldn't need to run all these sed and cp steps, just check out your own repo. It'd make it easier to send a pull request too, unless I'm missing something about your setup?

vadimkantorov commented 1 month ago

Managed to sed-through :)

https://github.com/vadimkantorov/wpssg/blob/57e4cdce65d4dc964273d2a007470cc39cb8843e/.github/workflows/publish.yml#L56-L72 - a ton of hacks, would be good to have it updated in this repo and in imposer

In publish.yml I combined postmark with wp2static and the GH Actions workflow produced the following static htmls: https://vadimkantorov.github.io/wpssg/

vadimkantorov commented 1 month ago

How to properly address problems of markdown exts and versions?

pjeby commented 1 month ago

With regard to both case-sensitivity and filename ingestion, you can implement these features using the plugin's postmark load wp-post hook. The Document object has a ->filename() method, so you can read the filename and add a date to the headers, re-case the headers, etc. For tables, I assume you need a compatible table extension. (Perhaps you should try specific versions of things and consult their manuals; using * as a version target isn't likely to produce stable results.)

vadimkantorov commented 1 month ago

Would you be okay to merge this PR for imposer?

I can also make a separate PR for postmark too which fixes the namespace

pjeby commented 1 month ago

I've updated imposer to depend on wp-cli 2.11+ and to change the namespaces. I've also similarly updated postmark and verified that it works correctly w/tables, smart punctuation, attributes, strikethrough, and so on. You should be able to use stock versions of both now -- let me know whether it works for you or not.

vadimkantorov commented 1 month ago

Your fixes helped! Now no patches needed! Thank you!

If you are curious to see, here is my attempt at using a WordPress/existing WordPress theme as a static-site-generator: https://github.com/vadimkantorov/wpssg/blob/master/.github/workflows/publish.yml I'm likely not using composer here very correctly - maybe wp-cli / postmark / wp2static could all be just installed / compiled via composer?

I'd say the next very useful thing could be a more native support for Jekyll-standard *.md files (extracting post dates from the file name + supporting some of typical front-matter fields without requiring casing (https://jekyllrb.com/docs/front-matter/ : title, author, authors, tags, category, categories). If I have time, I'll try to follow your advice on adding a hook.

But as I discovered, the WP ecosystem has dozens of markdown plugins :( everything is so fragmented... Basically, my idea is to export all posts from an existing server-hosted WP to markdown (maybe something like https://wordpress.org/plugins/ultimate-markdown/ is better if it can deparse html to markdown as IIUC postmark can't do that), and then migrate to WP usage as a static-site-generator where a MySql database is populated at a site build time and all posts are re-added every time from the markdown files...

pjeby commented 1 month ago

Yeah, postmark can't turn HTML to markdown, but it can certainly export HTML as-is.

For installations, yes you can install wp-cli and postmark with composer - you just need a composer.json file that lists the versions of everything you want and then composer install will install it. Scripts will then end up in vendor/bin. You can even install Wordpress itself that way, I personally use the johnpbloch/wordpress composer package, see this example. The wpackagist thing mentioned there lets you also install wordpress plugins by listing them as wpackagist-plugin/plugin-name in composer.json.

(That example doesn't list wp-cli, imposer, or postmark, because those are done with global installs to /composer/bin in that project's Dockerfile. composer-global there is a script from the php-server image.)

My own WP websites are built using a git repo with a composer.json in the root that installs WP and plugins, in a docker image that has the global wp-cli tool installed. But you could just as easily install everything with a single composer.json. I keep them separate mainly because it 1) made installs faster and 2) if you break something in the site it doesn't necessarily break the global install of wp-cli. Neither of those concerns are a big issue for you, I don't think, if you're running GH actions to rebuild the site every time, and the speed issue is less relevant now that composer 2 exists and is way faster than composer 1 (which is what I'd been using until recently).

vadimkantorov commented 1 month ago

The only thing that puts me off in this approach is having to rely on a somewhat unofficial repos https://github.com/johnpbloch/wordpress, https://github.com/johnpbloch/wordpress-core, https://github.com/johnpbloch/wordpress-core-installer for such a core package...

pjeby commented 1 month ago

You can always roll your own, I suppose. My stuff is based on the dirtsimple/mantle-site and dirtsimple/mantle-tools projects, whose approach was based on things I learned from Bedrock (which used to use the johnpbloch stuff, but now has their own).