@flarum/cli 3.0.12 → 3.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/README.md +33 -1
  2. package/boilerplate/skeleton/extension/composer.json +4 -0
  3. package/boilerplate/skeleton/extension/js/package.json +5 -5
  4. package/boilerplate/skeleton/extension/js/tsconfig.json +3 -0
  5. package/boilerplate/skeleton/extension/js/tsconfig.test.json +1 -0
  6. package/boilerplate/stubs/backend/advanced-api-resource.php +3 -3
  7. package/boilerplate/stubs/backend/model-factory.php +17 -0
  8. package/boilerplate/stubs/backend/model.php +3 -0
  9. package/lib/base-command.d.ts +21 -3
  10. package/lib/base-command.js +52 -5
  11. package/lib/commands/make/backend/model.js +10 -0
  12. package/lib/commands/upgrade/2.0.d.ts +43 -0
  13. package/lib/commands/upgrade/2.0.js +128 -2
  14. package/lib/steps/gen-ext-scaffolder.d.ts +5 -0
  15. package/lib/steps/gen-ext-scaffolder.js +17 -2
  16. package/lib/steps/stubs/backend/advanced-api-resource.js +1 -1
  17. package/lib/steps/stubs/backend/model-factory.d.ts +24 -0
  18. package/lib/steps/stubs/backend/model-factory.js +33 -0
  19. package/lib/steps/upgrade/twopointoh/backend/email-views.js +22 -30
  20. package/lib/steps/upgrade/twopointoh/backend/extension-models.d.ts +30 -0
  21. package/lib/steps/upgrade/twopointoh/backend/extension-models.js +34 -0
  22. package/lib/steps/upgrade/twopointoh/backend/json-api.d.ts +6 -0
  23. package/lib/steps/upgrade/twopointoh/backend/json-api.js +14 -0
  24. package/lib/steps/upgrade/twopointoh/backend/misc.d.ts +6 -0
  25. package/lib/steps/upgrade/twopointoh/backend/misc.js +19 -7
  26. package/lib/steps/upgrade/twopointoh/backend/model-factories.d.ts +18 -0
  27. package/lib/steps/upgrade/twopointoh/backend/model-factories.js +73 -0
  28. package/lib/steps/upgrade/twopointoh/backend/phpunit.d.ts +2 -0
  29. package/lib/steps/upgrade/twopointoh/backend/phpunit.js +16 -8
  30. package/lib/steps/upgrade/twopointoh/backend/search.d.ts +9 -0
  31. package/lib/steps/upgrade/twopointoh/backend/search.js +28 -10
  32. package/lib/steps/upgrade/twopointoh/base.d.ts +38 -0
  33. package/lib/steps/upgrade/twopointoh/base.js +73 -12
  34. package/lib/steps/upgrade/twopointoh/dependencies.d.ts +55 -0
  35. package/lib/steps/upgrade/twopointoh/dependencies.js +317 -20
  36. package/lib/steps/upgrade/twopointoh/frontend/admin-extender.d.ts +86 -0
  37. package/lib/steps/upgrade/twopointoh/frontend/admin-extender.js +842 -0
  38. package/lib/steps/upgrade/twopointoh/frontend/code-splitting/usage-of-lazy-modules.js +110 -18
  39. package/lib/steps/upgrade/twopointoh/frontend/export-registry/import-ext.js +13 -16
  40. package/lib/steps/upgrade/twopointoh/frontend/misc.d.ts +23 -0
  41. package/lib/steps/upgrade/twopointoh/frontend/misc.js +147 -8
  42. package/lib/steps/upgrade/twopointoh/infra.d.ts +16 -1
  43. package/lib/steps/upgrade/twopointoh/infra.js +87 -5
  44. package/lib/steps/upgrade/twopointoh/step-failures.d.ts +8 -0
  45. package/lib/steps/upgrade/twopointoh/step-failures.js +6 -0
  46. package/lib/steps/upgrade/twopointoh/todos.d.ts +22 -0
  47. package/lib/steps/upgrade/twopointoh/todos.js +57 -0
  48. package/lib/steps/upgrade/twopointoh/typescript-5-9.d.ts +15 -0
  49. package/lib/steps/upgrade/twopointoh/typescript-5-9.js +250 -0
  50. package/lib/utils/ast.js +3 -2
  51. package/lib/utils/babel-ts.d.ts +9 -0
  52. package/lib/utils/babel-ts.js +18 -0
  53. package/lib/utils/composer.d.ts +5 -0
  54. package/lib/utils/composer.js +10 -1
  55. package/lib/utils/terminal.d.ts +13 -0
  56. package/lib/utils/terminal.js +26 -0
  57. package/oclif.manifest.json +1 -1
  58. package/package.json +1 -1
  59. package/php-subsystem/index.php +12 -0
  60. package/php-subsystem/src/NodeUtil.php +19 -9
  61. package/php-subsystem/src/NodeVisitors/AddExtender.php +49 -1
  62. package/php-subsystem/src/Upgrade/TwoPointOh/JsonApi.php +2 -20
  63. package/php-subsystem/src/Upgrade/TwoPointOh/Misc.php +13 -17
  64. package/php-subsystem/src/Upgrade/TwoPointOh/ModelFactories.php +943 -0
  65. package/php-subsystem/src/Upgrade/TwoPointOh/PhpUnit.php +476 -71
  66. package/php-subsystem/src/Upgrade/TwoPointOh/Search.php +97 -13
