blob: 652ad563f9ce01857acad3466e245451fb9359c8 [file] [log] [blame]
Matthias Andreas Benkard7b2a3a12021-08-16 10:57:25 +02001<?php
2
3namespace LdapRecord\Models\ActiveDirectory;
4
5use InvalidArgumentException;
6use LdapRecord\Connection;
7use LdapRecord\Models\Attributes\Sid;
8use LdapRecord\Models\Entry as BaseEntry;
9use LdapRecord\Models\Events\Updated;
10use LdapRecord\Models\Types\ActiveDirectory;
11use LdapRecord\Query\Model\ActiveDirectoryBuilder;
12
13/** @mixin ActiveDirectoryBuilder */
14class Entry extends BaseEntry implements ActiveDirectory
15{
16 /**
17 * The default attributes that should be mutated to dates.
18 *
19 * @var array
20 */
21 protected $defaultDates = [
22 'whenchanged' => 'windows',
23 'whencreated' => 'windows',
24 'dscorepropagationdata' => 'windows',
25 ];
26
27 /**
28 * The attribute key that contains the Object SID.
29 *
30 * @var string
31 */
32 protected $sidKey = 'objectsid';
33
34 /**
35 * @inheritdoc
36 */
37 public function getObjectSidKey()
38 {
39 return $this->sidKey;
40 }
41
42 /**
43 * @inheritdoc
44 */
45 public function getObjectSid()
46 {
47 return $this->getFirstAttribute($this->sidKey);
48 }
49
50 /**
51 * @inheritdoc
52 */
53 public function getConvertedSid()
54 {
55 try {
56 return (string) new Sid($this->getObjectSid());
57 } catch (InvalidArgumentException $e) {
58 return;
59 }
60 }
61
62 /**
63 * Create a new query builder.
64 *
65 * @param Connection $connection
66 *
67 * @return ActiveDirectoryBuilder
68 */
69 public function newQueryBuilder(Connection $connection)
70 {
71 return new ActiveDirectoryBuilder($connection);
72 }
73
74 /**
75 * Determine if the object is deleted.
76 *
77 * @return bool
78 */
79 public function isDeleted()
80 {
Matthias Andreas Benkard1ba53812022-12-27 17:32:58 +010081 return strtoupper((string) $this->getFirstAttribute('isDeleted')) === 'TRUE';
Matthias Andreas Benkard7b2a3a12021-08-16 10:57:25 +020082 }
83
84 /**
85 * Restore a deleted object.
86 *
87 * @param string|null $newParentDn
88 *
Matthias Andreas Benkard7b2a3a12021-08-16 10:57:25 +020089 * @return bool
Matthias Andreas Benkard1ba53812022-12-27 17:32:58 +010090 *
91 * @throws \LdapRecord\LdapRecordException
Matthias Andreas Benkard7b2a3a12021-08-16 10:57:25 +020092 */
93 public function restore($newParentDn = null)
94 {
95 if (! $this->isDeleted()) {
96 return false;
97 }
98
99 $root = $newParentDn ?? $this->getDefaultRestoreLocation();
100 $rdn = explode('\0A', $this->getDn(), 2)[0];
101 $newDn = implode(',', [$rdn, $root]);
102
103 // We will initialize a model listener for the "updated" event to set
104 // the models distinguished name so all attributes are synchronized
105 // properly after the model has been successfully restored.
106 $this->listenForModelEvent(Updated::class, function (Updated $event) use ($newDn) {
107 if ($this->is($event->getModel())) {
108 $this->setDn($newDn);
109 }
110 });
111
Matthias Andreas Benkard1ba53812022-12-27 17:32:58 +0100112 $this->setRawAttribute('distinguishedname', $newDn);
113
114 $this->save(['isDeleted' => null]);
Matthias Andreas Benkard7b2a3a12021-08-16 10:57:25 +0200115 }
116
117 /**
118 * Get the RootDSE (AD schema) record from the directory.
119 *
120 * @param string|null $connection
121 *
Matthias Andreas Benkard7b2a3a12021-08-16 10:57:25 +0200122 * @return static
Matthias Andreas Benkard1ba53812022-12-27 17:32:58 +0100123 *
124 * @throws \LdapRecord\Models\ModelNotFoundException
Matthias Andreas Benkard7b2a3a12021-08-16 10:57:25 +0200125 */
126 public static function getRootDse($connection = null)
127 {
128 return static::on($connection ?? (new static())->getConnectionName())
129 ->in(null)
130 ->read()
131 ->whereHas('objectclass')
132 ->firstOrFail();
133 }
134
135 /**
136 * Get the objects restore location.
137 *
138 * @return string
139 */
140 protected function getDefaultRestoreLocation()
141 {
142 return $this->getFirstAttribute('lastKnownParent') ?? $this->getParentDn($this->getParentDn($this->getDn()));
143 }
144
145 /**
146 * Converts attributes for JSON serialization.
147 *
148 * @param array $attributes
149 *
150 * @return array
151 */
152 protected function convertAttributesForJson(array $attributes = [])
153 {
154 $attributes = parent::convertAttributesForJson($attributes);
155
156 if ($this->hasAttribute($this->sidKey)) {
157 // If the model has a SID set, we need to convert it due to it being in
158 // binary. Otherwise we will receive a JSON serialization exception.
159 return array_replace($attributes, [
160 $this->sidKey => [$this->getConvertedSid()],
161 ]);
162 }
163
164 return $attributes;
165 }
166}