Skip to content

Commit 6303331

Browse files
committed
Merge branch 'master' into v4.0
2 parents 64798b5 + cff35dc commit 6303331

File tree

9 files changed

+172
-19
lines changed

9 files changed

+172
-19
lines changed

.github/workflows/run-integration-tests.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ jobs:
2828
fail-fast: false
2929
matrix:
3030
os: [ubuntu-latest]
31-
php: [8.1, 8.2]
31+
php: [8.1, 8.2, 8.3]
3232

3333
name: ${{ matrix.os }} - P${{ matrix.php }}
3434

@@ -37,7 +37,7 @@ jobs:
3737
uses: actions/checkout@v2
3838

3939
- name: Cache dependencies
40-
uses: actions/cache@v2
40+
uses: actions/cache@v3
4141
with:
4242
path: ~/.composer/cache/files
4343
key: dependencies-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }}

.github/workflows/run-tests.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@ jobs:
1515
fail-fast: false
1616
matrix:
1717
os: [ubuntu-latest, windows-latest]
18-
php: [8.1, 8.2]
18+
php: [8.1, 8.2, 8.3, 8.4]
1919

2020
steps:
2121
- name: Checkout code
2222
uses: actions/checkout@v2
2323

2424
- name: Cache dependencies
25-
uses: actions/cache@v2
25+
uses: actions/cache@v3
2626
with:
2727
path: ~/.composer/cache/files
2828
key: dependencies-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }}

