1
|
|
|
<?php |
|
|
|
|
2
|
|
|
/** |
3
|
|
|
* @title Design Class |
4
|
|
|
* @desc File containing HTML for display management. |
5
|
|
|
* |
6
|
|
|
* @author Pierre-Henry Soria <[email protected]> |
7
|
|
|
* @copyright (c) 2012-2019, Pierre-Henry Soria. All Rights Reserved. |
8
|
|
|
* @license CC-BY License - http://creativecommons.org/licenses/by/3.0/ |
9
|
|
|
* @package PH7 / Framework / Layout / Html |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
namespace PH7\Framework\Layout\Html; |
13
|
|
|
|
14
|
|
|
defined('PH7') or exit('Restricted access'); |
15
|
|
|
|
16
|
|
|
use PH7\AdminCore; |
17
|
|
|
use PH7\AffiliateCore; |
18
|
|
|
use PH7\DbTableName; |
19
|
|
|
use PH7\Framework\Benchmark\Benchmark; |
20
|
|
|
use PH7\Framework\Cache\Cache; |
21
|
|
|
use PH7\Framework\Core\Kernel; |
22
|
|
|
use PH7\Framework\File\File; |
23
|
|
|
use PH7\Framework\Geo\Ip\Geo; |
24
|
|
|
use PH7\Framework\Geo\Misc\Country; |
25
|
|
|
use PH7\Framework\Http\Http; |
26
|
|
|
use PH7\Framework\Ip\Ip; |
27
|
|
|
use PH7\Framework\Module\Various as SysMod; |
28
|
|
|
use PH7\Framework\Mvc\Model\DbConfig; |
29
|
|
|
use PH7\Framework\Mvc\Model\Engine\Db; |
30
|
|
|
use PH7\Framework\Mvc\Request\Http as HttpRequest; |
31
|
|
|
use PH7\Framework\Mvc\Router\Uri; |
32
|
|
|
use PH7\Framework\Navigation\Browser; |
33
|
|
|
use PH7\Framework\Navigation\Page; |
34
|
|
|
use PH7\Framework\Navigation\Pagination; |
35
|
|
|
use PH7\Framework\Parse\Url as UrlParser; |
36
|
|
|
use PH7\Framework\Registry\Registry; |
37
|
|
|
use PH7\Framework\Security\Validate\Validate; |
38
|
|
|
use PH7\Framework\Session\Session; |
39
|
|
|
use PH7\Framework\Str\Str; |
40
|
|
|
use PH7\Framework\Translate\Lang; |
41
|
|
|
use PH7\Framework\Url\Url; |
42
|
|
|
use PH7\GenderTypeUserCore; |
43
|
|
|
use PH7\UserCore; |
44
|
|
|
use PH7\UserCoreModel; |
45
|
|
|
|
46
|
|
|
class Design |
47
|
|
|
{ |
48
|
|
|
const CACHE_GROUP = 'str/design'; |
49
|
|
|
const CACHE_AVATAR_GROUP = 'str/design/avatar/'; // We put a slash for after creating a directory for each username |
50
|
|
|
const CACHE_AVATAR_LIFETIME = 3600; |
51
|
|
|
|
52
|
|
|
const NONE_FLAG_FILENAME = 'none.gif'; |
53
|
|
|
const FLAG_ICON_EXT = '.gif'; |
54
|
|
|
const AVATAR_IMG_EXT = '.svg'; |
55
|
|
|
|
56
|
|
|
const SUCCESS_TYPE = 'success'; |
57
|
|
|
const ERROR_TYPE = 'error'; |
58
|
|
|
const WARNING_TYPE = 'warning'; |
59
|
|
|
const INFO_TYPE = 'info'; |
60
|
|
|
|
61
|
|
|
const MESSAGE_TYPES = [ |
62
|
|
|
self::SUCCESS_TYPE, |
63
|
|
|
self::ERROR_TYPE, |
64
|
|
|
self::WARNING_TYPE, |
65
|
|
|
self::INFO_TYPE |
66
|
|
|
]; |
67
|
|
|
|
68
|
|
|
const FLASH_MSG = 'flash_msg'; |
69
|
|
|
const FLASH_TYPE = 'flash_type'; |
70
|
|
|
|
71
|
|
|
const DEFAULT_REDIRECTION_DELAY = 3; // In secs |
72
|
|
|
const MAX_MESSAGE_LENGTH_SHOWN = 300; |
73
|
|
|
const MAX_IP_LENGTH_SHOWN = 15; |
74
|
|
|
|
75
|
|
|
/** @var bool */ |
76
|
|
|
protected $bIsDiv = false; |
77
|
|
|
|
78
|
|
|
/** @var Str */ |
79
|
|
|
protected $oStr; |
80
|
|
|
|
81
|
|
|
/** @var Session */ |
82
|
|
|
protected $oSession; |
83
|
|
|
|
84
|
|
|
/** @var HttpRequest */ |
85
|
|
|
protected $oHttpRequest; |
86
|
|
|
|
87
|
|
|
/** @var array */ |
88
|
|
|
protected $aCssDir = []; |
89
|
|
|
|
90
|
|
|
/** @var array */ |
91
|
|
|
protected $aCssFiles = []; |
92
|
|
|
|
93
|
|
|
/** @var array */ |
94
|
|
|
protected $aCssMedia = []; |
95
|
|
|
|
96
|
|
|
/** @var array */ |
97
|
|
|
protected $aJsDir = []; |
98
|
|
|
|
99
|
|
|
/** @var array */ |
100
|
|
|
protected $aJsFiles = []; |
101
|
|
|
|
102
|
|
|
/** @var array */ |
103
|
|
|
protected $aMessages = []; |
104
|
|
|
|
105
|
|
|
/** @var array */ |
106
|
|
|
protected $aErrors = []; |
107
|
|
|
|
108
|
|
|
public function __construct() |
109
|
|
|
{ |
110
|
|
|
/** Instance objects for the class **/ |
111
|
|
|
$this->oStr = new Str; |
112
|
|
|
$this->oSession = new Session; |
113
|
|
|
$this->oHttpRequest = new HttpRequest; |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
public function langList() |
117
|
|
|
{ |
118
|
|
|
$sCurrentPage = Page::cleanDynamicUrl('l'); |
119
|
|
|
//$aLangs = (new File)->getDirList(Registry::getInstance()->path_module_lang); |
|
|
|
|
120
|
|
|
$aLangs = (new File)->getDirList(PH7_PATH_APP_LANG); |
121
|
|
|
|
122
|
|
|
foreach ($aLangs as $sLang) { |
123
|
|
|
if ($sLang === PH7_LANG_NAME) { |
124
|
|
|
// Skip the current lang |
125
|
|
|
continue; |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
// Get the first|last two-letter country code |
129
|
|
|
$sAbbrLang = Lang::getIsoCode($sLang, Lang::FIRST_ISO_CODE); |
130
|
|
|
$sFlagCountryCode = Lang::getIsoCode($sLang, Lang::LAST_ISO_CODE); |
131
|
|
|
|
132
|
|
|
echo '<a href="', $sCurrentPage, $sLang, '" hreflang="', $sAbbrLang, '"><img src="', PH7_URL_STATIC, PH7_IMG, 'flag/s/', $sFlagCountryCode, self::FLAG_ICON_EXT, '" alt="', t($sAbbrLang), '" title="', t($sAbbrLang), '" /></a> '; |
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
unset($aLangs); |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
/** |
139
|
|
|
* For better SEO optimization for multilingual sites. Ref: https://support.google.com/webmasters/answer/189077 |
140
|
|
|
* |
141
|
|
|
* @return void |
142
|
|
|
*/ |
143
|
|
|
public function regionalUrls() |
144
|
|
|
{ |
145
|
|
|
$sCurrentPage = Page::cleanDynamicUrl('l'); |
146
|
|
|
$aLangs = (new File)->getDirList(PH7_PATH_APP_LANG); |
147
|
|
|
|
148
|
|
|
echo '<link rel="alternate" hreflang="x-default" href="', PH7_URL_ROOT, '">'; // For pages that aren't specifically targeted |
149
|
|
|
foreach ($aLangs as $sLang) { |
150
|
|
|
// Get only the two-letter country code |
151
|
|
|
$sAbbrLang = Lang::getIsoCode($sLang); |
152
|
|
|
echo '<link rel="alternate" hreflang="', $sAbbrLang, '" href="', $sCurrentPage, $sLang, '" />'; |
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
unset($aLangs, $sCurrentPage); |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
/** |
159
|
|
|
* Set an information message. |
160
|
|
|
* |
161
|
|
|
* @param string $sMsg |
162
|
|
|
* |
163
|
|
|
* @return void |
164
|
|
|
*/ |
165
|
|
|
public function setMessage($sMsg) |
166
|
|
|
{ |
167
|
|
|
$this->aMessages[] = $sMsg; |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
/** |
171
|
|
|
* Display the information message. |
172
|
|
|
* |
173
|
|
|
* @return void |
174
|
|
|
*/ |
175
|
|
|
public function message() |
176
|
|
|
{ |
177
|
|
|
if ($this->oHttpRequest->getExists('msg')) { |
178
|
|
|
$this->aMessages[] = substr($this->oHttpRequest->get('msg'), 0, self::MAX_MESSAGE_LENGTH_SHOWN); |
179
|
|
|
} |
180
|
|
|
|
181
|
|
|
$iMsgNum = count($this->aMessages); |
182
|
|
|
/** Check if there are any messages in $aMessages array **/ |
183
|
|
|
if ($iMsgNum > 0) { |
184
|
|
|
$this->staticFiles('js', PH7_STATIC . PH7_JS, 'jquery/apprise.js'); |
185
|
|
|
|
186
|
|
|
echo '<script>$(function(){Apprise(\''; |
187
|
|
|
|
188
|
|
|
if ($iMsgNum > 1) { |
189
|
|
|
echo '<strong>', t('You have'), ' <em>', $iMsgNum, '</em> ', nt('message:', 'messages:', $iMsgNum), '</strong><br />'; |
190
|
|
|
} |
191
|
|
|
|
192
|
|
|
for ($iKey = 0; $iKey < $iMsgNum; $iKey++) { |
193
|
|
|
echo $this->oStr->upperFirst(str_replace('-', ' ', $this->aMessages[$iKey])), '<br />'; |
194
|
|
|
} |
195
|
|
|
|
196
|
|
|
echo '\')});</script>'; |
197
|
|
|
} |
198
|
|
|
|
199
|
|
|
unset($this->aMessages); |
200
|
|
|
} |
201
|
|
|
|
202
|
|
|
/** |
203
|
|
|
* Set an error message. |
204
|
|
|
* |
205
|
|
|
* @param string $sErr |
206
|
|
|
* |
207
|
|
|
* @return void |
208
|
|
|
*/ |
209
|
|
|
public function setError($sErr) |
210
|
|
|
{ |
211
|
|
|
$this->aErrors[] = $sErr; |
212
|
|
|
} |
213
|
|
|
|
214
|
|
|
/** |
215
|
|
|
* Display the error message. |
216
|
|
|
* |
217
|
|
|
* @return void |
218
|
|
|
*/ |
219
|
|
|
public function error() |
220
|
|
|
{ |
221
|
|
|
if ($this->oHttpRequest->getExists('err')) { |
222
|
|
|
$this->aErrors[] = substr($this->oHttpRequest->get('err'), 0, self::MAX_MESSAGE_LENGTH_SHOWN); |
223
|
|
|
} |
224
|
|
|
|
225
|
|
|
$iErrNum = count($this->aErrors); |
226
|
|
|
/** Check if there are any errors in $aErrors array **/ |
227
|
|
|
if ($iErrNum > 0) { |
228
|
|
|
$this->staticFiles('js', PH7_STATIC . PH7_JS, 'jquery/apprise.js'); |
229
|
|
|
|
230
|
|
|
echo '<script>$(function(){Apprise(\''; |
231
|
|
|
echo '<strong>', t('You have'), ' <em>', $iErrNum, '</em> ', nt('error:', 'errors:', $iErrNum), '</strong><br />'; |
232
|
|
|
|
233
|
|
|
for ($iKey = 0; $iKey < $iErrNum; $iKey++) { |
234
|
|
|
echo $this->oStr->upperFirst(str_replace('-', ' ', $this->aErrors[$iKey])), '<br />'; |
235
|
|
|
} |
236
|
|
|
|
237
|
|
|
echo '\')});</script>'; |
238
|
|
|
} |
239
|
|
|
|
240
|
|
|
unset($this->aErrors); |
241
|
|
|
} |
242
|
|
|
|
243
|
|
|
/** |
244
|
|
|
* Redirect Page using Refresh with Header. |
245
|
|
|
* |
246
|
|
|
* @param string $sUrl If NULL, the URL will be the current page. Default NULL |
247
|
|
|
* @param string $sMsg , Optional, display a message after redirect of the page. |
248
|
|
|
* @param string $sType Type of message: "success", "info", "warning" or "error". Default: "success". |
249
|
|
|
* @param int $iTime Optional, a time. Default: "3" seconds. |
250
|
|
|
* |
251
|
|
|
* @return void |
252
|
|
|
*/ |
253
|
|
|
public function setRedirect($sUrl = null, $sMsg = null, $sType = self::SUCCESS_TYPE, $iTime = self::DEFAULT_REDIRECTION_DELAY) |
254
|
|
|
{ |
255
|
|
|
if ($sMsg !== null) { |
256
|
|
|
$this->setFlashMsg($sMsg, $sType); |
257
|
|
|
} |
258
|
|
|
|
259
|
|
|
$sUrl = $sUrl !== null ? $sUrl : $this->oHttpRequest->currentUrl(); |
260
|
|
|
|
261
|
|
|
header('Refresh: ' . $iTime . '; URL=' . $this->oHttpRequest->pH7Url($sUrl)); |
262
|
|
|
} |
263
|
|
|
|
264
|
|
|
/** |
265
|
|
|
* Get stats from the benchmark. |
266
|
|
|
* |
267
|
|
|
* @return void HTML output. |
268
|
|
|
*/ |
269
|
|
|
public function stat() |
270
|
|
|
{ |
271
|
|
|
$iCountQueries = Db::queryCount(); |
272
|
|
|
$sRequest = nt('Query', 'Queries', $iCountQueries); |
273
|
|
|
|
274
|
|
|
$sMicrotime = microtime(true) - Registry::getInstance()->start_time; |
|
|
|
|
275
|
|
|
$sTime = Benchmark::readableElapsedTime($sMicrotime); |
276
|
|
|
$iMemory = Benchmark::readableSize(memory_get_usage(true)); |
277
|
|
|
|
278
|
|
|
echo t('Queries time %0% | %1% %2% | Generated in %3% | Memory allocated %4%', Db::time(), $iCountQueries, $sRequest, $sTime, $iMemory); |
279
|
|
|
} |
280
|
|
|
|
281
|
|
|
/** |
282
|
|
|
* Display accurate homepage URL. |
283
|
|
|
* |
284
|
|
|
* @return void The homepage URL output. |
285
|
|
|
*/ |
286
|
|
|
public function homePageUrl() |
287
|
|
|
{ |
288
|
|
|
if (UserCore::auth()) { |
289
|
|
|
if (SysMod::isEnabled('user-dashboard')) { |
290
|
|
|
$this->url('user-dashboard', 'main', 'index'); |
291
|
|
|
} else { |
292
|
|
|
$this->url('user', 'browse', 'index'); |
293
|
|
|
} |
294
|
|
|
} elseif (AdminCore::auth()) { |
295
|
|
|
$this->url(PH7_ADMIN_MOD, 'main', 'index'); |
296
|
|
|
} elseif (AffiliateCore::auth()) { |
297
|
|
|
$this->url('affiliate', 'account', 'index'); |
298
|
|
|
} else { |
299
|
|
|
echo PH7_URL_ROOT; |
300
|
|
|
} |
301
|
|
|
} |
302
|
|
|
|
303
|
|
|
/** |
304
|
|
|
* @param string $sModule |
305
|
|
|
* @param string $sController |
306
|
|
|
* @param string $sAction |
307
|
|
|
* @param null|string $sVars |
308
|
|
|
* @param bool $bClear |
309
|
|
|
* |
310
|
|
|
* @return void |
311
|
|
|
*/ |
312
|
|
|
public function url($sModule, $sController, $sAction, $sVars = null, $bClear = true) |
313
|
|
|
{ |
314
|
|
|
$sUrl = Uri::get($sModule, $sController, $sAction, $sVars, $bClear); |
315
|
|
|
|
316
|
|
|
echo Url::clean($sUrl); // For the URL parameters to avoid invalid HTML code |
317
|
|
|
} |
318
|
|
|
|
319
|
|
|
/** |
320
|
|
|
* Create a link of to display a popup confirmation for a CRUD action (http://en.wikipedia.org/wiki/Create,_read,_update_and_delete). |
321
|
|
|
* |
322
|
|
|
* @param string $sLabel |
323
|
|
|
* @param string $sMod |
324
|
|
|
* @param string $sCtrl |
325
|
|
|
* @param string $sAct |
326
|
|
|
* @param int|string $mId Content ID |
327
|
|
|
* @param string $sClass Add a CSS class |
328
|
|
|
* |
329
|
|
|
* @return void HTML output. |
330
|
|
|
*/ |
331
|
|
|
public function popupLinkConfirm($sLabel, $sMod, $sCtrl, $sAct, $mId, $sClass = null) |
332
|
|
|
{ |
333
|
|
|
$sClass = $sClass !== null ? ' class="' . $sClass . '" ' : ' '; |
334
|
|
|
|
335
|
|
|
$aHttpParams = [ |
336
|
|
|
'label' => Url::encode($sLabel), |
337
|
|
|
'mod' => $sMod, |
338
|
|
|
'ctrl' => $sCtrl, |
339
|
|
|
'act' => $sAct, |
340
|
|
|
'id' => Url::encode($mId) |
341
|
|
|
]; |
342
|
|
|
|
343
|
|
|
echo '<a', $sClass, 'href="', PH7_URL_ROOT, 'asset/ajax/popup/confirm/?', Url::httpBuildQuery($aHttpParams), '" data-popup="classic">', $sLabel, '</a>'; |
344
|
|
|
} |
345
|
|
|
|
346
|
|
|
/** |
347
|
|
|
* @param string $sCountryCode The Country Code (e.g., US = United States). |
348
|
|
|
* |
349
|
|
|
* @return void Output the Flag Icon Url. |
350
|
|
|
*/ |
351
|
|
|
public function getSmallFlagIcon($sCountryCode) |
352
|
|
|
{ |
353
|
|
|
$sIcon = $this->oStr->lower($sCountryCode) . self::FLAG_ICON_EXT; |
354
|
|
|
$sDir = PH7_URL_STATIC . PH7_IMG . 'flag/s/'; |
355
|
|
|
|
356
|
|
|
echo is_file(PH7_PATH_STATIC . PH7_IMG . 'flag/s/' . $sIcon) ? $sDir . $sIcon : $sDir . self::NONE_FLAG_FILENAME; |
357
|
|
|
} |
358
|
|
|
|
359
|
|
|
/** |
360
|
|
|
* @return string |
361
|
|
|
*/ |
362
|
|
|
final public function softwareComment() |
363
|
|
|
{ |
364
|
|
|
echo PageDna::generateHtmlComment(); |
365
|
|
|
} |
366
|
|
|
|
367
|
|
|
/** |
368
|
|
|
* Provide a "Powered By" link. |
369
|
|
|
* |
370
|
|
|
* @param bool $bLink To include a link to pH7CMS or pH7Framework. |
371
|
|
|
* @param bool $bSoftwareName |
372
|
|
|
* @param bool $bVersion To include the version being used. |
373
|
|
|
* @param bool $bComment HTML comment. |
374
|
|
|
* @param bool $bEmailContext Is it for email content or not. |
375
|
|
|
* |
376
|
|
|
* @return void |
377
|
|
|
*/ |
378
|
|
|
final public function link($bLink = true, $bSoftwareName = true, $bVersion = false, $bComment = true, $bEmailContext = false) |
379
|
|
|
{ |
380
|
|
|
if (!$bEmailContext && (bool)DbConfig::getSetting('displayPoweredByLink')) { |
381
|
|
|
if ($bLink) { |
382
|
|
|
$bSoftwareName = true; |
383
|
|
|
} |
384
|
|
|
|
385
|
|
|
echo ($bSoftwareName ? '<span class="italic">' . t('Big thanks to') : ''), ' <strong>', ($bLink ? '<a class="underline" href="' . Kernel::SOFTWARE_WEBSITE . '" title="' . Kernel::SOFTWARE_DESCRIPTION . '">' : ''), ($bSoftwareName ? Kernel::SOFTWARE_NAME : ''), ($bVersion ? ' ' . Kernel::SOFTWARE_VERSION : ''), ($bLink ? '</a>' : ''), ($bSoftwareName ? '</strong><span role="img" aria-label="love">❤️</span></span>' : ''); |
386
|
|
|
} |
387
|
|
|
|
388
|
|
|
if ($bComment) { |
389
|
|
|
echo ' |
390
|
|
|
<!-- ', sprintf(Kernel::SOFTWARE_COPYRIGHT, date('Y')), ' --> |
391
|
|
|
<!-- Powered by ', Kernel::SOFTWARE_NAME, ' ', Kernel::SOFTWARE_VERSION, ', Build ', Kernel::SOFTWARE_BUILD, ' --> |
392
|
|
|
<!-- This notice cannot be removed in any case. |
393
|
|
|
This open source software is distributed for free and you must respect the thousands of days, months and several years it took to develop it. |
394
|
|
|
Think to the developer who worked hard for years coding what you use. |
395
|
|
|
All rights reserved to ', Kernel::SOFTWARE_NAME, ', ', Kernel::SOFTWARE_COMPANY, ' |
396
|
|
|
You can never claim that you own the code, developed or helped the software if it is not the case -->'; |
397
|
|
|
} |
398
|
|
|
|
399
|
|
|
echo '<!-- "Powered by ', Kernel::SOFTWARE_NAME, ', ', Kernel::SOFTWARE_VERSION_NAME, ', ', Kernel::SOFTWARE_VERSION, ', Build ', Kernel::SOFTWARE_BUILD, ' -->'; |
400
|
|
|
} |
401
|
|
|
|
402
|
|
|
/** |
403
|
|
|
* Provide a small "Powered By" link (e.g., for sitemap.xsl.tpl). |
404
|
|
|
* |
405
|
|
|
* @return void |
406
|
|
|
*/ |
407
|
|
|
final public function smallLink() |
408
|
|
|
{ |
409
|
|
|
echo '<strong>', t('THANKS to'), ' <a href="', Kernel::SOFTWARE_WEBSITE, '" title="', Kernel::SOFTWARE_DESCRIPTION, '">', Kernel::SOFTWARE_NAME, '</a> ', Kernel::SOFTWARE_VERSION, '!</strong> <span role="img" aria-label="love">❤️</span>'; |
410
|
|
|
} |
411
|
|
|
|
412
|
|
|
/** |
413
|
|
|
* @return void Output the relevant link based on the client browser's language. |
414
|
|
|
*/ |
415
|
|
|
final public function smartLink() |
416
|
|
|
{ |
417
|
|
|
// Get Client's Language Code |
418
|
|
|
$sLangCode = (new Browser)->getLanguage(true); |
419
|
|
|
|
420
|
|
|
// Default links, set to English |
421
|
|
|
$aSites = [ |
422
|
|
|
['title' => 'Free Dating CMS', 'link' => Kernel::SOFTWARE_GIT_REPO_URL], |
423
|
|
|
['title' => 'Flirt Hot Girls', 'link' => 'http://01script.com/p/dooba'], |
424
|
|
|
['title' => 'Romance Dating', 'link' => 'http://love-rencontre.wekiss.net'], |
425
|
|
|
['title' => 'Date your Friends', 'link' => 'http://01script.com/p/dooba'] |
426
|
|
|
]; |
427
|
|
|
|
428
|
|
|
if ($sLangCode === 'en-ie') { |
429
|
|
|
$aSites[] = ['title' => 'FREE Flirt in Dublin City', 'link' => 'http://01script.com/p/dooba']; |
430
|
|
|
$aSites[] = ['title' => 'Date Dubs in the Town!', 'link' => 'http://01script.com/p/dooba']; |
431
|
|
|
} elseif ($sLangCode === 'en-gb') { |
432
|
|
|
$aSites[] = ['title' => 'Date Brits near from YOU', 'link' => 'http://01script.com/p/dooba']; |
433
|
|
|
$aSites[] = ['title' => 'Date Londoners', 'link' => 'http://01script.com/p/dooba']; |
434
|
|
|
} elseif (strpos($sLangCode, 'fr') !== false) { |
435
|
|
|
/** |
436
|
|
|
* Reset the array since we don't want to mix it up with different langs (default one is English, not French) |
437
|
|
|
*/ |
438
|
|
|
$aSites = [ |
439
|
|
|
['title' => 'Rencontre d\'un soir', 'link' => 'http://01script.com/p/dooba'], |
440
|
|
|
['title' => 'Flirt Coquin', 'link' => 'http://01script.com/p/dooba'], |
441
|
|
|
['title' => 'Rencontre amoureuse', 'link' => 'http://love-rencontre.wekiss.net'] |
442
|
|
|
]; |
443
|
|
|
} |
444
|
|
|
|
445
|
|
|
$aSite = $aSites[array_rand($aSites)]; |
446
|
|
|
echo '<a href="', $aSite['link'], '">', $aSite['title'], '</a>'; |
447
|
|
|
} |
448
|
|
|
|
449
|
|
|
/** |
450
|
|
|
* @param string $sType (js or css). |
451
|
|
|
* @param string $sDir |
452
|
|
|
* @param string $sFiles |
453
|
|
|
* @param string $sCssMedia Only works for CSS files. The CSS Media type (e.g., screen,handheld,tv,projection). Default "all". Leave blank ('' or null) not to use the media attribute. |
454
|
|
|
* |
455
|
|
|
* @return void |
456
|
|
|
*/ |
457
|
|
|
public function staticFiles($sType, $sDir, $sFiles, $sCssMedia = 'all') |
458
|
|
|
{ |
459
|
|
|
if ($sType === 'js') { |
460
|
|
|
echo $this->externalJsFile(PH7_RELATIVE . 'asset/gzip/?t=js&d=' . $sDir . '&f=' . $sFiles); |
461
|
|
|
} else { |
462
|
|
|
echo $this->externalCssFile(PH7_RELATIVE . 'asset/gzip/?t=css&d=' . $sDir . '&f=' . $sFiles, $sCssMedia); |
463
|
|
|
} |
464
|
|
|
} |
465
|
|
|
|
466
|
|
|
/** |
467
|
|
|
* @param string $sDir The CSS folder. |
468
|
|
|
* @param string $sFiles The CSS files. |
469
|
|
|
* @param string $sCssMedia CSS Media type (e.g., screen,handheld,tv,projection). Default "all". Leave blank ('' or null) not to use the media attribute. |
470
|
|
|
* |
471
|
|
|
* @return void |
472
|
|
|
*/ |
473
|
|
|
public function addCss($sDir, $sFiles, $sCssMedia = 'all') |
474
|
|
|
{ |
475
|
|
|
$this->aCssDir[] = $sDir; |
476
|
|
|
$this->aCssFiles[] = $sFiles; |
477
|
|
|
$this->aCssMedia[] = $sCssMedia; |
478
|
|
|
} |
479
|
|
|
|
480
|
|
|
/** |
481
|
|
|
* @param string $sDir The JavaScript folder. |
482
|
|
|
* @param string $sFiles The JavaScript files. |
483
|
|
|
* |
484
|
|
|
* @return void |
485
|
|
|
*/ |
486
|
|
|
public function addJs($sDir, $sFiles) |
487
|
|
|
{ |
488
|
|
|
$this->aJsDir[] = $sDir; |
489
|
|
|
$this->aJsFiles[] = $sFiles; |
490
|
|
|
} |
491
|
|
|
|
492
|
|
|
/** |
493
|
|
|
* @return void |
494
|
|
|
*/ |
495
|
|
|
public function css() |
496
|
|
|
{ |
497
|
|
|
for ($iKey = 0, $iCount = count($this->aCssDir); $iKey < $iCount; $iKey++) { |
498
|
|
|
$this->staticFiles('css', $this->aCssDir[$iKey], $this->aCssFiles[$iKey], $this->aCssMedia[$iKey]); |
499
|
|
|
} |
500
|
|
|
|
501
|
|
|
unset($this->aCssDir, $this->aCssFiles, $this->aCssMedia); |
502
|
|
|
} |
503
|
|
|
|
504
|
|
|
/** |
505
|
|
|
* @return void |
506
|
|
|
*/ |
507
|
|
|
public function js() |
508
|
|
|
{ |
509
|
|
|
for ($iKey = 0, $iCount = count($this->aJsDir); $iKey < $iCount; $iKey++) { |
510
|
|
|
$this->staticFiles('js', $this->aJsDir[$iKey], $this->aJsFiles[$iKey]); |
511
|
|
|
} |
512
|
|
|
|
513
|
|
|
unset($this->aJsDir, $this->aJsFiles); |
514
|
|
|
} |
515
|
|
|
|
516
|
|
|
/** |
517
|
|
|
* Set flash message. |
518
|
|
|
* |
519
|
|
|
* @param string $sMessage |
520
|
|
|
* @param string $sType Type of message: "Design::SUCCESS_TYPE", "Design::INFO_TYPE", "Design::WARNING_TYPE" or "Design::ERROR_TYPE" |
521
|
|
|
* |
522
|
|
|
* @return void |
523
|
|
|
*/ |
524
|
|
|
public function setFlashMsg($sMessage, $sType = self::SUCCESS_TYPE) |
525
|
|
|
{ |
526
|
|
|
/** Check the type of message, otherwise it's the default one **/ |
527
|
|
|
$sType = in_array($sType, self::MESSAGE_TYPES, true) ? $sType : self::SUCCESS_TYPE; |
528
|
|
|
$sType = $sType === self::ERROR_TYPE ? 'danger' : $sType; // Now the "error" CSS class has become "danger", so we have to convert it |
529
|
|
|
$this->oSession->set( |
530
|
|
|
[ |
531
|
|
|
self::FLASH_MSG => $sMessage, |
532
|
|
|
self::FLASH_TYPE => $sType |
533
|
|
|
] |
534
|
|
|
); |
535
|
|
|
} |
536
|
|
|
|
537
|
|
|
/** |
538
|
|
|
* Flash displays the message defined in the method setFlash. |
539
|
|
|
* |
540
|
|
|
* @return void The message text with CSS layout depending on the type of message. |
541
|
|
|
*/ |
542
|
|
|
public function flashMsg() |
543
|
|
|
{ |
544
|
|
|
$aFlashData = [ |
545
|
|
|
self::FLASH_MSG, |
546
|
|
|
self::FLASH_TYPE |
547
|
|
|
]; |
548
|
|
|
|
549
|
|
|
if ($this->oSession->exists($aFlashData)) { |
550
|
|
|
echo '<div class="center bold alert alert-', $this->oSession->get(self::FLASH_TYPE), '" role="alert">', $this->oSession->get(self::FLASH_MSG), '</div>'; |
551
|
|
|
|
552
|
|
|
$this->oSession->remove($aFlashData); |
553
|
|
|
} |
554
|
|
|
} |
555
|
|
|
|
556
|
|
|
/** |
557
|
|
|
* Show the user IP address with a link to get the IP information. |
558
|
|
|
* |
559
|
|
|
* @internal If it's an IPv6, show only the beginning, otherwise it would be too long in the template. |
560
|
|
|
* |
561
|
|
|
* @param string $sIp Allows to specify another IP address than the client one. |
562
|
|
|
* @param bool $bPrint Print or Return the HTML code. Default TRUE |
563
|
|
|
* |
564
|
|
|
* @return void|string |
565
|
|
|
*/ |
566
|
|
|
public function ip($sIp = null, $bPrint = true) |
567
|
|
|
{ |
568
|
|
|
$sIp = Ip::get($sIp); |
569
|
|
|
$sHtml = '<a href="' . Ip::api($sIp) . '" title="' . t('See info of this IP, %0%', $sIp) . '" target="_blank" rel="noopener noreferrer">' . $this->oStr->extract($sIp, self::MAX_IP_LENGTH_SHOWN) . '</a>'; |
|
|
|
|
570
|
|
|
|
571
|
|
|
if (!$bPrint) { |
572
|
|
|
return $sHtml; |
573
|
|
|
} |
574
|
|
|
|
575
|
|
|
echo $sHtml; |
576
|
|
|
} |
577
|
|
|
|
578
|
|
|
/** |
579
|
|
|
* Show the geolocation of the user (with link that points to the Country controller). |
580
|
|
|
* |
581
|
|
|
* @param bool $bPrint Print or Return the HTML code. Default TRUE |
582
|
|
|
* |
583
|
|
|
* @return void|string |
584
|
|
|
*/ |
585
|
|
|
public function geoIp($bPrint = true) |
586
|
|
|
{ |
587
|
|
|
$sCountry = Geo::getCountry(); |
588
|
|
|
$sCountryCode = Country::fixCode(Geo::getCountryCode()); |
589
|
|
|
$sCountryLang = t($sCountryCode); // Country name translated into the user language |
590
|
|
|
$sCity = Geo::getCity(); |
591
|
|
|
|
592
|
|
|
if (SysMod::isEnabled('map')) { |
593
|
|
|
$sHtml = '<a href="' . Uri::get('map', 'country', 'index', $sCountry . PH7_SH . $sCity) . '" title="' . t('Meet New People in %0%, %1% with %site_name%!', $sCountryLang, $sCity) . '">' . $sCity . '</a>'; |
594
|
|
|
} else { |
595
|
|
|
$sHtml = '<abbr title="' . t('Meet New People in %0%, %1% thanks %site_name%!', $sCountryLang, $sCity) . '">' . $sCity . '</abbr>'; |
596
|
|
|
} |
597
|
|
|
|
598
|
|
|
if (!$bPrint) { |
599
|
|
|
return $sHtml; |
600
|
|
|
} |
601
|
|
|
|
602
|
|
|
echo $sHtml; |
603
|
|
|
} |
604
|
|
|
|
605
|
|
|
/** |
606
|
|
|
* Pagination. |
607
|
|
|
* |
608
|
|
|
* @param int $iTotalPages |
609
|
|
|
* @param int $iCurrentPage |
610
|
|
|
* |
611
|
|
|
* @return void The HTML pagination code. |
612
|
|
|
*/ |
613
|
|
|
public function pagination($iTotalPages, $iCurrentPage) |
614
|
|
|
{ |
615
|
|
|
echo (new Pagination($iTotalPages, $iCurrentPage))->getHtmlCode(); |
616
|
|
|
} |
617
|
|
|
|
618
|
|
|
/** |
619
|
|
|
* @param string $sUsername |
620
|
|
|
* @param string $sSex |
621
|
|
|
* @param int $iSize |
622
|
|
|
* @param bool $bPrint Print or Return the HTML code. |
623
|
|
|
* |
624
|
|
|
* @return void|string The default 150px avatar URL or the user avatar URL. |
625
|
|
|
*/ |
626
|
|
|
public function getUserAvatar($sUsername, $sSex = '', $iSize = null, $bPrint = true) |
627
|
|
|
{ |
628
|
|
|
$oCache = (new Cache)->start( |
629
|
|
|
self::CACHE_AVATAR_GROUP . $sUsername, |
630
|
|
|
$sSex . $iSize, |
631
|
|
|
self::CACHE_AVATAR_LIFETIME |
632
|
|
|
); |
633
|
|
|
|
634
|
|
|
if (!$sUrl = $oCache->get()) { |
635
|
|
|
$oUserModel = new UserCoreModel; |
636
|
|
|
|
637
|
|
|
$iProfileId = $oUserModel->getId(null, $sUsername); |
638
|
|
|
$oGetAvatar = $oUserModel->getAvatar($iProfileId); |
639
|
|
|
|
640
|
|
|
$sSize = ($iSize == 32 || $iSize == 64 || $iSize == 100 || $iSize == 150 || $iSize == 200 || $iSize == 400) ? '-' . $iSize : ''; |
641
|
|
|
|
642
|
|
|
$sAvatar = @$oGetAvatar->pic; |
643
|
|
|
$sExt = PH7_DOT . (new File)->getFileExt($sAvatar); |
644
|
|
|
|
645
|
|
|
$sDir = 'user/avatar/img/' . $sUsername . PH7_SH; |
646
|
|
|
$sPath = PH7_PATH_PUBLIC_DATA_SYS_MOD . $sDir . $sAvatar; |
647
|
|
|
$sUrl = PH7_URL_DATA_SYS_MOD . $sDir . str_replace($sExt, $sSize . $sExt, $sAvatar); |
648
|
|
|
|
649
|
|
|
$bIsModerationMode = AdminCore::isAdminPanel(); |
650
|
|
|
|
651
|
|
|
if (!is_file($sPath) || $oGetAvatar->approvedAvatar == '0') { |
652
|
|
|
/* If sex is empty, it is recovered in the database using information from member */ |
653
|
|
|
$sSex = !empty($sSex) ? $sSex : $oUserModel->getSex(null, $sUsername, DbTableName::MEMBER); |
654
|
|
|
$sSex = $this->oStr->lower($sSex); |
655
|
|
|
$sIcon = (GenderTypeUserCore::isGenderValid($sSex) || $sSex === PH7_ADMIN_USERNAME) ? $sSex : 'visitor'; |
656
|
|
|
$sUrlTplName = defined('PH7_TPL_NAME') ? PH7_TPL_NAME : PH7_DEFAULT_THEME; |
657
|
|
|
|
658
|
|
|
/** If the user doesn't have an avatar **/ |
659
|
|
|
if (!is_file($sPath)) { |
660
|
|
|
/* The user has no avatar, we try to get a Gravatar */ |
661
|
|
|
|
662
|
|
|
// Get the User Email |
663
|
|
|
$sEmail = $oUserModel->getEmail($iProfileId); |
664
|
|
|
|
665
|
|
|
$bSecuredGravatar = Http::isSsl(); |
666
|
|
|
$sUrl = $this->getGravatarUrl($sEmail, '404', $iSize, 'g', $bSecuredGravatar); |
667
|
|
|
|
668
|
|
|
if (!(new Validate)->url($sUrl, true)) { |
669
|
|
|
// If no Gravatar set, it returns 404, and we then set the default pH7CMS's avatar |
670
|
|
|
$sUrl = PH7_URL_TPL . $sUrlTplName . PH7_SH . PH7_IMG . 'icon/' . $sIcon . '_no_picture' . $sSize . self::AVATAR_IMG_EXT; |
671
|
|
|
} |
672
|
|
|
} elseif (!$bIsModerationMode) { // We don't display pending approval image when admins are on the panel admin |
673
|
|
|
$sUrl = PH7_URL_TPL . $sUrlTplName . PH7_SH . PH7_IMG . 'icon/pending' . $sSize . self::AVATAR_IMG_EXT; |
674
|
|
|
} |
675
|
|
|
} |
676
|
|
|
unset($oUserModel); |
677
|
|
|
|
678
|
|
|
/** |
679
|
|
|
* @internal Clean URL for parameters in Gravatar URL to make the HTML code valid. |
680
|
|
|
* If we set replace '&' by '&' before checking the 404's Gravatar URL, it will always return '200 OK', that's why we need to clean the URL now. |
681
|
|
|
*/ |
682
|
|
|
$oCache->put(Url::clean($sUrl)); |
683
|
|
|
} |
684
|
|
|
|
685
|
|
|
unset($oCache); |
686
|
|
|
|
687
|
|
|
if (!$bPrint) { |
688
|
|
|
return $sUrl; |
689
|
|
|
} |
690
|
|
|
|
691
|
|
|
echo $sUrl; |
692
|
|
|
} |
693
|
|
|
|
694
|
|
|
/** |
695
|
|
|
* Get the user profile link. |
696
|
|
|
* |
697
|
|
|
* @param string $sUsername |
698
|
|
|
* @param bool $bPrint Print or Return the HTML code. |
699
|
|
|
* |
700
|
|
|
* @return void|string The absolute user profile link. |
701
|
|
|
*/ |
702
|
|
|
public function getProfileLink($sUsername, $bPrint = true) |
703
|
|
|
{ |
704
|
|
|
$sHtml = '<a href="'; |
705
|
|
|
$sHtml .= (new UserCore)->getProfileLink($sUsername); |
706
|
|
|
$sHtml .= '" title="' . t("%0%'s profile", $sUsername) . '">' . $sUsername . '</a>'; |
707
|
|
|
|
708
|
|
|
if (!$bPrint) { |
709
|
|
|
return $sHtml; |
710
|
|
|
} |
711
|
|
|
|
712
|
|
|
echo $sHtml; |
713
|
|
|
} |
714
|
|
|
|
715
|
|
|
/** |
716
|
|
|
* Get the Gravatar URL. |
717
|
|
|
* |
718
|
|
|
* @param string $sEmail The user email address. |
719
|
|
|
* @param string $sType Default image type to show [ 404 | mp | identicon | monsterid | wavatar ] |
720
|
|
|
* @param int $iSize The size of the image. Default: 80 |
721
|
|
|
* @param string $sRating The max image rating allowed. Default: 'g' (for all) |
722
|
|
|
* @param bool $bSecure Display avatar via HTTPS, for example if the site uses HTTPS, you should use this option to not get a warning with most Web browsers. Default: FALSE |
723
|
|
|
* |
724
|
|
|
* @return string The Gravatar Link. |
725
|
|
|
*/ |
726
|
|
|
public function getGravatarUrl($sEmail, $sType = 'wavatar', $iSize = 80, $sRating = 'g', $bSecure = false) |
727
|
|
|
{ |
728
|
|
|
$sProtocol = $bSecure ? 'https' : 'http'; |
729
|
|
|
$bSubDomain = $bSecure ? 'secure' : 'www'; |
730
|
|
|
|
731
|
|
|
return $sProtocol . '://' . $bSubDomain . '.gravatar.com/avatar/' . md5(strtolower($sEmail)) . '?d=' . $sType . '&s=' . $iSize . '&r=' . $sRating; |
732
|
|
|
} |
733
|
|
|
|
734
|
|
|
/** |
735
|
|
|
* Get favicon from a URL. |
736
|
|
|
* |
737
|
|
|
* @param string $sUrl |
738
|
|
|
* |
739
|
|
|
* @return void The HTML favicon image. |
740
|
|
|
*/ |
741
|
|
|
public function favicon($sUrl) |
742
|
|
|
{ |
743
|
|
|
$iFaviconSize = 16; |
744
|
|
|
$sImg = Browser::favicon($sUrl); |
745
|
|
|
$sName = Http::getHostName($sUrl); |
746
|
|
|
|
747
|
|
|
$this->imgTag( |
748
|
|
|
$sImg, |
749
|
|
|
$sName, |
|
|
|
|
750
|
|
|
[ |
751
|
|
|
'width' => $iFaviconSize, |
752
|
|
|
'height' => $iFaviconSize |
753
|
|
|
] |
754
|
|
|
); |
755
|
|
|
} |
756
|
|
|
|
757
|
|
|
/** |
758
|
|
|
* Like Link. |
759
|
|
|
* |
760
|
|
|
* @param string $sUsername Username of member. |
761
|
|
|
* @param string $sFirstName First name of member. |
762
|
|
|
* @param string $sSex Sex of member. |
763
|
|
|
* @param string $sForceUrlKey Specify a specific URL from the like. Default NULL (current URL). |
764
|
|
|
* |
765
|
|
|
* @return void |
766
|
|
|
*/ |
767
|
|
|
public function like($sUsername, $sFirstName, $sSex, $sForceUrlKey = null) |
768
|
|
|
{ |
769
|
|
|
$aHttpParams = [ |
770
|
|
|
'msg' => t('You need to be a member for liking contents.'), |
771
|
|
|
'ref' => $this->oHttpRequest->currentController(), |
772
|
|
|
'a' => 'like', |
773
|
|
|
'u' => $sUsername, |
774
|
|
|
'f_n' => $sFirstName, |
775
|
|
|
's' => $sSex |
776
|
|
|
]; |
777
|
|
|
|
778
|
|
|
$bIsLogged = UserCore::auth(); |
779
|
|
|
$sLikeLink = $bIsLogged ? '#' : Uri::get('user', 'signup', 'step1', '?' . Url::httpBuildQuery($aHttpParams), false); |
780
|
|
|
$sLikeId = $bIsLogged ? ' id="like"' : ''; |
781
|
|
|
|
782
|
|
|
$sUrlKey = empty($sForceUrlKey) ? $this->oHttpRequest->currentUrl() : $sForceUrlKey; |
783
|
|
|
echo '<a rel="nofollow" href="', $sLikeLink, '" data-key="', $sUrlKey, '" title="', t('Like %0%', $sFirstName), '" class="like smooth-pink"', $sLikeId, '>', t('Like %0%', $sFirstName), '</a>'; |
784
|
|
|
$this->staticFiles('js', PH7_STATIC . PH7_JS, 'Like.js'); |
785
|
|
|
} |
786
|
|
|
|
787
|
|
|
/** |
788
|
|
|
* Add Normal size Social Media Widgets. |
789
|
|
|
* |
790
|
|
|
* @internal AddToAny JS file will be included through 'ph7_static_files' table. |
791
|
|
|
* |
792
|
|
|
* @return void HTML output. |
793
|
|
|
*/ |
794
|
|
|
public function likeApi() |
795
|
|
|
{ |
796
|
|
|
if ((bool)DbConfig::getSetting('socialMediaWidgets')) { |
797
|
|
|
$sHtml = <<<HTML |
798
|
|
|
<div class="a2a_kit a2a_kit_size_32 a2a_default_style"> |
799
|
|
|
<a class="a2a_dd" href="https://www.addtoany.com/share" rel="nofollow"></a> |
800
|
|
|
<a class="a2a_button_facebook"></a> |
801
|
|
|
<a class="a2a_button_twitter"></a> |
802
|
|
|
<a class="a2a_button_pinterest"></a> |
803
|
|
|
<a class="a2a_button_facebook_messenger"></a> |
804
|
|
|
<a class="a2a_button_linkedin"></a> |
805
|
|
|
</div> |
806
|
|
|
HTML; |
807
|
|
|
echo $sHtml; |
808
|
|
|
} |
809
|
|
|
} |
810
|
|
|
|
811
|
|
|
/** |
812
|
|
|
* Add Small size Social Media Widgets. |
813
|
|
|
* |
814
|
|
|
* @internal AddToAny JS file will be included through 'ph7_static_files' table. |
815
|
|
|
* |
816
|
|
|
* @return void HTML output. |
817
|
|
|
*/ |
818
|
|
|
public function littleLikeApi() |
819
|
|
|
{ |
820
|
|
|
if ((bool)DbConfig::getSetting('socialMediaWidgets')) { |
821
|
|
|
$sHtml = <<<HTML |
822
|
|
|
<div class="a2a_kit a2a_kit_size_32 a2a_default_style"> |
823
|
|
|
<a class="a2a_dd" href="https://www.addtoany.com/share" rel="nofollow"></a> |
824
|
|
|
<a class="a2a_button_facebook"></a> |
825
|
|
|
<a class="a2a_button_twitter"></a> |
826
|
|
|
<a class="a2a_button_pinterest"></a> |
827
|
|
|
</div> |
828
|
|
|
HTML; |
829
|
|
|
echo $sHtml; |
830
|
|
|
} |
831
|
|
|
} |
832
|
|
|
|
833
|
|
|
/** |
834
|
|
|
* Generate a Report Link. |
835
|
|
|
* |
836
|
|
|
* @param int $iId |
837
|
|
|
* @param string $sUsername |
838
|
|
|
* @param string $sFirstName |
839
|
|
|
* @param string $sSex |
840
|
|
|
* |
841
|
|
|
* @internal We do not use Url::httpBuildQuery() method for the first condition otherwise the URL is distorted and it doesn't work. |
842
|
|
|
* |
843
|
|
|
* @return void |
844
|
|
|
*/ |
845
|
|
|
public function report($iId, $sUsername, $sFirstName, $sSex) |
846
|
|
|
{ |
847
|
|
|
$iId = (int)$iId; |
848
|
|
|
|
849
|
|
|
if ($iId > PH7_GHOST_ID) { |
850
|
|
|
if (UserCore::auth()) { |
851
|
|
|
$aUrlParams = [ |
852
|
|
|
'spammer' => $iId, |
853
|
|
|
'type' => Registry::getInstance()->module |
|
|
|
|
854
|
|
|
]; |
855
|
|
|
$sReportLink = Uri::get( |
856
|
|
|
'report', |
857
|
|
|
'main', |
858
|
|
|
'abuse', |
859
|
|
|
'?' . Url::httpBuildQuery($aUrlParams) . '&url=' . $this->oHttpRequest->currentUrl(), |
860
|
|
|
false |
861
|
|
|
); |
862
|
|
|
|
863
|
|
|
$sReportLink .= '" data-popup="block-page'; |
864
|
|
|
} else { |
865
|
|
|
$aUrlParams = [ |
866
|
|
|
'msg' => t('You need to be a user to report contents.'), |
867
|
|
|
'ref' => 'profile', |
868
|
|
|
'a' => 'report', |
869
|
|
|
'u' => $sUsername, |
870
|
|
|
'f_n' => $sFirstName, |
871
|
|
|
's' => $sSex |
872
|
|
|
]; |
873
|
|
|
$sReportLink = Uri::get('user', 'signup', 'step1', '?' . Url::httpBuildQuery($aUrlParams), false); |
874
|
|
|
} |
875
|
|
|
|
876
|
|
|
echo '<a rel="nofollow" href="', $sReportLink, '" title="', t('Report Abuse'), '"><i class="fa fa-flag smooth-pink"></i></a>'; |
877
|
|
|
} else { |
878
|
|
|
echo '<abbr title="' . t('Report feature is not available for this content since the user who posted that content has been removed.') . '""><i class="fa fa-flag smooth-pink"></i></abbr>'; |
879
|
|
|
} |
880
|
|
|
} |
881
|
|
|
|
882
|
|
|
/** |
883
|
|
|
* Generate a Link tag. |
884
|
|
|
* |
885
|
|
|
* @param string $sLink The link. |
886
|
|
|
* @param bool $bNoFollow Set TRUE to set the link "nofollow", FALSE otherwise. Default TRUE |
887
|
|
|
* |
888
|
|
|
* @return void The HTML link tag. |
889
|
|
|
*/ |
890
|
|
|
public function urlTag($sLink, $bNoFollow = true) |
891
|
|
|
{ |
892
|
|
|
$sLinkName = UrlParser::name($sLink); |
893
|
|
|
$aDefAttrs = ['href' => $sLink, 'title' => $sLinkName]; |
894
|
|
|
|
895
|
|
|
if ($bNoFollow) { |
896
|
|
|
/** |
897
|
|
|
* Add "nofollow" attribute if "$bNoFollow" is TURE |
898
|
|
|
* If TRUE, this means we don't trust the link and might be opened on a new tab, so add "noopener noreferrer" to prevent Reverse Tabnabbing attacks. |
899
|
|
|
*/ |
900
|
|
|
$aDefAttrs += ['rel' => 'nofollow noopener noreferrer']; |
901
|
|
|
} |
902
|
|
|
|
903
|
|
|
$this->htmlTag('a', $aDefAttrs, true, $sLinkName); |
904
|
|
|
} |
905
|
|
|
|
906
|
|
|
/** |
907
|
|
|
* Generate a IMG tag. |
908
|
|
|
* |
909
|
|
|
* @param string $sImg The image. |
910
|
|
|
* @param string $sAlt Alternate text. |
911
|
|
|
* @param array $aAttrs Optional. Array containing the "name" and "value" HTML attributes. Default NULL |
912
|
|
|
* |
913
|
|
|
* @return void The HTML image tag. |
914
|
|
|
*/ |
915
|
|
|
public function imgTag($sImg, $sAlt, array $aAttrs = null) |
916
|
|
|
{ |
917
|
|
|
$aDefAttrs = ['src' => $sImg, 'alt' => $sAlt]; |
918
|
|
|
|
919
|
|
|
if ($aAttrs !== null) { |
920
|
|
|
$aDefAttrs += $aAttrs; // Update the attributes if necessary |
921
|
|
|
} |
922
|
|
|
|
923
|
|
|
$this->htmlTag('img', $aDefAttrs); |
924
|
|
|
} |
925
|
|
|
|
926
|
|
|
/** |
927
|
|
|
* Generate any HTML tag. |
928
|
|
|
* |
929
|
|
|
* @param string $sTag |
930
|
|
|
* @param array $aAttrs Optional. Default NULL |
931
|
|
|
* @param bool $bPair Optional. Default FALSE |
932
|
|
|
* @param string $sText Optional. Add text, available only for pair tag. Default NULL |
933
|
|
|
* |
934
|
|
|
* @return string The custom HTML tag. |
935
|
|
|
*/ |
936
|
|
|
public function htmlTag($sTag, array $aAttrs = null, $bPair = false, $sText = null) |
937
|
|
|
{ |
938
|
|
|
$sAttrs = ''; |
939
|
|
|
|
940
|
|
|
if ($aAttrs !== null) { |
941
|
|
|
foreach ($aAttrs as $sName => $sValue) { |
942
|
|
|
$sAttrs .= ' ' . $sName . '="' . $sValue . '"'; |
943
|
|
|
} |
944
|
|
|
} |
945
|
|
|
|
946
|
|
|
echo ($bPair ? '<' . $sTag . $sAttrs . '>' . ($sText === null ? '' : $sText) . '</' . $sTag . '>' : '<' . $sTag . $sAttrs . ' />'); |
947
|
|
|
} |
948
|
|
|
|
949
|
|
|
public function htmlHeader() |
950
|
|
|
{ |
951
|
|
|
echo '<!DOCTYPE html>'; |
952
|
|
|
} |
953
|
|
|
|
954
|
|
|
/** |
955
|
|
|
* Useful HTML Header. |
956
|
|
|
* |
957
|
|
|
* @param array $aMeta Default NULL |
958
|
|
|
* @param bool $bLogo Default FALSE |
959
|
|
|
* |
960
|
|
|
* @return void |
961
|
|
|
*/ |
962
|
|
|
final public function usefulHtmlHeader(array $aMeta = null, $bLogo = false) |
963
|
|
|
{ |
964
|
|
|
$this->bIsDiv = true; |
965
|
|
|
|
966
|
|
|
// DO NOT REMOVE THE COPYRIGHT CODE BELOW! Thank you! |
967
|
|
|
echo '<html><head><meta charset="utf-8" /> |
968
|
|
|
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1" /> |
969
|
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> |
970
|
|
|
<title>', (!empty($aMeta['title']) ? $aMeta['title'] : ''), '</title>'; |
971
|
|
|
|
972
|
|
|
if (!empty($aMeta['description'])) { |
973
|
|
|
echo '<meta name="description" content="', $aMeta['description'], '" />'; |
974
|
|
|
} |
975
|
|
|
|
976
|
|
|
if (!empty($aMeta['keywords'])) { |
977
|
|
|
echo '<meta name="keywords" content="', $aMeta['keywords'], '" />'; |
978
|
|
|
} |
979
|
|
|
|
980
|
|
|
echo '<meta name="author" content="', Kernel::SOFTWARE_COMPANY, '" /> |
981
|
|
|
<meta name="copyright" content="', sprintf(Kernel::SOFTWARE_COPYRIGHT, date('Y')), '" /> |
982
|
|
|
<meta name="creator" content="', Kernel::SOFTWARE_NAME, '" /> |
983
|
|
|
<meta name="designer" content="', Kernel::SOFTWARE_NAME, '" /> |
984
|
|
|
<meta name="generator" content="', Kernel::SOFTWARE_NAME, ' ', Kernel::SOFTWARE_VERSION_NAME, ' ', Kernel::SOFTWARE_VERSION, ', Build ', Kernel::SOFTWARE_BUILD, '" />'; |
985
|
|
|
$this->softwareComment(); |
986
|
|
|
$this->externalCssFile(PH7_URL_STATIC . PH7_CSS . 'js/jquery/smoothness/jquery-ui.css'); |
987
|
|
|
$this->staticFiles('css', PH7_LAYOUT . PH7_TPL . PH7_DEFAULT_THEME . PH7_SH . PH7_CSS, 'common.css,style.css,form.css'); |
988
|
|
|
$this->externalJsFile(PH7_URL_STATIC . PH7_JS . 'jquery/jquery.js'); |
989
|
|
|
$this->externalJsFile(PH7_URL_STATIC . PH7_JS . 'jquery/jquery-ui.js'); |
990
|
|
|
echo '<script>var pH7Url={base:\'', PH7_URL_ROOT, '\'}</script></head><body>'; |
991
|
|
|
|
992
|
|
|
if ($bLogo) { |
993
|
|
|
// Website's name |
994
|
|
|
$sSiteName = Registry::getInstance()->site_name; |
|
|
|
|
995
|
|
|
|
996
|
|
|
// Check if the website's name exists, otherwise we displayed the software's name |
997
|
|
|
$sName = !empty($sSiteName) ? $sSiteName : Kernel::SOFTWARE_NAME; |
998
|
|
|
|
999
|
|
|
echo '<header> |
1000
|
|
|
<div role="banner" id="logo"><h1><a href="', PH7_URL_ROOT, '" title="', $sName, ' — ', Kernel::SOFTWARE_NAME, ', ', Kernel::SOFTWARE_COMPANY, '">', $sName, '</a></h1></div> |
1001
|
|
|
</header>'; |
1002
|
|
|
} |
1003
|
|
|
|
1004
|
|
|
echo $this->flashMsg(), '<div class="msg"></div><div class="m_marg">'; |
1005
|
|
|
} |
1006
|
|
|
|
1007
|
|
|
public function htmlFooter() |
1008
|
|
|
{ |
1009
|
|
|
if ($this->bIsDiv) { |
1010
|
|
|
echo '</div>'; |
1011
|
|
|
} |
1012
|
|
|
|
1013
|
|
|
echo '</body></html>'; |
1014
|
|
|
} |
1015
|
|
|
|
1016
|
|
|
/** |
1017
|
|
|
* The XML tag doesn't work in PHP files since it is the same "<?" language tag. |
1018
|
|
|
* So this method can introduce the XML header without causing an error by the PHP interpreter. |
1019
|
|
|
* |
1020
|
|
|
* @return void |
1021
|
|
|
*/ |
1022
|
|
|
public function xmlHeader() |
1023
|
|
|
{ |
1024
|
|
|
echo '<?xml version="1.0" encoding="utf-8"?>'; |
1025
|
|
|
} |
1026
|
|
|
|
1027
|
|
|
/** |
1028
|
|
|
* Get an external CSS file. |
1029
|
|
|
* |
1030
|
|
|
* @param string $sFile CSS file. |
1031
|
|
|
* @param string $sCssMedia Only works for CSS files. The CSS Media type (e.g., screen,handheld,tv,projection). Default NULL |
1032
|
|
|
* |
1033
|
|
|
* @return void HTML link tag. |
1034
|
|
|
*/ |
1035
|
|
|
public function externalCssFile($sFile, $sCssMedia = null) |
1036
|
|
|
{ |
1037
|
|
|
$sCssMedia = $sCssMedia !== null ? ' media="' . $sCssMedia . '"' : ''; |
1038
|
|
|
|
1039
|
|
|
echo '<link rel="stylesheet" href="', $sFile, '"', $sCssMedia, ' />'; |
1040
|
|
|
} |
1041
|
|
|
|
1042
|
|
|
/** |
1043
|
|
|
* Get an external JS file. |
1044
|
|
|
* |
1045
|
|
|
* @param string $sFile JS file. |
1046
|
|
|
* |
1047
|
|
|
* @return void HTML script tag. |
1048
|
|
|
*/ |
1049
|
|
|
public function externalJsFile($sFile) |
1050
|
|
|
{ |
1051
|
|
|
echo '<script src="', $sFile, '"></script>'; |
1052
|
|
|
} |
1053
|
|
|
} |
1054
|
|
|
|
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.