diff --git a/app/Http/Controllers/DashController.php b/app/Http/Controllers/DashController.php index 82188fa..f248dc8 100644 --- a/app/Http/Controllers/DashController.php +++ b/app/Http/Controllers/DashController.php @@ -2,43 +2,38 @@ namespace App\Http\Controllers; +use Illuminate\Http\Request; use App\Services\SettingsService; use App\Services\AuthService; -use Illuminate\Http\Request; +use App\Services\PaginateService; class DashController extends Controller { - protected $files = []; protected $settings; - protected $auth; + protected $pages; public function __construct( SettingsService $settingsService, - AuthService $authService + AuthService $authService, + PaginateService $paginateService, ) { - $this->read(env('PAGES_PATH')); $this->settings = $settingsService; $this->auth = $authService; + $this->pages = $paginateService; } public function start(Request $request) { + $status = session('handle') !== null ? true : false; + $result = []; + if ($status) { + $result = $this->pages->getPage(1, 4); + //var_dump($result['pages'][1]['media'][0]['type']); + } return view('back.start', [ - "status" => (session('handle') !== null ? true : false), + "status" => $status, + "result" => $result, "title" => "Fipamo Dash" ]); } - - public function read($folder) - { - $folders = glob("$folder/*", GLOB_ONLYDIR); - foreach ($folders as $folder) { - //$this->files[] = $folder . "/"; - $this->read($folder); - } - $files = array_filter(glob("$folder/*md"), 'is_file'); - foreach ($files as $file) { - $this->files[] = $file; - } - } } diff --git a/app/Providers/FipamoServiceProvider.php b/app/Providers/FipamoServiceProvider.php index 84f7141..41880fe 100644 --- a/app/Providers/FipamoServiceProvider.php +++ b/app/Providers/FipamoServiceProvider.php @@ -5,6 +5,8 @@ namespace App\Providers; use Illuminate\Support\ServiceProvider; use App\Services\SettingsService; use App\Services\AuthService; +use App\Services\ContentService; +use App\Services\PaginateService; class FipamoServiceProvider extends ServiceProvider { @@ -20,6 +22,14 @@ class FipamoServiceProvider extends ServiceProvider $this->app->bind(AuthService::class, function ($app) { return new AuthService(new SettingsService()); }); + + $this->app->bind(ContentService::class, function ($app) { + return new ContentService(); + }); + + $this->app->bind(PaginateService::class, function ($app) { + return new PaginateService(new ContentService()); + }); } /** diff --git a/app/Services/ContentService.php b/app/Services/ContentService.php new file mode 100644 index 0000000..c4be81b --- /dev/null +++ b/app/Services/ContentService.php @@ -0,0 +1,195 @@ +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; + } +} diff --git a/app/Services/PaginateService.php b/app/Services/PaginateService.php new file mode 100644 index 0000000..509fa2f --- /dev/null +++ b/app/Services/PaginateService.php @@ -0,0 +1,90 @@ +content = $contentService; + } + + public function getPage(int $page, int $limit, string $sort = null) + { + $content = $this->content->loadAllPages(); + + $published = filter($content, function ($item) { + return $item['published'] == true && $item['deleted'] == false; + }); + $deleted = filter($content, function ($item) { + return $item['deleted'] == true; + }); + + // $all = $content; + $all = filter($content, function ($item) { + return $item['deleted'] == false; + }); + $filter = isset($sort) ? $sort : 'all'; + switch ($filter) { + case 'published': + $filtered = $published; + break; + case 'deleted': + $filtered = $deleted; + break; + default: + $filtered = $all; + break; + } + $numOfPages = ceil(count($filtered) / ($limit + 1)); + $folder = []; + + if (count($filtered) != 0) { + if (count($filtered) < $limit) { + $limit = count($filtered) - 1; + } + $range = $page * $limit - $limit; + + if ($range != 0) { + $range = $range + 1; + } + for ($i = 0; $i <= $limit; ++$i) { + if (isset($filtered[$i + $range])) { + array_push($folder, $filtered[$i + $range]); + } else { + // chill out + } + } + } + + $prev = $page - 1; + if ($prev <= 0) { + $prev = $numOfPages; + } + + $next = $page + 1; + if ($next > $numOfPages) { + $next = 1; + } + + return [ + 'pages' => $folder, + 'numOfPages' => $numOfPages, + 'entryCount' => count($filtered), + 'paginate' => [ + 'sort' => $sort, + 'nextPage' => $next, + 'prevPage' => $prev, + ], + 'stats' => [ + 'all' => count($all), + 'published' => count($published), + 'deleted' => count($deleted), + ], + ]; + } +} diff --git a/composer.json b/composer.json index 0b818f6..9fce414 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,12 @@ "laravel/framework": "^10.10", "laravel/sanctum": "^3.3", "laravel/tinker": "^2.8", - "lodash-php/lodash-php": "^0.09.0" + "league/commonmark": "^2.4", + "lodash-php/lodash-php": "^0.09.0", + "mnapoli/front-yaml": "^2.0", + "olegatro/html-sanitizer-relative": "^1.0", + "symfony/yaml": "^7.0", + "tgalopin/html-sanitizer": "^1.5" }, "require-dev": { "fakerphp/faker": "^1.9.1", diff --git a/composer.lock b/composer.lock index 2935b71..266019f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "7d751338a52e6d29523f9e2e76fc0397", + "content-hash": "35ea09eaea488e5d0e0c4a22059c367c", "packages": [ { "name": "brick/math", @@ -1894,6 +1894,76 @@ ], "time": "2024-01-28T23:22:08+00:00" }, + { + "name": "league/uri-parser", + "version": "1.4.1", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/uri-parser.git", + "reference": "671548427e4c932352d9b9279fdfa345bf63fa00" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/uri-parser/zipball/671548427e4c932352d9b9279fdfa345bf63fa00", + "reference": "671548427e4c932352d9b9279fdfa345bf63fa00", + "shasum": "" + }, + "require": { + "php": ">=7.0.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.0", + "phpstan/phpstan": "^0.9.2", + "phpstan/phpstan-phpunit": "^0.9.4", + "phpstan/phpstan-strict-rules": "^0.9.0", + "phpunit/phpunit": "^6.0" + }, + "suggest": { + "ext-intl": "Allow parsing RFC3987 compliant hosts", + "league/uri-schemes": "Allow validating and normalizing URI parsing results" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "League\\Uri\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://nyamsprod.com" + } + ], + "description": "userland URI parser RFC 3986 compliant", + "homepage": "https://github.com/thephpleague/uri-parser", + "keywords": [ + "parse_url", + "parser", + "rfc3986", + "rfc3987", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/thephpleague/uri-parser/issues", + "source": "https://github.com/thephpleague/uri-parser/tree/master" + }, + "abandoned": true, + "time": "2018-11-22T07:55:51+00:00" + }, { "name": "lodash-php/lodash-php", "version": "0.09", @@ -1951,6 +2021,110 @@ }, "time": "2024-02-01T07:59:55+00:00" }, + { + "name": "masterminds/html5", + "version": "2.8.1", + "source": { + "type": "git", + "url": "https://github.com/Masterminds/html5-php.git", + "reference": "f47dcf3c70c584de14f21143c55d9939631bc6cf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/f47dcf3c70c584de14f21143c55d9939631bc6cf", + "reference": "f47dcf3c70c584de14f21143c55d9939631bc6cf", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Masterminds\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matt Butcher", + "email": "technosophos@gmail.com" + }, + { + "name": "Matt Farina", + "email": "matt@mattfarina.com" + }, + { + "name": "Asmir Mustafic", + "email": "goetas@gmail.com" + } + ], + "description": "An HTML5 parser and serializer.", + "homepage": "http://masterminds.github.io/html5-php", + "keywords": [ + "HTML5", + "dom", + "html", + "parser", + "querypath", + "serializer", + "xml" + ], + "support": { + "issues": "https://github.com/Masterminds/html5-php/issues", + "source": "https://github.com/Masterminds/html5-php/tree/2.8.1" + }, + "time": "2023-05-10T11:58:31+00:00" + }, + { + "name": "mnapoli/front-yaml", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/mnapoli/FrontYAML.git", + "reference": "d42d84159f3725d50f7bda953ed90185b3c41cc4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mnapoli/FrontYAML/zipball/d42d84159f3725d50f7bda953ed90185b3c41cc4", + "reference": "d42d84159f3725d50f7bda953ed90185b3c41cc4", + "shasum": "" + }, + "require": { + "league/commonmark": "^2.0", + "php": "^7.4|^8.0", + "symfony/yaml": "^4.0|^5.0|^6.0|^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Mni\\FrontYAML\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "support": { + "source": "https://github.com/mnapoli/FrontYAML/tree/2.0.3" + }, + "time": "2024-02-07T14:42:22+00:00" + }, { "name": "monolog/monolog", "version": "3.5.0", @@ -2451,6 +2625,48 @@ ], "time": "2023-02-08T01:06:31+00:00" }, + { + "name": "olegatro/html-sanitizer-relative", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/olegatro/html-sanitizer-relative.git", + "reference": "1a4d4683c0c162653da6dcfe6050476dd8bfc026" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/olegatro/html-sanitizer-relative/zipball/1a4d4683c0c162653da6dcfe6050476dd8bfc026", + "reference": "1a4d4683c0c162653da6dcfe6050476dd8bfc026", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "php": ">=7.1", + "tgalopin/html-sanitizer": "^1.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "HtmlSanitizer\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Oleg Scherbakov", + "email": "shcherbakov.oleg88@gmail.com" + } + ], + "description": "Extension for html-sanitizer library by allowing relative urls in the A and Image tags", + "support": { + "issues": "https://github.com/olegatro/html-sanitizer-relative/issues", + "source": "https://github.com/olegatro/html-sanitizer-relative/tree/1.0.0" + }, + "time": "2021-02-05T13:39:44+00:00" + }, { "name": "phpoption/phpoption", "version": "1.9.2", @@ -5917,6 +6133,126 @@ ], "time": "2024-02-15T11:23:52+00:00" }, + { + "name": "symfony/yaml", + "version": "v7.0.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "2d4fca631c00700597e9442a0b2451ce234513d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/2d4fca631c00700597e9442a0b2451ce234513d3", + "reference": "2d4fca631c00700597e9442a0b2451ce234513d3", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/console": "<6.4" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0" + }, + "bin": [ + "Resources/bin/yaml-lint" + ], + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Loads and dumps YAML files", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/yaml/tree/v7.0.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-23T15:02:46+00:00" + }, + { + "name": "tgalopin/html-sanitizer", + "version": "1.5.0", + "source": { + "type": "git", + "url": "https://github.com/tgalopin/html-sanitizer.git", + "reference": "5d02dcb6f2ea4f505731eac440798caa1b3b0913" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/tgalopin/html-sanitizer/zipball/5d02dcb6f2ea4f505731eac440798caa1b3b0913", + "reference": "5d02dcb6f2ea4f505731eac440798caa1b3b0913", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "league/uri-parser": "^1.4.1", + "masterminds/html5": "^2.4", + "php": ">=7.1", + "psr/log": "^1.0|^2.0|^3.0" + }, + "require-dev": { + "phpunit/phpunit": "^7.4", + "symfony/var-dumper": "^4.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "HtmlSanitizer\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Titouan Galopin", + "email": "galopintitouan@gmail.com" + } + ], + "description": "Sanitize untrustworthy HTML user input", + "support": { + "issues": "https://github.com/tgalopin/html-sanitizer/issues", + "source": "https://github.com/tgalopin/html-sanitizer/tree/1.5.0" + }, + "abandoned": "symfony/html-sanitizer", + "time": "2021-09-14T08:27:50+00:00" + }, { "name": "tijsverkoyen/css-to-inline-styles", "version": "v2.2.7", @@ -8208,77 +8544,6 @@ ], "time": "2024-02-09T16:08:40+00:00" }, - { - "name": "symfony/yaml", - "version": "v7.0.3", - "source": { - "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "2d4fca631c00700597e9442a0b2451ce234513d3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/2d4fca631c00700597e9442a0b2451ce234513d3", - "reference": "2d4fca631c00700597e9442a0b2451ce234513d3", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/polyfill-ctype": "^1.8" - }, - "conflict": { - "symfony/console": "<6.4" - }, - "require-dev": { - "symfony/console": "^6.4|^7.0" - }, - "bin": [ - "Resources/bin/yaml-lint" - ], - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Yaml\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Loads and dumps YAML files", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/yaml/tree/v7.0.3" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-01-23T15:02:46+00:00" - }, { "name": "theseer/tokenizer", "version": "1.2.2", diff --git a/resources/views/back/start.blade.php b/resources/views/back/start.blade.php index b554012..d28f800 100644 --- a/resources/views/back/start.blade.php +++ b/resources/views/back/start.blade.php @@ -4,6 +4,7 @@ @section('main-content') @if($status) + @include('includes.index') @else @include('forms.login') @endif diff --git a/resources/views/includes/index.blade.php b/resources/views/includes/index.blade.php new file mode 100644 index 0000000..a015918 --- /dev/null +++ b/resources/views/includes/index.blade.php @@ -0,0 +1,37 @@ +
+
+

Recent

+
+
+
+
+ @if($result['entryCount'] != 0) + @foreach($result['pages'] as $page) + @php + $type = ''; + $file = ''; + if(isset($page['media'][0]['type'])) + { + $type = $page['media'][0]['type']; + } + if(isset($page['media'][0]['file'])) + { + $file = $page['media'][0]['file']; + } + @endphp + @if($type =='mp4') + + @include('includes.recent-meta') + + + @else + + @include('includes.recent-meta') + + @endif + @endforeach + @endif +
diff --git a/resources/views/includes/recent-meta.blade.php b/resources/views/includes/recent-meta.blade.php new file mode 100644 index 0000000..3b9b58f --- /dev/null +++ b/resources/views/includes/recent-meta.blade.php @@ -0,0 +1,46 @@ +@php + +if($page['menu'] == 'true') +{ + $menu = 'true'; +}else{ + $menu = 'false'; +} + +if($page['published'] == 'true') +{ + $published = 'true'; +}else{ + $published = 'false'; +} + +if($page['featured'] == 'true') +{ + $featured = 'true'; +}else{ + $featured = 'false'; +} + +@endphp + +