Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions %plugin_name%.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
* Author URI: %plugin_author_uri%
* Text Domain: %plugin_name%
* Domain Path: /languages
* Requires at least: 6.0
* Tested up to: 6.9
* Requires PHP: 8.2
* Requires at least: 7.1
* Tested up to: 7.1
* Requires PHP: 8.4
* Network: false
* License: MIT
* License URI: https://opensource.org/licenses/MIT
Expand Down
71 changes: 71 additions & 0 deletions .github/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<p align="center">
<a href="https://pollora.dev">
<img src="https://raw.githubusercontent.com/Pollora/.github/main/brand/banners/plugin-default.png" width="100%" alt="Pollora plugin template: the starting point for a Pollora WordPress plugin">
</a>
</p>

<p align="center">
<a href="https://github.com/Pollora/plugin-default/tags"><img src="https://img.shields.io/github/v/tag/Pollora/plugin-default?label=version" alt="Version"></a>
<a href="../LICENSE"><img src="https://img.shields.io/github/license/Pollora/plugin-default" alt="License"></a>
</p>

The plugin template that `php artisan pollora:make:plugin` downloads: a WordPress plugin registered with [Pollora](https://pollora.dev), with a PSR-4 `app/` directory, service providers, hooks declared with PHP attributes, Blade views and an optional Vite build. You start from a plugin that already loads, instead of wiring `add_action()` calls and a bootstrap file by hand.

## Installation

```bash
php artisan pollora:make:plugin my-plugin
```

The command downloads the latest tag of this template, replaces its placeholders with your plugin's name, namespace and header, and offers to activate the plugin. With assets (`--asset`), it also runs `npm install` and `npm run build`; without them, the Vite files are left out.

Requirements: a Pollora project (PHP 8.4+ and WordPress 7.1+ for a new one; the framework itself runs on PHP 8.3+), and Node.js 20.19+ or 22.12+ (Vite 8) when the plugin has assets.

## Structure

```
%plugin_name%/
├── app/ # Application code (PSR-4 autoloaded)
│ ├── Providers/ # Service providers (plugin, assets)
│ └── %plugin_namespace%Plugin.php # Main plugin class: activation, hooks
├── config/plugin.php # Name, version, text domain, assets path
├── resources/
│ ├── assets/ # CSS, JS files (Vite)
│ └── views/ # Blade templates
└── %plugin_name%.php # Main plugin file: header, pollora_register()
```

The main class declares its hooks with attributes, which Pollora discovers on its own:

```php
#[Action('init', priority: 10)]
public function onInit(): void
{
// …
}
```

## Development

```bash
npm install # once
npm run dev # Vite dev server with hot reload
npm run build # production build
```

## Documentation

- [Plugins](https://pollora.dev/advanced/plugins/): creating a plugin, its architecture, the command's options and asset management
- [Hooks](https://pollora.dev/hooks/actions-filters/), [post types](https://pollora.dev/content/post-types/) and the rest of the framework at [pollora.dev](https://pollora.dev)

## Template development

This repository is a template: its files carry placeholders that `pollora:make:plugin` substitutes, and the PHP classes in `app/` are `.stub` files, so it does not run as is. Develop on a plugin generated under the code name set in `bin/package-plugin.sh`, then copy it back with `./bin/package-plugin.sh /path/to/the/plugin`, which turns the names back into placeholders. `php bin/tests/run.php` checks the result.

## Contributing

Contributions are welcome: see the [contributing guide](https://github.com/Pollora/.github/blob/main/CONTRIBUTING.md). Report security issues privately, as described in the [security policy](https://github.com/Pollora/.github/blob/main/SECURITY.md).

## License

The Pollora plugin template is open-source software licensed under the [MIT license](../LICENSE). © [RuBee group](https://rubee.group)
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2025 RuBee group
Copyright (c) 2025 RuBee group (https://rubee.group)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
62 changes: 33 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,51 @@

%plugin_description%

## Description
Built with [Pollora](https://pollora.dev) from the [plugin-default](https://github.com/Pollora/plugin-default) template.

This plugin is built using the Pollora Framework, which provides a modern development experience by bridging Laravel and WordPress.

## Requirements

- WordPress 6.0 or higher
- PHP 8.2 or higher
- Pollora Framework

## Directory Structure
## What's inside

```
%plugin_name%/
├── app/ # Application code (PSR-4 autoloaded)
│ ├── Providers/ # Service providers
│ └── %plugin_namespace%Plugin.php # Main plugin class
├── config/ # Configuration files
├── app/ # PHP classes, namespace Plugin\%plugin_namespace%
│ ├── Providers/ # Service providers (plugin, assets)
│ └── %plugin_namespace%Plugin.php # Main class: activation, hooks declared with attributes
├── config/plugin.php # Name, version, text domain, assets path
├── resources/
│ ├── assets/ # CSS, JS files (Vite)
│ └── views/ # Blade templates
└── %plugin_name%.php # Main plugin file
│ ├── assets/ # CSS and JS, built with Vite (when generated with assets)
│ └── views/ # Blade templates
└── %plugin_name%.php # Plugin header, registers the plugin with Pollora
```

## Development
Hooks are declared on methods with attributes and discovered by Pollora, no `add_action()` needed:

```bash
# Install dependencies
npm install
```php
#[Action('init', priority: 10)]
public function onInit(): void
{
// …
}
```

# Development with HMR
npm run dev
## Commands

# Production build
npm run build
Run from the plugin's directory, when it has assets:

```bash
npm run dev # Vite dev server with hot reload
npm run build # production assets
```

## License
From the project root:

MIT — see [LICENSE](LICENSE).
```bash
php artisan pollora:make:block my-block --plugin=%plugin_name% # a new Gutenberg block
php artisan discovery:clear # after adding attribute-based classes
php artisan pollora:doctor # when something fails without an error
```

## Credits
## Read more

- Built with [Pollora Framework](https://pollora.dev)
- [Plugins](https://pollora.dev/advanced/plugins/): architecture, namespaces, discovery, assets
- [Actions and filters](https://pollora.dev/hooks/actions-filters/)
- [Gutenberg blocks](https://pollora.dev/blocks/gutenberg-blocks/)
45 changes: 44 additions & 1 deletion bin/package-plugin.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,15 @@ if [ ! -d "$SOURCE" ]; then
exit 1
fi

# The WordPress and PHP requirements in the plugin header belong to the
# template, which follows the framework; the development copy lags behind.
# Read them before the sync and put them back after it.
TEMPLATE_MAIN="$TARGET_DIR/%plugin_name%.php"
REQUIREMENTS=""
if [ -f "$TEMPLATE_MAIN" ]; then
REQUIREMENTS=$(grep -E '^ \* (Requires at least|Tested up to|Requires PHP):' "$TEMPLATE_MAIN" || true)
fi

# Sync files (exclude node_modules, locks, build artifacts, .git)
echo "Syncing files..."
rsync -av --delete \
Expand All @@ -43,13 +52,39 @@ rsync -av --delete \
--exclude='yarn.lock' \
--exclude='.git' \
--exclude='bin/' \
--exclude='/README.md' \
--exclude='/.github/' \
--exclude='/LICENSE' \
--exclude='/license.txt' \
"$SOURCE/" "$TARGET_DIR/" \
--quiet

# package.json comes from the development copy, which declares no license (or
# another one): the template's is MIT, the same as LICENSE.
echo "Setting the package.json license to MIT..."
node -e '
const fs = require("fs");
const [file, license] = process.argv.slice(1);
const pkg = JSON.parse(fs.readFileSync(file, "utf8"));
let out = pkg;
if ("license" in pkg) {
pkg.license = license;
} else {
out = {};
for (const [key, value] of Object.entries(pkg)) {
out[key] = value;
if (key === "private") out.license = license;
}
if (!("license" in out)) out.license = license;
}
fs.writeFileSync(file, JSON.stringify(out, null, 4) + "\n");
' "$TARGET_DIR/package.json" "MIT"

echo "Replacing code name with placeholders..."

find "$TARGET_DIR" -type f \
-not -path "*/.git/*" \
-not -path "*/.github/*" \
-not -path "*/node_modules/*" \
-not -path "*/bin/*" \
-not -name "package-plugin.sh" \
Expand Down Expand Up @@ -105,14 +140,22 @@ elif [ -f "$TARGET_DIR/%plugin_name%.php" ]; then
true
fi

if [ -n "$REQUIREMENTS" ] && [ -f "$TEMPLATE_MAIN" ]; then
echo "Restoring the template's requirements in the plugin header..."
while IFS= read -r line; do
key="${line%%:*}"
sed -i "s|^${key//\*/\\*}:.*|${line}|" "$TEMPLATE_MAIN"
done <<< "$REQUIREMENTS"
fi

echo "Checking nothing kept the code name..."

# The replacement rules above are a hand-maintained list, and theme-default
# shipped a tag where a whole new directory slipped past its equivalent: the
# blocks added under resources/views went out naming the development theme.
# Nothing there noticed, because nothing looked afterwards. This looks.
if leaked=$(grep -rn "${CODE_NAME}\|${CODE_STUDLY}\|${CODE_FUNCTION}\|${CODE_UPPER}" "$TARGET_DIR" \
--exclude-dir=.git --exclude-dir=node_modules --exclude=package-plugin.sh); then
--exclude-dir=.git --exclude-dir=.github --exclude-dir=bin --exclude-dir=node_modules --exclude=package-plugin.sh); then
echo ""
echo "Error: the code name survived packaging:"
echo "$leaked"
Expand Down
Loading