[738] | 1 | <?php
|
---|
| 2 |
|
---|
| 3 | include_once(dirname(__FILE__).'/NewsPage.php');
|
---|
[878] | 4 | include_once(dirname(__FILE__).'/NewsSource.php');
|
---|
| 5 | include_once(dirname(__FILE__).'/Import/Vismo.php');
|
---|
[738] | 6 |
|
---|
| 7 | function CategoryItemCompare($Item1, $Item2)
|
---|
| 8 | {
|
---|
[874] | 9 | if ($Item1['Index'] == $Item2['Index']) return 0;
|
---|
| 10 | return $Item1['Index'] > $Item2['Index'] ? -1 : 1;
|
---|
[738] | 11 | }
|
---|
| 12 |
|
---|
| 13 | class ModuleNews extends AppModule
|
---|
| 14 | {
|
---|
[887] | 15 | public int $NewsCountPerCategory = 3;
|
---|
| 16 | public string $UploadedFilesFolder = 'files/news/';
|
---|
[738] | 17 |
|
---|
[887] | 18 | function __construct(System $System)
|
---|
[738] | 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 |
|
---|
[891] | 30 | static function GetModels(): array
|
---|
| 31 | {
|
---|
| 32 | return array(
|
---|
| 33 | 'NewsCategory',
|
---|
| 34 | 'News',
|
---|
| 35 | );
|
---|
| 36 | }
|
---|
| 37 |
|
---|
[887] | 38 | function DoInstall(): void
|
---|
[738] | 39 | {
|
---|
[891] | 40 | foreach (self::GetModels() as $Model)
|
---|
| 41 | {
|
---|
| 42 | $this->InstallModel($Model::GetDesc());
|
---|
| 43 | }
|
---|
[738] | 44 | }
|
---|
| 45 |
|
---|
[887] | 46 | function DoUnInstall(): void
|
---|
[738] | 47 | {
|
---|
[891] | 48 | foreach (array_reverse(self::GetModels()) as $Model)
|
---|
| 49 | {
|
---|
| 50 | $this->UninstallModel($Model::GetDesc());
|
---|
| 51 | }
|
---|
[738] | 52 | }
|
---|
| 53 |
|
---|
[887] | 54 | function DoStart(): void
|
---|
[738] | 55 | {
|
---|
[887] | 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');
|
---|
[738] | 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 |
|
---|
[873] | 104 | if ($this->System->ModuleManager->ModulePresent('Search'))
|
---|
[738] | 105 | {
|
---|
[887] | 106 | ModuleSearch::Cast($this->System->GetModule('Search'))->RegisterSearch('Novinky', 'News', array('Title', 'Content'));
|
---|
[738] | 107 | }
|
---|
| 108 | }
|
---|
| 109 |
|
---|
[887] | 110 | function ShowNews(string $Category, int $ItemCount, int $DaysAgo): string
|
---|
[738] | 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>';
|
---|
[887] | 118 | if (ModuleUser::Cast($this->System->GetModule('User'))->User->CheckPermission('News', 'Insert', 'Group', $Category))
|
---|
[738] | 119 | $Output .= ' <a href="aktuality/?action=add&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;
|
---|
[873] | 125 | if ($DbResult->num_rows > 0)
|
---|
[738] | 126 | {
|
---|
| 127 | $Output .= '<table class="NewsTable">';
|
---|
[873] | 128 | while ($Row = $DbResult->fetch_array())
|
---|
[738] | 129 | {
|
---|
[873] | 130 | if ($Row['Name'] == '') $Author = $Row['Author'];
|
---|
[738] | 131 | else $Author = $Row['Name'];
|
---|
| 132 | $Output .= '<tr><td onclick="window.location=\'aktuality/?action=view&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']);
|
---|
[873] | 137 | if ($Row['Link'] != '') $Output .= '<br/><a href="'.$Row['Link'].'">Odkaz</a>';
|
---|
[738] | 138 |
|
---|
[873] | 139 | if ($Row['Enclosure'] != '')
|
---|
[738] | 140 | {
|
---|
| 141 | $Output .= '<br />Přílohy: ';
|
---|
| 142 | $Enclosures = explode(';', $Row['Enclosure']);
|
---|
[873] | 143 | foreach ($Enclosures as $Enclosure)
|
---|
[738] | 144 | {
|
---|
[873] | 145 | if (file_exists($this->UploadedFilesFolder.$Enclosure))
|
---|
[738] | 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>';
|
---|
[874] | 156 | return $Output;
|
---|
[738] | 157 | }
|
---|
| 158 |
|
---|
[887] | 159 | function LoadSettingsFromCookies(): void
|
---|
[738] | 160 | {
|
---|
| 161 | // Initialize default news setting
|
---|
| 162 | $this->NewsSetting = array();
|
---|
| 163 | $I = 1;
|
---|
| 164 | $DbResult = $this->Database->select('NewsCategory', '*', '1 ORDER BY Sequence');
|
---|
[873] | 165 | while ($NewsCategory = $DbResult->fetch_array())
|
---|
[738] | 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
|
---|
[873] | 172 | if (array_key_exists('NewsSetting', $_COOKIE))
|
---|
[738] | 173 | {
|
---|
| 174 | $NewsSettingCookie = unserialize($_COOKIE['NewsSetting']);
|
---|
[873] | 175 | foreach ($this->NewsSetting as $Index => $this->NewSetting)
|
---|
[738] | 176 | {
|
---|
[873] | 177 | if (array_key_exists($Index, $NewsSettingCookie))
|
---|
[738] | 178 | $this->NewsSetting[$Index] = array_merge($this->NewSetting, $NewsSettingCookie[$Index]);
|
---|
| 179 | }
|
---|
| 180 | }
|
---|
| 181 | }
|
---|
| 182 |
|
---|
[887] | 183 | function Show(): string
|
---|
[738] | 184 | {
|
---|
| 185 | $Output = '';
|
---|
| 186 |
|
---|
| 187 | $this->LoadSettingsFromCookies();
|
---|
| 188 |
|
---|
[873] | 189 | if (array_key_exists('Action', $_GET))
|
---|
[738] | 190 | {
|
---|
| 191 | // Show news customize menu
|
---|
[873] | 192 | if ($_GET['Action'] == 'CustomizeNews')
|
---|
[738] | 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>';
|
---|
[873] | 202 | for ($Column = 1; $Column <= $ColumnCount; $Column++)
|
---|
[738] | 203 | {
|
---|
| 204 | $Output .= '<td style="vertical-align: top; width: '.round(100 / $ColumnCount).'%;">';
|
---|
[873] | 205 | foreach ($this->NewsSetting as $SettingItem)
|
---|
| 206 | if (($SettingItem['Enabled'] == 1) and ($SettingItem['Group'] == $Column))
|
---|
[738] | 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>';
|
---|
[874] | 214 | return $Output;
|
---|
[738] | 215 | }
|
---|
| 216 |
|
---|
[887] | 217 | function ShowCustomizeMenu(): string
|
---|
[738] | 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;
|
---|
[873] | 223 | foreach ($this->NewsSetting as $SettingItem)
|
---|
[738] | 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.'"';
|
---|
[873] | 228 | if ($SettingItem['Enabled'] == 1) $Output .= ' checked="checked"';
|
---|
[738] | 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>';
|
---|
[874] | 237 | return $Output;
|
---|
[738] | 238 | }
|
---|
| 239 |
|
---|
[887] | 240 | function CustomizeSave(): void
|
---|
[738] | 241 | {
|
---|
| 242 | $Checkbox = array('' => 0, 'on' => 1);
|
---|
| 243 | $Setting = array();
|
---|
[873] | 244 | for ($I = 0; $I < $_POST['NewsCategoryCount']; $I++)
|
---|
[738] | 245 | {
|
---|
[873] | 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] = '';
|
---|
[738] | 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
|
---|
[873] | 257 | foreach ($Setting as $Index => $Item)
|
---|
[738] | 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 |
|
---|
[887] | 265 | function ModifyContent(string $Content): string
|
---|
[738] | 266 | {
|
---|
| 267 | $Result = '';
|
---|
| 268 |
|
---|
| 269 | // Make HTML link from URL
|
---|
| 270 | $I = 0;
|
---|
[873] | 271 | while (strpos($Content, 'http://') !== false)
|
---|
[738] | 272 | {
|
---|
| 273 | $I = strpos($Content, 'http://');
|
---|
[887] | 274 | if (($I > 0) and ($Content[$I - 1] != '"'))
|
---|
[738] | 275 | {
|
---|
| 276 | $Result .= substr($Content, 0, $I);
|
---|
| 277 | $Content = substr($Content, $I);
|
---|
[873] | 278 | if (strpos($Content, ' ') !== false)
|
---|
[738] | 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;
|
---|
[874] | 290 | return $Result;
|
---|
[738] | 291 | }
|
---|
[887] | 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 | }
|
---|
[738] | 301 | }
|
---|
[891] | 302 |
|
---|
| 303 | class 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 |
|
---|
| 321 | class 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 | }
|
---|