ILIAS  release_9 Revision v9.13-25-g2c18ec4c24f
ilDidacticTemplateLocalPolicyAction Class Reference

Description of class. More...

+ Inheritance diagram for ilDidacticTemplateLocalPolicyAction:
+ Collaboration diagram for ilDidacticTemplateLocalPolicyAction:

Public Member Functions

 __construct (int $action_id=0)
 
 addFilterPattern (ilDidacticTemplateFilterPattern $pattern)
 
 setFilterPatterns (array $patterns)
 Set filter patterns. More...
 
 getFilterPattern ()
 Get filter pattern. More...
 
 setFilterType (int $a_type)
 
 getFilterType ()
 
 setRoleTemplateType (int $a_tpl_type)
 
 getRoleTemplateType ()
 
 setRoleTemplateId (int $a_id)
 
 getRoleTemplateId ()
 
 save ()
 
 delete ()
 
 apply ()
 
 revert ()
 
 getType ()
 
 toXml (ilXmlWriter $writer)
 
 __clone ()
 
 read ()
 
- Public Member Functions inherited from ilDidacticTemplateAction
 __construct (int $action_id=0)
 
 getLogger ()
 
 getActionId ()
 
 setActionId (int $a_action_id)
 
 setType (int $a_type_id)
 
 setTemplateId (int $a_id)
 
 getTemplateId ()
 
 setRefId (int $a_ref_id)
 
 getRefId ()
 
 save ()
 Write action to db Overwrite for filling additional db fields. More...
 
 delete ()
 Delete didactic template action Overwrite for filling additional db fields. More...
 
 read ()
 
 getType ()
 Get type of template. More...
 
 apply ()
 Apply action. More...
 
 revert ()
 Implement everthing that is necessary to revert a didactic template return bool. More...
 
 __clone ()
 
 toXml (ilXmlWriter $writer)
 

Data Fields

const TPL_ACTION_OVERWRITE = 1
 
const TPL_ACTION_INTERSECT = 2
 
const TPL_ACTION_ADD = 3
 
const TPL_ACTION_SUBTRACT = 4
 
const TPL_ACTION_UNION = 5
 
- Data Fields inherited from ilDidacticTemplateAction
const TYPE_LOCAL_POLICY = 1
 
const TYPE_LOCAL_ROLE = 2
 
const TYPE_BLOCK_ROLE = 3
 
const FILTER_SOURCE_TITLE = 1
 
const FILTER_SOURCE_OBJ_ID = 2
 
const FILTER_PARENT_ROLES = 3
 
const FILTER_LOCAL_ROLES = 4
 
const PATTERN_PARENT_TYPE = 'action'
 

Protected Member Functions

 createLocalPolicy (ilObject $source, array $role)
 
 revertLocalPolicy (ilObject $source, array $role)
 
- Protected Member Functions inherited from ilDidacticTemplateAction
 initSourceObject ()
 
 filterRoles (ilObject $source)
 

Private Attributes

array $pattern = []
 
int $filter_type = self::FILTER_SOURCE_TITLE
 
int $role_template_type = self::TPL_ACTION_OVERWRITE
 
int $role_template_id = 0
 

Additional Inherited Members

- Protected Attributes inherited from ilDidacticTemplateAction
ilLogger $logger
 
ilDBInterface $db
 
ilRbacReview $review
 
ilRbacAdmin $admin
 

Detailed Description

Description of class.

Author
Stefan Meyer meyer.nosp@m.@lei.nosp@m.fos.c.nosp@m.om

Definition at line 11 of file class.ilDidacticTemplateLocalPolicyAction.php.

Constructor & Destructor Documentation

◆ __construct()

ilDidacticTemplateLocalPolicyAction::__construct ( int  $action_id = 0)

Member Function Documentation

◆ __clone()

ilDidacticTemplateLocalPolicyAction::__clone ( )

Definition at line 259 of file class.ilDidacticTemplateLocalPolicyAction.php.

References $pattern, getFilterPattern(), and setFilterPatterns().

260  {
261  parent::__clone();
262 
263  $clones = [];
264  foreach ($this->getFilterPattern() as $pattern) {
265  $clones[] = clone $pattern;
266  }
267  $this->setFilterPatterns($clones);
268  }
+ Here is the call graph for this function:

