Unverified Commit fe133a4b authored by Christian Giupponi's avatar Christian Giupponi Committed by GitHub

Merge pull request #2 from AsgardCms/master

Merge from AsgardCMS 
parents f61d8660 f6df9b81
...@@ -98,4 +98,20 @@ interface BaseRepository ...@@ -98,4 +98,20 @@ interface BaseRepository
* @return bool * @return bool
*/ */
public function clearCache(); public function clearCache();
/**
* Add where statement to current builder
*
* @param string $field
* @param string|int $value
* @param string $operator
*/
public function where(string $field, $value, string $operator = null);
/**
* Eager relationship(s) loading
*
* @param array|string $relationships
*/
public function with($relationships);
} }
...@@ -220,4 +220,24 @@ abstract class BaseCacheDecorator implements BaseRepository ...@@ -220,4 +220,24 @@ abstract class BaseCacheDecorator implements BaseRepository
$this->entityName $this->entityName
); );
} }
/**
* @inheritdoc
*/
public function where(string $field, $value, string $operator = null)
{
return $this->remember(function () use ($field, $value, $operator) {
return $this->repository->where($field, $value, $operator);
});
}
/**
* @inheritdoc
*/
public function with($relationships)
{
return $this->remember(function () use ($relationships) {
return $this->repository->with($relationships);
});
}
} }
...@@ -191,4 +191,26 @@ abstract class EloquentBaseRepository implements BaseRepository ...@@ -191,4 +191,26 @@ abstract class EloquentBaseRepository implements BaseRepository
{ {
return true; return true;
} }
/**
* @inheritdoc
*/
public function where(string $field, $value, string $operator = null)
{
if ($operator === null) {
$operator = '=';
} else {
list($value, $operator) = [$operator, $value];
}
return $this->model->where($field, $operator, $value);
}
/**
* @inheritdoc
*/
public function with($relationships)
{
return $this->model->with($relationships);
}
} }
...@@ -6,21 +6,16 @@ trait NamespacedEntity ...@@ -6,21 +6,16 @@ trait NamespacedEntity
{ {
/** /**
* Returns the entity namespace. * Returns the entity namespace.
*
* @return string
*/ */
public static function getEntityNamespace() public static function getEntityNamespace(): string
{ {
return isset(static::$entityNamespace) ? static::$entityNamespace : get_called_class(); return isset(static::$entityNamespace) ? static::$entityNamespace : get_called_class();
} }
/** /**
* Sets the entity namespace. * Sets the entity namespace.
*
* @param string $namespace
* @return void
*/ */
public static function setEntityNamespace($namespace) public static function setEntityNamespace(string $namespace)
{ {
static::$entityNamespace = $namespace; static::$entityNamespace = $namespace;
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<div class="row" style="margin-top: -35px;"> <div class="row" style="margin-top: -35px;">
<div class="col-xs-12"> <div class="col-xs-12">
<div class="sc-table"> <div class="sc-table">
<div class="el-row"> <div class="el-row">
<div class="title"> <div class="title">
<h4 v-if="singleModal">{{ trans('media.choose file') }}</h4> <h4 v-if="singleModal">{{ trans('media.choose file') }}</h4>
<h3 v-if="! singleModal">{{ trans('media.title.media') }}</h3> <h3 v-if="! singleModal">{{ trans('media.title.media') }}</h3>
...@@ -19,25 +19,38 @@ ...@@ -19,25 +19,38 @@
</div> </div>
<div class="box box-primary"> <div class="box box-primary">
<div class="box-body"> <div class="box-body">
<upload-zone v-if="showUploadZone" :parent-id="folderId"></upload-zone>
<div class="tool-bar el-row" style="padding-bottom: 20px;"> <div class="tool-bar el-row" style="padding-bottom: 20px;">
<div class="actions el-col el-col-14"> <div class="actions el-col el-col-19">
<new-folder :parent-id="folderId"></new-folder> <new-folder :parent-id="folderId"></new-folder>
<upload-button :parent-id="folderId"></upload-button> <div style="margin: 0 15px;">
<el-button-group style="width: 30%"> <el-button
<el-button type="warning" type="primary"
:disabled="selectedMedia.length === 0" @click="toggleUploadZone"
@click="showMoveMedia" >
>{{ trans('core.move') }} {{ trans('media.upload file') }}
</el-button> </el-button>
<el-button type="danger" :disabled="selectedMedia.length === 0" </div>
@click.prevent="batchDelete" :loading="filesAreDeleting"> <el-button-group>
<el-button
type="warning"
:disabled="selectedMedia.length === 0"
@click="showMoveMedia"
>
{{ trans('core.move') }}
</el-button>
<el-button
type="danger"
:disabled="selectedMedia.length === 0"
@click.prevent="batchDelete"
:loading="filesAreDeleting"
>
{{ trans('core.button.delete') }} {{ trans('core.button.delete') }}
</el-button> </el-button>
</el-button-group> </el-button-group>
</div> </div>
<div class="search el-col el-col-5"> <div class="search el-col el-col-5">
<el-input prefix-icon="el-icon-search" @keyup.native="performSearch" v-model="searchQuery"> <el-input prefix-icon="el-icon-search" @keyup.native="performSearch" v-model="searchQuery"></el-input>
</el-input>
</div> </div>
</div> </div>
<el-row> <el-row>
...@@ -50,59 +63,55 @@ ...@@ -50,59 +63,55 @@
</el-col> </el-col>
</el-row> </el-row>
<el-table <el-table
:data="data" :data="data"
stripe stripe
style="width: 100%" style="width: 100%"
ref="mediaTable" ref="mediaTable"
v-loading.body="tableIsLoading" v-loading.body="tableIsLoading"
@sort-change="handleSortChange" @sort-change="handleSortChange"
@selection-change="handleSelectionChange"> @selection-change="handleSelectionChange"
<el-table-column >
type="selection" <el-table-column type="selection" width="55"></el-table-column>
width="55">
</el-table-column>
<el-table-column label="" width="150"> <el-table-column label="" width="150">
<template slot-scope="scope"> <template slot-scope="scope">
<img :src="scope.row.small_thumb" alt="" v-if="scope.row.is_image"/> <img :src="scope.row.small_thumb" alt="" v-if="scope.row.is_image"/>
<i :class="`fa ${scope.row.fa_icon}`" style="font-size: 38px;" <i :class="`fa ${scope.row.fa_icon}`" style="font-size: 38px;" v-if="! scope.row.is_image && ! scope.row.is_folder"></i>
v-if="! scope.row.is_image && ! scope.row.is_folder"></i> <i class="fa fa-folder" style="font-size: 38px;" v-if="scope.row.is_folder"></i>
<i class="fa fa-folder" style="font-size: 38px;"
v-if="scope.row.is_folder"></i>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="filename" :label="trans('media.table.filename')" sortable="custom"> <el-table-column prop="filename" :label="trans('media.table.filename')" sortable="custom">
<template slot-scope="scope"> <template slot-scope="scope">
<strong v-if="scope.row.is_folder" style="cursor: pointer;" @click="enterFolder(scope)"> <strong v-if="scope.row.is_folder" style="cursor: pointer;" @click="enterFolder(scope)">
{{ scope.row.filename }} {{ scope.row.filename }}
</strong> </strong>
<span v-else> <span v-else>
<a href="#" <a href="#" @click.prevent="goToEdit(scope)">{{ scope.row.filename }}</a>
@click.prevent="goToEdit(scope)">{{ scope.row.filename }}</a>
</span> </span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="created_at" :label="trans('core.table.created at')" sortable="custom" <el-table-column prop="created_at" :label="trans('core.table.created at')" sortable="custom" width="150"></el-table-column>
width="150">
</el-table-column>
<el-table-column prop="actions" label="" width="150"> <el-table-column prop="actions" label="" width="150">
<template slot-scope="scope"> <template slot-scope="scope">
<div class="pull-right"> <div class="pull-right">
<el-button <el-button
type="primary" type="primary"
size="small" size="small"
@click.prevent="insertMedia(scope)" @click.prevent="insertMedia(scope)"
v-if="singleModal && ! scope.row.is_folder"> v-if="singleModal && ! scope.row.is_folder"
>
{{ trans('media.insert') }} {{ trans('media.insert') }}
</el-button> </el-button>
<div v-if="! singleModal"> <div v-if="! singleModal">
<el-button-group> <el-button-group>
<edit-button :to="{name: 'admin.media.media.edit', params: {mediaId: scope.row.id}}" <edit-button
v-if="! scope.row.is_folder"></edit-button> :to="{name: 'admin.media.media.edit', params: {mediaId: scope.row.id}}"
v-if="! scope.row.is_folder"
></edit-button>
<el-button <el-button
size="mini" size="mini"
@click.prevent="showEditFolder(scope.row)" @click.prevent="showEditFolder(scope.row)"
v-if="scope.row.is_folder && canEditFolders"> v-if="scope.row.is_folder && canEditFolders"
>
<i class="fa fa-pencil"></i> <i class="fa fa-pencil"></i>
</el-button> </el-button>
<delete-button :scope="scope" :rows="data"></delete-button> <delete-button :scope="scope" :rows="data"></delete-button>
...@@ -114,14 +123,14 @@ ...@@ -114,14 +123,14 @@
</el-table> </el-table>
<div class="pagination-wrap" style="text-align: center; padding-top: 20px;"> <div class="pagination-wrap" style="text-align: center; padding-top: 20px;">
<el-pagination <el-pagination
@size-change="handleSizeChange" @size-change="handleSizeChange"
@current-change="handleCurrentChange" @current-change="handleCurrentChange"
:current-page.sync="meta.current_page" :current-page.sync="meta.current_page"
:page-sizes="[10, 20, 50, 100]" :page-sizes="[10, 20, 50, 100]"
:page-size="parseInt(meta.per_page)" :page-size="parseInt(meta.per_page)"
layout="total, sizes, prev, pager, next, jumper" layout="total, sizes, prev, pager, next, jumper"
:total="meta.total"> :total="meta.total"
</el-pagination> ></el-pagination>
</div> </div>
</div> </div>
</div> </div>
...@@ -135,14 +144,14 @@ ...@@ -135,14 +144,14 @@
<script> <script>
import axios from 'axios'; import axios from 'axios';
import NewFolder from './NewFolder.vue'; import NewFolder from './NewFolder.vue';
import UploadButton from './UploadButton.vue'; import UploadZone from './UploadZone';
import RenameFolder from './RenameFolder.vue'; import RenameFolder from './RenameFolder.vue';
import MoveMediaDialog from './MoveMediaDialog.vue'; import MoveMediaDialog from './MoveMediaDialog.vue';
export default { export default {
components: { components: {
'new-folder': NewFolder, 'new-folder': NewFolder,
'upload-button': UploadButton, 'upload-zone': UploadZone,
'rename-folder': RenameFolder, 'rename-folder': RenameFolder,
'move-dialog': MoveMediaDialog, 'move-dialog': MoveMediaDialog,
}, },
...@@ -169,6 +178,7 @@ ...@@ -169,6 +178,7 @@
folderBreadcrumb: [ folderBreadcrumb: [
{ id: 0, name: 'Home' }, { id: 0, name: 'Home' },
], ],
showUploadZone: false,
filesAreDeleting: false, filesAreDeleting: false,
canEditFolders: true, canEditFolders: true,
}; };
...@@ -190,7 +200,6 @@ ...@@ -190,7 +200,6 @@
this.data = response.data.data; this.data = response.data.data;
this.meta = response.data.meta; this.meta = response.data.meta;
this.links = response.data.links; this.links = response.data.links;
this.order_meta.order_by = properties.order_by; this.order_meta.order_by = properties.order_by;
this.order_meta.order = properties.order; this.order_meta.order = properties.order;
}); });
...@@ -209,6 +218,7 @@ ...@@ -209,6 +218,7 @@
this.folderBreadcrumb = [ this.folderBreadcrumb = [
{ id: 0, name: 'Home' }, { id: 0, name: 'Home' },
]; ];
return; return;
} }
axios.get(route('api.media.folders.breadcrumb', { folder: folderId })) axios.get(route('api.media.folders.breadcrumb', { folder: folderId }))
...@@ -249,6 +259,9 @@ ...@@ -249,6 +259,9 @@
handleSelectionChange(selectedMedia) { handleSelectionChange(selectedMedia) {
this.selectedMedia = selectedMedia; this.selectedMedia = selectedMedia;
}, },
toggleUploadZone() {
this.showUploadZone = !this.showUploadZone;
},
showEditFolder(scope) { showEditFolder(scope) {
this.$events.emit('editFolderWasClicked', scope); this.$events.emit('editFolderWasClicked', scope);
}, },
...@@ -269,15 +282,15 @@ ...@@ -269,15 +282,15 @@
}, },
batchDelete() { batchDelete() {
this.$confirm(this.trans('core.modal.confirmation-message'), this.trans('core.modal.title'), { this.$confirm(this.trans('core.modal.confirmation-message'), this.trans('core.modal.title'), {
confirmButtonText: this.trans('core.button.delete'), confirmButtonText: this.trans('core.button.delete'),
cancelButtonText: this.trans('core.button.cancel'), cancelButtonText: this.trans('core.button.cancel'),
type: 'warning', type: 'warning',
}) })
.then(() => { .then(() => {
this.filesAreDeleting = true; this.filesAreDeleting = true;
axios.post(route('api.media.media.batch-destroy'), { axios.post(route('api.media.media.batch-destroy'), {
files: this.selectedMedia, files: this.selectedMedia,
}) })
.then((response) => { .then((response) => {
this.$message({ this.$message({
type: 'success', type: 'success',
......
<template> <template>
<div class="row"> <el-upload
<div class="col-xs-12"> class="media-upload"
<el-upload drag
class="media-upload" :action="uploadUrl"
drag list-type="picture"
:action="uploadUrl" :show-file-list="false"
:on-preview="handlePreview" :http-request="uploadFile"
:on-remove="handleRemove" multiple
:on-success="handleSuccess" >
:file-list="fileList" <i class="el-icon-upload"></i>
:headers="requestHeaders" <div class="el-upload__text">Drop file here or <em>click to upload</em></div>
multiple> </el-upload>
<i class="el-icon-upload"></i>
<div class="el-upload__text">Drop file here or <em>click to upload</em></div>
</el-upload>
</div>
</div>
</template> </template>
<script> <script>
import axios from 'axios';
export default { export default {
props: {
parentId: { type: Number },
},
data() { data() {
return { return {
fileList: [], fileIsUploading: false,
}; };
}, },
computed: { computed: {
uploadUrl() { uploadUrl() {
return route('api.media.store').domain + route('api.media.store').url; return route('api.media.store').domain + route('api.media.store').url;
}, },
requestHeaders() {
const userApiToken = document.head.querySelector('meta[name="user-api-token"]');
return {
Authorization: `Bearer ${userApiToken.content}`,
};
},
}, },
methods: { methods: {
handleSuccess(response) { uploadFile(event) {
this.$events.emit('fileWasUploaded', response); this.fileIsUploading = true;
this.fileList = []; const data = new FormData();
data.append('parent_id', this.parentId);
data.append('file', event.file);
axios.post(route('api.media.store'), data).then((response) => {
this.$events.emit('fileWasUploaded', response);
this.$message({
type: 'success',
message: this.trans('media.file uploaded'),
});
this.fileIsUploading = false;
}, (error) => {
console.log(error.response.data);
this.fileIsUploading = false;
this.$notify.error({
title: 'Error',
message: error.response.data.errors.file[0],
});
});
}, },
handlePreview() {},
handleRemove() {},
}, },
mounted() {},
}; };
</script> </script>
<style> <style>
.media-upload {
margin-bottom: 10px;
}
.el-upload__input { .el-upload__input {
display: none !important; display: none !important;
} }
.el-upload--text {
display: block; .el-upload--picture, .el-upload--picture-card {
width: 100%;
height: 175px;
line-height: 100px;
border: none;
} }
.el-upload-dragger { .el-upload-dragger {
width: 100%; width: 100%;
height: 100%;
} }
.media-upload {
margin-bottom: 10px; .el-upload-dragger .el-upload__text {
position: absolute;
bottom: 0;
width: 100%;
}
.el-upload--text {
display: block;
} }
</style> </style>
...@@ -3,102 +3,88 @@ ...@@ -3,102 +3,88 @@
namespace Modules\Tag\Contracts; namespace Modules\Tag\Contracts;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphToMany;
interface TaggableInterface interface TaggableInterface
{ {
/** /**
* The Eloquent tag entity name. * The Eloquent tag entity name.
* @var string
*/ */
public static function getEntityNamespace(); public static function getEntityNamespace(): string;
/** /**
* Returns the Eloquent tags entity name. * Returns the Eloquent tags entity name.
* @return string
*/ */
public static function getTagsModel(); public static function getTagsModel(): string;
/** /**
* Sets the Eloquent tags entity name. * Sets the Eloquent tags entity name.
* @param string $model
* @return void
*/ */
public static function setTagsModel($model); public static function setTagsModel(string $model);
/** /**
* Get all the entities with the given tag(s) * Get all the entities with the given tag(s)
* Optionally specify the column on which * Optionally specify the column on which
* to perform the search operation. * to perform the search operation.
* @param \Illuminate\Database\Eloquent\Builder $query *
* @param string|array $tags * @param string|array $tags
* @param string $type
* @return \Illuminate\Database\Eloquent\Builder
*/ */
public function scopeWhereTag(Builder $query, $tags, $type = 'slug'); public function scopeWhereTag(Builder $query, $tags, string $type = 'slug'): Builder;
/** /**
* Get all the entities with one of the given tag(s) * Get all the entities with one of the given tag(s)
* Optionally specify the column on which * Optionally specify the column on which
* to perform the search operation. * to perform the search operation.
* @param \Illuminate\Database\Eloquent\Builder $query *
* @param string|array $tags * @param string|array $tags
* @param string $type
* @return \Illuminate\Database\Eloquent\Builder
*/ */
public function scopeWithTag(Builder $query, $tags, $type = 'slug'); public function scopeWithTag(Builder $query, $tags, string $type = 'slug'): Builder;
/** /**
* Define the eloquent morphMany relationship * Define the eloquent morphMany relationship
* @return \Illuminate\Database\Eloquent\Relations\MorphToMany
*/ */
public function tags(); public function tags(): MorphToMany;
/** /**
* Returns all the tags under the current entity namespace. * Returns all the tags under the current entity namespace.
* @return \Illuminate\Database\Eloquent\Builder
*/ */
public static function allTags(); public static function allTags(): Builder;
/** /**
* Creates a new model instance. * Creates a new model instance.
* @return \Illuminate\Database\Eloquent\Model
*/ */
public static function createTagsModel(); public static function createTagsModel(): Model;
/** /**
* Syncs the given tags. * Syncs the given tags.
*
* @param string|array $tags * @param string|array $tags
* @param string $type
* @return bool
*/ */
public function setTags($tags, $type = 'name'); public function setTags($tags, string $type = 'name'): bool;
/** /**
* Detaches multiple tags from the entity or if no tags are * Detaches multiple tags from the entity or if no tags are
* passed, removes all the attached tags from the entity. * passed, removes all the attached tags from the entity.
*
* @param string|array|null $tags * @param string|array|null $tags
* @return bool
*/ */
public function untag($tags = null); public function untag($tags = null): bool;
/** /**
* Detaches the given tag from the entity. * Detaches the given tag from the entity.
* @param string $name
* @return void
*/ */
public function removeTag($name); public function removeTag(string $name);
/** /**
* Attaches multiple tags to the entity. * Attaches multiple tags to the entity.
* @param string|array $tags *
* @return bool * @param string|array $tags
*/ */
public function tag($tags); public function tag($tags): bool;
/** /**
* Attaches the given tag to the entity. * Attaches the given tag to the entity.
* @param string $name
* @return void
*/ */
public function addTag($name); public function addTag(string $name);
} }
...@@ -3,42 +3,29 @@ ...@@ -3,42 +3,29 @@
namespace Modules\Tag\Traits; namespace Modules\Tag\Traits;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphToMany;
use Modules\Tag\Entities\Tag; use Modules\Tag\Entities\Tag;
trait TaggableTrait trait TaggableTrait
{ {
/**
* {@inheritdoc}
*/
protected static $tagsModel = Tag::class; protected static $tagsModel = Tag::class;
/** public static function getTagsModel(): string
* {@inheritdoc}
*/
public static function getTagsModel()
{ {
return static::$tagsModel; return static::$tagsModel;
} }
/** public static function setTagsModel(string $model)
* {@inheritdoc}
*/
public static function setTagsModel($model)
{ {
static::$tagsModel = $model; static::$tagsModel = $model;
} }
/** public function scopeWhereTag(Builder $query, $tags, string $type = 'slug'): Builder
* {@inheritdoc}
*/
public function scopeWhereTag(Builder $query, $tags, $type = 'slug')
{ {
if (is_string($tags) === true) {
$tags = [$tags];
}
$query->with('translations'); $query->with('translations');
foreach ($tags as $tag) { foreach (array_wrap($tags) as $tag) {
$query->whereHas('tags', function (Builder $query) use ($type, $tag) { $query->whereHas('tags', function (Builder $query) use ($type, $tag) {
$query->whereHas('translations', function (Builder $query) use ($type, $tag) { $query->whereHas('translations', function (Builder $query) use ($type, $tag) {
$query->where($type, $tag); $query->where($type, $tag);
...@@ -49,14 +36,10 @@ trait TaggableTrait ...@@ -49,14 +36,10 @@ trait TaggableTrait
return $query; return $query;
} }
/** public function scopeWithTag(Builder $query, $tags, string $type = 'slug'): Builder
* {@inheritdoc}
*/
public function scopeWithTag(Builder $query, $tags, $type = 'slug')
{ {
if (is_string($tags) === true) { $tags = array_wrap($tags);
$tags = [$tags];
}
$query->with('translations'); $query->with('translations');
return $query->whereHas('tags', function (Builder $query) use ($type, $tags) { return $query->whereHas('tags', function (Builder $query) use ($type, $tags) {
...@@ -66,43 +49,31 @@ trait TaggableTrait ...@@ -66,43 +49,31 @@ trait TaggableTrait
}); });
} }
/** public function tags(): MorphToMany
* {@inheritdoc}
*/
public function tags()
{ {
return $this->morphToMany(static::$tagsModel, 'taggable', 'tag__tagged', 'taggable_id', 'tag_id'); return $this->morphToMany(static::$tagsModel, 'taggable', 'tag__tagged', 'taggable_id', 'tag_id');
} }
/** public static function createTagsModel(): Model
* {@inheritdoc}
*/
public static function createTagsModel()
{ {
return new static::$tagsModel; return new static::$tagsModel;
} }
/** public static function allTags(): Builder
* {@inheritdoc}
*/
public static function allTags()
{ {
$instance = new static; $instance = new static;
return $instance->createTagsModel()->with('translations')->whereNamespace($instance->getEntityClassName()); return self::createTagsModel()->with('translations')->where('namespace', $instance->getEntityClassName());
} }
/** public function setTags($tags, string $type = 'slug'): bool
* {@inheritdoc}
*/
public function setTags($tags, $type = 'slug')
{ {
if (empty($tags)) { if (empty($tags)) {
$tags = []; $tags = [];
} }
// Get the current entity tags // Get the current entity tags
$entityTags = $this->tags->pluck($type)->all(); $entityTags = $this->tags()->get()->pluck($type)->all();
// Prepare the tags to be added and removed // Prepare the tags to be added and removed
$tagsToAdd = array_diff($tags, $entityTags); $tagsToAdd = array_diff($tags, $entityTags);
...@@ -121,25 +92,18 @@ trait TaggableTrait ...@@ -121,25 +92,18 @@ trait TaggableTrait
return true; return true;
} }
/** public function tag($tags): bool
* {@inheritdoc}
*/
public function tag($tags)
{ {
foreach ($tags as $tag) { foreach (array_wrap($tags) as $tag) {
$this->addTag($tag); $this->addTag($tag);
} }
return true; return true;
} }
/** public function addTag(string $name)
* {@inheritdoc}
*/
public function addTag($name)
{ {
$tag = $this->createTagsModel()->where('namespace', $this->getEntityClassName()) $tag = self::allTags()
->with('translations')
->whereHas('translations', function (Builder $q) use ($name) { ->whereHas('translations', function (Builder $q) use ($name) {
$q->where('slug', $this->generateTagSlug($name)); $q->where('slug', $this->generateTagSlug($name));
})->first(); })->first();
...@@ -157,17 +121,14 @@ trait TaggableTrait ...@@ -157,17 +121,14 @@ trait TaggableTrait
$tag->save(); $tag->save();
} }
if ($this->tags->contains($tag->id) === false) { if ($this->tags()->get()->contains($tag->id) === false) {
$this->tags()->attach($tag); $this->tags()->attach($tag);
} }
} }
/** public function untag($tags = null): bool
* {@inheritdoc}
*/
public function untag($tags = null)
{ {
$tags = $tags ?: $this->tags->pluck('name')->all(); $tags = $tags ?: $this->tags()->get()->pluck('name')->all();
foreach ($tags as $tag) { foreach ($tags as $tag) {
$this->removeTag($tag); $this->removeTag($tag);
...@@ -176,14 +137,9 @@ trait TaggableTrait ...@@ -176,14 +137,9 @@ trait TaggableTrait
return true; return true;
} }
/** public function removeTag(string $name)
* {@inheritdoc}
*/
public function removeTag($name)
{ {
$tag = $this->createTagsModel() $tag = self::allTags()
->where('namespace', $this->getEntityClassName())
->with('translations')
->whereHas('translations', function (Builder $q) use ($name) { ->whereHas('translations', function (Builder $q) use ($name) {
$q->where('slug', $this->generateTagSlug($name)); $q->where('slug', $this->generateTagSlug($name));
})->first(); })->first();
...@@ -193,10 +149,7 @@ trait TaggableTrait ...@@ -193,10 +149,7 @@ trait TaggableTrait
} }
} }
/** protected function getEntityClassName(): string
* {@inheritdoc}
*/
protected function getEntityClassName()
{ {
if (isset(static::$entityNamespace)) { if (isset(static::$entityNamespace)) {
return static::$entityNamespace; return static::$entityNamespace;
...@@ -205,24 +158,21 @@ trait TaggableTrait ...@@ -205,24 +158,21 @@ trait TaggableTrait
return $this->tags()->getMorphClass(); return $this->tags()->getMorphClass();
} }
/** public function generateTagSlug($name, $separator = '-'): string
* {@inheritdoc}
*/
public function generateTagSlug($name, $separator = '-')
{ {
// Convert all dashes/underscores into separator // Convert all dashes/underscores into separator
$flip = $separator == '-' ? '_' : '-'; $flip = $separator == '-' ? '_' : '-';
$name = preg_replace('!['.preg_quote($flip).']+!u', $separator, $name); $name = preg_replace('![' . preg_quote($flip, '!') . ']+!u', $separator, $name);
// Replace @ with the word 'at' // Replace @ with the word 'at'
$name = str_replace('@', $separator.'at'.$separator, $name); $name = str_replace('@', $separator . 'at' . $separator, $name);
// Remove all characters that are not the separator, letters, numbers, or whitespace. // Remove all characters that are not the separator, letters, numbers, or whitespace.
$name = preg_replace('![^'.preg_quote($separator).'\pL\pN\s]+!u', '', mb_strtolower($name)); $name = preg_replace('![^' . preg_quote($separator, '!') . '\pL\pN\s]+!u', '', mb_strtolower($name));
// Replace all separator characters and whitespace by a single separator // Replace all separator characters and whitespace by a single separator
$name = preg_replace('!['.preg_quote($separator).'\s]+!u', $separator, $name); $name = preg_replace('![' . preg_quote($separator, '!') . '\s]+!u', $separator, $name);
return trim($name, $separator); return trim($name, $separator);
} }
......
...@@ -38,6 +38,7 @@ return [ ...@@ -38,6 +38,7 @@ return [
'create resource' => 'Create media', 'create resource' => 'Create media',
'edit resource' => 'Edit media', 'edit resource' => 'Edit media',
'destroy resource' => 'Delete media', 'destroy resource' => 'Delete media',
'file uploaded' => 'File uploaded successfully',
'file too large' => 'File is too large. Must be below :size MB.', 'file too large' => 'File is too large. Must be below :size MB.',
'some files not moved' => 'Some files were not moved', 'some files not moved' => 'Some files were not moved',
'files moved successfully' => 'Files moved successfully', 'files moved successfully' => 'Files moved successfully',
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
namespace Modules\$MODULE$\Providers; namespace Modules\$MODULE$\Providers;
use Illuminate\Database\Eloquent\Factory as EloquentFactory;
use Illuminate\Support\ServiceProvider; use Illuminate\Support\ServiceProvider;
use Modules\Core\Traits\CanPublishConfiguration; use Modules\Core\Traits\CanPublishConfiguration;
use Modules\Core\Events\BuildingSidebar; use Modules\Core\Events\BuildingSidebar;
...@@ -31,6 +32,8 @@ class $MODULE$ServiceProvider extends ServiceProvider ...@@ -31,6 +32,8 @@ class $MODULE$ServiceProvider extends ServiceProvider
$this->app['events']->listen(LoadingBackendTranslations::class, function (LoadingBackendTranslations $event) { $this->app['events']->listen(LoadingBackendTranslations::class, function (LoadingBackendTranslations $event) {
// append translations // append translations
}); });
$this->registerEloquentFactoriesFrom(__DIR__ . '/../Database/factories');
} }
public function boot() public function boot()
...@@ -54,4 +57,15 @@ class $MODULE$ServiceProvider extends ServiceProvider ...@@ -54,4 +57,15 @@ class $MODULE$ServiceProvider extends ServiceProvider
{ {
// add bindings // add bindings
} }
/**
* Register factories.
*
* @param string $path
* @return void
*/
protected function registerEloquentFactoriesFrom($path)
{
$this->app->make(EloquentFactory::class)->load($path);
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment