PageRenderTime 54ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/core/Tiki/Command/FakerTrackerCommand.php

https://gitlab.com/ElvisAns/tiki
PHP | 262 lines | 199 code | 23 blank | 40 comment | 19 complexity | 9e09ae5a30ef43356b6a4d01a0be89a0 MD5 | raw file
  1. <?php
  2. // (c) Copyright by authors of the Tiki Wiki CMS Groupware Project
  3. //
  4. // All Rights Reserved. See copyright.txt for details and a complete list of authors.
  5. // Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
  6. // $Id$
  7. namespace Tiki\Command;
  8. use Symfony\Component\Console\Command\Command;
  9. use Symfony\Component\Console\Input\InputArgument;
  10. use Symfony\Component\Console\Input\InputInterface;
  11. use Symfony\Component\Console\Input\InputOption;
  12. use Symfony\Component\Console\Output\OutputInterface;
  13. use Faker\Factory as FakerFactory;
  14. use TikiLib;
  15. use Tiki\Faker as TikiFaker;
  16. use Tracker_Definition;
  17. /**
  18. * Enabled the usage of Faker as a way to load random data to trackers
  19. */
  20. class FakerTrackerCommand extends Command
  21. {
  22. /**
  23. * Configures the current command.
  24. */
  25. protected function configure()
  26. {
  27. $this
  28. ->setName('faker:tracker')
  29. ->setDescription('Generate tracker fake data')
  30. ->addArgument(
  31. 'tracker',
  32. InputArgument::REQUIRED,
  33. 'Tracker id'
  34. )
  35. ->addOption(
  36. 'field',
  37. 'f',
  38. InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
  39. 'Override default faker for field. Format: field,faker[,faker_options]. Example: 1,text,30'
  40. )
  41. ->addOption(
  42. 'items',
  43. 'i',
  44. InputOption::VALUE_OPTIONAL,
  45. 'Number of items to generate',
  46. 100
  47. )
  48. ->addOption(
  49. 'random-status',
  50. 'r',
  51. InputOption::VALUE_NONE,
  52. 'Generate random item status'
  53. )
  54. ->addOption(
  55. 'reuse-files',
  56. null,
  57. InputOption::VALUE_OPTIONAL,
  58. 'Reuse existing files in the file gallery when possible',
  59. 1
  60. );
  61. }
  62. /**
  63. * Executes the current command.
  64. *
  65. * @param InputInterface $input
  66. * @param OutputInterface $output
  67. * @return null|int
  68. */
  69. protected function execute(InputInterface $input, OutputInterface $output)
  70. {
  71. if (! class_exists('\Faker\Factory')) {
  72. $output->writeln('<error>' . tra('Please install Faker package') . '</error>');
  73. return;
  74. }
  75. $trackerId = $input->getArgument('tracker');
  76. $numberItems = $input->getOption('items');
  77. $randomizeStatus = empty($input->getOption('random-status')) ? false : true;
  78. $fieldOverrideDefinition = $input->getOption('field');
  79. $reuseFiles = empty($input->getOption('reuse-files')) ? false : true;
  80. if (! is_numeric($numberItems)) {
  81. $output->writeln('<error>' . tra('The value of items is not a number') . '</error>');
  82. return;
  83. }
  84. $trackerDefinition = Tracker_Definition::get($trackerId);
  85. if (! $trackerDefinition) {
  86. $output->writeln('<error>' . tr('Tracker not found') . '</error>');
  87. return;
  88. }
  89. $fieldFakerOverride = [];
  90. foreach ($fieldOverrideDefinition as $fieldDefinition) {
  91. $arguments = array_map('trim', explode(',', $fieldDefinition));
  92. $fieldReference = array_shift($arguments);
  93. $action = array_shift($arguments);
  94. if (is_null($fieldReference) || is_null($action)) {
  95. $output->writeln('<error>' . tr('Invalid field definition: %0', $fieldDefinition) . '</error>');
  96. return;
  97. }
  98. if (empty($arguments)) {
  99. $fieldFakerOverride[$fieldReference] = $action;
  100. } else {
  101. $fieldFakerOverride[$fieldReference] = [$action, $arguments];
  102. }
  103. }
  104. $trackerFields = $trackerDefinition->getFields();
  105. $fakerFieldTypes = $this->mapTrackerItems();
  106. $fieldFakerMap = [];
  107. foreach ($trackerFields as $field) {
  108. if (isset($fieldFakerOverride[$field['fieldId']])) { // override by fieldId
  109. $fakerForField = $fieldFakerOverride[$field['fieldId']];
  110. } elseif (isset($fieldFakerOverride[$field['permName']])) { // override by permName
  111. $fakerForField = $fieldFakerOverride[$field['permName']];
  112. } elseif (preg_match('/~tc~faker:(.*)~\/tc~/', $field['description'], $matches)) {
  113. // check field descriptions for a faker formatter in the form of
  114. // ~tc~faker:lastName~/tc~ or ~tc~faker: numberBetween,1,100~/tc~ or ~tc~faker:dateTimeBetween,-6 months~/tc~
  115. // full list is here https://github.com/fzaninotto/Faker#formatters
  116. $parts = explode(',', trim($matches[1]));
  117. $formatter = array_shift($parts);
  118. if (! empty($parts)) {
  119. $formatter = [$formatter, $parts];
  120. }
  121. $fakerForField = $formatter;
  122. } elseif (isset($fakerFieldTypes[$field['type']])) { // default for field type
  123. $fakerForField = $fakerFieldTypes[$field['type']];
  124. } else { // if not defined, empty
  125. $fakerForField = '';
  126. }
  127. $fieldFakerMap[] = [
  128. 'fieldId' => $field['fieldId'],
  129. 'faker' => $fakerForField,
  130. ];
  131. }
  132. /** @var \TrackerLib $trackerLib */
  133. $trackerLib = TikiLib::lib('trk');
  134. $faker = FakerFactory::create();
  135. $tikiFaker = new TikiFaker($faker);
  136. $tikiFaker->setTikiFilesReuseFiles($reuseFiles);
  137. $faker->addProvider($tikiFaker);
  138. for ($i = 0; $i < $numberItems; $i++) {
  139. $fieldData = [];
  140. foreach ($fieldFakerMap as $fieldFaker) {
  141. $value = '';
  142. if (is_array($fieldFaker['faker'])) {
  143. $fakerAction = $fieldFaker['faker'][0];
  144. $fakerArguments = $fieldFaker['faker'][1];
  145. if (! is_array($fakerArguments)) {
  146. if ($fakerArguments == 'fieldId') {
  147. $fakerArguments = $trackerDefinition->getField($fieldFaker['fieldId']);
  148. }
  149. $fakerArguments = [$fakerArguments];
  150. } elseif ($fakerArguments[0] === 'fieldId') {
  151. $fakerArguments[0] = $trackerDefinition->getField($fieldFaker['fieldId']);
  152. } elseif (substr($fakerAction, 0, 4) === 'tiki') {
  153. array_unshift($fakerArguments, $trackerDefinition->getField($fieldFaker['fieldId']));
  154. }
  155. $value = call_user_func_array([$faker, $fakerAction], $fakerArguments);
  156. } elseif (! empty($fieldFaker['faker'])) {
  157. $fakerAction = $fieldFaker['faker'];
  158. $value = $faker->$fakerAction;
  159. }
  160. if (isset($value)) {
  161. if (is_object($value) && get_class($value) === 'DateTime') {
  162. $value = $value->format('U');
  163. }
  164. $fieldData[] = array_merge(
  165. $trackerLib->get_field_info($fieldFaker['fieldId']),
  166. [
  167. 'value' => $value,
  168. ]
  169. );
  170. }
  171. }
  172. if (! empty($fieldData)) {
  173. $status = ($randomizeStatus) ? array_rand(\TikiLib::lib('trk')->status_types()) : '';
  174. $trackerLib->replace_item($trackerId, 0, ['data' => $fieldData], $status);
  175. }
  176. }
  177. }
  178. /**
  179. * Return the current map of tracker field types to faker formatters
  180. *
  181. * @return array
  182. */
  183. protected function mapTrackerItems()
  184. {
  185. $map = [
  186. 'e' => 'tikiCategories', // Category - lookup on the valid values for category
  187. 'c' => 'tikiCheckbox', // Checkbox - lookup on the valid values for the checkbox
  188. 'y' => 'country', // Country Selector (improvement if uses the list from Tiki directly)
  189. 'b' => ['numberBetween', [0, 10000]], // Currency Field
  190. 'f' => 'unixTime', // Date and Time
  191. 'j' => 'unixTime', // Date and Time
  192. 'd' => ['tikiDropdown', 'fieldId'], // Drop Down - lookup on the valid values for the drop down
  193. 'D' => ['tikiDropdown', 'fieldId'], // Drop Down with Other field - lookup on the valid values for the drop down
  194. 'R' => ['tikiRadio', 'fieldId'], // Radio Buttons - lookup for valid values for Buttons
  195. 'M' => ['tikiMultiselect', 'fieldId'], // Multiselect - lookup on the valid values for the select
  196. 'w' => '', // Dynamic Items List - lookup on the valid values from other tracker (and sync between different fields)
  197. 'm' => 'email', // Email
  198. 'FG' => ['tikiFiles', 'fieldId'], // Files - lookup on valid files from gallery
  199. 'h' => '', // Header - empty
  200. 'icon' => ['tikiFiles', ['fieldId', true]], // Icon - lookup on valid files from gallery
  201. 'r' => ['tikiItemLink', 'fieldId'], // Item Link - lookup on valid items
  202. //'l' => '', // Items List - lookup on valid items
  203. 'LANG' => 'languageCode', // Language
  204. 'G' => 'tikiLocation', // Location - needs geo coordinates in the format <lat>,<long>,<zoom>
  205. 'math' => '', // Mathematical Calculation - empty
  206. 'n' => ['numberBetween', [0, 10000]], // Numeric Field
  207. 'k' => 'tikiPageSelector', // Page Selector - lookup for valid page names
  208. 'S' => ['tikiStaticText', 'fieldId'], // Static Text - empty
  209. 'a' => 'text', // Text Area
  210. 't' => ['text', [30]], // Text Field
  211. 'q' => ['tikiUniqueIdentifier', 'fieldId'], // AutoIncrement - empty
  212. 'L' => 'url', // Url
  213. 'u' => ['tikiUserSelector', 'fieldId'], // User Selector - lookup for valid users
  214. 'g' => 'tikiGroupSelector', // Group Selector - lookup for valid groups
  215. 'wiki' => 'text', //Wiki Page
  216. //'x' => '', // Action - Not supported
  217. 'articles' => 'tikiArticles', // Articles - lookup for valid articles
  218. //'C' => '', // Computed Field - not supported - backward compatibility
  219. //'A' => '', // Attachment - deprecated in favor of files field
  220. 'F' => ['words', [3, true]], // Tags
  221. //'GF' => '', // Geographic Feature
  222. //'i' => '', // Image - deprecated in favor of the files field
  223. //'N' => '', // In Group
  224. 'I' => 'localIpv4', // IP Selector
  225. //'kaltura' => '', // Kaltura video
  226. 'p' => '', // Ldap lookup - empty
  227. 'STARS' => ['tikiRating', 'fieldId'], // Rating - lookup for valid values
  228. //'*' => '', // Stars (deprecated)
  229. //'s' => '', // Stars (system - deprecated)
  230. 'REL' => ['tikiRelations', ['fieldId', true, 5]], // Relations, rand (true/false), max/number of relations
  231. //'STO' => '', // show.tiki.org - Not supported
  232. 'usergroups' => '', // Display list of user groups - empty
  233. //'p' => '', // User Preference - Not Supported
  234. //'U' => '', // User Subscription
  235. 'W' => '', // Webservice - empty
  236. ];
  237. return $map;
  238. }
  239. }