PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.6.4
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.6.4
1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.4 1.5.5 1.5.3 1.5.2 1.5.1 1.5.0 1.4.2 1.4.1 1.4.0 1.3.28 1.3.27 1.3.26 1.3.25 1.3.23 1.3.22 1.3.21 1.3.20 1.3.19 trunk 1.2.0 All 47 releases
fluent-cart / app / Services / Filter / LogFilter.php

LogFilter.php in FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler 1.6.4, at app/Services/Filter/LogFilter.php

129 lines 4.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentCart\App\Services\Filter;
4
5 use FluentCart\App\Models\Activity;
6 use FluentCart\Framework\Support\Str;
7
8 class LogFilter extends BaseFilter
9 {
10
11 public function applySimpleFilter(?string $search = null): void
12 {
13 $this->query->when($search ?? $this->search, function ($query, $search) {
14 return $query
15 ->where(function ($query) use ($search) {
16 $searchOptions = [];
17 if (Str::of($search)->contains('#')) {
18 $searchableColumns = ['id'];
19 $search = Str::of($search)->remove('#')->toString();
20 } else {
21 $searchableColumns = ['id', 'title', 'content', 'module_name'];
22 }
23
24 foreach ($searchableColumns as $index => $column) {
25 $searchOptions[$column] = [
26 'column' => $column,
27 'operator' => $index === 0 ? 'like_all' : 'or_like_all',
28 'value' => $search
29 ];
30 }
31 $query->search($searchOptions);
32 });
33 });
34 }
35
36
37 public function tabsMap(): array
38 {
39 return [
40 'success' => 'status',
41 'warning' => 'status',
42 'error' => 'status',
43 'failed' => 'status',
44 'info' => 'status',
45 'api' => 'log_type',
46 ];
47 }
48
49 public function getModel(): string
50 {
51 return Activity::class;
52 }
53
54 public static function getFilterName(): string
55 {
56 return 'logs';
57 }
58
59 /**
60 * @return array<string, array<string, mixed>>
61 */
62 protected static function sortableColumns(): array
63 {
64 return [
65 'id' => ['label' => __('ID', 'fluent-cart'), 'column' => 'id'],
66 'title' => ['label' => __('Title', 'fluent-cart'), 'column' => 'title'],
67 'created_at' => ['label' => __('Created At', 'fluent-cart'), 'column' => 'created_at'],
68 ];
69 }
70
71 /**
72 * No screen key, because there is no screen: the admin table (LogTable.js)
73 * does not override `Table::with()`, so nothing in the admin sends a `with`
74 * to the activity feed at all. Inventing a context key for a context that
75 * does not exist would be an entry with no reader.
76 *
77 * PUBLIC key — `user` is the relation name a consumer asks an activity
78 * endpoint for, and it is the name the repo's own remaining consumer sends:
79 * the Phase 16 throughput guard (`tests/integration/throughput-guards.php`,
80 * `throughput-activity-feed`) materializes `$activity->user` for every row
81 * inside its query-count boundary and asserts the count does not grow from
82 * 5 rows to 25. Without an eager-load path that guard cannot pass at all —
83 * the actor would be lazily fetched per row — so the only way to drop this
84 * key is to delete the N+1 assertion, which is the gate itself.
85 *
86 * No further permission bar: the feed mounts under `AdminPolicy`, so a
87 * caller here is already a super admin. The grant is narrow anyway —
88 * `Activity::user()` selects exactly ID, display_name and user_email on the
89 * relation itself.
90 *
91 * `Activity::activity()` is a `morphTo()` and MUST NEVER be allowlisted at
92 * any depth. Its target is chosen by the `module_type` column of each row,
93 * so a single `with=activity` would hydrate whatever model the log happens
94 * to point at — orders, subscriptions, licenses — bypassing every
95 * per-model permission check this map exists to enforce.
96 *
97 * @return array<string, callable>
98 */
99 protected function allowedWiths(): array
100 {
101 return [
102 'user' => [$this, 'publicUser'],
103 ];
104 }
105
106 /**
107 * The actor behind a log row. No select here: `Activity::user()` already
108 * narrows itself to ID, display_name and user_email.
109 *
110 * @param \FluentCart\Framework\Database\Orm\Builder $query
111 * @return \FluentCart\Framework\Database\Orm\Builder
112 */
113 protected function publicUser($query)
114 {
115 return $query->with(['user']);
116 }
117
118
119 public function applyActiveViewFilter(?string $activeView = null): void
120 {
121 $activeView = $activeView ?? $this->activeView;
122 $tabsMap = $this->tabsMap();
123
124 $this->query->when($activeView, function ($query, $activeView) use ($tabsMap) {
125 $query->where($tabsMap[$activeView], $activeView);
126 });
127 }
128 }
129