5 * Contains \Drupal\Console\Command\Field\InfoCommand.
8 namespace Drupal\Console\Command\Field;
10 use Symfony\Component\Console\Input\InputOption;
11 use Symfony\Component\Console\Input\InputInterface;
12 use Symfony\Component\Console\Output\OutputInterface;
13 use Symfony\Component\Console\Command\Command;
14 use Drupal\Core\Entity\EntityFieldManagerInterface;
15 use Drupal\Core\Entity\EntityTypeManagerInterface;
16 use Drupal\field\FieldConfigInterface;
17 use Drupal\Console\Core\Command\Shared\CommandTrait;
18 use Drupal\Console\Core\Style\DrupalStyle;
23 class InfoCommand extends Command
28 * @var EntityTypeManagerInterface
30 protected $entityTypeManager;
33 * @var EntityFieldManagerInterface
35 protected $entityFieldManager;
38 * InfoCommand constructor.
40 * @param EntityTypeManagerInterface $entityTypeManager
41 * @param EntityFieldManagerInterface $entityFieldManager
43 public function __construct(
44 EntityTypeManagerInterface $entityTypeManager,
45 EntityFieldManagerInterface $entityFieldManager
47 $this->entityTypeManager = $entityTypeManager;
48 $this->entityFieldManager = $entityFieldManager;
49 parent::__construct();
55 public function configure()
58 ->setName('field:info')
59 ->setDescription($this->trans('commands.field.info.description'))
60 ->setHelp($this->trans('commands.field.info.help'))
64 InputOption::VALUE_NONE,
65 $this->trans('commands.field.info.options.detailed')
70 InputOption::VALUE_OPTIONAL,
71 $this->trans('commands.field.info.options.entity')
76 InputOption::VALUE_OPTIONAL,
77 $this->trans('commands.field.info.options.bundle')
84 protected function execute(InputInterface $input, OutputInterface $output)
86 $io = new DrupalStyle($input, $output);
88 // Retrieve whether detailed option has been selected.
89 $detailedOutput = $input->getOption('detailed');
91 // Retrieve whether an entity type has been specified.
92 $entityTypeOption = $input->getOption('entity');
94 // Retrieve whether a specific bundle type has been specified.
95 $bundleTypeOption = $input->getOption('bundle');
97 $entityList = $this->entityTypeManager->getDefinitions();
98 $allFields = $this->entityFieldManager->getFieldMap();
100 // Set a flag so we can error if a specific entity type selected but not found.
101 $entityTypeOptionFound = false;
103 // Set a flag so we can error if a specific bundle type selected but not found.
104 $bundleTypeOptionFound = false;
106 // Let's count the fields found so we can display a message if none found.
109 foreach ($entityList as $entityTypeId => $entityValue) {
110 // If the Entity has bundleEntityType set we grab it.
111 $bundleEntityType = $entityValue->get('bundle_entity_type');
113 // Check to see if the entity has any bundle before continuing.
114 if (!empty($bundleEntityType)) {
115 $bundleTypes = $this->entityTypeManager
116 ->getStorage($bundleEntityType)->loadMultiple();
118 // If a specific entity type has been selected and this is it then we continue else we skip.
119 if ((!empty($entityTypeOption) && ($entityTypeOption == $entityTypeId))| empty($entityTypeOption)
121 // Store the fact that we found the entity type specified so we can error if not found.
122 $entityTypeOptionFound = true;
124 // Get the entity type label.
125 $bundleParent = $entityValue->get('label');
127 // Using counter to know whether to output header.
128 $bundleTypeCounter = 0;
129 foreach ($bundleTypes as $bundleType) {
130 // If a specific bundle type has been selected and this is it then we continue else we skip.
131 if ((!empty($bundleTypeOption) && ($bundleTypeOption == $bundleType->id()))| empty($bundleTypeOption)
133 // Store the fact that we found the bundle type specified so we can error if not found.
134 $bundleTypeOptionFound = true;
136 // Increase the bundle type counter so we know whether to output header.
137 $bundleTypeCounter++;
139 if ($bundleTypeCounter == 1) {
140 // Output the Parent Entity label if we haven't already.
141 if ($detailedOutput) {
142 // If detailed output then display the id as well.
143 $io->info(strtoupper($bundleParent) . ' (' . $entityTypeId . '):');
145 // otherwise just display the label for normal output.
146 $io->info(strtoupper($bundleParent . ':'));
151 // Load in the entityType fields.
152 $fields = $this->getBundleFields(
157 foreach ($fields as $field => $fieldArray) {
158 // We found a field so increase the field counter.
161 // Get the related / used in bundles from the field.
162 $relatedBundles = "";
163 $relatedBundlesArray = $allFields[$entityTypeId][$field]['bundles'];
165 // Turn those related / used in bundles array into a string.
166 foreach ($relatedBundlesArray as $relatedBundlesValue) {
167 if ($bundleTypes[$relatedBundlesValue]->id() != $bundleType->id()) {
168 if (!empty($relatedBundles)) {
169 $relatedBundles .= ', ' . $bundleTypes[$relatedBundlesValue]->label();
171 $relatedBundles = $bundleTypes[$relatedBundlesValue]->label();
176 // Build out our table for the fields.
177 $tableRows[] = $detailedOutput ? [
178 $fieldArray->get('label'),
179 $fieldArray->get('field_type'),
180 $fieldArray->get('description'),
183 $fieldArray->get('label'),
184 $fieldArray->get('field_type'),
188 // Clear the related bundles ready for the next field.
189 unset($relatedBundles);
192 // If detailed output then display bundle id and description.
193 if ($detailedOutput) {
194 // Output the bundle label and id.
195 $io->info($bundleType->label() . ' (' . $bundleType->id() . ')');
196 $io->info(strip_tags($bundleType->get('description')));
198 // Else just output the bundle label.
199 $io->info($bundleType->label());
202 // Fill out our table header.
203 // If no rows exist for the fields then we display a no results message.
204 if (!empty($tableRows)) {
205 $tableHeader = $detailedOutput ? [
206 $this->trans('commands.field.info.table.header-name'),
207 $this->trans('commands.field.info.table.header-type'),
208 $this->trans('commands.field.info.table.header-desc'),
209 $this->trans('commands.field.info.table.header-usage')
211 $this->trans('commands.field.info.table.header-name'),
212 $this->trans('commands.field.info.table.header-type'),
213 $this->trans('commands.field.info.table.header-usage')
215 $io->table($tableHeader, $tableRows);
218 $this->trans('commands.field.info.messages.fields-none')
219 . ' ' . $this->trans('commands.field.info.messages.in-bundle-type')
220 . " '" . $bundleType->label() . "'"
224 // Clear out the rows & headers arrays to start fresh.
225 unset($tableHeader, $tableRows);
227 // Create some space so the output looks nice.
235 // If entity type was specified but not found then display error message.
236 if (!empty($entityTypeOption)) {
237 if (!$entityTypeOptionFound) {
239 $this->trans('commands.field.info.messages.entity-type') .
240 ' ' . $entityTypeOption . ' ' .
241 $this->trans('commands.field.info.messages.not-found')
243 } elseif (!empty($bundleTypeOption) && !$bundleTypeOptionFound) {
244 // If specified entity type found and bundle type specified but not found then display error message.
246 $this->trans('commands.field.info.messages.bundle-type') .
247 ' ' . $bundleTypeOption . ' ' .
248 $this->trans('commands.field.info.messages.not-found') .
249 ' ' . $this->trans('commands.field.info.messages.in-entity-type') .
250 ' ' . $entityTypeOption
253 } elseif (!empty($bundleTypeOption) && !$bundleTypeOptionFound) {
254 // If specified bundle type not found then display error message.
256 $this->trans('commands.field.info.messages.bundle-type') .
257 ' ' . $bundleTypeOption . ' ' .
258 $this->trans('commands.field.info.messages.not-found')
260 } elseif ($fieldCounter == 0) {
261 // If no fields found then display appropriate message.
262 $io->comment($this->trans('commands.field.info.messages.fields-none'));
269 * Helper function to get the field definitions.
271 * @param string $entityTypeId
272 * The entity type we want to inspect.
273 * @param string $bundle
274 * The bundle we want to discover the fields of.
276 * An array of field storage definitions for the entity type,
277 * keyed by field name.
279 private function getBundleFields($entityTypeId, $bundle)
282 if (!empty($entityTypeId) && !empty($bundle)) {
283 $fields = array_filter(
284 $this->entityFieldManager->getFieldDefinitions($entityTypeId, $bundle),
285 function ($fieldDefinition) {
286 return $fieldDefinition instanceof FieldConfigInterface;