diff --git a/.ahoy/.scripts/dkan-lint.rb b/.ahoy/.scripts/dkan-lint.rb new file mode 100644 index 0000000000..ba75248b17 --- /dev/null +++ b/.ahoy/.scripts/dkan-lint.rb @@ -0,0 +1,52 @@ +require 'json' +require 'uri' +require 'net/http' +require 'fileutils' +require 'git' + +include FileUtils +include Git + +# Get the list of files from a PR +def get_pr_files(user, repo, pr) + uri = URI.parse("https://api.github.com/repos/#{user}/#{repo}/pulls/#{pr}/files") + + http = Net::HTTP.new(uri.host, uri.port) + request = Net::HTTP::Get.new(uri.request_uri) + http.use_ssl = true + response = http.request(request) + result = JSON.parse(response.body) + files = Array.new + + result.each do |i| + files.push(i['filename']) + end + + return files +end + +if 1==1 + user = 'GetDKAN' + repo = 'dkan' + pr = '2454' + files = get_pr_files(user, repo, pr) +elsif ARGV.any? + files = ARGV +else + FileUtils.cd 'dkan' + g = Git.open('.') + files = g.diff.name_status.select{|k,v| v != "D"}.keys + FileUtils.cd '..' +end + +if files.any? + # Filter file list for approved file types + files.select!{ |i| i[/\.*(\.php|\.inc|\.module|\.install|\.profile|\.info)$/] } + if files.any? + files.map! {|item| 'dkan/' + item} + puts "Linting files:\n" + files.join("\n") + puts `dkan/test/bin/phpcs --standard=Drupal,DrupalPractice -n --ignore=test/dkanextension/*,patches/* #{files.join(" ")}` + else + puts "No files available to lint; ending." + end +end diff --git a/.ahoy/.scripts/dkan-lint.sh b/.ahoy/.scripts/dkan-lint.sh deleted file mode 100644 index 4c99e71aed..0000000000 --- a/.ahoy/.scripts/dkan-lint.sh +++ /dev/null @@ -1,26 +0,0 @@ -echo "Installing dependencies.." -cd dkan -bash .ahoy/.scripts/composer-install.sh test - -test/bin/phpcs --config-set installed_paths test/vendor/drupal/coder/coder_sniffer -DRUPAL_FILES='\.*\(.php\|.inc\|.module\|.install\|.profile\|.info\)$' - -if [ ! -z "$1" ]; then - files="$files $@" -fi - -if [ -z "$files" ]; then - files=`git diff --name-only | grep "$DRUPAL_FILES"` -fi - -if [ "$CI_PULL_REQUEST" ]; then - echo Diff URL: "$CI_PULL_REQUEST".diff - files=`curl -sL "$CI_PULL_REQUEST".diff | grep "^+++" | sed 's/+++ b\///g' | grep "$DRUPAL_FILES"` -fi - -if [ ! -z "$files" ]; then - echo "Linting: $files" - test/bin/phpcs --standard=Drupal,DrupalPractice -n $files --ignore=test/dkanextension/* -else - echo "No Drupal file changes available for linting." -fi diff --git a/.ahoy/dkan.ahoy.yml b/.ahoy/dkan.ahoy.yml index 659d471f6c..f491cc8160 100644 --- a/.ahoy/dkan.ahoy.yml +++ b/.ahoy/dkan.ahoy.yml @@ -158,9 +158,13 @@ commands: cmd: ahoy cmd-proxy bash dkan/.ahoy/.scripts/dkan-unittests.sh "{{args}}" lint: - usage: Run linter on code + usage: Run linter on DKAN code hidden: true - cmd: ahoy cmd-proxy bash dkan/.ahoy/.scripts/dkan-lint.sh "{{args}}" + cmd: | + ahoy cmd-proxy gem install git + ahoy cmd-proxy bash dkan/.ahoy/.scripts/composer-install.sh dkan/test + ahoy cmd-proxy dkan/test/bin/phpcs --config-set installed_paths dkan/test/vendor/drupal/coder/coder_sniffer + ahoy cmd-proxy ruby dkan/.ahoy/.scripts/dkan-lint.rb {{args}} create-qa-users: usage: Create users for each core role for QA purposes diff --git a/.circleci/config.yml b/.circleci/config.yml index d18f134f77..f8e73b939d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -43,7 +43,9 @@ jobs: command: sudo apt-get update - run: name: Install Packages - command: sudo apt-get install -y ruby libpng-dev libmcrypt-dev mysql-client x11vnc + command: | + sudo apt-get install -y ruby libpng-dev libmcrypt-dev mysql-client x11vnc + sudo gem install git #Available Extensions: #bcmath bz2 calendar ctype curl dba dom enchant exif fileinfo filter ftp gd gettext gmp hash iconv imap interbase intl json ldap mbstring mcrypt mssql mysql mysqli oci8 odbc opcache pcntl pdo pdo_dblib pdo_firebird pdo_mysql pdo_oci pdo_odbc pdo_pgsql pdo_sqlite pgsql phar posix pspell readline recode reflection session shmop simplexml snmp soap sockets spl standard sybase_ct sysvmsg sysvsem sysvshm tidy tokenizer wddx xml xmlreader xmlrpc xmlwriter xsl zip @@ -118,9 +120,6 @@ jobs: key: v1-dkan-test-vendor paths: - dkan/test/vendor - - run: - name: Run Parallel Behat Tests - command: ruby dkan/.ahoy/.scripts/circle-behat.rb docroot/profiles/dkan/test/features # Lint only on 1st parallel instance. Deploy: blocks until parallelism is done, so doing it this way. - run: name: Run Lint @@ -128,6 +127,9 @@ jobs: if [ "$CIRCLE_NODE_INDEX" -eq "0" ]; then ahoy dkan lint fi + - run: + name: Run Parallel Behat Tests + command: ruby dkan/.ahoy/.scripts/circle-behat.rb docroot/profiles/dkan/test/features # Unit Tests only on 1st parallel instance. Deploy: blocks until parallelism is done, so doing it this way. - run: name: Run PHPUnit Tests diff --git a/docs/components/index.rst b/docs/components/index.rst index 5851adef4c..342e12b946 100644 --- a/docs/components/index.rst +++ b/docs/components/index.rst @@ -28,6 +28,7 @@ described inside the Datasets section, all this functionality is provided by the Storytelling Open Data Schema Map Visualizations + Link checker .. note:: The three modules mentioned above that are not distributed with DKAN continue to be maintained in separate repositories because they work diff --git a/docs/components/linkchecker.rst b/docs/components/linkchecker.rst new file mode 100644 index 0000000000..2504f4add4 --- /dev/null +++ b/docs/components/linkchecker.rst @@ -0,0 +1,26 @@ +DKAN Link Checker +================= + +DKAN Link Checker adds configuration and additional reporting to the `link checker `_ module. + + The Link checker module extracts links from your content when saved and periodically tries to detect broken hypertext links by checking the remote sites and evaluating the HTTP response codes. + +Installation +------------ +DKAN Link checker will check links in datasets, resources, and harvest sources. It is not enabled by default, to enable it, run these commands: + +- ``drush en dkan_linkchecker -y`` +- ``drush cc all`` +- ``drush linkchecker-analyze`` +- ``drush cron`` + +Links will be processed in batches and it may take a while to go through all of the links of your site. + +Permissions +----------- +Users with the **site manager** role will be able to + +- View the broken links report at ``admin/reports/dkan-linkchecker-report`` +- Access the link checker configuration screen at ``admin/config/content/linkchecker`` + +For more information on link checker `click here `_ diff --git a/drupal-org.make b/drupal-org.make index 14a65a77ee..911fd29861 100644 --- a/drupal-org.make +++ b/drupal-org.make @@ -199,6 +199,14 @@ projects: version: '1.1' link_iframe_formatter: version: '1.1' + linkchecker: + download: + type: git + url: 'https://git.drupal.org/project/linkchecker.git' + revision: 623819d04464b26af8e216113a88cd03f4bb4ccc + patch: + 965720: https://www.drupal.org/files/issues/linkchecker-views-integration-965720-124.patch + 1: patches/dkan_linkchecker_file.patch manualcrop: version: '1.6' markdown: diff --git a/modules/dkan/dkan_linkchecker/css/linkchecker.css b/modules/dkan/dkan_linkchecker/css/linkchecker.css new file mode 100644 index 0000000000..3fdfadc778 --- /dev/null +++ b/modules/dkan/dkan_linkchecker/css/linkchecker.css @@ -0,0 +1,21 @@ +.view-dkan-linkchecker-reports { + font-family: arial; + font-size: 12px; + font-weight: normal; +} +.view-dkan-linkchecker-reports .views-exposed-form .views-exposed-widget { + padding-top: 0; +} +.view-dkan-linkchecker-reports th.views-field-nothing { + text-align: center; +} +.view-dkan-linkchecker-reports td.views-field-nothing a:hover { + text-decoration: none; +} +.view-dkan-linkchecker-reports td.views-field-nothing a .btn-primary { + margin: 2px; + padding: 4px 8px; +} +.view-dkan-linkchecker-reports .views-field i { + font-size: 1.5em; +} diff --git a/modules/dkan/dkan_linkchecker/dkan_linkchecker.features.inc b/modules/dkan/dkan_linkchecker/dkan_linkchecker.features.inc new file mode 100644 index 0000000000..c218b9fcd9 --- /dev/null +++ b/modules/dkan/dkan_linkchecker/dkan_linkchecker.features.inc @@ -0,0 +1,22 @@ + "1"); + } +} + +/** + * Implements hook_views_api(). + */ +function dkan_linkchecker_views_api($module = NULL, $api = NULL) { + return array("api" => "3.0"); +} diff --git a/modules/dkan/dkan_linkchecker/dkan_linkchecker.features.user_permission.inc b/modules/dkan/dkan_linkchecker/dkan_linkchecker.features.user_permission.inc new file mode 100644 index 0000000000..60bb397e9d --- /dev/null +++ b/modules/dkan/dkan_linkchecker/dkan_linkchecker.features.user_permission.inc @@ -0,0 +1,53 @@ + 'access broken links report', + 'roles' => array( + 'site manager' => 'site manager', + ), + 'module' => 'linkchecker', + ); + + // Exported permission: 'access own broken links report'. + $permissions['access own broken links report'] = array( + 'name' => 'access own broken links report', + 'roles' => array( + 'site manager' => 'site manager', + ), + 'module' => 'linkchecker', + ); + + // Exported permission: 'administer linkchecker'. + $permissions['administer linkchecker'] = array( + 'name' => 'administer linkchecker', + 'roles' => array( + 'site manager' => 'site manager', + ), + 'module' => 'linkchecker', + ); + + // Exported permission: 'edit link settings'. + $permissions['edit link settings'] = array( + 'name' => 'edit link settings', + 'roles' => array( + 'site manager' => 'site manager', + ), + 'module' => 'linkchecker', + ); + } + + return $permissions; +} diff --git a/modules/dkan/dkan_linkchecker/dkan_linkchecker.info b/modules/dkan/dkan_linkchecker/dkan_linkchecker.info new file mode 100644 index 0000000000..44de63189e --- /dev/null +++ b/modules/dkan/dkan_linkchecker/dkan_linkchecker.info @@ -0,0 +1,24 @@ +name = DKAN Link Checker +description = Checks for broken links in datasets, resources, and harvest sources. +core = 7.x +package = DKAN +dependencies[] = dkan_sitewide_menu +dependencies[] = features +dependencies[] = linkchecker +dependencies[] = menu +dependencies[] = strongarm +dependencies[] = views +features[ctools][] = strongarm:strongarm:1 +features[ctools][] = views:views_default:3.0 +features[features_api][] = api:2 +features[user_permission][] = access broken links report +features[user_permission][] = access own broken links report +features[user_permission][] = administer linkchecker +features[user_permission][] = edit link settings +features[variable][] = linkchecker_check_links_types +features[variable][] = linkchecker_scan_node_dataset +features[variable][] = linkchecker_scan_node_harvest_source +features[variable][] = linkchecker_scan_node_resource +features[views_view][] = dkan_linkchecker_reports +features_exclude[dependencies][ctools] = ctools +project path = profiles/dkan/modules/dkan diff --git a/modules/dkan/dkan_linkchecker/dkan_linkchecker.install b/modules/dkan/dkan_linkchecker/dkan_linkchecker.install new file mode 100644 index 0000000000..e6a2081a6c --- /dev/null +++ b/modules/dkan/dkan_linkchecker/dkan_linkchecker.install @@ -0,0 +1,17 @@ + TRUE); + $disabled = array_merge($list, $n); + variable_set('views_defaults', $disabled); +} diff --git a/modules/dkan/dkan_linkchecker/dkan_linkchecker.module b/modules/dkan/dkan_linkchecker/dkan_linkchecker.module new file mode 100644 index 0000000000..7efb0cdfb9 --- /dev/null +++ b/modules/dkan/dkan_linkchecker/dkan_linkchecker.module @@ -0,0 +1,150 @@ + $config_parent_normal_path, ':menu' => 'menu-command-center-menu'))->fetchField(); + + $items = array(); + // Add links to command center menu for site manager access. + $items['cc/admin/config/link-checker'] = array( + 'menu_name' => 'menu-command-center-menu', + 'title' => 'Link Checker Settings', + 'page callback' => 'drupal_goto', + 'page arguments' => array('admin/config/content/linkchecker'), + 'access arguments' => array('administer linkchecker'), + 'weight' => 10, + 'type' => MENU_NORMAL_ITEM, + 'plid' => $config_plid, + ); + $items['cc/admin/config/link-checker/dkan-linkchecker-report'] = array( + 'menu_name' => 'menu-command-center-menu', + 'title' => 'Broken Links Report', + 'page callback' => 'drupal_goto', + 'page arguments' => array('admin/reports/dkan-linkchecker-report'), + 'access arguments' => array('access broken links report'), + 'weight' => 11, + 'type' => MENU_NORMAL_ITEM, + ); + return $items; +} + +/** + * Implements hook_menu_alter(). + */ +function dkan_linkchecker_menu_alter(&$items) { + // Remove normal linkchecker report link. + $items['admin/reports/linkchecker']['access callback'] = FALSE; +} + +/** + * Implements hook_views_pre_render(). + */ +function dkan_linkchecker_views_pre_render(&$view) { + if ($view->name == 'dkan_linkchecker_reports') { + // Re-write the output of the contact email. + foreach ($view->result as $key => $result) { + $email = ''; + // Dataset results. + if (isset($result->field_field_contact_email[0]['raw']['value'])) { + $email = ' '; + } + if (isset($result->field_field_contact_name[0]['rendered']['#markup'])) { + $result->field_field_contact_name[0]['rendered']['#markup'] = $email . $result->field_field_contact_name[0]['raw']['safe_value']; + } + // Resource results. + if (isset($result->field_field_contact_email_1[0]['raw']['value'])) { + $email = ' '; + } + if (isset($result->field_field_contact_name_1[0]['rendered']['#markup'])) { + $result->field_field_contact_name_1[0]['rendered']['#markup'] = $email . $result->field_field_contact_name_1[0]['raw']['safe_value']; + } + } + } +} + +/** + * Implements hook_views_query_alter(). + */ +function dkan_linkchecker_views_query_alter(&$view, &$query) { + if ($view->name == 'dkan_linkchecker_reports') { + switch ($view->exposed_raw_input['field_public_access_level_value']) { + case 'public': + _access_level_query($view, $query, 'public'); + break; + + case 'private': + _access_level_query($view, $query, 'private'); + break; + + case 'restricted': + _access_level_query($view, $query, 'restricted'); + break; + + default: + break; + } + } +} + +/** + * Create filter for public access level that includes resources. + */ +function _access_level_query(&$view, &$query, $level) { + // Get the public access level value from the dataset reference field. + $join = new views_join(); + $join->table = 'field_data_field_public_access_level'; + $join->field = 'entity_id'; + $join->left_table = 'node_linkchecker_node__field_data_field_dataset_ref'; + $join->left_field = 'field_dataset_ref_target_id'; + $join->type = 'LEFT'; + + // Do the actual join. + $query->table_queue['public_access_level'] = array( + 'alias' => 'public_access_level', + 'table' => 'field_data_field_public_access_level', + 'relationship' => 'node_linkchecker_node__field_data_field_dataset_ref', + 'join' => $join, + ); + + // This gathers the dataset results. + $query->where[1] = array( + 'conditions' => array( + array( + 'field' => 'public_access_level.field_public_access_level_value', + 'value' => $level, + 'operator' => '=', + ), + ), + 'type' => 'OR', + ); + + $query->table_queue['node_linkchecker_node__field_data_field_public_access_level']['join']->type = 'LEFT'; + // This gathers the resource results. + $query->add_where(1, db_or()->condition( + 'node_linkchecker_node__field_data_field_public_access_level.field_public_access_level_value', $level)); + // Add default filters back in. + $ignore = array(200, 301, 302); + $query->add_where(2, db_and()->condition('linkchecker_link.last_checked', 0, '!=')->condition('linkchecker_link.status', '0', '<>')->condition('linkchecker_link.code', $ignore, 'NOT IN')); + + return $query; +} diff --git a/modules/dkan/dkan_linkchecker/dkan_linkchecker.strongarm.inc b/modules/dkan/dkan_linkchecker/dkan_linkchecker.strongarm.inc new file mode 100644 index 0000000000..6ea4eb86e8 --- /dev/null +++ b/modules/dkan/dkan_linkchecker/dkan_linkchecker.strongarm.inc @@ -0,0 +1,43 @@ +disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */ + $strongarm->api_version = 1; + $strongarm->name = 'linkchecker_check_links_types'; + $strongarm->value = '0'; + $export['linkchecker_check_links_types'] = $strongarm; + + $strongarm = new stdClass(); + $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */ + $strongarm->api_version = 1; + $strongarm->name = 'linkchecker_scan_node_dataset'; + $strongarm->value = 1; + $export['linkchecker_scan_node_dataset'] = $strongarm; + + $strongarm = new stdClass(); + $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */ + $strongarm->api_version = 1; + $strongarm->name = 'linkchecker_scan_node_harvest_source'; + $strongarm->value = 1; + $export['linkchecker_scan_node_harvest_source'] = $strongarm; + + $strongarm = new stdClass(); + $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */ + $strongarm->api_version = 1; + $strongarm->name = 'linkchecker_scan_node_resource'; + $strongarm->value = 1; + $export['linkchecker_scan_node_resource'] = $strongarm; + + return $export; +} diff --git a/modules/dkan/dkan_linkchecker/dkan_linkchecker.views_default.inc b/modules/dkan/dkan_linkchecker/dkan_linkchecker.views_default.inc new file mode 100644 index 0000000000..02a80a77a5 --- /dev/null +++ b/modules/dkan/dkan_linkchecker/dkan_linkchecker.views_default.inc @@ -0,0 +1,477 @@ +name = 'dkan_linkchecker_reports'; + $view->description = 'Display a list of broken links.'; + $view->tag = 'default'; + $view->base_table = 'linkchecker_link'; + $view->human_name = 'DKAN Advanced Broken links'; + $view->core = 0; + $view->api_version = '3.0'; + $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ + + /* Display: Defaults */ + $handler = $view->new_display('default', 'Defaults', 'default'); + $handler->display->display_options['title'] = 'Private Broken links'; + $handler->display->display_options['items_per_page'] = 0; + $handler->display->display_options['use_more_always'] = FALSE; + $handler->display->display_options['access']['type'] = 'perm'; + $handler->display->display_options['access']['perm'] = 'access broken links report'; + $handler->display->display_options['cache']['type'] = 'none'; + $handler->display->display_options['query']['type'] = 'views_query'; + $handler->display->display_options['query']['options']['query_comment'] = FALSE; + $handler->display->display_options['exposed_form']['type'] = 'basic'; + $handler->display->display_options['exposed_form']['options']['reset_button'] = TRUE; + $handler->display->display_options['pager']['type'] = 'full'; + $handler->display->display_options['pager']['options']['items_per_page'] = '50'; + $handler->display->display_options['pager']['options']['offset'] = '0'; + $handler->display->display_options['pager']['options']['id'] = '0'; + $handler->display->display_options['pager']['options']['quantity'] = '9'; + $handler->display->display_options['style_plugin'] = 'table'; + $handler->display->display_options['style_options']['columns'] = array( + 'url' => 'url', + 'code' => 'code', + 'error' => 'error', + 'link_edit' => 'link_edit', + 'nid' => 'nid', + 'edit_node' => 'edit_node', + 'bid' => 'bid', + 'block_edit' => 'block_edit', + 'type' => 'type', + 'title' => 'title', + 'field_contact_email_1' => 'field_contact_email_1', + 'field_contact_email' => 'field_contact_email', + 'field_contact_name_1' => 'field_contact_name_1', + 'field_contact_name' => 'field_contact_name', + 'field_public_access_level_2' => 'field_public_access_level_2', + 'field_public_access_level' => 'field_public_access_level', + 'last_checked' => 'last_checked', + 'nothing' => 'nothing', + ); + $handler->display->display_options['style_options']['default'] = '-1'; + $handler->display->display_options['style_options']['info'] = array( + 'url' => array( + 'sortable' => 1, + 'default_sort_order' => 'asc', + 'align' => '', + 'separator' => '', + 'empty_column' => 0, + ), + 'code' => array( + 'sortable' => 1, + 'default_sort_order' => 'asc', + 'align' => '', + 'separator' => '', + 'empty_column' => 0, + ), + 'error' => array( + 'sortable' => 1, + 'default_sort_order' => 'asc', + 'align' => '', + 'separator' => '', + 'empty_column' => 0, + ), + 'link_edit' => array( + 'align' => '', + 'separator' => '', + 'empty_column' => 0, + ), + 'nid' => array( + 'sortable' => 0, + 'default_sort_order' => 'asc', + 'align' => '', + 'separator' => '', + 'empty_column' => 0, + ), + 'edit_node' => array( + 'align' => '', + 'separator' => '', + 'empty_column' => 0, + ), + 'bid' => array( + 'sortable' => 0, + 'default_sort_order' => 'asc', + 'align' => '', + 'separator' => '', + 'empty_column' => 0, + ), + 'block_edit' => array( + 'align' => '', + 'separator' => '', + 'empty_column' => 0, + ), + 'type' => array( + 'sortable' => 1, + 'default_sort_order' => 'asc', + 'align' => '', + 'separator' => '', + 'empty_column' => 0, + ), + 'title' => array( + 'sortable' => 1, + 'default_sort_order' => 'asc', + 'align' => '', + 'separator' => '', + 'empty_column' => 0, + ), + 'field_contact_email_1' => array( + 'sortable' => 0, + 'default_sort_order' => 'asc', + 'align' => '', + 'separator' => '', + 'empty_column' => 0, + ), + 'field_contact_email' => array( + 'sortable' => 0, + 'default_sort_order' => 'asc', + 'align' => '', + 'separator' => '', + 'empty_column' => 0, + ), + 'field_contact_name_1' => array( + 'sortable' => 0, + 'default_sort_order' => 'asc', + 'align' => '', + 'separator' => '', + 'empty_column' => 0, + ), + 'field_contact_name' => array( + 'sortable' => 0, + 'default_sort_order' => 'asc', + 'align' => '', + 'separator' => '', + 'empty_column' => 0, + ), + 'field_public_access_level_2' => array( + 'sortable' => 0, + 'default_sort_order' => 'asc', + 'align' => '', + 'separator' => '', + 'empty_column' => 0, + ), + 'field_public_access_level' => array( + 'sortable' => 0, + 'default_sort_order' => 'asc', + 'align' => '', + 'separator' => '', + 'empty_column' => 0, + ), + 'last_checked' => array( + 'sortable' => 1, + 'default_sort_order' => 'asc', + 'align' => '', + 'separator' => '', + 'empty_column' => 0, + ), + 'nothing' => array( + 'align' => '', + 'separator' => '', + 'empty_column' => 0, + ), + ); + $handler->display->display_options['style_options']['sticky'] = TRUE; + $handler->display->display_options['style_options']['empty_table'] = TRUE; + /* Header: Global: Result summary */ + $handler->display->display_options['header']['result']['id'] = 'result'; + $handler->display->display_options['header']['result']['table'] = 'views'; + $handler->display->display_options['header']['result']['field'] = 'result'; + /* No results behavior: Global: Text area */ + $handler->display->display_options['empty']['area']['id'] = 'area'; + $handler->display->display_options['empty']['area']['table'] = 'views'; + $handler->display->display_options['empty']['area']['field'] = 'area'; + $handler->display->display_options['empty']['area']['empty'] = TRUE; + $handler->display->display_options['empty']['area']['content'] = 'No broken links have been found.'; + $handler->display->display_options['empty']['area']['format'] = 'plain_text'; + /* Relationship: Broken links: Content with link */ + $handler->display->display_options['relationships']['nid']['id'] = 'nid'; + $handler->display->display_options['relationships']['nid']['table'] = 'linkchecker_node'; + $handler->display->display_options['relationships']['nid']['field'] = 'nid'; + /* Relationship: Entity Reference: Referenced Entity */ + $handler->display->display_options['relationships']['field_dataset_ref_target_id']['id'] = 'field_dataset_ref_target_id'; + $handler->display->display_options['relationships']['field_dataset_ref_target_id']['table'] = 'field_data_field_dataset_ref'; + $handler->display->display_options['relationships']['field_dataset_ref_target_id']['field'] = 'field_dataset_ref_target_id'; + $handler->display->display_options['relationships']['field_dataset_ref_target_id']['relationship'] = 'nid'; + /* Field: Broken links: URL */ + $handler->display->display_options['fields']['url']['id'] = 'url'; + $handler->display->display_options['fields']['url']['table'] = 'linkchecker_link'; + $handler->display->display_options['fields']['url']['field'] = 'url'; + $handler->display->display_options['fields']['url']['alter']['max_length'] = '40'; + $handler->display->display_options['fields']['url']['alter']['word_boundary'] = FALSE; + $handler->display->display_options['fields']['url']['alter']['trim'] = TRUE; + $handler->display->display_options['fields']['url']['hide_empty'] = TRUE; + /* Field: Broken links: HTTP status code */ + $handler->display->display_options['fields']['code']['id'] = 'code'; + $handler->display->display_options['fields']['code']['table'] = 'linkchecker_link'; + $handler->display->display_options['fields']['code']['field'] = 'code'; + $handler->display->display_options['fields']['code']['label'] = 'Response'; + $handler->display->display_options['fields']['code']['separator'] = ''; + /* Field: Broken links: Error message */ + $handler->display->display_options['fields']['error']['id'] = 'error'; + $handler->display->display_options['fields']['error']['table'] = 'linkchecker_link'; + $handler->display->display_options['fields']['error']['field'] = 'error'; + $handler->display->display_options['fields']['error']['label'] = 'Error'; + /* Field: Broken links: Edit link settings */ + $handler->display->display_options['fields']['link_edit']['id'] = 'link_edit'; + $handler->display->display_options['fields']['link_edit']['table'] = 'linkchecker_link'; + $handler->display->display_options['fields']['link_edit']['field'] = 'link_edit'; + $handler->display->display_options['fields']['link_edit']['exclude'] = TRUE; + $handler->display->display_options['fields']['link_edit']['alter']['alter_text'] = TRUE; + $handler->display->display_options['fields']['link_edit']['alter']['text'] = '
Edit link settings
'; + $handler->display->display_options['fields']['link_edit']['hide_empty'] = TRUE; + /* Field: Content: Nid */ + $handler->display->display_options['fields']['nid']['id'] = 'nid'; + $handler->display->display_options['fields']['nid']['table'] = 'node'; + $handler->display->display_options['fields']['nid']['field'] = 'nid'; + $handler->display->display_options['fields']['nid']['relationship'] = 'nid'; + $handler->display->display_options['fields']['nid']['exclude'] = TRUE; + /* Field: Content: Edit link */ + $handler->display->display_options['fields']['edit_node']['id'] = 'edit_node'; + $handler->display->display_options['fields']['edit_node']['table'] = 'views_entity_node'; + $handler->display->display_options['fields']['edit_node']['field'] = 'edit_node'; + $handler->display->display_options['fields']['edit_node']['relationship'] = 'nid'; + $handler->display->display_options['fields']['edit_node']['label'] = 'Edit node'; + $handler->display->display_options['fields']['edit_node']['exclude'] = TRUE; + $handler->display->display_options['fields']['edit_node']['alter']['alter_text'] = TRUE; + $handler->display->display_options['fields']['edit_node']['alter']['text'] = '
Edit node [nid]
'; + $handler->display->display_options['fields']['edit_node']['hide_empty'] = TRUE; + /* Field: Content: Type */ + $handler->display->display_options['fields']['type']['id'] = 'type'; + $handler->display->display_options['fields']['type']['table'] = 'node'; + $handler->display->display_options['fields']['type']['field'] = 'type'; + $handler->display->display_options['fields']['type']['relationship'] = 'nid'; + /* Field: Content: Title */ + $handler->display->display_options['fields']['title']['id'] = 'title'; + $handler->display->display_options['fields']['title']['table'] = 'node'; + $handler->display->display_options['fields']['title']['field'] = 'title'; + $handler->display->display_options['fields']['title']['relationship'] = 'nid'; + /* Field: Resource contact email */ + $handler->display->display_options['fields']['field_contact_email_1']['id'] = 'field_contact_email_1'; + $handler->display->display_options['fields']['field_contact_email_1']['table'] = 'field_data_field_contact_email'; + $handler->display->display_options['fields']['field_contact_email_1']['field'] = 'field_contact_email'; + $handler->display->display_options['fields']['field_contact_email_1']['relationship'] = 'field_dataset_ref_target_id'; + $handler->display->display_options['fields']['field_contact_email_1']['ui_name'] = 'Resource contact email'; + $handler->display->display_options['fields']['field_contact_email_1']['label'] = ''; + $handler->display->display_options['fields']['field_contact_email_1']['exclude'] = TRUE; + $handler->display->display_options['fields']['field_contact_email_1']['element_label_colon'] = FALSE; + /* Field: Dataset contact email */ + $handler->display->display_options['fields']['field_contact_email']['id'] = 'field_contact_email'; + $handler->display->display_options['fields']['field_contact_email']['table'] = 'field_data_field_contact_email'; + $handler->display->display_options['fields']['field_contact_email']['field'] = 'field_contact_email'; + $handler->display->display_options['fields']['field_contact_email']['relationship'] = 'nid'; + $handler->display->display_options['fields']['field_contact_email']['ui_name'] = 'Dataset contact email'; + $handler->display->display_options['fields']['field_contact_email']['label'] = ''; + $handler->display->display_options['fields']['field_contact_email']['exclude'] = TRUE; + $handler->display->display_options['fields']['field_contact_email']['element_label_colon'] = FALSE; + /* Field: Content: Contact Name */ + $handler->display->display_options['fields']['field_contact_name_1']['id'] = 'field_contact_name_1'; + $handler->display->display_options['fields']['field_contact_name_1']['table'] = 'field_data_field_contact_name'; + $handler->display->display_options['fields']['field_contact_name_1']['field'] = 'field_contact_name'; + $handler->display->display_options['fields']['field_contact_name_1']['relationship'] = 'field_dataset_ref_target_id'; + $handler->display->display_options['fields']['field_contact_name_1']['label'] = ''; + $handler->display->display_options['fields']['field_contact_name_1']['exclude'] = TRUE; + $handler->display->display_options['fields']['field_contact_name_1']['element_label_colon'] = FALSE; + /* Field: Content: Contact Name */ + $handler->display->display_options['fields']['field_contact_name']['id'] = 'field_contact_name'; + $handler->display->display_options['fields']['field_contact_name']['table'] = 'field_data_field_contact_name'; + $handler->display->display_options['fields']['field_contact_name']['field'] = 'field_contact_name'; + $handler->display->display_options['fields']['field_contact_name']['relationship'] = 'nid'; + $handler->display->display_options['fields']['field_contact_name']['empty'] = '[field_contact_name_1]'; + /* Field: Resource Access Level */ + $handler->display->display_options['fields']['field_public_access_level_2']['id'] = 'field_public_access_level_2'; + $handler->display->display_options['fields']['field_public_access_level_2']['table'] = 'field_data_field_public_access_level'; + $handler->display->display_options['fields']['field_public_access_level_2']['field'] = 'field_public_access_level'; + $handler->display->display_options['fields']['field_public_access_level_2']['relationship'] = 'field_dataset_ref_target_id'; + $handler->display->display_options['fields']['field_public_access_level_2']['ui_name'] = 'Resource Access Level'; + $handler->display->display_options['fields']['field_public_access_level_2']['label'] = 'Resource Access Level'; + $handler->display->display_options['fields']['field_public_access_level_2']['exclude'] = TRUE; + /* Field: Dataset Access Level */ + $handler->display->display_options['fields']['field_public_access_level']['id'] = 'field_public_access_level'; + $handler->display->display_options['fields']['field_public_access_level']['table'] = 'field_data_field_public_access_level'; + $handler->display->display_options['fields']['field_public_access_level']['field'] = 'field_public_access_level'; + $handler->display->display_options['fields']['field_public_access_level']['relationship'] = 'nid'; + $handler->display->display_options['fields']['field_public_access_level']['ui_name'] = 'Dataset Access Level'; + $handler->display->display_options['fields']['field_public_access_level']['label'] = 'Access Level'; + $handler->display->display_options['fields']['field_public_access_level']['empty'] = '[field_public_access_level_2]'; + /* Field: Broken links: Last checked */ + $handler->display->display_options['fields']['last_checked']['id'] = 'last_checked'; + $handler->display->display_options['fields']['last_checked']['table'] = 'linkchecker_link'; + $handler->display->display_options['fields']['last_checked']['field'] = 'last_checked'; + $handler->display->display_options['fields']['last_checked']['date_format'] = 'iso_8601_date'; + $handler->display->display_options['fields']['last_checked']['second_date_format'] = 'iso_8601_date'; + /* Field: Global: Custom text */ + $handler->display->display_options['fields']['nothing']['id'] = 'nothing'; + $handler->display->display_options['fields']['nothing']['table'] = 'views'; + $handler->display->display_options['fields']['nothing']['field'] = 'nothing'; + $handler->display->display_options['fields']['nothing']['label'] = 'Operations'; + $handler->display->display_options['fields']['nothing']['alter']['text'] = '[link_edit] + [edit_node]'; + $handler->display->display_options['fields']['nothing']['hide_empty'] = TRUE; + $handler->display->display_options['fields']['nothing']['hide_alter_empty'] = TRUE; + /* Sort criterion: Content: Title */ + $handler->display->display_options['sorts']['title']['id'] = 'title'; + $handler->display->display_options['sorts']['title']['table'] = 'node'; + $handler->display->display_options['sorts']['title']['field'] = 'title'; + $handler->display->display_options['sorts']['title']['relationship'] = 'nid'; + /* Filter criterion: Broken links: Last checked */ + $handler->display->display_options['filters']['last_checked']['id'] = 'last_checked'; + $handler->display->display_options['filters']['last_checked']['table'] = 'linkchecker_link'; + $handler->display->display_options['filters']['last_checked']['field'] = 'last_checked'; + $handler->display->display_options['filters']['last_checked']['operator'] = '!='; + $handler->display->display_options['filters']['last_checked']['value']['value'] = '0'; + $handler->display->display_options['filters']['last_checked']['group'] = 1; + /* Filter criterion: Broken links: Status */ + $handler->display->display_options['filters']['status']['id'] = 'status'; + $handler->display->display_options['filters']['status']['table'] = 'linkchecker_link'; + $handler->display->display_options['filters']['status']['field'] = 'status'; + $handler->display->display_options['filters']['status']['value'] = '1'; + $handler->display->display_options['filters']['status']['group'] = 1; + $handler->display->display_options['filters']['status']['expose']['operator_id'] = ''; + $handler->display->display_options['filters']['status']['expose']['label'] = 'Check link status'; + $handler->display->display_options['filters']['status']['expose']['operator'] = 'status_op'; + $handler->display->display_options['filters']['status']['expose']['identifier'] = 'status'; + $handler->display->display_options['filters']['status']['expose']['required'] = TRUE; + /* Filter criterion: Broken links: HTTP status code */ + $handler->display->display_options['filters']['code_1']['id'] = 'code_1'; + $handler->display->display_options['filters']['code_1']['table'] = 'linkchecker_link'; + $handler->display->display_options['filters']['code_1']['field'] = 'code'; + $handler->display->display_options['filters']['code_1']['operator'] = 'not in'; + $handler->display->display_options['filters']['code_1']['value'] = array( + 200 => '200', + 301 => '301', + 302 => '302', + ); + $handler->display->display_options['filters']['code_1']['group'] = 1; + /* Filter criterion: Broken links: HTTP status code */ + $handler->display->display_options['filters']['code']['id'] = 'code'; + $handler->display->display_options['filters']['code']['table'] = 'linkchecker_link'; + $handler->display->display_options['filters']['code']['field'] = 'code'; + $handler->display->display_options['filters']['code']['value'] = array( + 100 => '100', + 101 => '101', + 201 => '201', + 202 => '202', + 203 => '203', + 204 => '204', + 205 => '205', + 206 => '206', + 300 => '300', + 301 => '301', + 302 => '302', + 303 => '303', + 304 => '304', + 305 => '305', + 307 => '307', + 400 => '400', + 401 => '401', + 402 => '402', + 403 => '403', + 404 => '404', + 405 => '405', + 406 => '406', + 407 => '407', + 408 => '408', + 409 => '409', + 410 => '410', + 411 => '411', + 412 => '412', + 413 => '413', + 414 => '414', + 415 => '415', + 416 => '416', + 417 => '417', + 500 => '500', + 501 => '501', + 502 => '502', + 503 => '503', + 504 => '504', + 505 => '505', + -10053 => '-10053', + -11001 => '-11001', + ); + $handler->display->display_options['filters']['code']['group'] = 1; + $handler->display->display_options['filters']['code']['exposed'] = TRUE; + $handler->display->display_options['filters']['code']['expose']['operator_id'] = 'code_op'; + $handler->display->display_options['filters']['code']['expose']['label'] = 'HTTP status code'; + $handler->display->display_options['filters']['code']['expose']['operator'] = 'code_op'; + $handler->display->display_options['filters']['code']['expose']['identifier'] = 'code'; + $handler->display->display_options['filters']['code']['expose']['remember_roles'] = array( + 2 => '2', + 11 => 0, + 1 => 0, + 21 => 0, + 16 => 0, + 26 => 0, + ); + $handler->display->display_options['filters']['code']['expose']['reduce'] = TRUE; + /* Filter criterion: Content: Type */ + $handler->display->display_options['filters']['type']['id'] = 'type'; + $handler->display->display_options['filters']['type']['table'] = 'node'; + $handler->display->display_options['filters']['type']['field'] = 'type'; + $handler->display->display_options['filters']['type']['relationship'] = 'nid'; + $handler->display->display_options['filters']['type']['value'] = array( + 'dataset' => 'dataset', + 'harvest_source' => 'harvest_source', + 'resource' => 'resource', + ); + $handler->display->display_options['filters']['type']['group'] = 1; + $handler->display->display_options['filters']['type']['exposed'] = TRUE; + $handler->display->display_options['filters']['type']['expose']['operator_id'] = 'type_op'; + $handler->display->display_options['filters']['type']['expose']['label'] = 'Type'; + $handler->display->display_options['filters']['type']['expose']['operator'] = 'type_op'; + $handler->display->display_options['filters']['type']['expose']['identifier'] = 'type'; + $handler->display->display_options['filters']['type']['expose']['remember_roles'] = array( + 2 => '2', + 11 => 0, + 1 => 0, + 21 => 0, + 16 => 0, + 26 => 0, + ); + $handler->display->display_options['filters']['type']['expose']['reduce'] = TRUE; + /* Filter criterion: Content: Public Access Level (field_public_access_level) */ + $handler->display->display_options['filters']['field_public_access_level_value']['id'] = 'field_public_access_level_value'; + $handler->display->display_options['filters']['field_public_access_level_value']['table'] = 'field_data_field_public_access_level'; + $handler->display->display_options['filters']['field_public_access_level_value']['field'] = 'field_public_access_level_value'; + $handler->display->display_options['filters']['field_public_access_level_value']['relationship'] = 'nid'; + $handler->display->display_options['filters']['field_public_access_level_value']['group'] = 1; + $handler->display->display_options['filters']['field_public_access_level_value']['exposed'] = TRUE; + $handler->display->display_options['filters']['field_public_access_level_value']['expose']['operator_id'] = 'field_public_access_level_value_op'; + $handler->display->display_options['filters']['field_public_access_level_value']['expose']['label'] = 'Public Access Level'; + $handler->display->display_options['filters']['field_public_access_level_value']['expose']['operator'] = 'field_public_access_level_value_op'; + $handler->display->display_options['filters']['field_public_access_level_value']['expose']['identifier'] = 'field_public_access_level_value'; + $handler->display->display_options['filters']['field_public_access_level_value']['expose']['remember_roles'] = array( + 2 => '2', + 3 => 0, + 1 => 0, + 5 => 0, + 4 => 0, + 6 => 0, + ); + + /* Display: Advanced Broken links */ + $handler = $view->new_display('page', 'Advanced Broken links', 'dkan_linkchecker_admin_report_page'); + $handler->display->display_options['defaults']['title'] = FALSE; + $handler->display->display_options['title'] = 'Broken Links Report'; + $handler->display->display_options['display_description'] = 'Shows a list of broken links in content, with advanced filters.'; + $handler->display->display_options['defaults']['hide_admin_links'] = FALSE; + $handler->display->display_options['path'] = 'admin/reports/dkan-linkchecker-report'; + $handler->display->display_options['menu']['type'] = 'normal'; + $handler->display->display_options['menu']['title'] = 'Broken Links Report'; + $handler->display->display_options['menu']['description'] = 'Shows a list of broken links in content, with advanced filters.'; + $handler->display->display_options['menu']['weight'] = '2'; + $handler->display->display_options['menu']['name'] = 'management'; + $handler->display->display_options['menu']['context'] = 0; + $handler->display->display_options['menu']['context_only_inline'] = 0; + $export['dkan_linkchecker_reports'] = $view; + return $export; +} diff --git a/modules/dkan/dkan_sitewide/dkan_sitewide.module b/modules/dkan/dkan_sitewide/dkan_sitewide.module index b8bffbbc40..798884c553 100644 --- a/modules/dkan/dkan_sitewide/dkan_sitewide.module +++ b/modules/dkan/dkan_sitewide/dkan_sitewide.module @@ -167,7 +167,8 @@ function dkan_sitewide_update_status_alter(&$projects) { 'beautytips', 'feeds_field_fetcher', 'multistep', - 'file_resup' + 'file_resup', + 'linkchecker', ); foreach ($up_to_date_projects as $up_to_date_project) { diff --git a/patches/dkan_linkchecker_file.patch b/patches/dkan_linkchecker_file.patch new file mode 100644 index 0000000000..da9a3444e6 --- /dev/null +++ b/patches/dkan_linkchecker_file.patch @@ -0,0 +1,38 @@ +diff --git a/linkchecker.module b/linkchecker.module +index b7bbe3e..9b4b440 100644 +--- a/linkchecker.module ++++ b/linkchecker.module +@@ -333,6 +333,7 @@ function _linkchecker_link_node_ids($link, $node_author_account = NULL) { + 'text_long', + 'text', + 'link_field', ++ 'file', + ); + + // Only check link and text fields, since those are the only types we +@@ -1774,6 +1775,26 @@ function _linkchecker_parse_fields($entity_type, $bundle_name, $entity, $return_ + } + } + break; ++ ++ // File module field. ++ case 'file': ++ foreach ($entity_field as $language) { ++ foreach ($language as $item) { ++ $item += array( ++ 'title' => '', ++ ); ++ if (isset($item['uri'])) { ++ $text_items[] = $text_items_by_field[$field['field_name']][] = l($item['title'], $item['uri']); ++ $text_items[] = $text_items_by_field[$field['field_name']][] = _linkchecker_check_markup($item['title'], NULL, linkchecker_entity_language($entity_type, $entity), TRUE); ++ } ++ elseif (isset($item['filefield_dkan_remotefile']['url'])) { ++ $text_items[] = $text_items_by_field[$field['field_name']][] = l($item['title'], $item['filefield_dkan_remotefile']['url']); ++ $text_items[] = $text_items_by_field[$field['field_name']][] = _linkchecker_check_markup($item['title'], NULL, linkchecker_entity_language($entity_type, $entity), TRUE); ++ } ++ } ++ } ++ break; ++ + } + } diff --git a/test/behat.yml b/test/behat.yml index 4278c3b55b..7414de3f5e 100644 --- a/test/behat.yml +++ b/test/behat.yml @@ -16,6 +16,7 @@ default: - Drupal\DKANExtension\Context\HarvestSourceContext - Drupal\DKANExtension\Context\WorkflowContext - Drupal\DKANExtension\Context\DatasetAutoFillContext + - Drupal\DKANExtension\Context\LinkcheckerContext - Drupal\DKANExtension\Context\DatasetContext: - fields: title: title @@ -178,6 +179,7 @@ default: modal: "#modalContent" navigation: ".navigation-wrapper" other access: ".pane-dkan-sitewide-dkan-sitewide-other-access" + page header: ".page-header" primary tabs: ".tabs--primary" recline preview: ".recline-data-explorer" resource groups: "#edit-groups" diff --git a/test/composer.json b/test/composer.json index e867a6df99..e49103687c 100644 --- a/test/composer.json +++ b/test/composer.json @@ -12,7 +12,7 @@ "myplanetdigital/function_mock": "dev-master", "drupal/drupal-driver": "^1.2", "drupal/drupal-extension": "~3.0", - "squizlabs/php_codesniffer": "2.7.0", + "squizlabs/php_codesniffer": "^2.7.0", "drupal/coder": "8.2.10", "guzzlehttp/guzzle": "^6.3", "dkan/dkan_api_client": "1.0.0" @@ -20,10 +20,12 @@ "autoload": { "psr-0": { "Drupal\\DKANExtension\\": "dkanextension/src/" - }, - "drupal/coder": "8.2.10" + } }, "config": { - "bin-dir": "bin/" + "bin-dir": "bin/", + "platform": { + "php": "5.6.23" + } } } diff --git a/test/composer.lock b/test/composer.lock index b97686b03a..e44bd56866 100644 --- a/test/composer.lock +++ b/test/composer.lock @@ -1,10 +1,10 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "917c7eb3f81c0274b3fa9034faa7bcee", + "content-hash": "26bf28e6750b11dba8e69a9395de9055", "packages": [ { "name": "behat/behat", @@ -261,16 +261,16 @@ }, { "name": "behat/mink-extension", - "version": "2.3.0", + "version": "2.3.1", "source": { "type": "git", "url": "https://github.com/Behat/MinkExtension.git", - "reference": "badc565b7a1d05c4a4bf49c789045bcf7af6c6de" + "reference": "80f7849ba53867181b7e412df9210e12fba50177" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Behat/MinkExtension/zipball/badc565b7a1d05c4a4bf49c789045bcf7af6c6de", - "reference": "badc565b7a1d05c4a4bf49c789045bcf7af6c6de", + "url": "https://api.github.com/repos/Behat/MinkExtension/zipball/80f7849ba53867181b7e412df9210e12fba50177", + "reference": "80f7849ba53867181b7e412df9210e12fba50177", "shasum": "" }, "require": { @@ -316,7 +316,7 @@ "test", "web" ], - "time": "2017-11-24T19:30:49+00:00" + "time": "2018-02-06T15:36:30+00:00" }, { "name": "behat/mink-goutte-driver", @@ -647,21 +647,94 @@ ], "time": "2016-12-09T21:57:53+00:00" }, + { + "name": "drupal/core-render", + "version": "8.5.1", + "source": { + "type": "git", + "url": "https://github.com/drupal/core-render.git", + "reference": "168566d2d6b3465dc23249e97832330e4e628ea0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/drupal/core-render/zipball/168566d2d6b3465dc23249e97832330e4e628ea0", + "reference": "168566d2d6b3465dc23249e97832330e4e628ea0", + "shasum": "" + }, + "require": { + "drupal/core-utility": "^8.2", + "php": ">=5.5.9" + }, + "type": "library", + "autoload": { + "psr-4": { + "Drupal\\Component\\Render\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "description": "Renders placeholder variables for HTML and plain-text display.", + "homepage": "https://www.drupal.org/project/drupal", + "keywords": [ + "drupal" + ], + "time": "2018-02-01T21:35:01+00:00" + }, + { + "name": "drupal/core-utility", + "version": "8.5.1", + "source": { + "type": "git", + "url": "https://github.com/drupal/core-utility.git", + "reference": "affc9c7697820cc04f86d680914aa6d0d479935c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/drupal/core-utility/zipball/affc9c7697820cc04f86d680914aa6d0d479935c", + "reference": "affc9c7697820cc04f86d680914aa6d0d479935c", + "shasum": "" + }, + "require": { + "drupal/core-render": "^8.2", + "paragonie/random_compat": "^1.0|^2.0", + "php": ">=5.5.9" + }, + "type": "library", + "autoload": { + "psr-4": { + "Drupal\\Component\\Utility\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "description": "Mostly static utility classes for string, xss, array, image, and other commonly needed manipulations.", + "homepage": "https://www.drupal.org/project/drupal", + "keywords": [ + "drupal" + ], + "time": "2018-02-07T14:32:13+00:00" + }, { "name": "drupal/drupal-driver", - "version": "v1.3.2", + "version": "v1.4.0", "source": { "type": "git", "url": "https://github.com/jhedstrom/DrupalDriver.git", - "reference": "aa1f32b207939dfc0c96919be47b952d3c1b900b" + "reference": "919c6a39ef6a17bdcaf81dcff97b117ecfb6061c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/jhedstrom/DrupalDriver/zipball/aa1f32b207939dfc0c96919be47b952d3c1b900b", - "reference": "aa1f32b207939dfc0c96919be47b952d3c1b900b", + "url": "https://api.github.com/repos/jhedstrom/DrupalDriver/zipball/919c6a39ef6a17bdcaf81dcff97b117ecfb6061c", + "reference": "919c6a39ef6a17bdcaf81dcff97b117ecfb6061c", "shasum": "" }, "require": { + "drupal/core-utility": "^8.4", + "php": ">=5.5.9", "symfony/dependency-injection": "~2.6|~3.0", "symfony/process": "~2.5|~3.0" }, @@ -681,14 +754,13 @@ }, "autoload": { "psr-0": { - "Drupal\\Component": "src/", "Drupal\\Driver": "src/", "Drupal\\Tests\\Driver": "tests/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "GPL-2.0+" + "GPL-2.0-or-later" ], "authors": [ { @@ -703,7 +775,7 @@ "test", "web" ], - "time": "2017-11-28T21:51:43+00:00" + "time": "2018-02-09T18:02:28+00:00" }, { "name": "drupal/drupal-extension", @@ -823,16 +895,16 @@ }, { "name": "guzzlehttp/guzzle", - "version": "6.3.0", + "version": "6.3.2", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699" + "reference": "68d0ea14d5a3f42a20e87632a5f84931e2709c90" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/f4db5a78a5ea468d4831de7f0bf9d9415e348699", - "reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/68d0ea14d5a3f42a20e87632a5f84931e2709c90", + "reference": "68d0ea14d5a3f42a20e87632a5f84931e2709c90", "shasum": "" }, "require": { @@ -842,7 +914,7 @@ }, "require-dev": { "ext-curl": "*", - "phpunit/phpunit": "^4.0 || ^5.0", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4", "psr/log": "^1.0" }, "suggest": { @@ -851,7 +923,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "6.2-dev" + "dev-master": "6.3-dev" } }, "autoload": { @@ -884,7 +956,7 @@ "rest", "web service" ], - "time": "2017-06-22T18:50:49+00:00" + "time": "2018-03-26T16:33:04+00:00" }, { "name": "guzzlehttp/promises", @@ -1146,6 +1218,54 @@ "abandoned": true, "time": "2014-03-07T18:56:45+00:00" }, + { + "name": "paragonie/random_compat", + "version": "v2.0.12", + "source": { + "type": "git", + "url": "https://github.com/paragonie/random_compat.git", + "reference": "258c89a6b97de7dfaf5b8c7607d0478e236b04fb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/258c89a6b97de7dfaf5b8c7607d0478e236b04fb", + "reference": "258c89a6b97de7dfaf5b8c7607d0478e236b04fb", + "shasum": "" + }, + "require": { + "php": ">=5.2.0" + }, + "require-dev": { + "phpunit/phpunit": "4.*|5.*" + }, + "suggest": { + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + }, + "type": "library", + "autoload": { + "files": [ + "lib/random.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "keywords": [ + "csprng", + "pseudorandom", + "random" + ], + "time": "2018-04-04T21:24:14+00:00" + }, { "name": "phpdocumentor/reflection-common", "version": "1.0.1", @@ -1294,28 +1414,28 @@ }, { "name": "phpspec/prophecy", - "version": "1.7.3", + "version": "1.7.6", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "e4ed002c67da8eceb0eb8ddb8b3847bb53c5c2bf" + "reference": "33a7e3c4fda54e912ff6338c48823bd5c0f0b712" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/e4ed002c67da8eceb0eb8ddb8b3847bb53c5c2bf", - "reference": "e4ed002c67da8eceb0eb8ddb8b3847bb53c5c2bf", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/33a7e3c4fda54e912ff6338c48823bd5c0f0b712", + "reference": "33a7e3c4fda54e912ff6338c48823bd5c0f0b712", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.3|^7.0", "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", - "sebastian/comparator": "^1.1|^2.0", + "sebastian/comparator": "^1.1|^2.0|^3.0", "sebastian/recursion-context": "^1.0|^2.0|^3.0" }, "require-dev": { "phpspec/phpspec": "^2.5|^3.2", - "phpunit/phpunit": "^4.8.35 || ^5.7" + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5" }, "type": "library", "extra": { @@ -1353,7 +1473,7 @@ "spy", "stub" ], - "time": "2017-11-24T13:59:53+00:00" + "time": "2018-04-18T13:57:24+00:00" }, { "name": "phpunit/php-code-coverage", @@ -2357,16 +2477,16 @@ }, { "name": "squizlabs/php_codesniffer", - "version": "2.7.0", + "version": "2.9.1", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "571e27b6348e5b3a637b2abc82ac0d01e6d7bbed" + "reference": "dcbed1074f8244661eecddfc2a675430d8d33f62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/571e27b6348e5b3a637b2abc82ac0d01e6d7bbed", - "reference": "571e27b6348e5b3a637b2abc82ac0d01e6d7bbed", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/dcbed1074f8244661eecddfc2a675430d8d33f62", + "reference": "dcbed1074f8244661eecddfc2a675430d8d33f62", "shasum": "" }, "require": { @@ -2431,20 +2551,20 @@ "phpcs", "standards" ], - "time": "2016-09-01T23:53:02+00:00" + "time": "2017-05-22T02:43:20+00:00" }, { "name": "symfony/browser-kit", - "version": "v3.4.4", + "version": "v3.4.8", "source": { "type": "git", "url": "https://github.com/symfony/browser-kit.git", - "reference": "490f27762705c8489bd042fe3e9377a191dba9b4" + "reference": "840bb6f0d5b3701fd768b68adf7193c2d0f98f79" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/browser-kit/zipball/490f27762705c8489bd042fe3e9377a191dba9b4", - "reference": "490f27762705c8489bd042fe3e9377a191dba9b4", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/840bb6f0d5b3701fd768b68adf7193c2d0f98f79", + "reference": "840bb6f0d5b3701fd768b68adf7193c2d0f98f79", "shasum": "" }, "require": { @@ -2488,11 +2608,11 @@ ], "description": "Symfony BrowserKit Component", "homepage": "https://symfony.com", - "time": "2018-01-03T07:37:34+00:00" + "time": "2018-03-19T22:32:39+00:00" }, { "name": "symfony/class-loader", - "version": "v3.4.4", + "version": "v3.4.8", "source": { "type": "git", "url": "https://github.com/symfony/class-loader.git", @@ -2667,16 +2787,16 @@ }, { "name": "symfony/css-selector", - "version": "v3.4.4", + "version": "v3.4.8", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "e66394bc7610e69279bfdb3ab11b4fe65403f556" + "reference": "519a80d7c1d95c6cc0b67f686d15fe27c6910de0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/e66394bc7610e69279bfdb3ab11b4fe65403f556", - "reference": "e66394bc7610e69279bfdb3ab11b4fe65403f556", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/519a80d7c1d95c6cc0b67f686d15fe27c6910de0", + "reference": "519a80d7c1d95c6cc0b67f686d15fe27c6910de0", "shasum": "" }, "require": { @@ -2716,20 +2836,20 @@ ], "description": "Symfony CssSelector Component", "homepage": "https://symfony.com", - "time": "2018-01-03T07:37:34+00:00" + "time": "2018-03-19T22:32:39+00:00" }, { "name": "symfony/debug", - "version": "v3.4.4", + "version": "v3.4.8", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", - "reference": "53f6af2805daf52a43b393b93d2f24925d35c937" + "reference": "9cf7c2271cfb89ef9727db1b740ca77be57bf9d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/53f6af2805daf52a43b393b93d2f24925d35c937", - "reference": "53f6af2805daf52a43b393b93d2f24925d35c937", + "url": "https://api.github.com/repos/symfony/debug/zipball/9cf7c2271cfb89ef9727db1b740ca77be57bf9d7", + "reference": "9cf7c2271cfb89ef9727db1b740ca77be57bf9d7", "shasum": "" }, "require": { @@ -2772,20 +2892,20 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", - "time": "2018-01-18T22:16:57+00:00" + "time": "2018-04-03T05:22:50+00:00" }, { "name": "symfony/dependency-injection", - "version": "v2.8.34", + "version": "v2.8.38", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "91ad61e6f140b050eba4aa39bc52eece713f2a71" + "reference": "3d7cbf34cd75ede7f94b9b990f85bd089e15cd55" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/91ad61e6f140b050eba4aa39bc52eece713f2a71", - "reference": "91ad61e6f140b050eba4aa39bc52eece713f2a71", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/3d7cbf34cd75ede7f94b9b990f85bd089e15cd55", + "reference": "3d7cbf34cd75ede7f94b9b990f85bd089e15cd55", "shasum": "" }, "require": { @@ -2835,20 +2955,20 @@ ], "description": "Symfony DependencyInjection Component", "homepage": "https://symfony.com", - "time": "2018-01-29T08:55:23+00:00" + "time": "2018-02-19T16:23:47+00:00" }, { "name": "symfony/dom-crawler", - "version": "v3.4.4", + "version": "v3.4.8", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "09bd97b844b3151fab82f2fdd62db9c464b3910a" + "reference": "1a4cffeb059226ff6bee9f48acb388faf674afff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/09bd97b844b3151fab82f2fdd62db9c464b3910a", - "reference": "09bd97b844b3151fab82f2fdd62db9c464b3910a", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/1a4cffeb059226ff6bee9f48acb388faf674afff", + "reference": "1a4cffeb059226ff6bee9f48acb388faf674afff", "shasum": "" }, "require": { @@ -2891,20 +3011,20 @@ ], "description": "Symfony DomCrawler Component", "homepage": "https://symfony.com", - "time": "2018-01-03T07:37:34+00:00" + "time": "2018-03-19T22:32:39+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v2.8.34", + "version": "v2.8.38", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "d64be24fc1eba62f9daace8a8918f797fc8e87cc" + "reference": "9b69aad7d4c086dc94ebade2d5eb9145da5dac8c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/d64be24fc1eba62f9daace8a8918f797fc8e87cc", - "reference": "d64be24fc1eba62f9daace8a8918f797fc8e87cc", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/9b69aad7d4c086dc94ebade2d5eb9145da5dac8c", + "reference": "9b69aad7d4c086dc94ebade2d5eb9145da5dac8c", "shasum": "" }, "require": { @@ -2951,20 +3071,20 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2018-01-03T07:36:31+00:00" + "time": "2018-04-06T07:35:03+00:00" }, { "name": "symfony/filesystem", - "version": "v3.4.4", + "version": "v3.4.8", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "e078773ad6354af38169faf31c21df0f18ace03d" + "reference": "253a4490b528597aa14d2bf5aeded6f5e5e4a541" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/e078773ad6354af38169faf31c21df0f18ace03d", - "reference": "e078773ad6354af38169faf31c21df0f18ace03d", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/253a4490b528597aa14d2bf5aeded6f5e5e4a541", + "reference": "253a4490b528597aa14d2bf5aeded6f5e5e4a541", "shasum": "" }, "require": { @@ -3000,7 +3120,7 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2018-01-03T07:37:34+00:00" + "time": "2018-02-22T10:48:49+00:00" }, { "name": "symfony/polyfill-mbstring", @@ -3063,16 +3183,16 @@ }, { "name": "symfony/process", - "version": "v3.4.4", + "version": "v3.4.8", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "09a5172057be8fc677840e591b17f385e58c7c0d" + "reference": "4b7d64e852886319e93ddfdecff0d744ab87658b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/09a5172057be8fc677840e591b17f385e58c7c0d", - "reference": "09a5172057be8fc677840e591b17f385e58c7c0d", + "url": "https://api.github.com/repos/symfony/process/zipball/4b7d64e852886319e93ddfdecff0d744ab87658b", + "reference": "4b7d64e852886319e93ddfdecff0d744ab87658b", "shasum": "" }, "require": { @@ -3108,7 +3228,7 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2018-01-29T09:03:43+00:00" + "time": "2018-04-03T05:22:50+00:00" }, { "name": "symfony/translation", @@ -3292,5 +3412,8 @@ "prefer-stable": false, "prefer-lowest": false, "platform": [], - "platform-dev": [] + "platform-dev": [], + "platform-overrides": { + "php": "5.6.23" + } } diff --git a/test/dkanextension/src/Drupal/DKANExtension/Context/LinkcheckerContext.php b/test/dkanextension/src/Drupal/DKANExtension/Context/LinkcheckerContext.php new file mode 100644 index 0000000000..901b0fd29e --- /dev/null +++ b/test/dkanextension/src/Drupal/DKANExtension/Context/LinkcheckerContext.php @@ -0,0 +1,61 @@ +