Skip to content

Commit

Permalink
Started refactoring in blog model classes.
Browse files Browse the repository at this point in the history
  • Loading branch information
parpalak committed May 10, 2024
1 parent c64dfe2 commit cbc6cc2
Show file tree
Hide file tree
Showing 15 changed files with 432 additions and 282 deletions.
86 changes: 86 additions & 0 deletions _extensions/s2_blog/BlogUrlBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?php
/**
* @copyright 2024 Roman Parpalak
* @license MIT
* @package S2
*/

declare(strict_types=1);

namespace s2_extensions\s2_blog;

use S2\Cms\Model\UrlBuilder;

class BlogUrlBuilder
{
protected ?string $blogPath = null;
protected ?string $blogTagsPath = null;

public function __construct(
private readonly UrlBuilder $urlBuilder,
private readonly string $tagsUrl,
private readonly string $favoriteUrl,
private readonly string $blogUrl,
) {
}

public function main(): string
{
return $this->blogPath ?? $this->blogPath = $this->urlBuilder->link(str_replace(urlencode('/'), '/', urlencode($this->blogUrl)) . '/');
}

public function favorite(): string
{
return $this->main() . urlencode($this->favoriteUrl) . '/';
}

public function tags(): string
{
return $this->blogTagsPath ?? $this->blogTagsPath = $this->main() . urlencode($this->tagsUrl) . '/';
}

public function tag(string $tagUrl): string
{
return $this->tags() . urlencode($tagUrl) . '/';
}

public function year(int $year): string
{
return $this->main() . $year . '/';
}

public function month(int $year, int $month): string
{
return $this->main() . $year . '/' . self::extendNumber($month) . '/';
}

public function monthFromTimestamp(int $timestamp): string
{
return $this->main() . date('Y/m/', $timestamp);
}

public function day(int $year, int $month, int $day): string
{
return $this->main() . $year . '/' . self::extendNumber($month) . '/' . self::extendNumber($day) . '/';
}

public function post(int $year, int $month, int $day, string $url): string
{
return $this->main() . $year . '/' . self::extendNumber($month) . '/' . self::extendNumber($day) . '/' . urlencode($url);
}

public function postFromTimestamp(int $create_time, string $url): string
{
return $this->main() . date('Y/m/d/', $create_time) . urlencode($url);
}

public function blogIsOnTheSiteRoot(): bool
{
return $this->blogUrl === '';
}

private static function extendNumber(int $month): string
{
return str_pad((string)$month, 2, '0', STR_PAD_LEFT);
}
}
157 changes: 157 additions & 0 deletions _extensions/s2_blog/CalendarBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
<?php
/**
* @copyright 2024 Roman Parpalak
* @license MIT
* @package S2
*/

declare(strict_types=1);

namespace s2_extensions\s2_blog;

use S2\Cms\Pdo\DbLayer;

