├── .htaccess
├── LICENSE.txt
├── README.md
├── admin.php
├── changelog.txt
├── index.php
└── sp_theme
└── sedot_bootstrap
├── config.ini
├── template.php
└── widget.php
/.htaccess:
--------------------------------------------------------------------------------
1 |
2 | RewriteEngine On
3 | RewriteBase /
4 | RewriteRule ^index\.php$ - [L]
5 | RewriteCond %{REQUEST_FILENAME} !-f
6 | RewriteCond %{REQUEST_FILENAME} !-d
7 | RewriteRule . /index.php [L]
8 |
9 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) [2015] [sukualam]
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [DISCONTINUED]
2 |
3 | # Sedotpress
4 | The new lightweight and low-resources blogging platform written in PHP. It is single-file Flat-file blogging engine. No database required! All data saved in JSON format.
5 |
6 | ## Features:
7 | * Posts & comments saved in JSON format
8 | * Lightweight & Low-Resource
9 | * Portable
10 | * URL Rewriting
11 | * Built-In Comment System + Gravatar
12 | * Auto Generate sitemap.xml & rss.xml
13 | * etc ...
14 |
15 | ## Downloads:
16 | https://github.com/sukualam/sedotpress/archive/master.zip
17 |
18 | ## Installing:
19 | * Extract all files in the zip to server (you can place it in root "/" or subdirectory "blog/")
20 | * Edit some config in index.php
21 | * Chmod the sp_lang folder `chmod 777 -R sp_lang`
22 | * Finish!
23 |
24 | ## URL Rewrites:
25 | ##### Lighttpd
26 | * Add this line in /etc/lighttpd/lighttpd.conf
27 | * `url.rewrite = ("^/(.*)\.(.+)$" => "$0","^/(.+)/?$" => "/index.php/$1")`
28 |
29 | ##### Apache
30 | * Use the .htaccess
31 |
32 | ## Latest News:
33 | * 8/5/2015: This script totaly beginning, so, dont expect too much like wordpress function, but this script still in development way, if you see any bugs or suggestions, i will happy if you report it here.
34 | * To get the latest news and development status, visit my blog http://sedot.space
35 |
36 | ## Recent Changelog:
37 | ##### (for full changelog, read changelog.txt)
38 |
39 | ##Managing and Other:
40 | ##### To enter the admin area (backstage)
41 | * Open `http://(your_blog_url)/backstage`
42 |
43 | ##### Theme & Modification:
44 | * You can directly edit the source code, since this is just single file.
45 | * But, if a newer version is available, you must re-edit again.
46 |
47 | Report any bugs here, and contribute :)
48 |
49 | Thank you!
50 |
--------------------------------------------------------------------------------
/admin.php:
--------------------------------------------------------------------------------
1 | $val){
33 | $filter[$key] = htmlentities($val);
34 | }
35 | return @$filter;
36 | }else{
37 | return htmlentities($_POST[$str]);
38 | }
39 | }
40 | function nullStr($mixed,$prefix = 'untitled',$numbering = false){
41 | if(is_array($mixed)){
42 | foreach($mixed as $key => $val){
43 | if(is_null($mixed[$key]) || $mixed[$key] == ""){
44 | if(!$numbering){
45 | $mixed[$key] = $prefix;
46 | }else{
47 | $mixed[$key] = sedot::assignPostId($prefix);
48 | }
49 | }
50 | }
51 | }else{
52 | if(is_null($mixed) || $mixed == ''){
53 | if(!$numbering){
54 | $mixed = $prefix;
55 | }else{
56 | $mixed = sedot::assignPostId($prefix);
57 | }
58 | }
59 | }
60 | return $mixed;
61 | }
62 | function alertMessage($str,$type = 'info'){
63 | $alert = '
64 |
65 | ×
66 | %s
';
67 | return sprintf($alert,$type,$str);
68 | }
69 | function panelBox($str,$type = 'default'){
70 | $panel = '';
75 | return sprintf($panel,$type,$str);
76 | }
77 | function filterStr($str){
78 | $str = strtolower(sedot::plainString($str));
79 | $cleared = preg_replace('/[^a-zA-Z0-9\s]/u','',$str);
80 | return str_replace('\s','-',$cleared);
81 | }
82 | function setNavi($count = 5,$perpage = 5,$row = 5){
83 | $dummy = '';
84 | if($perpage <= 100){
85 | if($perpage <= 50){
86 | if($perpage <= 25){
87 | if($perpage <= 10){
88 | if($perpage <= 5){
89 | $perpage = 5;
90 | }else{
91 | $perpage = 10;
92 | }}else{
93 | $perpage = 25;
94 | }}else{
95 | $perpage = 50;
96 | }}else{
97 | $perpage = 100;
98 | }}else{
99 | $perpage = 100;
100 | }
101 |
102 | $countTimes = $count * 5;
103 | $total = ceil(ceil($countTimes) / $perpage);
104 |
105 | for($i = 0;$i < $total;$i++){
106 | $dummy[$i] = $i;
107 | }
108 |
109 | @$split = array_chunk($dummy,$row,true);
110 |
111 | if(is_null($split)){
112 | return false;
113 | }else{
114 | return $split;
115 | }
116 | }
117 | function pageNavi($current,$stack,$url){
118 | $out = '';
119 | $out .= '
120 | ';
150 | return $out;
151 | }
152 | }
153 |
154 | $admin = new backstage;
155 | $section = @$getRequest[1];
156 | $baseUrl = sprintf('%s/backstage/%s',SITE_URL,$section);
157 |
158 | $admin->createWidget('primary');
159 | $admin->createWidget('secondary');
160 |
161 | if($section == 'new' || $section == 'edit'){
162 | if($section == 'edit'){
163 | if(isset($getRequest[2]) && $getRequest[2] != '' || ! empty($getRequest[2])){
164 | if(file_exists(sprintf('sp_post/post%s',$getRequest[2]))){
165 | $isFileExist = true;
166 | }else{
167 | $isFileExist = false;
168 | }
169 | }else{
170 | $isFileExist = false;
171 | }
172 |
173 | if(! $isFileExist){
174 | die(sprintf('Invalid Operation - Back ',$admin->sectionLink('')));
175 | }
176 |
177 | $loadPost = $admin->loadPost($getRequest[2]);
178 | }
179 | $form = sprintf('Edit Post
180 | ',
204 | $admin->sectionLink(sprintf('%s/%s',$section,@$getRequest[2])),
205 | @$loadPost['title'],
206 | @$loadPost['tag'],
207 | @$loadPost['entry'],
208 | @$loadPost['permalink']);
209 |
210 | $admin->addWidget('primary',$form);
211 |
212 | $reqs = $admin->filterPOST();
213 |
214 | if(isset($reqs['submit'])){
215 |
216 | $data['date'] = date(DateTime::ISO8601);
217 | $data['title'] = $admin->nullStr($reqs['title'],'untitled-',true);
218 | $data['permalink'] = $admin->nullStr($reqs['permalink'],$admin->filterStr($data['title']));
219 | $data['tag'] = $admin->nullStr($reqs['tag'],'uncategorized');
220 | $data['entry'] = $admin->nullStr($_POST['entry'],'Unfinished Story');
221 | $data['status'] = $admin->nullStr($reqs['status'],'publish');
222 |
223 | if($section == 'new'){
224 | $postFileName = sprintf('sp_post/%s',$admin->assignPostId());
225 | }else{
226 | $postFileName = sprintf('sp_post/post%s',$getRequest[2]);
227 | }
228 |
229 |
230 | if($admin->toFile($postFileName,$admin->toJson($data),true)){
231 |
232 | $admin->create_index();
233 | $message = $admin->alertMessage('Post Published!','success');
234 | $admin->addWidget('primary',$message,'before');
235 |
236 | }else{
237 |
238 | $message = $admin->alertMessage('Something Wrong','danger');
239 | $admin->addWidget('primary',$message,'before');
240 |
241 | }
242 |
243 | }
244 | }
245 | elseif($section == 'mypost' || $section == 'draft'){
246 |
247 | if($section == 'mypost'){
248 | $indexPublished = $admin->loadJson('index','post');
249 |
250 | }else{
251 | $indexPublished = $admin->loadJson('index','draft');
252 | }
253 |
254 | $setNavi = $admin->setNavi(count($indexPublished),5,5);
255 |
256 |
257 |
258 | if(isset($getRequest[2]) && isset($getRequest[3])){
259 | if($getRequest[2] == 'page'){
260 | $indexKey = $getRequest[3];
261 | }
262 | else{
263 | $indexKey = 0;
264 | }
265 | }
266 | else{
267 | $indexKey = 0;
268 | }
269 |
270 | $indexList = $admin->index_page($indexPublished[$indexKey]);
271 |
272 | foreach($indexList as $meta){
273 | $tableRows = '
274 | %s
275 | %s
276 | %s
277 | %s
278 | %s
279 | ';
280 |
281 | $editPostUrl = sprintf('%s/%s',$admin->sectionLink('edit'),$meta['id']);
282 | $removePostUrl = sprintf('%s/%s',$admin->sectionLink('delete'),$meta['id']);
283 |
284 | @$formatRows .= sprintf($tableRows,
285 | $meta['date'],
286 | $meta['title'],
287 | round(filesize("sp_post/post{$meta['id']}") / 1024, 2),
288 | $meta['id'],
289 | '
290 |
291 |
292 | '
293 | );
294 | }
295 |
296 | $table = 'My Posts
297 |
298 |
299 |
300 | Date
301 | Title
302 | Size (Kb)
303 | Post Id
304 | Action
305 |
306 | %s
307 |
308 |
';
309 |
310 | $sidebar = 'Options
311 | Sorting Order';
312 | $formatTable = sprintf($table,$formatRows);
313 |
314 | $admin->addWidget('primary',$formatTable);
315 | $admin->addWidget('secondary',$sidebar);
316 |
317 | if($setNavi){
318 | $admin->addWidget('primary',$admin->pageNavi($indexKey,$setNavi,$baseUrl));
319 | }
320 | }
321 | elseif($section == 'delete' && isset($getRequest[2])){
322 | /*
323 | * Only for valid filename
324 | */
325 | if(! file_exists(sprintf('sp_post/post%s',$getRequest[2]))){
326 | die();
327 | }
328 |
329 | /*
330 | * Delete confirmation dialog
331 | */
332 |
333 | $form = 'Delete Post
334 |
335 |
336 |
337 | Yes
338 |
339 |
340 |
341 |
342 | No
343 |
344 |
345 |
346 | ';
347 |
348 | $msgError = $admin->alertMessage('Not Deleted','danger');
349 | $msgSuccess = $admin->alertMessage('Post Deleted','success');
350 |
351 | /*
352 | * Handling the message
353 | */
354 |
355 | if(isset($_POST['del'])){
356 | if($_POST['del'] == 'yes'){
357 | if($admin->removeExistingFile(sprintf('sp_post/post%s',$getRequest[2]))){
358 | $admin->addWidget('primary',$msgSuccess);
359 | $admin->create_index();
360 | }
361 | else{
362 | $admin->addWidget('primary',$msgError);
363 | }
364 | }
365 | else{
366 | $admin->addWidget('primary',$msgError);
367 | }
368 | }
369 | else{
370 | $admin->addWidget('primary',$form);
371 | }
372 | }
373 | elseif($section == 'widget'){
374 |
375 | /*
376 | * Load widget areas on templates
377 | */
378 | $widgetConf = parse_ini_file('sp_theme/'.THEME.'/config.ini');
379 | $widgetFile = '_widget-'.THEME;
380 | $widgetPath = 'sp_static/misc/'.$widgetFile.'.json';
381 | /*
382 | * Create default widget config in sp_json/ that store the widgets
383 | * Filename format: widget-{theme_name}.json
384 | * Still need to implemented
385 | */
386 | if(! file_exists($widgetPath)){
387 | foreach($widgetConf['area'] as $key => $widget){
388 | $widgetSection[$widget] = '';
389 | }
390 | $widgetSet = $admin->toJson($widgetSection);
391 |
392 | if($admin->toFile($widgetPath,$widgetSet)){
393 | $msg = 'Default Config Created';
394 | $admin->addWidget('primary',$admin->alertMessage($msg,'success'));
395 | }
396 | }
397 |
398 | $loadWidget = $admin->loadJson('misc',$widgetFile);
399 |
400 | if(isset($getRequest[2])){
401 | /*
402 | * $getRequest[2] means widget area name, example: sidebar1
403 | * This handle following action: edit,remove,new
404 | */
405 | if(@$_POST['widgetAction'] == 'edithtml'){
406 | $wArea = $_POST['widgetArea'];
407 | $wItemId = $_POST['widgetItemId'];
408 | $loadWidget[$wArea][$wItemId]['title'] = $_POST['widgetTitle'];
409 | $loadWidget[$wArea][$wItemId]['code'] = $_POST['htmlCode'];
410 | $rePack = $admin->toJson($loadWidget);
411 | $admin->toFile($widgetPath,$rePack,true);
412 | }
413 | if(isset($_POST['addWidget'])){
414 | if($_POST['addWidget'] == 'html'){
415 | $code = $_POST['htmlCode'];
416 | }else{
417 | $code = sprintf('#%1$s#',strtoupper($_POST['addWidget']));
418 | }
419 | $key = $admin->endKey($loadWidget[$getRequest[2]],true);
420 | $loadWidget[$getRequest[2]][$key] = array(
421 | 'type' => $_POST['addWidget'],
422 | 'title' => $_POST['widgetTitle'],
423 | 'code' => $code);
424 | $rePack = $admin->toJson($loadWidget);
425 | $admin->toFile($widgetPath,$rePack,true);
426 | }
427 | }
428 |
429 | if(isset($getRequest[3]) && $getRequest[3] == 'add' && ! isset($_POST['widgetType'])){
430 | # This will show the widget type for new widget action
431 | $form = sprintf('
432 | (%2$s) New Widget:
433 |
434 |
435 |
436 | Custom HTML/Javascript Code
437 |
438 |
439 |
440 |
441 |
442 | Own Function
443 |
444 |
445 |
446 | Cancel
447 | ',
448 | $admin->sectionLink(sprintf('widget/%1$s/add',$getRequest[2])),
449 | $getRequest[2],
450 | $admin->sectionLink('widget'));
451 | $admin->addWidget('primary',$admin->panelBox($form),'before');
452 | }
453 |
454 | if(isset($getRequest[3]) && $getRequest[3] == 'add' && isset($_POST['widgetType'])){
455 | #This handle the widget type
456 | if($_POST['widgetType'] == 'html'){
457 | $htmlForm = sprintf('
458 | New Widget
459 |
460 |
461 |
469 | ',
470 | $_POST['widgetId'],
471 | $admin->sectionLink(sprintf('widget/%s',$getRequest[2])));
472 | $admin->addWidget('primary',$admin->panelBox($htmlForm),'before');
473 | }
474 | elseif($_POST['widgetType'] == 'own'){
475 | $getWidgets = $admin->currentMethod('widget');
476 | foreach($getWidgets as $widgetName){
477 | $widgetNameList[] = ''.$widgetName.' ';
478 | }
479 | $htmlForm = sprintf('
480 | New Widget
481 |
482 |
494 | ',
495 | $_POST['widgetId'],
496 | $admin->sectionLink(sprintf('widget/%s',$getRequest[2])),
497 | implode(' ',$widgetNameList)
498 | );
499 | $admin->addWidget('primary',$admin->panelBox($htmlForm),'before');
500 | }
501 | else{
502 | $htmlForm = sprintf('
503 | New Widget
504 |
505 |
506 |
512 | ',
513 | $_POST['widgetId'],
514 | $admin->sectionLink(sprintf('widget/%s',$getRequest[2])),
515 | $_POST['widgetType']);
516 | $admin->addWidget('primary',$admin->panelBox($htmlForm),'before');
517 | }
518 | }
519 |
520 | /*
521 | * Move up the widget item
522 | */
523 |
524 | if(isset($getRequest[3]) && $getRequest[3] == 'up' && isset($getRequest[4])){
525 | $loadWidget[$getRequest[2]] = $admin->up($loadWidget[$getRequest[2]],$getRequest[4]);
526 | $loadWidget[$getRequest[2]] = array_values($loadWidget[$getRequest[2]]);
527 | $rePack = $admin->toJson($loadWidget);
528 | $admin->toFile($widgetPath,$rePack,true);
529 | }
530 |
531 | /*
532 | * Move down the widget item
533 | */
534 |
535 | if(isset($getRequest[3]) && $getRequest[3] == 'down' && isset($getRequest[4])){
536 | $loadWidget[$getRequest[2]] = $admin->down($loadWidget[$getRequest[2]],$getRequest[4]);
537 | $loadWidget[$getRequest[2]] = array_values($loadWidget[$getRequest[2]]);
538 | $rePack = $admin->toJson($loadWidget);
539 | $admin->toFile($widgetPath,$rePack,true);
540 | }
541 |
542 | /*
543 | * Delete widget item
544 | */
545 |
546 | if(isset($getRequest[3]) && $getRequest[3] == 'delete' && isset($getRequest[4])){
547 | unset($loadWidget[$getRequest[2]][$getRequest[4]]);
548 | $loadWidget[$getRequest[2]] = array_values($loadWidget[$getRequest[2]]);
549 | $rePack = $admin->toJson($loadWidget);
550 | $admin->toFile($widgetPath,$rePack,true);
551 | }
552 |
553 | if(isset($getRequest[3]) && $getRequest[3] == 'edit' && isset($getRequest[4])){
554 | /*
555 | * Edit the existing widget item in current widget area
556 | * $getRequest[4] means widget item id
557 | */
558 |
559 | $htmlForm = sprintf('
560 | Edit Widget
561 |
562 | Widget Type: %6$s
563 |
564 |
565 |
566 |
574 | ',
575 | $admin->sectionLink(sprintf('widget/%s',$getRequest[2])),
576 | $loadWidget[$getRequest[2]][$getRequest[4]]['title'],
577 | $loadWidget[$getRequest[2]][$getRequest[4]]['code'],
578 | $getRequest[2],
579 | $getRequest[4],
580 | $loadWidget[$getRequest[2]][$getRequest[4]]['type']
581 | );
582 |
583 | $admin->addWidget('primary',$admin->panelBox($htmlForm),'before');
584 |
585 | }
586 |
587 | /*
588 | * Create a simple widget management
589 | */
590 |
591 | foreach($widgetConf['area'] as $area){
592 | $widgetList = '';
593 | foreach($loadWidget[$area] as $keys => $widgets){
594 | $widgetList .= sprintf('
595 |
596 | %5$s
597 |
598 |
599 |
600 | ',
601 | $admin->sectionLink('widget') . '/' . $area . '/edit/' . $keys,
602 | $admin->sectionLink('widget') . '/' . $area . '/up/' . $keys,
603 | $admin->sectionLink('widget') . '/' . $area . '/down/' . $keys,
604 | $admin->sectionLink('widget') . '/' . $area . '/delete/' . $keys,
605 | $widgets['title'] == '' ? '(notitle)' : $widgets['title']);
606 | }
607 | $box = sprintf('
608 | %s
609 |
610 | ',
611 | $area,
612 | $admin->sectionLink('widget') . '/' . $area . '/add',
613 | $widgetList
614 | );
615 |
616 | $admin->addWidget('primary',$box);
617 |
618 | unset($widgetList);
619 | }
620 | }
621 | elseif($section == 'option'){
622 | $filename = 'config.json';
623 | }
624 | elseif($section == 'import'){
625 | $dialogBox = '
626 | Import from Blogger Backup (xml)
627 |
628 |
629 | ';
630 |
631 | if(isset($_POST['act']) && $_POST['act'] == 'ok'){
632 | $filename = 'blog.xml';
633 | $parse = simplexml_load_file($filename);
634 | $encode = json_encode($parse);
635 | $decode = json_decode($encode,true);
636 | $reverse = array_reverse($decode['entry'],true);
637 | $term = 'http://schemas.google.com/blogger/2008/kind#post';
638 | foreach($reverse as $id => $content){
639 | if($content['category'][0]['@attributes']['term'] == $term){
640 | array_shift($content['category']);
641 | foreach($content['category'] as $keys => $tag){
642 | $tags[] = $content['category'][$keys]['@attributes']['term'];
643 | }
644 | $link = $content['link'][4]['@attributes']['href'];
645 | $link = rtrim($link,'{.html}');
646 | $permalink = explode('/',$link);end($permalink);
647 | $permalink = $permalink[key($permalink)];
648 | $data['date'] = date(DateTime::ISO8601);
649 | $data['title'] = $content['title'];
650 | $data['permalink'] = $permalink;
651 | $data['tag'] = implode(',',$tags);
652 | $data['entry'] = $content['content'];
653 | $data['status'] = 'publish';
654 | $postFileName = sprintf('sp_post/%s',$admin->assignPostId());
655 | $admin->toFile($postFileName,$admin->toJson($data),true);
656 | unset($tags);
657 | }
658 | }
659 | $admin->create_index();
660 | }
661 | $admin->addWidget('primary',$dialogBox);
662 | }
663 | ?>
664 |
665 |
666 |
667 |
668 |
669 |
670 |
671 | [Backstage]
672 |
673 |
674 |
675 |
676 |
677 |
678 |
682 |
683 |
684 |
685 |
707 |
708 |
713 |
714 |
715 |
716 |
717 |
718 | widgetSection('primary'); ?>
719 |
720 |
721 |
722 |
734 |
735 |
736 |
737 |
738 |
739 |
746 |
747 |
748 |
--------------------------------------------------------------------------------
/changelog.txt:
--------------------------------------------------------------------------------
1 | Full Changelog
2 |
3 | v.0.1.7
4 | backstage now in separate file (admin.php)
5 | temporary disabled: builtin comment (can someone give me the idea??)
6 | new: custom template (create your own template)
7 | enhanced index caching by splitting index to separate file
8 | new: builtin widget
9 | major structure changes, not compatible to older version
10 | changed login method + blacklist ip
11 | enhanced url routing
12 |
13 | v.0.1.6 (??)
14 | code rewritten, skip to v.0.1.7
15 |
16 | v.0.1.5 (8/4/2015)
17 | major structure changes (it wont compatible with older version)
18 | optimized json files
19 | new: language files (you can create your own)
20 | new: menu editor
21 | new: saving post in published or draft mode
22 | new: threaded comment + reply
23 | new: gravatar icon for comments
24 | added "website", "email" field in comment format
25 | added 404 page
26 | some bugfixes
27 |
28 | v.0.1.4 (28/3/2015)
29 | now, post saved in json format
30 | permalink is auto generated (if field is empty)
31 | title is auto generated, like Untitled-1 (if field is empty)
32 | tag is auto generated, named "out-topic" (if field is empty)
33 | admin area layout changes
34 | added "edit" link every post
35 | added favicon.ico
36 | fixed meta description from cutted if there are html tag
37 | many bugfixes
38 |
39 | v.0.1.3 beta (26/3/2015)
40 | enabled RSS feeds
41 | enabled sitemap (auto generate)
42 | enabled post thumbnails
43 | added visual editor (WYSIWYG)
44 | enabled image upload (base64 encoded)
45 | minor style changes
46 |
47 | v.0.1.2 beta (25/3/2015)
48 | now support nested of directory, like this : (http://localhost/blog)
49 | minor backstage (admin area) fix
50 | now can delete post from backstage
51 |
52 | v.0.1.1 beta
53 | builtin comment system (beta)
54 | minor style change
55 |
56 | v0.1.0 beta
57 | (The current version is provide basic blogging features):
58 | Create/Edit a post
59 | Admin area (we call it backstage)
60 | Search a post
61 | Blog archives
62 | Tags
63 | Clean URL (permalink) / Url Rewrite
64 |
--------------------------------------------------------------------------------
/index.php:
--------------------------------------------------------------------------------
1 | total = $a;
79 | $this->page = $b;
80 | }
81 | function currentMethod($class){
82 | $allMethod = get_class_methods($class);
83 | if($parentClass = get_parent_class($class)){
84 | $parentMethod = get_class_methods($parentClass);
85 | $currentMethod = array_diff($allMethod, $parentMethod);
86 | }else{
87 | $currentMethod = $allMethod;
88 | }
89 | return($currentMethod);
90 | }
91 | function removeExistingFile($path){
92 | if(file_exists($path)){
93 | if(unlink($path)){
94 | return true;
95 | }else{
96 | return false;
97 | }
98 | }else{
99 | return false;
100 | }
101 | }
102 | function toJson($str){
103 | $jsonEncode = json_encode($str,
104 | JSON_HEX_TAG | JSON_HEX_APOS |
105 | JSON_HEX_QUOT | JSON_HEX_AMP |
106 | JSON_UNESCAPED_UNICODE);
107 | return $jsonEncode;
108 | }
109 | function createWidget($widgetId = 1){
110 | $this->primaryHTML[$widgetId] = array();
111 | }
112 | function addWidget($widgetId,$str,$order = 'after'){
113 | if($order == 'after'){
114 | array_push($this->primaryHTML[$widgetId],$str);
115 | }else{
116 | array_unshift($this->primaryHTML[$widgetId],$str);
117 | }
118 | }
119 | function widgetSection($opt = '1'){
120 | if(isset($opt)){
121 | foreach($this->primaryHTML[$opt] as $key => $widget){
122 | printf('%s',$widget);
123 | }
124 | }
125 | }
126 | function down($a,$x){
127 | if(count($a)-1 > $x){
128 | $b = array_slice($a,0,$x,true);
129 | $b[] = $a[$x+1];
130 | $b[] = $a[$x];
131 | $b += array_slice($a,$x+2,count($a),true);
132 | return($b);
133 | }else{
134 | return $a;
135 | }
136 | }
137 | function up($a,$x){
138 | if($x > 0 && $x < count($a)){
139 | $b = array_slice($a,0,($x-1),true);
140 | $b[] = $a[$x];
141 | $b[] = $a[$x-1];
142 | $b += array_slice($a,($x+1),count($a),true);
143 | return($b);
144 | }else{
145 | return $a;
146 | }
147 | }
148 | function enableWidget(){
149 | $widgetContainer = '
150 | %3$s
151 | %4$s
152 |
';
153 |
154 | $widgetTitle = '';
155 |
156 | $templateWidget = self::loadJson('misc','_widget-'.THEME);
157 | $getConfig = parse_ini_file('sp_theme/'.THEME.'/config.ini');
158 | foreach($getConfig['area'] as $widget){
159 | self::createWidget($widget);
160 | foreach($templateWidget[$widget] as $widgetKey => $content){
161 | if($content['title'] != ''){
162 | $content['title'] = sprintf($widgetTitle,$content['title']);
163 | }
164 | if($content['type'] == 'html'){
165 | $code = $content['code'];
166 | }else{
167 | $code = widget::$content['type']();
168 | }
169 | self::addWidget($widget,sprintf(
170 | $widgetContainer,
171 | $widget,
172 | $widgetKey,
173 | $content['title'],
174 | $code
175 | ));
176 | }
177 | }
178 | skipCreateWidget:
179 | }
180 | function toFile($path,$data,$truncate = false){
181 | if($truncate){
182 | self::removeExistingFile($path);
183 | }
184 | $openFile = fopen($path,"a+");
185 | if($openFile == false){
186 | return false;
187 | }else{
188 | $writeData = fwrite($openFile,$data);
189 | fclose($openFile);
190 | return true;
191 | }
192 | }
193 |
194 | function loadFile($path,$stream = false){
195 | @$openFile = fopen($path,"r");
196 | if(!$stream){
197 | @$readFile = fread($openFile,filesize($path));
198 | }else{
199 | @$readFile = fgets($openFile);
200 | }
201 | $containData = $readFile;
202 | @fclose($openFile);
203 | return $containData;
204 | }
205 | function loadPost($postnum){
206 | $loadPost = self::loadFile("sp_post/post{$postnum}",false);
207 | $this->postPart = json_decode($loadPost,true);
208 | return $this->postPart;
209 | }
210 | function formatPost($filename){
211 | $postPart = self::loadPost($filename);
212 | $postPart['tag'] = explode(',',$postPart['tag']);
213 | return $postPart;
214 | }
215 | function endKey($array, $increment = false, $trim = 'post'){
216 | if(is_null($array)){
217 | $key = 0;
218 | }else{
219 | end($array);
220 | $key = trim(key($array),$trim);
221 | }
222 | if($increment){
223 | $key += 1;
224 | }
225 | return $key;
226 | }
227 | function assignPostId($prefix = NULL){
228 | /*
229 | * This actually used for assigning post Id's in "publish" and "draft" mode
230 | * This function open 'sp_static/index/post.json'
231 | */
232 | $postList = self::loadJson('index','post');
233 | $newKey = self::endKey(array_reverse($postList[0],true),true);
234 | if(is_null($newKey)){
235 | $newKey = 1;
236 | }
237 | if(is_null($prefix)){
238 | $prefix = 'post';
239 | }
240 | /* Skip existing file */
241 | while(file_exists(sprintf('sp_post/%s%s',$prefix,$newKey))){
242 | $newKey += 1;
243 | }
244 | $key = $prefix . $newKey;
245 | return $key;
246 | }
247 | function getImg($string){
248 | preg_match('/src="([^"]*)"/',$string,$matches);
249 | if(!isset($matches[1]) || $matches[1] == "" || empty($matches[1])){
250 | return false;
251 | }else{
252 | return $matches[1];
253 | }
254 | }
255 | function plainString($text){
256 | // Copyright (c) 2008, David R. Nadeau, NadeauSoftware.com.
257 | // All rights reserved.
258 | $text = preg_replace(
259 | array(
260 | '@]*?>.*?@siu',
261 | '@@siu',
262 | '@@siu',
263 | '@]*?.*? @siu',
264 | '@]*?.*? @siu',
265 | '@]*?.*? @siu',
266 | '@]*?.*? @siu',
267 | '@]*?.*? @siu',
268 | '@]*?.*? @siu',
269 | '@<((br)|(hr))@iu',
270 | '@?((address)|(blockquote)|(center)|(del))@iu',
271 | '@?((div)|(h[1-9])|(ins)|(isindex)|(p)|(pre))@iu',
272 | '@?((dir)|(dl)|(dt)|(dd)|(li)|(menu)|(ol)|(ul))@iu',
273 | '@?((table)|(th)|(td)|(caption))@iu',
274 | '@?((form)|(button)|(fieldset)|(legend)|(input))@iu',
275 | '@?((label)|(select)|(optgroup)|(option)|(textarea))@iu',
276 | '@?((frameset)|(frame)|(iframe))@iu',
277 | ),
278 | array(
279 | ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
280 | "\n\$0", "\n\$0", "\n\$0", "\n\$0", "\n\$0", "\n\$0",
281 | "\n\$0", "\n\$0",
282 | ),
283 | $text);
284 | return strip_tags($text);
285 | }
286 | function getExcerpt($string,$length){
287 | $string = self::plainString($string);
288 | $excerpt = substr($string,0,$length);
289 | $cutlastword = strrpos($excerpt, ' ');
290 | $excerpt = substr($excerpt, 0, $cutlastword);
291 | return $excerpt;
292 | }
293 | function splitMeta($str){
294 | $meta['date'] = $str[0];
295 | $meta['title'] = $str[1];
296 | $meta['permalink'] = $str[2];
297 | $meta['tag'] = $str[3];
298 | return $meta;
299 | }
300 | function create_index($itemPerIndex = 5){
301 | $sitemapContainer = '
302 |
303 | %1$s
304 | ';
305 | $sitemapItem = '
306 | %1$s/%2$s ';
307 | $rssContainer = '
308 |
309 |
310 |
311 | %1$s
312 | %2$s
313 | %3$s %4$s
314 |
315 | ';
316 | $rssItem = '
317 | -
318 |
%1$s
319 | %2$s
320 | %3$s
321 | ';
322 | $dir = "sp_post/";
323 | $archiveDate = '';
324 | $countFileSize = '';
325 | $scandir = array_diff(scandir($dir),array('..','.'));
326 | natsort($scandir);
327 | $reverseOrder = array_reverse($scandir);
328 | foreach($reverseOrder as $file){
329 | $countFileSize += filesize("sp_post/{$file}");
330 | $dec = self::loadPost(ltrim($file,'post'));
331 | $postDate = explode(" ",date('Y m d',strtotime($dec['date'])));
332 | $splitTag = explode(",",$dec['tag']);
333 | $postTag[] = $splitTag;
334 | @$meta = array($dec['date'],$dec['title'],$dec['permalink'],$splitTag);
335 | if($dec['status'] == "publish"){
336 | $container[trim($file,'post')] = $meta;
337 | $countAllPost += 1;
338 | }else{
339 | $draft_container[trim($file,'post')] = $meta;
340 | }
341 | @$archiveDate[$postDate[0]][$postDate[1]][$postDate[2]] += 1;
342 | }
343 | foreach($postTag as $many){
344 | foreach($many as $tag){
345 | $tags[] = $tag;
346 | }
347 | }
348 | // split the container
349 | @$chunk = array_chunk($container,$itemPerIndex,TRUE);
350 | @$chunk_draft = array_chunk($draft_container,$itemPerIndex,TRUE);
351 | ## CREATE SITEMAP.XML
352 | foreach($container as $metadata){
353 | $xmlItems[] = sprintf(trim($sitemapItem,"\t\n\r\0\x0B"),SITE_URL,$metadata[2]);
354 | }
355 | $xml = sprintf(trim($sitemapContainer,"\t\n\r\0\x0B"),implode('',$xmlItems));
356 | ## CREATE RSS.XML
357 | // limit to (2 x $itemPerIndex)
358 | for($i = 0;$i<= 1;$i++){
359 | foreach($chunk[$i] as $postid => $metadata){
360 | $readPost = self::loadPost($postid);
361 | $rssItems[] = sprintf(trim($rssItem,"\t\n\r\0\x0B"),$readPost['title'],
362 | SITE_URL . '/'. $readPost['permalink'],
363 | htmlentities($readPost['entry']));
364 | }
365 | }
366 | $rss = sprintf(trim($rssContainer,"\t\n\r\0\x0B"),SITE_TITLE,SITE_URL,
367 | SITE_DESC,implode('',$rssItems));
368 | // count post each tag
369 | $counttag = array_count_values($tags);
370 | $reverse_year = array_reverse($archiveDate,true);
371 | $indexJson = self::toJson($chunk);
372 | $draftJson = self::toJson($chunk_draft);
373 | $tagJson = self::toJson($counttag);
374 | $archiveJson = self::toJson($reverse_year);
375 | ## SPLIT INDEX TO FILE
376 | foreach($chunk as $keyy => $chunkval){
377 | $chunkpart = self::toJson($chunkval);
378 | self::toFile("sp_static/index/index-{$keyy}.json",$chunkpart,true);
379 | }
380 | ## WRITE NEW DATA
381 | self::toFile("sp_static/index/totalpost.json",$countAllPost,true);
382 | self::toFile("sp_static/index/archive.json",$archiveJson,true);
383 | self::toFile("sp_static/index/draft.json",$draftJson,true);
384 | self::toFile("sp_static/index/post.json",$indexJson,true);
385 | self::toFile("sp_static/index/tag.json",$tagJson,true);
386 | self::toFile("sp_static/index/filesize.json",$countFileSize,true);
387 | self::toFile("sp_static/xml/rss.xml",$rss,true);
388 | self::toFile("sp_static/xml/sitemap.xml",$xml,true);
389 | }
390 | // load json file and decode it into associative array
391 | function loadJson($type = NULL,$name = NULL){
392 | $str = self::loadFile("sp_static/{$type}/{$name}.json",true);
393 | $jsonDecoded = json_decode($str,true);
394 | return $jsonDecoded;
395 | }
396 | // add ip address to blacklist
397 | function ipBlackList($specify = NULL){
398 | if(is_null($specify)){
399 | $ipBlackList = $_SERVER["REMOTE_ADDR"];
400 | }else{
401 | $ipBlackList = $specify;
402 | }
403 | $blackList = self::loadJson('misc','blacklist');
404 | $blackList[self::endKey($blackList,true)] = $ipBlackList;
405 | self::toFile('sp_static/misc/blacklist.json',self::toJson($blackList),true);
406 | }
407 | function isBlacklisted($specify = NULL){
408 | $blackList = self::loadJson('misc','blacklist');
409 | if(is_null($specify)){
410 | $ip = $_SERVER["REMOTE_ADDR"];
411 | }else{
412 | $ip = $specify;
413 | }
414 | if(@in_array($ip,$blackList)){
415 | return true;
416 | }else{
417 | return false;
418 | }
419 | }
420 | function totalPost(){
421 | $size = self::loadFile('sp_static/index/totalpost.json');
422 | return $size;
423 | }
424 | // create recent comment
425 | function create_recent_comment($permalink,$post_title,$comments){
426 | // read/write
427 | $filename = "sp_static/misc/recent_comment.json";
428 | $fgets = self::loadFile($filename,true);
429 | $decode = json_decode($fgets,true);
430 | $endkey = self::endKey($decode,true);
431 | if($endkey > 5){
432 | array_shift($decode);
433 | $newKey = 5;
434 | }else{
435 | $newKey = $endkey;
436 | }
437 | $decode[$newKey] = array($permalink,$post_title,$comments);
438 | $encode = self::toJson($decode);
439 | self::toFile($filename,$encode,true);
440 | }
441 | function search($mode,$query){
442 | $index = self::loadJson('index','post');
443 | $s = explode('+',strtolower(rtrim($query,'+')));
444 | $count = count($s);
445 | if($count <= 1){$amount = 1;}
446 | else{$amount = $count;}
447 | for($i = 0;$i <= count($index);$i++){
448 | foreach($index[$i] as $key => $val){
449 | if($mode == 0){
450 | $tgl = date('Y m d',strtotime($val[$mode]));
451 | $y = explode(' ',$tgl);
452 | if($amount == 1){
453 | if($y[0] == $s[0]){
454 | $found[$key] = '';
455 | }
456 | }
457 | if($amount == 2){
458 | if($y[0] == $s[0] && $y[1] == $s[1]){
459 | $found[$key] = '';
460 | }
461 | }
462 | if($amount >= 3){
463 | if($y[0] == $s[0] && $y[1] == $s[1] && $y[2] == $s[2]){
464 | $found[$key] = '';
465 | }
466 | }
467 | }
468 | if($mode == 1){
469 | $p = explode(' ',strtolower($val[$mode]));
470 | for($o = 0;$o < $amount;$o++){
471 | if(in_array($s[0],$p)){$found[$key] = '';}
472 | }
473 | unset($p);
474 | }
475 | if($mode == 2){
476 | $p = strtolower($val[$mode]);
477 | if($s[0] == $p){
478 | $found[$key] = '';
479 | break 2;
480 | }
481 | }
482 | if($mode == 3){
483 | $val[$mode] = array_map('strtolower',$val[$mode]);
484 | for($o = 0;$o < $amount;$o++){
485 | if(in_array(strtolower(urldecode($query)),$val[$mode])){$found[$key] = '';}
486 | }
487 | }
488 | unset($val);
489 | }
490 | }
491 | return $found;
492 | }
493 | function index_page($post_array,$read_meta = false){
494 | foreach($post_array as $postid => $metadata){
495 | $dec = self::loadPost($postid);
496 | if($read_meta){
497 | $postmeta = array(
498 | 'date' => $dec['date'],
499 | 'title' => $dec['title'],
500 | 'permalink' => $dec['permalink'],
501 | 'tag' => explode(',',$dec['tag'])
502 | );
503 | }else{
504 | $postmeta = self::splitMeta($metadata);
505 | }
506 | $thumbImg = self::getImg($dec['entry']);
507 | $konten = $dec['entry'];
508 | /* grouping */
509 | $group[$postid]["id"] = $postid;
510 | $group[$postid]["image"] = $thumbImg;
511 | $group[$postid]["tag"] = $postmeta['tag'];
512 | $group[$postid]["title"] = $postmeta['title'];
513 | $group[$postid]["url"] = self::_url($postmeta['permalink']);
514 | $group[$postid]["date"] = $postmeta['date'];
515 | $group[$postid]["entry"] = $konten;
516 | }
517 | return $group;
518 | }
519 | } # end sedot class
520 |
521 | include 'sp_theme/'.THEME.'/widget.php';
522 |
523 | ### START LISTENING ###
524 | $post = new sedot;
525 |
526 | if(!isset($_FRONT_PAGE)){$_FRONT_PAGE = false;}
527 | if(!isset($_SINGLE_POST)){$_SINGLE_POST = false;}
528 | if(!isset($_PAGE_404)){$_PAGE_404 = false;}
529 |
530 | if(empty($getRequest[0])){
531 | $_FRONT_PAGE = true;
532 | $pointer = $post->loadJson('index','index-0');
533 | $entries = $post->index_page($pointer,false);
534 | $post->navi($post->totalpost(),1);
535 | }
536 | elseif($getRequest[0] == "page"){
537 | $_FRONT_PAGE = true;
538 | $pagenum = $getRequest[1];
539 | $pointer = $post->loadJson('index','index-'.($pagenum - 1));
540 | $entries = $post->index_page($pointer,false);
541 | $post->navi($post->totalpost(),$pagenum);
542 | }
543 | elseif($getRequest[0] == "rss"){
544 | header("Content-Type: application/rss+xml; charset=ISO-8859-1");
545 | printf("%s",$post->loadFile("sp_static/xml/rss.xml"));
546 | exit;
547 | }
548 | elseif($getRequest[0] == "search" || $getRequest[0] == "tag" || $getRequest[0] == "timeline"){
549 | $_FRONT_PAGE = true;
550 | $_SEARCH_MODE = true;
551 | if($getRequest[0] == 'search'){$mode = 1;}
552 | elseif($getRequest[0] == 'tag'){$mode = 3;}
553 | elseif($getRequest[0] == 'timeline'){
554 | $mode = 0;
555 | $i = 1;
556 | while($getRequest[$i] != "page"){
557 | $timeline[] = $getRequest[$i];
558 | if($i > 6){break;}
559 | $i++;
560 | }
561 | $getRequest[1] = implode('+',$timeline);
562 | $getRequest[1] = rtrim($getRequest[1],'+');
563 |
564 | for($a = 2;$a < $i;$a++){
565 | unset($getRequest[$a]);
566 | }
567 | $getRequest = array_values($getRequest);
568 | }
569 | $find = array_chunk($post->search($mode,$getRequest[1]),5,true);
570 | $pagenum = $getRequest[3];
571 | if($pagenum == ''){$pagenum = 1;}
572 | $pointer = $find[$pagenum - 1];
573 | $entries = $post->index_page($pointer,true);
574 | $post->navi(count($find),$pagenum);
575 | }
576 | elseif($getRequest[0] == "backstage"){
577 | $authUser = @$_SERVER['PHP_AUTH_USER'];
578 | $authPass = @$_SERVER['PHP_AUTH_PW'];
579 | if($post->isBlacklisted()){
580 | die("IP Address Blocked");
581 | }
582 | if($authUser == ADMIN_NICKNM && $authPass == ADMIN_PASSWD){
583 | if(isset($getRequest[1]) && $getRequest[1] == "logout"){
584 | $isValid = false;
585 | }else{
586 | $isValid = true;
587 | }
588 | }else{
589 | $_SESSION["ATTEMPT"] += 1;
590 | $isValid = false;
591 | }
592 | if(!$isValid){
593 | if($_SESSION["ATTEMPT"] >= 10){
594 | $post->ipBlackList();
595 | die("Max Attempt");
596 | }else{
597 | header('WWW-Authenticate: Basic realm="sedotpress"');
598 | header('HTTP/1.0 401 Unauthorized');
599 | die("Not authorized");
600 | }
601 | }
602 | die(include 'admin.php');
603 | }
604 | else{
605 | $_SINGLE_POST = true;
606 | $pointer = $post->search(2,$getRequest[0]);
607 | $pointer = key($pointer);
608 | if(! $pointer || $pointer == '' || is_null($pointer)){
609 | header('HTTP/1.0 404 Not Found');
610 | $_SINGLE_POST = false;
611 | $_PAGE_404 = true;
612 | goto bypass;
613 | }
614 | $entry = $post->formatPost($pointer);
615 | bypass:
616 | }
617 | require 'sp_theme/'.THEME.'/template.php';
618 | ?>
619 |
--------------------------------------------------------------------------------
/sp_theme/sedot_bootstrap/config.ini:
--------------------------------------------------------------------------------
1 | [widget]
2 |
3 | area[] = "index-top";
4 | area[] = "index-bottom";
5 |
6 | area[] = "post-top";
7 | area[] = "post-bottom";
8 | area[] = "sidebar1";
9 |
10 | area[] = "sidebar2";
11 |
12 | area[] = "footer";
13 |
14 | area[] = "top";
--------------------------------------------------------------------------------
/sp_theme/sedot_bootstrap/template.php:
--------------------------------------------------------------------------------
1 | enableWidget();
7 |
8 | /* override widget that not declared ini config.ini */
9 | $post->createWidget('head');
10 | $post->createWidget('header');
11 |
12 | if($_PAGE_404){
13 | $message = '
14 |
404 NOT FOUND
15 | ';
16 | $post->addWidget('index-top',$message);
17 | }
18 | if($_FRONT_PAGE){
19 | if($getRequest[0] == "page"){
20 | $title = ''.SITE_TITLE.' | page '. $getRequest[1] . ' ';
21 | }elseif($_SEARCH_MODE){
22 | $_page = isset($getRequest[3]) ? ' | page '.$getRequest[3] : '';
23 | $title = ''.SITE_TITLE.' - '. $getRequest[1] . $_page . ' ';
24 | }else{
25 | $title = ''.SITE_TITLE.' - '.SITE_DESC.' ';
26 | }
27 | $metaDescription = ' ';
28 |
29 | foreach($entries as $id => $entry){
30 | foreach($entry['tag'] as $label){
31 | $tags[] = ''.$label.' ';
32 | }
33 | $format[] = '
34 |
35 |
36 | '.date('d-M-Y h:m', strtotime($entry['date'])).'
37 | '.implode(' ',$tags).'
38 |
39 |
40 |
41 | '.$post->getExcerpt($entry['entry'],250).'
42 |
43 |
';
44 | unset($tags);
45 | }
46 | $post->addWidget('index-top',implode('',$format));
47 | $post->addWidget('head',$title);
48 | $post->addWidget('head',$metaDescription);
49 | }
50 | if($_SINGLE_POST){
51 | foreach($entry['tag'] as $label){
52 | $tags[] = ''.$label.' ';
53 | }
54 | $title = ''.$entry['title'].' - '.SITE_TITLE.' ';
55 | $metaDescription = ' ';
56 | $format = '
57 |
58 | '.$entry['title'].'
59 | '.implode(' ',$tags).'
60 | '.$entry['entry'].'
61 |
62 |
';
63 | $post->addWidget('head',$title);
64 | $post->addWidget('head',$metaDescription);
65 | $post->addWidget('post-top',$format);
66 | }
67 |
68 | $header = sprintf('
69 | %s %s ',
70 | sprintf('%2$s ',SITE_URL,SITE_TITLE),SITE_DESC);
71 |
72 | $post->addWidget('header',$header);
73 | $generator = ' ';
74 | $post->addWidget('head',$generator);
75 | ?>
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 | widgetSection('head'); ?>
84 |
85 |
86 |
87 |
88 |
92 |
93 |
94 | widgetSection('top'); ?>
95 |
100 |
101 |
102 |
103 |
104 | widgetSection('index-top');
107 | $post->widgetSection('index-bottom');
108 | }else{
109 | $post->widgetSection('post-top');
110 | $post->widgetSection('post-bottom');
111 | }
112 | ?>
113 |
114 |
115 |
116 |
117 | widgetSection('sidebar1'); ?>
118 |
119 |
120 |
121 |
122 | widgetSection('sidebar2'); ?>
123 |
124 |
125 |
126 |
127 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
--------------------------------------------------------------------------------
/sp_theme/sedot_bootstrap/widget.php:
--------------------------------------------------------------------------------
1 | $count){
19 | $link = trim(SITE_URL,'/').'/tag/'.$name;
20 | $tags[] = ''.$name.' ';
21 | }
22 | $container = '';
23 | return sprintf($container,implode('',$tags));
24 | }
25 | function archives(){
26 | $archive = sedot::loadJson('index','archive');
27 | foreach($archive as $year => $x){
28 | foreach($x as $month => $y){
29 | $link = trim(SITE_URL,'/').'/timeline/'.$year.'/'.$month;
30 | $list[] = ''.date('F Y',strtotime($year.'-'.$month)).' ';
31 | }
32 | }
33 | $container = '';
34 | return sprintf($container,implode('',$list));
35 | }
36 | function pageNavi(){
37 | $url = ACTUAL_URL;
38 | $current = $this->page;
39 | $stack = $this->total;
40 | for($i = 1;$i <= $stack;$i++){$stack_temp[$i] = $i;}
41 | $stack = array_chunk($stack_temp,5,true);
42 | $out[] = ' ';
62 | return implode('',$out);
63 | }
64 | }
65 | ?>
--------------------------------------------------------------------------------