fipamo/app/Services/Data/ContentService.php
ro 36d04c8f68
reorganized services
service classes are beginning to swell as there functionality is being
fleshed out, so a new organizational structure was needed to make sure
class sizes don't become too large and to increase site managability and
legibilty as more features get added and the code base grows.

data is for retrieving, managing site information, assets interact with external files
and upkeep is for maintenance.

some additional tweaks were also made to the options menu template to
prep it for it's transition to a toolbar component
2024-05-12 22:14:53 -06:00

201 lines
7.3 KiB
PHP

<?php
namespace App\Services\Data;
use HtmlSanitizer\SanitizerBuilder;
use League\CommonMark\MarkdownConverter;
use League\CommonMark\Environment\Environment;
use HtmlSanitizer\Extension\Basic\BasicExtension;
use HtmlSanitizer\Extension\Listing\ListExtension;
use HtmlSanitizer\Extension\Iframe\IframeExtension;
use League\CommonMark\Extension\Table\TableExtension;
use League\CommonMark\Extension\Attributes\AttributesExtension;
use League\CommonMark\Extension\FrontMatter\FrontMatterExtension;
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
use League\CommonMark\Extension\Strikethrough\StrikethroughExtension;
use League\CommonMark\Extension\FrontMatter\Output\RenderedContentWithFrontMatter;
class ContentService
{
protected $files = [];
protected $config = [];
public function __construct()
{
$this->loadPages(env('PAGES_PATH'));
}
public function loadPages($folder)
{
$folders = glob("$folder/*", GLOB_ONLYDIR);
foreach ($folders as $folder) {
//$this->files[] = $folder . "/";
$this->loadPages($folder);
}
$files = array_filter(glob("$folder/*md"), 'is_file');
foreach ($files as $file) {
$this->files[] = $file;
}
}
public function loadAllPages()
{
$environment = new Environment($this->config);
$environment->addExtension(new CommonMarkCoreExtension());
// Add the extension
$environment->addExtension(new FrontMatterExtension());
//Add Strikethrough rendering
$environment->addExtension(new StrikethroughExtension());
//add attributes to elements in markdown
$environment->addExtension(new AttributesExtension());
//add table rendering
$environment->addExtension(new TableExtension());
// Instantiate the converter engine and start converting some Markdown!
$converter = new MarkdownConverter($environment);
$contents = [];
foreach ($this->files as $file) {
//get meta and html from file
$result = $converter->convertToHtml(file_get_contents($file));
$meta = [];
if ($result instanceof RenderedContentWithFrontMatter) {
$meta = $result->getFrontMatter();
}
//get raw markdown from file
$frontMatterExtension = new FrontMatterExtension();
$parsed = $frontMatterExtension
->getFrontMatterParser()
->parse(file_get_contents($file));
//never trust the front end. clean it up
//add what sanitizer extensions we need manually
$builder = new SanitizerBuilder();
$builder->registerExtension(new BasicExtension());
$builder->registerExtension(new IframeExtension());
$builder->registerExtension(new ListExtension());
//just add it straight because classname is already in use
$builder->registerExtension(new \HtmlSanitizer\Extension\Table\TableExtension());
//relative-a and relative-image
$builder->registerExtension(
new \HtmlSanitizer\Extension\Relative\A\AExtension()
);
$builder->registerExtension(
new \HtmlSanitizer\Extension\Relative\Image\ImageExtension()
);
$detergent = [
'extensions' => ['basic', 'list', 'relative-a', 'relative-image', 'iframe', 'table'],
'tags' => [
'div' => [
'allowed_attributes' => ['class', 'title', 'id', 'style'],
],
'img' => [
'allowed_attributes' => ['src', 'alt', 'title', 'class'],
],
'iframe' => [
'allowed_attributes' => ['height', 'width', 'title', 'src'],
],
],
];
$sanitizer = $builder->build($detergent);
$scrubbed = $sanitizer->sanitize($result->getContent());
if (isset($meta['feature'])) {
$featureList = explode(',', $meta['feature']);
} else {
$featureList = "";
}
$docs = '';
if (isset($meta['files'])) {
$fileList = explode(',', $meta['files']);
$docs = $meta['files'];
} else {
$fileList = [];
$docs = '';
}
$media = [];
$files = [];
if ($featureList != '') {
foreach ($featureList as $file) {
$item = trim($file);
$ext = pathinfo($item, PATHINFO_EXTENSION);
if ($item != null || $item != '') {
array_push($media, ['file' => $item, 'type' => trim($ext)]);
}
}
}
if ($fileList != "") {
foreach ($fileList as $file) {
$item = trim($file);
$ext = pathinfo($item, PATHINFO_EXTENSION);
if ($item != null || $item != '') {
array_push($files, ['file' => $item, 'type' => trim($ext)]);
}
}
}
//sort attributes into page object
$page = [
'id' => $meta['id'],
'uuid' => $meta['uuid'],
'title' => $meta['title'],
'feature' => $meta['feature'],
'files' => $docs,
'path' => $meta['path'],
'layout' => $meta['layout'],
'tags' => $meta['tags'],
'author' => $meta['author'],
'created' => date('Y M D d', $meta['created']),
'updated' => date('Y M D d', $meta['updated']),
'rawCreated' => $meta['created'],
'rawUpdated' => $meta['updated'],
'createdYear' => date('Y', $meta['created']),
'createdMonth' => date('m', $meta['created']),
'deleted' => $meta['deleted'],
'menu' => $meta['menu'],
'featured' => $meta['featured'],
'published' => $meta['published'],
'slug' => $meta['slug'],
'filePath' => $file,
'content' => $parsed->getContent(),
'html' => $scrubbed,
'media' => $media,
'docs' => $files
];
//checks for duplicates
$uuid = $meta['uuid'];
$found = current(
array_filter($contents, function ($item) use ($uuid) {
return isset($item['uuid']) && $uuid == $item['uuid'];
})
);
// if uuid is not present, add it
if (!$found) {
array_push($contents, $page);
}
}
$collection = collect($contents);
$sorted = $collection->sortBy([
['id', 'desc'],
]);
$sorted->values()->all();
return $sorted;
}
public static function getAll()
{
echo("YES");
}
}