├── .gitignore ├── 403.php ├── 404.php ├── admin ├── auth.php ├── category │ ├── delete.php │ ├── index.php │ ├── insert.php │ └── update.php ├── database.php ├── index.php ├── page │ ├── delete.php │ ├── index.php │ ├── insert.php │ ├── search.php │ └── update.php ├── post │ ├── delete.php │ ├── index.php │ ├── insert.php │ ├── search.php │ └── update.php └── user │ ├── delete.php │ ├── index.php │ ├── insert.php │ └── update.php ├── core ├── application.php ├── configuration-example.php ├── db │ ├── database.sql │ └── migrations │ │ ├── 1.sql │ │ ├── 2.sql │ │ ├── 3.sql │ │ ├── 4.sql │ │ ├── 5.sql │ │ └── 6.sql ├── functions.php ├── include │ ├── category │ │ ├── list.php │ │ └── main.php │ ├── feed │ │ └── main.php │ ├── home.php │ ├── page │ │ ├── list.php │ │ └── main.php │ ├── post │ │ ├── list.php │ │ └── main.php │ ├── search │ │ └── main.php │ └── user │ │ ├── list.php │ │ └── main.php ├── language │ ├── de.php │ └── en.php ├── migrations.php ├── namespace │ ├── Application.php │ ├── Database.php │ ├── Factory.php │ ├── FactoryInterface.php │ ├── HTTP.php │ ├── Language.php │ ├── Migrator.php │ ├── ORM │ │ ├── Entities │ │ │ ├── Category.php │ │ │ ├── Page.php │ │ │ ├── Post.php │ │ │ └── User.php │ │ ├── Entity.php │ │ ├── EntityInterface.php │ │ ├── Repositories │ │ │ ├── CategoryRepository.php │ │ │ ├── PageRepository.php │ │ │ ├── PostRepository.php │ │ │ └── UserRepository.php │ │ ├── Repository.php │ │ └── RepositorySearch.php │ ├── Parsedown.patch │ ├── Parsedown.php │ ├── Parsers │ │ ├── ArgumentParser.php │ │ ├── EmoticonParser.php │ │ ├── FunctionParser.php │ │ ├── MarkdownParser.php │ │ └── ParserInterface.php │ ├── Router.php │ └── Template │ │ ├── Exception.php │ │ ├── Factory.php │ │ └── Template.php ├── script │ └── convert_content_tags.php ├── ws-apache.conf └── ws-nginx.conf ├── index.php ├── license.md ├── readme.md ├── static └── image │ └── content │ └── computer-guy-public-domain.svg └── theme ├── admin ├── html │ ├── 403.php │ ├── 404.php │ ├── auth.php │ ├── category │ │ ├── delete.php │ │ ├── form.php │ │ ├── index.php │ │ ├── insert.php │ │ ├── item.php │ │ └── update.php │ ├── database.php │ ├── home.php │ ├── main.php │ ├── migration.php │ ├── page │ │ ├── delete.php │ │ ├── form.php │ │ ├── index.php │ │ ├── insert.php │ │ ├── item.php │ │ ├── search.php │ │ └── update.php │ ├── pagination.php │ ├── post │ │ ├── delete.php │ │ ├── form.php │ │ ├── index.php │ │ ├── insert.php │ │ ├── item.php │ │ ├── search.php │ │ └── update.php │ └── user │ │ ├── delete.php │ │ ├── form.php │ │ ├── index.php │ │ ├── insert.php │ │ ├── item.php │ │ └── update.php ├── lang │ ├── de.php │ └── en.php └── static │ ├── css │ ├── bright.css │ ├── bright.scss │ ├── dark.css │ ├── dark.scss │ └── import │ │ ├── _fontello.scss │ │ ├── _fonts.scss │ │ ├── _responsive.scss │ │ ├── _styles.scss │ │ └── _variables.scss │ ├── font │ ├── fontello.json │ ├── fontello.woff2 │ ├── kadwa-n-400.woff2 │ ├── ruda-n-400.woff2 │ └── ruda-n-700.woff2 │ ├── icon-public-domain.svg │ ├── img │ ├── noise-bright.png │ └── noise-dark.png │ └── main.js └── default ├── html ├── 403.php ├── 404.php ├── category │ ├── item.php │ ├── list.php │ └── main.php ├── feed │ ├── item.php │ └── main.php ├── home.php ├── main.php ├── page │ ├── item.php │ ├── list.php │ └── main.php ├── pagination.php ├── post │ ├── item.php │ ├── list.php │ └── main.php ├── search │ ├── main.php │ └── result.php └── user │ ├── item.php │ ├── list.php │ └── main.php ├── lang ├── de.php └── en.php └── static ├── css ├── import │ ├── _fontello.scss │ ├── _fonts.scss │ └── _responsive.scss ├── main.css └── main.scss ├── font ├── fontello.json ├── fontello.woff2 ├── ruda-n-400.woff2 └── ruda-n-700.woff2 ├── logo.png └── main.js /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea/ 2 | /.htaccess 3 | /static/ 4 | *.js.map 5 | *.css.map 6 | *.sass-cache 7 | /core/configuration.php 8 | -------------------------------------------------------------------------------- /403.php: -------------------------------------------------------------------------------- 1 | Application::getSecurityToken()], ['action' => 'logout'])) { 20 | session_destroy(); 21 | HTTP::redirect(Application::getAdminURL('auth.php')); 22 | } 23 | 24 | HTTP::redirect(Application::getAdminURL()); 25 | } 26 | 27 | #=============================================================================== 28 | # IF: Login action 29 | #=============================================================================== 30 | if(HTTP::issetPOST('username', 'password')) { 31 | if(HTTP::issetPOST(['token' => Application::getSecurityToken()])) { 32 | $UserRepository = Application::getRepository('User'); 33 | 34 | if($User = $UserRepository->findBy('username', HTTP::POST('username'))) { 35 | if(password_verify(HTTP::POST('password'), $User->get('password'))) { 36 | $_SESSION['USER_ID'] = $User->getID(); 37 | HTTP::redirect(Application::getAdminURL()); 38 | } else { 39 | $messages[] = $Language->text('authentication_failure'); 40 | } 41 | } else { 42 | $fake_hash = '$2y$10$xpnwDU2HumOgGQhVpMOP9uataEF82YXizniFhSUhYjUiXF8aoDk0C'; 43 | $fake_pass = HTTP::POST('password'); 44 | 45 | password_verify($fake_pass, $fake_hash); 46 | 47 | $messages[] = $Language->text('authentication_failure'); 48 | } 49 | } else { 50 | $messages[] = $Language->text('error_security_csrf'); 51 | } 52 | } 53 | 54 | #=============================================================================== 55 | # Build document 56 | #=============================================================================== 57 | $AuthTemplate = Template\Factory::build('auth'); 58 | $AuthTemplate->set('FORM', [ 59 | 'INFO' => $messages ?? [], 60 | 'DATA' => [ 61 | 'USERNAME' => HTTP::POST('username'), 62 | 'PASSWORD' => HTTP::POST('password'), 63 | ], 64 | 'TOKEN' => Application::getSecurityToken() 65 | ]); 66 | 67 | $MainTemplate = Template\Factory::build('main'); 68 | $MainTemplate->set('NAME', 'Authentication'); 69 | $MainTemplate->set('HTML', $AuthTemplate); 70 | echo $MainTemplate; 71 | -------------------------------------------------------------------------------- /admin/category/delete.php: -------------------------------------------------------------------------------- 1 | find(HTTP::GET('id'))) { 22 | Application::error404(); 23 | } 24 | 25 | #=============================================================================== 26 | # Check for delete request 27 | #=============================================================================== 28 | if(HTTP::issetPOST('delete')) { 29 | if(HTTP::issetPOST(['token' => Application::getSecurityToken()])) { 30 | try { 31 | $CategoryRepository->delete($Category); 32 | HTTP::redirect(Application::getAdminURL('category/')); 33 | } catch(PDOException $Exception) { 34 | $messages[] = $Exception->getMessage(); 35 | } 36 | } else { 37 | $messages[] = $Language->text('error_security_csrf'); 38 | } 39 | } 40 | 41 | #=============================================================================== 42 | # Build document 43 | #=============================================================================== 44 | $FormTemplate = Template\Factory::build('category/form'); 45 | $FormTemplate->set('HTML', parseEntityContent($Category)); 46 | $FormTemplate->set('FORM', [ 47 | 'TYPE' => 'DELETE', 48 | 'INFO' => $messages ?? [], 49 | 'DATA' => array_change_key_case($Category->getAll(), CASE_UPPER), 50 | 'TOKEN' => Application::getSecurityToken() 51 | ]); 52 | 53 | $DeleteTemplate = Template\Factory::build('category/delete'); 54 | $DeleteTemplate->set('HTML', $FormTemplate); 55 | 56 | $MainTemplate = Template\Factory::build('main'); 57 | $MainTemplate->set('NAME', $Language->text('title_category_delete')); 58 | $MainTemplate->set('HTML', $DeleteTemplate); 59 | echo $MainTemplate; 60 | -------------------------------------------------------------------------------- /admin/category/index.php: -------------------------------------------------------------------------------- 1 | getCount(); 24 | $lastSite = ceil($count / $site_size); 25 | 26 | $currentSite = HTTP::GET('site') ?? 1; 27 | $currentSite = intval($currentSite); 28 | 29 | #=============================================================================== 30 | # Redirect to category create form if no category exists 31 | #=============================================================================== 32 | if($count === 0) { 33 | HTTP::redirect(Application::getAdminURL('category/insert.php')); 34 | } 35 | 36 | if($currentSite < 1 or ($currentSite > $lastSite and $lastSite > 0)) { 37 | Application::error404(); 38 | } 39 | 40 | #=============================================================================== 41 | # Get paginated category list 42 | #=============================================================================== 43 | $categories = $CategoryRepository->getPaginatedTree( 44 | $site_size, ($currentSite-1) * $site_size); 45 | 46 | foreach($categories as $Category) { 47 | $templates[] = generateCategoryItemTemplate($Category, true); 48 | } 49 | 50 | #=============================================================================== 51 | # Build document 52 | #=============================================================================== 53 | $ListTemplate = Template\Factory::build('category/index'); 54 | $ListTemplate->set('LIST', [ 55 | 'CATEGORIES' => $templates ?? [] 56 | ]); 57 | 58 | $ListTemplate->set('PAGINATION', [ 59 | 'THIS' => $currentSite, 60 | 'LAST' => $lastSite, 61 | 'HTML' => createPaginationTemplate( 62 | $currentSite, $lastSite, Application::getAdminURL('category/') 63 | ) 64 | ]); 65 | 66 | $MainTemplate = Template\Factory::build('main'); 67 | $MainTemplate->set('NAME', $Language->text('title_category_overview', $currentSite)); 68 | $MainTemplate->set('HTML', $ListTemplate); 69 | echo $MainTemplate; 70 | -------------------------------------------------------------------------------- /admin/category/insert.php: -------------------------------------------------------------------------------- 1 | set('parent', HTTP::POST('parent') ?: null); 28 | $Category->set('slug', HTTP::POST('slug') ?: generateSlug(HTTP::POST('name'))); 29 | $Category->set('name', HTTP::POST('name') ?: null); 30 | $Category->set('body', HTTP::POST('body') ?: null); 31 | $Category->set('argv', HTTP::POST('argv') ?: null); 32 | $Category->set('time_insert', HTTP::POST('time_insert') ?: date('Y-m-d H:i:s')); 33 | $Category->set('time_update', HTTP::POST('time_update') ?: date('Y-m-d H:i:s')); 34 | 35 | if(HTTP::issetPOST(['token' => Application::getSecurityToken()])) { 36 | try { 37 | $CategoryRepository->insert($Category); 38 | HTTP::redirect(Application::getAdminURL('category/')); 39 | } catch(PDOException $Exception) { 40 | $messages[] = $Exception->getMessage(); 41 | } 42 | } 43 | 44 | else { 45 | $messages[] = $Language->text('error_security_csrf'); 46 | } 47 | } 48 | 49 | #=============================================================================== 50 | # Generate category list 51 | #=============================================================================== 52 | foreach($CategoryRepository->getAll([], 'name ASC') as $_Category) { 53 | $categoryList[] = [ 54 | 'ID' => $_Category->getID(), 55 | 'NAME' => $_Category->get('name'), 56 | 'PARENT' => $_Category->get('parent'), 57 | ]; 58 | } 59 | 60 | #=============================================================================== 61 | # Build document 62 | #=============================================================================== 63 | $FormTemplate = Template\Factory::build('category/form'); 64 | $FormTemplate->set('FORM', [ 65 | 'TYPE' => 'INSERT', 66 | 'INFO' => $messages ?? [], 67 | 'DATA' => array_change_key_case($Category->getAll(), CASE_UPPER), 68 | 'CATEGORY_LIST' => $categoryList ?? [], 69 | 'CATEGORY_TREE' => generateCategoryDataTree($categoryList ?? []), 70 | 'TOKEN' => Application::getSecurityToken() 71 | ]); 72 | 73 | $InsertTemplate = Template\Factory::build('category/insert'); 74 | $InsertTemplate->set('HTML', $FormTemplate); 75 | 76 | $MainTemplate = Template\Factory::build('main'); 77 | $MainTemplate->set('NAME', $Language->text('title_category_insert')); 78 | $MainTemplate->set('HTML', $InsertTemplate); 79 | echo $MainTemplate; 80 | -------------------------------------------------------------------------------- /admin/category/update.php: -------------------------------------------------------------------------------- 1 | find(HTTP::GET('id'))) { 22 | Application::error404(); 23 | } 24 | 25 | #=============================================================================== 26 | # Check for update request 27 | #=============================================================================== 28 | if(HTTP::issetPOST('update')) { 29 | $Category->set('slug', HTTP::POST('slug') ?: generateSlug(HTTP::POST('name'))); 30 | $Category->set('name', HTTP::POST('name') ?: null); 31 | $Category->set('body', HTTP::POST('body') ?: null); 32 | $Category->set('argv', HTTP::POST('argv') ?: null); 33 | $Category->set('time_insert', HTTP::POST('time_insert') ?: date('Y-m-d H:i:s')); 34 | $Category->set('time_update', HTTP::POST('time_update') ?: date('Y-m-d H:i:s')); 35 | 36 | # Modify parent field only if it is not a self-reference 37 | if(HTTP::POST('parent') != $Category->getID()) { 38 | $Category->set('parent', HTTP::POST('parent') ?: null); 39 | } 40 | 41 | if(HTTP::issetPOST(['token' => Application::getSecurityToken()])) { 42 | try { 43 | $CategoryRepository->update($Category); 44 | } catch(PDOException $Exception) { 45 | $messages[] = $Exception->getMessage(); 46 | } 47 | } 48 | 49 | else { 50 | $messages[] = $Language->text('error_security_csrf'); 51 | } 52 | } 53 | 54 | #=============================================================================== 55 | # Generate category list 56 | #=============================================================================== 57 | foreach($CategoryRepository->getAll([], 'name ASC') as $_Category) { 58 | $categoryList[] = [ 59 | 'ID' => $_Category->getID(), 60 | 'NAME' => $_Category->get('name'), 61 | 'PARENT' => $_Category->get('parent'), 62 | ]; 63 | } 64 | 65 | #=============================================================================== 66 | # Build document 67 | #=============================================================================== 68 | $FormTemplate = Template\Factory::build('category/form'); 69 | $FormTemplate->set('FORM', [ 70 | 'TYPE' => 'UPDATE', 71 | 'INFO' => $messages ?? [], 72 | 'DATA' => array_change_key_case($Category->getAll(), CASE_UPPER), 73 | 'CATEGORY_LIST' => $categoryList ?? [], 74 | 'CATEGORY_TREE' => generateCategoryDataTree($categoryList ?? []), 75 | 'TOKEN' => Application::getSecurityToken() 76 | ]); 77 | 78 | $UpdateTemplate = Template\Factory::build('category/update'); 79 | $UpdateTemplate->set('CATEGORY', generateItemTemplateData($Category)); 80 | $UpdateTemplate->set('HTML', $FormTemplate); 81 | 82 | $MainTemplate = Template\Factory::build('main'); 83 | $MainTemplate->set('NAME', $Language->text('title_category_update')); 84 | $MainTemplate->set('HTML', $UpdateTemplate); 85 | echo $MainTemplate; 86 | -------------------------------------------------------------------------------- /admin/database.php: -------------------------------------------------------------------------------- 1 | Application::getSecurityToken()])) { 18 | try { 19 | $Statement = $Database->query(HTTP::POST('command')); 20 | 21 | do { 22 | $result[] = print_r($Statement->fetchAll(), true); 23 | } while($Statement->nextRowset()); 24 | } catch(PDOException $Exception) { 25 | $messages[] = $Exception->getMessage(); 26 | } 27 | } else { 28 | $messages[] = $Language->text('error_security_csrf'); 29 | } 30 | } 31 | 32 | #=============================================================================== 33 | # Build document 34 | #=============================================================================== 35 | $DatabaseTemplate = Template\Factory::build('database'); 36 | $DatabaseTemplate->set('FORM', [ 37 | 'INFO' => $messages ?? [], 38 | 'TOKEN' => Application::getSecurityToken(), 39 | 'RESULT' => implode(null, $result ?? []), 40 | 'COMMAND' => HTTP::POST('command'), 41 | ]); 42 | 43 | $MainTemplate = Template\Factory::build('main'); 44 | $MainTemplate->set('NAME', 'SQL'); 45 | $MainTemplate->set('HTML', $DatabaseTemplate); 46 | echo $MainTemplate; 47 | -------------------------------------------------------------------------------- /admin/index.php: -------------------------------------------------------------------------------- 1 | getLast()) { 24 | $User = $UserRepository->find($Page->get('user')); 25 | $PageItemTemplate = generatePageItemTemplate($Page, $User); 26 | } 27 | 28 | if($Post = $PostRepository->getLast()) { 29 | $User = $UserRepository->find($Post->get('user')); 30 | $PostItemTemplate = generatePostItemTemplate($Post, $User); 31 | } 32 | 33 | if($User = $UserRepository->getLast()) { 34 | $UserItemTemplate = generateUserItemTemplate($User); 35 | } 36 | 37 | #=============================================================================== 38 | # Build document 39 | #=============================================================================== 40 | $HomeTemplate = Template\Factory::build('home'); 41 | $HomeTemplate->set('LAST', [ 42 | 'PAGE' => $PageItemTemplate ?? false, 43 | 'POST' => $PostItemTemplate ?? false, 44 | 'USER' => $UserItemTemplate ?? false 45 | ]); 46 | 47 | $HomeTemplate->set('COUNT', [ 48 | 'PAGE' => $PageRepository->getCount(), 49 | 'POST' => $PostRepository->getCount(), 50 | 'USER' => $UserRepository->getCount() 51 | ]); 52 | 53 | $MainTemplate = Template\Factory::build('main'); 54 | $MainTemplate->set('NAME', 'Dashboard'); 55 | $MainTemplate->set('HTML', $HomeTemplate); 56 | echo $MainTemplate; 57 | -------------------------------------------------------------------------------- /admin/page/delete.php: -------------------------------------------------------------------------------- 1 | find(HTTP::GET('id'))) { 22 | Application::error404(); 23 | } 24 | 25 | #=============================================================================== 26 | # Check for delete request 27 | #=============================================================================== 28 | if(HTTP::issetPOST('delete')) { 29 | if(HTTP::issetPOST(['token' => Application::getSecurityToken()])) { 30 | try { 31 | $PageRepository->delete($Page); 32 | HTTP::redirect(Application::getAdminURL('page/')); 33 | } catch(PDOException $Exception) { 34 | $messages[] = $Exception->getMessage(); 35 | } 36 | } else { 37 | $messages[] = $Language->text('error_security_csrf'); 38 | } 39 | } 40 | 41 | #=============================================================================== 42 | # Build document 43 | #=============================================================================== 44 | $FormTemplate = Template\Factory::build('page/form'); 45 | $FormTemplate->set('HTML', parseEntityContent($Page)); 46 | $FormTemplate->set('FORM', [ 47 | 'TYPE' => 'DELETE', 48 | 'INFO' => $messages ?? [], 49 | 'DATA' => array_change_key_case($Page->getAll(), CASE_UPPER), 50 | 'TOKEN' => Application::getSecurityToken() 51 | ]); 52 | 53 | $DeleteTemplate = Template\Factory::build('page/delete'); 54 | $DeleteTemplate->set('HTML', $FormTemplate); 55 | 56 | $MainTemplate = Template\Factory::build('main'); 57 | $MainTemplate->set('NAME', $Language->text('title_page_delete')); 58 | $MainTemplate->set('HTML', $DeleteTemplate); 59 | echo $MainTemplate; 60 | -------------------------------------------------------------------------------- /admin/page/index.php: -------------------------------------------------------------------------------- 1 | getCount(); 26 | $lastSite = ceil($count / $site_size); 27 | 28 | $currentSite = HTTP::GET('site') ?? 1; 29 | $currentSite = intval($currentSite); 30 | 31 | #=============================================================================== 32 | # Redirect to page create form if no page exists 33 | #=============================================================================== 34 | if(!$count) { 35 | HTTP::redirect(Application::getAdminURL('page/insert.php')); 36 | } 37 | 38 | if($currentSite < 1 or ($currentSite > $lastSite and $lastSite > 0)) { 39 | Application::error404(); 40 | } 41 | 42 | #=============================================================================== 43 | # Get paginated page list 44 | #=============================================================================== 45 | $pages = $PageRepository->getPaginated( 46 | $site_sort, 47 | $site_size, 48 | ($currentSite-1) * $site_size 49 | ); 50 | 51 | foreach($pages as $Page) { 52 | $User = $UserRepository->find($Page->get('user')); 53 | $templates[] = generatePageItemTemplate($Page, $User); 54 | } 55 | 56 | #=============================================================================== 57 | # Build document 58 | #=============================================================================== 59 | $ListTemplate = Template\Factory::build('page/index'); 60 | $ListTemplate->set('LIST', [ 61 | 'PAGES' => $templates ?? [] 62 | ]); 63 | 64 | $ListTemplate->set('PAGINATION', [ 65 | 'THIS' => $currentSite, 66 | 'LAST' => $lastSite, 67 | 'HTML' => createPaginationTemplate( 68 | $currentSite, $lastSite, Application::getAdminURL('page/') 69 | ) 70 | ]); 71 | 72 | $MainTemplate = Template\Factory::build('main'); 73 | $MainTemplate->set('NAME', $Language->text('title_page_overview', $currentSite)); 74 | $MainTemplate->set('HTML', $ListTemplate); 75 | echo $MainTemplate; 76 | -------------------------------------------------------------------------------- /admin/page/insert.php: -------------------------------------------------------------------------------- 1 | set('user', HTTP::POST('user')); 29 | $Page->set('slug', HTTP::POST('slug') ?: generateSlug(HTTP::POST('name'))); 30 | $Page->set('name', HTTP::POST('name') ?: null); 31 | $Page->set('body', HTTP::POST('body') ?: null); 32 | $Page->set('argv', HTTP::POST('argv') ?: null); 33 | $Page->set('time_insert', HTTP::POST('time_insert') ?: date('Y-m-d H:i:s')); 34 | $Page->set('time_update', HTTP::POST('time_update') ?: date('Y-m-d H:i:s')); 35 | 36 | if(HTTP::issetPOST(['token' => Application::getSecurityToken()])) { 37 | try { 38 | $PageRepository->insert($Page); 39 | HTTP::redirect(Application::getAdminURL('page/')); 40 | } catch(PDOException $Exception) { 41 | $messages[] = $Exception->getMessage(); 42 | } 43 | } 44 | 45 | else { 46 | $messages[] = $Language->text('error_security_csrf'); 47 | } 48 | } 49 | 50 | #=============================================================================== 51 | # Generate user list 52 | #=============================================================================== 53 | foreach($UserRepository->getAll([], 'fullname ASC') as $User) { 54 | $userList[] = [ 55 | 'ID' => $User->getID(), 56 | 'FULLNAME' => $User->get('fullname'), 57 | 'USERNAME' => $User->get('username'), 58 | ]; 59 | } 60 | 61 | #=============================================================================== 62 | # Build document 63 | #=============================================================================== 64 | $FormTemplate = Template\Factory::build('page/form'); 65 | $FormTemplate->set('FORM', [ 66 | 'TYPE' => 'INSERT', 67 | 'INFO' => $messages ?? [], 68 | 'DATA' => array_change_key_case($Page->getAll(), CASE_UPPER), 69 | 'USER_LIST' => $userList ?? [], 70 | 'TOKEN' => Application::getSecurityToken() 71 | ]); 72 | 73 | $InsertTemplate = Template\Factory::build('page/insert'); 74 | $InsertTemplate->set('HTML', $FormTemplate); 75 | 76 | $MainTemplate = Template\Factory::build('main'); 77 | $MainTemplate->set('NAME', $Language->text('title_page_insert')); 78 | $MainTemplate->set('HTML', $InsertTemplate); 79 | echo $MainTemplate; 80 | -------------------------------------------------------------------------------- /admin/page/search.php: -------------------------------------------------------------------------------- 1 | search($search, [], $site_size, $offset)) { 35 | $messages[] = Application::getLanguage()->text( 36 | 'search_no_results', htmlspecialchars($search)); 37 | } 38 | 39 | foreach($pages as $Page) { 40 | $User = $UserRepository->find($Page->get('user')); 41 | $templates[] = generatePageItemTemplate($Page, $User); 42 | } 43 | } catch(PDOException $Exception) { 44 | $messages[] = $Exception->getMessage(); 45 | } 46 | } 47 | 48 | #=============================================================================== 49 | # Create pagination only if there are results 50 | #=============================================================================== 51 | if($count = $PageRepository->getLastSearchOverallCount()) { 52 | $last = ceil($count / $site_size); 53 | 54 | $pagination_data = [ 55 | 'THIS' => $currentSite, 56 | 'LAST' => $last, 57 | 'HTML' => createPaginationTemplate( 58 | $currentSite, $last, Application::getAdminURL('page/search.php') 59 | ) 60 | ]; 61 | } 62 | 63 | #=============================================================================== 64 | # Build document 65 | #=============================================================================== 66 | $SearchTemplate = Template\Factory::build('page/search'); 67 | $SearchTemplate->set('QUERY', $search); 68 | $SearchTemplate->set('PAGES', $templates ?? []); 69 | $SearchTemplate->set('FORM', [ 70 | 'INFO' => $messages ?? [] 71 | ]); 72 | $SearchTemplate->set('PAGINATION', $pagination_data ?? []); 73 | 74 | $MainTemplate = Template\Factory::build('main'); 75 | $MainTemplate->set('NAME', $Language->text('title_page_search')); 76 | $MainTemplate->set('HTML', $SearchTemplate); 77 | 78 | echo $MainTemplate; 79 | -------------------------------------------------------------------------------- /admin/page/update.php: -------------------------------------------------------------------------------- 1 | find(HTTP::GET('id'))) { 23 | Application::error404(); 24 | } 25 | 26 | #=============================================================================== 27 | # Check for update request 28 | #=============================================================================== 29 | if(HTTP::issetPOST('update')) { 30 | $Page->set('user', HTTP::POST('user')); 31 | $Page->set('slug', HTTP::POST('slug') ?: generateSlug(HTTP::POST('name'))); 32 | $Page->set('name', HTTP::POST('name') ?: null); 33 | $Page->set('body', HTTP::POST('body') ?: null); 34 | $Page->set('argv', HTTP::POST('argv') ?: null); 35 | $Page->set('time_insert', HTTP::POST('time_insert') ?: date('Y-m-d H:i:s')); 36 | $Page->set('time_update', HTTP::POST('time_update') ?: date('Y-m-d H:i:s')); 37 | 38 | if(HTTP::issetPOST(['token' => Application::getSecurityToken()])) { 39 | try { 40 | $PageRepository->update($Page); 41 | } catch(PDOException $Exception) { 42 | $messages[] = $Exception->getMessage(); 43 | } 44 | } 45 | 46 | else { 47 | $messages[] = $Language->text('error_security_csrf'); 48 | } 49 | } 50 | 51 | #=============================================================================== 52 | # Generate user list 53 | #=============================================================================== 54 | foreach($UserRepository->getAll([], 'fullname ASC') as $User) { 55 | $userList[] = [ 56 | 'ID' => $User->getID(), 57 | 'FULLNAME' => $User->get('fullname'), 58 | 'USERNAME' => $User->get('username'), 59 | ]; 60 | } 61 | 62 | #=============================================================================== 63 | # Build document 64 | #=============================================================================== 65 | $FormTemplate = Template\Factory::build('page/form'); 66 | $FormTemplate->set('FORM', [ 67 | 'TYPE' => 'UPDATE', 68 | 'INFO' => $messages ?? [], 69 | 'DATA' => array_change_key_case($Page->getAll(), CASE_UPPER), 70 | 'USER_LIST' => $userList ?? [], 71 | 'TOKEN' => Application::getSecurityToken() 72 | ]); 73 | 74 | $UpdateTemplate = Template\Factory::build('page/update'); 75 | $UpdateTemplate->set('PAGE', generateItemTemplateData($Page)); 76 | $UpdateTemplate->set('HTML', $FormTemplate); 77 | 78 | $MainTemplate = Template\Factory::build('main'); 79 | $MainTemplate->set('NAME', $Language->text('title_page_update')); 80 | $MainTemplate->set('HTML', $UpdateTemplate); 81 | echo $MainTemplate; 82 | -------------------------------------------------------------------------------- /admin/post/delete.php: -------------------------------------------------------------------------------- 1 | find(HTTP::GET('id'))) { 22 | Application::error404(); 23 | } 24 | 25 | #=============================================================================== 26 | # Check for delete request 27 | #=============================================================================== 28 | if(HTTP::issetPOST('delete')) { 29 | if(HTTP::issetPOST(['token' => Application::getSecurityToken()])) { 30 | try { 31 | $PostRepository->delete($Post); 32 | HTTP::redirect(Application::getAdminURL('post/')); 33 | } catch(PDOException $Exception) { 34 | $messages[] = $Exception->getMessage(); 35 | } 36 | } else { 37 | $messages[] = $Language->text('error_security_csrf'); 38 | } 39 | } 40 | 41 | #=============================================================================== 42 | # Build document 43 | #=============================================================================== 44 | $FormTemplate = Template\Factory::build('post/form'); 45 | $FormTemplate->set('HTML', parseEntityContent($Post)); 46 | $FormTemplate->set('FORM', [ 47 | 'TYPE' => 'DELETE', 48 | 'INFO' => $messages ?? [], 49 | 'DATA' => array_change_key_case($Post->getAll(), CASE_UPPER), 50 | 'TOKEN' => Application::getSecurityToken() 51 | ]); 52 | 53 | $DeleteTemplate = Template\Factory::build('post/delete'); 54 | $DeleteTemplate->set('HTML', $FormTemplate); 55 | 56 | $MainTemplate = Template\Factory::build('main'); 57 | $MainTemplate->set('NAME', $Language->text('title_post_delete')); 58 | $MainTemplate->set('HTML', $DeleteTemplate); 59 | echo $MainTemplate; 60 | -------------------------------------------------------------------------------- /admin/post/index.php: -------------------------------------------------------------------------------- 1 | getCount(); 26 | $lastSite = ceil($count / $site_size); 27 | 28 | $currentSite = HTTP::GET('site') ?? 1; 29 | $currentSite = intval($currentSite); 30 | 31 | #=============================================================================== 32 | # Redirect to post create form if no post exists 33 | #=============================================================================== 34 | if(!$count) { 35 | HTTP::redirect(Application::getAdminURL('post/insert.php')); 36 | } 37 | 38 | if($currentSite < 1 or ($currentSite > $lastSite and $lastSite > 0)) { 39 | Application::error404(); 40 | } 41 | 42 | #=============================================================================== 43 | # Get paginated post list 44 | #=============================================================================== 45 | $posts = $PostRepository->getPaginated( 46 | $site_sort, 47 | $site_size, 48 | ($currentSite-1) * $site_size 49 | ); 50 | 51 | foreach($posts as $Post) { 52 | $User = $UserRepository->find($Post->get('user')); 53 | $templates[] = generatePostItemTemplate($Post, $User); 54 | } 55 | 56 | #=============================================================================== 57 | # Build document 58 | #=============================================================================== 59 | $ListTemplate = Template\Factory::build('post/index'); 60 | $ListTemplate->set('LIST', [ 61 | 'POSTS' => $templates ?? [] 62 | ]); 63 | 64 | $ListTemplate->set('PAGINATION', [ 65 | 'THIS' => $currentSite, 66 | 'LAST' => $lastSite, 67 | 'HTML' => createPaginationTemplate( 68 | $currentSite, $lastSite, Application::getAdminURL('post/') 69 | ) 70 | ]); 71 | 72 | $MainTemplate = Template\Factory::build('main'); 73 | $MainTemplate->set('NAME', $Language->text('title_post_overview', $currentSite)); 74 | $MainTemplate->set('HTML', $ListTemplate); 75 | echo $MainTemplate; 76 | -------------------------------------------------------------------------------- /admin/post/insert.php: -------------------------------------------------------------------------------- 1 | set('category', HTTP::POST('category') ?: null); 30 | $Post->set('user', HTTP::POST('user')); 31 | $Post->set('slug', HTTP::POST('slug') ?: generateSlug(HTTP::POST('name'))); 32 | $Post->set('name', HTTP::POST('name') ?: null); 33 | $Post->set('body', HTTP::POST('body') ?: null); 34 | $Post->set('argv', HTTP::POST('argv') ?: null); 35 | $Post->set('time_insert', HTTP::POST('time_insert') ?: date('Y-m-d H:i:s')); 36 | $Post->set('time_update', HTTP::POST('time_update') ?: date('Y-m-d H:i:s')); 37 | 38 | if(HTTP::issetPOST(['token' => Application::getSecurityToken()])) { 39 | try { 40 | $PostRepository->insert($Post); 41 | HTTP::redirect(Application::getAdminURL('post/')); 42 | } catch(PDOException $Exception) { 43 | $messages[] = $Exception->getMessage(); 44 | } 45 | } 46 | 47 | else { 48 | $messages[] = $Language->text('error_security_csrf'); 49 | } 50 | } 51 | 52 | #=============================================================================== 53 | # Generate user list 54 | #=============================================================================== 55 | foreach($UserRepository->getAll([], 'fullname ASC') as $User) { 56 | $userList[] = [ 57 | 'ID' => $User->getID(), 58 | 'FULLNAME' => $User->get('fullname'), 59 | 'USERNAME' => $User->get('username'), 60 | ]; 61 | } 62 | 63 | #=============================================================================== 64 | # Generate category list 65 | #=============================================================================== 66 | foreach($CategoryRepository->getAll([], 'name ASC') as $Category) { 67 | $categoryList[] = [ 68 | 'ID' => $Category->getID(), 69 | 'NAME' => $Category->get('name'), 70 | 'PARENT' => $Category->get('parent'), 71 | ]; 72 | } 73 | 74 | #=============================================================================== 75 | # Build document 76 | #=============================================================================== 77 | $FormTemplate = Template\Factory::build('post/form'); 78 | $FormTemplate->set('FORM', [ 79 | 'TYPE' => 'INSERT', 80 | 'INFO' => $messages ?? [], 81 | 'DATA' => array_change_key_case($Post->getAll(), CASE_UPPER), 82 | 'USER_LIST' => $userList ?? [], 83 | 'CATEGORY_LIST' => $categoryList ?? [], 84 | 'CATEGORY_TREE' => generateCategoryDataTree($categoryList ?? []), 85 | 'TOKEN' => Application::getSecurityToken() 86 | ]); 87 | 88 | $InsertTemplate = Template\Factory::build('post/insert'); 89 | $InsertTemplate->set('HTML', $FormTemplate); 90 | 91 | $MainTemplate = Template\Factory::build('main'); 92 | $MainTemplate->set('NAME', $Language->text('title_post_insert')); 93 | $MainTemplate->set('HTML', $InsertTemplate); 94 | echo $MainTemplate; 95 | -------------------------------------------------------------------------------- /admin/post/search.php: -------------------------------------------------------------------------------- 1 | HTTP::GET('user'), 37 | 'category' => HTTP::GET('category') 38 | ]; 39 | 40 | if(!$posts = $PostRepository->search($search, $filter, $site_size, $offset)) { 41 | $messages[] = Application::getLanguage()->text( 42 | 'search_no_results', htmlspecialchars($search)); 43 | } 44 | 45 | foreach($posts as $Post) { 46 | $User = $UserRepository->find($Post->get('user')); 47 | $templates[] = generatePostItemTemplate($Post, $User); 48 | } 49 | } catch(PDOException $Exception) { 50 | $messages[] = $Exception->getMessage(); 51 | } 52 | } 53 | 54 | #=============================================================================== 55 | # Create pagination only if there are results 56 | #=============================================================================== 57 | if($count = $PostRepository->getLastSearchOverallCount()) { 58 | $last = ceil($count / $site_size); 59 | 60 | $pagination_data = [ 61 | 'THIS' => $currentSite, 62 | 'LAST' => $last, 63 | 'HTML' => createPaginationTemplate( 64 | $currentSite, $last, Application::getAdminURL('post/search.php') 65 | ) 66 | ]; 67 | } 68 | 69 | #=============================================================================== 70 | # Generate user list 71 | #=============================================================================== 72 | foreach($UserRepository->getAll([], 'fullname ASC') as $User) { 73 | $userList[] = [ 74 | 'ID' => $User->getID(), 75 | 'FULLNAME' => $User->get('fullname'), 76 | 'USERNAME' => $User->get('username'), 77 | ]; 78 | } 79 | 80 | #=============================================================================== 81 | # Generate category list 82 | #=============================================================================== 83 | foreach($CategoryRepository->getAll([], 'name ASC') as $Category) { 84 | $categoryList[] = [ 85 | 'ID' => $Category->getID(), 86 | 'NAME' => $Category->get('name'), 87 | 'PARENT' => $Category->get('parent'), 88 | ]; 89 | } 90 | 91 | #=============================================================================== 92 | # Build document 93 | #=============================================================================== 94 | $SearchTemplate = Template\Factory::build('post/search'); 95 | $SearchTemplate->set('QUERY', $search); 96 | $SearchTemplate->set('POSTS', $templates ?? []); 97 | $SearchTemplate->set('FORM', [ 98 | 'INFO' => $messages ?? [], 99 | 'DATA' => [ 100 | 'USER' => HTTP::GET('user'), 101 | 'CATEGORY' => HTTP::GET('category') 102 | ], 103 | 'USER_LIST' => $userList ?? [], 104 | 'CATEGORY_LIST' => $categoryList ?? [], 105 | 'CATEGORY_TREE' => generateCategoryDataTree($categoryList ?? []) 106 | ]); 107 | $SearchTemplate->set('PAGINATION', $pagination_data ?? []); 108 | 109 | $MainTemplate = Template\Factory::build('main'); 110 | $MainTemplate->set('NAME', $Language->text('title_post_search')); 111 | $MainTemplate->set('HTML', $SearchTemplate); 112 | 113 | echo $MainTemplate; 114 | -------------------------------------------------------------------------------- /admin/post/update.php: -------------------------------------------------------------------------------- 1 | find(HTTP::GET('id'))) { 24 | Application::error404(); 25 | } 26 | 27 | #=============================================================================== 28 | # Check for update request 29 | #=============================================================================== 30 | if(HTTP::issetPOST('update')) { 31 | $Post->set('category', HTTP::POST('category') ?: null); 32 | $Post->set('user', HTTP::POST('user')); 33 | $Post->set('slug', HTTP::POST('slug') ?: generateSlug(HTTP::POST('name'))); 34 | $Post->set('name', HTTP::POST('name') ?: null); 35 | $Post->set('body', HTTP::POST('body') ?: null); 36 | $Post->set('argv', HTTP::POST('argv') ?: null); 37 | $Post->set('time_insert', HTTP::POST('time_insert') ?: date('Y-m-d H:i:s')); 38 | $Post->set('time_update', HTTP::POST('time_update') ?: date('Y-m-d H:i:s')); 39 | 40 | if(HTTP::issetPOST(['token' => Application::getSecurityToken()])) { 41 | try { 42 | $PostRepository->update($Post); 43 | } catch(PDOException $Exception) { 44 | $messages[] = $Exception->getMessage(); 45 | } 46 | } 47 | 48 | else { 49 | $messages[] = $Language->text('error_security_csrf'); 50 | } 51 | } 52 | 53 | #=============================================================================== 54 | # Generate user list 55 | #=============================================================================== 56 | foreach($UserRepository->getAll([], 'fullname ASC') as $User) { 57 | $userList[] = [ 58 | 'ID' => $User->getID(), 59 | 'FULLNAME' => $User->get('fullname'), 60 | 'USERNAME' => $User->get('username'), 61 | ]; 62 | } 63 | 64 | #=============================================================================== 65 | # Generate category list 66 | #=============================================================================== 67 | foreach($CategoryRepository->getAll([], 'name ASC') as $Category) { 68 | $categoryList[] = [ 69 | 'ID' => $Category->getID(), 70 | 'NAME' => $Category->get('name'), 71 | 'PARENT' => $Category->get('parent'), 72 | ]; 73 | } 74 | 75 | #=============================================================================== 76 | # Build document 77 | #=============================================================================== 78 | $FormTemplate = Template\Factory::build('post/form'); 79 | $FormTemplate->set('FORM', [ 80 | 'TYPE' => 'UPDATE', 81 | 'INFO' => $messages ?? [], 82 | 'DATA' => array_change_key_case($Post->getAll(), CASE_UPPER), 83 | 'USER_LIST' => $userList ?? [], 84 | 'CATEGORY_LIST' => $categoryList ?? [], 85 | 'CATEGORY_TREE' => generateCategoryDataTree($categoryList ?? []), 86 | 'TOKEN' => Application::getSecurityToken() 87 | ]); 88 | 89 | $UpdateTemplate = Template\Factory::build('post/update'); 90 | $UpdateTemplate->set('POST', generateItemTemplateData($Post)); 91 | $UpdateTemplate->set('HTML', $FormTemplate); 92 | 93 | $MainTemplate = Template\Factory::build('main'); 94 | $MainTemplate->set('NAME', $Language->text('title_post_update')); 95 | $MainTemplate->set('HTML', $UpdateTemplate); 96 | echo $MainTemplate; 97 | -------------------------------------------------------------------------------- /admin/user/delete.php: -------------------------------------------------------------------------------- 1 | find(HTTP::GET('id'))) { 22 | Application::error404(); 23 | } 24 | 25 | #=============================================================================== 26 | # Check for delete request 27 | #=============================================================================== 28 | if(HTTP::issetPOST('delete')) { 29 | if(HTTP::issetPOST(['token' => Application::getSecurityToken()])) { 30 | try { 31 | $UserRepository->delete($User); 32 | HTTP::redirect(Application::getAdminURL('user/')); 33 | } catch(PDOException $Exception) { 34 | $messages[] = $Exception->getMessage(); 35 | } 36 | } else { 37 | $messages[] = $Language->text('error_security_csrf'); 38 | } 39 | } 40 | 41 | #=============================================================================== 42 | # Build document 43 | #=============================================================================== 44 | $FormTemplate = Template\Factory::build('user/form'); 45 | $FormTemplate->set('HTML', parseEntityContent($User)); 46 | $FormTemplate->set('FORM', [ 47 | 'TYPE' => 'DELETE', 48 | 'INFO' => $messages ?? [], 49 | 'DATA' => array_change_key_case($User->getAll(['password']), CASE_UPPER), 50 | 'TOKEN' => Application::getSecurityToken() 51 | ]); 52 | 53 | $DeleteTemplate = Template\Factory::build('user/delete'); 54 | $DeleteTemplate->set('HTML', $FormTemplate); 55 | 56 | $MainTemplate = Template\Factory::build('main'); 57 | $MainTemplate->set('NAME', $Language->text('title_user_delete')); 58 | $MainTemplate->set('HTML', $DeleteTemplate); 59 | echo $MainTemplate; 60 | -------------------------------------------------------------------------------- /admin/user/index.php: -------------------------------------------------------------------------------- 1 | getCount(); 25 | $lastSite = ceil($count / $site_size); 26 | 27 | $currentSite = HTTP::GET('site') ?? 1; 28 | $currentSite = intval($currentSite); 29 | 30 | #=============================================================================== 31 | # Redirect to user create form if no user exists 32 | #=============================================================================== 33 | if(!$count) { 34 | HTTP::redirect(Application::getAdminURL('user/insert.php')); 35 | } 36 | 37 | if($currentSite < 1 or ($currentSite > $lastSite and $lastSite > 0)) { 38 | Application::error404(); 39 | } 40 | 41 | #=============================================================================== 42 | # Get paginated user list 43 | #=============================================================================== 44 | $users = $UserRepository->getPaginated( 45 | $site_sort, 46 | $site_size, 47 | ($currentSite-1) * $site_size 48 | ); 49 | 50 | foreach($users as $User) { 51 | $templates[] = generateUserItemTemplate($User); 52 | } 53 | 54 | #=============================================================================== 55 | # Build document 56 | #=============================================================================== 57 | $ListTemplate = Template\Factory::build('user/index'); 58 | $ListTemplate->set('LIST', [ 59 | 'USERS' => $templates ?? [] 60 | ]); 61 | 62 | $ListTemplate->set('PAGINATION', [ 63 | 'THIS' => $currentSite, 64 | 'LAST' => $lastSite, 65 | 'HTML' => createPaginationTemplate( 66 | $currentSite, $lastSite, Application::getAdminURL('user/') 67 | ) 68 | ]); 69 | 70 | $MainTemplate = Template\Factory::build('main'); 71 | $MainTemplate->set('NAME', $Language->text('title_user_overview', $currentSite)); 72 | $MainTemplate->set('HTML', $ListTemplate); 73 | echo $MainTemplate; 74 | -------------------------------------------------------------------------------- /admin/user/insert.php: -------------------------------------------------------------------------------- 1 | set('slug', HTTP::POST('slug') ?: generateSlug(HTTP::POST('username'))); 28 | $User->set('username', HTTP::POST('username') ?: null); 29 | $User->set('password', HTTP::POST('password') ? password_hash(HTTP::POST('password'), PASSWORD_BCRYPT, ['cost' => 10]) : false); 30 | $User->set('fullname', HTTP::POST('fullname') ?: null); 31 | $User->set('mailaddr', HTTP::POST('mailaddr') ?: null); 32 | $User->set('body', HTTP::POST('body') ?: null); 33 | $User->set('argv', HTTP::POST('argv') ?: null); 34 | $User->set('time_insert', HTTP::POST('time_insert') ?: date('Y-m-d H:i:s')); 35 | $User->set('time_update', HTTP::POST('time_update') ?: date('Y-m-d H:i:s')); 36 | 37 | if(HTTP::issetPOST(['token' => Application::getSecurityToken()])) { 38 | try { 39 | $UserRepository->insert($User); 40 | HTTP::redirect(Application::getAdminURL('user/')); 41 | } catch(PDOException $Exception) { 42 | $messages[] = $Exception->getMessage(); 43 | } 44 | } 45 | 46 | else { 47 | $messages[] = $Language->text('error_security_csrf'); 48 | } 49 | } 50 | 51 | #=============================================================================== 52 | # Build document 53 | #=============================================================================== 54 | $FormTemplate = Template\Factory::build('user/form'); 55 | $FormTemplate->set('FORM', [ 56 | 'TYPE' => 'INSERT', 57 | 'INFO' => $messages ?? [], 58 | 'DATA' => array_change_key_case($User->getAll(['password']), CASE_UPPER), 59 | 'TOKEN' => Application::getSecurityToken() 60 | ]); 61 | 62 | $InsertTemplate = Template\Factory::build('user/insert'); 63 | $InsertTemplate->set('HTML', $FormTemplate); 64 | 65 | $MainTemplate = Template\Factory::build('main'); 66 | $MainTemplate->set('NAME', $Language->text('title_user_insert')); 67 | $MainTemplate->set('HTML', $InsertTemplate); 68 | echo $MainTemplate; 69 | -------------------------------------------------------------------------------- /admin/user/update.php: -------------------------------------------------------------------------------- 1 | find(HTTP::GET('id'))) { 22 | Application::error404(); 23 | } 24 | 25 | #=============================================================================== 26 | # Check for update request 27 | #=============================================================================== 28 | if(HTTP::issetPOST('update')) { 29 | $User->set('slug', HTTP::POST('slug') ?: generateSlug(HTTP::POST('username'))); 30 | $User->set('username', HTTP::POST('username') ?: null); 31 | $User->set('password', HTTP::POST('password') ? password_hash(HTTP::POST('password'), PASSWORD_BCRYPT, ['cost' => 10]) : false); 32 | $User->set('fullname', HTTP::POST('fullname') ?: null); 33 | $User->set('mailaddr', HTTP::POST('mailaddr') ?: null); 34 | $User->set('body', HTTP::POST('body') ?: null); 35 | $User->set('argv', HTTP::POST('argv') ?: null); 36 | $User->set('time_insert', HTTP::POST('time_insert') ?: date('Y-m-d H:i:s')); 37 | $User->set('time_update', HTTP::POST('time_update') ?: date('Y-m-d H:i:s')); 38 | 39 | if(HTTP::issetPOST(['token' => Application::getSecurityToken()])) { 40 | try { 41 | $UserRepository->update($User); 42 | } catch(PDOException $Exception) { 43 | $messages[] = $Exception->getMessage(); 44 | } 45 | } 46 | 47 | else { 48 | $messages[] = $Language->text('error_security_csrf'); 49 | } 50 | } 51 | 52 | #=============================================================================== 53 | # Build document 54 | #=============================================================================== 55 | $FormTemplate = Template\Factory::build('user/form'); 56 | $FormTemplate->set('FORM', [ 57 | 'TYPE' => 'UPDATE', 58 | 'INFO' => $messages ?? [], 59 | 'DATA' => array_change_key_case($User->getAll(['password']), CASE_UPPER), 60 | 'TOKEN' => Application::getSecurityToken() 61 | ]); 62 | 63 | $UpdateTemplate = Template\Factory::build('user/update'); 64 | $UpdateTemplate->set('USER', generateItemTemplateData($User)); 65 | $UpdateTemplate->set('HTML', $FormTemplate); 66 | 67 | $MainTemplate = Template\Factory::build('main'); 68 | $MainTemplate->set('NAME', $Language->text('title_user_update')); 69 | $MainTemplate->set('HTML', $UpdateTemplate); 70 | echo $MainTemplate; 71 | -------------------------------------------------------------------------------- /core/configuration-example.php: -------------------------------------------------------------------------------- 1 | ] # 4 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 5 | # # 6 | # This file will override the pre-defined configuration settings of the system # 7 | # and is the primary file where you change the configuration. Do not touch any # 8 | # other files to change your configuration – just override it here! # 9 | # # 10 | # Documentation: # 11 | # 1. https://github.com/Nerdmind/Blog/wiki/Configuration # 12 | # 2. https://code.nerdmind.de/blog/wiki/tree/Configuration.md # 13 | # # 14 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 15 | 16 | # setlocale(LC_TIME, ['en_US.utf8', 'en_US']); 17 | 18 | Application::set('CORE.LANGUAGE', 'en'); 19 | Application::set('BLOGMETA.NAME', 'My Techblog'); 20 | Application::set('BLOGMETA.DESC', '[a creative description]'); 21 | Application::set('BLOGMETA.HOME', 'Home'); 22 | Application::set('BLOGMETA.MAIL', 'mail@example.org'); 23 | Application::set('BLOGMETA.LANG', 'en'); 24 | Application::set('DATABASE.BASENAME', 'blog'); 25 | Application::set('DATABASE.USERNAME', ''); 26 | Application::set('DATABASE.PASSWORD', ''); 27 | Application::set('TEMPLATE.NAME', 'default'); 28 | Application::set('TEMPLATE.LANG', Application::get('CORE.LANGUAGE')); 29 | Application::set('ADMIN.LANGUAGE', Application::get('CORE.LANGUAGE')); 30 | -------------------------------------------------------------------------------- /core/db/migrations/1.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE `page` ADD `argv` VARCHAR(100) NULL DEFAULT NULL AFTER `body`; 2 | ALTER TABLE `post` ADD `argv` VARCHAR(100) NULL DEFAULT NULL AFTER `body`; 3 | ALTER TABLE `user` ADD `argv` VARCHAR(100) NULL DEFAULT NULL AFTER `body`; 4 | -------------------------------------------------------------------------------- /core/db/migrations/2.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE `page` ADD UNIQUE KEY `time_insert` (`time_insert`); 2 | ALTER TABLE `post` ADD UNIQUE KEY `time_insert` (`time_insert`); 3 | ALTER TABLE `user` ADD UNIQUE KEY `time_insert` (`time_insert`); 4 | -------------------------------------------------------------------------------- /core/db/migrations/3.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE `post` ENGINE=InnoDB; 2 | ALTER TABLE `post` DROP INDEX `body`; 3 | ALTER TABLE `page` ADD FULLTEXT KEY `search` (`name`, `body`); 4 | ALTER TABLE `post` ADD FULLTEXT KEY `search` (`name`, `body`); 5 | ALTER TABLE `post` ADD CONSTRAINT `post_user` FOREIGN KEY (`user`) 6 | REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE; 7 | -------------------------------------------------------------------------------- /core/db/migrations/4.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE `page` MODIFY `argv` VARCHAR(250); 2 | ALTER TABLE `post` MODIFY `argv` VARCHAR(250); 3 | ALTER TABLE `user` MODIFY `argv` VARCHAR(250); 4 | -------------------------------------------------------------------------------- /core/db/migrations/5.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE `page` DROP FOREIGN KEY `page_user`; 2 | ALTER TABLE `post` DROP FOREIGN KEY `post_user`; 3 | 4 | ALTER TABLE `page` MODIFY `id` SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT, 5 | MODIFY `user` TINYINT UNSIGNED NOT NULL; 6 | ALTER TABLE `post` MODIFY `id` SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT, 7 | MODIFY `user` TINYINT UNSIGNED NOT NULL; 8 | ALTER TABLE `user` MODIFY `id` TINYINT UNSIGNED NOT NULL AUTO_INCREMENT; 9 | 10 | ALTER TABLE `page` ADD CONSTRAINT `page_user` FOREIGN KEY (`user`) 11 | REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE; 12 | ALTER TABLE `post` ADD CONSTRAINT `post_user` FOREIGN KEY (`user`) 13 | REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE; 14 | -------------------------------------------------------------------------------- /core/db/migrations/6.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `category` ( 2 | `id` tinyint(3) UNSIGNED NOT NULL AUTO_INCREMENT, 3 | `time_insert` datetime NOT NULL, 4 | `time_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 5 | `parent` tinyint(3) UNSIGNED DEFAULT NULL, 6 | `slug` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL, 7 | `name` varchar(100) NOT NULL, 8 | `body` text NOT NULL, 9 | `argv` varchar(250) DEFAULT NULL, 10 | PRIMARY KEY (`id`), 11 | UNIQUE KEY `time_insert` (`time_insert`), 12 | UNIQUE KEY `slug` (`slug`), 13 | KEY `category_parent` (`parent`), 14 | FULLTEXT KEY `search` (`name`, `body`) 15 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; 16 | 17 | ALTER TABLE `post` ADD `category` tinyint(3) UNSIGNED DEFAULT NULL AFTER `user`, 18 | ADD KEY `post_category` (`category`); 19 | 20 | ALTER TABLE `category` ADD CONSTRAINT `category_parent` FOREIGN KEY (`parent`) 21 | REFERENCES `category` (`id`) ON DELETE SET NULL ON UPDATE CASCADE; 22 | 23 | ALTER TABLE `post` ADD CONSTRAINT `post_category` FOREIGN KEY (`category`) 24 | REFERENCES `category` (`id`) ON DELETE SET NULL ON UPDATE CASCADE; 25 | -------------------------------------------------------------------------------- /core/include/category/list.php: -------------------------------------------------------------------------------- 1 | getCount(); 19 | $lastSite = ceil($count / $site_size); 20 | 21 | $currentSite = HTTP::GET('site') ?? 1; 22 | $currentSite = intval($currentSite); 23 | 24 | if($currentSite < 1 or ($currentSite > $lastSite and $lastSite > 0)) { 25 | Application::error404(); 26 | } 27 | 28 | #=============================================================================== 29 | # Single redirect 30 | #=============================================================================== 31 | if(Application::get('CATEGORY.REDIRECT_SINGLE') === true and $count === 1) { 32 | $Category = $CategoryRepository->getLast(); 33 | HTTP::redirect(Application::getEntityURL($Category)); 34 | } 35 | 36 | #=============================================================================== 37 | # Get paginated category list 38 | #=============================================================================== 39 | $categories = $CategoryRepository->getPaginatedTree( 40 | $site_size, 41 | ($currentSite-1) * $site_size 42 | ); 43 | 44 | foreach($categories as $Category) { 45 | $templates[] = generateCategoryItemTemplate($Category, true); 46 | } 47 | 48 | #=============================================================================== 49 | # Build document 50 | #=============================================================================== 51 | $ListTemplate = Template\Factory::build('category/list'); 52 | $ListTemplate->set('PAGINATION', [ 53 | 'THIS' => $currentSite, 54 | 'LAST' => $lastSite, 55 | 'HTML' => createPaginationTemplate( 56 | $currentSite, $lastSite, Application::getCategoryURL()) 57 | ]); 58 | $ListTemplate->set('LIST', [ 59 | 'CATEGORIES' => $templates ?? [] 60 | ]); 61 | 62 | $MainTemplate = Template\Factory::build('main'); 63 | $MainTemplate->set('HTML', $ListTemplate); 64 | $MainTemplate->set('HEAD', [ 65 | 'NAME' => $Language->text('title_category_overview', $currentSite) 66 | ]); 67 | 68 | echo $MainTemplate; 69 | -------------------------------------------------------------------------------- /core/include/feed/main.php: -------------------------------------------------------------------------------- 1 | getPaginated( 18 | Application::get('POST.FEED_SORT'), 19 | Application::get('POST.FEED_SIZE') 20 | ); 21 | 22 | #=============================================================================== 23 | # Build item templates 24 | #=============================================================================== 25 | foreach($posts as $Post) { 26 | $User = $UserRepository->find($Post->get('user')); 27 | 28 | try { 29 | $ItemTemplate = Template\Factory::build('feed/item'); 30 | } catch(Template\Exception $Exception) { 31 | # Backward compatibility if feed/item.php does not exist. 32 | $ItemTemplate = Template\Factory::build('feed/item_post'); 33 | } 34 | 35 | $post_data = generateItemTemplateData($Post); 36 | $post_data['GUID'] = sha1($Post->getID().$Post->get('time_insert')); 37 | 38 | #=============================================================================== 39 | # Generate category template data (including parents) 40 | #=============================================================================== 41 | foreach($CategoryRepository->findWithParents($Post->get('category')) as $Category) { 42 | $category_list[] = generateItemTemplateData($Category); 43 | } 44 | 45 | #=============================================================================== 46 | # Define data variable for current category 47 | #=============================================================================== 48 | if(isset($category_list)) { 49 | $category_data = $category_list[array_key_last($category_list)]; 50 | } 51 | 52 | $ItemTemplate->set('POST', $post_data); 53 | $ItemTemplate->set('USER', generateItemTemplateData($User)); 54 | $ItemTemplate->set('CATEGORY', $category_data ?? []); 55 | $ItemTemplate->set('CATEGORIES', $category_list ?? []); 56 | 57 | $templates[] = $ItemTemplate; 58 | } 59 | 60 | #=============================================================================== 61 | # Build document 62 | #=============================================================================== 63 | $FeedTemplate = Template\Factory::build('feed/main'); 64 | $FeedTemplate->set('FEED', [ 65 | 'TYPE' => 'post', 66 | 'LIST' => [ 67 | 'POSTS' => $templates ?? [], 68 | 'PAGES' => [], 69 | ] 70 | ]); 71 | 72 | echo $FeedTemplate; 73 | -------------------------------------------------------------------------------- /core/include/home.php: -------------------------------------------------------------------------------- 1 | getPaginated( 12 | Application::get('POST.LIST_SORT'), 13 | Application::get('POST.LIST_SIZE') 14 | ); 15 | 16 | foreach($posts as $Post) { 17 | $User = $UserRepository->find($Post->get('user')); 18 | $templates[] = generatePostItemTemplate($Post, $User); 19 | } 20 | 21 | #=============================================================================== 22 | # Pagination 23 | #=============================================================================== 24 | $count = $PostRepository->getCount(); 25 | $lastSite = ceil($count / Application::get('POST.LIST_SIZE')); 26 | 27 | #=============================================================================== 28 | # Build document 29 | #=============================================================================== 30 | $HomeTemplate = Template\Factory::build('home'); 31 | $HomeTemplate->set('PAGINATION', [ 32 | 'HTML' => createPaginationTemplate( 33 | 1, $lastSite, Application::getPostURL()) 34 | ]); 35 | $HomeTemplate->set('LIST', [ 36 | 'POSTS' => $templates ?? [] 37 | ]); 38 | 39 | $MainTemplate = Template\Factory::build('main'); 40 | $MainTemplate->set('HTML', $HomeTemplate); 41 | $MainTemplate->set('HEAD', [ 42 | 'NAME' => Application::get('BLOGMETA.HOME'), 43 | 'DESC' => Application::get('BLOGMETA.NAME').' – ' 44 | .Application::get('BLOGMETA.DESC'), 45 | 'PERM' => Application::getURL() 46 | ]); 47 | 48 | echo $MainTemplate; 49 | -------------------------------------------------------------------------------- /core/include/page/list.php: -------------------------------------------------------------------------------- 1 | getCount(); 20 | $lastSite = ceil($count / $site_size); 21 | 22 | $currentSite = HTTP::GET('site') ?? 1; 23 | $currentSite = intval($currentSite); 24 | 25 | if($currentSite < 1 or ($currentSite > $lastSite and $lastSite > 0)) { 26 | Application::error404(); 27 | } 28 | 29 | #=============================================================================== 30 | # Single redirect 31 | #=============================================================================== 32 | if(Application::get('PAGE.REDIRECT_SINGLE') === true and $count === 1) { 33 | $Page = $PageRepository->getLast(); 34 | HTTP::redirect(Application::getEntityURL($Page)); 35 | } 36 | 37 | #=============================================================================== 38 | # Get paginated page list 39 | #=============================================================================== 40 | $pages = $PageRepository->getPaginated( 41 | $site_sort, 42 | $site_size, 43 | ($currentSite-1) * $site_size 44 | ); 45 | 46 | foreach($pages as $Page) { 47 | $User = $UserRepository->find($Page->get('user')); 48 | $templates[] = generatePageItemTemplate($Page, $User); 49 | } 50 | 51 | #=============================================================================== 52 | # Build document 53 | #=============================================================================== 54 | $ListTemplate = Template\Factory::build('page/list'); 55 | $ListTemplate->set('PAGINATION', [ 56 | 'THIS' => $currentSite, 57 | 'LAST' => $lastSite, 58 | 'HTML' => createPaginationTemplate( 59 | $currentSite, $lastSite, Application::getPageURL() 60 | ) 61 | ]); 62 | $ListTemplate->set('LIST', [ 63 | 'PAGES' => $templates ?? [] 64 | ]); 65 | 66 | $MainTemplate = Template\Factory::build('main'); 67 | $MainTemplate->set('HTML', $ListTemplate); 68 | $MainTemplate->set('HEAD', [ 69 | 'NAME' => $Language->text('title_page_overview', $currentSite) 70 | ]); 71 | 72 | echo $MainTemplate; 73 | -------------------------------------------------------------------------------- /core/include/page/main.php: -------------------------------------------------------------------------------- 1 | findBy('slug', $param)) { 13 | if($Page = $PageRepository->find($param)) { 14 | HTTP::redirect(Application::getEntityURL($Page)); 15 | } 16 | } 17 | } 18 | 19 | else { 20 | if(!$Page = $PageRepository->find($param)) { 21 | if($Page = $PageRepository->findBy('slug', $param)) { 22 | HTTP::redirect(Application::getEntityURL($Page)); 23 | } 24 | } 25 | } 26 | 27 | #=============================================================================== 28 | # Throw 404 error if page could not be found 29 | #=============================================================================== 30 | if(!isset($Page)) { 31 | Application::error404(); 32 | } 33 | 34 | #=============================================================================== 35 | # Generate template data 36 | #=============================================================================== 37 | $User = $UserRepository->find($Page->get('user')); 38 | $page_data = generateItemTemplateData($Page); 39 | $user_data = generateItemTemplateData($User); 40 | 41 | #=============================================================================== 42 | # Add template data for previous and next page 43 | #=============================================================================== 44 | if($PrevPage = $PageRepository->findPrev($Page)) { 45 | $page_data['PREV'] = generateItemTemplateData($PrevPage); 46 | } 47 | 48 | if($NextPage = $PageRepository->findNext($Page)) { 49 | $page_data['NEXT'] = generateItemTemplateData($NextPage); 50 | } 51 | 52 | #=============================================================================== 53 | # Build document 54 | #=============================================================================== 55 | $PageTemplate = Template\Factory::build('page/main'); 56 | $PageTemplate->set('PAGE', $page_data); 57 | $PageTemplate->set('USER', $user_data); 58 | 59 | $MainTemplate = Template\Factory::build('main'); 60 | $MainTemplate->set('TYPE', 'PAGE'); 61 | $MainTemplate->set('PAGE', $page_data); 62 | $MainTemplate->set('USER', $user_data); 63 | $MainTemplate->set('HTML', $PageTemplate); 64 | $MainTemplate->set('HEAD', [ 65 | 'NAME' => $page_data['ATTR']['NAME'], 66 | 'DESC' => description($page_data['BODY']['HTML'](), 67 | Application::get('PAGE.DESCRIPTION_SIZE')), 68 | 'PERM' => $page_data['URL'], 69 | 'OG_IMAGES' => $page_data['FILE']['LIST'] 70 | ]); 71 | 72 | echo $MainTemplate; 73 | -------------------------------------------------------------------------------- /core/include/post/list.php: -------------------------------------------------------------------------------- 1 | getCount(); 20 | $lastSite = ceil($count / $site_size); 21 | 22 | $currentSite = HTTP::GET('site') ?? 1; 23 | $currentSite = intval($currentSite); 24 | 25 | if($currentSite < 1 or ($currentSite > $lastSite and $lastSite > 0)) { 26 | Application::error404(); 27 | } 28 | 29 | #=============================================================================== 30 | # Single redirect 31 | #=============================================================================== 32 | if(Application::get('POST.REDIRECT_SINGLE') === true and $count === 1) { 33 | $Post = $PostRepository->getLast(); 34 | HTTP::redirect(Application::getEntityURL($Post)); 35 | } 36 | 37 | #=============================================================================== 38 | # Get paginated post list 39 | #=============================================================================== 40 | $posts = $PostRepository->getPaginated( 41 | $site_sort, 42 | $site_size, 43 | ($currentSite-1) * $site_size 44 | ); 45 | 46 | foreach($posts as $Post) { 47 | $User = $UserRepository->find($Post->get('user')); 48 | $templates[] = generatePostItemTemplate($Post, $User); 49 | } 50 | 51 | #=============================================================================== 52 | # Build document 53 | #=============================================================================== 54 | $ListTemplate = Template\Factory::build('post/list'); 55 | $ListTemplate->set('PAGINATION', [ 56 | 'THIS' => $currentSite, 57 | 'LAST' => $lastSite, 58 | 'HTML' => createPaginationTemplate( 59 | $currentSite, $lastSite, Application::getPostURL()) 60 | ]); 61 | $ListTemplate->set('LIST', [ 62 | 'POSTS' => $templates ?? [] 63 | ]); 64 | 65 | $MainTemplate = Template\Factory::build('main'); 66 | $MainTemplate->set('HTML', $ListTemplate); 67 | $MainTemplate->set('HEAD', [ 68 | 'NAME' => $Language->text('title_post_overview', $currentSite) 69 | ]); 70 | 71 | echo $MainTemplate; 72 | -------------------------------------------------------------------------------- /core/include/post/main.php: -------------------------------------------------------------------------------- 1 | findBy('slug', $param)) { 14 | if($Post = $PostRepository->find($param)) { 15 | HTTP::redirect(Application::getEntityURL($Post)); 16 | } 17 | } 18 | } 19 | 20 | else { 21 | if(!$Post = $PostRepository->find($param)) { 22 | if($Post = $PostRepository->findBy('slug', $param)) { 23 | HTTP::redirect(Application::getEntityURL($Post)); 24 | } 25 | } 26 | } 27 | 28 | #=============================================================================== 29 | # Throw 404 error if post could not be found 30 | #=============================================================================== 31 | if(!isset($Post)) { 32 | Application::error404(); 33 | } 34 | 35 | #=============================================================================== 36 | # Generate template data 37 | #=============================================================================== 38 | $User = $UserRepository->find($Post->get('user')); 39 | $post_data = generateItemTemplateData($Post); 40 | $user_data = generateItemTemplateData($User); 41 | 42 | #=============================================================================== 43 | # Add template data for previous and next post 44 | #=============================================================================== 45 | if($PrevPost = $PostRepository->findPrev($Post)) { 46 | $post_data['PREV'] = generateItemTemplateData($PrevPost); 47 | } 48 | 49 | if($NextPost = $PostRepository->findNext($Post)) { 50 | $post_data['NEXT'] = generateItemTemplateData($NextPost); 51 | } 52 | 53 | #=============================================================================== 54 | # Generate category template data (including parents) 55 | #=============================================================================== 56 | foreach($CategoryRepository->findWithParents($Post->get('category')) as $Category) { 57 | $category_list[] = generateItemTemplateData($Category); 58 | } 59 | 60 | #=============================================================================== 61 | # Define data variable for current category 62 | #=============================================================================== 63 | if(isset($category_list)) { 64 | $category_data = $category_list[array_key_last($category_list)]; 65 | } 66 | 67 | #=============================================================================== 68 | # Build document 69 | #=============================================================================== 70 | $PostTemplate = Template\Factory::build('post/main'); 71 | $PostTemplate->set('POST', $post_data); 72 | $PostTemplate->set('USER', $user_data); 73 | $PostTemplate->set('CATEGORY', $category_data ?? []); 74 | $PostTemplate->set('CATEGORIES', $category_list ?? []); 75 | 76 | $MainTemplate = Template\Factory::build('main'); 77 | $MainTemplate->set('TYPE', 'POST'); 78 | $MainTemplate->set('POST', $post_data); 79 | $MainTemplate->set('USER', $user_data); 80 | $MainTemplate->set('HTML', $PostTemplate); 81 | $MainTemplate->set('HEAD', [ 82 | 'NAME' => $post_data['ATTR']['NAME'], 83 | 'DESC' => description($post_data['BODY']['HTML'](), 84 | Application::get('POST.DESCRIPTION_SIZE')), 85 | 'PERM' => $post_data['URL'], 86 | 'OG_IMAGES' => $post_data['FILE']['LIST'] 87 | ]); 88 | 89 | echo $MainTemplate; 90 | -------------------------------------------------------------------------------- /core/include/search/main.php: -------------------------------------------------------------------------------- 1 | HTTP::GET('d'), 26 | 'month' => HTTP::GET('m'), 27 | 'year' => HTTP::GET('y') 28 | ]; 29 | 30 | try { 31 | if (!$posts = $PostRepository->search($search, $filter, $site_size, $offset)) { 32 | $message = $Language->text('search_no_results', htmlspecialchars($search)); 33 | } 34 | } catch(PDOException $Exception) { 35 | $message = $Exception->getMessage(); 36 | } 37 | } 38 | 39 | $form_data = [ 40 | 'SELECT' => [ 41 | 'D' => HTTP::GET('d'), 42 | 'M' => HTTP::GET('m'), 43 | 'Y' => HTTP::GET('y'), 44 | ], 45 | 'OPTIONS' => [ 46 | 'D' => $PostRepository->getDistinctDays(), 47 | 'M' => $PostRepository->getDistinctMonths(), 48 | 'Y' => $PostRepository->getDistinctYears(), 49 | ] 50 | ]; 51 | 52 | $search_data = [ 53 | 'TEXT' => $search, 54 | 'INFO' => isset($message) ? $message : false, 55 | ]; 56 | 57 | #=============================================================================== 58 | # Build document 59 | #=============================================================================== 60 | if(!empty($posts)) { 61 | foreach($posts as $Post) { 62 | $User = $UserRepository->find($Post->get('user')); 63 | $templates[] = generatePostItemTemplate($Post, $User); 64 | } 65 | 66 | $count = $PostRepository->getLastSearchOverallCount(); 67 | $last = ceil($count / $site_size); 68 | 69 | $ResultTemplate = Template\Factory::build('search/result'); 70 | $ResultTemplate->set('FORM', $form_data); 71 | $ResultTemplate->set('SEARCH', $search_data); 72 | $ResultTemplate->set('RESULT', [ 73 | 'LIST' => $templates ?? [] 74 | ]); 75 | 76 | $ResultTemplate->set('PAGINATION', [ 77 | 'THIS' => $currentSite, 78 | 'LAST' => $last, 79 | 'HTML' => createPaginationTemplate( 80 | $currentSite, $last, Application::getURL('search/') 81 | ) 82 | ]); 83 | 84 | $MainTemplate = Template\Factory::build('main'); 85 | $MainTemplate->set('HTML', $ResultTemplate); 86 | $MainTemplate->set('HEAD', [ 87 | 'NAME' => $Language->text('title_search_results', htmlspecialchars($search)), 88 | 'PERM' => Application::getURL('search/') 89 | ]); 90 | } 91 | 92 | else { 93 | $SearchTemplate = Template\Factory::build('search/main'); 94 | $SearchTemplate->set('FORM', $form_data); 95 | $SearchTemplate->set('SEARCH', $search_data); 96 | 97 | $MainTemplate = Template\Factory::build('main'); 98 | $MainTemplate->set('HTML', $SearchTemplate); 99 | $MainTemplate->set('HEAD', [ 100 | 'NAME' => $Language->text('title_search_request'), 101 | 'PERM' => Application::getURL('search/') 102 | ]); 103 | } 104 | 105 | echo $MainTemplate; 106 | -------------------------------------------------------------------------------- /core/include/user/list.php: -------------------------------------------------------------------------------- 1 | getCount(); 19 | $lastSite = ceil($count / $site_size); 20 | 21 | $currentSite = HTTP::GET('site') ?? 1; 22 | $currentSite = intval($currentSite); 23 | 24 | if($currentSite < 1 or ($currentSite > $lastSite and $lastSite > 0)) { 25 | Application::error404(); 26 | } 27 | 28 | #=============================================================================== 29 | # Single redirect 30 | #=============================================================================== 31 | if(Application::get('USER.REDIRECT_SINGLE') === true and $count === 1) { 32 | $User = $UserRepository->getLast(); 33 | HTTP::redirect(Application::getEntityURL($User)); 34 | } 35 | 36 | #=============================================================================== 37 | # Get paginated user list 38 | #=============================================================================== 39 | $users = $UserRepository->getPaginated( 40 | $site_sort, 41 | $site_size, 42 | ($currentSite-1) * $site_size 43 | ); 44 | 45 | foreach($users as $User) { 46 | $templates[] = generateUserItemTemplate($User); 47 | } 48 | 49 | #=============================================================================== 50 | # Build document 51 | #=============================================================================== 52 | $ListTemplate = Template\Factory::build('user/list'); 53 | $ListTemplate->set('PAGINATION', [ 54 | 'THIS' => $currentSite, 55 | 'LAST' => $lastSite, 56 | 'HTML' => createPaginationTemplate( 57 | $currentSite, $lastSite, Application::getUserURL() 58 | ) 59 | ]); 60 | $ListTemplate->set('LIST', [ 61 | 'USERS' => $templates ?? [] 62 | ]); 63 | 64 | $MainTemplate = Template\Factory::build('main'); 65 | $MainTemplate->set('HTML', $ListTemplate); 66 | $MainTemplate->set('HEAD', [ 67 | 'NAME' => $Language->text('title_user_overview', $currentSite) 68 | ]); 69 | 70 | echo $MainTemplate; 71 | -------------------------------------------------------------------------------- /core/include/user/main.php: -------------------------------------------------------------------------------- 1 | findBy('slug', $param)) { 12 | if($User = $UserRepository->find($param)) { 13 | HTTP::redirect(Application::getEntityURL($User)); 14 | } 15 | } 16 | } 17 | 18 | else { 19 | if(!$User = $UserRepository->find($param)) { 20 | if($User = $UserRepository->findBy('slug', $param)) { 21 | HTTP::redirect(Application::getEntityURL($User)); 22 | } 23 | } 24 | } 25 | 26 | #=============================================================================== 27 | # Throw 404 error if user could not be found 28 | #=============================================================================== 29 | if(!isset($User)) { 30 | Application::error404(); 31 | } 32 | 33 | #=============================================================================== 34 | # Generate template data 35 | #=============================================================================== 36 | $user_data = generateItemTemplateData($User); 37 | 38 | #=============================================================================== 39 | # Add template data for previous and next user 40 | #=============================================================================== 41 | if($PrevUser = $UserRepository->findPrev($User)) { 42 | $user_data['PREV'] = generateItemTemplateData($PrevUser); 43 | } 44 | 45 | if($NextUser = $UserRepository->findNext($User)) { 46 | $user_data['NEXT'] = generateItemTemplateData($NextUser); 47 | } 48 | 49 | #=============================================================================== 50 | # Build document 51 | #=============================================================================== 52 | $UserTemplate = Template\Factory::build('user/main'); 53 | $UserTemplate->set('USER', $user_data); 54 | $UserTemplate->set('COUNT', [ 55 | 'PAGE' => $UserRepository->getNumberOfPages($User), 56 | 'POST' => $UserRepository->getNumberOfPosts($User) 57 | ]); 58 | 59 | $MainTemplate = Template\Factory::build('main'); 60 | $MainTemplate->set('TYPE', 'USER'); 61 | $MainTemplate->set('USER', $user_data); 62 | $MainTemplate->set('HTML', $UserTemplate); 63 | $MainTemplate->set('HEAD', [ 64 | 'NAME' => $user_data['ATTR']['FULLNAME'], 65 | 'DESC' => description($user_data['BODY']['HTML'](), 66 | Application::get('USER.DESCRIPTION_SIZE')), 67 | 'PERM' => $user_data['URL'], 68 | 'OG_IMAGES' => $user_data['FILE']['LIST'] 69 | ]); 70 | 71 | echo $MainTemplate; 72 | -------------------------------------------------------------------------------- /core/migrations.php: -------------------------------------------------------------------------------- 1 | isMigrationNeeded()) { 11 | if(session_status() !== PHP_SESSION_ACTIVE) { 12 | session_start(); 13 | } 14 | 15 | Application::set('TEMPLATE.NAME', Application::get('ADMIN.TEMPLATE')); 16 | Application::set('TEMPLATE.LANG', Application::get('ADMIN.LANGUAGE')); 17 | 18 | if(HTTP::issetPOST(['token' => Application::getSecurityToken()], 'run')) { 19 | if(!$migrated = $Migrator->runMigrations()) { 20 | Application::exit('CONFUSED: No migrations were performed?!'); 21 | } 22 | } 23 | 24 | $Template = Template\Factory::build('migration'); 25 | $Template->set('MIGRATION', [ 26 | 'LIST' => $Migrator->getMigrations(), 27 | 'SUCCESSFUL' => $migrated ?? [], 28 | 'SCHEMA_VERSION' => [ 29 | 'DATABASE' => $Migrator->getVersionFromTable(), 30 | 'CODEBASE' => $Migrator::CURRENT_SCHEMA_VERSION 31 | ], 32 | ]); 33 | 34 | Application::exit($Template); 35 | } 36 | 37 | #=============================================================================== 38 | # Check for an unsupported downgrade attempt 39 | #=============================================================================== 40 | else if($Migrator->isDowngradeAttempt()) { 41 | throw new Exception('MIGRATOR: The schema version used by *your* database is 42 | higher than the schema version defined in the codebase. It is officially 43 | not supported to automatically downgrade the database schema version!'); 44 | } 45 | -------------------------------------------------------------------------------- /core/namespace/Database.php: -------------------------------------------------------------------------------- 1 | code = $code; 8 | } 9 | 10 | #=============================================================================== 11 | # Return the language code 12 | #=============================================================================== 13 | public function getCode() { 14 | return $this->code; 15 | } 16 | 17 | #=============================================================================== 18 | # Load another language file 19 | #=============================================================================== 20 | public function load($filename) { 21 | if(file_exists($filename) and is_readable($filename)) { 22 | require $filename; 23 | $this->text = array_merge($this->text, $LANGUAGE ?? []); 24 | } 25 | } 26 | 27 | #=============================================================================== 28 | # Set language string 29 | #=============================================================================== 30 | public function set($name, $value) { 31 | return $this->text[$name] = $value; 32 | } 33 | 34 | #=============================================================================== 35 | # Return language string with included arguments 36 | #=============================================================================== 37 | public function text($name, $arguments = null): string { 38 | if(!isset($this->text[$name])) { 39 | return "{{$name}}"; 40 | } 41 | 42 | return vsprintf($this->text[$name], (array) $arguments); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /core/namespace/ORM/Entities/Category.php: -------------------------------------------------------------------------------- 1 | {$attribute} ?? null; 17 | } 18 | 19 | #=============================================================================== 20 | # Set attribute 21 | #=============================================================================== 22 | public function set(string $attribute, $value): void { 23 | if($this->{$attribute} !== $value) { 24 | $this->{$attribute} = $value; 25 | !in_array($attribute, $this->_modified) && 26 | array_push($this->_modified, $attribute); 27 | } 28 | } 29 | 30 | #=============================================================================== 31 | # Return ID 32 | #=============================================================================== 33 | final public function getID(): int { 34 | return $this->id; 35 | } 36 | 37 | #=============================================================================== 38 | # Get all attributes 39 | #=============================================================================== 40 | public function getAll(array $exclude = []): array { 41 | $attributes = get_object_vars($this); 42 | $exclude = array_merge($exclude, ['_modified']); 43 | 44 | return array_filter($attributes, function($attribute) use($exclude) { 45 | return !in_array($attribute, $exclude); 46 | }, ARRAY_FILTER_USE_KEY); 47 | } 48 | 49 | #=============================================================================== 50 | # Get an array of modified attribute keys 51 | #=============================================================================== 52 | public function getModifiedKeys(): array { 53 | return $this->_modified; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /core/namespace/ORM/EntityInterface.php: -------------------------------------------------------------------------------- 1 | Database->prepare($query); 18 | $Statement->execute([$User->getID()]); 19 | 20 | return $Statement->fetchColumn(); 21 | } 22 | 23 | #=============================================================================== 24 | # Get number of *posts* assigned to $User 25 | #=============================================================================== 26 | public function getNumberOfPosts(User $User): int { 27 | $query = 'SELECT COUNT(id) FROM %s WHERE user = ?'; 28 | $query = sprintf($query, PostRepository::getTableName()); 29 | 30 | $Statement = $this->Database->prepare($query); 31 | $Statement->execute([$User->getID()]); 32 | 33 | return $Statement->fetchColumn(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /core/namespace/ORM/RepositorySearch.php: -------------------------------------------------------------------------------- 1 | Database->prepare($query); 48 | $Statement->execute(array_merge($params ?? [], [$search])); 49 | 50 | if($entities = $this->fetchEntities($Statement)) { 51 | # Temporary (maybe crappy) solution to prevent a second count query. 52 | # Virtual column "_count" does not belong into the entities. 53 | $this->lastSearchOverallCount = $entities[0]->get('_count'); 54 | } 55 | 56 | return $entities; 57 | } 58 | 59 | #=============================================================================== 60 | # Get the number of overall results for the last performed search 61 | #=============================================================================== 62 | public function getLastSearchOverallCount(): int { 63 | return $this->lastSearchOverallCount; 64 | } 65 | 66 | #=============================================================================== 67 | # Get a list of distinct days 68 | #=============================================================================== 69 | public function getDistinctDays(): array { 70 | $query = 'SELECT DISTINCT DAY(time_insert) AS d FROM %s ORDER BY d'; 71 | $query = sprintf($query, static::getTableName()); 72 | 73 | $Statement = $this->Database->query($query); 74 | 75 | if($result = $Statement->fetchAll($this->Database::FETCH_COLUMN)) { 76 | return $result; 77 | } 78 | 79 | return []; 80 | } 81 | 82 | #=============================================================================== 83 | # Get a list of distinct months 84 | #=============================================================================== 85 | public function getDistinctMonths(): array { 86 | $query = 'SELECT DISTINCT MONTH(time_insert) AS m FROM %s ORDER BY m'; 87 | $query = sprintf($query, static::getTableName()); 88 | 89 | $Statement = $this->Database->query($query); 90 | 91 | if($result = $Statement->fetchAll($this->Database::FETCH_COLUMN)) { 92 | return $result; 93 | } 94 | 95 | return []; 96 | } 97 | 98 | #=============================================================================== 99 | # Get a list of distinct years 100 | #=============================================================================== 101 | public function getDistinctYears(): array { 102 | $query = 'SELECT DISTINCT YEAR(time_insert) AS y FROM %s ORDER BY y'; 103 | $query = sprintf($query, static::getTableName()); 104 | 105 | $Statement = $this->Database->query($query); 106 | 107 | if($result = $Statement->fetchAll($this->Database::FETCH_COLUMN)) { 108 | return $result; 109 | } 110 | 111 | return []; 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /core/namespace/Parsedown.patch: -------------------------------------------------------------------------------- 1 | 160,176d159 2 | < if (strpos($line, "\t") !== false) 3 | < { 4 | < $parts = explode("\t", $line); 5 | < 6 | < $line = $parts[0]; 7 | < 8 | < unset($parts[0]); 9 | < 10 | < foreach ($parts as $part) 11 | < { 12 | < $shortage = 4 - mb_strlen($line, 'utf-8') % 4; 13 | < 14 | < $line .= str_repeat(' ', $shortage); 15 | < $line .= $part; 16 | < } 17 | < } 18 | < 19 | 327c310,313 20 | < if ($Line['indent'] >= 4) 21 | --- 22 | > $conditionA = $Line['indent'] >= 4; 23 | > $conditionB = substr($Line['body'], 0, 1) === "\t"; 24 | > 25 | > if (($conditionA and $remove = 4) or ($conditionB and $remove = 1)) 26 | 329c315 27 | < $text = substr($Line['body'], 4); 28 | --- 29 | > $text = substr($Line['body'], $remove); 30 | 348c334,337 31 | < if ($Line['indent'] >= 4) 32 | --- 33 | > $conditionA = $Line['indent'] >= 4; 34 | > $conditionB = substr($Line['body'], 0, 1) === "\t"; 35 | > 36 | > if (($conditionA and $remove = 4) or ($conditionB and $remove = 1)) 37 | 359c348 38 | < $text = substr($Line['body'], 4); 39 | --- 40 | > $text = substr($Line['body'], $remove); 41 | -------------------------------------------------------------------------------- /core/namespace/Parsers/ArgumentParser.php: -------------------------------------------------------------------------------- 1 | Language = Application::getLanguage(); 13 | } 14 | 15 | #=========================================================================== 16 | # Get emoticons with their explanations 17 | #=========================================================================== 18 | public function getEmoticons(): array { 19 | $Language = $this->Language; 20 | 21 | return [ 22 | html_entity_decode('😊') => $Language->text('emoticon_1F60A'), 23 | html_entity_decode('😞') => $Language->text('emoticon_1F61E'), 24 | html_entity_decode('😃') => $Language->text('emoticon_1F603'), 25 | html_entity_decode('😛') => $Language->text('emoticon_1F61B'), 26 | html_entity_decode('😲') => $Language->text('emoticon_1F632'), 27 | html_entity_decode('😉') => $Language->text('emoticon_1F609'), 28 | html_entity_decode('😢') => $Language->text('emoticon_1F622'), 29 | html_entity_decode('😐') => $Language->text('emoticon_1F610'), 30 | html_entity_decode('😵') => $Language->text('emoticon_1F635'), 31 | html_entity_decode('😒') => $Language->text('emoticon_1F612'), 32 | html_entity_decode('😎') => $Language->text('emoticon_1F60E'), 33 | html_entity_decode('😟') => $Language->text('emoticon_1F61F'), 34 | html_entity_decode('😂') => $Language->text('emoticon_1F602'), 35 | html_entity_decode('😄') => $Language->text('emoticon_1F604'), 36 | ]; 37 | } 38 | 39 | #=========================================================================== 40 | # Parse occurring emoticons (*without* duplicates) 41 | #=========================================================================== 42 | public function parse(string $text): array { 43 | $emoticon_data = $this->getEmoticons(); 44 | $emoticon_list = array_keys($emoticon_data); 45 | $emoticon_list = implode('|', $emoticon_list); 46 | 47 | preg_match_all("#($emoticon_list)#", $text, $matches); 48 | 49 | foreach($matches[1] as $emoticon) { 50 | $emoticons[$emoticon] = $emoticon_data[$emoticon]; 51 | } 52 | 53 | return $emoticons ?? []; 54 | } 55 | 56 | #=========================================================================== 57 | # Wrap emoticons inside a titled span element 58 | #=========================================================================== 59 | public function transform(string $text): string { 60 | $emoticon_data = $this->getEmoticons(); 61 | $emoticon_list = array_keys($emoticon_data); 62 | $emoticon_list = implode('|', $emoticon_list); 63 | 64 | # TODO: Do not wrap emoticons if they occur inside a code block 65 | return preg_replace_callback("#($emoticon_list)#", function($matches) 66 | use($emoticon_data) { 67 | $emoticon = $matches[1]; 68 | $explanation = $emoticon_data[$emoticon]; 69 | return sprintf('%s', $explanation, $emoticon); 70 | }, $text); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /core/namespace/Parsers/MarkdownParser.php: -------------------------------------------------------------------------------- 1 | Parsedown = new Parsedown(); 13 | $this->Parsedown->setUrlsLinked(false); 14 | } 15 | 16 | #=========================================================================== 17 | # Parse Markdown (currently only images) 18 | #=========================================================================== 19 | public function parse(string $text): array { 20 | $image = '#\!\[(.*)\]\((.*)(?:\s[\'"](.*)[\'"])?\)#U'; 21 | 22 | if(preg_match_all($image, $text, $matches)) { 23 | $data['img']['src'] = $matches[2]; 24 | $data['img']['alt'] = $matches[1]; 25 | $data['img']['title'] = $matches[3]; 26 | } 27 | 28 | return $data ?? []; 29 | } 30 | 31 | #=========================================================================== 32 | # Transform Markdown to HTML 33 | #=========================================================================== 34 | public function transform(string $text): string { 35 | return $this->Parsedown->text($text); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /core/namespace/Parsers/ParserInterface.php: -------------------------------------------------------------------------------- 1 | 'route', 13 | 'pattern' => $pattern, 14 | 'callback' => $callback 15 | ]; 16 | } 17 | 18 | #=============================================================================== 19 | # Add redirect 20 | #=============================================================================== 21 | public static function addRedirect($pattern, $location, $code = 302) { 22 | $pattern = Application::get('PATHINFO.BASE').$pattern; 23 | 24 | return self::$routes[] = [ 25 | 'type' => 'redirect', 26 | 'code' => $code, 27 | 'pattern' => $pattern, 28 | 'location' => $location 29 | ]; 30 | } 31 | 32 | #=============================================================================== 33 | # Execute routing 34 | #=============================================================================== 35 | public static function execute($path) { 36 | $path = ltrim($path, '/'); 37 | $route_found = false; 38 | 39 | foreach(self::$routes as $route) { 40 | if($route['type'] === 'redirect') { 41 | $location = preg_replace("#^{$route['pattern']}$#", $route['location'], $path, -1, $count); 42 | 43 | if($count) { 44 | HTTP::redirect($location, $route['code']); 45 | } 46 | } 47 | 48 | else { 49 | if(preg_match("#^{$route['pattern']}$#", $path, $matches)) { 50 | # Remove the first element from matches which contains the whole string. 51 | array_shift($matches); 52 | 53 | $route_found = true; 54 | call_user_func_array($route['callback'], $matches); 55 | } 56 | } 57 | } 58 | 59 | if($route_found === false) { 60 | Application::error404(); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /core/namespace/Template/Exception.php: -------------------------------------------------------------------------------- 1 | set('Language', \Application::getLanguage()); 8 | $Template->set('BLOGMETA', [ 9 | 'NAME' => \Application::get('BLOGMETA.NAME'), 10 | 'DESC' => \Application::get('BLOGMETA.DESC'), 11 | 'MAIL' => \Application::get('BLOGMETA.MAIL'), 12 | 'LANG' => \Application::get('BLOGMETA.LANG'), 13 | ]); 14 | 15 | return $Template; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /core/namespace/Template/Template.php: -------------------------------------------------------------------------------- 1 | filename = $filename; 13 | 14 | if(!file_exists($filename)) { 15 | throw new Exception("Template file \"{$filename}\" does not exist."); 16 | } 17 | } 18 | 19 | #=============================================================================== 20 | # Set parameter 21 | #=============================================================================== 22 | public function set($name, $value) { 23 | return $this->parameters[$name] = $value; 24 | } 25 | 26 | #=============================================================================== 27 | # Get parameter 28 | #=============================================================================== 29 | public function get($name) { 30 | return $this->parameters[$name] ?? null; 31 | } 32 | 33 | #=============================================================================== 34 | # Return HTML 35 | #=============================================================================== 36 | public function __toString() { 37 | extract($this->parameters); 38 | 39 | ob_start(); 40 | require $this->filename; 41 | return ob_get_clean(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /core/ws-apache.conf: -------------------------------------------------------------------------------- 1 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 2 | # Apache configuration [Thomas Lange ] # 3 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 4 | # # 5 | # This file contains the configuration rules for the Apache HTTP server. It is # 6 | # recommended to include these rules directly into the Apache configuration! # 7 | # # 8 | # Additionally, it's recommended to ensure that the AllowOverride directive is # 9 | # disabled if these rules are included in the Apache configuration. Otherwise, # 10 | # the Apache HTTP server is checking for .htaccess files on every request. # 11 | # # 12 | # AllowOverride None # 13 | # # 14 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 15 | 16 | #=============================================================================== 17 | # Error pages 18 | #=============================================================================== 19 | ErrorDocument 403 /403.php 20 | ErrorDocument 404 /404.php 21 | 22 | #=============================================================================== 23 | # Enable RewriteEngine 24 | #=============================================================================== 25 | RewriteEngine On 26 | 27 | #=============================================================================== 28 | # Forbidden directories 29 | #=============================================================================== 30 | RewriteRule ^(.git|core|theme/([^/]+)/(html|lang))/ - [F] 31 | 32 | #=============================================================================== 33 | # Pass requests to index.php 34 | #=============================================================================== 35 | RewriteCond %{REQUEST_FILENAME} !-f 36 | RewriteCond %{REQUEST_FILENAME} !-d 37 | RewriteRule . index.php [L] 38 | 39 | #=============================================================================== 40 | # Redirect from old to new global static dir 41 | #=============================================================================== 42 | #Redirect 301 /rsrc/ /static/ 43 | -------------------------------------------------------------------------------- /core/ws-nginx.conf: -------------------------------------------------------------------------------- 1 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 2 | # nginx configuration [Thomas Lange ] # 3 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 4 | # # 5 | # This file contains the configuration from the Apaches .htaccess file written # 6 | # for the nginx high performance web server. Put the content of this file into # 7 | # the "server {}" block of your nginx virtual host configuration file. If your # 8 | # blog is installed in a sub directory, you might need to adjust this rules! # 9 | # # 10 | # How to setup PHP and passing requests via FastCGI to PHP-FPM is your job. If # 11 | # you encounter a "403 Forbidden" error on the home page, please make sure you # 12 | # have configured your nginx virtual host to look for an index.php file: # 13 | # # 14 | # index index.php [...]; # 15 | # # 16 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 17 | 18 | #=============================================================================== 19 | # Error pages 20 | #=============================================================================== 21 | error_page 403 /403.php; 22 | error_page 404 /404.php; 23 | 24 | #=============================================================================== 25 | # Forbidden directories 26 | #=============================================================================== 27 | location ~ ^/(.git|core|theme/([^/]+)/(html|lang))/ { 28 | return 403; 29 | } 30 | 31 | #=============================================================================== 32 | # Pass requests to index.php 33 | #=============================================================================== 34 | location / { 35 | try_files $uri $uri/ /index.php?$args; 36 | } 37 | 38 | #=============================================================================== 39 | # Redirect from old to new global static dir 40 | #=============================================================================== 41 | #rewrite ^/rsrc/(.*)$ /static/$1 permanent; 42 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | ] 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # PHP7 blogging application 2 | Easy blogging application written with PHP7! The application comes with a fulltext search functionality for posts and with customizable themes and languages. You can build your own theme if the default theme does not satisfy you. 3 | 4 | ![Default theme](https://nmnd.de/file/p/github-blog/default-theme.png) 5 | 6 | ## Administration interface 7 | ![Administration interface](https://nmnd.de/file/p/github-blog/admin-template-2.png) 8 | 9 | ## Content editor 10 | ![Content editor](https://nmnd.de/file/p/github-blog/admin-template-1.png) 11 | 12 | ## Requirements 13 | * PHP version `>= 7.3`! 14 | * MariaDB version `>= 10.2.2` or MySQL version `>= 8.0`! 15 | 16 | ## Installation 17 | 1. Clone the repository to the target directory (usually your *document root*). (Alternatively you also can download a specific release as ZIP archive and extract it to the target destination and skip step 2.) 18 | 2. Check out the latest tag (or the tag you wish) by running `git tag -l` and `git checkout `. If you wish to get the newest code and features which are not yet included in a release tag, you can use the `master` branch. 19 | 3. Create your MariaDB/MySQL database and import `core/db/database.sql`. 20 | 4. Copy `core/configuration-example.php` to `core/configuration.php` and customize the configuration and set in any case the settings for the database connection. 21 | 5. Configure your web server. **For nginx**, look at `core/ws-nginx.conf`; **for Apache**, look at `core/ws-apache.conf`. (You can copy `core/ws-apache.conf` to `.htaccess` if you want to.) 22 | 6. Navigate your browser to `/admin/auth.php` and authenticate with the default username `ChangeMe` and the password `changeme` (please note that the username is case-sensitive). 23 | 24 | ## Documentation 25 | You can find more information about the configuration and customization in the wiki: 26 | 27 | * [GitHub](https://github.com/Nerdmind/Blog/wiki) 28 | * [Mirror](https://code.nerdmind.de/blog/wiki/) 29 | -------------------------------------------------------------------------------- /theme/admin/html/403.php: -------------------------------------------------------------------------------- 1 |
2 |