readonly class CalendarBuilder
{
public function __construct(
private DbLayer $dbLayer,
private BlogUrlBuilder $blogUrlBuilder,
private int $startYear,
) {
}


/**
* @param ?int $day 0 for skipping highlight, null for skipping header
* @throws \S2\Cms\Pdo\DbLayerException
*/
public function calendar(?int $year = null, ?int $month = null, ?int $day = 0, string $url = '', array $dayUrls = null): string
{
if ($year === null) {
$year = (int)date('Y');
}

if ($month === null) {
$month = (int)date('m');
}

$startTime = mktime(0, 0, 0, $month, 1, $year);
$endTime = mktime(0, 0, 0, $month + 1, 1, $year);

// Dealing with week days
$currentColumnIndex = (int)date('w', $startTime);
if (\Lang::get('Sunday starts week', 's2_blog') !== '1') {
--$currentColumnIndex;
if ($currentColumnIndex === -1) {
$currentColumnIndex = 6;
}
}

// How many days have the month?
$daysInThisMonth = (int)date('j', mktime(0, 0, 0, $month + 1, 0, $year)); // day = 0

// Flags for the days when posts have been written
if ($dayUrls === null) {
$dayUrls = [];
$query = [
'SELECT' => 'create_time, url',
'FROM' => 's2_blog_posts',
'WHERE' => 'create_time < ' . $endTime . ' AND create_time >= ' . $startTime . ' AND published = 1'
];
$result = $this->dbLayer->buildAndQuery($query);
while ($row = $this->dbLayer->fetchRow($result)) {
$dayUrls[1 + (int)(($row[0] - $startTime) / 86400)][] = $row[1];
}
}

// Header
$monthName = \Lang::month($month);
if ($day === null) {
// One of 12 year tables
if ($startTime < time()) {
$monthName = '<a href="' . $this->blogUrlBuilder->monthFromTimestamp($startTime) . '">' . $monthName . '</a>';
}
$header = '<tr class="nav"><th colspan="7">' . $monthName . '</th></tr>';
} else {
if ($day !== 0) {
$monthName = '<a href="' . $this->blogUrlBuilder->monthFromTimestamp($startTime) . '">' . $monthName . '</a>';
}

// Links in the header
$next_month = $endTime < time() ? '<a class="nav_mon" href="' . $this->blogUrlBuilder->monthFromTimestamp($endTime) . '" title="' . \Lang::month(date('m', $endTime)) . date(', Y', $endTime) . '">&rarr;</a>' : '&rarr;';

$prevTime = mktime(0, 0, 0, $month - 1, 1, $year);
$prevMonth = $prevTime >= mktime(0, 0, 0, 1, 1, $this->startYear) ? '<a class="nav_mon" href="' . $this->blogUrlBuilder->monthFromTimestamp($prevTime) . '" title="' . \Lang::month(date('m', $prevTime)) . date(', Y', $prevTime) . '">&larr;</a>' : '&larr;';

$header = '<tr class="nav"><th>' . $prevMonth . '</th><th align="center" colspan="5">'
. $monthName . ', <a href="' . $this->blogUrlBuilder->year($year) . '">' . $year . '</a></th><th>' . $next_month . '</th></tr>';
}

// Titles
$output = '<table class="cal">' . $header . '<tr>';

// Empty cells before
for ($i = 0; $i < $currentColumnIndex; $i++) {
$output .= '<td' . ($this->isWeekend($i) ? ' class="sun"' : '') . '></td>';
}

// Days
for ($currentDayInMonth = 1; $currentDayInMonth <= $daysInThisMonth; $currentDayInMonth++) {
$currentColumnIndex++;
$cellContent = $currentDayInMonth; // Simple text content
if (isset($dayUrls[$currentDayInMonth])) {
if (\count($dayUrls[$currentDayInMonth]) !== 1 && ($currentDayInMonth !== $day || $url !== '')) {
// Several posts, link to the day page (if this is not the day selected)
$cellContent = '<a href="' . $this->blogUrlBuilder->day($year, $month, $currentDayInMonth) . '">' . $currentDayInMonth . '</a>';
}
if (\count($dayUrls[$currentDayInMonth]) === 1 && ($currentDayInMonth !== $day || $url === '')) {
// One post, link to it (if this is not the post selected)
$cellContent = '<a href="' . $this->blogUrlBuilder->post($year, $month, $currentDayInMonth, $dayUrls[$currentDayInMonth][0]) . '">' . $currentDayInMonth . '</a>';
}
}

$classes = [];
if ($currentDayInMonth === $day) {
// Current day
$classes[] = 'cur';
}

if ($this->isWeekend($currentColumnIndex)) {
// Weekend
$classes[] = 'sun';
}

$output .= '<td' . (!empty($classes) ? ' class="' . implode(' ', $classes) . '"' : '') . '>'
. $cellContent
. '</td>';

if (!($currentColumnIndex % 7) && ($currentDayInMonth !== $daysInThisMonth)) {
$output .= '</tr><tr>';
}
}

// Empty cells in the end
while ($currentColumnIndex % 7) {
$currentColumnIndex++;
$output .= '<td' . ($this->isWeekend($currentColumnIndex) ? ' class="sun"' : '') . '></td>';
}

$output .= '</tr></table>';
return $output;
}


private function isWeekend(int $n): bool
{
if ($n % 7 === 0) {
return true;
}
if ($n % 7 === 6 && \Lang::get('Sunday starts week', 's2_blog') != '1') {
return true;
}
if ($n % 7 === 1 && \Lang::get('Sunday starts week', 's2_blog') == '1') {
return true;
}
return false;
}
}
26 changes: 12 additions & 14 deletions _extensions/s2_blog/Controller/BlogController.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,32 +17,29 @@
use S2\Cms\Template\HtmlTemplate;
use S2\Cms\Template\HtmlTemplateProvider;
use S2\Cms\Template\Viewer;
use s2_extensions\s2_blog\BlogUrlBuilder;
use s2_extensions\s2_blog\CalendarBuilder;
use s2_extensions\s2_blog\Lib;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

abstract class BlogController implements ControllerInterface
{
protected string $template_id = 'blog.php';
protected string $blogPath;
protected string $blogTagsPath;

abstract public function body(Request $request, HtmlTemplate $template): ?Response;

public function __construct(
protected DbLayer $dbLayer,
protected CalendarBuilder $calendarBuilder,
protected BlogUrlBuilder $blogUrlBuilder,
protected ArticleProvider $articleProvider,
protected UrlBuilder $urlBuilder,
protected HtmlTemplateProvider $templateProvider,
protected Viewer $viewer,
protected string $tagsUrl,
protected string $blogUrl, // S2_BLOG_URL
protected string $blogTitle, // S2_BLOG_TITLE
)
{
$this->blogPath = $this->urlBuilder->link(str_replace(urlencode('/'), '/', urlencode($this->blogUrl)) . '/'); // S2_BLOG_PATH
$this->blogTagsPath = $this->blogPath . urlencode($this->tagsUrl) . '/'; // S2_BLOG_TAGS_PATH

Lang::load('s2_blog', function () {
if (file_exists(__DIR__ . '/../lang/' . S2_LANGUAGE . '.php'))
return require __DIR__ . '/../lang/' . S2_LANGUAGE . '.php';
Expand All @@ -61,7 +58,7 @@ public function handle(Request $request): Response
->putInPlaceholder('rss_link', [sprintf(
'<link rel="alternate" type="application/rss+xml" title="%s" href="%s" />',
s2_htmlencode(Lang::get('RSS link title', 's2_blog')),
$this->urlBuilder->link(str_replace(urlencode('/'), '/', urlencode($this->blogUrl)) . '/rss.xml')
$this->blogUrlBuilder->main() . 'rss.xml'
)])
;

Expand Down Expand Up @@ -134,7 +131,7 @@ public function getPosts(array $additionalQueryParts, bool $sortAsc = true, stri
$output = '';
foreach ($ids as $id) {
$post = &$posts[$id];
$link = $this->blogPath . date('Y/m/d/', $post['create_time']) . urlencode($post['url']);
$link = $this->blogUrlBuilder->postFromTimestamp((int)$post['create_time'], $post['url']);
$post['link'] = $link;
$post['title_link'] = $link;
$post['time'] = s2_date_time($post['create_time']);
Expand Down Expand Up @@ -172,8 +169,8 @@ public function blog_navigation(Request $request)

// Last posts on the blog main page
$s2_blog_navigation['last'] = array(
'title' => sprintf(Lang::get('Nav last', 's2_blog'), S2_MAX_ITEMS ? S2_MAX_ITEMS : 10),
'link' => S2_BLOG_PATH,
'title' => sprintf(Lang::get('Nav last', 's2_blog'), S2_MAX_ITEMS ?: 10),
'link' => $this->blogUrlBuilder->main(),
);

// Check for favorite posts
Expand All @@ -186,16 +183,17 @@ public function blog_navigation(Request $request)
($hook = s2_hook('fn_s2_blog_navigation_pre_is_favorite_qr')) ? eval($hook) : null;
$result = $this->dbLayer->buildAndQuery($query);

if ($this->dbLayer->fetchRow($result))
if ($this->dbLayer->fetchRow($result)) {
$s2_blog_navigation['favorite'] = array(
'title' => Lang::get('Nav favorite', 's2_blog'),
'link' => S2_BLOG_PATH . urlencode(S2_FAVORITE_URL) . '/',
'link' => $this->blogUrlBuilder->favorite(),
);
}

// Fetch important tags
$s2_blog_navigation['tags_header'] = array(
'title' => Lang::get('Nav tags', 's2_blog'),
'link' => S2_BLOG_TAGS_PATH,
'link' => $this->blogUrlBuilder->tags(),
);

$query = array(
Expand Down
7 changes: 4 additions & 3 deletions _extensions/s2_blog/Controller/BlogRss.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,17 @@
use Lang;
use S2\Cms\Controller\Rss;
use S2\Cms\Template\Viewer;
use s2_extensions\s2_blog\BlogUrlBuilder;
use s2_extensions\s2_blog\Lib;

readonly class BlogRss extends Rss
{
public function __construct(
protected BlogUrlBuilder $blogUrlBuilder,
protected Viewer $viewer,
protected string $baseUrl,
protected string $webmaster,
protected string $siteName,
protected string $blogUrl,
protected string $blogTitle,
)
{
Expand Down Expand Up @@ -53,7 +54,7 @@ protected function content(): array
], 's2_blog')),
'time' => $post['create_time'],
'modify_time' => $post['modify_time'],
'rel_path' => str_replace(urlencode('/'), '/', urlencode($this->blogUrl)) . date('/Y/m/d/', $post['create_time']) . urlencode($post['url']),
'rel_path' => $this->blogUrlBuilder->postFromTimestamp($post['create_time'], $post['url']),
'author' => $post['author'],
];
}
Expand All @@ -68,7 +69,7 @@ protected function title(): string

protected function link(): string
{
return str_replace(urlencode('/'), '/', urlencode($this->blogUrl)) . '/';
return $this->blogUrlBuilder->main();
}

protected function description(): string
Expand Down
Loading

0 comments on commit cbc6cc2

Please sign in to comment.