Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanup statuses #34

Merged
merged 13 commits into from
Apr 16, 2023
2 changes: 0 additions & 2 deletions demos/_demo-data/create-db.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@
$fileModel->addField('token', ['required' => true]);
$fileModel->addField('location', ['type' => 'text']);
$fileModel->addField('url', ['type' => 'text']);
$fileModel->addField('storage');
$fileModel->addField('status');
$fileModel->addField('source_file_id', ['type' => 'integer']);
$fileModel->addField('meta_filename');
$fileModel->addField('meta_extension');
$fileModel->addField('meta_md5');
Expand Down
36 changes: 23 additions & 13 deletions demos/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@
use Atk4\Filestore\Model\File;
use Atk4\Ui\Callback;
use Atk4\Ui\Columns;
use Atk4\Ui\Crud;
use Atk4\Ui\Form;
use Atk4\Ui\Grid;
use Atk4\Ui\Header;
use Atk4\Ui\Js\JsExpression;
use Atk4\Ui\View;
use League\Flysystem\Filesystem;
Expand All @@ -34,34 +37,41 @@
$adapter = new \League\Flysystem\Local\LocalFilesystemAdapter(__DIR__ . '/_demo-data/localfiles');
$filesystem = new Filesystem($adapter);

$col = Columns::addTo($app);
$columnsLayout = Columns::addTo($app);

$form = Form::addTo($col->addColumn());
// new friend form
$c1 = $columnsLayout->addColumn();
Header::addTo($c1, ['Add New Friend']);
$form = Form::addTo($c1);
$form->setModel(
(new Friend($app->db, [
'filesystem' => $filesystem,
]))->createEntity()
);

$gr = \Atk4\Ui\Grid::addTo($col->addColumn(), [
'menu' => false,
'paginator' => false,
]);
$gr->setModel(new File($app->db));