composer.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,10 @@
3434
"ext-json": "*",
3535
"ext-iconv": "*",
3636
"psr/log": "*",
37-
"psr/simple-cache": "^1.0|^2.0|^3.0",
3837
"nesbot/carbon": "*",
39-
"illuminate/contracts": "^8.0|^9.0|^10.0|^11.0",
40-
"illuminate/collections": "^8.0|^9.0|^10.0|^11.0"
38+
"psr/simple-cache": "^1.0|^2.0|^3.0",
39+
"illuminate/contracts": "^8.0|^9.0|^10.0|^11.0|^12.0",
40+
"illuminate/collections": "^8.0|^9.0|^10.0|^11.0|^12.0"
4141
},
4242
"require-dev": {
4343
"phpunit/phpunit": "^9.0",

src/Models/Model.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -973,11 +973,18 @@ protected function performInsert(): void
973973

974974
$this->dispatch('creating');
975975

976+
// Some PHP versions prevent non-numerically indexed arrays
977+
// from being sent to the server. To resolve this, we will
978+
// convert the attributes to numerically indexed arrays.
979+
$attributes = array_map('array_values', array_filter($this->getAttributes()));
980+
976981
// Here we perform the insert of new object in the directory,
977982
// but filter out any empty attributes before sending them
978983
// to the server. LDAP servers will throw an exception if
979984
// attributes have been given empty or null values.
980-
$this->dn = $query->insertAndGetDn($this->getDn(), array_filter($this->getAttributes()));
985+
$this->dn = $query->insertAndGetDn($this->getDn(), $attributes);
986+
987+
$this->attributes = $attributes;
981988

982989
$this->dispatch('created');
983990

src/Query/Builder.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,8 @@ public function each(Closure $callback, int $pageSize = 1000, bool $isCritical =
405405
*/
406406
public function chunk(int $pageSize, Closure $callback, bool $isCritical = false, bool $isolate = false): bool
407407
{
408+
$this->limit(0);
409+
408410
$start = microtime(true);
409411

410412
$chunk = function (Builder $query) use ($pageSize, $callback, $isCritical) {

src/Query/Model/ActiveDirectoryBuilder.php

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public function findBySidOrFail(string $sid, array $columns = ['*']): Model
4040
public function whereEnabled(): static
4141
{
4242
return $this->notFilter(
43-
fn ($query) => $query->whereDisabled()
43+
fn (self $query) => $query->whereDisabled()
4444
);
4545
}
4646

@@ -60,7 +60,7 @@ public function whereDisabled(): static
6060
public function whereMember(string $dn, bool $nested = false): static
6161
{
6262
return $this->nestedMatchQuery(
63-
fn ($attribute) => $this->whereEquals($attribute, $dn),
63+
fn (string $attribute) => $this->whereEquals($attribute, $this->substituteBaseDn($dn)),
6464
'member',
6565
$nested
6666
);
@@ -72,7 +72,7 @@ public function whereMember(string $dn, bool $nested = false): static
7272
public function orWhereMember(string $dn, bool $nested = false): static
7373
{
7474
return $this->nestedMatchQuery(
75-
fn ($attribute) => $this->orWhereEquals($attribute, $dn),
75+
fn (string $attribute) => $this->orWhereEquals($attribute, $this->substituteBaseDn($dn)),
7676
'member',
7777
$nested
7878
);
@@ -84,7 +84,7 @@ public function orWhereMember(string $dn, bool $nested = false): static
8484
public function whereMemberOf(string $dn, bool $nested = false): static
8585
{
8686
return $this->nestedMatchQuery(
87-
fn ($attribute) => $this->whereEquals($attribute, $dn),
87+
fn (string $attribute) => $this->whereEquals($attribute, $this->substituteBaseDn($dn)),
8888
'memberof',
8989
$nested
9090
);
@@ -96,7 +96,7 @@ public function whereMemberOf(string $dn, bool $nested = false): static
9696
public function whereNotMemberof(string $dn, bool $nested = false): static
9797
{
9898
return $this->nestedMatchQuery(
99-
fn ($attribute) => $this->whereNotEquals($attribute, $dn),
99+
fn (string $attribute) => $this->whereNotEquals($attribute, $this->substituteBaseDn($dn)),
100100
'memberof',
101101
$nested
102102
);
@@ -108,7 +108,7 @@ public function whereNotMemberof(string $dn, bool $nested = false): static
108108
public function orWhereMemberOf(string $dn, bool $nested = false): static
109109
{
110110
return $this->nestedMatchQuery(
111-
fn ($attribute) => $this->orWhereEquals($attribute, $dn),
111+
fn (string $attribute) => $this->orWhereEquals($attribute, $this->substituteBaseDn($dn)),
112112
'memberof',
113113
$nested
114114
);
@@ -120,7 +120,7 @@ public function orWhereMemberOf(string $dn, bool $nested = false): static
120120
public function orWhereNotMemberof(string $dn, bool $nested = false): static
121121
{
122122
return $this->nestedMatchQuery(
123-
fn ($attribute) => $this->orWhereNotEquals($attribute, $dn),
123+
fn (string $attribute) => $this->orWhereNotEquals($attribute, $this->substituteBaseDn($dn)),
124124
'memberof',
125125
$nested
126126
);
@@ -132,7 +132,7 @@ public function orWhereNotMemberof(string $dn, bool $nested = false): static
132132
public function whereManager(string $dn, bool $nested = false): static
133133
{
134134
return $this->nestedMatchQuery(
135-
fn ($attribute) => $this->whereEquals($attribute, $dn),
135+
fn (string $attribute) => $this->whereEquals($attribute, $this->substituteBaseDn($dn)),
136136
'manager',
137137
$nested
138138
);
@@ -144,7 +144,7 @@ public function whereManager(string $dn, bool $nested = false): static
144144
public function whereNotManager(string $dn, bool $nested = false): static
145145
{
146146
return $this->nestedMatchQuery(
147-
fn ($attribute) => $this->whereNotEquals($attribute, $dn),
147+
fn (string $attribute) => $this->whereNotEquals($attribute, $this->substituteBaseDn($dn)),
148148
'manager',
149149
$nested
150150
);
@@ -156,7 +156,7 @@ public function whereNotManager(string $dn, bool $nested = false): static
156156
public function orWhereManager(string $dn, bool $nested = false): static
157157
{
158158
return $this->nestedMatchQuery(
159-
fn ($attribute) => $this->orWhereEquals($attribute, $dn),
159+
fn (string $attribute) => $this->orWhereEquals($attribute, $this->substituteBaseDn($dn)),
160160
'manager',
161161
$nested
162162
);
@@ -168,7 +168,7 @@ public function orWhereManager(string $dn, bool $nested = false): static
168168
public function orWhereNotManager(string $dn, bool $nested = false): static
169169
{
170170
return $this->nestedMatchQuery(
171-
fn ($attribute) => $this->orWhereNotEquals($attribute, $dn),
171+
fn (string $attribute) => $this->orWhereNotEquals($attribute, $this->substituteBaseDn($dn)),
172172
'manager',
173173
$nested
174174
);

tests/Integration/QueryTest.php

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
3+
namespace LdapRecord\Tests\Integration;
4+
5+
use Illuminate\Support\LazyCollection;
6+
use LdapRecord\Models\OpenLDAP\User;
7+
use LdapRecord\Query\Collection;
8+
use LdapRecord\Tests\Integration\Concerns\MakesUsers;
9+
use LdapRecord\Tests\Integration\Concerns\SetupTestConnection;
10+
use LdapRecord\Tests\Integration\Concerns\SetupTestOu;
11+
12+
class QueryTest extends TestCase
13+
{
14+
use MakesUsers;
15+
use SetupTestConnection;
16+
use SetupTestOu;
17+
18+
protected function setUp(): void
19+
{
20+
parent::setUp();
21+
22+
$this->setupTestOu();
23+
}
24+
25+
public function test_it_can_paginate()
26+
{
27+
foreach (LazyCollection::range(1, 10) as $index) {
28+
$this->makeUser($this->ou)->save();
29+
}
30+
31+
$this->assertCount(10, User::paginate(5));
32+
}
33+
34+
public function test_it_can_chunk()
35+
{
36+
foreach (LazyCollection::range(1, 10) as $index) {
37+
$this->makeUser($this->ou)->save();
38+
}
39+
40+
$pages = 0;
41+
42+
User::chunk(5, function (Collection $results) use (&$pages) {
43+
$pages++;
44+
45+
$this->assertCount(5, $results);
46+
});
47+
48+
$this->assertEquals(2, $pages);
49+
}
50+
51+
public function test_it_cannot_override_limit_when_chunking()
52+
{
53+
foreach (LazyCollection::range(1, 10) as $index) {
54+
$this->makeUser($this->ou)->save();
55+
}
56+
57+
$pages = 0;
58+
59+
User::limit(1)->chunk(5, function (Collection $results) use (&$pages) {
60+
$pages++;
61+
62+
$this->assertCount(5, $results);
63+
});
64+
65+
$this->assertEquals(2, $pages);
66+
}
67+
}

tests/Unit/Models/ModelTest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,28 @@ public function test_generated_dns_properly_substitute_base_on_creation()
783783
$this->assertEquals('cn=foo,dc=local,dc=com', $model->getDn());
784784
}
785785

786+
public function test_attribute_values_are_numerically_indexed_on_create()
787+
{
788+
Container::addConnection(new Connection([
789+
'base_dn' => 'dc=local,dc=com',
790+
]));
791+
792+
DirectoryFake::setup()->getLdapConnection()->expect(
793+
LdapFake::operation('add')->once()->with(fn ($dn) => true, fn ($attributes) => (
794+
collect($attributes)->every(fn ($values) => array_is_list($values))
795+
))->andReturnTrue(),
796+
);
797+
798+
$model = new Entry;
799+
800+
$model->objectclass = ['bar'];
801+
$model->cn = ['invalid' => 'John Doe'];
802+
803+
$model->save();
804+
805+
$this->assertEquals($model->cn, ['John Doe']);
806+
}
807+
786808
public function test_setting_dn_attributes_set_distinguished_name_on_model()
787809
{
788810
$this->assertEquals('foo', (new Entry(['distinguishedname' => 'foo']))->getDn());

tests/Unit/Query/Model/ActiveDirectoryTest.php

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,24 @@ public function test_where_member_of()
3232
$this->assertEquals('(memberof=cn=Accounting,dc=org,dc=acme)', $b->getUnescapedQuery());
3333
}
3434

35+
public function test_where_member_of_substitutes_base_dn()
36+
{
37+
$b = $this->newBuilder();
38+
$b->setBaseDn('dc=org,dc=acme');
39+
$b->whereMemberOf('cn=Accounting,{base}');
40+
$where = $b->filters['and'][0];
41+
$this->assertEquals('memberof', $where['field']);
42+
$this->assertEquals('=', $where['operator']);
43+
$this->assertEquals(
44+
'\63\6e\3d\41\63\63\6f\75\6e\74\69\6e\67\2c\64\63\3d\6f\72\67\2c\64\63\3d\61\63\6d\65',
45+
$where['value']
46+
);
47+
$this->assertEquals(
48+
'(memberof=cn=Accounting,dc=org,dc=acme)',
49+
$b->getUnescapedQuery()
50+
);
51+
}
52+
3553
public function test_where_member_of_nested()
3654
{
3755
$b = $this->newBuilder();
@@ -46,6 +64,24 @@ public function test_where_member_of_nested()
4664
$this->assertEquals('(memberof:1.2.840.113556.1.4.1941:=cn=Accounting,dc=org,dc=acme)', $b->getUnescapedQuery());
4765
}
4866

67+
public function test_where_member_of_nested_substitutes_base_dn()
68+
{
69+
$b = $this->newBuilder();
70+
$b->setBaseDn('dc=org,dc=acme');
71+
$b->whereMemberOf('cn=Accounting,{base}', $nested = true);
72+
$where = $b->filters['and'][0];
73+
$this->assertEquals('memberof:1.2.840.113556.1.4.1941:', $where['field']);
74+
$this->assertEquals('=', $where['operator']);
75+
$this->assertEquals(
76+
'\63\6e\3d\41\63\63\6f\75\6e\74\69\6e\67\2c\64\63\3d\6f\72\67\2c\64\63\3d\61\63\6d\65',
77+
$where['value']
78+
);
79+
$this->assertEquals(
80+
'(memberof:1.2.840.113556.1.4.1941:=cn=Accounting,dc=org,dc=acme)',
81+
$b->getUnescapedQuery()
82+
);
83+
}
84+
4985
public function test_or_where_member_of()
5086
{
5187
$b = $this->newBuilder();
@@ -64,6 +100,25 @@ public function test_or_where_member_of()
64100
);
65101
}
66102

103+
public function test_or_where_member_of_substitutes_base_dn()
104+
{
105+
$b = $this->newBuilder();
106+
$b->setBaseDn('dc=org,dc=acme');
107+
$b->orWhereEquals('cn', 'John Doe');
108+
$b->orWhereMemberOf('cn=Accounting,{base}');
109+
$where = $b->filters['or'][1];
110+
$this->assertEquals('memberof', $where['field']);
111+
$this->assertEquals('=', $where['operator']);
112+
$this->assertEquals(
113+
'\63\6e\3d\41\63\63\6f\75\6e\74\69\6e\67\2c\64\63\3d\6f\72\67\2c\64\63\3d\61\63\6d\65',
114+
$where['value']
115+
);
116+
$this->assertEquals(
117+
'(|(cn=John Doe)(memberof=cn=Accounting,dc=org,dc=acme))',
118+
$b->getUnescapedQuery()
119+
);
120+
}
121+
67122
public function test_or_where_member_of_nested()
68123
{
69124
$b = $this->newBuilder();

0 commit comments

Comments
 (0)