@@ -230,6 +230,39 @@ class Search extends Replacement
230
230
  $this->returnExtendersNode = $returnExtendersNode;
231
231
  }
232
232
 
233
+ /** The class a registration names, by the name it has once it is a filter. */
234
+ private function registeredClass(Node\Expr $expr): ?string
235
+ {
236
+ if ($expr instanceof Node\Expr\ClassConstFetch && $expr->class instanceof Node\Name) {
237
+ $name = ($expr->class->getAttribute('resolvedName') ?? $expr->class)->toString();
238
+ } elseif ($expr instanceof Node\Scalar\String_) {
239
+ $name = $expr->value;
240
+ } else {
241
+ return null;
242
+ }
243
+
244
+ $name = str_replace(['FilterGambit', 'GambitFilter'], 'Filter', $name);
245
+
246
+ return ltrim(str_replace('Gambit', 'Filter', $name), '\\');
247
+ }
248
+
249
+ /**
250
+ * 1.x registered a class that was both a gambit and a filter
251
+ * twice, with each extender: 2.0 needs it once.
252
+ */
253
+ private function register(string $searcher, string $kind, Node\Expr $expr): void
254
+ {
255
+ $class = $this->registeredClass($expr);
256
+
257
+ foreach ($this->data['searchers'][$searcher][$kind] ?? [] as $registered) {
258
+ if ($class !== null && $this->registeredClass($registered) === $class) {
259
+ return;
260
+ }
261
+ }
262
+
263
+ $this->data['searchers'][$searcher][$kind][] = $expr;
264
+ }
265
+
233
266
  private function findNew(Node $node): ?Node\Expr\New_
234
267
  {
235
268
  if ($node instanceof Node\Expr\New_) {
@@ -292,9 +325,9 @@ class Search extends Replacement
292
325
  }
293
326
 
294
327
  if ($method === 'addFilter') {
295
- $this->data['searchers'][$searcher]['filters'][] = $arg->value;
328
+ $this->register($searcher, 'filters', $arg->value);
296
329
  } elseif ($method === 'addFilterMutator') {
297
- $this->data['searchers'][$searcher]['mutators'][] = $arg->value;
330
+ $this->register($searcher, 'mutators', $arg->value);
298
331
  }
299
332
  } elseif ($class === 'Flarum\Extend\SimpleFlarumSearch') {
300
333
  $searcher = NodeUtil::className($new->args[0]->value->class);
@@ -318,7 +351,7 @@ class Search extends Replacement
318
351
  }
319
352
 
320
353
  if ($method === 'addGambit') {
321
- $this->data['searchers'][$searcher]['filters'][] = $arg->value;
354
+ $this->register($searcher, 'filters', $arg->value);
322
355
  } elseif ($method === 'setFullTextGambit') {
323
356
  $this->data['searchers'][$searcher]['fulltext'] = isset($resolvedName)
324
357
  ? $resolvedName->name
@@ -381,13 +414,48 @@ class Search extends Replacement
381
414
  $collectorData = $collector->data;
382
415
  } elseif (isset($visitor)) {
383
416
  $collectorData = [
384
- 'extendData' => $visitor->data,
417
+ 'extendData' => $this->reportable($visitor->data),
385
418
  ];
386
419
  }
387
420
 
388
421
  return new ReplacementResult($code, $collectorData);
389
422
  }
390
423
 
424
+ /**
425
+ * The searchers the extenders registered, with each filter and mutator by
426
+ * the name it is written with, which is what the step reads. Not their
427
+ * syntax trees: a fully qualified name's refers to itself, which can't be
428
+ * encoded as JSON.
429
+ */
430
+ protected function reportable(array $data): array
431
+ {
432
+ $searchers = [];
433
+
434
+ foreach ($data['searchers'] ?? [] as $searcher => $registered) {
435
+ foreach (['filters', 'mutators'] as $kind) {
436
+ if (! isset($registered[$kind])) {
437
+ continue;
438
+ }
439
+
440
+ $classes = [];
441
+
442
+ foreach ($registered[$kind] as $expr) {
443
+ if ($expr instanceof Node\Scalar\String_) {
444
+ $classes[] = ['class' => ['name' => $expr->value]];
445
+ } elseif ($expr instanceof Node\Expr\ClassConstFetch && $expr->class instanceof Node\Name) {
446
+ $classes[] = ['class' => ['name' => $expr->class->name]];
447
+ }
448
+ }
449
+
450
+ $registered[$kind] = $classes;
451
+ }
452
+
453
+ $searchers[$searcher] = $registered;
454
+ }
455
+
456
+ return ['searchers' => $searchers];
457
+ }
458
+
391
459
  function replaceNamespaces(string $file, string $code, array $ast, array $data): ?ReplacementResult
392
460
  {
393
461
  $traverser = $this->traverser();
@@ -439,16 +507,32 @@ class Search extends Replacement
439
507
  ],
440
508
  'return' => ['void'],
441
509
  ],
442
- 'constrain' => [
443
- 'params' => [
444
- 'query' => ['\\Illuminate\\Database\\Eloquent\\Builder'],
445
- 'actor' => ['\\Flarum\\User\\User'],
446
- 'negate' => ['bool'],
447
- ],
448
- 'return' => ['void'],
449
- ],
450
510
  ],
451
- ]));
511
+ ], function (Node $node) {
512
+ // A filter's constrain() helper is its own, so its parameters are
513
+ // left as they are, but for the query it is given: 2.0 makes that
514
+ // an Eloquent builder.
515
+ if (! $node instanceof Node\Stmt\ClassMethod || strtolower($node->name->name) !== 'constrain') {
516
+ return;
517
+ }
518
+
519
+ foreach ($node->params as $param) {
520
+ $nullable = $param->type instanceof Node\NullableType;
521
+ $type = $nullable ? $param->type->type : $param->type;
522
+
523
+ if (! $type instanceof Node\Name || ltrim(NodeUtil::className($type), '\\') !== 'Illuminate\\Database\\Query\\Builder') {
524
+ continue;
525
+ }
526
+
527
+ $eloquent = NodeUtil::makeType(['\\Illuminate\\Database\\Eloquent\\Builder']);
528
+
529
+ if ($nullable) {
530
+ $param->type->type = $eloquent;
531
+ } else {
532
+ $param->type = $eloquent;
533
+ }
534
+ }
535
+ }));
452
536
 
453
537
  return new ReplacementResult($traverser->traverse($ast));
454
538
  }