$form->onSubmit(function (Form $form) use ($gr) {
$form->onSubmit(function (Form $form) use ($app) {
$form->model->save();

return $gr->jsReload();
return $app->layout->jsReload();
});

// list all filestore files
$c2 = $columnsLayout->addColumn();
Header::addTo($c2, ['All Filestore Files']);
$gr = Grid::addTo($c2, [
'paginator' => false,
]);
$files = new File($app->db, ['flysystem' => $filesystem]);
$gr->setModel($files);

View::addTo($app, ['ui' => 'divider']);

$crud = \Atk4\Ui\Crud::addTo($app);
// CRUD with all Friends records
Header::addTo($app, ['All Friends']);
$crud = Crud::addTo($app);
$crud->setModel(new Friend($app->db, ['filesystem' => $filesystem]));

View::addTo($app, ['ui' => 'divider']);

// custom actions
$callbackDownload = Callback::addTo($app);
$callbackDownload->set(function () use ($crud) {
$id = $crud->getApp()->stickyGet('row_id');
Expand Down
9 changes: 6 additions & 3 deletions src/Field/FileField.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ protected function init(): void
$this->fieldNameBase = preg_replace('~_id$~', '', $this->shortName);
$this->importFields();

$this->onHookToOwnerEntity(Model::HOOK_AFTER_SAVE, function (Model $m) {
// on insert/update delete old file and mark new one as linked
$fx = function (Model $m) {
if ($m->isDirty($this->shortName)) {
$old = $m->getDirtyRef()[$this->shortName];
$new = $m->get($this->shortName);
Expand All @@ -71,10 +72,12 @@ protected function init(): void

// mark new file as linked
if ($new) {
$m->refModel($this->shortName)->loadBy('token', $new)->save(['status' => 'linked']);
$m->refModel($this->shortName)->loadBy('token', $new)->save(['status' => File::STATUS_LINKED]);
}
}
});
};
$this->onHookToOwnerEntity(Model::HOOK_AFTER_INSERT, $fx);
DarkSide666 marked this conversation as resolved.
Show resolved Hide resolved
$this->onHookToOwnerEntity(Model::HOOK_AFTER_UPDATE, $fx);

$this->onHookToOwnerEntity(Model::HOOK_AFTER_DELETE, function (Model $m) {
$token = $m->get($this->shortName);
Expand Down
2 changes: 1 addition & 1 deletion src/Form/Control/Upload.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ protected function deleted(string $token): ?JsExpressionable
$model = $this->entityField->getField()->fileModel;
$entity = $model->loadBy('token', $token);

if ($entity->get('status') === 'draft') {
if ($entity->get('status') === $entity::STATUS_DRAFT) {
$entity->delete();
}

Expand Down
34 changes: 17 additions & 17 deletions src/Helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,38 +13,38 @@ class Helper
/**
* @return never
*/
public static function download(File $model, App $app): void
protected static function terminate(File $model, App $app): void
{
$app->setResponseHeader('Content-Description', 'File Transfer');
$app->setResponseHeader('Content-Type', 'application/octet-stream');
$app->setResponseHeader('Cache-Control', 'must-revalidate');
$app->setResponseHeader('Expires', '-1');
$app->setResponseHeader('Content-Disposition', 'attachment; filename="' . $model->get('meta_filename') . '"');
$app->setResponseHeader('Content-Length', (string) $model->get('meta_size'));
$app->setResponseHeader('Pragma', 'public');
$app->setResponseHeader('Accept-Ranges', 'bytes');
$path = $model->get('location');
$resource = $model->flysystem->readStream($path);
$stream = (new Psr17Factory())->createStreamFromResource($resource);

static::output($model, $app);
$app->terminate($stream);
}

/**
* @return never
*/
protected static function output(File $model, App $app): void
public static function download(File $model, App $app): void
{
$path = $model->get('location');
$resource = $model->flysystem->readStream($path);
$stream = (new Psr17Factory())->createStreamFromResource($resource);
$app->setResponseHeader('Content-Description', 'Download File');
$app->setResponseHeader('Content-Type', $model->get('meta_mime_type'));
$app->setResponseHeader('Cache-Control', 'must-revalidate');
$app->setResponseHeader('Expires', '-1');
$app->setResponseHeader('Content-Disposition', 'attachment; filename="' . $model->get('meta_filename') . '"');
$app->setResponseHeader('Content-Length', (string) $model->get('meta_size'));
$app->setResponseHeader('Pragma', 'public');
$app->setResponseHeader('Accept-Ranges', 'bytes');

$app->terminate($stream);
static::terminate($model, $app);
}

/**
* @return never
*/
public static function view(File $model, App $app): void
{
$app->setResponseHeader('Content-Description', 'File Transfer');
$app->setResponseHeader('Content-Description', 'View File');
$app->setResponseHeader('Content-Type', $model->get('meta_mime_type'));
$app->setResponseHeader('Cache-Control', 'must-revalidate');
$app->setResponseHeader('Expires', '-1');
Expand All @@ -53,6 +53,6 @@ public static function view(File $model, App $app): void
$app->setResponseHeader('Pragma', 'public');
$app->setResponseHeader('Accept-Ranges', 'bytes');

static::output($model, $app);
static::terminate($model, $app);
}
}
50 changes: 31 additions & 19 deletions src/Model/File.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,34 +13,30 @@ class File extends Model

public ?string $titleField = 'meta_filename';

/** All uploaded files first get this status */
public const STATUS_DRAFT = 'draft';
/** When file is linked to some other model */
public const STATUS_LINKED = 'linked';
/** @const list<string> */
public const ALL_STATUSES = [
self::STATUS_DRAFT,
self::STATUS_LINKED,
];

/** @var Filesystem */
public $flysystem;

public function newFile(): Model
{
$entity = $this->createEntity();

$entity->set('token', uniqid('token-'));
$entity->set('location', uniqid('file-') . '.bin');

return $entity;
}

protected function init(): void
{
parent::init();

$this->addField('token', ['system' => true, 'type' => 'string', 'required' => true]);
$this->addField('location');
$this->addField('url');
$this->addField('storage');
$this->hasOne('source_file_id', [
'model' => [self::class],
]);

$this->addField('status', [
'enum' => ['draft', 'uploaded', 'thumbok', 'normalok', 'ready', 'linked'],
'default' => 'draft',
'enum' => self::ALL_STATUSES,
'default' => self::STATUS_DRAFT,
]);

$this->addField('meta_filename');
Expand All @@ -52,10 +48,26 @@ protected function init(): void
$this->addField('meta_image_width', ['type' => 'integer']);
$this->addField('meta_image_height', ['type' => 'integer']);

$this->onHook(Model::HOOK_BEFORE_DELETE, function (self $m) {
if ($m->flysystem) { // @phpstan-ignore-line
$m->flysystem->delete($m->get('location'));
// delete physical file from storage after we delete DB record
$this->onHook(Model::HOOK_AFTER_DELETE, function (self $m) {
$path = $m->get('location');
if ($path && $m->flysystem->fileExists($path)) {
$m->flysystem->delete($path);
}
});
}

/**
* @return static
*/
public function newFile(): Model
{
$this->assertIsModel();

$entity = $this->createEntity();
$entity->set('token', uniqid('token-'));
$entity->set('location', uniqid('file-') . '.bin');

return $entity;
}
}