Skip to content

Commit aee88b0

Browse files
authored
Merge pull request #399 from josegonzalez/field-value-replacement
Add support for field-value replacements
2 parents 389a36e + 72cb7af commit aee88b0

File tree

3 files changed

+84
-5
lines changed

3 files changed

+84
-5
lines changed

docs/configuration.rst

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,19 @@ passed in under each field in your behavior configuration.
2828
- {DS}: Replaced by a ``DIRECTORY_SEPARATOR``
2929
- {model}: Replaced by the Table-alias() method.
3030
- {table}: Replaced by the Table->table() method.
31-
- {field}: Replaced by the field name.
31+
- {field}: Replaced by the name of the field which will store
32+
the upload filename.
33+
- {field-value:(\w+)}: Replaced by value contained in the
34+
current entity in the specified field. As an example, if
35+
your path has ``{field-value:unique_id}`` and the entity
36+
being saved has a value of ``4b3403665fea6`` for the field
37+
``unique_id``, then ``{field-value:unique_id}`` will be
38+
replaced with ``4b3403665fea6``. This replacement can be used
39+
multiple times for one or more fields. If the value is not
40+
a string or zero-length, a LogicException will be thrown.
3241
- {primaryKey}: Replaced by the entity primary key, when
33-
available. If used on a new record being created, will have
34-
undefined behavior.
42+
available. If used on a new record being created, a
43+
LogicException will be thrown.
3544
- {year}: Replaced by ``date('Y')``
3645
- {month}: Replaced by ``date('m')``
3746
- {day}: Replaced by ``date('d')``

src/File/Path/Basepath/DefaultTrait.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,21 @@ public function basepath()
4040
'{DS}' => DIRECTORY_SEPARATOR,
4141
];
4242

43+
if (preg_match_all("/{field-value:(\w+)}/", $path, $matches)) {
44+
foreach ($matches[1] as $field) {
45+
$value = $this->entity->get($field);
46+
if ($value === null) {
47+
throw new LogicException(sprintf('Field value for substitution is missing: %s', $field));
48+
}if (!is_scalar($value)) {
49+
throw new LogicException(sprintf('Field value for substitution must be a integer, float, string or boolean: %s', $field));
50+
} elseif (strlen($value) < 1) {
51+
throw new LogicException(sprintf('Field value for substitution must be non-zero in length: %s', $field));
52+
}
53+
54+
$replacements[sprintf('{field-value:%s}', $field)] = $value;
55+
}
56+
}
57+
4358
return str_replace(
4459
array_keys($replacements),
4560
array_values($replacements),

tests/TestCase/File/Path/Basepath/DefaultTraitTest.php

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public function testNewEntity()
6161
$mock->data = ['name' => 'filename'];
6262
$mock->field = 'field';
6363
$mock->entity->expects($this->once())->method('isNew')->will($this->returnValue(true));
64-
$this->assertEquals('webroot/files/Table-field/1/', $mock->basepath());
64+
$mock->basepath();
6565
}
6666

6767
public function testExitingEntityWithCompositePrimaryKey()
@@ -76,7 +76,7 @@ public function testExitingEntityWithCompositePrimaryKey()
7676
$mock->field = 'field';
7777
$mock->entity->expects($this->once())->method('isNew')->will($this->returnValue(false));
7878
$mock->table->expects($this->once())->method('primaryKey')->will($this->returnValue(['id', 'other_id']));
79-
$this->assertEquals('webroot/files/Table-field/1/', $mock->basepath());
79+
$mock->basepath();
8080
}
8181

8282
public function testYearWithMonthPath()
@@ -118,4 +118,59 @@ public function testModelFieldYearWithMonthAndDayPath()
118118

119119
$this->assertEquals('webroot/files/Table/field/' . date("Y") . '/' . date("m") . '/' . date("d") . '/', $mock->basepath());
120120
}
121+
122+
public function testFieldValueMissing()
123+
{
124+
$this->setExpectedException('LogicException', 'Field value for substitution is missing: field');
125+
126+
$mock = $this->getMockForTrait('Josegonzalez\Upload\File\Path\Basepath\DefaultTrait');
127+
$mock->entity = $this->getMock('Cake\ORM\Entity');
128+
$mock->table = $this->getMock('Cake\ORM\Table');
129+
$mock->settings = ['path' => 'webroot{DS}files{DS}{model}{DS}{field-value:field}{DS}'];
130+
$mock->data = ['name' => 'filename'];
131+
$mock->field = 'field';
132+
$mock->entity->expects($this->any())->method('get')->will($this->returnValue(null));
133+
$mock->basepath();
134+
}
135+
136+
public function testFieldValueNonScalar()
137+
{
138+
$this->setExpectedException('LogicException', 'Field value for substitution must be a integer, float, string or boolean: field');
139+
140+
$mock = $this->getMockForTrait('Josegonzalez\Upload\File\Path\Basepath\DefaultTrait');
141+
$mock->entity = $this->getMock('Cake\ORM\Entity');
142+
$mock->table = $this->getMock('Cake\ORM\Table');
143+
$mock->settings = ['path' => 'webroot{DS}files{DS}{model}{DS}{field-value:field}{DS}'];
144+
$mock->data = ['name' => 'filename'];
145+
$mock->field = 'field';
146+
$mock->entity->expects($this->any())->method('get')->will($this->returnValue([]));
147+
$mock->basepath();
148+
}
149+
150+
public function testFieldValueZeroLength()
151+
{
152+
$this->setExpectedException('LogicException', 'Field value for substitution must be non-zero in length: field');
153+
154+
$mock = $this->getMockForTrait('Josegonzalez\Upload\File\Path\Basepath\DefaultTrait');
155+
$mock->entity = $this->getMock('Cake\ORM\Entity');
156+
$mock->table = $this->getMock('Cake\ORM\Table');
157+
$mock->settings = ['path' => 'webroot{DS}files{DS}{model}{DS}{field-value:field}{DS}'];
158+
$mock->data = ['name' => 'filename'];
159+
$mock->field = 'field';
160+
$mock->entity->expects($this->any())->method('get')->will($this->returnValue(''));
161+
$mock->basepath();
162+
}
163+
164+
public function testFieldValue()
165+
{
166+
$mock = $this->getMockForTrait('Josegonzalez\Upload\File\Path\Basepath\DefaultTrait');
167+
$mock->entity = $this->getMock('Cake\ORM\Entity');
168+
$mock->table = $this->getMock('Cake\ORM\Table');
169+
$mock->settings = ['path' => 'webroot{DS}files{DS}{model}{DS}{field-value:field}{DS}'];
170+
$mock->data = ['name' => 'filename'];
171+
$mock->field = 'field';
172+
$mock->entity->expects($this->any())->method('get')->will($this->returnValue('value'));
173+
$mock->table->expects($this->once())->method('alias')->will($this->returnValue('Table'));
174+
$this->assertEquals('webroot/files/Table/value/', $mock->basepath());
175+
}
121176
}

0 commit comments

Comments
 (0)