text('403_heading_text')?>

3 |

text('403_heading_desc')?>

4 |
5 | -------------------------------------------------------------------------------- /theme/admin/html/404.php: -------------------------------------------------------------------------------- 1 |
2 |

text('404_heading_text')?>

3 |

text('404_heading_desc')?>

4 |
5 | -------------------------------------------------------------------------------- /theme/admin/html/auth.php: -------------------------------------------------------------------------------- 1 |
2 |

text('authentication_text')?>

3 |

text('authentication_desc')?>

4 | 5 | 6 |
7 |
    8 | 9 |
  • 10 | 11 |
12 |
13 | 14 | 15 |
16 | 17 | 18 |
19 | 21 | 22 |
23 | 24 |
25 | 26 | 28 | 29 |
30 | 31 |
32 |
33 | 34 |
35 | 36 |
37 |
38 |
39 | -------------------------------------------------------------------------------- /theme/admin/html/category/delete.php: -------------------------------------------------------------------------------- 1 |
2 |

text('delete_category')?>

3 |

text('delete_category_desc')?>

4 | 5 | 6 |
7 | -------------------------------------------------------------------------------- /theme/admin/html/category/index.php: -------------------------------------------------------------------------------- 1 |
2 |

text('category_overview')?>

3 |

text('overview_category_desc')?>

