vendor/oveleon/contao-cookiebar/src/Resources/contao/classes/Cookiebar.php line 174

Open in your IDE?
  1. <?php
  2. /**
  3. * This file is part of Oveleon Contao Cookiebar.
  4. *
  5. * @package contao-cookiebar
  6. * @license AGPL-3.0
  7. * @author Daniele Sciannimanica <https://github.com/doishub>
  8. * @copyright Oveleon <https://www.oveleon.de/>
  9. */
  10. namespace Oveleon\ContaoCookiebar;
  11. use Contao\Cache;
  12. use Contao\DataContainer;
  13. use Contao\Environment;
  14. use Contao\FrontendTemplate;
  15. use Contao\Input;
  16. use Contao\PageModel;
  17. use Contao\StringUtil;
  18. use Contao\System;
  19. use Doctrine\DBAL\Connection;
  20. use FOS\HttpCache\ResponseTagger;
  21. use Oveleon\ContaoCookiebar\DependencyInjection\Configuration;
  22. use Oveleon\ContaoCookiebar\Exception\NoCookiebarSpecifiedException;
  23. use Symfony\Component\HttpFoundation\IpUtils;
  24. class Cookiebar
  25. {
  26. /**
  27. * Config cache
  28. * @var null
  29. */
  30. static private $configCache = null;
  31. /**
  32. * Create and return config object
  33. *
  34. * @param integer $configId
  35. * @param null $objMeta
  36. *
  37. * @return object
  38. */
  39. public static function getConfig($configId, $objMeta=null)
  40. {
  41. if(null !== static::$configCache)
  42. {
  43. return static::$configCache;
  44. }
  45. $objCookiebar = CookiebarModel::findById($configId);
  46. if(null === $objCookiebar)
  47. {
  48. throw new NoCookiebarSpecifiedException('No cookiebar specified');
  49. }
  50. $objCookieGroups = CookieGroupModel::findPublishedByPid($objCookiebar->id);
  51. if(null === $objCookieGroups)
  52. {
  53. return null;
  54. }
  55. $objConfig = $objCookiebar->current();
  56. $arrGroups = [];
  57. // Overwrite metadata
  58. if(null !== $objMeta)
  59. {
  60. $objConfig->description = $objMeta->cookiebarDescription;
  61. $objConfig->infoDescription = $objMeta->cookiebarInfoDescription;
  62. $objConfig->infoUrls = $objMeta->cookiebarInfoUrls;
  63. $objConfig->excludePages = $objMeta->cookiebarExcludePages;
  64. $objConfig->buttonColorScheme = $objMeta->cookiebarButtonColorScheme;
  65. $objConfig->template = $objMeta->cookiebarTemplate;
  66. $objConfig->alignment = $objMeta->cookiebarAlignment;
  67. $objConfig->blocking = $objMeta->cookiebarBlocking;
  68. $objConfig->hideOnInit = $objMeta->cookiebarHideOnInit;
  69. }
  70. DataContainer::loadDataContainer('tl_cookie');
  71. while($objCookieGroups->next())
  72. {
  73. $objGroup = $objCookieGroups->current();
  74. $arrCookies = [];
  75. $objCookies = CookieModel::findPublishedByPid($objCookieGroups->id);
  76. if(null !== $objCookies)
  77. {
  78. while($objCookies->next())
  79. {
  80. if(
  81. ($objCookies->token === 'csrf_contao_csrf_token' && Environment::get('ssl')) ||
  82. ($objCookies->token === 'csrf_https-contao_csrf_token' && !Environment::get('ssl'))
  83. )
  84. {
  85. continue;
  86. }
  87. // Adding the global configuration with checking whether this may be used
  88. $strTypePalette = $GLOBALS['TL_DCA']['tl_cookie']['palettes'][$objCookies->type] ?? false;
  89. if($objCookies->globalConfig && $strTypePalette && strpos($strTypePalette, 'globalConfig') !== false)
  90. {
  91. $intConfigKey = $objCookies->globalConfig;
  92. $strConfigKey = 'ccb_global_config';
  93. $arrConfigs = Cache::has($strConfigKey) ? Cache::get($strConfigKey) : null;
  94. if(null === $arrConfigs || !array_key_exists($intConfigKey, $arrConfigs))
  95. {
  96. /** @var CookieConfigModel $objConfigModel */
  97. $objConfigModel = CookieConfigModel::findById($intConfigKey);
  98. if(null !== $objConfigModel)
  99. {
  100. $objGlobalConfig = new CookieConfig($objConfigModel);
  101. $objGlobalConfig->addCookie( $objCookies->current() );
  102. $arrConfigs[ $intConfigKey ] = $objGlobalConfig;
  103. Cache::set($strConfigKey, $arrConfigs);
  104. }
  105. }
  106. else
  107. {
  108. /** @var CookieConfig $objGlobalConfig */
  109. $objGlobalConfig = $arrConfigs[ $intConfigKey ];
  110. $objGlobalConfig->addCookie( $objCookies->current() );
  111. $arrConfigs[ $intConfigKey ] = $objGlobalConfig;
  112. Cache::set($strConfigKey, $arrConfigs);
  113. }
  114. }
  115. $arrCookies[] = new CookieHandler($objCookies->current());
  116. }
  117. }
  118. $objGroup->hasCookies = count($arrCookies);
  119. $objGroup->isLocked = $objGroup->identifier === 'lock';
  120. $objGroup->cookies = $arrCookies;
  121. $arrGroups[] = $objGroup;
  122. }
  123. global $objPage;
  124. $objConfig->groups = $arrGroups;
  125. $objConfig->pageId = $objPage->rootId;
  126. $objConfig->configs = null;
  127. // Add global configuration
  128. if(Cache::has('ccb_global_config'))
  129. {
  130. $objConfig->configs = Cache::get('ccb_global_config');
  131. }
  132. // Cache config
  133. static::$configCache = $objConfig;
  134. return $objConfig;
  135. }
  136. /**
  137. * Return config by page
  138. *
  139. * @param $varPage
  140. *
  141. * @return object|null
  142. */
  143. public static function getConfigByPage($varPage)
  144. {
  145. if(!($varPage instanceof PageModel))
  146. {
  147. $objPage = PageModel::findById( $varPage );
  148. }else $objPage = $varPage;
  149. if(!$objPage->activateCookiebar)
  150. {
  151. return null;
  152. }
  153. return static::getConfig($objPage->cookiebarConfig, !!$objPage->overwriteCookiebarMeta ? $objPage : null);
  154. }
  155. /**
  156. * Returns all configurations [id => title]
  157. *
  158. * @return array
  159. */
  160. public static function getConfigurationList(): array
  161. {
  162. $objCookiebars = CookiebarModel::findAll();
  163. $arrCookiebars = [];
  164. if(null != $objCookiebars)
  165. {
  166. while($objCookiebars->next())
  167. {
  168. $arrCookiebars[ $objCookiebars->id ] = $objCookiebars->title;
  169. }
  170. }
  171. return $arrCookiebars;
  172. }
  173. /**
  174. * Return all iFrame-Types
  175. *
  176. * @return array|null
  177. */
  178. public static function getIframeTypes(): ?array
  179. {
  180. return System::getContainer()->getParameter('contao_cookiebar.iframe_types');
  181. }
  182. /**
  183. * Parse Cookiebar template
  184. *
  185. * @param $objConfig
  186. * @return string
  187. */
  188. public static function parseCookiebarTemplate($objConfig)
  189. {
  190. System::loadLanguageFile('tl_cookiebar');
  191. /** @var FrontendTemplate $objTemplate */
  192. $objTemplate = new FrontendTemplate($objConfig->template);
  193. $cssID = unserialize($objConfig->cssID);
  194. $objTemplate->cssID = $cssID[0];
  195. $objTemplate->class = $cssID[1] ? $objConfig->template . ' ' . $objConfig->alignment . ' ' . trim($cssID[1]) : $objConfig->template . ' ' . $objConfig->alignment;
  196. if($objConfig->blocking)
  197. {
  198. $objTemplate->class .= ' cc-blocked';
  199. }
  200. $objTemplate->description = $objConfig->description;
  201. $objTemplate->buttonColorScheme = $objConfig->buttonColorScheme;
  202. $objTemplate->infoDescription = $objConfig->infoDescription;
  203. $objTemplate->groups = $objConfig->groups;
  204. $objTemplate->saveLabel = $GLOBALS['TL_LANG']['tl_cookiebar']['saveLabel'];
  205. $objTemplate->acceptAllLabel = $GLOBALS['TL_LANG']['tl_cookiebar']['acceptAllLabel'];
  206. $objTemplate->denyAllLabel = $GLOBALS['TL_LANG']['tl_cookiebar']['denyAllLabel'];
  207. $objTemplate->infoLabel = $GLOBALS['TL_LANG']['tl_cookiebar']['infoLabel'];
  208. $objTemplate->showDetailsLabel = $GLOBALS['TL_LANG']['tl_cookiebar']['showDetailsLabel'];
  209. $objTemplate->hideDetailsLabel = $GLOBALS['TL_LANG']['tl_cookiebar']['hideDetailsLabel'];
  210. $objTemplate->showMoreDetailsLabel = $GLOBALS['TL_LANG']['tl_cookiebar']['showMoreDetailsLabel'];
  211. $objTemplate->hideMoreDetailsLabel = $GLOBALS['TL_LANG']['tl_cookiebar']['hideMoreDetailsLabel'];
  212. $objTemplate->providerLabel = $GLOBALS['TL_LANG']['tl_cookiebar']['providerLabel'];
  213. $objTemplate->expireLabel = $GLOBALS['TL_LANG']['tl_cookiebar']['expireLabel'];
  214. $objTemplate->tokenLabel = $GLOBALS['TL_LANG']['tl_cookiebar']['tokenLabel'];
  215. $objTemplate->forInfix = $GLOBALS['TL_LANG']['tl_cookiebar']['forInfix'];
  216. // Collect info links
  217. $arrLinks = [];
  218. if($varLinks = StringUtil::deserialize($objConfig->infoUrls))
  219. {
  220. foreach ($varLinks as $link) {
  221. $objPage = PageModel::findById($link);
  222. if(null !== $objPage)
  223. {
  224. $arrLinks[ $objPage->title ] = $objPage->getAbsoluteUrl();
  225. }
  226. }
  227. }
  228. $objTemplate->infoUrls = $arrLinks;
  229. // HOOK: parseCookiebarTemplate
  230. if (isset($GLOBALS['TL_HOOKS']['parseCookiebarTemplate']) && \is_array($GLOBALS['TL_HOOKS']['parseCookiebarTemplate']))
  231. {
  232. foreach ($GLOBALS['TL_HOOKS']['parseCookiebarTemplate'] as $callback)
  233. {
  234. System::importStatic($callback[0])->{$callback[1]}($objTemplate, $objConfig);
  235. }
  236. }
  237. // Tag the response
  238. if (System::getContainer()->has('fos_http_cache.http.symfony_response_tagger'))
  239. {
  240. /** @var ResponseTagger $responseTagger */
  241. $responseTagger = System::getContainer()->get('fos_http_cache.http.symfony_response_tagger');
  242. $responseTagger->addTags(array('oveleon.cookiebar.' . $objConfig->id));
  243. }
  244. return $objTemplate->parse();
  245. }
  246. /**
  247. * Collect cookie scripts
  248. *
  249. * @param object $objConfig
  250. *
  251. * @return array
  252. */
  253. public static function validateCookies($objConfig): array
  254. {
  255. $arrResponse = [];
  256. foreach ($objConfig->groups as $group)
  257. {
  258. foreach ($group->cookies as $cookie)
  259. {
  260. if($cookie->isLocked)
  261. {
  262. continue;
  263. }
  264. $arrCookie = [
  265. 'id' => $cookie->id,
  266. 'type' => $cookie->type,
  267. 'checked' => !!$cookie->checked,
  268. 'token' => static::parseToken($cookie->token),
  269. 'resources' => $cookie->resources,
  270. 'priority' => $cookie->priority ?? 0,
  271. 'scripts' => $cookie->scripts
  272. ];
  273. if($cookie->type === 'iframe')
  274. {
  275. $arrCookie['iframeType'] = $cookie->iframeType;
  276. }
  277. $arrResponse[ $cookie->id ] = $arrCookie;
  278. }
  279. }
  280. return $arrResponse;
  281. }
  282. /**
  283. * Collect global config scripts
  284. *
  285. * @param object $objConfig
  286. *
  287. * @return array
  288. */
  289. public static function validateGlobalConfigs($objConfig): array
  290. {
  291. $arrResponse = [];
  292. if(null === $objConfig->configs)
  293. {
  294. return $arrResponse;
  295. }
  296. foreach ($objConfig->configs as $config)
  297. {
  298. $arrConfig = [
  299. 'id' => $config->id,
  300. 'type' => $config->type,
  301. 'cookies' => array_combine(array_keys($config->arrCookies), array_keys($config->arrCookies)),
  302. 'resources' => $config->resources,
  303. 'scripts' => $config->scripts
  304. ];
  305. $arrResponse[ $config->id ] = $arrConfig;
  306. }
  307. return $arrResponse;
  308. }
  309. /**
  310. * Parse token string and return their as array
  311. *
  312. * @param $varToken
  313. *
  314. * @return array|null
  315. */
  316. public static function parseToken($varToken): ?array
  317. {
  318. if(is_array($varToken)){
  319. return $varToken;
  320. }
  321. if($varToken === ''){
  322. return null;
  323. }
  324. if(strpos($varToken, ',') !== false)
  325. {
  326. $varToken = explode(",", $varToken);
  327. }else $varToken = [$varToken];
  328. return $varToken;
  329. }
  330. /**
  331. * Delete cookie by their token/s
  332. *
  333. * @param $varToken
  334. */
  335. public static function deleteCookieByToken($varToken): void
  336. {
  337. $varToken = static::parseToken($varToken);
  338. if(null === $varToken){
  339. return;
  340. }
  341. $arrDomains = static::getDomainCollection($_SERVER['HTTP_HOST']);
  342. foreach ($varToken as $token)
  343. {
  344. setcookie(trim($token), "", time() - 3600, '/');
  345. foreach ($arrDomains as $domain)
  346. {
  347. setcookie(trim($token), "", time() - 3600, '/', $domain);
  348. }
  349. }
  350. }
  351. /**
  352. * Return a collection of possible domains
  353. *
  354. * @param $domain
  355. *
  356. * @return array
  357. */
  358. private static function getDomainCollection($domain): array
  359. {
  360. $arrCollection = [$domain, '.' . $domain];
  361. preg_match("/[^\.\/]+\.[^\.\/]+$/", $domain, $matches);
  362. $strDomain = $matches[0];
  363. // Add domain without subdomains
  364. $arrCollection[] = $strDomain;
  365. // Add domain without subdomains and starting dot
  366. $arrCollection[] = '.' . $strDomain;
  367. return array_unique($arrCollection);
  368. }
  369. /**
  370. * Deletes the cookie from old versions
  371. *
  372. * @deprecated Deprecated since CCB 1.2.0 to be removed in 2.0. Provided for backward compatibility.
  373. */
  374. public static function checkCookie(): void
  375. {
  376. if(Input::cookie(System::getContainer()->getParameter('contao_cookiebar.storage_key')))
  377. {
  378. setcookie(System::getContainer()->getParameter('contao_cookiebar.storage_key'),"",time() - 3600,'/');
  379. }
  380. }
  381. /**
  382. * Create and save new log entry
  383. *
  384. * @param $configId
  385. * @param null|string $ip
  386. * @param null|string $url
  387. * @param null|array $data
  388. */
  389. public static function log($configId, $url=null, $ip=null, $data=null): void
  390. {
  391. $strIp = $ip ?? Environment::get('ip');
  392. if(System::getContainer()->getParameter('contao_cookiebar.anonymize_ip'))
  393. {
  394. $strIp = IpUtils::anonymize($strIp);
  395. }
  396. // Check if the cookie bar exists (#128)
  397. if(!$cookieBar = CookiebarModel::findById($configId))
  398. {
  399. throw new \InvalidArgumentException("Cookie bar configuration could not be found, the log entry was skipped");
  400. }
  401. // Check if it is a valid URL (#128)
  402. if ($url && (filter_var('https://www.example.com' . $url, FILTER_VALIDATE_URL) === false))
  403. {
  404. throw new \InvalidArgumentException("The URL passed is not valid");
  405. }
  406. $objLog = new CookieLogModel();
  407. $objLog->cid = $configId;
  408. $objLog->version = $cookieBar->version;
  409. $objLog->domain = Environment::get('url');
  410. $objLog->url = $url ?? Environment::get('requestUri');
  411. $objLog->ip = $strIp;
  412. $objLog->tstamp = time();
  413. if(null !== $data)
  414. {
  415. // Remove values which are not of type integer (#128)
  416. foreach ($data as $index => $cookieId)
  417. {
  418. if(!((int) $cookieId == $cookieId))
  419. {
  420. unset($data[$index]);
  421. }
  422. }
  423. /** @var Connection $db */
  424. $db = System::getContainer()->get('database_connection');
  425. $result = $db->fetchAllAssociative("SELECT id, title, token FROM tl_cookie WHERE id IN (?)", [$data], [Connection::PARAM_INT_ARRAY]);
  426. $objLog->config = serialize($result);
  427. }
  428. $objLog->save();
  429. }
  430. }