fipamo/app/Services/ContentService.php
ro 2395278893
added content collector and pagination
plugged in the dash index template which required grabbing markdown
pages and converting them to data the system can use and then pagination
that is used to sort content into pages

start page now switches from login screen to index based on session, but
that might be changes so it's a bit more clean to work with middleware
2024-03-03 17:49:05 -06:00

196 lines
7.2 KiB
PHP

<?php
namespace App\Services;
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;
}
}