4 | 7 | 8 |
9 | 10 | 11 | 12 |
13 | 14 | 15 |
16 | -------------------------------------------------------------------------------- /theme/admin/html/category/insert.php: -------------------------------------------------------------------------------- 1 |
2 |

text('insert_category')?>

3 |

text('insert_category_desc')?>

4 | 5 | 6 |
7 | -------------------------------------------------------------------------------- /theme/admin/html/category/item.php: -------------------------------------------------------------------------------- 1 | 46 | -------------------------------------------------------------------------------- /theme/admin/html/category/update.php: -------------------------------------------------------------------------------- 1 |
2 |

3 | # 4 | text('update_category')?> 5 |

6 |

text('update_category_desc')?>

7 | 11 | 12 | 13 |
14 | -------------------------------------------------------------------------------- /theme/admin/html/database.php: -------------------------------------------------------------------------------- 1 |
2 |

text('overview_database_text')?>

3 |

text('overview_database_desc')?>

4 | 5 | 6 |
7 |
    8 | 9 |
  • 10 | 11 |
12 |
13 | 14 | 15 |
16 | 17 | 18 |
19 | 20 |
21 | 22 | 23 |
24 |
25 |
26 | 27 | 28 |
29 | 30 |
31 |
32 |
33 | -------------------------------------------------------------------------------- /theme/admin/html/home.php: -------------------------------------------------------------------------------- 1 |
2 |

