diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 961edb7..0000000 --- a/.eslintignore +++ /dev/null @@ -1,8 +0,0 @@ -core/assets/vendor/**/* -core/modules/locale/tests/locale_test.js -vendor/**/* -sites/**/files/**/* -libraries/**/* -sites/**/libraries/**/* -profiles/**/libraries/**/* -**/js_test_files/**/* diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index f9dbd5b..0000000 --- a/.eslintrc +++ /dev/null @@ -1,94 +0,0 @@ -{ - "extends": "eslint:recommended", - "root": true, - "env": { - "browser": true - }, - "globals": { - "Drupal": true, - "drupalSettings": true, - "drupalTranslations": true, - "domready": true, - "jQuery": true, - "_": true, - "matchMedia": true, - "Backbone": true, - "Modernizr": true, - "CKEDITOR": true - }, - "rules": { - "array-bracket-spacing": ["error", "never"], - "block-scoped-var": "error", - "brace-style": ["error", "stroustrup", {"allowSingleLine": true}], - "comma-dangle": ["error", "never"], - "comma-spacing": "error", - "comma-style": ["error", "last"], - "computed-property-spacing": ["error", "never"], - "curly": ["error", "all"], - "eol-last": "error", - "eqeqeq": ["error", "smart"], - "guard-for-in": "error", - "indent": ["error", 2, {"SwitchCase": 1}], - "key-spacing": ["error", {"beforeColon": false, "afterColon": true}], - "keyword-spacing": ["error", {"before": true, "after": true}], - "linebreak-style": ["error", "unix"], - "lines-around-comment": ["error", {"beforeBlockComment": true, "afterBlockComment": false}], - "new-parens": "error", - "no-array-constructor": "error", - "no-caller": "error", - "no-catch-shadow": "error", - "no-eval": "error", - "no-extend-native": "error", - "no-extra-bind": "error", - "no-extra-parens": ["error", "functions"], - "no-implied-eval": "error", - "no-iterator": "error", - "no-label-var": "error", - "no-labels": "error", - "no-lone-blocks": "error", - "no-loop-func": "error", - "no-multi-spaces": "error", - "no-multi-str": "error", - "no-native-reassign": "error", - "no-nested-ternary": "error", - "no-new-func": "error", - "no-new-object": "error", - "no-new-wrappers": "error", - "no-octal-escape": "error", - "no-process-exit": "error", - "no-proto": "error", - "no-return-assign": "error", - "no-script-url": "error", - "no-sequences": "error", - "no-shadow-restricted-names": "error", - "no-spaced-func": "error", - "no-trailing-spaces": "error", - "no-undef-init": "error", - "no-undefined": "error", - "no-unused-expressions": "error", - "no-unused-vars": ["error", {"vars": "all", "args": "none"}], - "no-with": "error", - "object-curly-spacing": ["error", "never"], - "one-var": ["error", "never"], - "quote-props": ["error", "consistent-as-needed"], - "quotes": ["error", "single", "avoid-escape"], - "semi": ["error", "always"], - "semi-spacing": ["error", {"before": false, "after": true}], - "space-before-blocks": ["error", "always"], - "space-before-function-paren": ["error", {"anonymous": "always", "named": "never"}], - "space-in-parens": ["error", "never"], - "space-infix-ops": "error", - "space-unary-ops": ["error", { "words": true, "nonwords": false }], - "spaced-comment": ["error", "always"], - "strict": ["error", "function"], - "yoda": ["error", "never"], - "max-nested-callbacks": ["warn", 3], - "valid-jsdoc": ["warn", { - "prefer": { - "returns": "return", - "property": "prop" - }, - "requireReturn": false - }] - } -} diff --git a/.github/workflows/module-test.yml b/.github/workflows/module_test.yml similarity index 82% rename from .github/workflows/module-test.yml rename to .github/workflows/module_test.yml index 85d913f..19d8905 100644 --- a/.github/workflows/module-test.yml +++ b/.github/workflows/module_test.yml @@ -30,9 +30,12 @@ jobs: with: coverage: none php-version: ${{ matrix.PHP }} + extensions: Imagick, gd, pdo_mysql - name: Start MySql service - run: sudo /etc/init.d/mysql start + run: | + sudo /etc/init.d/mysql start + mysql -uroot -proot -e "ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'root';" - name: Cache composer dependencies uses: actions/cache@v1 diff --git a/.github/workflows/reviewdog.yml b/.github/workflows/reviewdog.yml index a3f8995..c027d01 100644 --- a/.github/workflows/reviewdog.yml +++ b/.github/workflows/reviewdog.yml @@ -3,17 +3,6 @@ name: Check coding styles on: [pull_request] jobs: - eslint: - name: runner / eslint - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - - name: eslint - uses: reviewdog/action-eslint@v1 - with: - github_token: ${{ secrets.github_token }} - phpcs: name: runner / phpcs runs-on: ubuntu-latest @@ -25,6 +14,7 @@ jobs: with: github_token: ${{ secrets.github_token }} level: error + filter_mode: nofilter misspell: name: runner / misspell diff --git a/graphql/ivw.base.graphqls b/graphql/ivw.base.graphqls new file mode 100644 index 0000000..3b9bb80 --- /dev/null +++ b/graphql/ivw.base.graphqls @@ -0,0 +1,11 @@ +type Ivw { + st: String + cp: String + sv: String + sc: String + co: String + mobile_cp: String + mobile_st: String + mobile_sv: String + mobile_width: String +} diff --git a/graphql/ivw.extension.graphqls b/graphql/ivw.extension.graphqls new file mode 100644 index 0000000..12284ce --- /dev/null +++ b/graphql/ivw.extension.graphqls @@ -0,0 +1,3 @@ +extend type Query { + ivw(path: String!): Ivw +} diff --git a/ivw_integration.tokens.inc b/ivw_integration.tokens.inc index affe476..6b15eb7 100644 --- a/ivw_integration.tokens.inc +++ b/ivw_integration.tokens.inc @@ -102,7 +102,7 @@ function ivw_integration_tokens($type, $tokens, array $data, array $options, Bub elseif (isset($data['term']) && $data['term'] instanceof TermInterface) { $lookupFrom = 'term'; } - /* @var \Drupal\ivw_integration\IvwLookupServiceInterface $lookup */ + /** @var \Drupal\ivw_integration\IvwLookupServiceInterface $lookup */ $lookup = \Drupal::service('ivw_integration.lookup'); foreach ($tokens as $name => $original) { diff --git a/src/IvwLookupService.php b/src/IvwLookupService.php index ea22b5d..957a6b7 100644 --- a/src/IvwLookupService.php +++ b/src/IvwLookupService.php @@ -13,9 +13,7 @@ use Drupal\taxonomy\TermInterface; /** - * Class IvwLookupService. - * - * @package Drupal\ivw_integration + * Service to get correct values based on the content hierarchy. */ class IvwLookupService implements IvwLookupServiceInterface { @@ -75,11 +73,8 @@ public function byCurrentRoute($name, $parentOnly = FALSE) { * {@inheritdoc} */ public function byRoute($name, RouteMatchInterface $route, $parentOnly = FALSE) { - - $entity = NULL; - foreach (self::getSupportedEntityParameters() as $parameter) { - /* @var ContentEntityInterface $entity */ + /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */ if ($entity = $route->getParameter($parameter)) { if (is_numeric($entity)) { @@ -116,12 +111,10 @@ public function getCacheTagsByCurrentRoute() { * {@inheritdoc} */ public function getCacheTagsByRoute(RouteMatchInterface $route) { - - $entity = NULL; $cache_tags = []; foreach (self::getSupportedEntityParameters() as $parameter) { - /* @var ContentEntityInterface $entity */ + /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */ if ($entity = $route->getParameter($parameter)) { if (is_numeric($entity)) { @@ -160,12 +153,11 @@ public function getCacheTagsByRoute(RouteMatchInterface $route) { * The gathered cache tags. */ private function getCacheTagsByTerm(TermInterface $term) { - /* @var \Drupal\taxonomy\TermStorage $termStorage */ + /** @var \Drupal\taxonomy\TermStorageInterface $termStorage */ $termStorage = $this->entityTypeManager->getStorage('taxonomy_term'); $cache_tags = $term->getCacheTags(); - /** @var \Drupal\taxonomy\TermInterface $parent */ foreach ($termStorage->loadParents($term->id()) as $parent) { $parentCacheTags = $this->getCacheTagsByTerm($parent); $cache_tags = Cache::mergeTags($cache_tags, $parentCacheTags); @@ -299,7 +291,7 @@ protected function searchTerm($name, TermInterface $term, $parentOnly = FALSE) { } } - /* @var \Drupal\taxonomy\TermStorage $termStorage */ + /** @var \Drupal\taxonomy\TermStorageInterface $termStorage */ $termStorage = $this->entityTypeManager->getStorage('taxonomy_term'); foreach ($termStorage->loadParents($term->id()) as $parent) { diff --git a/src/IvwLookupServiceInterface.php b/src/IvwLookupServiceInterface.php index 44d28bf..c671e98 100644 --- a/src/IvwLookupServiceInterface.php +++ b/src/IvwLookupServiceInterface.php @@ -7,9 +7,7 @@ use Drupal\taxonomy\TermInterface; /** - * Interface IvwLookupServiceInterface. - * - * @package Drupal\ivw_integration + * Interface for the lookup service. */ interface IvwLookupServiceInterface { diff --git a/src/IvwTracker.php b/src/IvwTracker.php index 0a94a5f..fa81d9d 100644 --- a/src/IvwTracker.php +++ b/src/IvwTracker.php @@ -5,12 +5,12 @@ use Drupal\Core\Cache\Cache; use Drupal\Core\Cache\CacheableDependencyInterface; use Drupal\Core\Config\ConfigFactoryInterface; +use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Utility\Token; +use Drupal\taxonomy\TermInterface; /** - * Class IvwTracker. - * - * @package Drupal\ivw_integration + * Provides all the IVW tracking information. */ class IvwTracker implements IvwTrackerInterface, CacheableDependencyInterface { @@ -65,18 +65,18 @@ public function __construct( /** * {@inheritdoc} */ - public function getTrackingInformation() { + public function getTrackingInformation(ContentEntityInterface $entity = NULL) { if (!isset($this->trackingInformation)) { $this->trackingInformation = [ 'st' => $this->getSt(), 'mobile_st' => $this->getMobileSt(), - 'cp' => $this->getCp(), - 'sv' => $this->getSv(), - 'mobile_sv' => $this->getMobileSv(), + 'cp' => $this->getCp($entity), + 'sv' => $this->getSv($entity), + 'mobile_sv' => $this->getMobileSv($entity), 'sc' => $this->getSc(), ]; // Calculate cpm based upon cp. - // TODO: this is absolutely not generic. + // @todo This is absolutely not generic. $this->trackingInformation['cpm'] = str_replace('D1A', 'D2A', $this->trackingInformation['cp']); } return $this->trackingInformation; @@ -110,11 +110,21 @@ protected function getMobileSt() { * @return string * The value of the cp parameter. */ - protected function getCp() { + protected function getCp(ContentEntityInterface $entity = NULL) { $settings = $this->configFactory->get('ivw_integration.settings'); $code_template = $settings->get('code_template'); - return $this->token->replace($code_template, [], ['sanitize' => FALSE]); + $data = []; + if ($entity) { + if ($entity instanceof TermInterface) { + $data['term'] = $entity; + } + else { + $data['entity'] = $entity; + } + } + + return $this->token->replace($code_template, $data, ['sanitize' => FALSE]); } /** @@ -124,8 +134,17 @@ protected function getCp() { * The value of the sv parameter. * If non is defined anywhere 'in' is returned as default. */ - protected function getSv() { - $sv = $this->token->replace('[ivw:frabo]', [], ['sanitize' => FALSE]); + protected function getSv(ContentEntityInterface $entity = NULL) { + $data = []; + if ($entity) { + if ($entity instanceof TermInterface) { + $data['term'] = $entity; + } + else { + $data['entity'] = $entity; + } + } + $sv = $this->token->replace('[ivw:frabo]', $data, ['sanitize' => FALSE]); return empty($sv) ? 'in' : $sv; } @@ -136,8 +155,17 @@ protected function getSv() { * The value of the sv parameter. * If non is defined anywhere 'mo' is returned as default. */ - protected function getMobileSv() { - $sv = $this->token->replace('[ivw:frabo_mobile]', [], ['sanitize' => FALSE]); + protected function getMobileSv(ContentEntityInterface $entity = NULL) { + $data = []; + if ($entity) { + if ($entity instanceof TermInterface) { + $data['term'] = $entity; + } + else { + $data['entity'] = $entity; + } + } + $sv = $this->token->replace('[ivw:frabo_mobile]', $data, ['sanitize' => FALSE]); return empty($sv) ? 'mo' : $sv; } diff --git a/src/IvwTrackerInterface.php b/src/IvwTrackerInterface.php index 4a8e7a6..758acc8 100644 --- a/src/IvwTrackerInterface.php +++ b/src/IvwTrackerInterface.php @@ -2,10 +2,10 @@ namespace Drupal\ivw_integration; +use Drupal\Core\Entity\ContentEntityInterface; + /** - * Interface IvwTrackerInterface. - * - * @package Drupal\ivw_integration + * Interface for the tracking service. */ interface IvwTrackerInterface { @@ -16,6 +16,6 @@ interface IvwTrackerInterface { * Array containing 'st', 'mobile_st', 'cp', 'cpm', * 'sv' and 'mobile_sv' parameters. */ - public function getTrackingInformation(); + public function getTrackingInformation(ContentEntityInterface $entity = NULL); } diff --git a/src/Plugin/GraphQL/DataProducer/IvwCall.php b/src/Plugin/GraphQL/DataProducer/IvwCall.php new file mode 100644 index 0000000..c647817 --- /dev/null +++ b/src/Plugin/GraphQL/DataProducer/IvwCall.php @@ -0,0 +1,150 @@ +get('renderer'), + $container->get('ivw_integration.tracker'), + $container->get('config.factory') + ); + } + + /** + * IVW constructor. + * + * @param array $configuration + * The plugin configuration array. + * @param string $pluginId + * The plugin id. + * @param mixed $pluginDefinition + * The plugin definition. + * @param \Drupal\Core\Render\RendererInterface $renderer + * The renderer service. + * @param \Drupal\ivw_integration\IvwTrackerInterface $ivwTracker + * The ivw tracker service. + * @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory + * The config factory service. + */ + public function __construct( + array $configuration, + string $pluginId, + $pluginDefinition, + RendererInterface $renderer, + IvwTrackerInterface $ivwTracker, + ConfigFactoryInterface $configFactory + ) { + parent::__construct($configuration, $pluginId, $pluginDefinition); + $this->renderer = $renderer; + $this->ivwTracker = $ivwTracker; + $this->config = $configFactory->get('ivw_integration.settings'); + } + + /** + * Resolve the IVW data attributes. + * + * @param \Drupal\Core\Entity\EntityInterface $entity + * The entity. + * @param \Drupal\Core\Cache\RefinableCacheableDependencyInterface $metadata + * The cacheable dependency interface. + * + * @return mixed + * The IVW attributes. + */ + public function resolve(EntityInterface $entity, RefinableCacheableDependencyInterface $metadata) { + if (!($entity instanceof ContentEntityInterface)) { + return ''; + } + $context = new RenderContext(); + $result = $this->renderer->executeInRenderContext($context, function () use ($entity) { + $tracker = $this->ivwTracker->getTrackingInformation($entity); + + // Site is missing, do not render tag. + if (empty($tracker['st'])) { + return []; + } + + $mobile_width = $this->config->get("mobile_width") ? $this->config->get("mobile_width") : ''; + $mobile_site = $this->config->get("mobile_site") ? $this->config->get("mobile_site") : ''; + + return [ + 'st' => $tracker['st'], + 'cp' => $tracker['cp'], + 'sv' => $tracker['sv'], + 'sc' => $tracker['sc'], + // Not yet configurable. + 'co' => '', + 'mobile_cp' => $tracker['cpm'], + 'mobile_st' => $mobile_site, + 'mobile_sv' => $tracker['mobile_sv'], + 'mobile_width' => $mobile_width, + ]; + }); + + if (!$context->isEmpty()) { + $metadata->addCacheableDependency($context->pop()); + } + + return $result ?? ''; + } + +} diff --git a/src/Plugin/GraphQL/SchemaExtension/IvwSchemaExtension.php b/src/Plugin/GraphQL/SchemaExtension/IvwSchemaExtension.php new file mode 100644 index 0000000..8474bd4 --- /dev/null +++ b/src/Plugin/GraphQL/SchemaExtension/IvwSchemaExtension.php @@ -0,0 +1,37 @@ +addFieldResolver('Query', 'ivw', $builder->compose( + $builder->produce('route_load') + ->map('path', $builder->fromArgument('path')), + $builder->produce('route_entity') + ->map('url', $builder->fromParent()), + $builder->produce('ivw_call') + ->map('entity', $builder->fromParent()) + )); + } + +}