Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Player formatter #22

Merged
merged 17 commits into from May 8, 2018
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -95,8 +95,8 @@ unit_kernel_tests: &unit_kernel_tests
- store_artifacts:
path: /var/www/html/artifacts

# Run Behat tests. This command invokes the test-js.sh hook.
behat_tests: &behat_tests
# Run FunctionalJavascript tests. This command invokes the test-js.sh hook.
js_tests: &js_tests
<<: *defaults
steps:
- attach_workspace:
@@ -107,6 +107,7 @@ behat_tests: &behat_tests
- run:
working_directory: /var/www/html
command: |
cp modules/$CIRCLE_PROJECT_REPONAME/.circleci/test-js.sh .
./test-js.sh $CIRCLE_PROJECT_REPONAME
- store_artifacts:
@@ -154,8 +155,8 @@ jobs:
<<: *update_dependencies
run-unit-kernel-tests:
<<: *unit_kernel_tests
run-behat-tests:
<<: *behat_tests
run-js-tests:
<<: *js_tests
run-code-sniffer:
<<: *code_sniffer

@@ -169,7 +170,7 @@ workflows:
- run-unit-kernel-tests:
requires:
- update-dependencies
- run-behat-tests:
- run-js-tests:
requires:
- update-dependencies
- run-code-sniffer:
@@ -182,7 +183,7 @@ workflows:
- run-unit-kernel-tests:
requires:
- update-dependencies
- run-behat-tests:
- run-js-tests:
requires:
- update-dependencies
- run-code-sniffer:
@@ -0,0 +1,50 @@
#!/bin/bash -ex

# Jenkins test-js.sh hook implementation.
#
# Runs FunctionalJavascript tests.

if [ ! -f dependencies_updated ]
then
./update-dependencies.sh $1
fi

# This is the command used by the base image to serve Drupal. We redirect logs
# from stdout so they aren't intermingled with Behat's test output. The proper
# docker method for this would be to run Behat in a separate container, but
# this is tricky with Circle's docker executor.
# https://circleci.com/docs/2.0/executor-types/#machine-executor-overview
for i in /var/log/apache2/*.log
do
rm -v $i
touch $i
done
mkdir -p artifacts/logs
ln -v /var/log/apache2/*log artifacts/logs
apachectl start

# Wait for the mariadb container to come up.
while ! mysqladmin ping --silent -h127.0.0.1; do sleep 1; done

# Restore and update a previously installed Drupal site.
mv ../settings.php sites/default/
vendor/bin/drush sql-create -y
zcat ../drupal.sql.gz | vendor/bin/drush sqlc
vendor/bin/drush updatedb -y

cp modules/$1/phpunit.core.xml.dist core/phpunit.xml
set +e
vendor/bin/phpunit -c core --verbose --debug --group $1 --testsuite functional-javascript

if [ $? -gt 0 ]
then
echo 'FunctionalJavascript tests failed. The last 100 lines of the access log are:'
tail -n 100 /var/log/apache2/access.log
echo ''
echo 'The last 100 lines of the error log are:'
tail -n 100 /var/log/apache2/error.log
exit 1
fi

# Restore -e in case we add more later.
set -e
@@ -16,8 +16,8 @@
"require": {
"symfony/cache": "^3.4",
"highwire/drupal-psr-16": "^1.0",
"lullabot/mpx-php": "dev-fix-account",
"lullabot/drupal-symfony-lock": "dev-master",
"lullabot/mpx-php": "dev-fix-nextlist",
"lullabot/drupal-symfony-lock": "^1.0",
"symfony/property-info": "^3.4"
},
"require-dev": {
@@ -16,6 +16,9 @@ media_mpx.media_mpx_account.*:
account:
label: The URI of the account
type: uri
public_id:
label: The Public ID of the account
type: string

media_mpx.media_mpx_user.*:
type: config_entity
@@ -32,3 +35,25 @@ media_mpx.media_mpx_user.*:
label: 'Password'
uuid:
type: string

media.source.media_mpx_media:
type: media_mpx.account_aware
label: '"Media" media source configuration'

media_mpx.account_aware:
type: mapping
mapping:
source_field:
type: string
label: 'Source field'
account:
type: string
label: 'mpx Account entity ID'

field.formatter.settings.media_mpx_video:
type: mapping
label: 'mpx media rendered with a player'
mapping:
player:
type: uri
label: 'mpx Player'
@@ -6,6 +6,6 @@ services:
- { name: drush.command }
media_mpx.notification_queuer:
class: \Drupal\media_mpx\Commands\NotificationQueuer
arguments: ['@entity_type.manager', '@media_mpx.authenticated_client_factory', '@media_mpx.data_service_manager', '@queue', '@state']
arguments: ['@entity_type.manager', '@queue', '@media_mpx.notification_listener']
tags:
- { name: drush.command }
@@ -3,7 +3,6 @@ type: module
description: 'Provides thePlatform mpx integration.'
package: Media
core: 8.x
package: 'Media'
dependencies:
- drupal:media (>=8.5.0)
configure: entity.media_mpx_account.collection
@@ -26,3 +26,17 @@ function media_mpx_help($route_name, RouteMatchInterface $route_match) {

return NULL;
}

/**
* Implements hook_theme().
*/
function media_mpx_theme() {
return [
'media_mpx_iframe' => [
'variables' => [
'url' => '',
'attributes' => [],
],
],
];
}
@@ -21,6 +21,10 @@ services:
class: Drupal\media_mpx\DataObjectImporter
arguments: ['@keyvalue', '@entity_type.manager']

