summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSergii Bondarenko2015-10-24 15:23:18 (GMT)
committerSergii Bondarenko2015-10-24 15:23:18 (GMT)
commita75535aa4c3e6dc1ab1596ebb33871b6cdce683b (patch)
treed4f498e1ff55526a9d228fac65b52a1eb0c38f38
First version of a module7.x-1.0
-rw-r--r--README.md23
-rw-r--r--environment_fieldaccess.configure.inc14
-rw-r--r--environment_fieldaccess.grant.inc17
-rw-r--r--environment_fieldaccess.info13
-rw-r--r--environment_fieldaccess.module78
-rw-r--r--help/fieldaccess.pngbin0 -> 165357 bytes
-rw-r--r--tests/environment_fieldaccess.fields.inc129
-rw-r--r--tests/environment_fieldaccess.test155
-rw-r--r--tests/environment_fieldaccess_test/environment_fieldaccess_test.info7
-rw-r--r--tests/environment_fieldaccess_test/environment_fieldaccess_test.module24
10 files changed, 460 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..fa4bfee
--- /dev/null
+++ b/README.md
@@ -0,0 +1,23 @@
+# Environment Field Access
+
+Restrict an access to fields depending on environment.
+
+## Usage
+
+Create an environment via `hook_environment()`, go to editing of any existing
+field and configure an access in `Field Access` settings group.
+
+![Field Access settings](help/fieldaccess.png)
+
+## Dependencies
+
+- [Environment](https://www.drupal.org/project/environment)
+- [Field Access](https://www.drupal.org/project/fieldaccess)
+
+## Testing
+
+```shell
+drush dl simpletest
+drush en simpletest -y
+drush test-run EnvironmentFieldAccessTestCase
+```
diff --git a/environment_fieldaccess.configure.inc b/environment_fieldaccess.configure.inc
new file mode 100644
index 0000000..bb12ea5
--- /dev/null
+++ b/environment_fieldaccess.configure.inc
@@ -0,0 +1,14 @@
+<?php
+/**
+ * @file
+ * Configure access arguments.
+ */
+
+/**
+ * Configure access arguments.
+ *
+ * @see callback_fieldaccess_configure()
+ */
+function environment_fieldaccess_configure(array $settings, array &$form, array &$form_state) {
+ return _environment_fieldaccess_settings($settings);
+}
diff --git a/environment_fieldaccess.grant.inc b/environment_fieldaccess.grant.inc
new file mode 100644
index 0000000..20fc157
--- /dev/null
+++ b/environment_fieldaccess.grant.inc
@@ -0,0 +1,17 @@
+<?php
+/**
+ * @file
+ * Check an access.
+ */
+
+/**
+ * Check an access.
+ *
+ * @see callback_fieldaccess_grant()
+ */
+function environment_fieldaccess_grant(array $settings, \stdClass $object, \stdClass $account, array $context) {
+ $settings = _environment_fieldaccess_settings($settings, TRUE);
+ $state = array_key_exists(environment_current(), $settings['environment']);
+
+ return $settings['not'] ? !$state : $state;
+}
diff --git a/environment_fieldaccess.info b/environment_fieldaccess.info
new file mode 100644
index 0000000..bd4cd9a
--- /dev/null
+++ b/environment_fieldaccess.info
@@ -0,0 +1,13 @@
+name = Environment Field Access
+description = Control access of fields depending on configured environment.
+package = Field Access
+core = 7.x
+php = 5.4
+
+testing_api = 2.x
+
+files[] = tests/environment_fieldaccess.test
+files[] = tests/environment_fieldaccess.fields.inc
+
+dependencies[] = environment
+dependencies[] = fieldaccess
diff --git a/environment_fieldaccess.module b/environment_fieldaccess.module
new file mode 100644
index 0000000..ab9c367
--- /dev/null
+++ b/environment_fieldaccess.module
@@ -0,0 +1,78 @@
+<?php
+/**
+ * @file
+ * Environment Field Access.
+ */
+
+/**
+ * Implements hook_fieldaccess_info().
+ */
+function environment_fieldaccess_fieldaccess_info() {
+ $label = t('Access field depending on environment');
+ $info = [];
+
+ foreach (['edit', 'view'] as $type) {
+ $data = [
+ 'type' => $type,
+ 'label' => $label,
+ ];
+
+ foreach (['configure', 'grant'] as $func) {
+ $data += [
+ "{$func}" => "environment_fieldaccess_$func",
+ "{$func}_file" => "environment_fieldaccess.$func.inc",
+ ];
+ }
+
+ $info["environment_fieldaccess_$type"] = $data;
+ }
+
+ return $info;
+}
+
+/**
+ * Get instance of current site.
+ *
+ * @param array $settings
+ * Configured settings.
+ * @param bool $get
+ * Get values.
+ *
+ * @return array
+ * Form definition or, if second argument is TRUE - configured values.
+ */
+function _environment_fieldaccess_settings(array $settings, $get = FALSE) {
+ $environments = $elements = $values = [];
+
+ if (!$get) {
+ foreach (environment_load() as $environment => $definition) {
+ $environments[$environment] = $definition['label'];
+ }
+ }
+
+ $elements['environment'] = [
+ '#type' => 'select',
+ '#title' => t('Allow access for selected environments'),
+ '#options' => $environments,
+ '#multiple' => TRUE,
+ '#default_value' => '',
+ ];
+
+ $elements['not'] = [
+ '#type' => 'checkbox',
+ '#title' => t('Reverse (NOT)'),
+ '#default_value' => 0,
+ ];
+
+ foreach ($elements as $element => &$definition) {
+ // Updated default value from settings.
+ if (isset($settings[$element])) {
+ $definition['#default_value'] = $settings[$element];
+ }
+
+ // Collect form values.
+ $values[$element] = isset($definition['#default_value']) ? $definition['#default_value'] : NULL;
+ }
+
+ return $get ? $values : $elements;
+}
diff --git a/help/fieldaccess.png b/help/fieldaccess.png
new file mode 100644
index 0000000..d11c0aa
--- /dev/null
+++ b/help/fieldaccess.png
Binary files differ
diff --git a/tests/environment_fieldaccess.fields.inc b/tests/environment_fieldaccess.fields.inc
new file mode 100644
index 0000000..cdfa619
--- /dev/null
+++ b/tests/environment_fieldaccess.fields.inc
@@ -0,0 +1,129 @@
+<?php
+/**
+ * @file
+ * Environment Field Access (Fields Helper).
+ */
+
+/**
+ * Class EnvironmentFieldAccessFields.
+ */
+class EnvironmentFieldAccessFields {
+
+ private $fields = [];
+ private $instances = [];
+
+ /**
+ * Set field definitions.
+ *
+ * @param array[] $fields
+ * An associative array where keys - field names and values - definition.
+ */
+ public function __construct(array $fields) {
+ $this->fields = $fields;
+ }
+
+ /**
+ * Create fields.
+ *
+ * @throws \FieldException
+ * When cannot create a field.
+ */
+ public function create() {
+ foreach ($this->fields as $name => $data) {
+ if (!db_table_exists("field_data_$name")) {
+ field_create_field($data + [
+ 'default' => '',
+ 'not null' => TRUE,
+ 'field_name' => $name,
+ ]);
+ }
+ }
+ }
+
+ /**
+ * Completely delete fields.
+ *
+ * This function deletes tables: "field_data_NAME" and "field_revision_NAME"
+ * and entries in "field_config" and "field_config_instances".
+ */
+ public function delete() {
+ foreach (array_keys($this->fields) as $name) {
+ // Delete tables.
+ foreach (['data', 'revision'] as $table_type) {
+ $table = "field_{$table_type}_{$name}";
+
+ if (db_table_exists($table)) {
+ db_drop_table($table);
+ }
+ }
+
+ // Delete entries.
+ foreach (['config', 'config_instance'] as $table_type) {
+ db_delete("field_$table_type")
+ ->condition('field_name', $name)
+ ->execute();
+ }
+ }
+ }
+
+ /**
+ * Attach existing fields into entity.
+ *
+ * @param string $entity_type
+ * Entity machine name.
+ * @param string $bundle_name
+ * Entity bundle name.
+ *
+ * @throws \FieldException
+ * When instance cannot be created.
+ */
+ public function attach($entity_type, $bundle_name) {
+ $attached_fields = field_info_instances($entity_type, $bundle_name);
+
+ foreach ($this->fields as $field_name => $data) {
+ if (empty($attached_fields[$field_name]) && field_info_field($field_name)) {
+ field_create_instance($data + [
+ 'bundle' => $bundle_name,
+ 'field_name' => $field_name,
+ 'entity_type' => $entity_type,
+ ]);
+ }
+ }
+ }
+
+ /**
+ * Get field instances.
+ *
+ * @return array[]
+ * Field instances.
+ */
+ public function &getInstances() {
+ if (empty($this->instances)) {
+ $query = db_select('field_config_instance', 'fci')
+ ->fields('fci', ['field_name', 'data'])
+ ->condition('field_name', array_keys($this->fields))
+ ->execute()
+ ->fetchAllKeyed();
+
+ $this->instances = array_map('unserialize', $query);
+ }
+
+ return $this->instances;
+ }
+
+ /**
+ * Save field instances.
+ *
+ * @throws \Exception
+ * @throws \InvalidMergeQueryException
+ */
+ public function saveInstances() {
+ foreach ($this->instances as $field_name => $data) {
+ db_merge('field_config_instance')
+ ->fields(['data' => serialize($data)])
+ ->condition('field_name', $field_name)
+ ->execute();
+ }
+ }
+
+}
diff --git a/tests/environment_fieldaccess.test b/tests/environment_fieldaccess.test
new file mode 100644
index 0000000..98ff511
--- /dev/null
+++ b/tests/environment_fieldaccess.test
@@ -0,0 +1,155 @@
+<?php
+/**
+ * @file
+ * Environment Field Access (Test).
+ */
+
+/**
+ * Class EnvironmentFieldAccessTestCase.
+ */
+class EnvironmentFieldAccessTestCase extends \DrupalWebTestCase {
+
+ /**
+ * Name of module for testing. Also used as field name.
+ */
+ const TEST_MODULE = 'environment_fieldaccess_test';
+
+ /**
+ * @var \EnvironmentFieldAccessFields
+ */
+ private $fieldsManager;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function __construct($test_id = NULL) {
+ // Prevent wrong execution.
+ if (strpos($GLOBALS['base_url'], 'default') !== FALSE) {
+ throw new \RuntimeException('Test cannot be run from CLI if $base_url variable not set.');
+ }
+
+ parent::__construct($test_id);
+
+ $fieldaccess = [];
+
+ foreach (environment_fieldaccess_fieldaccess_info() as $name => $info) {
+ $fieldaccess[$info['type']] = [
+ 'access_name' => $name,
+ 'individual' => 0,
+ 'settings' => [
+ 'not' => 0,
+ 'environment' => [
+ 'test_show' => 'test_show',
+ ],
+ ],
+ ];
+ }
+
+ $this->fieldsManager = new \EnvironmentFieldAccessFields([
+ self::TEST_MODULE => [
+ 'type' => 'text',
+ 'label' => self::TEST_MODULE,
+ 'settings' => [
+ 'fieldaccess' => $fieldaccess,
+ 'user_register_form' => TRUE,
+ ],
+ ],
+ ]);
+ }
+
+ /**
+ * Delete created fields.
+ */
+ public function __destruct() {
+ $this->fieldsManager->delete();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function getInfo() {
+ return [
+ 'name' => 'Environment Field Access',
+ 'group' => 'Field API',
+ 'description' => 'Testing field access depending on environment.',
+ ];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setUp() {
+ // Enable modules.
+ parent::setUp(self::TEST_MODULE);
+ // Create fields for testing.
+ $this->fieldsManager->create();
+ // Attach field to "user" entity.
+ $this->fieldsManager->attach('user', 'user');
+ }
+
+ /**
+ * Access allowed in current environment.
+ */
+ public function testAccessAllowed() {
+ // Set an environment to "test_show", go to "user/register" and
+ // try to find the field on a page.
+ $this->assertEnvironment('test_show');
+ $this->assertFieldByXPath($this->fieldXpath());
+ }
+
+ /**
+ * Access disallowed in another environment.
+ */
+ public function testAccessDisallowed() {
+ // Set an environment to "test_hide", go to "user/register" and
+ // make sure that field does not exist on a page.
+ $this->assertEnvironment('test_hide');
+ $this->assertNoFieldByXPath($this->fieldXpath());
+ }
+
+ /**
+ * Access disallowed in current environment ("not" option selected).
+ */
+ public function testNotAccessAllowed() {
+ // Set an environment to "test_show", go to "user/register" and
+ // make sure that field does not exist on a page, because "not"
+ // option is selected.
+ $instances =& $this->fieldsManager->getInstances();
+
+ foreach ($instances[self::TEST_MODULE]['settings']['fieldaccess'] as $type => &$info) {
+ $info['settings']['not'] = 1;
+ }
+
+ $this->fieldsManager->saveInstances();
+
+ $this->assertEnvironment('test_show');
+ $this->assertNoFieldByXPath($this->fieldXpath());
+ }
+
+ /**
+ * Switch the environment.
+ *
+ * @param string $environment
+ * Environment name.
+ */
+ private function assertEnvironment($environment) {
+ $this->assertTrue(environment_switch($environment));
+ $this->assertTrue(environment_current() === $environment);
+
+ $this->drupalGet('user/register');
+ $this->assertResponse(200);
+ }
+
+ /**
+ * Build XPath of field.
+ *
+ * @return string
+ * Field XPath.
+ */
+ private function fieldXpath() {
+ return $this->buildXPathQuery('//label[text()[starts-with(., :text)]]', [
+ ':text' => self::TEST_MODULE,
+ ]);
+ }
+
+}
diff --git a/tests/environment_fieldaccess_test/environment_fieldaccess_test.info b/tests/environment_fieldaccess_test/environment_fieldaccess_test.info
new file mode 100644
index 0000000..667796c
--- /dev/null
+++ b/tests/environment_fieldaccess_test/environment_fieldaccess_test.info
@@ -0,0 +1,7 @@
+name = Environment Field Access (Test)
+package = Field
+hidden = TRUE
+core = 7.x
+php = 5.4
+
+dependencies[] = environment_fieldaccess
diff --git a/tests/environment_fieldaccess_test/environment_fieldaccess_test.module b/tests/environment_fieldaccess_test/environment_fieldaccess_test.module
new file mode 100644
index 0000000..7dfa118
--- /dev/null
+++ b/tests/environment_fieldaccess_test/environment_fieldaccess_test.module
@@ -0,0 +1,24 @@
+<?php
+/**
+ * @file
+ * Environment Field Access (Test).
+ */
+
+/**
+ * Implements hook_environment().
+ */
+function environment_fieldaccess_test_environment() {
+ $environments = [];
+
+ $environments['test_show'] = [
+ 'label' => t('Environment for testing'),
+ 'description' => t('Environment, where fields are available'),
+ ];
+
+ $environments['test_hide'] = [
+ 'label' => t('Environment for testing'),
+ 'description' => t('Environment, where fields are not available'),
+ ];
+
+ return $environments;
+}