text('overview_dashboard_text')?>

3 |

text('overview_dashboard_desc')?>

4 | 5 |

text('last_post')?>

6 |

7 | text('posts')?>: 8 | | text('insert')?> 9 | | text('search')?> 10 |

11 | 12 |
13 | 14 |
15 | 16 |

text('home_no_posts')?>

17 | 18 | 19 |

text('last_page')?>

20 |

21 | text('pages')?>: 22 | | text('insert')?> 23 | | text('search')?> 24 |

25 | 26 | 27 |
28 | 29 |
30 | 31 |

text('home_no_pages')?>

32 | 33 | 34 |

text('last_user')?>

35 |

36 | text('users')?>: 37 | | text('insert')?> 38 |

39 | 40 | 41 |
42 | 43 |
44 | 45 |

text('home_no_users')?>

46 | 47 |
48 | -------------------------------------------------------------------------------- /theme/admin/html/main.php: -------------------------------------------------------------------------------- 1 | '/', 'samesite' => 'Lax']; 4 | 5 | if($toogle === 'dark') { 6 | $_COOKIE['dark_mode'] = true; 7 | setcookie('dark_mode', true, $options); 8 | } else { 9 | unset($_COOKIE['dark_mode']); 10 | setcookie('dark_mode', null, array_merge($options, ['expires' => -1])); 11 | } 12 | } 13 | 14 | $theme = isset($_COOKIE['dark_mode']) ? 'dark' : 'bright'; 15 | ?> 16 | 17 | 18 | 19 | 20 | 21 | 22 | "> 23 | 24 | <?=escapeHTML($NAME)?> | Administration 25 | 26 | 27 |
28 |
29 |
30 | 31 | 32 | 33 |
34 |
35 |
36 |
37 |
38 | 55 |
56 |
57 | 58 | 59 | 60 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /theme/admin/html/migration.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | "> 9 | <?=$Language->text('maintenance_mode')?> 10 | 11 | 12 |
13 |
14 |
15 | 16 |
17 |
text('maintenance_mode')?>
18 |
19 |
20 |
21 | 26 |
27 |