media_mpx.notification_listener:
class: Drupal\media_mpx\NotificationListener
arguments: ['@media_mpx.authenticated_client_factory', '@media_mpx.data_service_manager', '@state', '@logger.channel.media_mpx']

# We need to define our own handler stack instance separate from Drupal
# core's. Otherwise, when we add the mpx_errors handler, it gets applied to
# all HTTP requests, and not just those sent to mpx.
@@ -24,7 +24,7 @@
<!-- Do not limit the amount of memory tests take to run. -->
<ini name="memory_limit" value="-1"/>
<!-- Example SIMPLETEST_BASE_URL value: http://localhost -->
<env name="SIMPLETEST_BASE_URL" value=""/>
<env name="SIMPLETEST_BASE_URL" value="http://localhost"/>
<!-- Example SIMPLETEST_DB value: mysql://username:password@localhost/databasename#table_prefix -->
<env name="SIMPLETEST_DB" value=""/>
<!-- Example BROWSERTEST_OUTPUT_DIRECTORY value: /path/to/webroot/sites/simpletest/browser_output -->
@@ -33,6 +33,7 @@
<env name="SYMFONY_DEPRECATIONS_HELPER" value="weak_vendors"/>
<!-- Example for changing the driver class for mink tests MINK_DRIVER_CLASS value: 'Drupal\FunctionalJavascriptTests\DrupalSelenium2Driver' -->
<!-- Example for changing the driver args to mink tests MINK_DRIVER_ARGS value: '["http://127.0.0.1:8510"]' -->
<env name="MINK_DRIVER_ARGS_WEBDRIVER" value='["chrome", null, "http://localhost:4444/wd/hub"]'/>
<!-- Example for changing the driver args to phantomjs tests MINK_DRIVER_ARGS_PHANTOMJS value: '["http://127.0.0.1:8510"]' -->
<!-- Example for changing the driver args to webdriver tests MINK_DRIVER_ARGS_WEBDRIVER value: '["firefox", null, "http://localhost:4444/wd/hub"]' -->
</php>
@@ -2,19 +2,13 @@

namespace Drupal\media_mpx\Commands;

use Lullabot\Mpx\DataService\NotificationListener;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Queue\QueueFactory;
use Drupal\Core\State\StateInterface;
use Drupal\media\MediaSourceInterface;
use Drupal\media\MediaTypeInterface;
use Drupal\media_mpx\AuthenticatedClientFactory;
use Drupal\media_mpx\DataObjectImporter;
use Drupal\media_mpx\Notification;
use Drupal\media_mpx\Plugin\media\Source\MpxMediaSourceInterface;
use Drupal\media_mpx\NotificationListener;
use Drush\Commands\DrushCommands;
use GuzzleHttp\Exception\ConnectException;
use Lullabot\Mpx\DataService\DataServiceManager;
use Psr\Log\LoggerAwareTrait;

/**
@@ -28,20 +22,6 @@ class NotificationQueuer extends DrushCommands {
*/
const MEDIA_MPX_NOTIFICATION_QUEUE = 'media_mpx_notification';

/**
* The factory to load authenticated mpx clients.
*
* @var \Drupal\media_mpx\AuthenticatedClientFactory
*/
private $authenticatedClientFactory;

/**
* The manager to discover data service classes.
*
* @var \Lullabot\Mpx\DataService\DataServiceManager
*/
private $dataServiceManager;

/**
* The factory to load the mpx notification queue.
*
@@ -50,39 +30,33 @@ class NotificationQueuer extends DrushCommands {
private $queueFactory;

/**
* The state backend for notification IDs.
* The entity type manager interface.
*
* @var \Drupal\Core\State\StateInterface
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
private $state;
private $entityTypeManager;

/**
* The entity type manager interface.
* The Drupal mpx notification listener.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
* @var \Drupal\media_mpx\NotificationListener
*/
private $entityTypeManager;
private $listener;

