auth: admin permissions per function
[minimedit.git] / article.inc.php
1 <?php
2 global $monthname;
3 $monthname = ['?',
4         'januari', 'februari', 'maart', 'april', 'mei', 'juni',
5         'juli', 'augustus', 'september', 'oktober', 'november', 'december',
6 ];
7
8 function showdate($parts)
9 {
10         global $monthname;
11         return implode(' ', array_filter([
12                 intval(@$parts[2]), $parts[1] > 0 ? $monthname[intval($parts[1])] : '', $parts[0],
13                 count($parts) > 5 ? "$parts[3]:$parts[4]" : '',
14         ]));
15 }
16
17 class ArchiveArticle
18 {
19         public $raw, $preface, $title, $body;
20         public $meta = [];
21
22         function __construct($path)
23         {
24                 $this->page = $path;
25                 $this->link = preg_replace('{(?:/index)?\.html$}', '', $path);
26                 if (file_exists($this->page)) {
27                         $this->raw = file_get_contents($this->page);
28
29                         if (preg_match_all('{
30                                 \G <meta \s+ property="( [^"]+ )" \s+ content="( [^"]* )" > \s*
31                         }x', $this->raw, $meta)) {
32                                 $matchlen = array_sum(array_map('strlen', $meta[0]));
33                                 $this->raw = substr($this->raw, $matchlen); # delete matched contents
34                                 $this->meta = array_combine($meta[1], $meta[2]); # [property => content]
35                         }
36
37                         @list ($this->preface, $this->title, $this->body) =
38                                 preg_split('{<h2>(.*?)</h2>\s*}', $this->raw, 2, PREG_SPLIT_DELIM_CAPTURE);
39                 }
40         }
41
42         function __get($col)
43         {
44                 return $this->$col = $this->$col();  # run method and cache
45         }
46
47         function safetitle()
48         {
49                 return trim($this->meta['og:title'] ?? strip_tags($this->title));
50         }
51         function name()
52         {
53                 return $this->safetitle ?: $this->link;
54         }
55
56         function last()
57         {
58                 return filemtime($this->page);
59         }
60         function lastiso()
61         {
62                 return date(DATE_ATOM, $this->last);
63         }
64
65         function dateparts()
66         {
67                 preg_match('< / (\d{4}) [/-] (\d{2}) (?:- (\d{2}) )? - >x', $this->page, $ymd);
68                 array_shift($ymd);
69                 return $ymd;
70         }
71         function dateiso()
72         {
73                 return implode('-', $this->dateparts()) . 'T12:00:00+02:00';
74         }
75         function date()
76         {
77                 return showdate($this->dateparts);
78         }
79
80         function story()
81         {
82                 if ( preg_match('{
83                         \n (?: < (?: p | figure [^>]* ) >\s* )+ (<img\ [^>]*>) | \n <hr\ />
84                 }x', $this->body, $img, PREG_OFFSET_CAPTURE) ) {
85                         # strip part after matching divider (image)
86                         if (isset($img[1])) {
87                                 $this->img = $img[1][0];
88                         }
89                         return substr($this->body, 0, $img[0][1]);
90                 }
91                 return $this->body;
92         }
93
94         function teaser()
95         {
96                 if ($override = @$this->meta['og:description']) {
97                         # prefer specific page description if found in metadata
98                         return $override;
99                 }
100
101                 if (preg_match('{
102                         </h2> (?: \s+ | <p\sclass="nav\b.*?</p> | <div[^>]*> )* <p> \s* (.*?) </p>
103                 }sx', $this->raw, $bodyp, PREG_OFFSET_CAPTURE)) {
104                         # fallback paragraph contents following the page header
105                         if ($bodyp[1][1] < 256) {
106                                 return $bodyp[1][0];
107                         }
108                 }
109
110                 # starting paragraph for documents without title (assumed simple/partial)
111                 if (strpos($this->raw, '<h2') === FALSE and preg_match('{
112                         \A <p> \s* (.*?) </p>
113                 }sx', $this->raw, $bodyp)) {
114                         return $bodyp[1];
115                 }
116         }
117
118         function img()
119         {
120                 $this->img = NULL;
121                 $this->story;
122                 return $this->img;
123         }
124         function image()
125         {
126                 if ($override = @$this->meta['og:image']) {
127                         # prefer specific page image if found in metadata
128                         return $override;
129                 }
130
131                 if ( preg_match('/\bsrc="([^"]*)"/', $this->img, $src) ) {
132                         return $src[1];
133                 }
134         }
135         function thumb($size = '300x')
136         {
137                 if (!$this->image or $this->image[0] !== '/') return;
138                 return preg_replace(
139                         ['{^(?:/thumb/[^/]*)?}', '/\.groot(?=\.\w+$)/'], ["thumb/$size", ''],
140                         $this->image
141                 );
142         }
143 }