text('maintenance_mode')?>

28 | 29 |

text('migration_successful')?>

30 |
    31 | 32 |
  • Migration
  • 33 | 34 |
35 | 36 |

text("migration_upgrade", [$database_schema, $codebase_schema])?>

37 |
38 |
    39 | $commands): ?> 40 |
  • 41 |

    Migration

    42 |

    text('migration_notice', [$migration-1, $migration])?>

    43 |
    44 |
  • 45 | 46 |
47 | 48 | 49 |
50 | 51 |
52 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /theme/admin/html/page/delete.php: -------------------------------------------------------------------------------- 1 |
2 |

text('delete_page')?>

3 |

text('delete_page_desc')?>

4 | 5 | 6 |
7 | -------------------------------------------------------------------------------- /theme/admin/html/page/index.php: -------------------------------------------------------------------------------- 1 |
2 |

text('page_overview')?>

3 |

text('overview_page_desc')?>

4 | 8 | 9 |
10 | 11 | 12 | 13 |
14 | 15 | 16 |
17 | -------------------------------------------------------------------------------- /theme/admin/html/page/insert.php: -------------------------------------------------------------------------------- 1 |
2 |

text('insert_page')?>

3 |

text('insert_page_desc')?>

4 | 5 | 6 |
7 | -------------------------------------------------------------------------------- /theme/admin/html/page/item.php: -------------------------------------------------------------------------------- 1 | 41 | -------------------------------------------------------------------------------- /theme/admin/html/page/search.php: -------------------------------------------------------------------------------- 1 |
> 2 |