/**
* NotificationQueuer constructor.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager interface.
* @param \Drupal\media_mpx\AuthenticatedClientFactory $authenticated_client_factory
* The factory to load authenticated mpx clients.
* @param \Lullabot\Mpx\DataService\DataServiceManager $data_service_manager
* The manager to discover data service classes.
* @param \Drupal\Core\Queue\QueueFactory $queue_factory
* The factory to load the mpx notification queue.
* @param \Drupal\Core\State\StateInterface $state
* The state backend for notification IDs.
* @param \Drupal\media_mpx\NotificationListener $listener
* The Drupal mpx notification listener.
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager, AuthenticatedClientFactory $authenticated_client_factory, DataServiceManager $data_service_manager, QueueFactory $queue_factory, StateInterface $state) {
public function __construct(EntityTypeManagerInterface $entity_type_manager, QueueFactory $queue_factory, NotificationListener $listener) {
$this->entityTypeManager = $entity_type_manager;
$this->authenticatedClientFactory = $authenticated_client_factory;
$this->dataServiceManager = $data_service_manager;
$this->queueFactory = $queue_factory;
$this->state = $state;
$this->listener = $listener;
}

/**
@@ -101,83 +75,23 @@ public function listen($media_type_id) {
// First, we find the last notification ID.
$media_type = $this->loadMediaType($media_type_id);
$media_source = DataObjectImporter::loadMediaSource($media_type);
$notification_id = $this->getNotificationId($media_source);
$notification_id = $this->listener->getNotificationId($media_source);

// Next, we fetch notifications, removing duplicates (such as multiple saves
// of an mpx object in a row).
$notifications = $this->fetchNotifications($media_source, $notification_id);
$this->io()->note(dt('Waiting for a notification from mpx after notification ID @id...', ['@id' => $notification_id]));
$notifications = $this->listener->listen($media_source, $notification_id);
$notifications = $this->filterDuplicateNotifications($notifications);

// Take the notifications and store them in the queue for processing later.
$this->queueNotifications($media_type, $notifications);

// Let the next listen call start from where we left off.
$notification_key = $media_source->getPluginId() . '_notification_id';
$this->state->set($notification_key, end($notifications)->getId());
$this->listener->setNotificationId($media_source, end($notifications));

$this->io()->progressFinish();
}

/**
* Return the current notification ID, or -1 if one is not set.
*
* @param \Drupal\media\MediaSourceInterface $media_source
* The media source the notification ID is for.
*
* @return int
* The notification ID.
*/
protected function getNotificationId(MediaSourceInterface $media_source): int {
// @todo should this really be state?
$state = \Drupal::state();
$notification_key = $media_source->getPluginId() . '_notification_id';
if (!$notification_id = $state->get($notification_key)) {
// @todo Should we throw a warning?
$notification_id = -1;
}

return $notification_id;
}

/**
* Fetch notifications from mpx.
*
* @param \Drupal\media_mpx\Plugin\media\Source\MpxMediaSourceInterface $media_source
* The media source notifications are being listened for.
* @param int $notification_id
* The last notification ID that was processed.
*
* @return \Lullabot\Mpx\DataService\Notification[]
* An array of notifications.
*/
private function fetchNotifications(MpxMediaSourceInterface $media_source, int $notification_id): array {
$account = $media_source->getAccount();

$client = $this->authenticatedClientFactory->fromUser($account->getUserEntity());
$definition = $media_source->getPluginDefinition()['media_mpx'];
$service = $this->dataServiceManager->getDataService($definition['service_name'], $definition['object_type'], $definition['schema_version']);
// @todo Client ID needs to be configured somehow.
$listener = new NotificationListener($client, $service, 'drush-drupal8-mpx');

$promise = $listener->listen($notification_id);
$this->io()->note(dt('Waiting for a notification from mpx after notification ID @id...', ['@id' => $notification_id]));
try {
return $promise->wait();
}
catch (ConnectException $e) {
// This may be a timeout if no notifications are available. However, there
// is no good method from the exception to determine if a timeout
// occurred.
if (strpos($e->getMessage(), 'cURL error 28') !== FALSE) {
$this->logger()->info('A timeout occurred while waiting for notifications. This is expected when no content is changing in mpx. No action is required.');
return [];
}

// Some other connection exception occurred, so throw that up.
throw $e;
}
}

/**
* Remove multiple notifications for the same ID.
*
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.