tarte_au_citron-1.0.0-beta1/src/LibraryJsDiscover.php
src/LibraryJsDiscover.php
<?php
namespace Drupal\tarte_au_citron;
use Drupal\Component\Serialization\Json;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Config\ImmutableConfig;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
/**
* Gathers the services plugins.
*/
class LibraryJsDiscover implements LibraryJsDiscoverInterface {
use StringTranslationTrait;
/**
* The config object.
*
* @var \Drupal\Core\Config\ImmutableConfig|null
*/
protected ?ImmutableConfig $config = NULL;
/**
* Constructs a new LibraryJsDiscover object.
*
* @param \Drupal\Core\Cache\CacheBackendInterface $cache
* Cache backend instance to use.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $moduleHandler
* Module handler service.
* @param \Drupal\tarte_au_citron\ServicesManagerInterface $servicesManager
* Module handler service.
* @param \Drupal\Core\Language\LanguageManagerInterface $languageManager
* The language module.
*/
public function __construct(
protected CacheBackendInterface $cache,
protected ModuleHandlerInterface $moduleHandler,
protected ServicesManagerInterface $servicesManager,
protected LanguageManagerInterface $languageManager,
) {
}
/**
* {@inheritdoc}
*/
public function getJsServices(): array {
$cid = 'tarte_au_citron:services_js';
if ($data_cached = $this->cache->get($cid)) {
$results = $data_cached->data;
}
else {
$content_json_path = DRUPAL_ROOT . '/libraries/tarteaucitron/tarteaucitron.services.js';
$content_json = file_get_contents($content_json_path);
preg_match_all('/tarteaucitron\.services\.([^\s]+)\s*=\s*(\{.*\};)/Us', $content_json, $matches);
$results = [];
foreach ($matches[1] as $key => $service) {
$jsonServiceStr = $matches[2][$key];
$jsonServiceStr = preg_replace('/,\s*("|\')?cookies("|\')?\s*:\s*.*};/Us', '}', $jsonServiceStr);
$results[$service] = $this->getJsonFromString($jsonServiceStr);
preg_match_all('/tarteaucitron\.user\.(' . $service . '\w+)/i', $content_json, $matches_params);
$results[$service]['params'] = array_unique($matches_params[1]);
}
$this->cache->set($cid, $results);
}
return $results;
}
/**
* Extract the texts.
*
* @param array $data
* The data.
* @param array $texts
* The texts.
*/
protected function extractTexts(array &$data, array $texts): void {
foreach ($texts as $key => $value) {
if (is_array($value)) {
$data[$key] = [
'type' => 'mapping',
'children' => [],
];
$this->extractTexts($data[$key]['children'], $value);
}
else {
$data[$key] = [
'type' => 'text',
'default_value' => $value,
];
}
}
}
/**
* {@inheritdoc}
*/
public function getTextsAvailableLanguagesConfig(): array {
$cid = 'tarte_au_citron:texts_availables';
$data_cached = $this->cache->get($cid);
if (!$data_cached) {
$content_json_path = DRUPAL_ROOT . '/libraries/tarteaucitron/tarteaucitron.js';
$content_json = file_get_contents($content_json_path);
$data = [];
if (preg_match('/\s*availableLanguages\s*=\s*\'([a-z,\s*]+)\'/i', $content_json, $matches)) {
$languageString = $matches[1];
$languageString = preg_replace('/[^a-z,]/i', '', $languageString);
$data = explode(',', $languageString);
$availableLanguages = $this->languageManager->getLanguages();
$data = array_intersect_key($availableLanguages, array_flip($data));
}
$this->cache->set($cid, $data);
return $data;
}
return $data_cached->data;
}
/**
* {@inheritdoc}
*/
public function getTextsConfig(): array {
$cid = 'tarte_au_citron:configurations_texts';
$data_cached = $this->cache->get($cid);
if (!$data_cached) {
$content_json_path = DRUPAL_ROOT . '/libraries/tarteaucitron/lang/tarteaucitron.en.js';
$currentLangId = $this->languageManager->getCurrentLanguage()->getId();
if (array_key_exists($currentLangId, $this->getTextsAvailableLanguagesConfig())) {
$content_json_path = DRUPAL_ROOT . '/libraries/tarteaucitron/lang/tarteaucitron.' . $currentLangId . '.js';
}
$content_json = file_get_contents($content_json_path);
$data = [];
if (preg_match('/tarteaucitron.lang\s*=\s*(\{.*\});/Us', $content_json, $matches)) {
$this->extractTexts($data, $this->getJsonFromString($matches[1]));
}
foreach ($this->servicesManager->getServices(TRUE) as $service) {
$data['engage-' . $service->getPluginId()] = [
'type' => 'text',
'default_value' => $this->t('@name is disabled.', ['@name' => $service->getPluginTitle()], ['langcode' => 'en'])->render(),
];
}
$this->moduleHandler->alter('tarte_au_citron_texts_config', $data);
$this->cache->set($cid, $data);
return $data;
}
return $data_cached->data;
}
/**
* {@inheritdoc}
*/
public function getLibraryVersion(): string {
$cid = 'tarte_au_citron:library_version';
$data_cached = $this->cache->get($cid);
if (!$data_cached) {
$content_json_path = DRUPAL_ROOT . '/libraries/tarteaucitron/tarteaucitron.js';
$content_json = file_get_contents($content_json_path);
$data = $this->t('Unknown');
if (preg_match('/\s*(\'|")version(\'|")\s*:\s*((\d+\.)?\d+),/Us', $content_json, $matches)) {
$data = $matches[3];
}
$this->cache->set($cid, $data);
return $data;
}
return $data_cached->data;
}
/**
* {@inheritdoc}
*/
public function getJsConfig(): array {
$cid = 'tarte_au_citron:configurations_js';
$data_cached = $this->cache->get($cid);
if (!$data_cached) {
$content_json_path = DRUPAL_ROOT . '/libraries/tarteaucitron/tarteaucitron.js';
$content_json = file_get_contents($content_json_path);
$data = [];
if (preg_match('/defaults\s*=\s*(\{.*})/Us', $content_json, $matches)) {
try {
$data = $this->getJsonFromString($matches[1]);
foreach ($data as $key => $value) {
$data[$key] = [
'type' => is_bool($value) ? 'boolean' : 'label',
'default_value' => $value,
];
}
}
catch (\Exception $e) {
// Do nothing, prevent errors.
}
}
if (preg_match_all('/\s*tarteaucitron\.parameters\.([a-z\-_0-9]+)/i', $content_json, $matches)) {
foreach (array_unique($matches[1]) as $key) {
if (isset($data[$key]) || $key === 'hasOwnProperty') {
continue;
}
$isBool = mb_strpos($key, 'is') === 0 || mb_strpos($key, 'has') === 0;
$data[$key] = [
'type' => $isBool ? 'boolean' : 'label',
'default_value' => $isBool ? FALSE : '',
];
}
}
foreach ($data as $key => $value) {
if ($value['type'] !== 'label' || !preg_match('/(Url|Link)$/', $key)) {
continue;
}
$data[$key]['isUrl'] = TRUE;
}
$this->moduleHandler->alter('tarte_au_citron_config', $data);
$this->cache->set($cid, $data);
return $data;
}
return $data_cached->data;
}
/**
* Return Json element from string.
*
* @param string $string
* The string.
*
* @return mixed
* The String json decoded.
*/
protected function getJsonFromString(string $string): mixed {
$jsonStr = preg_replace('/\s\s+/', '', $string);
$jsonStr = preg_replace_callback('/:\s*\'(.*)\',/U', function ($m) {
return ':"' . str_replace('"', '\\\\\"', $m[1]) . '",';
}, $jsonStr);
$jsonStr = preg_replace_callback('/(,|{)\s*(("|\')?([^\'"]+)("|\')?)\s*:/U', function ($m) {
return $m[1] . '"' . $m[4] . '":';
}, $jsonStr);
return Json::decode($jsonStr);
}
public function hasJsMinified(): bool {
$cid = 'tarte_au_citron:has_minified';
$data_cached = $this->cache->get($cid);
if (!$data_cached) {
$data = file_exists(DRUPAL_ROOT . '/libraries/tarteaucitron/tarteaucitron.min.js');
$this->cache->set($cid, $data);
return $data;
}
return $data_cached->data;
}
}