text('title_page_search')?>

3 |

text('search_page_desc')?>

4 | 5 | 6 |
7 |
    8 | 9 |
  • 10 | 11 |
12 |
13 | 14 | 15 |
16 |
17 | 19 | 20 |
21 | 22 |
23 |
24 |
25 | 26 |
27 |
28 | 29 |
30 | 31 | 32 | 33 |
34 | 35 | 36 | 37 | 38 |
39 | -------------------------------------------------------------------------------- /theme/admin/html/page/update.php: -------------------------------------------------------------------------------- 1 |
2 |

3 | # 4 | text('update_page')?> 5 |

6 |

text('update_page_desc')?>

7 | 11 | 12 | 13 |
14 | -------------------------------------------------------------------------------- /theme/admin/html/pagination.php: -------------------------------------------------------------------------------- 1 | 31 | -------------------------------------------------------------------------------- /theme/admin/html/post/delete.php: -------------------------------------------------------------------------------- 1 |
2 |

text('delete_post')?>

3 |

text('delete_post_desc')?>

4 | 5 | 6 |
7 | -------------------------------------------------------------------------------- /theme/admin/html/post/index.php: -------------------------------------------------------------------------------- 1 |
2 |

text('post_overview')?>

3 |

text('overview_post_desc')?>

4 | 8 | 9 |
10 | 11 | 12 | 13 |
14 | 15 | 16 |
17 | -------------------------------------------------------------------------------- /theme/admin/html/post/insert.php: -------------------------------------------------------------------------------- 1 |
2 |

