Skip to content
This repository has been archived by the owner on Jan 6, 2023. It is now read-only.

Commit

Permalink
fix replacing a file
Browse files Browse the repository at this point in the history
Fixes #54
  • Loading branch information
wellingguzman committed Apr 11, 2018
1 parent 69719b6 commit ec804bb
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 66 deletions.
74 changes: 45 additions & 29 deletions src/core/Directus/Application/CoreServicesProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -301,50 +301,66 @@ protected function getEmitter()

return $payload;
}, Emitter::P_HIGH);
$emitter->addFilter('collection.update:before', function (Payload $payload) use ($container) {
$savesFile = function (Payload $payload, $replace = false) use ($container) {
$collectionName = $payload->attribute('collection_name');
if ($collectionName !== SchemaManager::COLLECTION_FILES) {
return null;
}

if ($replace === true && !$payload->has('data')) {
return null;
}

/** @var Acl $auth */
$acl = $container->get('acl');
$data = $payload->getData();

/** @var \Directus\Filesystem\Files $files */
$files = $container->get('files');

if (array_key_exists('data', $data) && filter_var($data['data'], FILTER_VALIDATE_URL)) {
$dataInfo = $files->getLink($data['data']);
} else {
$dataInfo = $files->getDataInfo($data['data']);
}

$type = ArrayUtils::get($dataInfo, 'type', ArrayUtils::get($data, 'type'));

if (strpos($type, 'embed/') === 0) {
$recordData = $files->saveEmbedData($dataInfo);
} else {
$recordData = $files->saveData($payload['data'], $payload['filename'], $replace);
}

$payload->replace(array_merge($recordData, ArrayUtils::omit($data, 'filename')));
$payload->remove('data');
$payload->set('upload_user', $acl->getUserId());
$payload->set('upload_date', DateTimeUtils::nowInUTC()->toString());
};
$emitter->addFilter('collection.update:before', function (Payload $payload) use ($container, $savesFile) {
$collection = SchemaService::getCollection($payload->attribute('collection_name'));

/** @var Acl $acl */
$acl = $container->get('acl');
if ($dateModified = $collection->getDateUpdateField()) {
$payload[$dateModified] = DateTimeUtils::nowInUTC()->toString();
}

if ($userModified = $collection->getUserUpdateField()) {
$payload[$userModified] = $acl->getUserId();
}

// NOTE: exclude date_uploaded from updating a file record
if ($collection->getName() === 'directus_files') {
$payload->remove('date_uploaded');
}
return $payload;
}, Emitter::P_HIGH);
$emitter->addFilter('collection.insert:before', function (Payload $payload) use ($container) {
if ($payload->attribute('collection_name') === 'directus_files') {
/** @var Acl $auth */
$acl = $container->get('acl');
$data = $payload->getData();

/** @var \Directus\Filesystem\Files $files */
$files = $container->get('files');

if (array_key_exists('data', $data) && filter_var($data['data'], FILTER_VALIDATE_URL)) {
$dataInfo = $files->getLink($data['data']);
} else {
$dataInfo = $files->getDataInfo($data['data']);
}
$savesFile($payload, true);

$type = ArrayUtils::get($dataInfo, 'type', ArrayUtils::get($data, 'type'));

if (strpos($type, 'embed/') === 0) {
$recordData = $files->saveEmbedData($dataInfo);
} else {
$recordData = $files->saveData($payload['data'], $payload['filename']);
}

$payload->replace(array_merge($recordData, ArrayUtils::omit($data, 'filename')));
$payload->remove('data');
$payload->set('upload_user', $acl->getUserId());
$payload->set('upload_date', DateTimeUtils::nowInUTC()->toString());
}
return $payload;
}, Emitter::P_HIGH);
$emitter->addFilter('collection.insert:before', function (Payload $payload) use ($savesFile) {
$savesFile($payload, false);

return $payload;
});
Expand Down
80 changes: 54 additions & 26 deletions src/core/Directus/Database/TableGateway/BaseTableGateway.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use Directus\Database\TableGatewayFactory;
use Directus\Database\SchemaService;
use Directus\Exception\Exception;
use Directus\Filesystem\Files;
use Directus\Filesystem\Thumbnail;
use Directus\Permissions\Acl;
use Directus\Permissions\Exception\ForbiddenCollectionDeleteException;
Expand Down Expand Up @@ -343,40 +344,32 @@ public function addOrUpdateRecordByArray(array $recordData, $collectionName = nu
$primaryKey = $TableGateway->primaryKeyFieldName;
$hasPrimaryKeyData = isset($recordData[$primaryKey]);
$rowExists = false;
$currentItem = null;
$originalFilename = null;

if ($hasPrimaryKeyData) {
$select = new Select($collectionName);
$select->columns([$primaryKey]);
$select->columns(['*']);
$select->where([
$primaryKey => $recordData[$primaryKey]
]);
$select->limit(1);
$rowExists = $TableGateway->ignoreFilters()->selectWith($select)->count() > 0;
}

if ($rowExists) {
$Update = new Update($collectionName);
$Update->set($recordData);
$Update->where([
$primaryKey => $recordData[$primaryKey]
]);
$TableGateway->updateWith($Update);

$this->runHook('postUpdate', [$TableGateway, $recordData, $this->adapter, null]);
} else {
$recordData = $this->applyHook('collection.insert:before', $recordData, [
'collection_name' => $collectionName
]);
$recordData = $this->applyHook('collection.insert.' . $collectionName . ':before', $recordData);
$TableGateway->insert($recordData);
$result = $TableGateway->ignoreFilters()->selectWith($select);
$rowExists = $result->count() > 0;
if ($rowExists) {
$currentItem = $result->current()->toArray();
}

// Only get the last inserted id, if the column has auto increment value
$columnObject = $this->getTableSchema()->getField($primaryKey);
if ($columnObject->hasAutoIncrement()) {
$recordData[$primaryKey] = $TableGateway->getLastInsertValue();
if ($collectionName === SchemaManager::COLLECTION_FILES) {
$originalFilename = ArrayUtils::get($currentItem, 'filename');
$recordData = array_merge([
'filename' => $originalFilename
], $recordData);
}
}

if ($collectionName == 'directus_files' && static::$container) {
$afterAction = function ($collectionName, $recordData, $replace = false) use ($TableGateway) {
if ($collectionName == SchemaManager::COLLECTION_FILES && static::$container) {
$Files = static::$container->get('files');
$ext = $thumbnailExt = pathinfo($recordData['filename'], PATHINFO_EXTENSION);

Expand All @@ -388,12 +381,12 @@ public function addOrUpdateRecordByArray(array $recordData, $collectionName = nu

$thumbnailPath = 'thumbs/THUMB_' . $recordData['filename'];
if ($Files->exists($thumbnailPath)) {
$Files->rename($thumbnailPath, 'thumbs/' . $recordData[$this->primaryKeyFieldName] . '.' . $thumbnailExt);
$Files->rename($thumbnailPath, 'thumbs/' . $recordData[$this->primaryKeyFieldName] . '.' . $thumbnailExt, $replace);
}

$updateArray = [];
if ($Files->getSettings('file_naming') == 'file_id') {
$Files->rename($recordData['filename'], str_pad($recordData[$this->primaryKeyFieldName], 11, '0', STR_PAD_LEFT) . '.' . $ext);
$Files->rename($recordData['filename'], str_pad($recordData[$this->primaryKeyFieldName], 11, '0', STR_PAD_LEFT) . '.' . $ext, $replace);
$updateArray['filename'] = str_pad($recordData[$this->primaryKeyFieldName], 11, '0', STR_PAD_LEFT) . '.' . $ext;
$recordData['filename'] = $updateArray['filename'];
}
Expand All @@ -405,6 +398,41 @@ public function addOrUpdateRecordByArray(array $recordData, $collectionName = nu
$TableGateway->updateWith($Update);
}
}
};

if ($rowExists) {
$Update = new Update($collectionName);
$Update->set($recordData);
$Update->where([
$primaryKey => $recordData[$primaryKey]
]);
$TableGateway->updateWith($Update);

if ($collectionName == 'directus_files' && static::$container) {
if ($originalFilename && $recordData['filename'] !== $originalFilename) {
/** @var Files $Files */
$Files = static::$container->get('files');
$Files->delete(['filename' => $originalFilename]);
}
}

$afterAction($collectionName, $recordData, true);

$this->runHook('postUpdate', [$TableGateway, $recordData, $this->adapter, null]);
} else {
$recordData = $this->applyHook('collection.insert:before', $recordData, [
'collection_name' => $collectionName
]);
$recordData = $this->applyHook('collection.insert.' . $collectionName . ':before', $recordData);
$TableGateway->insert($recordData);

// Only get the last inserted id, if the column has auto increment value
$columnObject = $this->getTableSchema()->getField($primaryKey);
if ($columnObject->hasAutoIncrement()) {
$recordData[$primaryKey] = $TableGateway->getLastInsertValue();
}

$afterAction($collectionName, $recordData);

$this->runHook('postInsert', [$TableGateway, $recordData, $this->adapter, null]);
}
Expand Down
40 changes: 29 additions & 11 deletions src/core/Directus/Filesystem/Files.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Directus\Filesystem;

use Directus\Application\Application;
use Directus\Exception\Exception;
use Directus\Filesystem\Exception\ForbiddenException;
use Directus\Util\DateTimeUtils;
use Directus\Util\Formatting;
Expand Down Expand Up @@ -59,8 +60,12 @@ public function exists($path)
return $this->filesystem->getAdapter()->has($path);
}

public function rename($path, $newPath)
public function rename($path, $newPath, $replace = false)
{
if ($replace === true && $this->filesystem->exists($newPath)) {
$this->filesystem->getAdapter()->delete($newPath);
}

return $this->filesystem->getAdapter()->rename($path, $newPath);
}

Expand All @@ -73,7 +78,7 @@ public function delete($file)
}

$ext = pathinfo($file['filename'], PATHINFO_EXTENSION);
if ($ext) {
if ($ext && isset($file['id'])) {
$thumbPath = 'thumbs/' . $file['id'] . '.' . $ext;
if ($this->exists($thumbPath)) {
$this->emitter->run('files.thumbnail.deleting', [$file]);
Expand Down Expand Up @@ -245,23 +250,25 @@ public function getDataInfo($data)
*
* @param string $fileData - base64 data
* @param string $fileName - name of the file
* @param bool $replace
*
* @return array
*/
public function saveData($fileData, $fileName)
public function saveData($fileData, $fileName, $replace = false)
{
$fileData = base64_decode($this->getDataInfo($fileData)['data']);

// @TODO: merge with upload()
$fileName = $this->getFileName($fileName);
$fileName = $this->getFileName($fileName, $replace !== true);

$filePath = $this->getConfig('root') . '/' . $fileName;

$this->emitter->run('files.saving', ['name' => $fileName, 'size' => strlen($fileData)]);
$this->write($fileName, $fileData);
$this->write($fileName, $fileData, $replace);
$this->emitter->run('files.saving:after', ['name' => $fileName, 'size' => strlen($fileData)]);

unset($fileData);
$this->createThumbnails($fileName);
$this->createThumbnails($fileName, $replace);

$fileData = $this->getFileInfo($fileName);
$fileData['title'] = Formatting::fileNameToFileTitle($fileName);
Expand Down Expand Up @@ -434,10 +441,11 @@ public function getConfig($key = '')
*
* TODO: it should return thumbnail info.
* @param string $imageName - the name of the image. it must exists on files.
* @param bool $replace
*
* @return void
*/
private function createThumbnails($imageName)
private function createThumbnails($imageName, $replace = false)
{
$targetFileName = $this->filesystem->getPath($imageName);
$info = pathinfo($targetFileName);
Expand All @@ -451,7 +459,7 @@ private function createThumbnails($imageName)
$thumbnailTempName = 'thumbs/THUMB_' . $imageName;
$thumbImg = Thumbnail::writeImage($info['extension'], $thumbnailTempName, $img, $this->getSettings('thumbnail_quality'));
$this->emitter->run('files.thumbnail.saving', ['name' => $imageName, 'size' => strlen($thumbImg)]);
$this->write($thumbnailTempName, $thumbImg);
$this->write($thumbnailTempName, $thumbImg, $replace);
$this->emitter->run('files.thumbnail.saving:after', ['name' => $imageName, 'size' => strlen($thumbImg)]);
}
}
Expand All @@ -462,15 +470,20 @@ private function createThumbnails($imageName)
*
* @param $location
* @param $data
* @param bool $replace
*
* @throws \RuntimeException
*/
public function write($location, $data)
public function write($location, $data, $replace = false)
{
$throwException = function () use ($location) {
throw new ForbiddenException(sprintf('No permission to write: %s', $location));
};

if ($replace === true && $this->filesystem->exists($location)) {
$this->filesystem->getAdapter()->delete($location);
}

try {
if (!$this->filesystem->getAdapter()->write($location, $data)) {
$throwException();
Expand Down Expand Up @@ -591,18 +604,23 @@ private function uniqueName($fileName, $targetPath, $attempt = 0)
* Get file name based on file naming setting
*
* @param string $fileName
* @param bool $unique
*
* @return string
*/
private function getFileName($fileName)
private function getFileName($fileName, $unique = true)
{
switch ($this->getSettings('file_naming')) {
case 'file_hash':
$fileName = $this->hashFileName($fileName);
break;
}

return $this->uniqueName($fileName, $this->filesystem->getPath());
if ($unique) {
$fileName = $this->uniqueName($fileName, $this->filesystem->getPath());
}

return $fileName;
}

/**
Expand Down

0 comments on commit ec804bb

Please sign in to comment.