◆ addFilterPattern()

ilDidacticTemplateLocalPolicyAction::addFilterPattern ( ilDidacticTemplateFilterPattern  $pattern)

Definition at line 30 of file class.ilDidacticTemplateLocalPolicyAction.php.

References $pattern.

Referenced by read().

30  : void
31  {
32  $this->pattern[] = $pattern;
33  }
+ Here is the caller graph for this function:

◆ apply()

ilDidacticTemplateLocalPolicyAction::apply ( )

Definition at line 120 of file class.ilDidacticTemplateLocalPolicyAction.php.

References createLocalPolicy(), ilDidacticTemplateAction\filterRoles(), ilDidacticTemplateAction\getLogger(), and ilDidacticTemplateAction\initSourceObject().

120  : bool
121  {
122  $source = $this->initSourceObject();
123  // Create a role folder for the new local policies
124  $roles = $this->filterRoles($source);
125 
126  // Create local policy for filtered roles
127  foreach ($roles as $role_id => $role) {
128  $this->getLogger()->debug('Apply to role: ' . $role['title']);
129  $this->getLogger()->debug('Role parent: ' . $role['parent']);
130  $this->getLogger()->debug('Source ref_id: ' . $source->getRefId());
131 
132  // No local policies for protected roles of higher context
133  if (
134  (int) $role['parent'] !== $source->getRefId() &&
135  $this->review->isProtected($role['parent'], $role_id)
136  ) {
137  $this->getLogger()->debug('Ignoring protected role.');
138  continue;
139  }
140  $this->createLocalPolicy($source, $role);
141  }
142 
143  return true;
144  }
+ Here is the call graph for this function:

◆ createLocalPolicy()

ilDidacticTemplateLocalPolicyAction::createLocalPolicy ( ilObject  $source,
array  $role 
)
protected

Definition at line 290 of file class.ilDidacticTemplateLocalPolicyAction.php.

References ilDidacticTemplateAction\getLogger(), ilObject\getRefId(), getRoleTemplateId(), getRoleTemplateType(), ILIAS\Repository\int(), ILIAS\Repository\logger(), ilObjRole\MODE_PROTECTED_DELETE_LOCAL_POLICIES, ilObjRole\MODE_UNPROTECTED_DELETE_LOCAL_POLICIES, and ROLE_FOLDER_ID.

Referenced by apply().

290  : bool
291  {
292  // fetch role information
293  $role_data = [];
294  foreach ($this->review->getParentRoleIds($source->getRefId()) as $role_id => $tmp_role) {
295  if ((int) $role_id === (int) $role['obj_id']) {
296  $role_data = $tmp_role;
297  }
298  }
299 
300  // Add local policy
301  if (!$this->review->isRoleAssignedToObject((int) $role['obj_id'], $source->getRefId())) {
302  $this->admin->assignRoleToFolder(
303  (int) $role['obj_id'],
304  $source->getRefId(),
305  'n'
306  );
307  }
308 
309  // do nothing if role is protected in higher context
310  if (
311  (int) $role['parent'] !== $source->getRefId() &&
312  $this->review->isProtected($source->getRefId(), (int) $role['obj_id'])
313  ) {
314  $this->getLogger()->info('Ignoring protected role: ' . $role['title']);
315  return false;
316  }
317 
318  switch ($this->getRoleTemplateType()) {
319  case self::TPL_ACTION_UNION:
320 
321  $this->logger->info('Using ilRbacAdmin::copyRolePermissionUnion()');
322  $this->admin->copyRolePermissionUnion(
323  (int) $role_data['obj_id'],
324  (int) $role_data['parent'],
325  $this->getRoleTemplateId(),
327  (int) $role_data['obj_id'],
328  $source->getRefId()
329  );
330  break;
331 
332  case self::TPL_ACTION_OVERWRITE:
333 
334  $this->logger->info('Using ilRbacAdmin::copyRoleTemplatePermission()');
335  $this->admin->copyRoleTemplatePermissions(
336  $this->getRoleTemplateId(),
338  $source->getRefId(),
339  (int) $role_data['obj_id'],
340  true
341  );
342  break;
343 
344  case self::TPL_ACTION_INTERSECT:
345 
346  $this->logger->info('Using ilRbacAdmin::copyRolePermissionIntersection()' . $this->getRoleTemplateId());
347  $this->admin->copyRolePermissionIntersection(
348  (int) $role_data['obj_id'],
349  (int) $role_data['parent'],
350  $this->getRoleTemplateId(),
352  $source->getRefId(),
353  (int) $role_data['obj_id']
354  );
355  break;
356  }
357  // Change existing object
358  $role_obj = new ilObjRole((int) $role_data['obj_id']);
359  $role_obj->changeExistingObjects(
360  $source->getRefId(),
362  ['all']
363  );
364 
365  return true;
366  }
Class ilObjRole.
const MODE_PROTECTED_DELETE_LOCAL_POLICIES
const ROLE_FOLDER_ID
Definition: constants.php:34
const MODE_UNPROTECTED_DELETE_LOCAL_POLICIES
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ delete()