text('insert_post')?>

3 |

text('insert_post_desc')?>

4 | 5 | 6 |
7 | -------------------------------------------------------------------------------- /theme/admin/html/post/item.php: -------------------------------------------------------------------------------- 1 | 47 | -------------------------------------------------------------------------------- /theme/admin/html/post/search.php: -------------------------------------------------------------------------------- 1 | %s%s [%d]'; 5 | $select = ($category['ID'] == $selected) ? ' selected' : ''; 6 | 7 | printf($option, $category['ID'], $select, $prefix, escapeHTML($category['NAME']), $category['ID']); 8 | 9 | if(isset($category['CHILDS'])) { 10 | # If there are children, call self and pass children array. 11 | (__FUNCTION__)($category['CHILDS'], $selected, $prefix.'– '); 12 | } 13 | } 14 | } 15 | ?> 16 |
> 17 |

text('title_post_search')?>

18 |

text('search_post_desc')?>

19 | 20 | 21 |
22 |
    23 | 24 |
  • 25 | 26 |
27 |
28 | 29 | 30 |
31 |
32 | 34 | 35 |
36 | 37 |
38 | 39 | 41 | 42 |
43 | 47 |
48 | 49 | 51 | 52 |
53 | 59 |
60 |
61 |
62 | 63 |
64 |
65 | 66 |
67 | 68 | 69 | 70 |
71 | 72 | 73 | 74 | 75 |
76 | -------------------------------------------------------------------------------- /theme/admin/html/post/update.php: -------------------------------------------------------------------------------- 1 |
2 |

3 | # 4 | text('update_post')?> 5 |

6 |

text('update_post_desc')?>

7 | 11 | 12 | 13 |
14 | -------------------------------------------------------------------------------- /theme/admin/html/user/delete.php: -------------------------------------------------------------------------------- 1 |
2 |

text('delete_user')?>

3 |

text('delete_user_desc')?>

4 | 5 |

text('delete_user_warning')?>

6 | 7 | 8 |
9 | -------------------------------------------------------------------------------- /theme/admin/html/user/index.php: -------------------------------------------------------------------------------- 1 |
2 |

text('user_overview')?>

3 |

text('overview_user_desc')?>

4 | 7 | 8 |
9 | 10 | 11 | 12 |
13 | 14 | 15 |
16 | -------------------------------------------------------------------------------- /theme/admin/html/user/insert.php: -------------------------------------------------------------------------------- 1 |
2 |

text('insert_user')?>

3 |

text('insert_user_desc')?>

4 | 5 | 6 |
7 | -------------------------------------------------------------------------------- /theme/admin/html/user/item.php: -------------------------------------------------------------------------------- 1 | 45 | -------------------------------------------------------------------------------- /theme/admin/html/user/update.php: -------------------------------------------------------------------------------- 1 |
2 |

3 | # 4 | text('update_user')?> 5 |

6 |

text('update_user_desc')?>

7 | 11 | 12 | 13 |
14 | -------------------------------------------------------------------------------- /theme/admin/static/css/bright.scss: -------------------------------------------------------------------------------- 1 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 | # Content background and border color 3 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 4 | $htmlBackground: url("../img/noise-bright.png") #DDD; 5 | $backgroundColor: #FFF; 6 | $backgroundColorEmphasize: #EEE; 7 | $borderColor: #AAA; 8 | 9 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 10 | # Header and navigation 11 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 12 | $headerBarTextColor: #333; 13 | $headerBarBackgroundColor: #5E819F; 14 | $navigationLinkBackgroundColor: #DDD; 15 | $navigationLinkFocusedBackgroundColor: #CCC; 16 | 17 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 18 | # Text colors 19 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 20 | $textColor: #333; 21 | $textColorLight: #444; 22 | $textColorStrong: #000; 23 | $formElementTextColor: #404040; 24 | $codeTextColor: #008B45; 25 | $linkColor: #0060A0; 26 | $linkColorFocused: #CCC; 27 | $warningTextColor: #B03060; 28 | 29 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 30 | # Misc 31 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 32 | $itemLinkHoverBackgroundColor: #DDD; 33 | $paginationActiveBackgroundColor: #CCC; 34 | 35 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 36 | # Forms 37 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 38 | $formBackgroundColorEmphasize: #DDD; 39 | $formButtonBorderColor: #404040; 40 | $formButtonTextColor: #EEE; 41 | 42 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 43 | # Form buttons 44 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 45 | $insertButtonBackgroundColor: #4D8D5D; 46 | $updateButtonBackgroundColor: #6A8AA5; 47 | $deleteButtonBackgroundColor: #C45C66; 48 | 49 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 50 | # Information message box 51 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 52 | $messageListTextColor: #EEE; 53 | $messageListBackgroundColor: #C45C66; 54 | 55 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 56 | # Scrollbars 57 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 58 | $scrollbarColor: #A1A1A1; 59 | $scrollbarHoverColor: #888888; 60 | $scrollbarBackground: #E1E1E1; 61 | 62 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 63 | # Import stylesheet 64 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 65 | @import "import/styles"; 66 | 67 | #theme-toogle-bright { 68 | display: none; 69 | } 70 | -------------------------------------------------------------------------------- /theme/admin/static/css/dark.scss: -------------------------------------------------------------------------------- 1 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 | # Content background and border color 3 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 4 | $htmlBackground: url("../img/noise-dark.png") #3D434B; 5 | $backgroundColorEmphasize: #32373E; 6 | $backgroundColor: #3D434B; 7 | $borderColor: #1D232B; 8 | 9 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 10 | # Header and navigation 11 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 12 | $headerBarTextColor: #000; 13 | $headerBarBackgroundColor: #3B546A; 14 | $navigationLinkBackgroundColor: #2D333B; 15 | $navigationLinkFocusedBackgroundColor: #1D232B; 16 | 17 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 18 | # Text colors 19 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 20 | $textColor: #9DAAB7; 21 | $textColorLight: #8D9AA7; 22 | $textColorStrong: #CDDAE7; 23 | $formElementTextColor: #8D9AA7; 24 | $codeTextColor: #FFB830; 25 | $linkColor: #5EA4D3; 26 | $linkColorFocused: #42474E; 27 | $warningTextColor: #FFB830; 28 | 29 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 30 | # Misc 31 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 32 | $itemLinkHoverBackgroundColor: #42474E; 33 | $paginationActiveBackgroundColor: #42474E; 34 | 35 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 36 | # Forms 37 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 38 | $formBackgroundColorEmphasize: #4D535B; 39 | $formButtonBorderColor: #404040; 40 | $formButtonTextColor: #CCC; 41 | 42 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 43 | # Form buttons 44 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 45 | $insertButtonBackgroundColor: #396644; 46 | $updateButtonBackgroundColor: #597186; 47 | $deleteButtonBackgroundColor: #8F4F55; 48 | 49 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 50 | # Information message box 51 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 52 | $messageListTextColor: #BBB; 53 | $messageListBackgroundColor: #8C434A; 54 | 55 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 56 | # Scrollbars 57 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 58 | $scrollbarColor: #838994; 59 | $scrollbarHoverColor: #4C566A; 60 | $scrollbarBackground: #2E3440; 61 | 62 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 63 | # Import stylesheet 64 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 65 | @import "import/styles"; 66 | 67 | #theme-toogle-dark { 68 | display: none; 69 | } 70 | -------------------------------------------------------------------------------- /theme/admin/static/css/import/_fonts.scss: -------------------------------------------------------------------------------- 1 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 | # Font "Font Awesome" [4.7.0] (by Fontello): SIL Open Font License (OFL) 3 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 4 | @font-face { 5 | font-family: "Fontello"; 6 | font-weight: 400; 7 | font-style: normal; 8 | src: url("../font/fontello.woff2") format("woff2"); 9 | } 10 | 11 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 12 | # Font "Kadwa": SIL Open Font License (OFL) 13 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 14 | @font-face { 15 | font-family: "Kadwa"; 16 | font-weight: 400; 17 | src: url("../font/kadwa-n-400.woff2") format("woff2"); 18 | } 19 | 20 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 21 | # Font "Ruda": SIL Open Font License (OFL) 22 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 23 | @font-face { 24 | font-family: "Ruda"; 25 | font-weight: 400; 26 | src: url("../font/ruda-n-400.woff2") format("woff2"); 27 | } 28 | 29 | @font-face { 30 | font-family: "Ruda"; 31 | font-weight: 700; 32 | src: url("../font/ruda-n-700.woff2") format("woff2"); 33 | } 34 | -------------------------------------------------------------------------------- /theme/admin/static/css/import/_responsive.scss: -------------------------------------------------------------------------------- 1 | @media only screen and (max-width: 90em /*1440px*/) { 2 | .item-container.grid { 3 | grid-template-columns: 1fr 1fr; 4 | } 5 | } 6 | 7 | @media only screen and (min-width: 62.5em /*1000px*/) { 8 | #main-content { 9 | border: 0.05rem solid $borderColor; 10 | border-top: none; 11 | border-bottom: none; 12 | } 13 | } 14 | 15 | @media only screen and (max-width: 62.5em /*1000px*/) { 16 | .item-container.grid { 17 | grid-template-columns: 1fr; 18 | } 19 | } 20 | 21 | @media only screen and (max-width: 50em /*800px*/) { 22 | html { 23 | font-size: 1.125rem; /*18px*/ 24 | } 25 | } 26 | 27 | @media only screen and (max-width: 37.5em /*600px*/) { 28 | #main-content { 29 | padding: 0.5rem; 30 | } 31 | 32 | #main-navi { 33 | font-size: 1rem; 34 | 35 | ul { 36 | li { 37 | span { 38 | display: none; 39 | } 40 | 41 | .fa { 42 | margin-right: 0; 43 | } 44 | } 45 | } 46 | 47 | a { 48 | padding: 0.5rem; 49 | } 50 | } 51 | 52 | #emoticon-list-wrapper { 53 | display: none; 54 | } 55 | 56 | .item-container.grid { 57 | grid-column-gap: 0.75rem; 58 | grid-row-gap: 0.75rem; 59 | column-gap: 0.75rem; 60 | row-gap: 0.75rem; 61 | } 62 | 63 | .form-grid { 64 | grid-template-columns: 7rem 1fr; 65 | 66 | &-item, &-item.first, label { 67 | grid-column: unset; 68 | } 69 | } 70 | 71 | .actions { 72 | float: none; 73 | display: flex; 74 | width: 100%; 75 | flex-grow: 1; 76 | justify-content: center; 77 | overflow: hidden; 78 | box-sizing: border-box; 79 | 80 | &-before { 81 | float: none; 82 | } 83 | 84 | li { 85 | flex-grow: 1; 86 | 87 | + li { 88 | border-left: none; 89 | } 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /theme/admin/static/css/import/_variables.scss: -------------------------------------------------------------------------------- 1 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 | # Line height 3 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 4 | $lineHeight: 1.2rem; 5 | 6 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 7 | # Font families 8 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 9 | $fontFamily: "Ruda", "sans-serif"; 10 | $fontFamilyTextarea: "Kadwa", "sans-serif"; 11 | $fontFamilyMonospaced: "monospace"; 12 | 13 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 14 | # Text font sizes 15 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 16 | $fontSize: 0.7rem; 17 | $fontSizeSmall: $fontSize - 0.1rem; 18 | $fontSizeLarge: $fontSize + 0.1rem; 19 | 20 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 21 | # Heading font sizes 22 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 23 | $fontSizeH1: 0.80rem; 24 | $fontSizeH2: 0.70rem; 25 | $fontSizeH3: 0.65rem; 26 | 27 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 28 | # Content widths 29 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 30 | $contentWidth: 50rem; 31 | $contentWidthWide: 90rem; 32 | -------------------------------------------------------------------------------- /theme/admin/static/font/fontello.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nerdmind/Blog/31d7269f217f56b017d8e05a66caa2501212ed06/theme/admin/static/font/fontello.woff2 -------------------------------------------------------------------------------- /theme/admin/static/font/kadwa-n-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nerdmind/Blog/31d7269f217f56b017d8e05a66caa2501212ed06/theme/admin/static/font/kadwa-n-400.woff2 -------------------------------------------------------------------------------- /theme/admin/static/font/ruda-n-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nerdmind/Blog/31d7269f217f56b017d8e05a66caa2501212ed06/theme/admin/static/font/ruda-n-400.woff2 -------------------------------------------------------------------------------- /theme/admin/static/font/ruda-n-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nerdmind/Blog/31d7269f217f56b017d8e05a66caa2501212ed06/theme/admin/static/font/ruda-n-700.woff2 -------------------------------------------------------------------------------- /theme/admin/static/icon-public-domain.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /theme/admin/static/img/noise-bright.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nerdmind/Blog/31d7269f217f56b017d8e05a66caa2501212ed06/theme/admin/static/img/noise-bright.png -------------------------------------------------------------------------------- /theme/admin/static/img/noise-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nerdmind/Blog/31d7269f217f56b017d8e05a66caa2501212ed06/theme/admin/static/img/noise-dark.png -------------------------------------------------------------------------------- /theme/default/html/403.php: -------------------------------------------------------------------------------- 1 | ] # 4 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 5 | # # 6 | # [see documentation] # 7 | # # 8 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 9 | ?> 10 |

