1
0
Files
breadcrumb-the-shire/core/Service/Content/PageService.php
fs 0e86925464 refactor: rename lib/ to core/ for clearer core-module separation
Rename the top-level lib/ directory to core/ so the project root
immediately communicates which code is core platform and which lives
in modules/. PHP namespaces (MintyPHP\*) are unchanged — only the
Composer PSR-4 path mapping moves from lib/ to core/.

Module-internal lib/ directories (modules/*/lib/) are untouched.

Updated across the full stack:
- composer.json PSR-4 mapping
- bootstrap entry points (web/index.php, bin/*, tests/bootstrap.php)
- tooling configs (phpstan.neon, phpunit.xml, php-cs-fixer)
- 26 architecture contract tests
- enforcement-policy, guard-catalog, quality-gates
- all documentation (CLAUDE.md, README, 25 docs/, .agents/skills/)
- bin/qa-extended.sh search paths
- .claude/settings.local.json permission paths

Workflow: .agents/runs/CORE-LIB-RENAME-001/ (Analyst → Planner →
Executor → Code Review (4 findings fixed) → Security Review →
Acceptance Test → Finalizer)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 23:20:42 +02:00

161 lines
5.2 KiB
PHP

<?php
namespace MintyPHP\Service\Content;
use MintyPHP\I18n;
use MintyPHP\Repository\Content\PageContentRepository;
use MintyPHP\Repository\Content\PageRepository;
class PageService
{
public static function findBySlug(string $slug): ?array
{
$slug = trim($slug);
if ($slug === '') {
return null;
}
return PageRepository::findBySlug($slug);
}
public static function findBySlugWithLocale(string $slug, ?string $locale = null): ?array
{
$page = self::findBySlug($slug);
if (!$page || !isset($page['id'])) {
return null;
}
$locale = $locale ?: (I18n::$locale ?? I18n::$defaultLocale);
$content = PageContentRepository::findByPageIdAndLocale((int) $page['id'], $locale);
$usedLocale = $locale;
$fallbackLocale = I18n::$defaultLocale;
if (defined('APP_LOCALES') && is_array(APP_LOCALES) && count(APP_LOCALES) > 0) {
$fallbackLocale = APP_LOCALES[0];
}
if (!$content && $fallbackLocale !== $locale) {
$content = PageContentRepository::findByPageIdAndLocale((int) $page['id'], $fallbackLocale);
if ($content) {
$usedLocale = $fallbackLocale;
}
}
if (!$content) {
$content = [
'locale' => $usedLocale,
'content' => null,
];
}
return [
'page' => $page,
'content' => $content,
'locale' => $usedLocale,
];
}
public static function updateContentBySlug(
string $slug,
string $content,
int $currentUserId = 0,
?string $locale = null
): array {
$slug = trim($slug);
if ($slug === '') {
return ['ok' => false, 'status' => 404, 'error' => 'not_found'];
}
$page = PageRepository::findBySlug($slug);
if (!$page || !isset($page['id'])) {
return ['ok' => false, 'status' => 404, 'error' => 'not_found'];
}
$locale = $locale ?: (I18n::$locale ?? I18n::$defaultLocale);
$content = trim($content);
$normalized = null;
if ($content !== '') {
$decoded = json_decode($content, true);
if (!is_array($decoded)) {
return ['ok' => false, 'errors' => [t('Content is invalid')]];
}
if (!isset($decoded['blocks']) || !is_array($decoded['blocks'])) {
$decoded['blocks'] = [];
}
$normalized = json_encode($decoded, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
}
$existing = PageContentRepository::findByPageIdAndLocale((int) $page['id'], $locale);
$updated = false;
if ($existing && isset($existing['id'])) {
$updated = PageContentRepository::update((int) $existing['id'], [
'content' => $normalized,
'modified_by' => $currentUserId > 0 ? $currentUserId : null,
]);
} else {
$createdId = PageContentRepository::create([
'page_id' => (int) $page['id'],
'locale' => $locale,
'content' => $normalized,
'created_by' => $currentUserId > 0 ? $currentUserId : null,
]);
$updated = (bool) $createdId;
}
if (!$updated) {
return ['ok' => false, 'errors' => [t('Page can not be updated')]];
}
return ['ok' => true, 'page' => $page];
}
public static function copyContentToLocale(
string $slug,
string $fromLocale,
string $toLocale,
int $currentUserId = 0
): array {
$slug = trim($slug);
$fromLocale = trim($fromLocale);
$toLocale = trim($toLocale);
if ($slug === '' || $fromLocale === '' || $toLocale === '') {
return ['ok' => false, 'errors' => [t('Target language required')]];
}
$page = PageRepository::findBySlug($slug);
if (!$page || !isset($page['id'])) {
return ['ok' => false, 'status' => 404, 'error' => 'not_found'];
}
$source = PageContentRepository::findByPageIdAndLocale((int) $page['id'], $fromLocale);
if (!$source) {
return ['ok' => false, 'errors' => [t('Source content not found')]];
}
$target = PageContentRepository::findByPageIdAndLocale((int) $page['id'], $toLocale);
$content = $source['content'] ?? null;
$updated = false;
if ($target && isset($target['id'])) {
$updated = PageContentRepository::update((int) $target['id'], [
'content' => $content,
'modified_by' => $currentUserId > 0 ? $currentUserId : null,
]);
} else {
$createdId = PageContentRepository::create([
'page_id' => (int) $page['id'],
'locale' => $toLocale,
'content' => $content,
'created_by' => $currentUserId > 0 ? $currentUserId : null,
]);
$updated = (bool) $createdId;
}
if (!$updated) {
return ['ok' => false, 'errors' => [t('Page can not be updated')]];
}
return ['ok' => true];
}
}