ilDidacticTemplateLocalPolicyAction::delete ( )

Definition at line 108 of file class.ilDidacticTemplateLocalPolicyAction.php.

References ilDidacticTemplateAction\getActionId(), and getFilterPattern().

108  : void
109  {
110  parent::delete();
111  $query = 'DELETE FROM didactic_tpl_alp ' .
112  'WHERE action_id = ' . $this->db->quote($this->getActionId(), 'integer');
113  $this->db->manipulate($query);
114 
115  foreach ($this->getFilterPattern() as $pattern) {
116  $pattern->delete();
117  }
118  }
+ Here is the call graph for this function:

◆ getFilterPattern()

ilDidacticTemplateLocalPolicyAction::getFilterPattern ( )

Get filter pattern.

Returns
ilDidacticTemplateFilterPattern[]

Definition at line 48 of file class.ilDidacticTemplateLocalPolicyAction.php.

References $pattern.

Referenced by __clone(), delete(), save(), and toXml().

+ Here is the caller graph for this function:

◆ getFilterType()

ilDidacticTemplateLocalPolicyAction::getFilterType ( )

Definition at line 58 of file class.ilDidacticTemplateLocalPolicyAction.php.

References $filter_type.

Referenced by save(), and toXml().

+ Here is the caller graph for this function:

◆ getRoleTemplateId()

ilDidacticTemplateLocalPolicyAction::getRoleTemplateId ( )

Definition at line 78 of file class.ilDidacticTemplateLocalPolicyAction.php.

References $role_template_id.

Referenced by createLocalPolicy(), save(), and toXml().

+ Here is the caller graph for this function:

◆ getRoleTemplateType()

ilDidacticTemplateLocalPolicyAction::getRoleTemplateType ( )

Definition at line 68 of file class.ilDidacticTemplateLocalPolicyAction.php.

References $role_template_type.

Referenced by createLocalPolicy(), save(), and toXml().

+ Here is the caller graph for this function:

◆ getType()

ilDidacticTemplateLocalPolicyAction::getType ( )

Definition at line 183 of file class.ilDidacticTemplateLocalPolicyAction.php.

183  : int
184  {
185  return self::TYPE_LOCAL_POLICY;
186  }

◆ read()

ilDidacticTemplateLocalPolicyAction::read ( )

Definition at line 270 of file class.ilDidacticTemplateLocalPolicyAction.php.

References $res, addFilterPattern(), ilDBConstants\FETCHMODE_OBJECT, ilDidacticTemplateAction\getActionId(), ilDidacticTemplateFilterPatternFactory\lookupPatternsByParentId(), setFilterType(), setRoleTemplateId(), setRoleTemplateType(), and ilDBConstants\T_INTEGER.

270  : void
271  {
272  parent::read();
273  $query = 'SELECT * FROM didactic_tpl_alp ' .
274  'WHERE action_id = ' . $this->db->quote($this->getActionId(), ilDBConstants::T_INTEGER);
275  $res = $this->db->query($query);
276  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
277  $this->setFilterType((int) $row->filter_type);
278  $this->setRoleTemplateType((int) $row->template_type);
279  $this->setRoleTemplateId((int) $row->template_id);
280  }
281  // Read filter
283  $this->getActionId(),
284  self::PATTERN_PARENT_TYPE
285  ) as $pattern) {
286  $this->addFilterPattern($pattern);
287  }
288  }
$res
Definition: ltiservices.php:69
addFilterPattern(ilDidacticTemplateFilterPattern $pattern)
static lookupPatternsByParentId(int $a_parent_id, string $a_parent_type)
+ Here is the call graph for this function:

◆ revert()

ilDidacticTemplateLocalPolicyAction::revert ( )

Definition at line 146 of file class.ilDidacticTemplateLocalPolicyAction.php.

References ilDidacticTemplateAction\filterRoles(), ilDidacticTemplateAction\getLogger(), ilDidacticTemplateAction\initSourceObject(), ilObjRole\MODE_PROTECTED_DELETE_LOCAL_POLICIES, ilObjRole\MODE_UNPROTECTED_DELETE_LOCAL_POLICIES, and revertLocalPolicy().

146  : bool
147  {
148  $source = $this->initSourceObject();
149  $roles = $this->filterRoles($source);
150 
151  // Delete local policy for filtered roles
152  foreach ($roles as $role_id => $role) {
153  // Do not delete local policies of auto generated roles
154  if (!$this->review->isGlobalRole($role['obj_id']) &&
155  $this->review->isAssignable($role['obj_id'], $source->getRefId()) &&
156  $this->review->isSystemGeneratedRole($role['obj_id'])) {
157  $this->getLogger()->debug('Reverting local policy of auto generated role: ' . $role['title']);
158  $this->revertLocalPolicy($source, $role);
159  } else {
160  $this->getLogger()->debug('Reverting local policy and deleting local role: ' . $role['title']);
161 
162  // delete local role and change exiting objects
163  $this->admin->deleteLocalRole($role_id, $source->getRefId());
164 
165  // Change existing object
166  $role_obj = new ilObjRole($role_id);
167 
168  $protected = $this->review->isProtected($role['parent'], $role['rol_id']);
169 
170  $role_obj->changeExistingObjects(
171  $source->getRefId(),
172  $protected ?
175  ['all']
176  );
177  }
178  }
179 
180  return true;
181  }
Class ilObjRole.
const MODE_PROTECTED_DELETE_LOCAL_POLICIES
const MODE_UNPROTECTED_DELETE_LOCAL_POLICIES
+ Here is the call graph for this function:

◆ revertLocalPolicy()

ilDidacticTemplateLocalPolicyAction::revertLocalPolicy ( ilObject  $source,
array  $role 
)
protected

Definition at line 368 of file class.ilDidacticTemplateLocalPolicyAction.php.

References $res, ilDBConstants\FETCHMODE_OBJECT, ilObject\getRefId(), ILIAS\Repository\int(), ILIAS\Repository\logger(), ilObjRole\MODE_PROTECTED_DELETE_LOCAL_POLICIES, ilObjRole\MODE_UNPROTECTED_DELETE_LOCAL_POLICIES, and ROLE_FOLDER_ID.

Referenced by revert().

368  : bool
369  {
370  $this->logger->info('Reverting policy for role ' . $role['title']);
371  // Local policies can only be reverted for auto generated roles. Otherwise the
372  // original role settings are unknown
373  if (strpos($role['title'], 'il_') !== 0) {
374  $this->logger->warning('Cannot revert local policy for role ' . $role['title']);
375  return false;
376  }
377 
378  // No local policies
379  if (!$this->review->getLocalPolicies($source->getRefId())) {
380  return false;
381  }
382 
383  $exploded_title = explode('_', $role['title']);
384  $rolt_title = $exploded_title[0] . '_' . $exploded_title[1] . '_' . $exploded_title[2];
385 
386  // Lookup role template
387  $query = 'SELECT obj_id FROM object_data ' .
388  'WHERE title = ' . $this->db->quote($rolt_title, 'text') . ' ' .
389  'AND type = ' . $this->db->quote('rolt', 'text');
390  $res = $this->db->query($query);
391  $rolt_id = 0;
392  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
393  $rolt_id = (int) $row->obj_id;
394  }
395 
396  // No template found
397  if (!$rolt_id) {
398  return false;
399  }
400 
401  $this->admin->copyRoleTemplatePermissions(
402  $rolt_id,
404  $source->getRefId(),
405  (int) $role['obj_id'],
406  true
407  );
408 
409  // Change existing object
410  $role_obj = new ilObjRole((int) $role['obj_id']);
411  $role_obj->changeExistingObjects(
412  $source->getRefId(),
414  ['all']
415  );
416 
417  return true;
418  }
Class ilObjRole.
$res
Definition: ltiservices.php:69
const MODE_PROTECTED_DELETE_LOCAL_POLICIES
const ROLE_FOLDER_ID
Definition: constants.php:34
const MODE_UNPROTECTED_DELETE_LOCAL_POLICIES
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ save()