text('403_heading_text')?>

11 |

text('403_heading_desc')?>

12 | -------------------------------------------------------------------------------- /theme/default/html/404.php: -------------------------------------------------------------------------------- 1 | ] # 4 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 5 | # # 6 | # [see documentation] # 7 | # # 8 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 9 | ?> 10 |

text('404_heading_text')?>

11 |

text('404_heading_desc')?>

12 | -------------------------------------------------------------------------------- /theme/default/html/category/item.php: -------------------------------------------------------------------------------- 1 | ] # 4 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 5 | # # 6 | # [see documentation] # 7 | # # 8 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 9 | ?> 10 |
11 |
12 |

13 | 14 | 15 | 16 |

17 | 18 | text('posts')?>: – 19 | text('categories')?>: 20 | 21 |
22 | 23 |
24 | 25 |
26 | 27 |
28 | -------------------------------------------------------------------------------- /theme/default/html/category/list.php: -------------------------------------------------------------------------------- 1 | ] # 4 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 5 | # # 6 | # [see documentation] # 7 | # # 8 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 9 | ?> 10 |

text('category_overview')?>

11 |

text('category_list_title', $PAGINATION['THIS'])?>

12 | 13 | 14 |
15 | 16 | 17 | 18 |
19 | 20 |

text('category_list_empty')?>

21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /theme/default/html/category/main.php: -------------------------------------------------------------------------------- 1 | ] # 4 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 5 | # # 6 | # [see documentation] # 7 | # # 8 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 9 | ?> 10 |

11 | 12 |
    13 | 14 |
  • 15 | 16 |
17 | 18 | 19 |
20 | 21 |
22 | 23 | 24 |
25 | 26 | 27 | 28 |
29 | 30 | 31 |

text('posts')?>

32 |
text('category_posts_page', $PAGINATION['THIS'])?>
33 | 34 |
35 | 36 | 37 | 38 |
39 | 40 | 41 |
42 | text('category_empty')?> 43 |
44 | 45 | -------------------------------------------------------------------------------- /theme/default/html/feed/item.php: -------------------------------------------------------------------------------- 1 | ] # 4 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 5 | # # 6 | # [see documentation] # 7 | # # 8 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 9 | 10 | $HTML = $POST['BODY']['HTML'](); 11 | ?> 12 | 13 | <?=escapeHTML($POST['ATTR']['NAME'])?> 14 | 15 | 16 | 17 | 18 | 19 | 20 | 22 | ]]> 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /theme/default/html/feed/main.php: -------------------------------------------------------------------------------- 1 | ] # 4 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 5 | # # 6 | # [see documentation] # 7 | # # 8 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 9 | 10 | $title = escapeHTML($BLOGMETA['NAME']); 11 | $self = Application::getURL('feed/'); 12 | ?> 13 | '?> 14 | 16 | 17 | <?=$title?> 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | <?=$title?> 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /theme/default/html/home.php: -------------------------------------------------------------------------------- 1 | ] # 4 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 5 | # # 6 | # [see documentation] # 7 | # # 8 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 9 | ?> 10 |

text('home_heading_text', escapeHTML(Application::get('BLOGMETA.NAME')))?>Feed

11 |

text('home_heading_desc', Application::get('POST.LIST_SIZE'))?>

12 | 13 |
14 | 15 | 16 | 17 |
18 | 19 | 20 | -------------------------------------------------------------------------------- /theme/default/html/page/item.php: -------------------------------------------------------------------------------- 1 | ] # 4 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 5 | # # 6 | # [see documentation] # 7 | # # 8 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 9 | ?> 10 |
11 |
12 |

13 | 14 |

15 | 16 |
17 |
18 |

19 |
20 |
21 | -------------------------------------------------------------------------------- /theme/default/html/page/list.php: -------------------------------------------------------------------------------- 1 | ] # 4 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 5 | # # 6 | # [see documentation] # 7 | # # 8 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 9 | ?> 10 |

text('page_overview')?>

11 |

text('page_overview_heading_desc', $PAGINATION['THIS'])?>

12 | 13 |
14 | 15 | 16 | 17 |
18 | 19 | 20 | -------------------------------------------------------------------------------- /theme/default/html/page/main.php: -------------------------------------------------------------------------------- 1 | ] # 4 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 5 | # # 6 | # [see documentation] # 7 | # # 8 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 9 | 10 | $user = "{$USER['ATTR']['FULLNAME']}"; 11 | $time = ""; 12 | ?> 13 |

14 |

text('page_main_heading_desc', [$user, $time])?>

15 | 16 |
17 | 18 |
19 | 20 | 35 | -------------------------------------------------------------------------------- /theme/default/html/pagination.php: -------------------------------------------------------------------------------- 1 | ] # 4 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 5 | # # 6 | # [see documentation] # 7 | # # 8 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 9 | ?> 10 | 40 | -------------------------------------------------------------------------------- /theme/default/html/post/item.php: -------------------------------------------------------------------------------- 1 | ] # 4 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 5 | # # 6 | # [see documentation] # 7 | # # 8 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 9 | ?> 10 |
11 |
12 |

13 | 14 |

15 | 16 |
17 |
18 | 19 |
20 |
21 | -------------------------------------------------------------------------------- /theme/default/html/post/list.php: -------------------------------------------------------------------------------- 1 | ] # 4 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 5 | # # 6 | # [see documentation] # 7 | # # 8 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 9 | ?> 10 |

text('post_overview')?>Feed

11 |

text('post_overview_heading_desc', $PAGINATION['THIS'])?>

12 | 13 |
14 | 15 | 16 | 17 |
18 | 19 | 20 | -------------------------------------------------------------------------------- /theme/default/html/post/main.php: -------------------------------------------------------------------------------- 1 | ] # 4 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 5 | # # 6 | # [see documentation] # 7 | # # 8 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 9 | 10 | $user = "{$USER['ATTR']['FULLNAME']}"; 11 | $time = ""; 12 | ?> 13 |

14 |

text('post_main_heading_desc', [$user, $time])?>

15 | 16 |
17 | 18 |
19 | 20 | 21 |
    22 | 23 |
  • 24 | 25 |
26 | 27 | 28 | 43 | -------------------------------------------------------------------------------- /theme/default/html/search/main.php: -------------------------------------------------------------------------------- 1 |

text('search_base_heading_text')?>

2 |

text('search_base_heading_desc')?>

3 | 4 | 5 |
6 | 7 | 8 |
9 | 10 | 11 | 18 | 25 | 32 | 33 | 34 |
35 | -------------------------------------------------------------------------------- /theme/default/html/search/result.php: -------------------------------------------------------------------------------- 1 |

text('search_result_heading_text', escapeHTML($SEARCH['TEXT']))?>

2 |

text('search_result_heading_desc')?>

3 | 4 |
5 | 6 | 7 | 14 | 21 | 28 | 29 | 30 |
31 | 32 |
33 | 34 | 35 | 36 |
37 | 38 | 39 | -------------------------------------------------------------------------------- /theme/default/html/user/item.php: -------------------------------------------------------------------------------- 1 | ] # 4 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 5 | # # 6 | # [see documentation] # 7 | # # 8 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 9 | ?> 10 |
11 |
12 |

13 | 14 |

15 | 16 |
17 |
18 | 19 |
20 |
21 | -------------------------------------------------------------------------------- /theme/default/html/user/list.php: -------------------------------------------------------------------------------- 1 | ] # 4 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 5 | # # 6 | # [see documentation] # 7 | # # 8 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 9 | ?> 10 |

text('user_overview')?>

11 |

text('user_overview_heading_desc', $PAGINATION['THIS'])?>

12 | 13 |
14 | 15 | 16 | 17 |
18 | 19 | 20 | -------------------------------------------------------------------------------- /theme/default/html/user/main.php: -------------------------------------------------------------------------------- 1 | ] # 4 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 5 | # # 6 | # [see documentation] # 7 | # # 8 | #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# 9 | ?> 10 |

11 |

text('user_main_heading_desc', [escapeHTML($USER['ATTR']['USERNAME']), $COUNT['POST'], $COUNT['PAGE']])?>

12 | 13 |
14 | 15 |
16 | 17 | 32 | -------------------------------------------------------------------------------- /theme/default/static/css/import/_fonts.scss: -------------------------------------------------------------------------------- 1 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 | # Font "Font Awesome" [4.7.0] (by Fontello): SIL Open Font License (OFL) 3 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 4 | @font-face { 5 | font-family: "Fontello"; 6 | font-weight: 400; 7 | font-style: normal; 8 | src: url("../font/fontello.woff2") format("woff2"); 9 | } 10 | 11 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 12 | # Font "Ruda": SIL Open Font License (OFL) 13 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 14 | @font-face { 15 | font-family: "Ruda"; 16 | font-weight: 400; 17 | src: url("../font/ruda-n-400.woff2") format("woff2"); 18 | } 19 | 20 | @font-face { 21 | font-family: "Ruda"; 22 | font-weight: 700; 23 | src: url("../font/ruda-n-700.woff2") format("woff2"); 24 | } 25 | -------------------------------------------------------------------------------- /theme/default/static/css/import/_responsive.scss: -------------------------------------------------------------------------------- 1 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 | # Responsive Level #1 3 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 4 | @media only screen and (max-width: 50em) { 5 | html { 6 | font-size: 1.125rem; /*18px*/ 7 | background-image: none !important; 8 | } 9 | 10 | body { 11 | line-height: 1.2rem; 12 | } 13 | 14 | #container { 15 | margin: 0; 16 | border-right: none; 17 | border-left: none; 18 | } 19 | } 20 | 21 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 22 | # Responsive Level #2 23 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 24 | @media only screen and (max-width: 37.5em) { 25 | main, #main-header > div { 26 | padding: 1rem; 27 | } 28 | 29 | #main-navi { 30 | padding: 0.25rem 1rem; 31 | } 32 | 33 | #main-navi a { 34 | border: 0.05rem solid transparent; 35 | } 36 | 37 | #main-navi a:hover, #main-navi a:focus { 38 | border: 0.05rem solid #BBB; 39 | } 40 | 41 | #main-navi > ul { 42 | display: none; 43 | float: none; 44 | } 45 | 46 | #main-navi > ul > li a { 47 | display: block; 48 | text-align: left; 49 | padding: 0 0.25rem; 50 | } 51 | 52 | #main-navi { 53 | overflow: hidden; 54 | } 55 | 56 | #toogle-nav-label { 57 | display: block; 58 | } 59 | 60 | #toogle-nav:checked + ul { 61 | display: block; 62 | } 63 | 64 | #main-navi li:last-child { 65 | float: none; 66 | } 67 | 68 | .item > header { 69 | text-align: center; 70 | } 71 | 72 | .item > header > h2, 73 | .item > header > .info { 74 | float: none; 75 | display: block; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /theme/default/static/font/fontello.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nerdmind/Blog/31d7269f217f56b017d8e05a66caa2501212ed06/theme/default/static/font/fontello.woff2 -------------------------------------------------------------------------------- /theme/default/static/font/ruda-n-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nerdmind/Blog/31d7269f217f56b017d8e05a66caa2501212ed06/theme/default/static/font/ruda-n-400.woff2 -------------------------------------------------------------------------------- /theme/default/static/font/ruda-n-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nerdmind/Blog/31d7269f217f56b017d8e05a66caa2501212ed06/theme/default/static/font/ruda-n-700.woff2 -------------------------------------------------------------------------------- /theme/default/static/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nerdmind/Blog/31d7269f217f56b017d8e05a66caa2501212ed06/theme/default/static/logo.png -------------------------------------------------------------------------------- /theme/default/static/main.js: -------------------------------------------------------------------------------- 1 | //============================================================================== 2 | // Elements which contains the location of the previous and next site 3 | //============================================================================== 4 | const prev = document.getElementById("prev-site"); 5 | const next = document.getElementById("next-site"); 6 | 7 | //============================================================================== 8 | // Handle arrow keys and change the location to the desired direction 9 | //============================================================================== 10 | document.addEventListener("keyup", function(e) { 11 | if(!e.ctrlKey && !e.shiftKey && !e.altKey) { 12 | (e.keyCode === 37 && prev) && (window.location.href = prev.getAttribute("href")); 13 | (e.keyCode === 39 && next) && (window.location.href = next.getAttribute("href")); 14 | } 15 | }, false); 16 | --------------------------------------------------------------------------------