ILIAS  release_10 Revision v10.1-43-ga1241a92c2f
CapabilityTest.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
31 
32 class CapabilityTest extends TestCase
33 {
37  public \PHPUnit\Framework\MockObject\MockObject $workspace_access_handler;
38  public \PHPUnit\Framework\MockObject\MockObject|TypeResolver $type_resolver;
40  private ilAccessHandler|MockObject $access;
41  private ilCtrlInterface|MockObject $ctrl;
43  private Services|MockObject $http;
44  private URIBuilder|MockObject $static_url;
46 
47  private static array $readme_infos = [];
48 
49  private static bool $update_readme = false;
50 
51  protected function setUp(): void
52  {
53  if (!defined('ILIAS_HTTP_PATH')) {
54  define('ILIAS_HTTP_PATH', 'https://ilias.unit.test');
55  }
56 
57  $this->file_info_repository = $this->createMock(\ilObjFileInfoRepository::class);
58  $this->access = $this->createMock(\ilAccessHandler::class);
59  $this->ctrl = $this->createMock(\ilCtrlInterface::class);
60  $this->action_repository = $this->createMock(ActionRepository::class);
61  $this->http = $this->createMock(Services::class);
62  $this->static_url = $this->createMock(URIBuilder::class);
63  $this->type_resolver = $this->createMock(TypeResolver::class);
64  $this->workspace_access_handler = $this->createMock(ilWorkspaceAccessHandler::class);
65 
66  $this->type_resolver->method('resolveTypeByObjectId')
67  ->withAnyParameters()
68  ->willReturn('file');
69 
70  $this->capability_builder = new CapabilityBuilder(
71  $this->file_info_repository,
72  $this->access,
73  $this->ctrl,
74  $this->action_repository,
75  $this->http,
76  $this->static_url,
77  $this->type_resolver,
78  $this->workspace_access_handler
79  );
80  }
81 
82  protected function tearDown(): void
83  {
84  }
85 
86  public static function tearDownAfterClass(): void
87  {
88  if (!self::$update_readme) {
89  return;
90  }
91  self::updateREADME();
92  }
93 
94  public static function environmentProvider(): array
95  {
96  return [
97  'testerei' => [
98  'wopi_view' => true,
99  'wopi_edit' => true,
100  'infopage_first' => true,
101  'user_permissions' => [
102  Permissions::READ,
103  Permissions::WRITE,
104  Permissions::VISIBLE,
105  Permissions::EDIT_CONTENT,
106  Permissions::VIEW_CONTENT
107  ],
108  'expected_best' => Capabilities::FORCED_INFO_PAGE
109  ],
110  [
111  'wopi_view' => true,
112  'wopi_edit' => true,
113  'infopage_first' => false,
114  'user_permissions' => [
115  Permissions::READ,
116  Permissions::WRITE,
117  Permissions::VISIBLE,
118  Permissions::EDIT_CONTENT,
119  Permissions::VIEW_CONTENT
120  ],
121  'expected_best' => Capabilities::VIEW_EXTERNAL
122  ],
123  [
124  'wopi_view' => true,
125  'wopi_edit' => true,
126  'infopage_first' => false,
127  'user_permissions' => [
128  Permissions::EDIT_CONTENT,
129  Permissions::VIEW_CONTENT
130  ],
131  'expected_best' => Capabilities::VIEW_EXTERNAL
132  ],
133  [
134  'wopi_view' => false,
135  'wopi_edit' => false,
136  'infopage_first' => true,
137  'user_permissions' => [
138  Permissions::READ,
139  Permissions::VISIBLE
140  ],
141  'expected_best' => Capabilities::FORCED_INFO_PAGE
142  ],
143  [
144  'wopi_view' => true,
145  'wopi_edit' => true,
146  'infopage_first' => false,
147  'user_permissions' => [
148  Permissions::EDIT_CONTENT,
149  ],
150  'expected_best' => Capabilities::EDIT_EXTERNAL
151  ],
152  [
153  'wopi_view' => true,
154  'wopi_edit' => true,
155  'infopage_first' => false,
156  'user_permissions' => [
157  Permissions::READ,
158  ],
159  'expected_best' => Capabilities::DOWNLOAD
160  ],
161  [
162  'wopi_view' => true,
163  'wopi_edit' => true,
164  'infopage_first' => false,
165  'user_permissions' => [
166  Permissions::WRITE,
167  Permissions::READ,
168  ],
169  'expected_best' => Capabilities::DOWNLOAD
170  ],
171  [
172  'wopi_view' => true,
173  'wopi_edit' => true,
174  'infopage_first' => false,
175  'user_permissions' => [
176  Permissions::WRITE,
177  ],
178  'expected_best' => Capabilities::MANAGE_VERSIONS
179  ],
180  [
181  'wopi_view' => true,
182  'wopi_edit' => true,
183  'infopage_first' => false,
184  'user_permissions' => [
185  Permissions::VISIBLE,
186  ],
187  'expected_best' => Capabilities::INFO_PAGE
188  ],
189  [
190  'wopi_view' => true,
191  'wopi_edit' => true,
192  'infopage_first' => true,
193  'user_permissions' => [
194  Permissions::WRITE,
195  Permissions::READ,
196  ],
197  'expected_best' => Capabilities::FORCED_INFO_PAGE
198  ],
199  [
200  'wopi_view' => true,
201  'wopi_edit' => true,
202  'infopage_first' => false,
203  'user_permissions' => [
204  Permissions::NONE,
205  ],
206  'expected_best' => Capabilities::NONE
207  ],
208  ];
209  }
210 
211  #[DataProvider('environmentProvider')]
212  public function testCapabilityPriority(
213  bool $wopi_view,
214  bool $wopi_edit,
215  bool $infopage_first,
216  array $permissions,
217  Capabilities $expected_best
218  ): void {
219  static $id;
220 
221  $id++;
222 
223  $context = new Context(
224  $id,
225  $id,
226  Context::CONTEXT_REPO
227  );
228 
229  $this->access->method('checkAccess')
230  ->willReturnCallback(
231  function (string $permission) use ($permissions): bool {
232  $checked_permissions = explode(',', $permission);
233  $common_permissions = array_intersect(
234  array_map(static fn(Permissions $p): string => $p->value, $permissions),
235  $checked_permissions
236  );
237  return $common_permissions !== [];
238  }
239  );
240 
241  $file_info = $this->createMock(\ilObjFileInfo::class);
242  $file_info->method('shouldDownloadDirectly')
243  ->willReturn(!$infopage_first);
244 
245  $this->file_info_repository->method('getByObjectId')
246  ->with($context->getObjectId())
247  ->willReturn($file_info);
248 
249  $this->action_repository->method('hasEditActionForSuffix')
250  ->willReturn($wopi_edit);
251 
252  $this->action_repository->method('hasViewActionForSuffix')
253  ->willReturn($wopi_view);
254 
255  $capabilities = $this->capability_builder->get($context);
256  $best = $capabilities->getBest();
257 
258  $this->assertEquals($expected_best, $best->getCapability());
259 
260  self::$readme_infos[] = [
261  implode(', ', array_map(fn(Permissions $p): string => $p->value, $permissions)), // permissions
262  ($wopi_view ? 'Yes' : 'No'),
263  ($wopi_edit ? 'Yes' : 'No'),
264  ($infopage_first ? 'Info-Page' : 'Open'),
265  $best->getCapability()->name
266  ];
267  }
268 
269  private static function updateREADME(): void
270  {
271  // UPDATE README
272  $readme_file = __DIR__ . '/../../docs/README.md';
273  $readme_content = file_get_contents($readme_file);
274 
275  $table = [
276  [
277  'User\'s Permissions',
278  'WOPI View Action av.',
279  'WOPI Edit Action av.',
280  'Click-Setting',
281  'Expected Capability'
282  ]
283  ];
284  $readme_infos = self::$readme_infos;
285  // sort $readme_infos by last column
286  usort($readme_infos, static function ($a, $b): int {
287  $a_string = implode('', array_reverse($a));
288  $b_string = implode('', array_reverse($b));
289 
290  return strcmp((string) $a_string, (string) $b_string);
291  });
292 
293  $table = array_merge($table, $readme_infos);
294 
295  // Define the markers for the block
296  $start_marker = "<!-- START CAPABILITY_TABLE -->";
297  $end_marker = "<!-- END CAPABILITY_TABLE -->";
298 
299  // Prepare the new block content
300  $new_block = $start_marker . "\n\n" . self::arrayToMarkdownTable($table) . "\n\n" . $end_marker;
301 
302  // Replace the content between the markers
303  $pattern = '/' . preg_quote($start_marker, '/') . '.*?' . preg_quote($end_marker, '/') . '/s';
304  $readme_content = preg_replace($pattern, $new_block, $readme_content);
305 
306  file_put_contents($readme_file, $readme_content);
307  }
308 
309  private static function arrayToMarkdownTable(array $data): string
310  {
311  // Check if the input array is valid
312  if (empty($data) || !is_array($data[0])) {
313  throw new InvalidArgumentException("Input must be a non-empty array of arrays.");
314  }
315 
316  // Calculate the maximum width of each column
317  $col_widths = array_map(
318  static fn($col_index): int => max(
319  array_map(
320  static fn($row): int => isset($row[$col_index]) ? mb_strlen((string) $row[$col_index]) : 0,
321  $data
322  )
323  ),
324  array_keys($data[0])
325  );
326 
327  // Function to pad a row's columns to match the maximum width
328  $pad_row = static fn($row): array => array_map(static function ($value, $index) use ($col_widths): string {
329  $value ??= ''; // Handle missing values
330  return str_pad($value, $col_widths[$index], " ", STR_PAD_RIGHT);
331  }, $row, array_keys($col_widths));
332 
333  // Format the header and rows
334  $header = $pad_row($data[0]);
335  $rows = array_map($pad_row, array_slice($data, 1));
336 
337  // Build the Markdown table
338  $header_row = "| "
339  . implode(" | ", $header)
340  . " |";
341  $sep_row = "| "
342  . implode(" | ", array_map(static fn($width): string => str_repeat("-", $width), $col_widths))
343  . " |";
344  $data_rows = array_map(static fn($row): string => "| " . implode(" | ", $row) . " |", $rows);
345 
346  // Combine all parts
347  return implode("\n", array_merge([$header_row, $sep_row], $data_rows));
348  }
349 
350 }
ActionRepository MockObject $action_repository
CapabilityBuilder $capability_builder
$context
Definition: webdav.php:31
static updateREADME()
ilObjFileInfoRepository MockObject $file_info_repository
testCapabilityPriority(bool $wopi_view, bool $wopi_edit, bool $infopage_first, array $permissions, Capabilities $expected_best)
ilAccessHandler MockObject $access
static array $readme_infos
PHPUnit Framework MockObject MockObject $workspace_access_handler
static environmentProvider()
static bool $update_readme
static http()
Fetches the global http state from ILIAS.
static arrayToMarkdownTable(array $data)
Services MockObject $http
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:24
URIBuilder MockObject $static_url
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples
PHPUnit Framework MockObject MockObject TypeResolver $type_resolver
ilCtrlInterface MockObject $ctrl
static tearDownAfterClass()