ilDidacticTemplateLocalPolicyAction::save ( )

Definition at line 83 of file class.ilDidacticTemplateLocalPolicyAction.php.

References ilDidacticTemplateAction\getActionId(), getFilterPattern(), getFilterType(), getRoleTemplateId(), and getRoleTemplateType().

83  : int
84  {
85  if (!parent::save()) {
86  return 0;
87  }
88 
89  $query = 'INSERT INTO didactic_tpl_alp (action_id,filter_type,template_type,template_id) ' .
90  'VALUES( ' .
91  $this->db->quote($this->getActionId(), 'integer') . ', ' .
92  $this->db->quote($this->getFilterType(), 'integer') . ', ' .
93  $this->db->quote($this->getRoleTemplateType(), 'integer') . ', ' .
94  $this->db->quote($this->getRoleTemplateId(), 'integer') . ' ' .
95  ')';
96  $this->db->manipulate($query);
97 
98  foreach ($this->getFilterPattern() as $pattern) {
99  /* @var ilDidacticTemplateFilterPattern $pattern */
100  $pattern->setParentId($this->getActionId());
101  $pattern->setParentType(self::PATTERN_PARENT_TYPE);
102  $pattern->save();
103  }
104 
105  return $this->getActionId();
106  }
+ Here is the call graph for this function:

◆ setFilterPatterns()

ilDidacticTemplateLocalPolicyAction::setFilterPatterns ( array  $patterns)

Set filter patterns.

Parameters
ilDidacticTemplateExcludeFilterPattern[]$patterns

Definition at line 39 of file class.ilDidacticTemplateLocalPolicyAction.php.

Referenced by __clone().

39  : void
40  {
41  $this->pattern = $patterns;
42  }
+ Here is the caller graph for this function:

◆ setFilterType()

ilDidacticTemplateLocalPolicyAction::setFilterType ( int  $a_type)

Definition at line 53 of file class.ilDidacticTemplateLocalPolicyAction.php.

Referenced by read().

53  : void
54  {
55  $this->filter_type = $a_type;
56  }
+ Here is the caller graph for this function:

◆ setRoleTemplateId()

ilDidacticTemplateLocalPolicyAction::setRoleTemplateId ( int  $a_id)

Definition at line 73 of file class.ilDidacticTemplateLocalPolicyAction.php.

Referenced by read().

73  : void
74  {
75  $this->role_template_id = $a_id;
76  }
+ Here is the caller graph for this function:

◆ setRoleTemplateType()

ilDidacticTemplateLocalPolicyAction::setRoleTemplateType ( int  $a_tpl_type)

Definition at line 63 of file class.ilDidacticTemplateLocalPolicyAction.php.

Referenced by read().

63  : void
64  {
65  $this->role_template_type = $a_tpl_type;
66  }
+ Here is the caller graph for this function:

◆ toXml()

ilDidacticTemplateLocalPolicyAction::toXml ( ilXmlWriter  $writer)

Definition at line 188 of file class.ilDidacticTemplateLocalPolicyAction.php.

References ilObject\_lookupType(), ilXmlWriter\appendXML(), getFilterPattern(), getFilterType(), getRoleTemplateId(), getRoleTemplateType(), IL_INST_ID, ilRoleXmlExport\MODE_DTPL, ROLE_FOLDER_ID, ilXmlWriter\xmlEndTag(), and ilXmlWriter\xmlStartTag().

