PageRenderTime 37ms CodeModel.GetById 9ms RepoModel.GetById 1ms app.codeStats 0ms

/web/core/modules/views/tests/src/Kernel/FieldApiDataTest.php

https://gitlab.com/mohamed_hussein/prodt
PHP | 385 lines | 279 code | 50 blank | 56 comment | 2 complexity | b0bc23aaad06102f86a95389c6fbc3ce MD5 | raw file
  1. <?php
  2. namespace Drupal\Tests\views\Kernel;
  3. use Drupal\Component\Render\MarkupInterface;
  4. use Drupal\field\Entity\FieldConfig;
  5. use Drupal\field\Entity\FieldStorageConfig;
  6. use Drupal\language\Entity\ConfigurableLanguage;
  7. use Drupal\language\Entity\ContentLanguageSettings;
  8. use Drupal\node\Entity\Node;
  9. use Drupal\node\Entity\NodeType;
  10. use Drupal\views\Views;
  11. /**
  12. * Tests the Field Views data.
  13. *
  14. * @group views
  15. */
  16. class FieldApiDataTest extends ViewsKernelTestBase {
  17. /**
  18. * {@inheritdoc}
  19. */
  20. protected static $modules = [
  21. 'field',
  22. 'filter',
  23. 'language',
  24. 'node',
  25. 'user',
  26. ];
  27. /**
  28. * {@inheritdoc}
  29. */
  30. public static $testViews = ['test_field_config_translation_filter'];
  31. /**
  32. * {@inheritdoc}
  33. */
  34. protected function setUp($import_test_views = TRUE): void {
  35. parent::setUp($import_test_views);
  36. $this->installEntitySchema('user');
  37. $this->installEntitySchema('node');
  38. $this->installSchema('node', ['node_access']);
  39. }
  40. /**
  41. * Unit testing the views data structure.
  42. *
  43. * We check data structure for both node and node revision tables.
  44. */
  45. public function testViewsData() {
  46. $field_storage_string = FieldStorageConfig::create([
  47. 'field_name' => 'field_string',
  48. 'entity_type' => 'node',
  49. 'type' => 'string',
  50. ]);
  51. $field_storage_string->save();
  52. $field_storage_string_long = FieldStorageConfig::create([
  53. 'field_name' => 'field_string_long',
  54. 'entity_type' => 'node',
  55. 'type' => 'string_long',
  56. ]);
  57. $field_storage_string_long->save();
  58. NodeType::create(['type' => 'page'])->save();
  59. NodeType::create(['type' => 'article'])->save();
  60. // Attach the field to nodes.
  61. FieldConfig::create([
  62. 'field_name' => 'field_string',
  63. 'entity_type' => 'node',
  64. 'bundle' => 'page',
  65. 'label' => 'GiraffeA" label',
  66. ])->save();
  67. // Attach the string_long field to the page node type.
  68. FieldConfig::create([
  69. 'field_name' => 'field_string_long',
  70. 'entity_type' => 'node',
  71. 'bundle' => 'page',
  72. 'label' => 'string_long label',
  73. ])->save();
  74. // Attach the same field to a different bundle with a different label.
  75. FieldConfig::create([
  76. 'field_name' => 'field_string',
  77. 'entity_type' => 'node',
  78. 'bundle' => 'article',
  79. 'label' => 'GiraffeB" label',
  80. ])->save();
  81. // Now create some example nodes/users for the view result.
  82. for ($i = 0; $i < 5; $i++) {
  83. $edit = [
  84. 'field_string' => [(['value' => $this->randomMachineName()])],
  85. ];
  86. $nodes[] = Node::create(['type' => 'page'] + $edit);
  87. }
  88. /** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */
  89. $table_mapping = $this->container->get('entity_type.manager')
  90. ->getStorage('node')
  91. ->getTableMapping();
  92. $current_table = $table_mapping->getDedicatedDataTableName($field_storage_string);
  93. $revision_table = $table_mapping->getDedicatedRevisionTableName($field_storage_string);
  94. $data = $this->getViewsData();
  95. $this->assertArrayHasKey($current_table, $data);
  96. $this->assertArrayHasKey($revision_table, $data);
  97. // The node field should join against node_field_data.
  98. $this->assertArrayHasKey('node_field_data', $data[$current_table]['table']['join']);
  99. $this->assertArrayHasKey('node_field_revision', $data[$revision_table]['table']['join']);
  100. $expected_join = [
  101. 'table' => $current_table,
  102. 'left_field' => 'nid',
  103. 'field' => 'entity_id',
  104. 'extra' => [
  105. ['field' => 'deleted', 'value' => 0, 'numeric' => TRUE],
  106. ['left_field' => 'langcode', 'field' => 'langcode'],
  107. ],
  108. ];
  109. $this->assertSame($expected_join, $data[$current_table]['table']['join']['node_field_data']);
  110. $expected_join = [
  111. 'table' => $revision_table,
  112. 'left_field' => 'vid',
  113. 'field' => 'revision_id',
  114. 'extra' => [
  115. ['field' => 'deleted', 'value' => 0, 'numeric' => TRUE],
  116. ['left_field' => 'langcode', 'field' => 'langcode'],
  117. ],
  118. ];
  119. $this->assertSame($expected_join, $data[$revision_table]['table']['join']['node_field_revision']);
  120. // Test click sortable for string field.
  121. $this->assertTrue($data[$current_table][$field_storage_string->getName()]['field']['click sortable']);
  122. // Click sort should only be on the primary field.
  123. $this->assertArrayNotHasKey($field_storage_string->getName(), $data[$revision_table]);
  124. // Test click sortable for long text field.
  125. $data_long = $this->getViewsData('field_string_long');
  126. $current_table_long = $table_mapping->getDedicatedDataTableName($field_storage_string_long);
  127. $this->assertTrue($data_long[$current_table_long][$field_storage_string_long->getName()]['field']['click sortable']);
  128. $this->assertInstanceOf(MarkupInterface::class, $data[$current_table][$field_storage_string->getName()]['help']);
  129. $this->assertEquals('Appears in: page, article. Also known as: Content: GiraffeB&quot; label', $data[$current_table][$field_storage_string->getName()]['help']);
  130. $this->assertInstanceOf(MarkupInterface::class, $data[$current_table][$field_storage_string->getName() . '_value']['help']);
  131. $this->assertEquals('Appears in: page, article. Also known as: Content: GiraffeA&quot; label (field_string)', $data[$current_table][$field_storage_string->getName() . '_value']['help']);
  132. // Since each label is only used once, views_entity_field_label() will
  133. // return a label using alphabetical sorting.
  134. $this->assertEquals('GiraffeA&quot; label (field_string)', $data[$current_table][$field_storage_string->getName() . '_value']['title']);
  135. // Attach the same field to a different bundle with a different label.
  136. NodeType::create(['type' => 'news'])->save();
  137. FieldConfig::create([
  138. 'field_name' => $field_storage_string->getName(),
  139. 'entity_type' => 'node',
  140. 'bundle' => 'news',
  141. 'label' => 'GiraffeB" label',
  142. ])->save();
  143. $this->container->get('views.views_data')->clear();
  144. $data = $this->getViewsData();
  145. // Now the 'GiraffeB&quot; label' is used twice and therefore will be
  146. // selected by views_entity_field_label().
  147. $this->assertEquals('GiraffeB&quot; label (field_string)', $data[$current_table][$field_storage_string->getName() . '_value']['title']);
  148. $this->assertInstanceOf(MarkupInterface::class, $data[$current_table][$field_storage_string->getName()]['help']);
  149. $this->assertEquals('Appears in: page, article, news. Also known as: Content: GiraffeA&quot; label', $data[$current_table][$field_storage_string->getName()]['help']);
  150. }
  151. /**
  152. * Gets the views data for the field created in setUp().
  153. *
  154. * @param string $field_storage_key
  155. * (optional) The optional field name.
  156. *
  157. * @return array
  158. * Views data.
  159. */
  160. protected function getViewsData($field_storage_key = 'field_string') {
  161. $views_data = $this->container->get('views.views_data');
  162. $data = [];
  163. // Check the table and the joins of the first field. Attached to node only.
  164. /** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */
  165. $table_mapping = $this->container->get('entity_type.manager')->getStorage('node')->getTableMapping();
  166. $field_storage = FieldStorageConfig::loadByName('node', $field_storage_key);
  167. $current_table = $table_mapping->getDedicatedDataTableName($field_storage);
  168. $revision_table = $table_mapping->getDedicatedRevisionTableName($field_storage);
  169. $data[$current_table] = $views_data->get($current_table);
  170. $data[$revision_table] = $views_data->get($revision_table);
  171. return $data;
  172. }
  173. /**
  174. * Tests filtering entries with different translatability.
  175. */
  176. public function testEntityFieldFilter() {
  177. NodeType::create(['type' => 'bundle1'])->save();
  178. NodeType::create(['type' => 'bundle2'])->save();
  179. // Create some example content.
  180. ConfigurableLanguage::create(['id' => 'es'])->save();
  181. ConfigurableLanguage::create(['id' => 'fr'])->save();
  182. ContentLanguageSettings::loadByEntityTypeBundle('node', 'bundle1')
  183. ->setDefaultLangcode('es')
  184. ->setLanguageAlterable(TRUE)
  185. ->save();
  186. ContentLanguageSettings::loadByEntityTypeBundle('node', 'bundle2')
  187. ->setDefaultLangcode('es')
  188. ->setLanguageAlterable(TRUE)
  189. ->save();
  190. $field_translation_map = [
  191. 1 => ['bundle1' => TRUE, 'bundle2' => TRUE],
  192. 2 => ['bundle1' => FALSE, 'bundle2' => FALSE],
  193. 3 => ['bundle1' => TRUE, 'bundle2' => FALSE],
  194. ];
  195. for ($i = 1; $i < 4; $i++) {
  196. $field_name = "field_name_$i";
  197. FieldStorageConfig::create([
  198. 'field_name' => $field_name,
  199. 'entity_type' => 'node',
  200. 'type' => 'string',
  201. ])->save();
  202. foreach (['bundle1', 'bundle2'] as $bundle) {
  203. FieldConfig::create([
  204. 'field_name' => $field_name,
  205. 'entity_type' => 'node',
  206. 'bundle' => $bundle,
  207. 'translatable' => $field_translation_map[$i][$bundle],
  208. ])->save();
  209. }
  210. }
  211. $node1 = Node::create([
  212. 'title' => 'Test title bundle1',
  213. 'type' => 'bundle1',
  214. 'langcode' => 'es',
  215. 'field_name_1' => 'field name 1: es',
  216. 'field_name_2' => 'field name 2: es',
  217. 'field_name_3' => 'field name 3: es',
  218. ]);
  219. $node1->save();
  220. /** @var \Drupal\node\NodeInterface $translation */
  221. $node1->addTranslation('fr', [
  222. 'title' => $node1->title->value,
  223. 'field_name_1' => 'field name 1: fr',
  224. 'field_name_3' => 'field name 3: fr',
  225. ])->save();
  226. $node2 = Node::create([
  227. 'title' => 'Test title bundle2',
  228. 'type' => 'bundle2',
  229. 'langcode' => 'es',
  230. 'field_name_1' => 'field name 1: es',
  231. 'field_name_2' => 'field name 2: es',
  232. 'field_name_3' => 'field name 3: es',
  233. ]);
  234. $node2->save();
  235. $node2->addTranslation('fr', [
  236. 'title' => $node2->title->value,
  237. 'field_name_1' => 'field name 1: fr',
  238. ])->save();
  239. $map = [
  240. 'nid' => 'nid',
  241. 'langcode' => 'langcode',
  242. ];
  243. $view = Views::getView('test_field_config_translation_filter');
  244. // Filter by 'field name 1: es'.
  245. $view->setDisplay('embed_1');
  246. $this->executeView($view);
  247. $expected = [
  248. [
  249. 'nid' => $node1->id(),
  250. 'langcode' => 'es',
  251. ],
  252. [
  253. 'nid' => $node2->id(),
  254. 'langcode' => 'es',
  255. ],
  256. ];
  257. $this->assertIdenticalResultset($view, $expected, $map);
  258. $view->destroy();
  259. // Filter by 'field name 1: fr'.
  260. $view->setDisplay('embed_2');
  261. $this->executeView($view);
  262. $expected = [
  263. [
  264. 'nid' => $node1->id(),
  265. 'langcode' => 'fr',
  266. ],
  267. [
  268. 'nid' => $node2->id(),
  269. 'langcode' => 'fr',
  270. ],
  271. ];
  272. $this->assertIdenticalResultset($view, $expected, $map);
  273. $view->destroy();
  274. // Filter by 'field name 2: es'.
  275. $view->setDisplay('embed_3');
  276. $this->executeView($view);
  277. $expected = [
  278. [
  279. 'nid' => $node1->id(),
  280. 'langcode' => 'es',
  281. ],
  282. [
  283. 'nid' => $node1->id(),
  284. 'langcode' => 'fr',
  285. ],
  286. [
  287. 'nid' => $node2->id(),
  288. 'langcode' => 'es',
  289. ],
  290. [
  291. 'nid' => $node2->id(),
  292. 'langcode' => 'fr',
  293. ],
  294. ];
  295. $this->assertIdenticalResultset($view, $expected, $map);
  296. $view->destroy();
  297. // Filter by 'field name 2: fr', which doesn't exist.
  298. $view->setDisplay('embed_4');
  299. $this->executeView($view);
  300. $expected = [];
  301. $this->assertIdenticalResultset($view, $expected, $map);
  302. $view->destroy();
  303. // Filter by 'field name 3: es'.
  304. $view->setDisplay('embed_5');
  305. $this->executeView($view);
  306. $expected = [
  307. [
  308. 'nid' => $node1->id(),
  309. 'langcode' => 'es',
  310. ],
  311. [
  312. 'nid' => $node2->id(),
  313. 'langcode' => 'es',
  314. ],
  315. // Why is this one returned?
  316. [
  317. 'nid' => $node2->id(),
  318. 'langcode' => 'fr',
  319. ],
  320. ];
  321. $this->assertIdenticalResultset($view, $expected, $map);
  322. $view->destroy();
  323. // Filter by 'field name 3: fr'.
  324. $view->setDisplay('embed_6');
  325. $this->executeView($view);
  326. $expected = [
  327. [
  328. 'nid' => $node1->id(),
  329. 'langcode' => 'fr',
  330. ],
  331. ];
  332. $this->assertIdenticalResultset($view, $expected, $map);
  333. $view->destroy();
  334. }
  335. }