diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..eb6c183 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,81 @@ +language: php +cache: + bundler: true + directories: + - $HOME/tmp/drush + - $HOME/.bundle + apt: true + +php: + - 5.4 + - 5.5 + - 5.6 + +mysql: + database: drupal + username: root + encoding: utf8 + +install: + - "mysql -e 'create database drupal;'" + + # Install latest Drush 7. + - export PATH="$HOME/.composer/vendor/bin:$PATH" + - composer self-update + - composer global require --no-interaction --prefer-source drush/drush:dev-master + + # Make sure we don't fail when checking out projects + - echo -e "Host github.com\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config + + # LAMP package installation (mysql is already started) + - sudo apt-get update + - sudo apt-get install apache2 libapache2-mod-fastcgi + + # enable php-fpm, travis does not support any other method with php and apache + - sudo cp ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.conf.default ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.conf + - sudo a2enmod rewrite actions fastcgi alias + - echo "cgi.fix_pathinfo = 1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini + - ~/.phpenv/versions/$(phpenv version-name)/sbin/php-fpm + + # Make sure the apache root is in our wanted directory + - echo "$(curl -fsSL https://gist.githubusercontent.com/nickveenhof/11386315/raw/b8abaf9304fe12b5cc7752d39c29c1edae8ac2e6/gistfile1.txt)" | sed -e "s,PATH,$TRAVIS_BUILD_DIR/../drupal,g" | sudo tee /etc/apache2/sites-available/default > /dev/null + + # Disable sendmail. + - echo sendmail_path=`which true` >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini + + # Forward the errors to the syslog so we can print them + - echo "error_log=syslog" >> `php --ini | grep "Loaded Configuration" | awk '{print $4}'` + + # Build Codebase. + - TESTDIR=$(pwd) + - cd .. + - git clone --branch 8.0.x --depth 1 http://git.drupal.org/project/drupal.git drupal + - cd drupal + - wget https://www.drupal.org/files/issues/2189345_0.patch + - git apply -v -p1 < 2189345_0.patch + + # Restart apache and test it + - sudo service apache2 restart + - curl -v "http://localhost" + +before_script: + - ln -s $TESTDIR modules/commerce + # Mysql might time out for long tests, increase the wait timeout. + - mysql -e 'SET @@GLOBAL.wait_timeout=1200' + # Update drupal core + - git pull origin 8.0.x + - drush si --db-url=mysql://root:@127.0.0.1/drupal --account-name=admin --account-pass=admin --site-mail=admin@example.com --site-name="Commerce" --yes + - drush en -y simpletest profile + +script: + # Run the tests + - php core/scripts/run-tests.sh --verbose --color --concurrency 4 --php `which php` --url http://localhost "profile" | tee /tmp/test.txt; TEST_EXIT=${PIPESTATUS[0]}; echo $TEST_EXIT + # Check if we had fails in the run-tests.sh script + # Exit with the inverted value, because if there are no fails found, it will exit with 1 and for us that\ + # is a good thing so invert it to 0. Travis has some issues with the exclamation mark in front so we have to fiddle a + # bit. + # Also make the grep case insensitive and fail on run-tests.sh regular fails as well on fatal errors. + - TEST_OUTPUT=$(! egrep -i "([0-9]+ fails)|(PHP Fatal error)|([0-9]+ exceptions)" /tmp/test.txt > /dev/null)$? + - echo $TEST_OUTPUT + - php -i | grep 'php.ini' + - sudo cat /var/log/apache2/error.log \ No newline at end of file diff --git a/profile.api.php b/profile.api.php index 252ddf5..32bde66 100644 --- a/profile.api.php +++ b/profile.api.php @@ -35,11 +35,11 @@ */ function hook_profile_access($op, Drupal\profile\Entity\Profile $profile, Drupal\user\Entity\User $account) { // Explicitly deny access for a 'secret' profile type. - if ($profile->type == 'secret' && !user_access('custom permission')) { + if ($profile->type == 'secret' && !\Drupal::currentUser()->hasPermission('custom permission')) { return FALSE; } // For profiles other than the default profile grant access. - if ($profile->type != 'main' && user_access('custom permission')) { + if ($profile->type != 'main' && \Drupal::currentUser()->hasPermission('custom permission')) { return TRUE; } // In other cases do not alter access. diff --git a/src/Access/ProfileAccessCheck.php b/src/Access/ProfileAccessCheck.php index 7ee1cec..5900ab9 100644 --- a/src/Access/ProfileAccessCheck.php +++ b/src/Access/ProfileAccessCheck.php @@ -12,7 +12,7 @@ use Drupal\Core\Session\AccountInterface; use Drupal\Core\Language\LanguageInterface; use Symfony\Component\Routing\Route; -use Symfony\Component\HttpFoundation\Request; + use Drupal\profile\ProfileTypeInterface; use Symfony\Component\HttpFoundation\RequestStack; diff --git a/src/Form/DeleteMultiple.php b/src/Form/DeleteMultiple.php index 9ed6a2c..7cbb3ff 100644 --- a/src/Form/DeleteMultiple.php +++ b/src/Form/DeleteMultiple.php @@ -12,7 +12,7 @@ use Drupal\Core\Url; use Drupal\Component\Utility\String; use Drupal\Core\Form\FormStateInterface; -use Drupal\user\TempStoreFactory; +use Drupal\user\PrivateTempStoreFactory; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -29,11 +29,11 @@ class DeleteMultiple extends ConfirmFormBase { protected $profiles = array(); /** - * The tempstore factory. + * The private_tempstore factory. * - * @var \Drupal\user\TempStoreFactory + * @var \Drupal\user\PrivateTempStoreFactory */ - protected $tempStoreFactory; + protected $privateTempStoreFactory; /** * The node storage. @@ -45,13 +45,13 @@ class DeleteMultiple extends ConfirmFormBase { /** * Constructs a DeleteMultiple form object. * - * @param \Drupal\user\TempStoreFactory $temp_store_factory - * The tempstore factory. + * @param \Drupal\user\PrivateTempStoreFactory $temp_store_factory + * The private tempstore factory. * @param \Drupal\Core\Entity\EntityManagerInterface $manager * The entity manager. */ - public function __construct(TempStoreFactory $temp_store_factory, EntityManagerInterface $manager) { - $this->tempStoreFactory = $temp_store_factory; + public function __construct(PrivateTempStoreFactory $privateTempStoreFactory, EntityManagerInterface $manager) { + $this->privateTempStoreFactory = $privateTempStoreFactory; $this->storage = $manager->getStorage('profile'); } @@ -60,7 +60,7 @@ public function __construct(TempStoreFactory $temp_store_factory, EntityManagerI */ public static function create(ContainerInterface $container) { return new static( - $container->get('user.tempstore'), + $container->get('user.private_tempstore'), $container->get('entity.manager') ); } @@ -76,7 +76,7 @@ public function getFormId() { * {@inheritdoc} */ public function getQuestion() { - return format_plural(count($this->profiles), 'Are you sure you want to delete this profile?', 'Are you sure you want to delete these profiles?'); + return \Drupal::translation()->formatPlural(count($this->profiles), 'Are you sure you want to delete this profile?', 'Are you sure you want to delete these profiles?'); } /** @@ -99,7 +99,7 @@ public function getConfirmText() { public function buildForm(array $form, FormStateInterface $form_state) { $this->profiles = $this->tempStoreFactory->get('profile_multiple_delete_confirm')->get(\Drupal::currentUser()->id()); if (empty($this->profiles)) { - return new RedirectResponse(url('admin/config/people/profiles', array('absolute' => TRUE))); + return new RedirectResponse(\Drupal::url('admin/config/people/profiles', array('absolute' => TRUE))); } $form['profiles'] = array( @@ -122,7 +122,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) { $this->tempStoreFactory->get('profile_multiple_delete_confirm')->delete(\Drupal::currentUser()->id()); $count = count($this->profiles); $this->logger('content')->notice('Deleted @count profiles.', array('@count' => $count)); - drupal_set_message(format_plural($count, 'Deleted 1 profile.', 'Deleted @count profiles.')); + drupal_set_message(\Drupal::translation()->formatPlural($count, 'Deleted 1 profile.', 'Deleted @count profiles.')); } $form_state->setRedirect('profile.overview_profiles'); } diff --git a/src/Form/ProfileTypeDeleteForm.php b/src/Form/ProfileTypeDeleteForm.php index 58ed706..58f1ada 100644 --- a/src/Form/ProfileTypeDeleteForm.php +++ b/src/Form/ProfileTypeDeleteForm.php @@ -9,6 +9,7 @@ use Drupal\Core\Entity\EntityConfirmFormBase; use Drupal\Core\Database\Connection; +use Drupal\Core\Logger\RfcLogLevel; use Symfony\Component\DependencyInjection\ContainerInterface; use Drupal\Core\Url; use Drupal\Core\Form\FormStateInterface; @@ -90,7 +91,7 @@ public function submit(array $form, FormStateInterface $form_state) { \Drupal::service('logger.factory') ->get('profile') - ->log(WATCHDOG_NOTICE, 'Profile type %label has been deleted.', array('@type' => $this->entity->label())); + ->log(RfcLogLevel::NOTICE, 'Profile type %label has been deleted.', array('@type' => $this->entity->label())); drupal_set_message(t('Profile type %label has been deleted.', array('%label' => $this->entity->label()))); diff --git a/src/Plugin/Action/DeleteProfile.php b/src/Plugin/Action/DeleteProfile.php index ddd5552..cc78a97 100644 --- a/src/Plugin/Action/DeleteProfile.php +++ b/src/Plugin/Action/DeleteProfile.php @@ -10,7 +10,7 @@ use Drupal\Core\Action\ActionBase; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Session\AccountInterface; -use Drupal\user\TempStoreFactory; +use Drupal\user\PrivateTempStoreFactory; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -28,9 +28,9 @@ class DeleteProfile extends ActionBase implements ContainerFactoryPluginInterfac /** * The tempstore object. * - * @var \Drupal\user\TempStore + * @var \Drupal\user\PrivateTempStore */ - protected $tempStore; + protected $privateTempStore; /** * Constructs a new DeleteNode object. @@ -41,27 +41,27 @@ class DeleteProfile extends ActionBase implements ContainerFactoryPluginInterfac * The plugin ID for the plugin instance. * @param mixed $plugin_definition * The plugin implementation definition. - * @param \Drupal\user\TempStoreFactory $temp_store_factory + * @param \Drupal\user\PrivateTempStoreFactory $privateTempStoreFactory * The tempstore factory. */ - public function __construct(array $configuration, $plugin_id, $plugin_definition, TempStoreFactory $temp_store_factory) { + public function __construct(array $configuration, $plugin_id, $plugin_definition, PrivateTempStoreFactory $privateTempStoreFactory) { parent::__construct($configuration, $plugin_id, $plugin_definition); - $this->tempStore = $temp_store_factory->get('profile_multiple_delete_confirm'); + $this->privateTempStore = $privateTempStoreFactory->get('profile_multiple_delete_confirm'); } /** * {@inheritdoc} */ public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { - return new static($configuration, $plugin_id, $plugin_definition, $container->get('user.tempstore')); + return new static($configuration, $plugin_id, $plugin_definition, $container->get('user.private_tempstore')); } /** * {@inheritdoc} */ public function executeMultiple(array $entities) { - $this->tempStore->set(\Drupal::currentUser()->id(), $entities); + $this->privateTempStore->set(\Drupal::currentUser()->id(), $entities); } /** diff --git a/src/Plugin/Derivative/ProfileAddLocalTask.php b/src/Plugin/Derivative/ProfileAddLocalTask.php index b492422..0274084 100644 --- a/src/Plugin/Derivative/ProfileAddLocalTask.php +++ b/src/Plugin/Derivative/ProfileAddLocalTask.php @@ -9,18 +9,17 @@ use Drupal\Component\Plugin\Derivative\DeriverBase; use Drupal\Component\Utility\Unicode; -use Drupal\field\FieldInstanceConfigInterface; +use Drupal\field\FieldConfigInterface; use Drupal\user\UserInterface; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface; use Symfony\Component\DependencyInjection\ContainerInterface; -use Drupal\Core\Cache\Cache; + use Drupal\Core\PhpStorage\PhpStorageFactory; -use Symfony\Component\HttpFoundation\Request; /** * Provides dynamic routes to add profiles. @@ -82,7 +81,7 @@ public function getDerivativeDefinitions($base_plugin_definition) { $configs = array(); foreach ($this->config as $config) { $instances = array_filter($this->entityManager->getFieldDefinitions('profile', $config->get('id')), function ($field_definition) { - return $field_definition instanceof FieldInstanceConfigInterface; + return $field_definition instanceof FieldConfigInterface; }); $display = FALSE; diff --git a/src/Plugin/views/field/LinkDelete.php b/src/Plugin/views/field/LinkDelete.php index 82664da..0eb0b98 100644 --- a/src/Plugin/views/field/LinkDelete.php +++ b/src/Plugin/views/field/LinkDelete.php @@ -7,7 +7,7 @@ namespace Drupal\profile\Plugin\views\field; -use Drupal\profile\Plugin\views\field\Link; + use Drupal\views\ResultRow; /** diff --git a/src/Plugin/views/field/LinkEdit.php b/src/Plugin/views/field/LinkEdit.php index 9b57565..7c712ba 100644 --- a/src/Plugin/views/field/LinkEdit.php +++ b/src/Plugin/views/field/LinkEdit.php @@ -7,7 +7,7 @@ namespace Drupal\profile\Plugin\views\field; -use Drupal\profile\Plugin\views\field\Link; + use Drupal\views\ResultRow; /** diff --git a/src/Plugin/views/field/ProfileBulkForm.php b/src/Plugin/views/field/ProfileBulkForm.php index 8363dfa..bb1bc67 100644 --- a/src/Plugin/views/field/ProfileBulkForm.php +++ b/src/Plugin/views/field/ProfileBulkForm.php @@ -7,7 +7,7 @@ namespace Drupal\profile\Plugin\views\field; -use Drupal\Core\Entity\EntityManagerInterface; + use Drupal\system\Plugin\views\field\BulkForm; /** diff --git a/src/ProfileAccessControlHandler.php b/src/ProfileAccessControlHandler.php index 6fe46c3..e63d88b 100644 --- a/src/ProfileAccessControlHandler.php +++ b/src/ProfileAccessControlHandler.php @@ -10,8 +10,8 @@ use Drupal\Core\Access\AccessResult; use Drupal\Core\Entity\EntityHandlerInterface; use Drupal\Core\Entity\EntityTypeInterface; -use Drupal\Core\Field\FieldDefinitionInterface; -use Drupal\Core\Field\FieldItemListInterface; + + use Drupal\Core\Language\LanguageInterface; use Drupal\Core\Entity\EntityAccessControlHandler; use Drupal\Core\Entity\EntityInterface; diff --git a/src/ProfileInterface.php b/src/ProfileInterface.php index 8bf0066..2f68d32 100644 --- a/src/ProfileInterface.php +++ b/src/ProfileInterface.php @@ -10,7 +10,7 @@ use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Entity\EntityChangedInterface; use Drupal\user\EntityOwnerInterface; -use Drupal\user\UserInterface; + /** * Provides an interface defining a profile entity. diff --git a/src/ProfileTypeListBuilder.php b/src/ProfileTypeListBuilder.php index cdb395b..5b7cb23 100644 --- a/src/ProfileTypeListBuilder.php +++ b/src/ProfileTypeListBuilder.php @@ -44,15 +44,17 @@ public function getOperations(EntityInterface $entity) { // which have the weights 15, 20, 25. if (isset($operations['edit'])) { $operations['edit'] = array( - 'title' => t('Edit'), - 'weight' => 30, - ) + $entity->urlInfo('edit-form')->toArray(); + 'title' => t('Edit'), + 'weight' => 30, + 'url' => $entity->urlInfo('edit-form') + ); } if (isset($operations['delete'])) { $operations['delete'] = array( 'title' => t('Delete'), 'weight' => 35, - ) + $entity->urlInfo('delete-form')->toArray(); + 'url' => $entity->urlInfo('delete-form') + ); } // Sort the operations to normalize link order. uasort($operations, array( diff --git a/src/Tests/ProfileAccessTest.php b/src/Tests/ProfileAccessTest.php index 14272ee..384422b 100644 --- a/src/Tests/ProfileAccessTest.php +++ b/src/Tests/ProfileAccessTest.php @@ -7,9 +7,9 @@ namespace Drupal\profile\Tests; -use Drupal\simpletest\WebTestBase; -use Drupal\field\Entity\FieldStorageConfig; use Drupal\field\Entity\FieldConfig; +use Drupal\field\Entity\FieldStorageConfig; +use Drupal\simpletest\WebTestBase; /** * Tests profile access handling. @@ -20,6 +20,10 @@ class ProfileAccessTest extends WebTestBase { public static $modules = array('profile', 'text'); + private $type; + private $field; + private $admin_user; + function setUp() { parent::setUp(); @@ -40,29 +44,36 @@ function setUp() { $this->field = FieldStorageConfig::create($this->field); $this->field->save(); - $this->instance = array( - 'entity_type' => $this->field->entity_type, - 'field_name' => $this->field->field_name, + $instance = array( + 'entity_type' => $this->field->get('entity_type'), + 'field_name' => $this->field->get('field_name'), 'bundle' => $this->type->id(), 'label' => 'Full name', 'widget' => array( 'type' => 'text_textfield', ), ); - $this->instance = FieldConfig::create($this->instance); - $this->instance->save(); + $instance = FieldConfig::create($instance); + $instance->save(); - $this->display = entity_get_display('profile', 'test', 'default') - ->setComponent($this->field->field_name, array( + $display = entity_get_display('profile', 'test', 'default') + ->setComponent($this->field->get('field_name'), array( 'type' => 'text_default', )); - $this->display->save(); + $display->save(); - $this->form = entity_get_form_display('profile', 'test', 'default') - ->setComponent($this->field->field_name, array( + + entity_get_display('profile', 'test', 'default') + ->setComponent($this->field->get('field_name'), array( + 'type' => 'text_default', + )) + ->save(); + + entity_get_form_display('profile', 'test', 'default') + ->setComponent($this->field->get('field_name'), array( 'type' => 'string_textfield', - )); - $this->form->save(); + )) + ->save(); $this->checkPermissions(array(), TRUE); @@ -81,7 +92,7 @@ function setUp() { */ function testAdminOnlyProfiles() { $id = $this->type->id(); - $field_name = $this->field->field_name; + $field_name = $this->field->get('field_name'); // Create a test user account. $web_user = $this->drupalCreateUser(array('access user profiles')); diff --git a/src/Tests/ProfileAttachTest.php b/src/Tests/ProfileAttachTest.php index c1a9f9d..f828f82 100644 --- a/src/Tests/ProfileAttachTest.php +++ b/src/Tests/ProfileAttachTest.php @@ -20,31 +20,43 @@ class ProfileAttachTest extends WebTestBase { public static $modules = array('profile', 'text'); + /** + * The entity type to test against + */ + protected $profile_type; + + /** + * The entity type to test against + */ + protected $profile_field; + + protected $instance; + function setUp() { parent::setUp(); - $this->type = entity_create('profile_type', array( + $this->profile_type = entity_create('profile_type', array( 'id' => 'test', 'label' => 'Test profile', 'weight' => 0, 'registration' => TRUE, )); - $this->type->save(); + $this->profile_type->save(); - $this->field = array( + $this->profile_field = array( 'field_name' => 'profile_fullname', 'type' => 'text', 'entity_type' => 'profile', 'cardinality' => 1, 'translatable' => FALSE, ); - $this->field = FieldStorageConfig::create($this->field); - $this->field->save(); + $this->profile_field = FieldStorageConfig::create($this->profile_field); + $this->profile_field->save(); $this->instance = array( - 'entity_type' => $this->field->entity_type, - 'field_name' => $this->field->field_name, - 'bundle' => $this->type->id(), + 'entity_type' => $this->profile_field->get('entity_type'), + 'field_name' => $this->profile_field->get('field_name'), + 'bundle' => $this->profile_type->id(), 'label' => 'Full name', 'required' => TRUE, 'widget' => array( @@ -54,18 +66,17 @@ function setUp() { $this->instance = FieldConfig::create($this->instance); $this->instance->save(); - $this->display = entity_get_display('profile', 'test', 'default') - ->setComponent($this->field->field_name, array( + $display = entity_get_display('profile', 'test', 'default') + ->setComponent($this->profile_field->get('field_name'), array( 'type' => 'text_default', )); - $this->display->save(); + $display->save(); - $this->form = entity_get_form_display('profile', 'test', 'default') - ->setComponent($this->field->field_name, array( + $form = entity_get_form_display('profile', 'test', 'default') + ->setComponent($this->profile_field->get('field_name'), array( 'type' => 'string_textfield', )); - $this->form->save(); - + $form->save(); $this->checkPermissions(array(), TRUE); } @@ -73,15 +84,17 @@ function setUp() { * Test user registration integration. */ function testUserRegisterForm() { - $id = $this->type->id(); - $field_name = $this->field->field_name; - - // Allow registration without administrative approval and log in user - // directly after registering. - \Drupal::config('user.settings') + $id = $this->profile_type->id(); + $field_name = $this->profile_field->get('field_name'); + + $config = $this->config('user.settings'); + // Don't require email verification and allow registration by site visitors + // without administrator approval. + $config + ->set('verify_mail', FALSE) ->set('register', USER_REGISTER_VISITORS) - ->set('verify_mail', 0) ->save(); + user_role_grant_permissions(DRUPAL_AUTHENTICATED_RID, array('view own test profile')); // Verify that the additional profile field is attached and required. @@ -107,7 +120,7 @@ function testUserRegisterForm() { // Verify that a new profile was created for the new user ID. $profiles = entity_load_multiple_by_properties('profile', array( 'uid' => $new_user->id(), - 'type' => $this->type->id(), + 'type' => $this->profile_type->id(), )); $profile = reset($profiles); $this->assertEqual($profile->get($field_name)->value, $edit["entity_" . $id . "[$field_name][0][value]"], 'Field value found in loaded profile.'); diff --git a/src/Tests/ProfileFieldAccessTest.php b/src/Tests/ProfileFieldAccessTest.php index ad2fc16..53173f0 100644 --- a/src/Tests/ProfileFieldAccessTest.php +++ b/src/Tests/ProfileFieldAccessTest.php @@ -18,6 +18,11 @@ class ProfileFieldAccessTest extends WebTestBase { public static $modules = array('profile', 'text', 'field_ui'); + private $type; + private $admin_user; + private $web_user; + private $other_user; + function setUp() { parent::setUp(); @@ -67,7 +72,6 @@ function testPrivateField() { 'field[settings][profile_private]' => 1, ); $this->drupalPostForm(NULL, $edit, t('Save field settings')); - $this->drupalPostForm(NULL, array(), t('Save settings')); // Fill in a field value.