188  : void
189  {
190  $writer->xmlStartTag('localPolicyAction');
191 
192  switch ($this->getFilterType()) {
193  case self::FILTER_SOURCE_OBJ_ID:
194  $writer->xmlStartTag('roleFilter', ['source' => 'objId']);
195  break;
196 
197  case self::FILTER_PARENT_ROLES:
198  $writer->xmlStartTag('roleFilter', ['source' => 'parentRoles']);
199  break;
200 
201  case self::FILTER_LOCAL_ROLES:
202  $writer->xmlStartTag('roleFilter', ['source' => 'localRoles']);
203  break;
204 
205  case self::FILTER_SOURCE_TITLE:
206  default:
207  $writer->xmlStartTag('roleFilter', ['source' => 'title']);
208  break;
209  }
210 
211  foreach ($this->getFilterPattern() as $pattern) {
212  $pattern->toXml($writer);
213  }
214  $writer->xmlEndTag('roleFilter');
215 
216  $il_role_id = 'il_' . IL_INST_ID . '_' . ilObject::_lookupType($this->getRoleTemplateId()) . '_' . $this->getRoleTemplateId();
217 
218  switch ($this->getRoleTemplateType()) {
219  case self::TPL_ACTION_OVERWRITE:
220  $writer->xmlStartTag(
221  'localPolicyTemplate',
222  [
223  'type' => 'overwrite',
224  'id' => $il_role_id
225  ]
226  );
227  break;
228 
229  case self::TPL_ACTION_INTERSECT:
230  $writer->xmlStartTag(
231  'localPolicyTemplate',
232  [
233  'type' => 'intersect',
234  'id' => $il_role_id
235  ]
236  );
237  break;
238 
239  case self::TPL_ACTION_UNION:
240  $writer->xmlStartTag(
241  'localPolicyTemplate',
242  [
243  'type' => 'union',
244  'id' => $il_role_id
245  ]
246  );
247  break;
248  }
249 
250  $exp = new ilRoleXmlExport();
251  $exp->setMode(ilRoleXmlExport::MODE_DTPL);
252  $exp->addRole($this->getRoleTemplateId(), ROLE_FOLDER_ID);
253  $exp->write();
254  $writer->appendXML($exp->xmlDumpMem(false));
255  $writer->xmlEndTag('localPolicyTemplate');
256  $writer->xmlEndTag('localPolicyAction');
257  }
const IL_INST_ID
Definition: constants.php:40
appendXML(string $a_str)
append xml string to document
xmlEndTag(string $tag)
Writes an endtag.
const ROLE_FOLDER_ID
Definition: constants.php:34
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
xmlStartTag(string $tag, ?array $attrs=null, bool $empty=false, bool $encode=true, bool $escape=true)
Writes a starttag.
static _lookupType(int $id, bool $reference=false)
+ Here is the call graph for this function:

Field Documentation

◆ $filter_type

int ilDidacticTemplateLocalPolicyAction::$filter_type = self::FILTER_SOURCE_TITLE
private

Definition at line 21 of file class.ilDidacticTemplateLocalPolicyAction.php.

Referenced by getFilterType().

◆ $pattern

array ilDidacticTemplateLocalPolicyAction::$pattern = []
private

◆ $role_template_id

int ilDidacticTemplateLocalPolicyAction::$role_template_id = 0
private

Definition at line 23 of file class.ilDidacticTemplateLocalPolicyAction.php.

Referenced by getRoleTemplateId().

◆ $role_template_type

int ilDidacticTemplateLocalPolicyAction::$role_template_type = self::TPL_ACTION_OVERWRITE
private

Definition at line 22 of file class.ilDidacticTemplateLocalPolicyAction.php.

Referenced by getRoleTemplateType().

◆ TPL_ACTION_ADD

const ilDidacticTemplateLocalPolicyAction::TPL_ACTION_ADD = 3

◆ TPL_ACTION_INTERSECT

const ilDidacticTemplateLocalPolicyAction::TPL_ACTION_INTERSECT = 2

◆ TPL_ACTION_OVERWRITE

const ilDidacticTemplateLocalPolicyAction::TPL_ACTION_OVERWRITE = 1

◆ TPL_ACTION_SUBTRACT

const ilDidacticTemplateLocalPolicyAction::TPL_ACTION_SUBTRACT = 4

◆ TPL_ACTION_UNION

const ilDidacticTemplateLocalPolicyAction::TPL_ACTION_UNION = 5

The documentation for this class was generated from the following file: