source: trunk/Modules/News/News.php@ 891

Last change on this file since 891 was 891, checked in by chronos, 4 years ago
  • Added: More modules models installation.
File size: 12.9 KB
Line 
1<?php
2
3include_once(dirname(__FILE__).'/NewsPage.php');
4include_once(dirname(__FILE__).'/NewsSource.php');
5include_once(dirname(__FILE__).'/Import/Vismo.php');
6
7function CategoryItemCompare($Item1, $Item2)
8{
9 if ($Item1['Index'] == $Item2['Index']) return 0;
10 return $Item1['Index'] > $Item2['Index'] ? -1 : 1;
11}
12
13class ModuleNews extends AppModule
14{
15 public int $NewsCountPerCategory = 3;
16 public string $UploadedFilesFolder = 'files/news/';
17
18 function __construct(System $System)
19 {
20 parent::__construct($System);
21 $this->Name = 'News';
22 $this->Version = '1.0';
23 $this->Creator = 'Chronos';
24 $this->License = 'GNU/GPL';
25 $this->Description = 'News and news groups management';
26 $this->Dependencies = array('User', 'Log', 'File');
27 $this->SupportedModules = array('Search');
28 }
29
30 static function GetModels(): array
31 {
32 return array(
33 'NewsCategory',
34 'News',
35 );
36 }
37
38 function DoInstall(): void
39 {
40 foreach (self::GetModels() as $Model)
41 {
42 $this->InstallModel($Model::GetDesc());
43 }
44 }
45
46 function DoUnInstall(): void
47 {
48 foreach (array_reverse(self::GetModels()) as $Model)
49 {
50 $this->UninstallModel($Model::GetDesc());
51 }
52 }
53
54 function DoStart(): void
55 {
56 $this->System->RegisterPage(['aktuality'], 'PageNews');
57 $this->System->RegisterPage(['aktuality', 'subscription'], 'PageNewsSubscription');
58 $this->System->RegisterPage(['aktuality', 'rss'], 'PageNewsRss');
59 $this->System->RegisterPage(['aktuality', 'aktualizace'], 'PageNewsUpdate');
60 $this->System->FormManager->RegisterClass('News', array(
61 'Title' => 'Aktualita',
62 'Table' => 'News',
63 'DefaultSortColumn' => 'Date',
64 'DefaultSortOrder' => 1,
65 'Items' => array(
66 'Category' => array('Type' => 'TNewsCategory', 'Caption' => 'Kategorie', 'Default' => 0),
67 'Title' => array('Type' => 'String', 'Caption' => 'Nadpis', 'Default' => ''),
68 'Content' => array('Type' => 'Text', 'Caption' => 'Obsah', 'Default' => ''),
69 'Date' => array('Type' => 'Date', 'Caption' => 'Datum', 'Default' => ''),
70 'Author' => array('Type' => 'String', 'Caption' => 'Autor', 'Default' => ''),
71 'Enclosure' => array('Type' => 'String', 'Caption' => 'Přílohy', 'Default' => ''),
72 'User' => array('Type' => 'TUser', 'Caption' => 'Uživatel', 'Default' => ''),
73 'IP' => array('Type' => 'IPv4Address', 'Caption' => 'IP adresa', 'Default' => '', 'ReadOnly' => true),
74 'Link' => array('Type' => 'Hyperlink', 'Caption' => 'Odkaz', 'Default' => ''),
75 ),
76 ));
77 $this->System->FormManager->RegisterClass('NewsCategory', array(
78 'Title' => 'Kategorie aktualit',
79 'Table' => 'NewsCategory',
80 'Items' => array(
81 'Caption' => array('Type' => 'String', 'Caption' => 'Titulek', 'Default' => ''),
82 'RSS' => array('Type' => 'Hyperlink', 'Caption' => 'Zdroj RSS', 'Default' => ''),
83 'Permission' => array('Type' => 'Boolean', 'Caption' => 'Veřejné upravitelné', 'Default' => ''),
84 'Sequence' => array('Type' => 'Integer', 'Caption' => 'Pořadí', 'Default' => ''),
85 'Group' => array('Type' => 'Integer', 'Caption' => 'Skupina', 'Default' => ''),
86 'News' => array('Type' => 'TNewsList', 'Caption' => 'Aktuality', 'Default' => ''),
87 ),
88 ));
89 $this->System->FormManager->RegisterFormType('TNewsCategory', array(
90 'Type' => 'Reference',
91 'Table' => 'NewsCategory',
92 'Id' => 'Id',
93 'Name' => 'Caption',
94 'Filter' => '1',
95 ));
96 $this->System->FormManager->RegisterFormType('TNewsList', array(
97 'Type' => 'ManyToOne',
98 'Table' => 'News',
99 'Id' => 'Id',
100 'Ref' => 'Category',
101 'Filter' => '1',
102 ));
103
104 if ($this->System->ModuleManager->ModulePresent('Search'))
105 {
106 ModuleSearch::Cast($this->System->GetModule('Search'))->RegisterSearch('Novinky', 'News', array('Title', 'Content'));
107 }
108 }
109
110 function ShowNews(string $Category, int $ItemCount, int $DaysAgo): string
111 {
112 $ItemCount = abs($ItemCount);
113 $DaysAgo = abs($DaysAgo);
114 $DbResult = $this->Database->select('NewsCategory', '*', 'Id='.$Category);
115 $Row = $DbResult->fetch_array();
116 $Output = '<div class="NewsPanel"><div class="Title">'.$Row['Caption'];
117 $Output .= '<div class="Action"><a href="aktuality/?category='.$Category.'">Zobrazit</a>';
118 if (ModuleUser::Cast($this->System->GetModule('User'))->User->CheckPermission('News', 'Insert', 'Group', $Category))
119 $Output .= ' <a href="aktuality/?action=add&amp;category='.$Category.'">Přidat</a>';
120 $Output .= '</div></div><div class="Content">';
121 $DbResult = $this->Database->query('SELECT `News`.*, `User`.`Name` FROM `News` LEFT JOIN `User` ON `User`.`Id`=`News`.`User` WHERE (`News`.`Category`='.$Category.') AND (DATE_SUB(NOW(), INTERVAL '.$DaysAgo.' DAY) < `News`.`Date`) ORDER BY `News`.`Date` DESC LIMIT 0,'.$ItemCount);
122
123 $Index = 0;
124 $FontSize = 12;
125 if ($DbResult->num_rows > 0)
126 {
127 $Output .= '<table class="NewsTable">';
128 while ($Row = $DbResult->fetch_array())
129 {
130 if ($Row['Name'] == '') $Author = $Row['Author'];
131 else $Author = $Row['Name'];
132 $Output .= '<tr><td onclick="window.location=\'aktuality/?action=view&amp;id='.$Row['Id'].
133 '\'" onmouseover="zobraz('."'new".$Category.$Index."'".')" style="cursor: pointer; margin: 0px;">'.
134 '<table class="NewsItemFrame"><tr><td style="font-size: '.$FontSize.'pt"><strong>'.$Row['Title'].'</strong></td>'.
135 '<td align="right" style="font-size: '.$FontSize.'pt">'.$Author.' ('.HumanDate($Row['Date']).')</td></tr></table>';
136 $Output .= '<div id="new'.$Category.$Index.'" class="NewsTableItem">'.$this->ModifyContent($Row['Content']);
137 if ($Row['Link'] != '') $Output .= '<br/><a href="'.$Row['Link'].'">Odkaz</a>';
138
139 if ($Row['Enclosure'] != '')
140 {
141 $Output .= '<br />Přílohy: ';
142 $Enclosures = explode(';', $Row['Enclosure']);
143 foreach ($Enclosures as $Enclosure)
144 {
145 if (file_exists($this->UploadedFilesFolder.$Enclosure))
146 $Output .= ' <a href="'.$this->UploadedFilesFolder.$Enclosure.'">'.$Enclosure.'</a>';
147 }
148 }
149 $Output .= '</div></td></tr>';
150 $Index = $Index + 1;
151 $FontSize = $FontSize - 1;
152 }
153 $Output .= '</table>';
154 }
155 $Output .= '</div></div>';
156 return $Output;
157 }
158
159 function LoadSettingsFromCookies(): void
160 {
161 // Initialize default news setting
162 $this->NewsSetting = array();
163 $I = 1;
164 $DbResult = $this->Database->select('NewsCategory', '*', '1 ORDER BY Sequence');
165 while ($NewsCategory = $DbResult->fetch_array())
166 {
167 $this->NewsSetting[] = array('CategoryId' => $NewsCategory['Id'], 'Index' => $I, 'Enabled' => 1,
168 'ItemCount' => $this->System->Config['Web']['News']['Count'], 'DaysAgo' => $this->System->Config['Web']['News']['DaysAgo'], 'Group' => $NewsCategory['Group']);
169 $I++;
170 }
171 // Merge defaults with user setting
172 if (array_key_exists('NewsSetting', $_COOKIE))
173 {
174 $NewsSettingCookie = unserialize($_COOKIE['NewsSetting']);
175 foreach ($this->NewsSetting as $Index => $this->NewSetting)
176 {
177 if (array_key_exists($Index, $NewsSettingCookie))
178 $this->NewsSetting[$Index] = array_merge($this->NewSetting, $NewsSettingCookie[$Index]);
179 }
180 }
181 }
182
183 function Show(): string
184 {
185 $Output = '';
186
187 $this->LoadSettingsFromCookies();
188
189 if (array_key_exists('Action', $_GET))
190 {
191 // Show news customize menu
192 if ($_GET['Action'] == 'CustomizeNews')
193 {
194 $Output .= $this->ShowCustomizeMenu();
195 }
196 }
197
198 $Output .= '<div onmouseout="skryj(predchozi)">';
199
200 $ColumnCount = 2;
201 $Output .= '<table style="width: 100%"><tr>';
202 for ($Column = 1; $Column <= $ColumnCount; $Column++)
203 {
204 $Output .= '<td style="vertical-align: top; width: '.round(100 / $ColumnCount).'%;">';
205 foreach ($this->NewsSetting as $SettingItem)
206 if (($SettingItem['Enabled'] == 1) and ($SettingItem['Group'] == $Column))
207 $Output .= $this->ShowNews($SettingItem['CategoryId'], $SettingItem['ItemCount'], $SettingItem['DaysAgo']);
208 $Output .= '</td>';
209 }
210 $Output .= '</tr></table>';
211
212 $Output .= '<a href="aktuality/subscription"><img class="RSSIcon" src="images/rss20.png" alt="Aktuality přes RSS" /></a> <a href="aktuality/subscription">Automatické sledování novinek</a>';
213 $Output .= '</div>';
214 return $Output;
215 }
216
217 function ShowCustomizeMenu(): string
218 {
219 $Output = '<form action="?Action=CustomizeNewsSave" method="post">';
220 $Output .= '<table width="100%" cellspacing="0" border="1"><tr><td><table cellspacing="0" width="100%">';
221 $Output .= '<tr><th>Kategorie</th><th>Pozice</th><th>Zobrazit</th><th>Max. počet</th><th>Posledních dnů</th><th>Sloupec</th></tr>';
222 $I = 0;
223 foreach ($this->NewsSetting as $SettingItem)
224 {
225 $DbResult = $this->Database->select('NewsCategory', '*', 'Id='.$SettingItem['CategoryId']);
226 $NewsCategory = $DbResult->fetch_array();
227 $Output .= '<tr><td>'.$NewsCategory['Caption'].'</td><td align="center"><input type="text" size="2" name="NewsCategoryIndex'.$I.'" value="'.$SettingItem['Index'].'" /></td><td align="center"><input type="checkbox" name="NewsCategoryEnabled'.$I.'"';
228 if ($SettingItem['Enabled'] == 1) $Output .= ' checked="checked"';
229 $Output .= ' /></td>'.
230 '<td align="center"><input type="text" size="2" name="NewsCategoryCount'.$I.'" value="'.$SettingItem['ItemCount'].'" />'.
231 '<input type="hidden" name="NewsCategoryId'.$I.'" value="'.$SettingItem['CategoryId'].'" /></td>'.
232 '<td align="center"><input type="text" size="3" name="NewsCategoryDaysAgo'.$I.'" value="'.$SettingItem['DaysAgo'].'" /></td>'.
233 '<td><input type="text" size="3" name="NewsColumn'.$I.'" value="'.$SettingItem['Group'].'"/></td></tr>';
234 $I++;
235 }
236 $Output .= '</table><input type="hidden" name="NewsCategoryCount" value="'.count($this->NewsSetting).'" /><input type="submit" value="Uložit" /></form></td></tr></table><br>';
237 return $Output;
238 }
239
240 function CustomizeSave(): void
241 {
242 $Checkbox = array('' => 0, 'on' => 1);
243 $Setting = array();
244 for ($I = 0; $I < $_POST['NewsCategoryCount']; $I++)
245 {
246 if (($_POST['NewsCategoryDaysAgo'.$I] * 1) < 0) $_POST['NewsCategoryIndex'.$I] = 0;
247 if (($_POST['NewsCategoryCount'.$I] * 1) < 0) $_POST['NewsCategoryCount'.$I] = 0;
248 if (($_POST['NewsColumn'.$I] * 1) < 1) $_POST['NewsColumn'.$I] = 1;
249 if (!array_key_exists('NewsCategoryEnabled'.$I, $_POST)) $_POST['NewsCategoryEnabled'.$I] = '';
250 $Setting[] = array('CategoryId' => $_POST['NewsCategoryId'.$I], 'Enabled' => $Checkbox[$_POST['NewsCategoryEnabled'.$I]], 'ItemCount' => ($_POST['NewsCategoryCount'.$I]*1), 'DaysAgo' => ($_POST['NewsCategoryDaysAgo'.$I]*1), 'Index' => ($_POST['NewsCategoryIndex'.$I]*1),
251 'Group' => $_POST['NewsColumn'.$I]);
252 }
253 // Sort indexes
254 usort($Setting, 'CategoryItemCompare');
255 $Setting = array_reverse($Setting);
256 // Normalize indexes
257 foreach ($Setting as $Index => $Item)
258 $Setting[$Index]['Index'] = $Index + 1;
259
260 // Store new cookie value
261 $_COOKIE['NewsSetting'] = serialize($Setting);
262 setcookie('NewsSetting', $_COOKIE['NewsSetting'], time() + 60 * 60 * 24 * 365);
263 }
264
265 function ModifyContent(string $Content): string
266 {
267 $Result = '';
268
269 // Make HTML link from URL
270 $I = 0;
271 while (strpos($Content, 'http://') !== false)
272 {
273 $I = strpos($Content, 'http://');
274 if (($I > 0) and ($Content[$I - 1] != '"'))
275 {
276 $Result .= substr($Content, 0, $I);
277 $Content = substr($Content, $I);
278 if (strpos($Content, ' ') !== false)
279 $URL = substr($Content, 0, strpos($Content, ' '));
280 else $URL = substr($Content, 0);
281 $Result .= '<a href="'.$URL.'">'.$URL.'</a>';
282 $Content = substr($Content, strlen($URL));
283 } else
284 {
285 $Result .= substr($Content, 0, $I + 1);
286 $Content = substr($Content, $I + 1);
287 }
288 }
289 $Result .= $Content;
290 return $Result;
291 }
292
293 static function Cast(AppModule $AppModule): ModuleNews
294 {
295 if ($AppModule instanceof ModuleNews)
296 {
297 return $AppModule;
298 }
299 throw new Exception('Expected ModuleNews type but got '.gettype($AppModule));
300 }
301}
302
303class News extends Model
304{
305 static function GetDesc(): ModelDesc
306 {
307 $Desc = new ModelDesc('News');
308 $Desc->AddReference('Category', 'NewsCategory', true);
309 $Desc->AddString('Title');
310 $Desc->AddText('Content');
311 $Desc->AddDate('Date');
312 $Desc->AddString('Author');
313 $Desc->AddString('Enclosure');
314 $Desc->AddReference('User', 'User');
315 $Desc->AddString('IP');
316 $Desc->AddString('Link');
317 return $Desc;
318 }
319}
320
321class NewsCategory extends Model
322{
323 static function GetDesc(): ModelDesc
324 {
325 $Desc = new ModelDesc('NewsCategory');
326 $Desc->AddString('Caption');
327 $Desc->AddString('RSS');
328 $Desc->AddBoolean('Permission');
329 $Desc->AddInteger('Sequence');
330 $Desc->AddInteger('Group');
331 return $Desc;
332 }
333}
Note: See TracBrowser for help on using the repository browser.