Importing content
Content importers convert data from external sources (Telegram, WordPress, Jekyll, REST APIs, databases, etc.) into YiiPress markdown files with front matter. They are invoked via the yii import command.
Importer interface
An importer implements YiiPress\Import\ContentImporterInterface:
interface ContentImporterInterface { public function options(): array; public function import(array $options, string $targetDirectory, string $collection): ImportResult; public function name(): string; }
options()— returns a list ofImporterOptionobjects declaring what CLI options this importer accepts. Each option becomes a--nameflag in theyii importcommand.import()— receives resolved option values as$options(keyed by option name), creates.mdfiles in$targetDirectory/$collection/, copies media to$targetDirectory/$collection/assets/, and creates_collection.yamlif missing.name()— returns the unique identifier used as thesourceargument inyii import(e.g.,telegram,wordpress).
ImporterOption
Each importer declares its options using ImporterOption:
new ImporterOption( name: 'directory', description: 'Path to the export directory', required: true, default: null, path: true, )
name— option name, used as--nameon the CLI and as key in the$optionsarray.description— help text shown inyii import --help.required— whether the option must be provided. The command validates this before callingimport().default— default value when the option is not provided (only for optional options).path— whether the option value is a filesystem path. Path options are resolved relative to the project root; non-path options such as comma-separated IDs are passed through unchanged.
ImportResult
ImportResult is a value object returned by import() containing:
totalMessages()— total number of source items found.importedCount()— number of items successfully imported.importedFiles()— list of created file paths.skippedFiles()— list of skipped items with reasons.warnings()— list of warning messages.
Built-in importers
TelegramContentImporter
Imports messages from a Telegram Desktop channel export (JSON format).
Options:
--directory— Path to the Telegram export directory containingresult.json(required)--ignore_message_ids— Comma-separated list of message IDs to skip during import (optional)
See commands.md for usage details.
MediumContentImporter
Imports Markdown files from a Medium Markdown export directory.
Options:
--directory— Path to the Medium Markdown export directory (required)
The importer scans posts/ first when present, otherwise the provided directory, and converts .md files into the selected YiiPress collection. It supports YAML front matter, preserves common metadata (title, date, origin URL, draft status, tags, and categories), infers missing titles/dates from headings and filenames, and avoids overwriting duplicate output filenames.
See commands.md for usage details.
GhostContentImporter
Imports posts and pages from a Ghost JSON export.
Options:
--file— Path to the Ghost.jsonexport file (required)
The importer converts Ghost posts into the selected YiiPress collection and Ghost pages into standalone content root markdown files. It preserves common metadata (title, date, draft status, excerpt summary, feature image, tags, and authors), keeps html as the markdown body, skips unsupported post types, and avoids overwriting duplicate output filenames.
See commands.md for usage details.
WordPressContentImporter
Imports posts and pages from a WordPress WXR XML export.
Options:
--file— Path to the WordPress WXR.xmlexport file (required)
The importer converts WordPress posts into the selected YiiPress collection and WordPress pages into standalone content root markdown files. It preserves common metadata (title, date, permalink path, draft status, excerpt summary, tags, and categories), keeps content:encoded as the markdown body, skips unsupported WordPress item types, and avoids overwriting duplicate output filenames.
See commands.md for usage details.
JekyllContentImporter
Imports Markdown posts from a Jekyll site _posts/ directory.
Options:
--directory— Path to the Jekyll site directory containing_posts(required)
The importer accepts .md and .markdown posts named YYYY-MM-DD-slug, preserves common front matter (title, date, permalink, tags, categories), and creates a default collection config when one does not exist.
See commands.md for usage details.
HugoContentImporter
Imports Markdown content from a Hugo site.
Options:
--directory— Path to the Hugo site directory (required)
The importer scans content/posts/, then content/post/, then content/, accepts .md files, supports YAML (---) and simple TOML (+++) front matter, preserves common fields (title, date, url / permalink, draft, tags, categories), and creates a default collection config when one does not exist.
See commands.md for usage details.
Writing a custom importer
Create a class implementing ContentImporterInterface. Each importer declares its own options — a file-based importer might need a directory, while an API-based importer might need url and api-key.
For example, a REST API importer:
final class RestApiContentImporter implements ContentImporterInterface { public function options(): array { return [ new ImporterOption(name: 'url', description: 'API endpoint URL', required: true), new ImporterOption(name: 'api-key', description: 'API authentication key', required: true), new ImporterOption(name: 'limit', description: 'Max posts to import', default: '100'), ]; } public function import(array $options, string $targetDirectory, string $collection): ImportResult { $url = $options['url']; $apiKey = $options['api-key']; $limit = (int) ($options['limit'] ?? '100'); // 1. Fetch data from the API // 2. For each post, create a .md file with front matter in $targetDirectory/$collection/ // 3. Return ImportResult with stats } public function name(): string { return 'rest-api'; } }
Each generated markdown file should follow the standard YiiPress front matter format:
--- title: My Post Title date: 2024-03-15 10:30:00 tags: - php - tutorial --- Post content in markdown...
To register the importer, add it to the importers array in config/common/di/importer.php:
use YiiPress\Console\ImportCommand; use YiiPress\Import\Telegram\TelegramContentImporter; use YiiPress\Import\RestApiContentImporter; return [ ImportCommand::class => [ '__construct()' => [ 'rootPath' => dirname(__DIR__, 3), 'importers' => [ 'telegram' => new TelegramContentImporter(), 'rest-api' => new RestApiContentImporter(), ], ], ], ];
The array key must match the value returned by name() and is used as the source argument:
yii import rest-api --url=https://api.example.com/posts --api-key=secret