gkratz / adminbundle
A bundle to manage CMS administration for symfony 3
Requires
- php: >=5.5.0
- doctrine/doctrine-bundle: *
- egeloen/ckeditor-bundle: ~5
- geoip2/geoip2: ^2.4
- helios-ag/fm-elfinder-bundle: ^6.1
- knplabs/knp-paginator-bundle: ^2.5
- leafo/scssphp: 0.6.6
- lexik/form-filter-bundle: ~5.0
- ob/highcharts-bundle: ^1.2
- patchwork/jsqueeze: ~2.0
- simplethings/entity-audit-bundle: ^1.0
- stof/doctrine-extensions-bundle: ~1.1
- symfony/assetic-bundle: ^2.8
- symfony/framework-bundle: >=3.0.1
- twig/extensions: *
- twig/twig: *
Requires (Dev)
This package is auto-updated.
Last update: 2024-10-26 18:44:12 UTC
README
//-- extraordinary --//
IN ONE COMMAND, YOU WILL GENERATE EVERYTHING FOR YOUR BACK-OFFICE
INCLUDING USERS AND CONFIGURATION
START A NEW PROJECT AND INSTALL IT TO UNDERSTAND THE POWER OF THIS BUNDLE.
//-- database --//
We recommend to use a mariadb database if you have errors with sql queries.
The bundle use complexes sql queries and MARIADB is better than mysql in this case.
//-- entities --//
Every entity that you will CREATE for your own project
MUST absolutely have a field named "state" type integer.
if you want to use the TRASH PLUGIN and the SEARCH PLUGIN
INSTALLATION
1) //-- add in the "composer.json" of your project --//
"require": {
// ...
"gkratz/adminbundle": "dev-master",
"friendsofsymfony/user-bundle": "dev-master",
"beberlei/DoctrineExtensions": "dev-master"
}
2) //-- activate the bundle in your "app\AppKernel.php" --//
new Gkratz\AdminBundle\GkratzAdminBundle(),
new Ambta\DoctrineEncryptBundle\AmbtaDoctrineEncryptBundle(),
new Ob\HighchartsBundle\ObHighchartsBundle(),
new Knp\Bundle\PaginatorBundle\KnpPaginatorBundle(),
new Lexik\Bundle\FormFilterBundle\LexikFormFilterBundle(),
new Symfony\Bundle\AsseticBundle\AsseticBundle(),
new FOS\UserBundle\FOSUserBundle(),
new Stof\DoctrineExtensionsBundle\StofDoctrineExtensionsBundle(),
new Ivory\CKEditorBundle\IvoryCKEditorBundle(),
new FM\ElfinderBundle\FMElfinderBundle(),
new SimpleThings\EntityAudit\SimpleThingsEntityAuditBundle(),
new Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle(),
if (in_array($this->getEnvironment(), array('dev', 'test'))) {
// ...
$bundles[] = new Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle();
// ...
}
3) //-- enter this command in your terminal and don't worry about the "Undefined index: search"db_driver" at path "fos_user" must be configured" alert when installing the vendors. Error will be corrected by other steps of the installation --//
//-- after installation, verify if the gkratz folder is present in the vendor folder. If no, enter this command: "php composer update gkratz/adminbundle" --//
//-- after installation, verify if the beberlei folder is present in the vendor folder. If no, enter this command: "php composer update beberlei/DoctrineExtensions" --//
php composer require doctrine/doctrine-fixtures-bundle
4) //-- update your "app\config\config.yml" file --//
# Twig Configuration
twig:
# ...
globals:
my_site: '@gkratz_twig_my_site'
form_themes:
- LexikFormFilterBundle:Form:form_div_layout.html.twig
- GkratzAdminBundle:form:form_errors.html.twig
# Doctrine Configuration
doctrine:
# ...
orm:
# ...
dql:
string_functions:
# To use SOUNDEX mysql function with Doctrine
SOUNDEX: Gkratz\AdminBundle\Extensions\Doctrine\SoundexFunction
datetime_functions:
month: DoctrineExtensions\Query\Mysql\Month
year: DoctrineExtensions\Query\Mysql\Year
day: DoctrineExtensions\Query\Mysql\Day
dayofweek: DoctrineExtensions\Query\Mysql\DayOfWeek
# Doctrine Migrations Configuration
doctrine_migrations:
dir_name: "%kernel.root_dir%/Migrations"
namespace: Application\Migrations
table_name: migration_versions
name: Application Migrations
organize_migrations: false # Version >=1.2 Possible values are: "BY_YEAR", "BY_YEAR_AND_MONTH", false
# KNPPaginator Configuration
knp_paginator:
default_options:
distinct: false
template:
pagination: GkratzAdminBundle:admin/__partial:pagination.html.twig
# Stof Configuration
stof_doctrine_extensions:
orm:
default:
sluggable: true
# Assetic Configuration
assetic:
debug: "%kernel.debug%"
use_controller: false
bundles: [GkratzAdminBundle, AppBundle, FOSUserBundle]
filters:
cssrewrite: ~
jsqueeze: ~
scssphp:
# the formatter must be the FQCN (don't use the 'compressed' value)
formatter: "Leafo\\ScssPhp\\Formatter\\Compressed"
# FOSUser Configuration
fos_user:
db_driver: orm
firewall_name: main
user_class: AppBundle\Entity\User
from_email:
address: webmaster@example.com
sender_name: Admin
registration:
confirmation:
enabled: true # change to false to disable email confirmation
template: FOSUserBundle:Registration:email.html.twig
resetting:
email:
template: FOSUserBundle:Resetting:email.html.twig
profile:
form:
type: Gkratz\AdminBundle\Form\ProfileType
name: gkratz_profile_form
validation_groups: [Profile, Default]
service:
mailer: fos_user.mailer.twig_swift
# ELFinder Configuration
fm_elfinder:
assets_path: /assets
instances:
default:
locale: "%locale%" # defaults to current request locale
editor: ckeditor # other options are tinymce, tinymce4, form, custom and simple
fullscreen: true # defaults true, applies to simple and ckeditor editors
theme: smoothness # jquery theme
include_assets: true # disable if you want to handle loading of the javascript and css assets yourself
connector:
debug: true # defaults to false
roots: # at least one root must be defined
uploads:
show_hidden: false # defaults to false
driver: LocalFileSystem
path: uploads/img/filemanager
# upload_allow: ['image/png', 'image/jpg', 'image/jpeg', 'application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.ms-excel']
upload_allow: ['image/png', 'image/jpg', 'image/jpeg']
upload_deny: ['all']
upload_max_size: 8M
# IvoryCKEditor Configuration
ivory_ck_editor:
default_config: default
configs:
default:
toolbar: standard
locale: "%locale%"
filebrowserBrowseRoute: elfinder
filebrowserBrowseRouteParameters: []
# SimpleThingsEntityAudit Configuration
simple_things_entity_audit:
audited_entities:
- AppBundle\Entity\Post
# Monolog Configuration
monolog:
channels: ["gkadmin"]
handlers:
file:
type: stream
path: "%kernel.logs_dir%/gkadmin.log"
level: info
channels: gkadmin
# Gkratz Admin Configuration
gkratz_admin:
search:
allow_approaching: true # may be very slow. set false to only allow perfect match.
fields: Post.title, Post.content, User.username, User.lastname, User.firstname, User.address
notification:
option: true # set false to @TODO develop notification listeners
fields: thing, other, another
5) //-- make sure that this line in "app\config\config.yml" is decommented to enable translations --//
framework:
translator: { fallbacks: ["%locale%"] }
6) //-- update your "app\config\routing.yml" file --//
#LINE 1 - this route must ABSOLUTELY be
#at the top of the routing.yml file
GkratzAdmin:
resource: "@GkratzAdminBundle/Controller/"
type: annotation
prefix: /admin
fos_user_security:
resource: "@FOSUserBundle/Resources/config/routing/security.xml"
fos_user_profile:
resource: "@FOSUserBundle/Resources/config/routing/profile.xml"
prefix: /profile
fos_user_register:
resource: "@FOSUserBundle/Resources/config/routing/registration.xml"
prefix: /register
fos_user_resetting:
resource: "@FOSUserBundle/Resources/config/routing/resetting.xml"
prefix: /resetting
fos_user_change_password:
resource: "@FOSUserBundle/Resources/config/routing/change_password.xml"
prefix: /profile
elfinder:
resource: "@FMElfinderBundle/Resources/config/routing.yml"
7) //-- update your "src\AppBundle\Controller\DefaultController.php" --// //-- AND EVERY OTHER FRONT CONTROLLER TO USE MAINTENANCE ACTIVATION --// //-- use only render() method to render view, not renderView() --//
<?php
namespace AppBundle\Controller;
use AppBundle\Entity\Post;
use Gkratz\AdminBundle\Controller\GKratzController;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class DefaultController extends GKratzController
{
/**
* @Route("/", name="homepage")
*/
public function indexAction(Request $request)
{
return $this->render('default/index.html.twig', [
'base_dir' => realpath($this->getParameter('kernel.project_dir')).DIRECTORY_SEPARATOR,
]);
}
/**
* @Route("/{slug}", name="front_routage")
*/
public function routingAction($slug){
/** @var \AppBundle\Entity\Post $post */
$post = $this->getDoctrine()->getRepository(Post::class)->getFrontPage($slug);
if (null === $post){
throw new NotFoundHttpException();
} else {
return $this->render('@GkratzAdmin/admin/page.html.twig', ['entity' => $post]);
}
}
}
8) //-- generate user entity THAT EXTENDS FOSUSER MODEL --//
php bin/console doctrine:generate:entity
//-- shortcut name: AppBundle:User --//
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use FOS\UserBundle\Model\User as BaseUser;
use Gkratz\AdminBundle\Constants\Constants;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
/**
* @ORM\Table(name="user")
* @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
* @UniqueEntity("email")
* @UniqueEntity("username")
* @ORM\HasLifecycleCallbacks()
*/
class User extends BaseUser
{
const ROLES_LIST = array(
'ROLE_ANONYMOUS_USER' => 'ROLE_ANONYMOUS_USER',
'ROLE_USER' => 'ROLE_USER',
'ROLE_ADMIN' => 'ROLE_ADMIN',
'ROLE_SUPER_ADMIN' => 'ROLE_SUPER_ADMIN',
);
public function __construct()
{
parent::__construct();
$this->roles = array(self::ROLES_LIST['ROLE_USER'], self::ROLES_LIST['ROLE_ANONYMOUS_USER']);
$this->state = 0;
}
/**
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @var String
* @ORM\Column(name="lastname", type="string", length=100, nullable=true)
*/
private $lastname;
/**
* @var String
* @ORM\Column(name="firstname", type="string", length=100, nullable=true)
*/
private $firstname;
/**
* @var String
* @ORM\Column(name="address", type="string", length=100, nullable=true)
* @Assert\Length(min=10, max=190)
*/
private $address;
/**
* @var String
* @ORM\Column(name="phone_number", type="string", length=100, nullable=true)
*/
private $phoneNumber;
/**
* @var \DateTime
* @ORM\Column(name="birthdate", type="datetime", length=255, nullable=true)
*/
private $birthdate;
/**
* @var Integer
* @ORM\Column(name="state", type="integer", nullable=true)
*/
private $state;
/**
* @var String
* @ORM\Column(name="avatar", type="string", length=255, nullable=true)
*/
private $avatar;
/**
* @Assert\File(
* maxSize = "2048k",
* mimeTypes = {"image/png", "image/jpg", "image/gif", "image/jpeg"},
* mimeTypesMessage = "Please upload a valid image"
* )
*/
private $avatarSrc;
public function getAvatarSrc()
{
return $this->avatarSrc;
}
public function setAvatarSrc(UploadedFile $avatarSrc = null)
{
$this->avatarSrc = $avatarSrc;
}
/**
* @ORM\PreUpdate
*/
public function upload()
{
$this->enabled = ($this->state == Constants::ENTITY_STATE_VALID) ? 1 : 0;
if (null === $this->avatarSrc) {
return;
}
$name = ''.time().'-'.$this->avatarSrc->getClientOriginalName();
$this->avatarSrc->move($this->getUploadRootDir(), $name);
$this->avatar = $name;
}
public function getUploadDir()
{
return 'uploads/avatar';
}
protected function getUploadRootDir()
{
return __DIR__.'/../../../web/'.$this->getUploadDir();
}
}
9) //-- update your "app\config\security.yml" file --//
security:
encoders:
AppBundle\Entity\User: sha512
providers:
main:
id: fos_user.user_provider.username_email
firewalls:
main:
pattern: ^/
form_login:
login_path: fos_user_security_login
check_path: fos_user_security_check
provider: main
csrf_token_generator: security.csrf.token_manager
anonymous: true
logout:
path: fos_user_security_logout
remember_me:
secret: "%secret%"
role_hierarchy:
ROLE_USER: [ROLE_ANONYMOUS_USER]
ROLE_ADMIN: [ROLE_USER, ROLE_ALLOWED_TO_SWITCH]
ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
access_control:
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/, role: ROLE_ADMIN }
- { path: ^/efconnect, role: ROLE_ADMIN }
- { path: ^/elfinder, role: ROLE_ADMIN }
10) //-- enter this command in your terminal WARNING! THE DATABASE MUST BE CREATED BEFORE LAUNCHING COMMAND --//
//-- the command install folders. in case of error during the command, see the "gkratzadmin\Command folder --//
//-- IN PRODUCTION MODE, USE: "php bin/console gkratz:generate:all --env=prod"
php bin/console gkratz:generate:all
11) //-- load example datas. In case of error, truncate the tables and enter again the command --//
php bin/console doctrine:fixtures:load --append
HOW TO USE
- visit the complete admin at yoursite/admin (username/password: user/user or admin/admin)
- to use the softDelete filter, every entity with a state field must be filtered in front-end:
ie: $this->getDoctrine()->getRepository(Class:class)->findBy(array('state' => 0, 'otherField' => 'otherValue'));
- to use the search plugin, you need to activate the fields for the search in the config.yml and
your entity must have a state integer field
# config.yml
# GkratzAdminBundle Configuration
gkratz_admin:
search:
allow_approaching: true # may be very slow. set false to only allow perfect match.
fields: Post.title, Post.content, User.username, User.lastname, User.firstname, User.locality, User.country
# ...
- you can use database strings encryption with the @Encrypted() annotation
don't forget the use statement: use Ambta\DoctrineEncryptBundle\Configuration\Encrypted;
- you can use shortcuts:
* ctrl + h: navigate from profile or back-office to the homepage
* ctrl + p: navigate from back-office to profile
(only for users with role 'ROLE_ADMIN')
* ctrl + b: navigate from profile to back-office
(only for users with role 'ROLE_ADMIN')
* ctrl + click: select elements in lists of entities or tables sortable
(only for users with role 'ROLE_ADMIN')
* shift + click: select elements in lists of entities or tables sortable
(only for users with role 'ROLE_ADMIN')
* ctrl + a: select/deselect all elements in lists of entities or tables sortable
(only for users with role 'ROLE_ADMIN')
* ctrl + s: save and submit forms
(only for users with role 'ROLE_ADMIN')
- to make a CRUD for a new entity named "Barfoo", you just need:
* a "state" integer field to your entity "Barfoo"
* an entry in the menu with this path: {{ path('gkratz_admin_admin_barfoo_index') }}
* a BarfooType and a BarfooFilterType
* a folder "barfoo" in Gkartz\AdminBundle\Resources\views\admin folder with 2 views: index and form,
* a BarfooController in Gkartz\AdminBundle\Controller\Admin with:
<?php
namespace Gkratz\AdminBundle\Controller\Admin;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
/**
* @Route("/user")
* Class BarfooController
* @package Gkratz\AdminBundle\Controller\Admin
*/
class BarfooController extends AdminController
{
protected function getClassFilterForm(){
return \Gkratz\AdminBundle\FormFilter\BarfooFilterType::class;
}
protected function getClassForm(){
return \Gkratz\AdminBundle\Form\BarfooType::class;
}
protected function getClass(){
return 'AppBundle\Entity\Barfoo';
}
protected function getClassName(){
return \AppBundle\Entity\Barfoo::class;
}
protected function getName(){
return 'barfoo';
}
protected function getLabel(){
return 'Barfoo';
}
}
OVERRIDE
- all the views and controllers are override ready. Like any bundle.
- take your time to understand the power of the bundle: backup, maintenance, messaging, notifying, UX and UI, data modeling in viewing, ...
- you can easily modify the layout use for the fosuser views