├── .editorconfig ├── .gitignore ├── ConfigTypes └── DefaultSettings.php ├── LICENSE ├── Mutators └── PostNameMutator.php ├── PostTypes ├── Attachments.php ├── CategoryPosts.php ├── Pages.php └── Posts.php ├── README.md ├── composer.json ├── config └── niku-cms.php ├── database └── migrations │ ├── 2016_09_10_202151_add_posts_for_cms.php │ ├── 2016_09_10_203126_add_config_to_cms.php │ ├── 2016_09_10_203126_add_post_meta_to_cms.php │ ├── 2016_09_10_203126_add_taxonomy_pivot_to_cms.php │ ├── 2016_09_10_203127_add_postmeta_to_taxonomy.php │ └── 2018_03_01_1111111_add_details_to_postmeta.php ├── package-lock.json ├── posttypes ├── Attachments.php ├── CategoryPosts.php ├── Pages.php └── Posts.php └── src ├── Cms.php ├── CmsServiceProvider.php └── Http ├── Controllers ├── Cms │ ├── CheckPostController.php │ ├── CreatePostController.php │ ├── CustomPostController.php │ ├── DeletePostController.php │ ├── EditCustomPostController.php │ ├── EditPostController.php │ ├── ListPostsController.php │ ├── ShowCustomGetPostController.php │ ├── ShowPostController.php │ ├── ShowPostTaxonomies.php │ ├── ShowTaxonomyPosts.php │ ├── SpecificFieldsEditPostController.php │ ├── SpecificFileEditPostController.php │ └── TaxonomyController.php ├── Config │ ├── EditConfigController.php │ └── ShowConfigController.php ├── ConfigController.php ├── MutatorController.php ├── cmsController.php └── mediaController.php ├── Middlewares ├── WhitelistConfigGroupsMiddleware.php └── WhitelistPostTypesMiddleware.php ├── NikuConfig.php ├── NikuPostmeta.php ├── NikuPosts.php ├── NikuTaxonomies.php └── NikuTaxonomyMeta.php /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = tab 5 | # indent_size = 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | composer.phar 3 | composer.lock 4 | .DS_Store 5 | /.idea -------------------------------------------------------------------------------- /ConfigTypes/DefaultSettings.php: -------------------------------------------------------------------------------- 1 | 'The config type does not exist.', 21 | ]; 22 | 23 | public $successMessage = [ 24 | 'config_updated' => 'Config successful updated', 25 | ]; 26 | 27 | // Setting up the template structure 28 | public $view = []; 29 | 30 | public function __construct() 31 | { 32 | $this->view(); 33 | } 34 | 35 | public function view() 36 | { 37 | $this->view = [ 38 | 'default' => [ 39 | 'customFields' => [ 40 | 'text' => [ 41 | 'component' => 'niku-cms-text-customfield', 42 | 'label' => 'Text', 43 | 'value' => '', 44 | 'validation' => 'required', 45 | ], 46 | 'periods' => [ 47 | 'component' => 'niku-cms-repeater-customfield', 48 | 'label' => 'Perioden', 49 | 'validation' => 'required', 50 | 'customFields' => [ 51 | 52 | 'label' => [ 53 | 'component' => 'niku-cms-text-customfield', 54 | 'label' => 'Label', 55 | 'value' => '', 56 | 'validation' => 'required', 57 | ], 58 | 59 | 'boolean' => [ 60 | 'component' => 'niku-cms-boolean-customfield', 61 | 'label' => 'Boolean button', 62 | 'value' => '', 63 | 'validation' => 'required', 64 | ], 65 | 66 | ] 67 | ], 68 | ], 69 | ], 70 | ]; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Nick Kuijpers 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Mutators/PostNameMutator.php: -------------------------------------------------------------------------------- 1 | 'required', 21 | 'status' => 'required', 22 | 'post_name' => 'required', 23 | ]; 24 | 25 | // Setting up the template structure 26 | public $view = [ 27 | 'default' => [ 28 | 'customFields' => [ 29 | 'text' => [ 30 | 'component' => 'niku-cms-text-customfield', 31 | 'label' => 'Text', 32 | 'value' => '', 33 | 'validation' => 'required', 34 | ], 35 | ], 36 | ], 37 | ]; 38 | } 39 | -------------------------------------------------------------------------------- /PostTypes/CategoryPosts.php: -------------------------------------------------------------------------------- 1 | 'The post type does not exist.', 30 | 'post_type_identifier_does_not_exist' => 'The post type identifier does not exist.', 31 | 'post_does_not_exist' => 'The post does not exist.', 32 | 'sub_post_type_does_not_exist' => 'The sub post type does not exist', 33 | 'no_taxonomy_posts_connected' => 'There are no posts connected to this taxonomy.', 34 | ]; 35 | 36 | public $successMessage = [ 37 | 'post_created' => 'Post successful created.', 38 | 'post_deleted' => 'Post successful deleted', 39 | 'post_updated' => 'Post successful updated', 40 | ]; 41 | 42 | // Register events based on the actions 43 | public $events = [ 44 | 'on_create' => [ 45 | // 46 | ], 47 | 'on_browse' => [ 48 | // 49 | ], 50 | 'on_read' => [ 51 | // 52 | ], 53 | 'on_edit' => [ 54 | // 55 | ], 56 | 'on_delete' => [ 57 | // 58 | ], 59 | ]; 60 | 61 | // Setting up the template structure 62 | public $templates = [ 63 | 'default' => [ 64 | 65 | 'label' => 'Default', 66 | 67 | 'customFields' => [ 68 | 69 | 'description' => [ 70 | 'component' => 'niku-cms-editor-customfield', 71 | 'label' => 'Description', 72 | 'saveable' => false, 73 | ], 74 | 75 | 'mutated_value' => [ 76 | 'component' => 'niku-cms-text-customfield', 77 | 'label' => 'Text', 78 | 'value' => '', 79 | 'validation' => 'required', 80 | 'saveable' => true, 81 | 'mutator' => 'App\Cms\Mutators\PostNameMutator', 82 | ], 83 | 84 | 'posts' => [ 85 | 'component' => 'niku-cms-category-posts-customfield', 86 | 'label' => 'Associated posts', 87 | 'config' => [ 88 | 'sub_post_type' => 'posts', 89 | 'posts_edit_url_identifier' => 'Single', 90 | 'saveable' => false, 91 | ], 92 | ], 93 | 94 | ], 95 | ], 96 | ]; 97 | 98 | /** 99 | * Determine if the user is authorized to make this request. 100 | * You can create some custom function here to manipulate 101 | * the functionalty on some certain custom actions. 102 | */ 103 | public function authorized() 104 | { 105 | return true; 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /PostTypes/Pages.php: -------------------------------------------------------------------------------- 1 | [ 41 | 'return_to' => 'step1', 42 | ], 43 | ]; 44 | 45 | public $errorMessages = [ 46 | 'post_type_does_not_exist' => 'The post type does not exist.', 47 | 'post_type_identifier_does_not_exist' => 'The post type identifier does not exist.', 48 | 'post_does_not_exist' => 'The post does not exist.', 49 | 'sub_post_type_does_not_exist' => 'The sub post type does not exist', 50 | 'no_taxonomy_posts_connected' => 'There are no posts connected to this taxonomy.', 51 | ]; 52 | 53 | public $successMessage = [ 54 | 'post_created' => 'Post successful created.', 55 | 'post_deleted' => 'Post successful deleted', 56 | 'post_updated' => 'Post successful updated', 57 | ]; 58 | 59 | // Register events based on the actions 60 | public $events = [ 61 | 'on_create' => [ 62 | // 63 | ], 64 | 'on_browse' => [ 65 | // 66 | ], 67 | 'on_read' => [ 68 | // 69 | ], 70 | 'on_edit' => [ 71 | // 72 | ], 73 | 'on_delete' => [ 74 | // 75 | ], 76 | ]; 77 | 78 | public $view = []; 79 | 80 | public function __construct() 81 | { 82 | $this->view(); 83 | } 84 | 85 | // Setting up the template structure 86 | public function view() 87 | { 88 | $this->view = [ 89 | 'default' => [ 90 | 91 | 'label' => 'Default', 92 | 93 | 'customFields' => [ 94 | 'text' => [ 95 | 'component' => 'niku-cms-text-customfield', 96 | 'label' => 'Text', 97 | 'value' => '', 98 | 'validation' => 'required', 99 | 'single_field_updateable' => [ 100 | 'active' => true, 101 | 'reload_fields' => '*', 102 | ], 103 | ], 104 | 'PostMultiselect' => [ 105 | 'component' => 'niku-cms-posttype-multiselect', 106 | 'label' => 'Post multiselect', 107 | 'post_type' => ['page'], 108 | 'validation' => 'required', 109 | ], 110 | 'mutated_value' => [ 111 | 'component' => 'niku-cms-text-customfield', 112 | 'label' => 'Text', 113 | 'value' => '', 114 | 'validation' => 'required', 115 | 'saveable' => true, 116 | 'mutator' => 'App\Cms\Mutators\PostNameMutator', 117 | ], 118 | 'periods' => [ 119 | 'component' => 'niku-cms-repeater-customfield', 120 | 'label' => 'Perioden', 121 | 'validation' => 'required', 122 | 'customFields' => [ 123 | 124 | 'label' => [ 125 | 'component' => 'niku-cms-text-customfield', 126 | 'label' => 'Label', 127 | 'value' => '', 128 | 'validation' => '', 129 | ], 130 | 131 | 'boolean' => [ 132 | 'component' => 'niku-cms-boolean-customfield', 133 | 'label' => 'Boolean button', 134 | 'value' => '', 135 | 'validation' => '', 136 | 'conditional' => [ 137 | 'show_when' => [ 138 | [ 139 | 'custom_field' => 'text', 140 | 'operator' => '==', 141 | 'value' => 'YES', 142 | ], 143 | ], 144 | ], 145 | ], 146 | 147 | ] 148 | ], 149 | ], 150 | ], 151 | ]; 152 | } 153 | 154 | public function append_list_query($query, $postTypeModel, $request) 155 | { 156 | 157 | } 158 | 159 | public function append_show_get_query($query, $postTypeModel, $request) 160 | { 161 | return $query->where('post_title', 'test'); 162 | } 163 | 164 | public function append_show_edit_query($query, $postTypeModel, $request) 165 | { 166 | 167 | } 168 | 169 | public function append_show_delete_query($query, $postTypeModel, $request) 170 | { 171 | 172 | } 173 | 174 | public function append_show_check_query($query, $postTypeModel, $request) 175 | { 176 | 177 | } 178 | 179 | public function append_show_specific_field_query($query, $postTypeModel, $request) 180 | { 181 | 182 | } 183 | 184 | public function append_show_crud_query($query, $postTypeModel, $request) 185 | { 186 | 187 | } 188 | 189 | } 190 | -------------------------------------------------------------------------------- /PostTypes/Posts.php: -------------------------------------------------------------------------------- 1 | 'required', 21 | 'status' => 'required', 22 | 'post_name' => 'required', 23 | ]; 24 | 25 | // Setting up the template structure 26 | public $view = [ 27 | 'default' => [ 28 | 'customFields' => [ 29 | 'text' => [ 30 | 'component' => 'niku-cms-text-customfield', 31 | 'label' => 'Text', 32 | 'value' => '', 33 | 'validation' => 'required', 34 | ], 35 | ], 36 | ], 37 | ]; 38 | 39 | /** 40 | * Determine if the user is authorized to make this request. 41 | * You can create some custom function here to manipulate 42 | * the functionalty on some certain custom actions. 43 | */ 44 | public function authorized() 45 | { 46 | return true; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Laravel Post Manager 2 | 3 | [![Latest Stable Version](https://poser.pugx.org/niku-solutions/cms/v/stable)](https://packagist.org/packages/niku-solutions/cms) 4 | [![Latest Unstable Version](https://poser.pugx.org/niku-solutions/cms/v/unstable)](https://packagist.org/packages/niku-solutions/cms) 5 | [![License](https://poser.pugx.org/niku-solutions/cms/license)](https://packagist.org/packages/niku-solutions/cms) 6 | [![Monthly Downloads](https://poser.pugx.org/niku-solutions/cms/d/monthly)](https://packagist.org/packages/niku-solutions/cms) 7 | 8 | A API based codeable post manager for Laravel with custom fields. Extendable as you wish. Based on the API request, you will receive the post type configurations 9 | in a way where you can build your front-end with. We will take care of the CRUD functionality with support of taxonomies, media management and post meta. 10 | 11 | We use our package internally in our projects to remove the need of basic post management. We are now able to setup advanced dashboard functionality for all type of 12 | post data like Pages, Posts, Products and whatever post type or category you require. You can add or remove custom fields in no time with no need to touch the 13 | database as the package does that automatically for you and save the data and shows it to you when displaying the editting form. 14 | 15 | > We are working on a decoupled front-end package in Vue.js and Axios which makes it possible to interact with the API in your Laravel project or Single Page Application. 16 | 17 | #### Features 18 | * Custom post types 19 | * Configuration pages 20 | * Taxonomies like categories 21 | * Media manager with upload functionality and management 22 | * Repeating custom field groups 23 | * Custom fields 24 | * Validation rules for custom fields 25 | * Conditional custom fields based on template selection 26 | * Easy default user authentication based on if a user is logged in 27 | * Possibility to let users only view their own posts 28 | * Menu management support, you will need our front-end package for that. 29 | 30 | ## Installation 31 | 32 | Install the package via composer: 33 | 34 | ``` 35 | composer require niku-solutions/cms 36 | ``` 37 | 38 | Register the following class into the 'providers' array in your config/app.php 39 | 40 | ```php 41 | Niku\Cms\CmsServiceProvider::class, 42 | ``` 43 | 44 | Register the following middleware to whitelist your post types and config groups in the route files. You dont have to do anything further with this as we use this in our provider to secure the api routes of the post manager. 45 | 46 | ```php 47 | use Niku\Cms\Http\Middlewares\WhitelistPostTypesMiddleware; 48 | use Niku\Cms\Http\Middlewares\WhitelistConfigGroupsMiddleware; 49 | 50 | protected $routeMiddleware = [ 51 | ... 52 | 'posttypes' => WhitelistPostTypesMiddleware::class, 53 | 'groups' => WhitelistConfigGroupsMiddleware::class, 54 | ... 55 | ]; 56 | ``` 57 | 58 | You need to run the following artisan command to publish the required config file to register your post types. 59 | 60 | ``` 61 | php artisan vendor:publish --tag=niku-config 62 | ``` 63 | 64 | If you run the following vendor publish, you will receive a example set of post types to use 65 | 66 | ``` 67 | php artisan vendor:publish --tag=niku-posttypes 68 | ``` 69 | 70 | Migrate the database tables by running: 71 | 72 | ``` 73 | php artisan migrate 74 | ``` 75 | 76 | ### Usage 77 | 78 | Before you are able to use the post types, you need to whitelist and setup the required custom fields and templates in the config/niku-cms.php file. 79 | 80 | ```php 81 | return [ 82 | 'post_types' => [ 83 | 84 | // Default 85 | 'attachment' => App\Cms\PostTypes\Attachment::class, 86 | 87 | // CMS 88 | 'page' => App\Cms\PostTypes\Pages::class, 89 | 'posts' => App\Cms\PostTypes\Pages::class, 90 | 'posts-category' => App\Cms\PostTypes\PostsCategory::class, 91 | 92 | ], 93 | 94 | 'config_types' => [ 95 | 96 | // Registering the single config page 97 | 'defaultsettings' => App\Cms\ConfigTypes\DefaultSettings::class, 98 | 99 | ]; 100 | ``` 101 | 102 | You can register the routes by pasting the following method in your route file. You can add middlewares like you would normally do to 103 | secure the routes with authentication etc. The post_type in the registed routes are variable but secured by a parameter in the method, so by default no api requests are enabled. 104 | 105 | To enable the API routes, you need to register the names of the post types you would like to use as you see in the 'register_post_types' array key below. 106 | When registering a post type, you fill in the name of the array key in the config/niku-cms.php file. For more information about the config, read on. 107 | 108 | If you for example have 2 user roles which have to communicate to the same post type but require different permissions, you can create 2 config files 109 | where the normal user account can only view their own posts, and the superadmin can view all of the users their posts. You do that by naming the array 110 | key of the config/niku-cms.php unique and creating 2 config files where the '$identifier' is pointed to the same 'post_type'. 111 | 112 | ```php 113 | Niku\Cms\Cms::postTypeRoutes([ 114 | 'register_post_types' => [ 115 | 'posts', 116 | 'superadminposts', 117 | ], 118 | ]); 119 | 120 | // Registering the routes for config pages 121 | Niku\Cms\Cms::postTypeRoutes([ 122 | 'register_groups' => [ 123 | 'defaultsettings', 124 | ], 125 | ]); 126 | ``` 127 | 128 | For each post type registered, you can set up default data and custom fields. You can add validations to the validation array key of the custom field you insert. All Laravel validation rules 129 | will be supported as it will only pass it thru to the validator class. 130 | 131 | ```php 132 | namespace App\Cms\PostTypes; 133 | 134 | use Niku\Cms\Http\NikuPosts; 135 | 136 | class Pages extends NikuPosts 137 | { 138 | // The label of the custom post type 139 | public $label = 'Pages'; 140 | 141 | // Custom post type identifer 142 | public $identifier = 'page'; 143 | 144 | // Users can only view their own posts when this is set to true 145 | public $userCanOnlySeeHisOwnPosts = false; 146 | 147 | public $config = [ 148 | 149 | ]; 150 | 151 | // Setting up the template structure 152 | public $templates = [ 153 | 'default' => [ 154 | 'customFields' => [ 155 | 'post_content' => [ 156 | 'component' => 'niku-cms-text-customfield', 157 | 'label' => 'Text', 158 | 'value' => '', 159 | 'validation' => 'required', 160 | ], 161 | 'author' => [ 162 | 'component' => 'niku-cms-text-customfield', 163 | 'label' => 'Author', 164 | 'validation' => 'required', 165 | ], 166 | // more custom fields 167 | ], 168 | ], 169 | ]; 170 | 171 | } 172 | 173 | ``` 174 | 175 | Do you want to change the custom fields displayed based on the template? You can add multiple views which are selectable in the frontend for the end user and change the visible custom fields. 176 | 177 | ```php 178 | public $templates = [ 179 | 'default' => [ 180 | 'label' => 'Default page', 181 | 'template' => 'default', 182 | 'customFields' => [ 183 | 'text' => [ 184 | 'component' => 'niku-cms-text-customfield', 185 | 'label' => 'Text', 186 | 'value' => '', 187 | 'validation' => 'required', 188 | ] 189 | ] 190 | ], 191 | 'sidebar' => [ 192 | 'label' => 'Sidebar layout', 193 | 'template' => 'sidebar-layout', 194 | 'customFields' => [ 195 | 'text' => [ 196 | 'component' => 'niku-cms-text-customfield', 197 | 'label' => 'Text', 198 | 'value' => '', 199 | 'validation' => 'required', 200 | ] 201 | ] 202 | ], 203 | ]; 204 | ``` 205 | 206 | #### Blog 207 | 208 | If you want a blog like method, you can do the following. 209 | 210 | Enable the following type in your routes/web.php. 211 | 212 | ```php 213 | Route::get('blog', 'BlogController@blog'); 214 | Route::get('blog/{slug}', 'BlogController@singleBlog'); 215 | ``` 216 | 217 | Next you enable the required methods in the controller. 218 | 219 | ```php 220 | public function blog() 221 | { 222 | $posts = Posts::where([ 223 | ['status', '=', '1'], 224 | ['post_type', '=', 'post'] 225 | ])->with('postmeta')->get(); 226 | return view('static.blog', compact('posts')); 227 | } 228 | ``` 229 | 230 | And then in your view, you do the following. This syntax will be recreated in the future to make it more fluent but for now it works. 231 | 232 | ```blade 233 | @foreach($posts as $post) 234 |
235 | @if(!empty($post->getMeta('image'))) 236 | getMeta('image')); 238 | $image = $image->url; 239 | ?> 240 |
241 | 242 |
243 | @endif 244 |
245 |

{{ $post->post_title }}

246 |

{!! $post->getMeta('excerpt') !!}

