Add Project-Pro Blog module with initial SQL setup, CSS styles, and template files

- Created SQL installation scripts for categories and posts tables.
- Added uninstall scripts to drop the created tables.
- Introduced CSS styles for blog layout, including responsive design for posts and categories.
- Implemented PHP redirection in index files to prevent direct access.
- Developed Smarty templates for blog category tree, post list, and individual post details.
- Ensured proper caching headers in PHP files to enhance performance.
This commit is contained in:
2026-03-03 15:24:51 +01:00
parent 8d14e5d95c
commit 5f93428041
35 changed files with 3128 additions and 2 deletions

View File

@@ -0,0 +1,269 @@
<?php
/**
* Project-Pro Blog
*
* @author Project-Pro <https://www.project-pro.pl>
* @copyright 2024 Project-Pro
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
*/
if (!defined('_PS_VERSION_')) {
exit;
}
require_once __DIR__ . '/classes/BlogCategory.php';
require_once __DIR__ . '/classes/BlogPost.php';
class Projectproblog extends Module
{
const POSTS_PER_PAGE = 9;
public function __construct()
{
$this->name = 'projectproblog';
$this->tab = 'content_management';
$this->version = '1.0.0';
$this->author = 'Project-Pro';
$this->author_uri = 'https://www.project-pro.pl';
$this->need_instance = 0;
$this->bootstrap = true;
$this->ps_versions_compliancy = [
'min' => '1.7.0.0',
'max' => _PS_VERSION_,
];
parent::__construct();
$this->displayName = $this->l('Project-Pro Blog');
$this->description = $this->l('Moduł bloga z obsługą kategorii, podkategorii i wpisów wielojęzycznych.');
}
/* ------------------------------------------------------------------ */
/* INSTALL / UNINSTALL */
/* ------------------------------------------------------------------ */
public function install()
{
$this->createImgDir();
return parent::install()
&& $this->installSql()
&& $this->installTabs()
&& $this->registerHook('moduleRoutes');
}
protected function createImgDir()
{
$dir = _PS_MODULE_DIR_ . 'projectproblog/views/img/posts/';
if (!is_dir($dir)) {
@mkdir($dir, 0755, true);
}
}
public function uninstall()
{
return $this->uninstallTabs()
&& $this->uninstallSql()
&& parent::uninstall();
}
/* ------------------------------------------------------------------ */
/* SQL */
/* ------------------------------------------------------------------ */
protected function installSql()
{
$sql = file_get_contents(__DIR__ . '/sql/install.sql');
$sql = str_replace('PREFIX_', _DB_PREFIX_, $sql);
foreach (array_filter(array_map('trim', explode(';', $sql))) as $query) {
if (!Db::getInstance()->execute($query)) {
return false;
}
}
return true;
}
protected function uninstallSql()
{
$sql = file_get_contents(__DIR__ . '/sql/uninstall.sql');
$sql = str_replace('PREFIX_', _DB_PREFIX_, $sql);
foreach (array_filter(array_map('trim', explode(';', $sql))) as $query) {
if (!Db::getInstance()->execute($query)) {
return false;
}
}
return true;
}
/* ------------------------------------------------------------------ */
/* TABS (menu admina) */
/* ------------------------------------------------------------------ */
protected function installTabs()
{
// Szukamy odpowiedniego rodzica w menu BO — fallback do 0 (główne menu)
$parentCandidates = ['AdminParentContent', 'AdminParentCmsContent', 'AdminParentThemes'];
$idMenuParent = 0;
foreach ($parentCandidates as $candidate) {
$found = (int) Tab::getIdFromClassName($candidate);
if ($found > 0) {
$idMenuParent = $found;
break;
}
}
// Tab-rodzic (bez kontrolera — tylko nagłówek w menu)
$idParent = $this->addTab(
'AdminProjectproBlog',
'Project-Pro Blog',
$idMenuParent,
''
);
if (!$idParent) {
return false;
}
// Podmenu: Kategorie
if (!$this->addTab(
'AdminProjectproBlogCategories',
'Kategorie bloga',
$idParent,
$this->name
)) {
return false;
}
// Podmenu: Wpisy
if (!$this->addTab(
'AdminProjectproBlogPosts',
'Wpisy bloga',
$idParent,
$this->name
)) {
return false;
}
return true;
}
protected function addTab($className, $name, $idParent, $module)
{
$tab = new Tab();
$tab->active = 1;
$tab->class_name = $className;
$tab->id_parent = (int) $idParent;
$tab->module = $module;
$tab->name = [];
foreach (Language::getLanguages(false) as $lang) {
$tab->name[$lang['id_lang']] = $name;
}
if (!$tab->add()) {
return false;
}
return (int) $tab->id;
}
protected function uninstallTabs()
{
$tabs = [
'AdminProjectproBlogCategories',
'AdminProjectproBlogPosts',
'AdminProjectproBlog',
];
foreach ($tabs as $className) {
$id = (int) Tab::getIdFromClassName($className);
if ($id) {
$tab = new Tab($id);
$tab->delete();
}
}
return true;
}
/* ------------------------------------------------------------------ */
/* ROUTING */
/* ------------------------------------------------------------------ */
public function hookModuleRoutes()
{
return [
'module-projectproblog-list' => [
'controller' => 'list',
'rule' => 'blog',
'keywords' => [],
'params' => [
'fc' => 'module',
'module' => $this->name,
],
],
'module-projectproblog-category' => [
'controller' => 'list',
'rule' => 'blog/kategoria/{slug}',
'keywords' => [
'slug' => [
'regexp' => '[_a-zA-Z0-9\-]+',
'param' => 'slug',
],
],
'params' => [
'fc' => 'module',
'module' => $this->name,
],
],
'module-projectproblog-post' => [
'controller' => 'post',
'rule' => 'blog/wpis/{slug}',
'keywords' => [
'slug' => [
'regexp' => '[_a-zA-Z0-9\-]+',
'param' => 'slug',
],
],
'params' => [
'fc' => 'module',
'module' => $this->name,
],
],
];
}
/* ------------------------------------------------------------------ */
/* HELPERS — generowanie linków */
/* ------------------------------------------------------------------ */
public static function getBlogUrl($idLang = null)
{
return Context::getContext()->link->getModuleLink('projectproblog', 'list', [], true, $idLang);
}
public static function getCategoryUrl($linkRewrite, $idLang = null)
{
return Context::getContext()->link->getModuleLink(
'projectproblog',
'list',
['slug' => $linkRewrite],
true,
$idLang
);
}
public static function getPostUrl($linkRewrite, $idLang = null)
{
return Context::getContext()->link->getModuleLink(
'projectproblog',
'post',
['slug' => $linkRewrite],
true,
$idLang
);
}
}