247 |
248 | Read more 249 |
250 |
251 | @endforeach 252 | ``` 253 | 254 | #### Switching templates 255 | 256 | If you have enabled more than 1 post type template in the config/niku-cms.php, you will see a option appear in the backend to switch between templates. When you have 257 | selected one template, you can switch views in the frontend like this. 258 | 259 | ```blade 260 | @extends('static.layouts.' . $posts->template) 261 | ``` 262 | 263 | ## API 264 | 265 | To retrieve the base structure of your post type, you can request the following post API where the value is 0. This means we creating a new post. 266 | The result of this request will give you the structure of what you have inserted in the config file. With this data you can build the front-end 267 | of your page to automaticly create the input fields of the create form. 268 | 269 | You will trigger this API on initialisation of the page where you want to create a new post item. (/superadmin/pages/create). 270 | 271 | ``` 272 | POST /your-prefix/{post_type}/show/0 273 | ``` 274 | 275 | ```json 276 | { 277 | "post": { 278 | "template": "default" 279 | }, 280 | "postmeta": [], 281 | "templates": { 282 | "default": { 283 | "customFields": { 284 | "text": { 285 | "component": "niku-cms-text-customfield", 286 | "label": "Text", 287 | "value": "", 288 | "validation": "required", 289 | "id": "text" 290 | }, 291 | "PostMultiselect": { 292 | "component": "niku-cms-posttype-multiselect", 293 | "label": "Post multiselect", 294 | "post_type": [ 295 | "page" 296 | ], 297 | "validation": "required", 298 | "id": "PostMultiselect" 299 | }, 300 | "periods": { 301 | "component": "niku-cms-repeater-customfield", 302 | "label": "Perioden", 303 | "validation": "required", 304 | "customFields": { 305 | "label": { 306 | "component": "niku-cms-text-customfield", 307 | "label": "Label", 308 | "value": "", 309 | "validation": "" 310 | }, 311 | "boolean": { 312 | "component": "niku-cms-boolean-customfield", 313 | "label": "Boolean button", 314 | "value": "", 315 | "validation": "" 316 | } 317 | }, 318 | "id": "periods" 319 | } 320 | } 321 | } 322 | }, 323 | "config": [] 324 | } 325 | ``` 326 | 327 | ## Extending the custom fields and defining your own 328 | 329 | You can create your own custom fields by using the registered component identifier to identify which Vue component you need to show. This information 330 | will be attached to the API request when requesting the following API; 331 | 332 | ```php 333 | 'text' => [ 334 | 'component' => 'niku-cms-text-customfield', 335 | 'label' => 'Text', 336 | 'value' => '', 337 | 'validation' => 'required', 338 | ], 339 | ``` 340 | 341 | Registrate your component with they key you define in the post type config. 342 | 343 | ```javascript 344 | Vue.component('niku-cms-text-customfield', require('./components/customFields/text.vue')); 345 | ``` 346 | 347 | And for example use the following code structure 348 | 349 | ```vue 350 | 358 | 372 | ``` 373 | 374 | ## Security Vulnerabilities 375 | 376 | If you find any security vulnerabilities, please send a direct e-mail to Nick Kuijpers at n.kuijpers@niku-solutions.nl. 377 | 378 | ## License 379 | 380 | The MIT License (MIT). Please see [MIT license](http://opensource.org/licenses/MIT) for more information. 381 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "niku-solutions/cms", 3 | "description": "A codeable and flexible custom post type manager for Laravel with custom fields. Extendable and as dynamic as you wish.", 4 | "keywords": [ 5 | "laravel cms", 6 | "laravel post manager", 7 | "laravel page manager" 8 | ], 9 | "license": "MIT", 10 | "authors": [ 11 | { 12 | "name": "Nick Kuijpers", 13 | "email": "info@niku-solutions.nl" 14 | } 15 | ], 16 | "autoload": { 17 | "psr-4": { 18 | "Niku\\Cms\\": "src/" 19 | } 20 | }, 21 | "require": { 22 | "php": "^7.0|^7.1", 23 | "illuminate/http": "^5.2", 24 | "illuminate/auth": "^5.2", 25 | "illuminate/database": "^5.2", 26 | "illuminate/support": "^5.2" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /config/niku-cms.php: -------------------------------------------------------------------------------- 1 | [ 9 | 'page' => App\Cms\PostTypes\Pages::class, 10 | 'attachment' => App\Cms\PostTypes\Attachment::class, 11 | // 12 | ], 13 | 14 | 'config_types' => [ 15 | 'defaultsettings' => App\Cms\ConfigTypes\DefaultSettings::class, 16 | // 17 | ] 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /database/migrations/2016_09_10_202151_add_posts_for_cms.php: -------------------------------------------------------------------------------- 1 | bigIncrements('id'); 17 | 18 | $table->text('post_title')->nullable(); 19 | $table->bigInteger('post_author')->nullable(); 20 | $table->longText('post_content')->nullable(); 21 | $table->longText('custom')->nullable(); 22 | $table->text('post_excerpt')->nullable(); 23 | $table->string('post_password')->nullable(); 24 | $table->string('post_name')->nullable(); 25 | $table->bigInteger('post_parent')->nullable(); 26 | $table->string('post_type')->nullable(); 27 | $table->integer('menu_order')->nullable(); 28 | $table->string('post_mime_type')->nullable(); 29 | $table->string('status')->nullable(); 30 | $table->string('taxonomy')->nullable()->default('post'); 31 | $table->string('template')->nullable(); 32 | $table->index(['post_name', 'id']); 33 | 34 | $table->timestamps(); 35 | }); 36 | } 37 | 38 | /** 39 | * Reverse the migrations. 40 | * 41 | * @return void 42 | */ 43 | public function down() 44 | { 45 | Schema::drop('cms_posts'); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /database/migrations/2016_09_10_203126_add_config_to_cms.php: -------------------------------------------------------------------------------- 1 | bigIncrements('id'); 17 | $table->string('option_name')->nullable(); 18 | $table->longText('option_value')->nullable(); 19 | $table->string('group')->nullable()->default('default'); 20 | $table->longText('custom')->nullable(); 21 | 22 | $table->string('type')->nullable(); 23 | $table->timestamps(); 24 | 25 | $table->index(['option_name', 'id']); 26 | }); 27 | } 28 | 29 | /** 30 | * Reverse the migrations. 31 | * 32 | * @return void 33 | */ 34 | public function down() 35 | { 36 | Schema::drop('cms_config'); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /database/migrations/2016_09_10_203126_add_post_meta_to_cms.php: -------------------------------------------------------------------------------- 1 | bigIncrements('id'); 17 | $table->bigInteger('post_id', false, true); 18 | $table->string('meta_key'); 19 | $table->longText('meta_value')->nullable(); 20 | $table->longText('custom')->nullable(); 21 | $table->string('group')->nullable(); 22 | $table->timestamps(); 23 | 24 | $table->index(['post_id']); 25 | 26 | $table->foreign('post_id')->references('id')->on('cms_posts')->onDelete('cascade'); 27 | 28 | }); 29 | } 30 | 31 | /** 32 | * Reverse the migrations. 33 | * 34 | * @return void 35 | */ 36 | public function down() 37 | { 38 | Schema::drop('cms_postmeta'); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /database/migrations/2016_09_10_203126_add_taxonomy_pivot_to_cms.php: -------------------------------------------------------------------------------- 1 | bigIncrements('id'); 17 | 18 | $table->bigInteger('post_id')->unsigned(); 19 | $table->bigInteger('taxonomy_post_id')->unsigned(); 20 | 21 | $table->string('taxonomy')->nullable(); 22 | $table->longText('custom')->nullable(); 23 | $table->bigInteger('menu_order')->nullable(); 24 | 25 | $table->bigInteger('post_parent')->nullable(); 26 | 27 | $table->foreign('post_id')->references('id')->on('cms_posts')->onDelete('cascade'); 28 | $table->foreign('taxonomy_post_id')->references('id')->on('cms_posts')->onDelete('cascade'); 29 | 30 | $table->timestamps(); 31 | 32 | }); 33 | } 34 | 35 | /** 36 | * Reverse the migrations. 37 | * 38 | * @return void 39 | */ 40 | public function down() 41 | { 42 | Schema::drop('cms_taxonomy'); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /database/migrations/2016_09_10_203127_add_postmeta_to_taxonomy.php: -------------------------------------------------------------------------------- 1 | bigIncrements('id'); 17 | $table->bigInteger('taxonomy_id', false, true); 18 | $table->string('meta_key'); 19 | $table->longText('meta_value')->nullable(); 20 | $table->string('group')->nullable(); 21 | $table->longText('custom')->nullable(); 22 | $table->timestamps(); 23 | 24 | $table->index(['taxonomy_id']); 25 | 26 | $table->foreign('taxonomy_id')->references('id')->on('cms_taxonomy')->onDelete('cascade'); 27 | 28 | }); 29 | } 30 | 31 | /** 32 | * Reverse the migrations. 33 | * 34 | * @return void 35 | */ 36 | public function down() 37 | { 38 | Schema::drop('cms_taxonomymeta'); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /database/migrations/2018_03_01_1111111_add_details_to_postmeta.php: -------------------------------------------------------------------------------- 1 | bigInteger('menu_order')->nullable(); 17 | }); 18 | } 19 | 20 | /** 21 | * Reverse the migrations. 22 | * 23 | * @return void 24 | */ 25 | public function down() 26 | { 27 | Schema::table('cms_postmeta', function (Blueprint $table) { 28 | $table->dropColumn('menu_order'); 29 | }); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "lockfileVersion": 1 3 | } 4 | -------------------------------------------------------------------------------- /posttypes/Attachments.php: -------------------------------------------------------------------------------- 1 | 'required', 21 | 'status' => 'required', 22 | 'post_name' => 'required', 23 | ]; 24 | 25 | // Setting up the template structure 26 | public $view = [ 27 | 'default' => [ 28 | 'customFields' => [ 29 | 'text' => [ 30 | 'component' => 'niku-cms-text-customfield', 31 | 'label' => 'Text', 32 | 'value' => '', 33 | 'validation' => 'required', 34 | ], 35 | ], 36 | ], 37 | ]; 38 | } 39 | -------------------------------------------------------------------------------- /posttypes/CategoryPosts.php: -------------------------------------------------------------------------------- 1 | 'The post type does not exist.', 30 | 'post_type_identifier_does_not_exist' => 'The post type identifier does not exist.', 31 | 'post_does_not_exist' => 'The post does not exist.', 32 | 'sub_post_type_does_not_exist' => 'The sub post type does not exist', 33 | 'no_taxonomy_posts_connected' => 'There are no posts connected to this taxonomy.', 34 | ]; 35 | 36 | public $successMessage = [ 37 | 'post_created' => 'Post successful created.', 38 | 'post_deleted' => 'Post successful deleted', 39 | 'post_updated' => 'Post successful updated', 40 | ]; 41 | 42 | // Register events based on the actions 43 | public $events = [ 44 | 'on_create' => [ 45 | // 46 | ], 47 | 'on_browse' => [ 48 | // 49 | ], 50 | 'on_read' => [ 51 | // 52 | ], 53 | 'on_edit' => [ 54 | // 55 | ], 56 | 'on_delete' => [ 57 | // 58 | ], 59 | ]; 60 | 61 | // Setting up the template structure 62 | public $templates = [ 63 | 'default' => [ 64 | 65 | 'label' => 'Default', 66 | 67 | 'customFields' => [ 68 | 69 | 'description' => [ 70 | 'component' => 'niku-cms-editor-customfield', 71 | 'label' => 'Description', 72 | 'saveable' => false, 73 | ], 74 | 75 | 'mutated_value' => [ 76 | 'component' => 'niku-cms-text-customfield', 77 | 'label' => 'Text', 78 | 'value' => '', 79 | 'validation' => 'required', 80 | 'saveable' => true, 81 | 'mutator' => 'App\Cms\Mutators\PostNameMutator', 82 | ], 83 | 84 | 'posts' => [ 85 | 'component' => 'niku-cms-category-posts-customfield', 86 | 'label' => 'Associated posts', 87 | 'config' => [ 88 | 'sub_post_type' => 'posts', 89 | 'posts_edit_url_identifier' => 'Single', 90 | 'saveable' => false, 91 | ], 92 | ], 93 | 94 | ], 95 | ], 96 | ]; 97 | 98 | /** 99 | * Determine if the user is authorized to make this request. 100 | * You can create some custom function here to manipulate 101 | * the functionalty on some certain custom actions. 102 | */ 103 | public function authorized() 104 | { 105 | return true; 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /posttypes/Pages.php: -------------------------------------------------------------------------------- 1 | [ 41 | 'return_to' => 'step1', 42 | ], 43 | ]; 44 | 45 | public $errorMessages = [ 46 | 'post_type_does_not_exist' => 'The post type does not exist.', 47 | 'post_type_identifier_does_not_exist' => 'The post type identifier does not exist.', 48 | 'post_does_not_exist' => 'The post does not exist.', 49 | 'sub_post_type_does_not_exist' => 'The sub post type does not exist', 50 | 'no_taxonomy_posts_connected' => 'There are no posts connected to this taxonomy.', 51 | ]; 52 | 53 | public $successMessage = [ 54 | 'post_created' => 'Post successful created.', 55 | 'post_deleted' => 'Post successful deleted', 56 | 'post_updated' => 'Post successful updated', 57 | ]; 58 | 59 | // Register events based on the actions 60 | public $events = [ 61 | 'on_create' => [ 62 | // 63 | ], 64 | 'on_browse' => [ 65 | // 66 | ], 67 | 'on_read' => [ 68 | // 69 | ], 70 | 'on_edit' => [ 71 | // 72 | ], 73 | 'on_delete' => [ 74 | // 75 | ], 76 | ]; 77 | 78 | public $view = []; 79 | 80 | public function __construct() 81 | { 82 | $this->view(); 83 | } 84 | 85 | // Setting up the template structure 86 | public function view() 87 | { 88 | $this->view = [ 89 | 'default' => [ 90 | 91 | 'label' => 'Default', 92 | 93 | 'customFields' => [ 94 | 'text' => [ 95 | 'component' => 'niku-cms-text-customfield', 96 | 'label' => 'Text', 97 | 'value' => '', 98 | 'validation' => 'required', 99 | 'single_field_updateable' => [ 100 | 'active' => true, 101 | 'reload_fields' => '*', 102 | ], 103 | ], 104 | 'PostMultiselect' => [ 105 | 'component' => 'niku-cms-posttype-multiselect', 106 | 'label' => 'Post multiselect', 107 | 'post_type' => ['page'], 108 | 'validation' => 'required', 109 | ], 110 | 'mutated_value' => [ 111 | 'component' => 'niku-cms-text-customfield', 112 | 'label' => 'Text', 113 | 'value' => '', 114 | 'validation' => 'required', 115 | 'saveable' => true, 116 | 'mutator' => 'App\Cms\Mutators\PostNameMutator', 117 | ], 118 | 'periods' => [ 119 | 'component' => 'niku-cms-repeater-customfield', 120 | 'label' => 'Perioden', 121 | 'validation' => 'required', 122 | 'customFields' => [ 123 | 124 | 'label' => [ 125 | 'component' => 'niku-cms-text-customfield', 126 | 'label' => 'Label', 127 | 'value' => '', 128 | 'validation' => '', 129 | ], 130 | 131 | 'boolean' => [ 132 | 'component' => 'niku-cms-boolean-customfield', 133 | 'label' => 'Boolean button', 134 | 'value' => '', 135 | 'validation' => '', 136 | 'conditional' => [ 137 | 'show_when' => [ 138 | [ 139 | 'custom_field' => 'text', 140 | 'operator' => '==', 141 | 'value' => 'YES', 142 | ], 143 | ], 144 | ], 145 | ], 146 | 147 | ] 148 | ], 149 | ], 150 | ], 151 | ]; 152 | } 153 | 154 | public function append_list_query($query, $postTypeModel, $request) 155 | { 156 | 157 | } 158 | 159 | public function append_show_get_query($query, $postTypeModel, $request) 160 | { 161 | return $query->where('post_title', 'test'); 162 | } 163 | 164 | public function append_show_edit_query($query, $postTypeModel, $request) 165 | { 166 | 167 | } 168 | 169 | public function append_show_delete_query($query, $postTypeModel, $request) 170 | { 171 | 172 | } 173 | 174 | public function append_show_check_query($query, $postTypeModel, $request) 175 | { 176 | 177 | } 178 | 179 | public function append_show_specific_field_query($query, $postTypeModel, $request) 180 | { 181 | 182 | } 183 | 184 | public function append_show_crud_query($query, $postTypeModel, $request) 185 | { 186 | 187 | } 188 | 189 | } 190 | -------------------------------------------------------------------------------- /posttypes/Posts.php: -------------------------------------------------------------------------------- 1 | 'required', 21 | 'status' => 'required', 22 | 'post_name' => 'required', 23 | ]; 24 | 25 | // Setting up the template structure 26 | public $view = [ 27 | 'default' => [ 28 | 'customFields' => [ 29 | 'text' => [ 30 | 'component' => 'niku-cms-text-customfield', 31 | 'label' => 'Text', 32 | 'value' => '', 33 | 'validation' => 'required', 34 | ], 35 | ], 36 | ], 37 | ]; 38 | 39 | /** 40 | * Determine if the user is authorized to make this request. 41 | * You can create some custom function here to manipulate 42 | * the functionalty on some certain custom actions. 43 | */ 44 | public function authorized() 45 | { 46 | return true; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/Cms.php: -------------------------------------------------------------------------------- 1 | $value) { 21 | $i++; 22 | 23 | if($i == 1){ 24 | $groups .= $value; 25 | } else { 26 | $groups .= '|' . $value; 27 | } 28 | } 29 | 30 | Route::group([ 31 | 'middleware' => 'groups:' . $groups 32 | ], function ($object) { 33 | 34 | Route::post('/config/{group}/show', '\Niku\Cms\Http\Controllers\Config\ShowConfigController@init')->name('show'); 35 | Route::post('/config/{group}/edit', '\Niku\Cms\Http\Controllers\Config\EditConfigController@init')->name('edit'); 36 | 37 | }); 38 | } 39 | 40 | public static function postTypeRoutes($postTypeConfig = []) 41 | { 42 | $postTypes = ''; 43 | $i = 0; 44 | foreach($postTypeConfig['register_post_types'] as $key => $value) { 45 | $i++; 46 | 47 | if($i == 1){ 48 | $postTypes .= $value; 49 | } else { 50 | $postTypes .= '|' . $value; 51 | } 52 | } 53 | 54 | Route::group([ 55 | 'middleware' => 'posttypes:' . $postTypes 56 | ], function ($object) { 57 | 58 | // Crud listing all posts by post type 59 | Route::post('/{post_type}/show/{identifier}', '\Niku\Cms\Http\Controllers\Cms\ShowPostController@init')->name('show'); 60 | Route::get('/{post_type}/show/{identifier}/{method}/{customid?}', '\Niku\Cms\Http\Controllers\Cms\ShowCustomGetPostController@init')->name('show'); 61 | Route::post('/{post_type}/show/{identifier}/{method}/{customid?}', '\Niku\Cms\Http\Controllers\Cms\ShowCustomGetPostController@init')->name('show'); 62 | 63 | // Taxonomy 64 | Route::post('/{post_type}/show/{identifier}/taxonomies/{sub_post_type}', '\Niku\Cms\Http\Controllers\Cms\ShowPostTaxonomies@init')->name('show'); 65 | Route::post('/{post_type}/show/{identifier}/posts/{sub_post_type}', '\Niku\Cms\Http\Controllers\Cms\ShowTaxonomyPosts@init')->name('show'); 66 | 67 | // Crud 68 | Route::post('/{post_type}/check/{identifier}', '\Niku\Cms\Http\Controllers\Cms\CheckPostController@init')->name('check'); 69 | Route::post('/{post_type}/delete/{identifier}', '\Niku\Cms\Http\Controllers\Cms\DeletePostController@init')->name('delete'); 70 | Route::post('/{post_type}/edit/{identifier}', '\Niku\Cms\Http\Controllers\Cms\EditPostController@init')->name('edit'); 71 | Route::post('/{post_type}/create', '\Niku\Cms\Http\Controllers\Cms\CreatePostController@init')->name('create'); 72 | 73 | Route::post('/{post_type}/custom/edit/{method?}', '\Niku\Cms\Http\Controllers\Cms\EditCustomPostController@init')->name('create'); 74 | Route::post('/{post_type}/custom/{method?}', '\Niku\Cms\Http\Controllers\Cms\CustomPostController@init')->name('create'); 75 | 76 | Route::post('/{post_type}/edit/{identifier}/taxonomy', '\Niku\Cms\Http\Controllers\Cms\TaxonomyController@init')->name('taxonomy'); 77 | 78 | // Single custom field updation 79 | Route::post('/{post_type}/edit-specific-fields/{identifier}', '\Niku\Cms\Http\Controllers\Cms\SpecificFieldsEditPostController@init')->name('single'); 80 | Route::post('/{post_type}/edit-specific-file/{identifier}/{key}', '\Niku\Cms\Http\Controllers\Cms\SpecificFileEditPostController@init')->name('single'); 81 | 82 | // Listing the posts 83 | Route::post('/{post_type}/{method?}/{id?}', '\Niku\Cms\Http\Controllers\Cms\ListPostsController@init')->name('list'); 84 | }); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/CmsServiceProvider.php: -------------------------------------------------------------------------------- 1 | = 5.3){ 21 | $this->loadMigrationsFrom(__DIR__.'/../database/migrations'); 22 | } 23 | 24 | // Register translations 25 | $this->loadTranslationsFrom(__DIR__.'/../translations', 'niku-assets'); 26 | 27 | // Register config 28 | $this->publishes([ 29 | __DIR__.'/../config/niku-cms.php' => config_path('niku-cms.php'), 30 | ], 'niku-config'); 31 | 32 | // Register the default post types 33 | $this->publishes([ 34 | __DIR__.'/../PostTypes' => app_path('/Cms/PostTypes'), 35 | ], 'niku-posttypes'); 36 | 37 | $this->publishes([ 38 | __DIR__.'/../Mutators' => app_path('/Cms/Mutators'), 39 | ], 'niku-posttypes'); 40 | 41 | $this->publishes([ 42 | __DIR__.'/../ConfigTypes' => app_path('/Cms/ConfigTypes'), 43 | ], 'niku-posttypes'); 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Http/Controllers/Cms/CheckPostController.php: -------------------------------------------------------------------------------- 1 | getPostType($postType); 17 | if(!$postTypeModel){ 18 | $errorMessages = 'You are not authorized to do this.'; 19 | return $this->abort($errorMessages); 20 | } 21 | 22 | if(method_exists($postTypeModel, 'override_check_post')){ 23 | return $postTypeModel->override_check_post($id, $request); 24 | } 25 | 26 | $result = $this->execute($request, $postType, $id); 27 | if($result->code == 'failure'){ 28 | return response()->json($result, 422); 29 | } 30 | 31 | $config = $this->getConfig($postTypeModel); 32 | 33 | if(method_exists($postTypeModel, 'override_check_config_response')){ 34 | $config = $postTypeModel->override_check_config_response($postTypeModel, $result->post->id, $config, $request); 35 | } 36 | 37 | $response = [ 38 | 'code' => 'success', 39 | 'message' => $result->message, 40 | 'action' => 'check', 41 | 'config' => $config, 42 | 'post' => [ 43 | 'id' => $result->post->id, 44 | 'post_title' => $result->post->post_title, 45 | 'post_name' => $result->post->post_name, 46 | 'status' => $result->post->status, 47 | 'post_type' => $result->post->post_type, 48 | 'created_at' => $result->post->created_at, 49 | 'updated_at' => $result->post->updated_at, 50 | ], 51 | ]; 52 | 53 | if(method_exists($postTypeModel, 'override_check_response')){ 54 | return $postTypeModel->override_check_response($result->post->id, $request, $response); 55 | } 56 | 57 | return response()->json($response, 200); 58 | } 59 | 60 | public function getConfig($postTypeModel) 61 | { 62 | // Merge the configuration values 63 | $config = []; 64 | if($postTypeModel->config){ 65 | $config = $postTypeModel->config; 66 | } 67 | 68 | $config = $config; 69 | 70 | // Adding public config 71 | if($postTypeModel->skipCreation){ 72 | $config['skip_creation'] = $postTypeModel->skipCreation; 73 | if($postTypeModel->skipToRouteName){ 74 | $config['skip_to_route_name'] = $postTypeModel->skipToRouteName; 75 | } 76 | } else { 77 | $config['skip_creation'] = false; 78 | $config['skip_to_route_name'] = ''; 79 | } 80 | 81 | // Adding public config 82 | if($postTypeModel->disableEditOnlyCheck){ 83 | $config['disable_edit_only_check'] = $postTypeModel->disableEditOnlyCheck; 84 | } else { 85 | $config['disable_edit_only_check'] = false; 86 | } 87 | 88 | if($postTypeModel->disableEdit){ 89 | $config['disable_edit'] = $postTypeModel->disableEdit; 90 | } else { 91 | $config['disable_edit'] = false; 92 | } 93 | 94 | if($postTypeModel->disableDelete){ 95 | $config['disable_delete'] = $postTypeModel->disableDelete; 96 | } else { 97 | $config['disable_delete'] = false; 98 | } 99 | 100 | if($postTypeModel->disableCreate){ 101 | $config['disable_create'] = $postTypeModel->disableCreate; 102 | } else { 103 | $config['disable_create'] = false; 104 | } 105 | 106 | if($postTypeModel->getPostByPostName){ 107 | $config['get_post_by_postname'] = $postTypeModel->getPostByPostName; 108 | } else { 109 | $config['get_post_by_postname'] = false; 110 | } 111 | 112 | $allKeys = collect($this->getValidationsKeys($postTypeModel)); 113 | 114 | // Adding public config 115 | if($postTypeModel->enableAllSpecificFieldsUpdate){ 116 | $config['specific_fields']['enable_all'] = $postTypeModel->enableAllSpecificFieldsUpdate; 117 | $config['specific_fields']['exclude_fields'] = $postTypeModel->excludeSpecificFieldsFromUpdate; 118 | $config['specific_fields']['enabled_fields'] = $allKeys->keys(); 119 | } else { 120 | $config['specific_fields']['enable_all'] = $postTypeModel->enableAllSpecificFieldsUpdate; 121 | $config['specific_fields']['exclude_fields'] = $postTypeModel->excludeSpecificFieldsFromUpdate; 122 | $config['specific_fields']['enabled_fields'] = $allKeys->where('single_field_updateable.active', 'true')->keys(); 123 | } 124 | 125 | return $config; 126 | } 127 | 128 | public function internal($request, $postType, $id) 129 | { 130 | $result = $this->execute($request, $postType, $id); 131 | 132 | if($result->code == 'failure'){ 133 | return $result; 134 | } 135 | 136 | return [ 137 | 'code' => 'success', 138 | 'message' => $result->message, 139 | 'action' => 'check', 140 | 'post' => [ 141 | 'id' => $result->post->id, 142 | 'post_title' => $result->post->post_title, 143 | 'post_name' => $result->post->post_name, 144 | 'status' => $result->post->status, 145 | 'post_type' => $result->post->post_type, 146 | 'created_at' => $result->post->created_at, 147 | 'updated_at' => $result->post->updated_at, 148 | ], 149 | ]; 150 | } 151 | 152 | public function execute($request, $postType, $id) 153 | { 154 | $postTypeModel = $this->getPostType($postType); 155 | if(!$postTypeModel){ 156 | $errorMessages = 'You are not authorized to do this.'; 157 | return (object) [ 158 | 'code' => 'failure', 159 | 'validation' => false, 160 | 'errors' => $errorMessages, 161 | ]; 162 | } 163 | 164 | $config = $this->getConfig($postTypeModel); 165 | 166 | // Check if the post type has a identifier 167 | if(empty($postTypeModel->identifier)){ 168 | $errorMessages = 'The post type does not have a identifier.'; 169 | if(array_has($postTypeModel->errorMessages, 'post_type_identifier_does_not_exist')){ 170 | $errorMessages = $postTypeModel->errorMessages['post_type_identifier_does_not_exist']; 171 | } 172 | return (object) [ 173 | 'code' => 'failure', 174 | 'validation' => false, 175 | 'errors' => $errorMessages, 176 | ]; 177 | } 178 | 179 | // Get the post instance 180 | $post = $this->findPostInstance($postTypeModel, $request, $postType, $id, 'check_post'); 181 | if(!$post){ 182 | $errorMessages = 'Post does not exist.'; 183 | if(array_has($postTypeModel->errorMessages, 'post_does_not_exist')){ 184 | $errorMessages = $postTypeModel->errorMessages['post_does_not_exist']; 185 | } 186 | return (object) [ 187 | 'code' => 'failure', 188 | 'validation' => false, 189 | 'errors' => $errorMessages, 190 | ]; 191 | } 192 | 193 | $allFieldKeys = $this->getValidationsKeys($postTypeModel); 194 | 195 | $secondRequest = new Request; 196 | 197 | foreach($allFieldKeys as $toSaveKey => $toSaveValue){ 198 | $configValue = $this->getCustomFieldValueWithoutConfig($postTypeModel, $post, $toSaveKey); 199 | $secondRequest[$toSaveKey] = $configValue; 200 | } 201 | 202 | // Receive the post meta values 203 | $postmeta = $secondRequest->all(); 204 | 205 | // Validating the request 206 | $validationRules = $this->validatePostFields($secondRequest->all(), $secondRequest, $postTypeModel); 207 | 208 | // Manipulate the request so we can empty out the values where the conditional field is not shown 209 | $postmeta = $this->removeValuesByConditionalLogic($postmeta, $postTypeModel, $post); 210 | $logicValidations = $this->removeValidationsByConditionalLogic($postmeta, $postTypeModel, $post); 211 | 212 | foreach($logicValidations as $postmetaKey => $postmetaValue){ 213 | if($postmetaValue === false){ 214 | if(array_key_exists($postmetaKey, $validationRules)){ 215 | unset($validationRules[$postmetaKey]); 216 | } 217 | } 218 | } 219 | 220 | $validatedFields = $this->validatePost($secondRequest, $post, $validationRules); 221 | if($validatedFields['status'] === false){ 222 | $errors = $validatedFields['errors']; 223 | return (object) [ 224 | 'code' => 'failure', 225 | 'validation' => true, 226 | 'errors' => $errors->messages(), 227 | 'config' => $config, 228 | ]; 229 | } 230 | 231 | if(method_exists($postTypeModel, 'on_check_check')){ 232 | $onCheck = $postTypeModel->on_check_check($postTypeModel, $post->id, $postmeta); 233 | if($onCheck['continue'] === false){ 234 | $errorMessages = 'You are not authorized to do this.'; 235 | if(array_key_exists('message', $onCheck)){ 236 | $errorMessages = $onCheck['message']; 237 | } 238 | return (object) [ 239 | 'code' => 'failure', 240 | 'validation' => false, 241 | 'errors' => $errorMessages, 242 | 'config' => $config, 243 | ]; 244 | } 245 | } 246 | 247 | // Lets fire events as registered in the post type 248 | $this->triggerEvent('on_check_event', $postTypeModel, $post->id, $postmeta); 249 | 250 | $successMessage = 'Post succesfully checked.'; 251 | if(array_has($postTypeModel->successMessage, 'post_checked')){ 252 | $successMessage = $postTypeModel->successMessage['post_checked']; 253 | } 254 | 255 | return (object) [ 256 | 'code' => 'success', 257 | 'post' => $post, 258 | 'message' => $successMessage, 259 | 'config' => $config, 260 | ]; 261 | 262 | } 263 | 264 | /** 265 | * Validating the creation and change of a post 266 | */ 267 | protected function validatePost($request, $post, $validationRules) 268 | { 269 | $validationRules = $this->validateFieldByConditionalLogic($validationRules, $post, $post); 270 | 271 | // Lets receive the current items from the post type validation array 272 | if(array_key_exists('post_name', $validationRules) && !is_array($validationRules['post_name'])){ 273 | 274 | $exploded = explode('|', $validationRules['post_name']); 275 | 276 | $validationRules['post_name'] = []; 277 | 278 | foreach($exploded as $key => $value){ 279 | $validationRules['post_name'][] = $value; 280 | } 281 | } 282 | 283 | // Lets validate if a post_name is required. 284 | if(!$post->disableDefaultPostName){ 285 | 286 | // If we are edditing the current existing post, we must remove the unique check 287 | if($request->get('post_name') == $post->post_name){ 288 | 289 | $validationRules['post_name'] = 'required'; 290 | 291 | // If this is not a existing post name, we need to validate if its unique. They are changing the post name. 292 | } else { 293 | 294 | // Make sure that only the post_name of the requested post_type is unique 295 | $validationRules['post_name'][] = 'required'; 296 | $validationRules['post_name'][] = Rule::unique('cms_posts')->where(function ($query) use ($post) { 297 | return $query->where('post_type', $post->identifier); 298 | }); 299 | 300 | } 301 | 302 | } 303 | 304 | $validator = Validator::make($request->all(), $validationRules); 305 | if ($validator->fails()) { 306 | return [ 307 | 'status' => false, 308 | 'errors' => $validator->errors() 309 | ]; 310 | } else { 311 | return true; 312 | } 313 | } 314 | 315 | } 316 | -------------------------------------------------------------------------------- /src/Http/Controllers/Cms/CreatePostController.php: -------------------------------------------------------------------------------- 1 | getPostType($postType); 18 | if(!$postTypeModel){ 19 | $errorMessages = 'You are not authorized to do this.'; 20 | return $this->abort($errorMessages); 21 | } 22 | 23 | // Check if the post type has a identifier 24 | if(empty($postTypeModel->identifier)){ 25 | $errorMessages = 'The post type does not have a identifier.'; 26 | if(array_has($postTypeModel->errorMessages, 'post_type_identifier_does_not_exist')){ 27 | $errorMessages = $postTypeModel->errorMessages['post_type_identifier_does_not_exist']; 28 | } 29 | return $this->abort($errorMessages); 30 | } 31 | 32 | if($postTypeModel->disableCreate){ 33 | $errorMessages = 'The post type does not support creating.'; 34 | if(array_has($postTypeModel->errorMessages, 'post_type_identifier_does_not_support_create')){ 35 | $errorMessages = $postTypeModel->errorMessages['post_type_identifier_does_not_support_create']; 36 | } 37 | return $this->abort($errorMessages); 38 | } 39 | 40 | if(method_exists($postTypeModel, 'override_create_post')){ 41 | return $postTypeModel->override_create_post($request); 42 | } 43 | 44 | // Override post meta when we need to skip creation 45 | if($postTypeModel->skipCreation === true){ 46 | 47 | $allFieldKeys = collect($this->getValidationsKeys($postTypeModel))->map(function($value, $key){ 48 | return ''; 49 | })->toArray(); 50 | 51 | // $request = $this->resetRequestValues($request); 52 | // foreach($allFieldKeys as $toSaveKey => $toSaveValue){ 53 | // $configValue = $this->getCustomFieldValue($postTypeModel, $postTypeModel, $toSaveKey); 54 | // $request[$toSaveKey] = $configValue; 55 | // } 56 | 57 | $postmeta = $request->all(); 58 | 59 | // Getting the post instance where we can add upon 60 | $post = $postTypeModel; 61 | $post->status = 'concept'; 62 | 63 | } else { 64 | 65 | $allFieldKeys = collect($this->getValidationsKeys($postTypeModel))->map(function($value, $key){ 66 | return ''; 67 | })->toArray(); 68 | 69 | // Receive the post meta values 70 | $postmeta = $request->all(); 71 | 72 | foreach($postmeta as $postmetaKey => $postmetaValue){ 73 | $allFieldKeys[$postmetaKey] = $postmeta[$postmetaKey]; 74 | } 75 | 76 | $postmeta = $allFieldKeys; 77 | 78 | // Validating the request 79 | $validationRules = $this->validatePostFields($request->all(), $request, $postTypeModel); 80 | 81 | // Validate the post 82 | $this->validatePost($postTypeModel, $request, $validationRules); 83 | 84 | // Getting the post instance where we can add upon 85 | $post = $postTypeModel; 86 | } 87 | 88 | // Lets check if we have configured a custom post type identifer 89 | if(!empty($post->identifier)){ 90 | $postType = $post->identifier; 91 | } 92 | 93 | if(method_exists($postTypeModel, 'on_create_check')){ 94 | $onCheck = $postTypeModel->on_create_check($postTypeModel, $post->id, $postmeta); 95 | if($onCheck['continue'] === false){ 96 | $errorMessages = 'You are not authorized to do this.'; 97 | if(array_key_exists('message', $onCheck)){ 98 | $errorMessages = $onCheck['message']; 99 | } 100 | return $this->abort($errorMessages); 101 | } 102 | } 103 | 104 | // Saving the post values to the database 105 | $post = $this->savePostToDatabase('create', $post, $postTypeModel, $oldRequest); 106 | 107 | // Saving the post meta values to the database 108 | $this->savePostMetaToDatabase($postmeta, $postTypeModel, $post); 109 | 110 | // Lets fire events as registered in the post type 111 | $this->triggerEvent('on_create_event', $postTypeModel, $post->id, $postmeta); 112 | 113 | $successMessage = 'Post succesfully created.'; 114 | if(array_has($postTypeModel->successMessage, 'post_created')){ 115 | $successMessage = $postTypeModel->successMessage['post_created']; 116 | } 117 | 118 | $config = $this->getConfig($postTypeModel); 119 | 120 | $post = [ 121 | 'id' => $post->id, 122 | 'post_title' => $post->post_title, 123 | 'post_name' => $post->post_name, 124 | 'status' => $post->status, 125 | 'post_type' => $post->post_type, 126 | 'created_at' => $post->created_at, 127 | 'updated_at' => $post->updated_at, 128 | ]; 129 | 130 | if(method_exists($postTypeModel, 'override_create_config_response')){ 131 | $config = $postTypeModel->override_create_config_response($postTypeModel, $post['id'], $config, $request); 132 | } 133 | 134 | // Return the response 135 | return response()->json([ 136 | 'config' => $config, 137 | 'code' => 'success', 138 | 'message' => $successMessage, 139 | 'action' => 'create', 140 | 'post' => $post, 141 | ], 200); 142 | } 143 | 144 | public function getConfig($postTypeModel) 145 | { 146 | // Merge the configuration values 147 | $config = []; 148 | if($postTypeModel->config){ 149 | $config = $postTypeModel->config; 150 | } 151 | 152 | $config = $config; 153 | 154 | // Adding public config 155 | if($postTypeModel->skipCreation){ 156 | $config['skip_creation'] = $postTypeModel->skipCreation; 157 | if($postTypeModel->skipToRouteName){ 158 | $config['skip_to_route_name'] = $postTypeModel->skipToRouteName; 159 | } 160 | } else { 161 | $config['skip_creation'] = false; 162 | $config['skip_to_route_name'] = ''; 163 | } 164 | 165 | // Adding public config 166 | if($postTypeModel->disableEditOnlyCheck){ 167 | $config['disable_edit_only_check'] = $postTypeModel->disableEditOnlyCheck; 168 | } else { 169 | $config['disable_edit_only_check'] = false; 170 | } 171 | 172 | if($postTypeModel->disableEdit){ 173 | $config['disable_edit'] = $postTypeModel->disableEdit; 174 | } else { 175 | $config['disable_edit'] = false; 176 | } 177 | 178 | if($postTypeModel->disableDelete){ 179 | $config['disable_delete'] = $postTypeModel->disableDelete; 180 | } else { 181 | $config['disable_delete'] = false; 182 | } 183 | 184 | if($postTypeModel->disableCreate){ 185 | $config['disable_create'] = $postTypeModel->disableCreate; 186 | } else { 187 | $config['disable_create'] = false; 188 | } 189 | 190 | if($postTypeModel->getPostByPostName){ 191 | $config['get_post_by_postname'] = $postTypeModel->getPostByPostName; 192 | } else { 193 | $config['get_post_by_postname'] = false; 194 | } 195 | 196 | $allKeys = collect($this->getValidationsKeys($postTypeModel)); 197 | 198 | // Adding public config 199 | if($postTypeModel->enableAllSpecificFieldsUpdate){ 200 | $config['specific_fields']['enable_all'] = $postTypeModel->enableAllSpecificFieldsUpdate; 201 | $config['specific_fields']['exclude_fields'] = $postTypeModel->excludeSpecificFieldsFromUpdate; 202 | $config['specific_fields']['enabled_fields'] = $allKeys->keys(); 203 | } else { 204 | $config['specific_fields']['enable_all'] = $postTypeModel->enableAllSpecificFieldsUpdate; 205 | $config['specific_fields']['exclude_fields'] = $postTypeModel->excludeSpecificFieldsFromUpdate; 206 | $config['specific_fields']['enabled_fields'] = $allKeys->where('single_field_updateable.active', 'true')->keys(); 207 | } 208 | 209 | return $config; 210 | } 211 | 212 | /** 213 | * Validating the creation and change of a post 214 | */ 215 | protected function validatePost($postTypeModel, $request, $validationRules) 216 | { 217 | // Lets receive the current items from the post type validation array 218 | if(array_key_exists('post_name', $validationRules) && !is_array($validationRules['post_name'])){ 219 | 220 | $exploded = explode('|', $validationRules['post_name']); 221 | 222 | $validationRules['post_name'] = []; 223 | 224 | foreach($exploded as $key => $value){ 225 | $validationRules['post_name'][] = $value; 226 | } 227 | } 228 | 229 | // Lets validate if a post_name is required. 230 | if(!$postTypeModel->disableDefaultPostName){ 231 | 232 | // Make sure that only the post_name of the requested post_type is unique 233 | $validationRules['post_name'][] = 'required'; 234 | $validationRules['post_name'][] = Rule::unique('cms_posts')->where(function ($query) use ($postTypeModel) { 235 | return $query->where('post_type', $postTypeModel->identifier); 236 | }); 237 | 238 | } 239 | 240 | return $this->validate($request, $validationRules); 241 | } 242 | } 243 | -------------------------------------------------------------------------------- /src/Http/Controllers/Cms/CustomPostController.php: -------------------------------------------------------------------------------- 1 | getPostType($postType); 20 | if(!$postTypeModel){ 21 | $errorMessages = 'You are not authorized to do this.'; 22 | return $this->abort($errorMessages); 23 | } 24 | 25 | if(!empty($method)){ 26 | 27 | if(method_exists($postTypeModel, 'show_custom_post_' . $method)){ 28 | $methodToEdit = 'show_custom_post_' . $method; 29 | return $postTypeModel->$methodToEdit($request); 30 | } else { 31 | $errorMessages = 'The post type does not have the custom method ' . $method . '.'; 32 | if(array_has($postTypeModel->errorMessages, 'post_type_does_not_have_the_support_custom_method')){ 33 | $errorMessages = $postTypeModel->errorMessages['post_type_does_not_have_the_support_custom_method']; 34 | } 35 | return $this->abort($errorMessages); 36 | } 37 | 38 | } 39 | 40 | $config = $this->getConfig($postTypeModel); 41 | 42 | // Validate if we need to validate a other post type before showing this post type 43 | $validateBefore = $this->validatePostTypeBefore($request, $postTypeModel, $id); 44 | if($validateBefore['status'] === false){ 45 | $errorMessages = $validateBefore['message']; 46 | return $this->abort($errorMessages, $validateBefore['config'], 'post_validation_error'); 47 | } 48 | 49 | $post = $this->findPostInstance($postTypeModel, $request, $postType, $id, 'show_post'); 50 | if(!$post){ 51 | $errorMessages = 'Post does not exist.'; 52 | if(array_has($postTypeModel->errorMessages, 'post_does_not_exist')){ 53 | $errorMessages = $postTypeModel->errorMessages['post_does_not_exist']; 54 | } 55 | return $this->abort($errorMessages, $config); 56 | } 57 | 58 | // Converting the updated_at to the input picker in the front-end 59 | $updatedAtCustomField = $this->getCustomFieldObject($postTypeModel, 'updated_at'); 60 | 61 | // If we have not set a custom date format, we will not touch this formatting 62 | if(!empty($updatedAtCustomField['date_format_php'])){ 63 | $post->created = $post->updated_at->format($updatedAtCustomField['date_format_php']); 64 | } 65 | 66 | // Converting the created_at to the input picker in the front-end 67 | $createdAtCustomField = $this->getCustomFieldObject($postTypeModel, 'created_at'); 68 | 69 | // If we have not set a custom date format, we will not touch this formatting 70 | if(!empty($post->created_at)){ 71 | if(!empty($createdAtCustomField['date_format_php'])){ 72 | $post->created = $post->created_at->format($createdAtCustomField['date_format_php']); 73 | } 74 | } 75 | 76 | // Retrieve all the post meta's and taxonomies 77 | $postmeta = $this->retrieveConfigPostMetas($post, $postTypeModel); 78 | 79 | $collection = []; 80 | $collection['post'] = []; 81 | $collection['postmeta'] = []; 82 | 83 | // Mergin the collection with the data and custom fields 84 | $collection['templates'] = $this->mergeCollectionWithView($postTypeModel->view, $collection, $postTypeModel); 85 | 86 | // Lets check if there are any manipulators active 87 | $collection = $this->showConditional($postTypeModel, $collection); 88 | 89 | // Lets check if there are any manipulators active 90 | $collection = $this->showMutator($postTypeModel, $collection, $request); 91 | 92 | if(method_exists($postTypeModel, 'on_show_mutator')){ 93 | $collection = $postTypeModel->on_show_mutator($postTypeModel, $post->id, $postmeta, $collection); 94 | } 95 | 96 | // Cleaning up the output 97 | unset($collection['postmeta']); 98 | 99 | if(method_exists($postTypeModel, 'on_show_check')){ 100 | $onShowCheck = $postTypeModel->on_show_check($postTypeModel, $post->id, $postmeta); 101 | if($onShowCheck['continue'] === false){ 102 | $errorMessages = 'You are not authorized to do this.'; 103 | if(array_key_exists('message', $onShowCheck)){ 104 | $errorMessages = $onShowCheck['message']; 105 | } 106 | return $this->abort($errorMessages, $config); 107 | } 108 | } 109 | 110 | // Lets fire events as registered in the post type 111 | $this->triggerEvent('on_show_event', $postTypeModel, $post->id, $postmeta); 112 | 113 | unset($collection['post']); 114 | unset($collection['postmeta']); 115 | 116 | if(method_exists($postTypeModel, 'show_custom_post')){ 117 | $methodToEdit = 'show_custom_post'; 118 | return $postTypeModel->show_custom_post($collection, $request); 119 | } else { 120 | $errorMessages = 'The post type does not have the show method'; 121 | if(array_has($postTypeModel->errorMessages, 'post_type_does_not_have_the_show_method')){ 122 | $errorMessages = $postTypeModel->errorMessages['post_type_does_not_have_the_show_method']; 123 | } 124 | return $this->abort($errorMessages); 125 | } 126 | 127 | // Returning the full collection 128 | return response()->json($collection); 129 | } 130 | 131 | public function getConfig($postTypeModel) 132 | { 133 | // Merge the configuration values 134 | $config = []; 135 | if($postTypeModel->config){ 136 | $config = $postTypeModel->config; 137 | } 138 | 139 | $config = $config; 140 | 141 | // Adding public config 142 | if($postTypeModel->skipCreation){ 143 | $config['skip_creation'] = $postTypeModel->skipCreation; 144 | if($postTypeModel->skipToRouteName){ 145 | $config['skip_to_route_name'] = $postTypeModel->skipToRouteName; 146 | } 147 | } else { 148 | $config['skip_creation'] = false; 149 | $config['skip_to_route_name'] = ''; 150 | } 151 | 152 | // Adding public config 153 | if($postTypeModel->disableEditOnlyCheck){ 154 | $config['disable_edit_only_check'] = $postTypeModel->disableEditOnlyCheck; 155 | } else { 156 | $config['disable_edit_only_check'] = false; 157 | } 158 | 159 | if($postTypeModel->disableEdit){ 160 | $config['disable_edit'] = $postTypeModel->disableEdit; 161 | } else { 162 | $config['disable_edit'] = false; 163 | } 164 | 165 | if($postTypeModel->disableDelete){ 166 | $config['disable_delete'] = $postTypeModel->disableDelete; 167 | } else { 168 | $config['disable_delete'] = false; 169 | } 170 | 171 | if($postTypeModel->disableCreate){ 172 | $config['disable_create'] = $postTypeModel->disableCreate; 173 | } else { 174 | $config['disable_create'] = false; 175 | } 176 | 177 | if($postTypeModel->getPostByPostName){ 178 | $config['get_post_by_postname'] = $postTypeModel->getPostByPostName; 179 | } else { 180 | $config['get_post_by_postname'] = false; 181 | } 182 | 183 | $allKeys = collect($this->getValidationsKeys($postTypeModel)); 184 | 185 | // Adding public config 186 | if($postTypeModel->enableAllSpecificFieldsUpdate){ 187 | $config['specific_fields']['enable_all'] = $postTypeModel->enableAllSpecificFieldsUpdate; 188 | $config['specific_fields']['exclude_fields'] = $postTypeModel->excludeSpecificFieldsFromUpdate; 189 | $config['specific_fields']['enabled_fields'] = $allKeys->keys(); 190 | } else { 191 | $config['specific_fields']['enable_all'] = $postTypeModel->enableAllSpecificFieldsUpdate; 192 | $config['specific_fields']['exclude_fields'] = $postTypeModel->excludeSpecificFieldsFromUpdate; 193 | $config['specific_fields']['enabled_fields'] = $allKeys->where('single_field_updateable.active', 'true')->keys(); 194 | } 195 | 196 | return $config; 197 | } 198 | 199 | /** 200 | * Get all the post meta keys of the post 201 | */ 202 | protected function retrieveConfigPostMetas($post, $postTypeModel) 203 | { 204 | $metaKeys = []; 205 | $metaTaxonomies = []; 206 | 207 | $allKeys = $this->getValidationsKeys($postTypeModel); 208 | foreach($allKeys as $key => $value){ 209 | 210 | $customFieldObject = $this->getCustomFieldObject($postTypeModel, $key); 211 | 212 | if(isset($customFieldObject['type']) && $customFieldObject['type'] == 'taxonomy'){ 213 | 214 | // We need to get the values from the taxonomy table 215 | if(array_key_exists('post_type', $customFieldObject)){ 216 | 217 | $customfieldPostTypes = $this->getPostTypeIdentifiers($customFieldObject['post_type']); 218 | 219 | // Lets query the post to retrieve all the connected ids 220 | $taxonomyIds = $post->taxonomies()->whereIn('post_type', $customfieldPostTypes) 221 | ->get(); 222 | 223 | // Lets foreach all the posts because we only need the id 224 | $ids = []; 225 | foreach($taxonomyIds as $value){ 226 | array_push($ids, $value->id); 227 | } 228 | 229 | $ids = json_encode($ids); 230 | 231 | $metaTaxonomies[$key] = [ 232 | 'meta_key' => $key, 233 | 'meta_value' => $ids, 234 | ]; 235 | 236 | } 237 | 238 | // The other items are default 239 | } else { 240 | 241 | // Register it to the main array so we can query it later 242 | array_push($metaKeys, $key); 243 | 244 | } 245 | 246 | } 247 | 248 | // Lets query the database to get only the values where we have registered the meta keys 249 | $postmetaSimple = $post->postmeta() 250 | ->whereIn('meta_key', $metaKeys) 251 | ->select(['meta_key', 'meta_value']) 252 | ->get() 253 | ->keyBy('meta_key') 254 | ->toArray(); 255 | 256 | // Lets attach the default post columns 257 | $defaultPostData = []; 258 | 259 | $defaultPostData['post_title'] = [ 260 | 'meta_key' => 'post_title', 261 | 'meta_value' => $post->post_title, 262 | ]; 263 | 264 | $defaultPostData['post_name'] = [ 265 | 'meta_key' => 'post_name', 266 | 'meta_value' => $post->post_name, 267 | ]; 268 | 269 | // Lets merge all the types of configs 270 | $postmeta = array_merge($postmetaSimple, $metaTaxonomies, $defaultPostData); 271 | 272 | // Return the post meta's 273 | return $postmeta; 274 | } 275 | 276 | /** 277 | * Appending the key added in the config to the array 278 | * so we can use it very easliy in the component. 279 | */ 280 | protected function mergeCollectionWithView($view, $collection, $postTypeModel) 281 | { 282 | $post = $collection['post']; 283 | $postmeta = $collection['postmeta']; 284 | 285 | // Foreaching all templates in the custom field configuration file 286 | foreach($view as $templateKey => $template){ 287 | 288 | // If the array custom fields is not empty 289 | if(!empty($template['customFields'])){ 290 | 291 | // We foreach all custom fields in this template section 292 | foreach($template['customFields'] as $customFieldKey => $customField){ 293 | 294 | // Setting post data to the custom fields 295 | switch($customFieldKey){ 296 | 297 | // If we find the customFieldKey created_at, we know it is in the config file 298 | case 'created_at': 299 | 300 | // Because of that we will add the post created_at value to the custom field 301 | if(!empty($post['created_at'])){ 302 | $view[$templateKey]['customFields'][$customFieldKey]['id'] = $customFieldKey; 303 | $view[$templateKey]['customFields'][$customFieldKey]['value'] = $post['created_at']; 304 | } 305 | 306 | break; 307 | 308 | // If we find the customFieldKey updated_at, we know it is in the config file 309 | case 'updated_at': 310 | 311 | // Because of that we will add the post updated_at value to the custom field 312 | if(!empty($post['updated_at'])){ 313 | $view[$templateKey]['customFields'][$customFieldKey]['id'] = $customFieldKey; 314 | $view[$templateKey]['customFields'][$customFieldKey]['value'] = $post['updated_at']; 315 | } 316 | 317 | break; 318 | 319 | // If we find the customFieldKey updated_at, we know it is in the config file 320 | case 'status': 321 | 322 | // Because of that we will add the post status value to the custom field 323 | if(!empty($post['status'])){ 324 | $view[$templateKey]['customFields'][$customFieldKey]['id'] = $customFieldKey; 325 | $view[$templateKey]['customFields'][$customFieldKey]['value'] = $post['status']; 326 | } 327 | 328 | break; 329 | } 330 | 331 | // Lets set the key to the array 332 | $view[$templateKey]['customFields'][$customFieldKey]['id'] = $customFieldKey; 333 | 334 | if(array_key_exists($customFieldKey, $postmeta)){ 335 | $view[$templateKey]['customFields'][$customFieldKey]['value'] = $postmeta[$customFieldKey]['meta_value']; 336 | } 337 | 338 | // When output is disabled, we need to remove the fields from the arrays 339 | if(array_key_exists('output', $customField) && !$customField['output']){ 340 | unset($view[$templateKey]['customFields'][$customFieldKey]); 341 | } 342 | 343 | // If the array custom fields is not empty 344 | if(!empty($customField['customFields'])){ 345 | 346 | // We foreach all custom fields in this template section 347 | foreach($customField['customFields'] as $innerCustomFieldKey => $innerCustomField){ 348 | 349 | // Lets set the key to the array 350 | $view[$templateKey]['customFields'][$customFieldKey]['customFields'][$innerCustomFieldKey]['id'] = $innerCustomFieldKey; 351 | 352 | if(array_key_exists($innerCustomFieldKey, $postmeta)){ 353 | $view[$templateKey]['customFields'][$customFieldKey]['customFields'][$innerCustomFieldKey]['value'] = $postmeta[$innerCustomFieldKey]['meta_value']; 354 | } 355 | 356 | // When output is disabled, we need to remove the fields from the arrays 357 | if(array_key_exists('output', $innerCustomField) && !$innerCustomField['output']){ 358 | unset($view[$templateKey]['customFields'][$customFieldKey]['customFields'][$innerCustomFieldKey]); 359 | } 360 | 361 | } 362 | 363 | // If the array custom fields is not empty 364 | if(!empty($innerCustomField['customFields'])){ 365 | 366 | // We foreach all custom fields in this template section 367 | foreach($innerCustomField['customFields'] as $innerInnerCustomFieldKey => $innerInnerCustomField){ 368 | 369 | // Lets set the key to the array 370 | $view[$templateKey]['customFields'][$customFieldKey]['customFields'][$innerCustomFieldKey]['customFields'][$innerInnerCustomFieldKey]['id'] = $innerInnerCustomFieldKey; 371 | 372 | if(array_key_exists($innerInnerCustomFieldKey, $postmeta)){ 373 | $view[$templateKey]['customFields'][$customFieldKey]['customFields'][$innerCustomFieldKey]['customFields'][$innerInnerCustomFieldKey]['value'] = $postmeta[$innerInnerCustomFieldKey]['meta_value']; 374 | } 375 | 376 | // When output is disabled, we need to remove the fields from the arrays 377 | if(array_key_exists('output', $innerInnerCustomField) && !$innerInnerCustomField['output']){ 378 | unset($view[$templateKey]['customFields'][$customFieldKey]['customFields'][$innerCustomFieldKey]['customFields'][$innerInnerCustomFieldKey]); 379 | } 380 | 381 | } 382 | } 383 | } 384 | } 385 | } 386 | } 387 | 388 | return $view; 389 | } 390 | } 391 | -------------------------------------------------------------------------------- /src/Http/Controllers/Cms/DeletePostController.php: -------------------------------------------------------------------------------- 1 | getPostType($postType); 18 | if(!$postTypeModel){ 19 | $errorMessages = 'You are not authorized to do this.'; 20 | return $this->abort($errorMessages); 21 | } 22 | 23 | if(method_exists($postTypeModel, 'override_delete_post')){ 24 | return $postTypeModel->override_delete_post($id, $request); 25 | } 26 | 27 | // Check if the post type has a identifier 28 | if(empty($postTypeModel->identifier)){ 29 | $errorMessages = 'The post type does not have a identifier.'; 30 | if(array_has($postTypeModel->errorMessages, 'post_type_identifier_does_not_exist')){ 31 | $errorMessages = $postTypeModel->errorMessages['post_type_identifier_does_not_exist']; 32 | } 33 | return $this->abort($errorMessages); 34 | } 35 | 36 | $post = $this->findPostInstance($postTypeModel, $request, $postType, $id, 'delete_post'); 37 | if(!$post){ 38 | $errorMessages = 'Post does not exist.'; 39 | if(array_has($postTypeModel->errorMessages, 'post_does_not_exist')){ 40 | $errorMessages = $postTypeModel->errorMessages['post_does_not_exist']; 41 | } 42 | return $this->abort($errorMessages); 43 | } 44 | 45 | if($postTypeModel->disableDelete){ 46 | $errorMessages = 'The post type does not support deleting.'; 47 | if(array_has($postTypeModel->errorMessages, 'post_type_identifier_does_not_support_deleting')){ 48 | $errorMessages = $postTypeModel->errorMessages['post_type_identifier_does_not_support_deleting']; 49 | } 50 | return $this->abort($errorMessages); 51 | } 52 | 53 | if(method_exists($postTypeModel, 'on_delete_check')){ 54 | $onCheck = $postTypeModel->on_delete_check($postTypeModel, $post->id, []); 55 | if($onCheck['continue'] === false){ 56 | $errorMessages = 'You are not authorized to do this.'; 57 | if(array_key_exists('message', $onCheck)){ 58 | $errorMessages = $onCheck['message']; 59 | } 60 | return $this->abort($errorMessages); 61 | } 62 | } 63 | 64 | // Delete the post 65 | $post->delete(); 66 | 67 | // Lets fire events as registered in the post type 68 | $this->triggerEvent('on_delete_event', $postTypeModel, $post->id, []); 69 | 70 | $successMessage = 'Post succesfully deleted.'; 71 | if(array_has($postTypeModel->successMessage, 'post_deleted')){ 72 | $successMessage = $postTypeModel->successMessage['post_deleted']; 73 | } 74 | 75 | if(method_exists($postTypeModel, 'override_delete_response')){ 76 | return $postTypeModel->override_delete_response($post, $request); 77 | } 78 | 79 | // Return the response 80 | return response()->json([ 81 | 'code' => 'success', 82 | 'message' => $successMessage, 83 | 'post' => [ 84 | 'id' => $post->id, 85 | 'post_title' => $post->post_title, 86 | 'post_name' => $post->post_name, 87 | 'status' => $post->status, 88 | 'post_type' => $post->post_type, 89 | 'created_at' => $post->created_at, 90 | 'updated_at' => $post->updated_at, 91 | ], 92 | ], 200); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/Http/Controllers/Cms/EditCustomPostController.php: -------------------------------------------------------------------------------- 1 | getPostType($postType); 15 | if(!$postTypeModel){ 16 | $errorMessages = 'You are not authorized to do this.'; 17 | return $this->abort($errorMessages); 18 | } 19 | 20 | if($postTypeModel->enableCustomValidations === true){ 21 | $validationRules = $this->validatePostFields($request->all(), $request, $postTypeModel); 22 | $this->validate($request, $validationRules); 23 | } 24 | 25 | if(empty($method)){ 26 | if(method_exists($postTypeModel, 'edit_custom_post')){ 27 | return $postTypeModel->edit_custom_post($request); 28 | } else { 29 | $errorMessages = 'The post type does not have the custom method.'; 30 | if(array_has($postTypeModel->errorMessages, 'post_type_does_not_have_the_support_custom_method')){ 31 | $errorMessages = $postTypeModel->errorMessages['post_type_does_not_have_the_support_custom_method']; 32 | } 33 | return $this->abort($errorMessages); 34 | } 35 | 36 | } else { 37 | 38 | if(method_exists($postTypeModel, 'edit_custom_post_' . $method)){ 39 | $methodToEdit = 'edit_custom_post_' . $method; 40 | return $postTypeModel->$methodToEdit($request); 41 | } else { 42 | $errorMessages = 'The post type does not have the custom method ' . $method . '.'; 43 | if(array_has($postTypeModel->errorMessages, 'post_type_does_not_have_the_support_custom_method')){ 44 | $errorMessages = $postTypeModel->errorMessages['post_type_does_not_have_the_support_custom_method']; 45 | } 46 | return $this->abort($errorMessages); 47 | } 48 | 49 | } 50 | 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/Http/Controllers/Cms/EditPostController.php: -------------------------------------------------------------------------------- 1 | getPostType($postType); 15 | if(!$postTypeModel){ 16 | $errorMessages = 'You are not authorized to do this.'; 17 | return $this->abort($errorMessages); 18 | } 19 | 20 | if(method_exists($postTypeModel, 'override_edit_post')){ 21 | return $postTypeModel->override_edit_post($id, $request); 22 | } 23 | 24 | // Check if the post type has a identifier 25 | if(empty($postTypeModel->identifier)){ 26 | $errorMessages = 'The post type does not have a identifier.'; 27 | if(array_has($postTypeModel->errorMessages, 'post_type_identifier_does_not_exist')){ 28 | $errorMessages = $postTypeModel->errorMessages['post_type_identifier_does_not_exist']; 29 | } 30 | return $this->abort($errorMessages); 31 | } 32 | 33 | // Validate if we need to validate a other post type before showing this post type 34 | $validateBefore = $this->validatePostTypeBefore($request, $postTypeModel, $id); 35 | if($validateBefore['status'] === false){ 36 | $errorMessages = $validateBefore['message']; 37 | return $this->abort($errorMessages, $validateBefore['config']); 38 | } 39 | 40 | // Disable editting of form 41 | if($postTypeModel->disableEditOnlyCheck){ 42 | $errorMessages = 'The post type does not support editting.'; 43 | if(array_has($postTypeModel->errorMessages, 'post_type_identifier_does_not_support_edit')){ 44 | $errorMessages = $postTypeModel->errorMessages['post_type_identifier_does_not_support_edit']; 45 | } 46 | return $this->abort($errorMessages); 47 | } 48 | 49 | // Disable editting of form 50 | if($postTypeModel->disableEdit){ 51 | $errorMessages = 'The post type does not support editting.'; 52 | if(array_has($postTypeModel->errorMessages, 'post_type_identifier_does_not_support_edit')){ 53 | $errorMessages = $postTypeModel->errorMessages['post_type_identifier_does_not_support_edit']; 54 | } 55 | return $this->abort($errorMessages); 56 | } 57 | 58 | $allFieldKeys = collect($this->getValidationsKeys($postTypeModel))->map(function($value, $key){ 59 | return ''; 60 | })->toArray(); 61 | 62 | // Receive the post meta values 63 | $postmeta = $request->all(); 64 | 65 | foreach($postmeta as $postmetaKey => $postmetaValue){ 66 | $allFieldKeys[$postmetaKey] = $postmeta[$postmetaKey]; 67 | } 68 | 69 | $postmeta = $allFieldKeys; 70 | 71 | // Validating the request 72 | $validationRules = $this->validatePostFields($request->all(), $request, $postTypeModel); 73 | 74 | // Unset unrequired post meta keys 75 | $postmeta = $this->removeUnrequiredMetas($postmeta, $postTypeModel); 76 | 77 | $config = $this->getConfig($postTypeModel); 78 | 79 | // Get the post instance 80 | $post = $this->findPostInstance($postTypeModel, $request, $postType, $id, 'edit_post'); 81 | if(!$post){ 82 | $errorMessages = 'Post does not exist.'; 83 | if(array_has($postTypeModel->errorMessages, 'post_does_not_exist')){ 84 | $errorMessages = $postTypeModel->errorMessages['post_does_not_exist']; 85 | } 86 | return $this->abort($errorMessages, $config); 87 | } 88 | 89 | if(method_exists($postTypeModel, 'override_edit_config_response')){ 90 | $config = $postTypeModel->override_edit_config_response($postTypeModel, $post->id, $config, $request); 91 | } 92 | 93 | // Manipulate the request so we can empty out the values where the conditional field is not shown 94 | $postmeta = $this->removeValuesByConditionalLogic($postmeta, $postTypeModel, $post); 95 | $logicValidations = $this->removeValidationsByConditionalLogic($postmeta, $postTypeModel, $post); 96 | 97 | foreach($logicValidations as $postmetaKey => $postmetaValue){ 98 | if($postmetaValue === false){ 99 | if(array_key_exists($postmetaKey, $validationRules)){ 100 | unset($validationRules[$postmetaKey]); 101 | } 102 | } 103 | } 104 | 105 | $this->validatePost($request, $post, $validationRules); 106 | 107 | if(method_exists($postTypeModel, 'on_edit_check')){ 108 | $onCheck = $postTypeModel->on_edit_check($postTypeModel, $post->id, $postmeta); 109 | if($onCheck['continue'] === false){ 110 | $errorMessages = 'You are not authorized to do this.'; 111 | if(array_key_exists('message', $onCheck)){ 112 | $errorMessages = $onCheck['message']; 113 | } 114 | return response()->json($errorMessages, 422); 115 | } 116 | } 117 | 118 | // Saving the post values to the database 119 | $post = $this->savePostToDatabase('edit', $post, $postTypeModel, $request, $postType); 120 | 121 | // Saving the post meta values to the database 122 | $this->savePostMetaToDatabase($postmeta, $postTypeModel, $post); 123 | 124 | // Lets fire events as registered in the post type 125 | $this->triggerEvent('on_edit_event', $postTypeModel, $post->id, $postmeta); 126 | 127 | $successMessage = 'Post succesfully updated.'; 128 | if(array_has($postTypeModel->successMessage, 'post_updated')){ 129 | $successMessage = $postTypeModel->successMessage['post_updated']; 130 | } 131 | 132 | $response = [ 133 | 'config' => $config, 134 | 'code' => 'success', 135 | 'message' => $successMessage, 136 | 'action' => 'edit', 137 | 'post' => [ 138 | 'id' => $post->id, 139 | 'post_title' => $post->post_title, 140 | 'post_name' => $post->post_name, 141 | 'status' => $post->status, 142 | 'post_type' => $post->post_type, 143 | 'created_at' => $post->created_at, 144 | 'updated_at' => $post->updated_at, 145 | ], 146 | ]; 147 | 148 | if(method_exists($postTypeModel, 'override_edit_response')){ 149 | return $postTypeModel->override_edit_response($post->id, $request, $response); 150 | } 151 | 152 | // Lets return the response 153 | return response()->json($response, 200); 154 | } 155 | 156 | public function getConfig($postTypeModel) 157 | { 158 | // Merge the configuration values 159 | $config = []; 160 | if($postTypeModel->config){ 161 | $config = $postTypeModel->config; 162 | } 163 | 164 | $config = $config; 165 | 166 | // Adding public config 167 | if($postTypeModel->skipCreation){ 168 | $config['skip_creation'] = $postTypeModel->skipCreation; 169 | if($postTypeModel->skipToRouteName){ 170 | $config['skip_to_route_name'] = $postTypeModel->skipToRouteName; 171 | } 172 | } else { 173 | $config['skip_creation'] = false; 174 | $config['skip_to_route_name'] = ''; 175 | } 176 | 177 | // Adding public config 178 | if($postTypeModel->disableEditOnlyCheck){ 179 | $config['disable_edit_only_check'] = $postTypeModel->disableEditOnlyCheck; 180 | } else { 181 | $config['disable_edit_only_check'] = false; 182 | } 183 | 184 | if($postTypeModel->disableEdit){ 185 | $config['disable_edit'] = $postTypeModel->disableEdit; 186 | } else { 187 | $config['disable_edit'] = false; 188 | } 189 | 190 | if($postTypeModel->disableDelete){ 191 | $config['disable_delete'] = $postTypeModel->disableDelete; 192 | } else { 193 | $config['disable_delete'] = false; 194 | } 195 | 196 | if($postTypeModel->disableCreate){ 197 | $config['disable_create'] = $postTypeModel->disableCreate; 198 | } else { 199 | $config['disable_create'] = false; 200 | } 201 | 202 | if($postTypeModel->getPostByPostName){ 203 | $config['get_post_by_postname'] = $postTypeModel->getPostByPostName; 204 | } else { 205 | $config['get_post_by_postname'] = false; 206 | } 207 | 208 | $allKeys = collect($this->getValidationsKeys($postTypeModel)); 209 | 210 | // Adding public config 211 | if($postTypeModel->enableAllSpecificFieldsUpdate){ 212 | $config['specific_fields']['enable_all'] = $postTypeModel->enableAllSpecificFieldsUpdate; 213 | $config['specific_fields']['exclude_fields'] = $postTypeModel->excludeSpecificFieldsFromUpdate; 214 | $config['specific_fields']['enabled_fields'] = $allKeys->keys(); 215 | } else { 216 | $config['specific_fields']['enable_all'] = $postTypeModel->enableAllSpecificFieldsUpdate; 217 | $config['specific_fields']['exclude_fields'] = $postTypeModel->excludeSpecificFieldsFromUpdate; 218 | $config['specific_fields']['enabled_fields'] = $allKeys->where('single_field_updateable.active', 'true')->keys(); 219 | } 220 | 221 | return $config; 222 | } 223 | 224 | /** 225 | * Validating the creation and change of a post 226 | */ 227 | protected function validatePost($request, $post, $validationRules) 228 | { 229 | $validationRules = $this->validateFieldByConditionalLogic($validationRules, $post, $post); 230 | 231 | // Lets receive the current items from the post type validation array 232 | if(array_key_exists('post_name', $validationRules) && !is_array($validationRules['post_name'])){ 233 | 234 | $exploded = explode('|', $validationRules['post_name']); 235 | 236 | $validationRules['post_name'] = []; 237 | 238 | foreach($exploded as $key => $value){ 239 | $validationRules['post_name'][] = $value; 240 | } 241 | } 242 | 243 | // Lets validate if a post_name is required. 244 | if(!$post->disableDefaultPostName){ 245 | 246 | // If we are edditing the current existing post, we must remove the unique check 247 | if($request->get('post_name') == $post->post_name){ 248 | 249 | $validationRules['post_name'] = 'required'; 250 | 251 | // If this is not a existing post name, we need to validate if its unique. They are changing the post name. 252 | } else { 253 | 254 | // Make sure that only the post_name of the requested post_type is unique 255 | $validationRules['post_name'][] = 'required'; 256 | $validationRules['post_name'][] = Rule::unique('cms_posts')->where(function ($query) use ($post) { 257 | return $query->where('post_type', $post->identifier); 258 | }); 259 | 260 | } 261 | 262 | } 263 | 264 | return $this->validate($request, $validationRules); 265 | } 266 | 267 | } 268 | -------------------------------------------------------------------------------- /src/Http/Controllers/Cms/ListPostsController.php: -------------------------------------------------------------------------------- 1 | getPostType($postType); 15 | if(!$postTypeModel){ 16 | $errorMessages = 'You are not authorized to do this.'; 17 | return $this->abort($errorMessages); 18 | } 19 | 20 | if(!empty($method)){ 21 | if(method_exists($postTypeModel, 'get_custom_list_' . $method)){ 22 | $methodToEdit = 'get_custom_list_' . $method; 23 | return $postTypeModel->$methodToEdit($request, $customId); 24 | } else { 25 | $errorMessages = 'The post type does not have the custom list get method ' . $method . '.'; 26 | if(array_has($postTypeModel->errorMessages, 'post_type_does_not_have_the_support_custom_list_get_method')){ 27 | $errorMessages = $postTypeModel->errorMessages['post_type_does_not_have_the_support_custom_list_get_method']; 28 | } 29 | return $this->abort($errorMessages); 30 | } 31 | } 32 | 33 | if(method_exists($postTypeModel, 'override_list_post')){ 34 | return $postTypeModel->override_list_post($id, $request); 35 | } 36 | 37 | // Check if the post type has a identifier 38 | if(empty($postTypeModel->identifier)){ 39 | $errorMessages = 'The post type does not have a identifier.'; 40 | if(array_has($postTypeModel->errorMessages, 'post_type_identifier_does_not_exist')){ 41 | $errorMessages = $postTypeModel->errorMessages['post_type_identifier_does_not_exist']; 42 | } 43 | return $this->abort($errorMessages); 44 | } 45 | 46 | if($postTypeModel->overrideDefaultListing === true){ 47 | 48 | if(method_exists($postTypeModel, 'override_listing_show_method')){ 49 | return $postTypeModel->override_listing_show_method($request, $postType); 50 | } else { 51 | $errorMessages = 'The post type does not have the custom method'; 52 | if(array_has($postTypeModel->errorMessages, 'post_type_does_not_have_the_support_custom_method')){ 53 | $errorMessages = $postTypeModel->errorMessages['post_type_does_not_have_the_support_custom_method']; 54 | } 55 | return $this->abort($errorMessages); 56 | } 57 | 58 | // Return the response 59 | return response()->json([ 60 | 'config' => $config, 61 | 'label' => $postTypeModel->label, 62 | 'objects' => $posts, 63 | ]); 64 | 65 | } 66 | 67 | $where = []; 68 | 69 | // If the user can only see his own posts 70 | if($postTypeModel->userCanOnlySeeHisOwnPosts){ 71 | $where[] = ['post_author', '=', Auth::user()->id]; 72 | } 73 | 74 | // Lets check if we have configured a custom post type identifer 75 | if(!empty($postTypeModel->identifier)){ 76 | $postType = $postTypeModel->identifier; 77 | } 78 | 79 | $postTypeAliases = []; 80 | $postTypeIsArray = false; 81 | if(!empty($postTypeModel->postTypeAliases)){ 82 | if(is_array($postTypeModel->postTypeAliases)){ 83 | if(count($postTypeModel->postTypeAliases) > 0){ 84 | $postTypeIsArray = true; 85 | $postTypeAliases = $postTypeModel->postTypeAliases; 86 | $postTypeAliases[] = $postType; 87 | } 88 | } 89 | } 90 | 91 | // Adding a custom query functionality so we can manipulate the find by the config 92 | if($postTypeModel->appendCustomWhereQueryToCmsPosts){ 93 | foreach($postTypeModel->appendCustomWhereQueryToCmsPosts as $key => $value){ 94 | $where[] = [$value[0], $value[1], $value[2]]; 95 | } 96 | } 97 | 98 | $appendQuery = false; 99 | if(method_exists($postTypeModel, 'append_list_query')){ 100 | $appendQuery = true; 101 | } 102 | 103 | // Query the database 104 | $posts = $postTypeModel::where($where) 105 | ->when($appendQuery, function ($query) use ($postTypeModel, $request){ 106 | return $postTypeModel->append_list_query($query, $postTypeModel, $request); 107 | }) 108 | 109 | // When there are multiple post types 110 | ->when($postTypeIsArray, function ($query) use ($postTypeAliases){ 111 | return $query->whereIn('post_type', $postTypeAliases); 112 | }, function($query) use ($postType) { 113 | return $query->where('post_type', $postType); 114 | }) 115 | 116 | ->select([ 117 | 'id', 118 | 'post_title', 119 | 'post_name', 120 | 'status', 121 | 'post_type', 122 | 'created_at', 123 | 'updated_at', 124 | ]) 125 | ->with('postmeta') 126 | ->orderBy('id', 'desc') 127 | ->get(); 128 | 129 | if($postTypeModel->getPostByPostName === false){ 130 | $posts->map(function($item, $key){ 131 | $item->post_name = $item->id; 132 | return $item; 133 | }); 134 | } 135 | 136 | 137 | if(method_exists($postTypeModel, 'on_list_check')){ 138 | $onCheck = $postTypeModel->on_list_check($postTypeModel, $posts, []); 139 | if($onCheck['continue'] === false){ 140 | $errorMessages = 'You are not authorized to do this.'; 141 | if(array_key_exists('message', $onCheck)){ 142 | $errorMessages = $onCheck['message']; 143 | } 144 | return $this->abort($errorMessages); 145 | } 146 | } 147 | 148 | // Lets fire events as registered in the post type 149 | $this->triggerEvent('on_browse_event', $postTypeModel, $posts, []); 150 | 151 | $config = $this->getConfig($postTypeModel); 152 | 153 | // Return the response 154 | return response()->json([ 155 | 'config' => $config, 156 | 'label' => $postTypeModel->label, 157 | 'objects' => $posts, 158 | ]); 159 | } 160 | 161 | public function getConfig($postTypeModel) 162 | { 163 | // Merge the configuration values 164 | $config = []; 165 | if($postTypeModel->config){ 166 | $config = $postTypeModel->config; 167 | } 168 | 169 | $config = $config; 170 | 171 | // Adding public config 172 | if($postTypeModel->skipCreation){ 173 | $config['skip_creation'] = $postTypeModel->skipCreation; 174 | if($postTypeModel->skipToRouteName){ 175 | $config['skip_to_route_name'] = $postTypeModel->skipToRouteName; 176 | } 177 | } else { 178 | $config['skip_creation'] = false; 179 | $config['skip_to_route_name'] = ''; 180 | } 181 | 182 | // Adding public config 183 | if($postTypeModel->disableEditOnlyCheck){ 184 | $config['disable_edit_only_check'] = $postTypeModel->disableEditOnlyCheck; 185 | } else { 186 | $config['disable_edit_only_check'] = false; 187 | } 188 | 189 | if($postTypeModel->disableEdit){ 190 | $config['disable_edit'] = $postTypeModel->disableEdit; 191 | } else { 192 | $config['disable_edit'] = false; 193 | } 194 | 195 | if($postTypeModel->disableDelete){ 196 | $config['disable_delete'] = $postTypeModel->disableDelete; 197 | } else { 198 | $config['disable_delete'] = false; 199 | } 200 | 201 | if($postTypeModel->disableCreate){ 202 | $config['disable_create'] = $postTypeModel->disableCreate; 203 | } else { 204 | $config['disable_create'] = false; 205 | } 206 | 207 | if($postTypeModel->getPostByPostName){ 208 | $config['get_post_by_postname'] = $postTypeModel->getPostByPostName; 209 | } else { 210 | $config['get_post_by_postname'] = false; 211 | } 212 | 213 | return $config; 214 | } 215 | } 216 | -------------------------------------------------------------------------------- /src/Http/Controllers/Cms/ShowCustomGetPostController.php: -------------------------------------------------------------------------------- 1 | getPostType($postType); 18 | if(!$postTypeModel){ 19 | $errorMessages = 'You are not authorized to do this.'; 20 | return $this->abort($errorMessages); 21 | } 22 | 23 | $config = $this->getConfig($postTypeModel); 24 | 25 | // Check if the post type has a identifier 26 | if(empty($postTypeModel->identifier)){ 27 | $errorMessages = 'The post type does not have a identifier.'; 28 | if(array_has($postTypeModel->errorMessages, 'post_type_identifier_does_not_exist')){ 29 | $errorMessages = $postTypeModel->errorMessages['post_type_identifier_does_not_exist']; 30 | } 31 | return $this->abort($errorMessages, $config); 32 | } 33 | 34 | $post = $this->findPostInstance($postTypeModel, $request, $postType, $id, 'show_post'); 35 | if(!$post){ 36 | $errorMessages = 'Post does not exist.'; 37 | if(array_has($postTypeModel->errorMessages, 'post_does_not_exist')){ 38 | $errorMessages = $postTypeModel->errorMessages['post_does_not_exist']; 39 | } 40 | return $this->abort($errorMessages, $config); 41 | } 42 | 43 | if(method_exists($postTypeModel, 'show_custom_get_' . $method)){ 44 | $methodToEdit = 'show_custom_get_' . $method; 45 | return $postTypeModel->$methodToEdit($request, $id, $customId, $post); 46 | } else { 47 | $errorMessages = 'The post type does not have the custom show get method ' . $method . '.'; 48 | if(array_has($postTypeModel->errorMessages, 'post_type_does_not_have_the_support_custom_show_getmethod')){ 49 | $errorMessages = $postTypeModel->errorMessages['post_type_does_not_have_the_support_custom_show_getmethod']; 50 | } 51 | return $this->abort($errorMessages); 52 | } 53 | } 54 | 55 | public function getConfig($postTypeModel) 56 | { 57 | // Merge the configuration values 58 | $config = []; 59 | if($postTypeModel->config){ 60 | $config = $postTypeModel->config; 61 | } 62 | 63 | $config = $config; 64 | 65 | // Adding public config 66 | if($postTypeModel->skipCreation){ 67 | $config['skip_creation'] = $postTypeModel->skipCreation; 68 | if($postTypeModel->skipToRouteName){ 69 | $config['skip_to_route_name'] = $postTypeModel->skipToRouteName; 70 | } 71 | } else { 72 | $config['skip_creation'] = false; 73 | $config['skip_to_route_name'] = ''; 74 | } 75 | 76 | // Adding public config 77 | if($postTypeModel->disableEditOnlyCheck){ 78 | $config['disable_edit_only_check'] = $postTypeModel->disableEditOnlyCheck; 79 | } else { 80 | $config['disable_edit_only_check'] = false; 81 | } 82 | 83 | if($postTypeModel->disableEdit){ 84 | $config['disable_edit'] = $postTypeModel->disableEdit; 85 | } else { 86 | $config['disable_edit'] = false; 87 | } 88 | 89 | if($postTypeModel->disableDelete){ 90 | $config['disable_delete'] = $postTypeModel->disableDelete; 91 | } else { 92 | $config['disable_delete'] = false; 93 | } 94 | 95 | if($postTypeModel->disableCreate){ 96 | $config['disable_create'] = $postTypeModel->disableCreate; 97 | } else { 98 | $config['disable_create'] = false; 99 | } 100 | 101 | if($postTypeModel->getPostByPostName){ 102 | $config['get_post_by_postname'] = $postTypeModel->getPostByPostName; 103 | } else { 104 | $config['get_post_by_postname'] = false; 105 | } 106 | 107 | $allKeys = collect($this->getValidationsKeys($postTypeModel)); 108 | 109 | // Adding public config 110 | if($postTypeModel->enableAllSpecificFieldsUpdate){ 111 | $config['specific_fields']['enable_all'] = $postTypeModel->enableAllSpecificFieldsUpdate; 112 | $config['specific_fields']['exclude_fields'] = $postTypeModel->excludeSpecificFieldsFromUpdate; 113 | $config['specific_fields']['enabled_fields'] = $allKeys->keys(); 114 | } else { 115 | $config['specific_fields']['enable_all'] = $postTypeModel->enableAllSpecificFieldsUpdate; 116 | $config['specific_fields']['exclude_fields'] = $postTypeModel->excludeSpecificFieldsFromUpdate; 117 | $config['specific_fields']['enabled_fields'] = $allKeys->where('single_field_updateable.active', 'true')->keys(); 118 | } 119 | 120 | return $config; 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/Http/Controllers/Cms/ShowPostController.php: -------------------------------------------------------------------------------- 1 | getPostType($postType); 18 | if(!$postTypeModel){ 19 | $errorMessages = 'You are not authorized to do this.'; 20 | return $this->abort($errorMessages); 21 | } 22 | 23 | if(method_exists($postTypeModel, 'override_show_post')){ 24 | return $postTypeModel->override_show_post($id, $request, $postType); 25 | } 26 | 27 | $config = $this->getConfig($postTypeModel); 28 | 29 | // Check if the post type has a identifier 30 | if(empty($postTypeModel->identifier)){ 31 | $errorMessages = 'The post type does not have a identifier.'; 32 | if(array_has($postTypeModel->errorMessages, 'post_type_identifier_does_not_exist')){ 33 | $errorMessages = $postTypeModel->errorMessages['post_type_identifier_does_not_exist']; 34 | } 35 | return $this->abort($errorMessages, $config); 36 | } 37 | 38 | // Validate if we need to validate a other post type before showing this post type 39 | $validateBefore = $this->validatePostTypeBefore($request, $postTypeModel, $id); 40 | if($validateBefore['status'] === false){ 41 | $errorMessages = $validateBefore['message']; 42 | return $this->abort($errorMessages, $validateBefore['config'], 'post_validation_error'); 43 | } 44 | 45 | $post = $this->findPostInstance($postTypeModel, $request, $postType, $id, 'show_post'); 46 | if(!$post){ 47 | $errorMessages = 'Post does not exist.'; 48 | if(array_has($postTypeModel->errorMessages, 'post_does_not_exist')){ 49 | $errorMessages = $postTypeModel->errorMessages['post_does_not_exist']; 50 | } 51 | return $this->abort($errorMessages, $config); 52 | } 53 | 54 | // Converting the updated_at to the input picker in the front-end 55 | $updatedAtCustomField = $this->getCustomFieldObject($postTypeModel, 'updated_at'); 56 | 57 | // If we have not set a custom date format, we will not touch this formatting 58 | if(!empty($updatedAtCustomField['date_format_php'])){ 59 | $post->created = $post->updated_at->format($updatedAtCustomField['date_format_php']); 60 | } 61 | 62 | // Converting the created_at to the input picker in the front-end 63 | $createdAtCustomField = $this->getCustomFieldObject($postTypeModel, 'created_at'); 64 | 65 | // If we have not set a custom date format, we will not touch this formatting 66 | if(!empty($post->created_at)){ 67 | if(!empty($createdAtCustomField['date_format_php'])){ 68 | $post->created = $post->created_at->format($createdAtCustomField['date_format_php']); 69 | } 70 | } 71 | 72 | // Retrieve all the post meta's and taxonomies 73 | $postmeta = $this->retrieveConfigPostMetas($post, $postTypeModel); 74 | 75 | $postArray = $post->toArray(); 76 | 77 | $postArraySanitized = []; 78 | 79 | if(array_has($postArray, 'id')){ 80 | $postArraySanitized['id'] = $postArray['id']; 81 | } 82 | 83 | if(array_has($postArray, 'post_title')){ 84 | $postArraySanitized['post_title'] = $postArray['post_title']; 85 | } 86 | 87 | if(array_has($postArray, 'post_name')){ 88 | $postArraySanitized['post_name'] = $postArray['post_name']; 89 | } 90 | 91 | if(array_has($postArray, 'status')){ 92 | $postArraySanitized['status'] = $postArray['status']; 93 | } 94 | 95 | if(array_has($postArray, 'post_type')){ 96 | $postArraySanitized['post_type'] = $postArray['post_type']; 97 | } 98 | 99 | if(array_has($postArray, 'created_at')){ 100 | $postArraySanitized['created_at'] = $postArray['created_at']; 101 | } 102 | 103 | if(array_has($postArray, 'updated_at')){ 104 | $postArraySanitized['updated_at'] = $postArray['updated_at']; 105 | } 106 | 107 | // Format the collection 108 | $collection = [ 109 | 'post' => $postArraySanitized, 110 | 'postmeta' => $postmeta, 111 | ]; 112 | 113 | // Mergin the collection with the data and custom fields 114 | $collection['templates'] = $this->mergeCollectionWithView($postTypeModel->view, $collection, $postTypeModel); 115 | 116 | // Setting the config 117 | $collection['config'] = $config; 118 | 119 | // Lets check if there are any manipulators active 120 | $collection = $this->showMutator($postTypeModel, $collection, $request); 121 | 122 | if(method_exists($postTypeModel, 'on_show_mutator')){ 123 | $collection = $postTypeModel->on_show_mutator($postTypeModel, $post->id, $postmeta, $collection); 124 | } 125 | 126 | // Lets check if there are any manipulators active 127 | $collection = $this->showConditional($postTypeModel, $collection); 128 | 129 | // Cleaning up the output 130 | unset($collection['postmeta']); 131 | 132 | if(method_exists($postTypeModel, 'on_show_check')){ 133 | $onShowCheck = $postTypeModel->on_show_check($postTypeModel, $post->id, $postmeta); 134 | if($onShowCheck['continue'] === false){ 135 | $errorMessages = 'You are not authorized to do this.'; 136 | if(array_key_exists('message', $onShowCheck)){ 137 | $errorMessages = $onShowCheck['message']; 138 | } 139 | return $this->abort($errorMessages, $config); 140 | } 141 | } 142 | 143 | // Lets fire events as registered in the post type 144 | $this->triggerEvent('on_show_event', $postTypeModel, $post->id, $postmeta); 145 | 146 | $collection['instance'] = [ 147 | 'post_type' => $postType, 148 | 'post_identifier' => $id, 149 | ]; 150 | 151 | // Returning the full collection 152 | return response()->json($collection); 153 | } 154 | 155 | public function getConfig($postTypeModel) 156 | { 157 | // Merge the configuration values 158 | $config = []; 159 | if($postTypeModel->config){ 160 | $config = $postTypeModel->config; 161 | } 162 | 163 | $config = $config; 164 | 165 | // Adding public config 166 | if($postTypeModel->skipCreation){ 167 | $config['skip_creation'] = $postTypeModel->skipCreation; 168 | if($postTypeModel->skipToRouteName){ 169 | $config['skip_to_route_name'] = $postTypeModel->skipToRouteName; 170 | } 171 | } else { 172 | $config['skip_creation'] = false; 173 | $config['skip_to_route_name'] = ''; 174 | } 175 | 176 | // Adding public config 177 | if($postTypeModel->disableEditOnlyCheck){ 178 | $config['disable_edit_only_check'] = $postTypeModel->disableEditOnlyCheck; 179 | } else { 180 | $config['disable_edit_only_check'] = false; 181 | } 182 | 183 | if($postTypeModel->disableEdit){ 184 | $config['disable_edit'] = $postTypeModel->disableEdit; 185 | } else { 186 | $config['disable_edit'] = false; 187 | } 188 | 189 | if($postTypeModel->disableDelete){ 190 | $config['disable_delete'] = $postTypeModel->disableDelete; 191 | } else { 192 | $config['disable_delete'] = false; 193 | } 194 | 195 | if($postTypeModel->disableCreate){ 196 | $config['disable_create'] = $postTypeModel->disableCreate; 197 | } else { 198 | $config['disable_create'] = false; 199 | } 200 | 201 | if($postTypeModel->getPostByPostName){ 202 | $config['get_post_by_postname'] = $postTypeModel->getPostByPostName; 203 | } else { 204 | $config['get_post_by_postname'] = false; 205 | } 206 | 207 | $allKeys = collect($this->getValidationsKeys($postTypeModel)); 208 | 209 | // Adding public config 210 | if($postTypeModel->enableAllSpecificFieldsUpdate){ 211 | $config['specific_fields']['enable_all'] = $postTypeModel->enableAllSpecificFieldsUpdate; 212 | $config['specific_fields']['exclude_fields'] = $postTypeModel->excludeSpecificFieldsFromUpdate; 213 | $config['specific_fields']['enabled_fields'] = $allKeys->keys(); 214 | } else { 215 | $config['specific_fields']['enable_all'] = $postTypeModel->enableAllSpecificFieldsUpdate; 216 | $config['specific_fields']['exclude_fields'] = $postTypeModel->excludeSpecificFieldsFromUpdate; 217 | $config['specific_fields']['enabled_fields'] = $allKeys->where('single_field_updateable.active', 'true')->keys(); 218 | } 219 | 220 | return $config; 221 | } 222 | 223 | /** 224 | * Get all the post meta keys of the post 225 | */ 226 | protected function retrieveConfigPostMetas($post, $postTypeModel) 227 | { 228 | $metaKeys = []; 229 | $metaTaxonomies = []; 230 | 231 | $allKeys = $this->getValidationsKeys($postTypeModel); 232 | foreach($allKeys as $key => $value){ 233 | 234 | $customFieldObject = $this->getCustomFieldObject($postTypeModel, $key); 235 | 236 | if(isset($customFieldObject['type']) && $customFieldObject['type'] == 'taxonomy'){ 237 | 238 | // We need to get the values from the taxonomy table 239 | if(array_key_exists('post_type', $customFieldObject)){ 240 | 241 | $customfieldPostTypes = $this->getPostTypeIdentifiers($customFieldObject['post_type']); 242 | 243 | // Lets query the post to retrieve all the connected ids 244 | $taxonomyIds = $post->taxonomies()->whereIn('post_type', $customfieldPostTypes) 245 | ->get(); 246 | 247 | // Lets foreach all the posts because we only need the id 248 | $ids = []; 249 | foreach($taxonomyIds as $value){ 250 | array_push($ids, $value->id); 251 | } 252 | 253 | $ids = json_encode($ids); 254 | 255 | $metaTaxonomies[$key] = [ 256 | 'meta_key' => $key, 257 | 'meta_value' => $ids, 258 | ]; 259 | 260 | } 261 | 262 | // The other items are default 263 | } else { 264 | 265 | // Register it to the main array so we can query it later 266 | array_push($metaKeys, $key); 267 | 268 | } 269 | 270 | } 271 | 272 | // Lets query the database to get only the values where we have registered the meta keys 273 | $postmetaSimple = $post->postmeta() 274 | ->whereIn('meta_key', $metaKeys) 275 | ->select(['meta_key', 'meta_value']) 276 | ->get() 277 | ->keyBy('meta_key') 278 | ->toArray(); 279 | 280 | // Lets attach the default post columns 281 | $defaultPostData = []; 282 | 283 | $defaultPostData['post_title'] = [ 284 | 'meta_key' => 'post_title', 285 | 'meta_value' => $post->post_title, 286 | ]; 287 | 288 | $defaultPostData['post_name'] = [ 289 | 'meta_key' => 'post_name', 290 | 'meta_value' => $post->post_name, 291 | ]; 292 | 293 | // Lets merge all the types of configs 294 | $postmeta = array_merge($postmetaSimple, $metaTaxonomies, $defaultPostData); 295 | 296 | // Return the post meta's 297 | return $postmeta; 298 | } 299 | 300 | /** 301 | * Appending the key added in the config to the array 302 | * so we can use it very easliy in the component. 303 | */ 304 | protected function mergeCollectionWithView($view, $collection, $postTypeModel) 305 | { 306 | $post = $collection['post']; 307 | $postmeta = $collection['postmeta']; 308 | 309 | // Foreaching all templates in the custom field configuration file 310 | foreach($view as $templateKey => $template){ 311 | 312 | // If the array custom fields is not empty 313 | if(!empty($template['customFields'])){ 314 | 315 | // We foreach all custom fields in this template section 316 | foreach($template['customFields'] as $customFieldKey => $customField){ 317 | 318 | // Setting post data to the custom fields 319 | switch($customFieldKey){ 320 | 321 | // If we find the customFieldKey created_at, we know it is in the config file 322 | case 'created_at': 323 | 324 | // Because of that we will add the post created_at value to the custom field 325 | if(!empty($post['created_at'])){ 326 | $view[$templateKey]['customFields'][$customFieldKey]['id'] = $customFieldKey; 327 | $view[$templateKey]['customFields'][$customFieldKey]['value'] = $post['created_at']; 328 | } 329 | 330 | break; 331 | 332 | // If we find the customFieldKey updated_at, we know it is in the config file 333 | case 'updated_at': 334 | 335 | // Because of that we will add the post updated_at value to the custom field 336 | if(!empty($post['updated_at'])){ 337 | $view[$templateKey]['customFields'][$customFieldKey]['id'] = $customFieldKey; 338 | $view[$templateKey]['customFields'][$customFieldKey]['value'] = $post['updated_at']; 339 | } 340 | 341 | break; 342 | 343 | // If we find the customFieldKey updated_at, we know it is in the config file 344 | case 'status': 345 | 346 | // Because of that we will add the post status value to the custom field 347 | if(!empty($post['status'])){ 348 | $view[$templateKey]['customFields'][$customFieldKey]['id'] = $customFieldKey; 349 | $view[$templateKey]['customFields'][$customFieldKey]['value'] = $post['status']; 350 | } 351 | 352 | break; 353 | } 354 | 355 | // Lets set the key to the array 356 | $view[$templateKey]['customFields'][$customFieldKey]['id'] = $customFieldKey; 357 | 358 | if(array_key_exists($customFieldKey, $postmeta)){ 359 | $view[$templateKey]['customFields'][$customFieldKey]['value'] = $postmeta[$customFieldKey]['meta_value']; 360 | } 361 | 362 | // When output is disabled, we need to remove the fields from the arrays 363 | if(array_key_exists('output', $customField) && !$customField['output']){ 364 | unset($view[$templateKey]['customFields'][$customFieldKey]); 365 | } 366 | 367 | // If the array custom fields is not empty 368 | if(!empty($customField['customFields'])){ 369 | 370 | // We foreach all custom fields in this template section 371 | foreach($customField['customFields'] as $innerCustomFieldKey => $innerCustomField){ 372 | 373 | // Lets set the key to the array 374 | $view[$templateKey]['customFields'][$customFieldKey]['customFields'][$innerCustomFieldKey]['id'] = $innerCustomFieldKey; 375 | 376 | if(array_key_exists($innerCustomFieldKey, $postmeta)){ 377 | $view[$templateKey]['customFields'][$customFieldKey]['customFields'][$innerCustomFieldKey]['value'] = $postmeta[$innerCustomFieldKey]['meta_value']; 378 | } 379 | 380 | // When output is disabled, we need to remove the fields from the arrays 381 | if(array_key_exists('output', $innerCustomField) && !$innerCustomField['output']){ 382 | unset($view[$templateKey]['customFields'][$customFieldKey]['customFields'][$innerCustomFieldKey]); 383 | } 384 | 385 | } 386 | 387 | // If the array custom fields is not empty 388 | if(!empty($innerCustomField['customFields'])){ 389 | 390 | // We foreach all custom fields in this template section 391 | foreach($innerCustomField['customFields'] as $innerInnerCustomFieldKey => $innerInnerCustomField){ 392 | 393 | // Lets set the key to the array 394 | $view[$templateKey]['customFields'][$customFieldKey]['customFields'][$innerCustomFieldKey]['customFields'][$innerInnerCustomFieldKey]['id'] = $innerInnerCustomFieldKey; 395 | 396 | if(array_key_exists($innerInnerCustomFieldKey, $postmeta)){ 397 | $view[$templateKey]['customFields'][$customFieldKey]['customFields'][$innerCustomFieldKey]['customFields'][$innerInnerCustomFieldKey]['value'] = $postmeta[$innerInnerCustomFieldKey]['meta_value']; 398 | } 399 | 400 | // When output is disabled, we need to remove the fields from the arrays 401 | if(array_key_exists('output', $innerInnerCustomField) && !$innerInnerCustomField['output']){ 402 | unset($view[$templateKey]['customFields'][$customFieldKey]['customFields'][$innerCustomFieldKey]['customFields'][$innerInnerCustomFieldKey]); 403 | } 404 | 405 | } 406 | } 407 | } 408 | } 409 | } 410 | } 411 | 412 | return $view; 413 | } 414 | } 415 | -------------------------------------------------------------------------------- /src/Http/Controllers/Cms/ShowPostTaxonomies.php: -------------------------------------------------------------------------------- 1 | getPostType($postType); 17 | if(!$postTypeModel){ 18 | $errorMessages = 'You are not authorized to do this.'; 19 | return $this->abort($errorMessages); 20 | } 21 | 22 | // Check if the post type has a identifier 23 | if(empty($postTypeModel->identifier)){ 24 | $errorMessages = 'The post type does not have a identifier.'; 25 | if(array_has($postTypeModel->errorMessages, 'post_type_identifier_does_not_exist')){ 26 | $errorMessages = $postTypeModel->errorMessages['post_type_identifier_does_not_exist']; 27 | } 28 | return $this->abort($errorMessages); 29 | } 30 | 31 | $post = $this->findPostInstance($postTypeModel, $request, $postType, $id, 'show_post'); 32 | if(!$post){ 33 | $errorMessages = 'Post does not exist.'; 34 | if(array_has($postTypeModel->errorMessages, 'post_does_not_exist')){ 35 | $errorMessages = $postTypeModel->errorMessages['post_does_not_exist']; 36 | } 37 | return $this->abort($errorMessages); 38 | } 39 | 40 | // Lets get the post type of the sub post type object 41 | $subPostTypeModel = $this->getPostType($subPostType); 42 | if(!$subPostTypeModel){ 43 | $errorMessages = 'You are not authorized to do this.'; 44 | if(array_has($postTypeModel->errorMessages, 'sub_post_type_does_not_exist')){ 45 | $errorMessages = $postTypeModel->errorMessages['sub_post_type_does_not_exist']; 46 | } 47 | return $this->abort($errorMessages); 48 | } 49 | 50 | $collection = collect([ 51 | 'objects' => $post->taxonomies()->where('post_type', '=', $subPostTypeModel->identifier)->get()->toArray(), 52 | ]); 53 | 54 | // Returning the full collection 55 | return response()->json($collection); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Http/Controllers/Cms/ShowTaxonomyPosts.php: -------------------------------------------------------------------------------- 1 | getPostType($postType); 17 | if(!$postTypeModel){ 18 | $errorMessages = 'You are not authorized to do this.'; 19 | return $this->abort($errorMessages); 20 | } 21 | 22 | // Check if the post type has a identifier 23 | if(empty($postTypeModel->identifier)){ 24 | $errorMessages = 'The post type does not have a identifier.'; 25 | if(array_has($postTypeModel->errorMessages, 'post_type_identifier_does_not_exist')){ 26 | $errorMessages = $postTypeModel->errorMessages['post_type_identifier_does_not_exist']; 27 | } 28 | return $this->abort($errorMessages); 29 | } 30 | 31 | $post = $this->findPostInstance($postTypeModel, $request, $postType, $id, 'show_post'); 32 | if(!$post){ 33 | $errorMessages = 'Post does not exist.'; 34 | if(array_has($postTypeModel->errorMessages, 'post_does_not_exist')){ 35 | $errorMessages = $postTypeModel->errorMessages['post_does_not_exist']; 36 | } 37 | return $this->abort($errorMessages); 38 | } 39 | 40 | // Lets get the post type of the sub post type object 41 | $subPostTypeModel = $this->getPostType($subPostType); 42 | if(!$subPostTypeModel){ 43 | $errorMessages = 'You are not authorized to do this.'; 44 | if(array_has($postTypeModel->errorMessages, 'sub_post_type_does_not_exist')){ 45 | $errorMessages = $postTypeModel->errorMessages['sub_post_type_does_not_exist']; 46 | } 47 | return $this->abort($errorMessages); 48 | } 49 | 50 | $collection = collect([ 51 | 'objects' => $post->posts()->where('post_type', '=', $subPostTypeModel->identifier)->get()->toArray(), 52 | ]); 53 | 54 | // Returning the full collection 55 | return response()->json($collection); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Http/Controllers/Cms/SpecificFieldsEditPostController.php: -------------------------------------------------------------------------------- 1 | getPostType($postType); 20 | if(!$postTypeModel){ 21 | $errorMessages = 'You are not authorized to do this.'; 22 | return $this->abort($errorMessages); 23 | } 24 | 25 | // Check if the post type has a identifier 26 | if(empty($postTypeModel->identifier)){ 27 | $errorMessages = 'The post type does not have a identifier.'; 28 | if(array_has($postTypeModel->errorMessages, 'post_type_identifier_does_not_exist')){ 29 | $errorMessages = $postTypeModel->errorMessages['post_type_identifier_does_not_exist']; 30 | } 31 | return $this->abort($errorMessages); 32 | } 33 | 34 | // Disable editting of form 35 | if($postTypeModel->disableEdit){ 36 | $errorMessages = 'The post type does not support editting.'; 37 | if(array_has($postTypeModel->errorMessages, 'post_type_identifier_does_not_support_edit')){ 38 | $errorMessages = $postTypeModel->errorMessages['post_type_identifier_does_not_support_edit']; 39 | } 40 | return $this->abort($errorMessages); 41 | } 42 | 43 | // Validate if we need to validate a other post type before showing this post type 44 | $validateBefore = $this->validatePostTypeBefore($request, $postTypeModel, $id); 45 | if($validateBefore['status'] === false){ 46 | $errorMessages = $validateBefore['message']; 47 | return $this->abort($errorMessages, $validateBefore['config']); 48 | } 49 | 50 | $sanitizedKeys = $this->getValidationsKeys($postTypeModel); 51 | foreach($sanitizedKeys as $saniKey => $saniValue){ 52 | $sanitizedKeys[$saniKey] = ''; 53 | } 54 | 55 | $verifiedFields = []; 56 | $reloadFields = []; 57 | $reloadFieldsMethod = 'none'; 58 | 59 | // For each custom field given, we need to validate the permission 60 | foreach($request->all() as $key => $value){ 61 | 62 | // Lets check if the custom field exists and if we got permission 63 | $customFieldObject = $this->getCustomFieldObject($postTypeModel, $key); 64 | if(array_has($customFieldObject, 'single_field_updateable.active')){ 65 | if($customFieldObject['single_field_updateable']['active']){ 66 | $verifiedFields[] = $key; 67 | 68 | if(array_has($customFieldObject, 'single_field_updateable.reload_fields')){ 69 | if(is_array($customFieldObject['single_field_updateable']['reload_fields'])){ 70 | $reloadFieldsMethod = 'specific'; 71 | $reloadFields[] = $customFieldObject['single_field_updateable']['reload_fields']; 72 | } else if ($customFieldObject['single_field_updateable']['reload_fields'] == '*'){ 73 | $reloadFieldsMethod = 'all'; 74 | $reloadFields[] = $sanitizedKeys; 75 | } 76 | } 77 | } 78 | } 79 | 80 | } 81 | 82 | // If updating all specific fields is enabled, we override the verified fields 83 | if($postTypeModel->enableAllSpecificFieldsUpdate){ 84 | $whitelistedCustomFields = $this->getWhitelistedCustomFields($postTypeModel, $request->all()); 85 | 86 | $reloadFields = $sanitizedKeys; 87 | 88 | // If there is a exlusion active, lets progress that 89 | if(is_array($postTypeModel->excludeSpecificFieldsFromUpdate)){ 90 | foreach($postTypeModel->excludeSpecificFieldsFromUpdate as $excludeKey => $excludeValue){ 91 | unset($whitelistedCustomFields[$excludeValue]); 92 | unset($reloadFields[$excludeValue]); 93 | } 94 | } 95 | 96 | } else { 97 | $whitelistedCustomFields = $this->getWhitelistedCustomFields($postTypeModel, $request->only($verifiedFields)); 98 | } 99 | 100 | $toValidateKeys = []; 101 | foreach($whitelistedCustomFields as $whiteKey => $whiteValue){ 102 | $customFieldObject = $this->getCustomFieldObject($postTypeModel, $whiteKey); 103 | if(is_array($customFieldObject)){ 104 | if(array_key_exists('saveable', $customFieldObject) && $customFieldObject['saveable'] == false){ 105 | 106 | } else { 107 | $toValidateKeys[$whiteKey] = $customFieldObject; 108 | } 109 | } 110 | } 111 | 112 | // Validating the request 113 | $validationRules = $this->validatePostFields($toValidateKeys, $request, $postTypeModel, true); 114 | 115 | // Get the post instance 116 | $post = $this->findPostInstance($postTypeModel, $request, $postType, $id, 'specific_field_post'); 117 | if(!$post){ 118 | $errorMessages = 'Post does not exist.'; 119 | if(array_has($postTypeModel->errorMessages, 'post_does_not_exist')){ 120 | $errorMessages = $postTypeModel->errorMessages['post_does_not_exist']; 121 | } 122 | return $this->abort($errorMessages); 123 | } 124 | 125 | // Need to remove validations if the logic is false 126 | $logicValidations = $this->removeValidationsByConditionalLogic($whitelistedCustomFields, $postTypeModel, $post); 127 | foreach($logicValidations as $postmetaKey => $postmetaValue){ 128 | if($postmetaValue === false){ 129 | if(array_key_exists($postmetaKey, $validationRules)){ 130 | unset($validationRules[$postmetaKey]); 131 | unset($whitelistedCustomFields[$postmetaKey]); 132 | } 133 | } 134 | } 135 | 136 | // Setting a full request so we can show to the front-end what values were given 137 | $fullRequest = $request; 138 | 139 | // Regenerate the request to pass it thru existing code 140 | $request = $this->resetRequestValues($request); 141 | foreach($whitelistedCustomFields as $postmetaKey => $postmetaValue){ 142 | $request[$postmetaKey] = $postmetaValue; 143 | } 144 | // Manipulate the request so we can empty out the values where the conditional field is not shown 145 | $whitelistedCustomFields = $this->removeValuesByConditionalLogic($whitelistedCustomFields, $postTypeModel, $post); 146 | 147 | if(method_exists($postTypeModel, 'on_edit_single_field_event')){ 148 | $onCheck = $postTypeModel->on_edit_single_field_event($postTypeModel, $post->id, $whitelistedCustomFields); 149 | if($onCheck['continue'] === false){ 150 | $errorMessages = 'You are not authorized to do this.'; 151 | if(array_key_exists('message', $onCheck)){ 152 | $errorMessages = $onCheck['message']; 153 | } 154 | return $this->abort($errorMessages); 155 | } 156 | } 157 | 158 | // Saving the post values to the database 159 | $post = $this->savePostToDatabase('edit', $post, $postTypeModel, $request, $postType, true); 160 | 161 | // Saving the post meta values to the database 162 | $this->savePostMetaToDatabase($whitelistedCustomFields, $postTypeModel, $post, $fullRequest); 163 | 164 | // We need to trigger this after saving the changes to the database, its a test for now 165 | // but if we dont do this, the values wont update in the database but will not be 166 | // visible in the frontend unless we do a hard refresh. The risk now is that 167 | // people are allowed to inset everything into the database without 168 | // validation but if you use the check or edit function in the 169 | // end, we will validate the post and all the custo fields. 170 | $this->validatePost($request, $post, $validationRules); 171 | 172 | // Lets fire events as registered in the post type 173 | $this->triggerEvent('on_edit_single_field_event', $postTypeModel, $post->id, $whitelistedCustomFields); 174 | 175 | $successMessage = 'Field succesfully updated.'; 176 | if(array_has($postTypeModel->successMessage, 'field_updated')){ 177 | $successMessage = $postTypeModel->successMessage['field_updated']; 178 | } 179 | 180 | $show = (new ShowPostController)->init($fullRequest, $postType, $id); 181 | $showResponse = json_decode($show->getContent()); 182 | 183 | // Lets return the response 184 | return response()->json([ 185 | 'code' => 'success', 186 | 'show_response' => $showResponse, 187 | 'message' => $successMessage, 188 | 'action' => 'edit', 189 | 'post' => [ 190 | 'id' => $post->id, 191 | 'post_title' => $post->post_title, 192 | 'post_name' => $post->post_name, 193 | 'status' => $post->status, 194 | 'post_type' => $post->post_type, 195 | 'created_at' => $post->created_at, 196 | 'updated_at' => $post->updated_at, 197 | ], 198 | 'fields_updated' => $whitelistedCustomFields, 199 | 'fields_given' => $fullRequest->all(), 200 | 'reload_fields_method' => $reloadFieldsMethod, 201 | 'reload_fields' => $reloadFields, 202 | ], 200); 203 | } 204 | 205 | /** 206 | * Validating the creation and change of a post 207 | */ 208 | protected function validatePost($request, $post, $validationRules) 209 | { 210 | $currentValidationRuleKeys = []; 211 | foreach($request->all() as $requestKey => $requestValue){ 212 | $currentValidationRuleKeys[$requestKey] = $requestKey; 213 | } 214 | 215 | $validationRules = $this->validateFieldByConditionalLogic($validationRules, $post, $post); 216 | 217 | // Lets receive the current items from the post type validation array 218 | if(array_key_exists('post_name', $validationRules) && !is_array($validationRules['post_name'])){ 219 | 220 | $exploded = explode('|', $validationRules['post_name']); 221 | 222 | $validationRules['post_name'] = []; 223 | 224 | foreach($exploded as $key => $value){ 225 | $validationRules['post_name'][] = $value; 226 | } 227 | } 228 | 229 | // Lets validate if a post_name is required. 230 | if(!$post->disableDefaultPostName){ 231 | 232 | // If we are edditing the current existing post, we must remove the unique check 233 | if($request->get('post_name') == $post->post_name){ 234 | 235 | $validationRules['post_name'] = 'required'; 236 | 237 | // If this is not a existing post name, we need to validate if its unique. They are changing the post name. 238 | } else { 239 | 240 | // Make sure that only the post_name of the requested post_type is unique 241 | $validationRules['post_name'][] = 'required'; 242 | $validationRules['post_name'][] = Rule::unique('cms_posts')->where(function ($query) use ($post) { 243 | return $query->where('post_type', $post->identifier); 244 | }); 245 | 246 | } 247 | 248 | } 249 | 250 | $newValidationRules = []; 251 | foreach($currentValidationRuleKeys as $finalKeys => $finalValues){ 252 | if(array_key_exists($finalKeys, $validationRules)){ 253 | $newValidationRules[$finalKeys] = $validationRules[$finalKeys]; 254 | } 255 | } 256 | 257 | return $this->validate($request, $newValidationRules); 258 | } 259 | } 260 | -------------------------------------------------------------------------------- /src/Http/Controllers/Cms/SpecificFileEditPostController.php: -------------------------------------------------------------------------------- 1 | getPostType($postType); 20 | if(!$postTypeModel){ 21 | $errorMessages = 'You are not authorized to do this.'; 22 | return $this->abort($errorMessages); 23 | } 24 | 25 | // Check if the post type has a identifier 26 | if(empty($postTypeModel->identifier)){ 27 | $errorMessages = 'The post type does not have a identifier.'; 28 | if(array_has($postTypeModel->errorMessages, 'post_type_identifier_does_not_exist')){ 29 | $errorMessages = $postTypeModel->errorMessages['post_type_identifier_does_not_exist']; 30 | } 31 | return $this->abort($errorMessages); 32 | } 33 | 34 | // Disable editting of form 35 | if($postTypeModel->disableEdit){ 36 | $errorMessages = 'The post type does not support editting.'; 37 | if(array_has($postTypeModel->errorMessages, 'post_type_identifier_does_not_support_edit')){ 38 | $errorMessages = $postTypeModel->errorMessages['post_type_identifier_does_not_support_edit']; 39 | } 40 | return $this->abort($errorMessages); 41 | } 42 | 43 | // Validate if we need to validate a other post type before showing this post type 44 | $validateBefore = $this->validatePostTypeBefore($request, $postTypeModel, $id); 45 | if($validateBefore['status'] === false){ 46 | $errorMessages = $validateBefore['message']; 47 | return $this->abort($errorMessages, $validateBefore['config']); 48 | } 49 | 50 | $sanitizedKeys = $this->getValidationsKeys($postTypeModel); 51 | foreach($sanitizedKeys as $saniKey => $saniValue){ 52 | $sanitizedKeys[$saniKey] = ''; 53 | } 54 | 55 | $verifiedFields = []; 56 | $reloadFields = []; 57 | $reloadFieldsMethod = 'none'; 58 | 59 | // For each custom field given, we need to validate the permission 60 | foreach($request->all() as $key => $value){ 61 | 62 | // Lets check if the custom field exists and if we got permission 63 | $customFieldObject = $this->getCustomFieldObject($postTypeModel, $key); 64 | if(array_has($customFieldObject, 'single_field_updateable.active')){ 65 | if($customFieldObject['single_field_updateable']['active']){ 66 | $verifiedFields[] = $key; 67 | 68 | if(array_has($customFieldObject, 'single_field_updateable.reload_fields')){ 69 | if(is_array($customFieldObject['single_field_updateable']['reload_fields'])){ 70 | $reloadFieldsMethod = 'specific'; 71 | $reloadFields[] = $customFieldObject['single_field_updateable']['reload_fields']; 72 | } else if ($customFieldObject['single_field_updateable']['reload_fields'] == '*'){ 73 | $reloadFieldsMethod = 'all'; 74 | $reloadFields[] = $sanitizedKeys; 75 | } 76 | } 77 | } 78 | } 79 | 80 | } 81 | 82 | // If updating all specific fields is enabled, we override the verified fields 83 | if($postTypeModel->enableAllSpecificFieldsUpdate){ 84 | $whitelistedCustomFields = $this->getWhitelistedCustomFields($postTypeModel, $request->all()); 85 | 86 | $reloadFields = $sanitizedKeys; 87 | 88 | // If there is a exlusion active, lets progress that 89 | if(is_array($postTypeModel->excludeSpecificFieldsFromUpdate)){ 90 | foreach($postTypeModel->excludeSpecificFieldsFromUpdate as $excludeKey => $excludeValue){ 91 | unset($whitelistedCustomFields[$excludeValue]); 92 | unset($reloadFields[$excludeValue]); 93 | } 94 | } 95 | 96 | } else { 97 | $whitelistedCustomFields = $this->getWhitelistedCustomFields($postTypeModel, $request->only($verifiedFields)); 98 | } 99 | 100 | $toValidateKeys = []; 101 | foreach($whitelistedCustomFields as $whiteKey => $whiteValue){ 102 | $customFieldObject = $this->getCustomFieldObject($postTypeModel, $whiteKey); 103 | if(is_array($customFieldObject)){ 104 | if(array_key_exists('saveable', $customFieldObject) && $customFieldObject['saveable'] == false){ 105 | 106 | } else { 107 | $toValidateKeys[$whiteKey] = $customFieldObject; 108 | } 109 | } 110 | } 111 | 112 | // Validating the request 113 | $validationRules = $this->validatePostFields($toValidateKeys, $request, $postTypeModel, true); 114 | 115 | // Get the post instance 116 | $post = $this->findPostInstance($postTypeModel, $request, $postType, $id, 'specific_field_post'); 117 | if(!$post){ 118 | $errorMessages = 'Post does not exist.'; 119 | if(array_has($postTypeModel->errorMessages, 'post_does_not_exist')){ 120 | $errorMessages = $postTypeModel->errorMessages['post_does_not_exist']; 121 | } 122 | return $this->abort($errorMessages); 123 | } 124 | 125 | // Need to remove validations if the logic is false 126 | $logicValidations = $this->removeValidationsByConditionalLogic($whitelistedCustomFields, $postTypeModel, $post); 127 | foreach($logicValidations as $postmetaKey => $postmetaValue){ 128 | if($postmetaValue === false){ 129 | if(array_key_exists($postmetaKey, $validationRules)){ 130 | unset($validationRules[$postmetaKey]); 131 | unset($whitelistedCustomFields[$postmetaKey]); 132 | } 133 | } 134 | } 135 | 136 | $this->validatePost($request, $post, $validationRules); 137 | 138 | // Setting a full request so we can show to the front-end what values were given 139 | $fullRequest = $request; 140 | 141 | // Regenerate the request to pass it thru existing code 142 | $request = $this->resetRequestValues($request); 143 | foreach($whitelistedCustomFields as $postmetaKey => $postmetaValue){ 144 | $request[$postmetaKey] = $postmetaValue; 145 | } 146 | // Manipulate the request so we can empty out the values where the conditional field is not shown 147 | $whitelistedCustomFields = $this->removeValuesByConditionalLogic($whitelistedCustomFields, $postTypeModel, $post); 148 | 149 | if(method_exists($postTypeModel, 'on_edit_single_field_event')){ 150 | $onCheck = $postTypeModel->on_edit_single_field_event($postTypeModel, $post->id, $whitelistedCustomFields); 151 | if($onCheck['continue'] === false){ 152 | $errorMessages = 'You are not authorized to do this.'; 153 | if(array_key_exists('message', $onCheck)){ 154 | $errorMessages = $onCheck['message']; 155 | } 156 | return $this->abort($errorMessages); 157 | } 158 | } 159 | 160 | // Saving the post values to the database 161 | $post = $this->savePostToDatabase('edit', $post, $postTypeModel, $request, $postType, true); 162 | 163 | // Saving the post meta values to the database 164 | $this->savePostMetaToDatabase($whitelistedCustomFields, $postTypeModel, $post, $fullRequest, $customFieldKey); 165 | 166 | // Lets fire events as registered in the post type 167 | $this->triggerEvent('on_edit_single_field_event', $postTypeModel, $post->id, $whitelistedCustomFields); 168 | 169 | $successMessage = 'Field succesfully updated.'; 170 | if(array_has($postTypeModel->successMessage, 'field_updated')){ 171 | $successMessage = $postTypeModel->successMessage['field_updated']; 172 | } 173 | 174 | $show = (new ShowPostController)->init($request, $postType, $id); 175 | $showResponse = json_decode($show->getContent()); 176 | 177 | // Lets return the response 178 | return response()->json([ 179 | 'code' => 'success', 180 | 'show_response' => $showResponse, 181 | 'message' => $successMessage, 182 | 'action' => 'edit', 183 | 'post' => [ 184 | 'id' => $post->id, 185 | 'post_title' => $post->post_title, 186 | 'post_name' => $post->post_name, 187 | 'status' => $post->status, 188 | 'post_type' => $post->post_type, 189 | 'created_at' => $post->created_at, 190 | 'updated_at' => $post->updated_at, 191 | ], 192 | 'fields_updated' => $whitelistedCustomFields, 193 | 'fields_given' => $fullRequest->all(), 194 | 'reload_fields_method' => $reloadFieldsMethod, 195 | 'reload_fields' => $reloadFields, 196 | ], 200); 197 | } 198 | 199 | /** 200 | * Validating the creation and change of a post 201 | */ 202 | protected function validatePost($request, $post, $validationRules) 203 | { 204 | $currentValidationRuleKeys = []; 205 | foreach($request->all() as $requestKey => $requestValue){ 206 | $currentValidationRuleKeys[$requestKey] = $requestKey; 207 | } 208 | 209 | $validationRules = $this->validateFieldByConditionalLogic($validationRules, $post, $post); 210 | 211 | // Lets receive the current items from the post type validation array 212 | if(array_key_exists('post_name', $validationRules) && !is_array($validationRules['post_name'])){ 213 | 214 | $exploded = explode('|', $validationRules['post_name']); 215 | 216 | $validationRules['post_name'] = []; 217 | 218 | foreach($exploded as $key => $value){ 219 | $validationRules['post_name'][] = $value; 220 | } 221 | } 222 | 223 | // Lets validate if a post_name is required. 224 | if(!$post->disableDefaultPostName){ 225 | 226 | // If we are edditing the current existing post, we must remove the unique check 227 | if($request->get('post_name') == $post->post_name){ 228 | 229 | $validationRules['post_name'] = 'required'; 230 | 231 | // If this is not a existing post name, we need to validate if its unique. They are changing the post name. 232 | } else { 233 | 234 | // Make sure that only the post_name of the requested post_type is unique 235 | $validationRules['post_name'][] = 'required'; 236 | $validationRules['post_name'][] = Rule::unique('cms_posts')->where(function ($query) use ($post) { 237 | return $query->where('post_type', $post->identifier); 238 | }); 239 | 240 | } 241 | 242 | } 243 | 244 | $newValidationRules = []; 245 | foreach($currentValidationRuleKeys as $finalKeys => $finalValues){ 246 | if(array_key_exists($finalKeys, $validationRules)){ 247 | $newValidationRules[$finalKeys] = $validationRules[$finalKeys]; 248 | } 249 | } 250 | 251 | return $this->validate($request, $newValidationRules); 252 | } 253 | } 254 | -------------------------------------------------------------------------------- /src/Http/Controllers/Cms/TaxonomyController.php: -------------------------------------------------------------------------------- 1 | getPostType($postType); 16 | if(!$postTypeModel){ 17 | $errorMessages = 'You are not authorized to do this.'; 18 | return $this->abort($errorMessages); 19 | } 20 | 21 | // Validate the required fields 22 | $this->validate($request, [ 23 | 'action' => 'required', 24 | 'id' => 'required', 25 | 'taxonomy_post_id' => 'required', 26 | ]); 27 | 28 | // Check if the post type has a identifier 29 | if(empty($postTypeModel->identifier)){ 30 | $errorMessages = 'The post type does not have a identifier.'; 31 | if(array_has($postTypeModel->errorMessages, 'post_type_identifier_does_not_exist')){ 32 | $errorMessages = $postTypeModel->errorMessages['post_type_identifier_does_not_exist']; 33 | } 34 | return $this->abort($errorMessages); 35 | } 36 | 37 | // Disable editting of form 38 | if($postTypeModel->disableEdit){ 39 | $errorMessages = 'The post type does not support editting.'; 40 | if(array_has($postTypeModel->errorMessages, 'post_type_identifier_does_not_support_edit')){ 41 | $errorMessages = $postTypeModel->errorMessages['post_type_identifier_does_not_support_edit']; 42 | } 43 | return $this->abort($errorMessages); 44 | } 45 | 46 | switch($request->action){ 47 | 48 | // Creating a taxonomy 49 | case 'attach': 50 | 51 | $taxonomyInstance = new NikuTaxonomies; 52 | $taxonomyInstance->post_id = $request->post_id; 53 | $taxonomyInstance->taxonomy_post_id = $request->taxonomy_post_id; 54 | $taxonomyInstance->taxonomy = $postType; 55 | 56 | if($request->has('custom')){ 57 | $taxonomyInstance->custom = $request->custom; 58 | } 59 | 60 | if($request->has('menu_order')){ 61 | $taxonomyInstance->menu_order = $request->menu_order; 62 | } 63 | 64 | $taxonomyInstance->save(); 65 | 66 | break; 67 | 68 | // Deleting the taxonomy 69 | case 'detach': 70 | 71 | $taxonomyInstance = NikuTaxonomies::where([ 72 | ['id', '=', $request->id], 73 | ['taxonomy_post_id', '=', $request->taxonomy_post_id], 74 | ['post_id', '=', $request->post_id], 75 | ])->first(); 76 | 77 | if($taxonomyInstance){ 78 | $taxonomyInstance->delete(); 79 | } 80 | 81 | break; 82 | 83 | // Editting the taxonomy 84 | case 'edit': 85 | 86 | $taxonomyInstance = NikuTaxonomies::where([ 87 | ['id', '=', $request->id], 88 | ['taxonomy_post_id', '=', $request->taxonomy_post_id], 89 | ['post_id', '=', $request->post_id], 90 | ])->first(); 91 | 92 | if(!$taxonomyInstance){ 93 | $errorMessages = 'Taxonomy does not exist.'; 94 | if(array_has($postTypeModel->errorMessages, 'taxonomy_does_not_exist')){ 95 | $errorMessages = $postTypeModel->errorMessages['taxonomy_does_not_exist']; 96 | } 97 | return $this->abort($errorMessages); 98 | } 99 | 100 | if($request->has('custom')){ 101 | $taxonomyInstance->custom = $request->custom; 102 | } 103 | 104 | if($request->has('menu_order')){ 105 | $taxonomyInstance->menu_order = $request->menu_order; 106 | } 107 | 108 | if($request->has('taxonomymeta')){ 109 | $toSave = []; 110 | foreach($request->taxonomymeta as $key => $value){ 111 | $toSave[$key] = $value; 112 | } 113 | 114 | $taxonomyInstance->saveMetas($toSave); 115 | } 116 | 117 | $taxonomyInstance->save(); 118 | 119 | break; 120 | case 'sync': 121 | 122 | break; 123 | } 124 | 125 | $successMessage = 'Taxonomy succesfully updated.'; 126 | if(array_has($postTypeModel->successMessage, 'taxonomy_updated')){ 127 | $successMessage = $postTypeModel->successMessage['taxonomy_updated']; 128 | } 129 | 130 | // Lets return the response 131 | return response()->json([ 132 | 'code' => 'success', 133 | 'message' => $successMessage, 134 | 'action' => 'taxonomy_edit', 135 | ], 200); 136 | } 137 | 138 | } 139 | -------------------------------------------------------------------------------- /src/Http/Controllers/Config/EditConfigController.php: -------------------------------------------------------------------------------- 1 | getPostType($group); 18 | if(!$postTypeModel){ 19 | $errorMessages = 'You are not authorized to do this.'; 20 | return $this->abort($errorMessages); 21 | } 22 | 23 | // Recieving the values 24 | $configMeta = $request->all(); 25 | 26 | // Unsetting values which we do not need 27 | $unsetValues = ['_token']; 28 | foreach($unsetValues as $value){ 29 | unset($configMeta[$value]); 30 | } 31 | 32 | // Receiving validation rules from config 33 | $validationRules = []; 34 | foreach ($configMeta as $key => $value) { 35 | 36 | // Setting the path to get the validation rules 37 | if(strpos($key, '_repeater_') !== false) { 38 | $explodedValue = explode('_', $key); 39 | 40 | // Removing the old repeater values so we can resave them all, if we do 41 | // not do this, it will keep having the old values in the database. 42 | NikuConfig::where([ 43 | ['option_name', 'like', $explodedValue[0] . '_' . $explodedValue[1] . '_%'], 44 | ['group', '=', $group] 45 | ])->delete(); 46 | 47 | // For each all groups to get the validation 48 | foreach($postTypeModel->view as $templateKey => $template){ 49 | if(array_has($template, 'customFields.' . $explodedValue[0] . '.customFields.' . $explodedValue[3] . '.validation')){ 50 | $rule = $template['customFields'][$explodedValue[0]]['customFields'][$explodedValue[3]]['validation']; 51 | } 52 | } 53 | 54 | } else { 55 | 56 | // For each all groups to get the validation 57 | foreach($postTypeModel->view as $templateKey => $template){ 58 | if(array_has($template, 'customFields.' . $key . '.validation')){ 59 | $rule = $template['customFields'][$key]['validation']; 60 | } 61 | } 62 | 63 | } 64 | 65 | // Appending the validation rules to the validation array 66 | if(!empty($rule)){ 67 | $validationRules[$key] = $rule; 68 | } 69 | 70 | } 71 | 72 | // Validate the request 73 | if(!empty($validationRules)){ 74 | $this->validatePost($request, $validationRules); 75 | } 76 | 77 | // Lets update or create the fields in the post request 78 | foreach($configMeta as $index => $value){ 79 | 80 | NikuConfig::updateOrCreate( 81 | ['option_name' => $index], 82 | [ 83 | 'option_value' => $value, 84 | 'group' => $group 85 | ] 86 | ); 87 | } 88 | 89 | $successMessage = 'Config succesfully updated.'; 90 | if(array_has($postTypeModel->successMessage, 'config_updated')){ 91 | $successMessage = $postTypeModel->successMessage['config_updated']; 92 | } 93 | 94 | // Lets return the response 95 | return response()->json([ 96 | 'code' => 'success', 97 | 'message' => $successMessage, 98 | 'action' => 'config_updated', 99 | ], 200); 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /src/Http/Controllers/Config/ShowConfigController.php: -------------------------------------------------------------------------------- 1 | getPostType($group); 18 | if(!$postTypeModel){ 19 | $errorMessages = 'You are not authorized to do this.'; 20 | return $this->abort($errorMessages); 21 | } 22 | 23 | // Receiving the current data of the group 24 | $config = NikuConfig::where('group', '=', $group) 25 | ->get() 26 | ->keyBy('option_name') 27 | ->toArray(); 28 | 29 | $templates = $postTypeModel->view; 30 | 31 | // Appending the key added in the config to the array 32 | // so we can use it very easliy in the component. 33 | foreach($templates as $key => $template){ 34 | 35 | if(!empty($template['customFields'])){ 36 | 37 | // For each custom fields 38 | foreach($template['customFields'] as $ckey => $customField){ 39 | $templates[$key]['customFields'][$ckey]['id'] = $ckey; 40 | 41 | // Adding the values to the result 42 | if(!empty($config[$ckey])){ 43 | $templates[$key]['customFields'][$ckey]['value'] = $config[$ckey]['option_value']; 44 | } 45 | } 46 | } 47 | } 48 | 49 | $collection = collect([ 50 | 'config' => $this->getConfig($postTypeModel), 51 | 'templates' => $templates, 52 | ]); 53 | 54 | return response()->json($collection); 55 | } 56 | 57 | public function getConfig($postTypeModel) 58 | { 59 | // Merge the configuration values 60 | $config = []; 61 | if($postTypeModel->config){ 62 | $config = $postTypeModel->config; 63 | } 64 | 65 | $config = $config; 66 | 67 | // Adding public config 68 | if($postTypeModel->skipCreation){ 69 | $config['skip_creation'] = $postTypeModel->skipCreation; 70 | if($postTypeModel->skipToRouteName){ 71 | $config['skip_to_route_name'] = $postTypeModel->skipToRouteName; 72 | } 73 | } else { 74 | $config['skip_creation'] = false; 75 | $config['skip_to_route_name'] = ''; 76 | } 77 | 78 | // Adding public config 79 | if($postTypeModel->disableEditOnlyCheck){ 80 | $config['disable_edit_only_check'] = $postTypeModel->disableEditOnlyCheck; 81 | } else { 82 | $config['disable_edit_only_check'] = false; 83 | } 84 | 85 | if($postTypeModel->disableEdit){ 86 | $config['disable_edit'] = $postTypeModel->disableEdit; 87 | } else { 88 | $config['disable_edit'] = false; 89 | } 90 | 91 | if($postTypeModel->disableDelete){ 92 | $config['disable_delete'] = $postTypeModel->disableDelete; 93 | } else { 94 | $config['disable_delete'] = false; 95 | } 96 | 97 | if($postTypeModel->disableCreate){ 98 | $config['disable_create'] = $postTypeModel->disableCreate; 99 | } else { 100 | $config['disable_create'] = false; 101 | } 102 | 103 | if($postTypeModel->getPostByPostName){ 104 | $config['get_post_by_postname'] = $postTypeModel->getPostByPostName; 105 | } else { 106 | $config['get_post_by_postname'] = false; 107 | } 108 | 109 | $allKeys = collect($this->getValidationsKeys($postTypeModel)); 110 | 111 | // Adding public config 112 | if($postTypeModel->enableAllSpecificFieldsUpdate){ 113 | $config['specific_fields']['enable_all'] = $postTypeModel->enableAllSpecificFieldsUpdate; 114 | $config['specific_fields']['exclude_fields'] = $postTypeModel->excludeSpecificFieldsFromUpdate; 115 | $config['specific_fields']['enabled_fields'] = $allKeys->keys(); 116 | } else { 117 | $config['specific_fields']['enable_all'] = $postTypeModel->enableAllSpecificFieldsUpdate; 118 | $config['specific_fields']['exclude_fields'] = $postTypeModel->excludeSpecificFieldsFromUpdate; 119 | $config['specific_fields']['enabled_fields'] = $allKeys->where('single_field_updateable.active', 'true')->keys(); 120 | } 121 | 122 | return $config; 123 | } 124 | 125 | } 126 | -------------------------------------------------------------------------------- /src/Http/Controllers/ConfigController.php: -------------------------------------------------------------------------------- 1 | authorizations($postTypeModel)){ 34 | return false; 35 | } 36 | 37 | return $postTypeModel; 38 | 39 | } else { 40 | return false; 41 | } 42 | } 43 | 44 | protected function authorizations($postTypeModel) 45 | { 46 | // If users can only view their own posts, we need to make 47 | // sure that the users are logged in before continueing. 48 | if(!$this->userCanOnlySeeHisOwnPosts($postTypeModel)){ 49 | return false; 50 | } 51 | 52 | return true; 53 | } 54 | 55 | /** 56 | * If the user can only see his own post(s) 57 | */ 58 | protected function userCanOnlySeeHisOwnPosts($postTypeModel) 59 | { 60 | if($postTypeModel->userCanOnlySeeHisOwnPosts){ 61 | if(!Auth::check()){ 62 | return false; 63 | } else { 64 | return true; 65 | } 66 | } else { 67 | return true; 68 | } 69 | } 70 | 71 | /** 72 | * Validating the creation and change of a post 73 | */ 74 | protected function validatePost($request, $validationRules) 75 | { 76 | return $this->validate($request, $validationRules); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/Http/Controllers/MutatorController.php: -------------------------------------------------------------------------------- 1 | validate($request, [ 21 | 'file' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:4096', 22 | ]); 23 | 24 | $fileName = basename($request->file->getClientOriginalName(), '.' . $request->file->getClientOriginalExtension()); 25 | $fileExtension = $request->file->getClientOriginalExtension(); 26 | $postName = $this->sanitizeUrl($fileName); 27 | $mime = $request->file->getMimeType(); 28 | 29 | $postmeta = NikuPostmeta::where([ 30 | ['meta_key', '=', 'attachment_url'], 31 | ['meta_value', 'LIKE', '/uploads/images/' . $fileName . '%'] 32 | ])->get(); 33 | 34 | if($postmeta->count() != 0){ 35 | $count = $postmeta->count() + 1; 36 | $fileCount = '-' . $count; 37 | } else { 38 | $fileCount = ''; 39 | } 40 | 41 | $postName = $postName . $fileCount; 42 | $fileName = $fileName . $fileCount . '.' . $fileExtension; 43 | 44 | $post = new NikuPosts; 45 | $post->post_title = $fileName; 46 | $post->post_name = $postName; 47 | $post->post_type = 'attachment'; 48 | $post->post_mime_type = $mime; 49 | $post->status = 'inherit'; 50 | if(Auth::check()){ 51 | $post->post_author = Auth::user()->id; 52 | } else { 53 | $post->post_author = '0'; 54 | } 55 | $post->save(); 56 | 57 | $postmeta = new NikuPostmeta; 58 | $postmeta->post_id = $post->id; 59 | $postmeta->meta_key = 'attachment_url'; 60 | $postmeta->meta_value = '/uploads/images/' . $fileName; 61 | $postmeta->save(); 62 | 63 | $request->file->move(public_path('uploads/images'), $fileName); 64 | 65 | $postObject = collect([ 66 | 'status' => 0, 67 | 'postmeta' => [ 68 | 0 => [ 69 | 'meta_value' => $postmeta->meta_value, 70 | ] 71 | ], 72 | 'id' => $postmeta->post_id 73 | ]); 74 | 75 | return response()->json([ 76 | 'object' => $postObject 77 | ]); 78 | } 79 | 80 | /** 81 | * Function for sanitizing slugs 82 | */ 83 | protected function sanitizeUrl($url) 84 | { 85 | $url = $url; 86 | $url = preg_replace('~[^\\pL0-9_]+~u', '-', $url); // substitutes anything but letters, numbers and '_' with separator 87 | $url = trim($url, "-"); 88 | $url = iconv("utf-8", "us-ascii//TRANSLIT", $url); // TRANSLIT does the whole job 89 | $url = strtolower($url); 90 | $url = preg_replace('~[^-a-z0-9_]+~', '', $url); // keep only letters, numbers, '_' and separator 91 | return $url; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/Http/Middlewares/WhitelistConfigGroupsMiddleware.php: -------------------------------------------------------------------------------- 1 | route('group'), $acceptedGroups)){ 23 | $message = $request->route('post_type') . ' config group is not supported. '; 24 | $hint = 'Verify if you are authorized to use this config group.'; 25 | return response()->json([ 26 | 'code' => 'unsupported_config_group', 27 | 'errors' => [ 28 | 'unsupported_config_group' => [ 29 | 0 => $message . $hint, 30 | ], 31 | ], 32 | 'hint' => $hint, 33 | ], 400); 34 | } 35 | 36 | return $next($request); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Http/Middlewares/WhitelistPostTypesMiddleware.php: -------------------------------------------------------------------------------- 1 | route('post_type') . ' post type is not supported. '; 22 | $authorized = false; 23 | 24 | // Lets verify that we are authorized to use this post type 25 | if(in_array($request->route('post_type'), $acceptedPostTypes)){ 26 | $authorized = true; 27 | $message = ''; 28 | 29 | // We need to validate access of the sub post type for the taxonomy API. Lets check if we are using this method 30 | if(array_key_exists('sub_post_type', $request->route()->parameters)){ 31 | 32 | // There is sub post type in the request, we need to authorize 33 | $authorized = false; 34 | $message .= $request->route('sub_post_type') . ' post type is not supported.'; 35 | 36 | // Lets authorize the variable 37 | if(in_array($request->route('sub_post_type'), $acceptedPostTypes)){ 38 | $authorized = true; 39 | } 40 | 41 | // We can continue authorized because there is no sub post type in the request 42 | } else { 43 | $authorized = true; 44 | } 45 | 46 | } 47 | 48 | if(!$authorized){ 49 | $hint = 'Verify if you are authorized to use this post type.'; 50 | return response()->json([ 51 | 'code' => 'unsupported_post_type', 52 | 'errors' => [ 53 | 'unsupported_post_type' => [ 54 | 0 => $message . $hint, 55 | ], 56 | ], 57 | 'hint' => $hint, 58 | ], 400); 59 | } 60 | 61 | return $next($request); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/Http/NikuConfig.php: -------------------------------------------------------------------------------- 1 | hasOne('Niku\Cms\Http\Posts', 'id', 'post_id'); 16 | } 17 | 18 | } 19 | 20 | -------------------------------------------------------------------------------- /src/Http/NikuPosts.php: -------------------------------------------------------------------------------- 1 | hasMany('Niku\Cms\Http\NikuPostmeta', 'post_id', 'id'); 36 | } 37 | 38 | /** 39 | * Get posts of taxonomy 40 | */ 41 | public function posts() 42 | { 43 | return $this->belongsToMany('Niku\Cms\Http\NikuPosts', 'cms_taxonomy', 'taxonomy_post_id', 'post_id')->withPivot('id', 'custom', 'menu_order'); 44 | } 45 | 46 | /** 47 | * Get taxonomies of post 48 | */ 49 | public function taxonomies() 50 | { 51 | return $this->belongsToMany('Niku\Cms\Http\NikuPosts', 'cms_taxonomy', 'post_id', 'taxonomy_post_id')->withPivot('id', 'custom', 'menu_order'); 52 | } 53 | 54 | /** 55 | * Retrieve the meta value of a certain key 56 | */ 57 | public function getMeta($key) 58 | { 59 | $postmeta = $this->postmeta; 60 | $postmeta = $postmeta->keyBy('meta_key'); 61 | if(array_has($postmeta, $key . '.meta_value')){ 62 | $returnValue = $postmeta[$key]['meta_value']; 63 | return $returnValue; 64 | } 65 | } 66 | 67 | public function saveMetas($metas) 68 | { 69 | foreach($metas as $key => $value){ 70 | 71 | if(is_array($value)){ 72 | $value = json_encode($value); 73 | } 74 | 75 | // Saving it to the database based on key value array 76 | $object = [ 77 | 'meta_key' => $key, 78 | 'meta_value' => $value, 79 | ]; 80 | 81 | // Update or create the meta key of the post 82 | $this->postmeta()->updateOrCreate([ 83 | 'meta_key' => $key 84 | ], $object); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/Http/NikuTaxonomies.php: -------------------------------------------------------------------------------- 1 | hasMany('Niku\Cms\Http\NikuTaxonomyMeta', 'taxonomy_id', 'id'); 19 | } 20 | 21 | /** 22 | * Retrieve the meta value of a certain key 23 | */ 24 | public function getMeta($key) 25 | { 26 | $taxonomymeta = $this->taxonomymeta; 27 | $taxonomymeta = $taxonomymeta->keyBy('meta_key'); 28 | if(array_has($taxonomymeta, $key . '.meta_value')){ 29 | $returnValue = $taxonomymeta[$key]['meta_value']; 30 | return $returnValue; 31 | } 32 | } 33 | 34 | public function saveMetas($metas) 35 | { 36 | foreach($metas as $key => $value){ 37 | 38 | if(is_array($value)){ 39 | $value = json_encode($value); 40 | } 41 | 42 | // Saving it to the database based on key value array 43 | $object = [ 44 | 'meta_key' => $key, 45 | 'meta_value' => $value, 46 | ]; 47 | 48 | // Update or create the meta key of the post 49 | $this->taxonomymeta()->updateOrCreate([ 50 | 'meta_key' => $key 51 | ], $object); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Http/NikuTaxonomyMeta.php: -------------------------------------------------------------------------------- 1 | hasOne('Niku\Cms\Http\Taxonomymeta', 'id', 'taxonomy_id'); 16 | } 17 | 18 | } 19 | 20 | --------------------------------------------------------------------------------