protected function getAdministratorRole()
    {
        $role = Voyager::model('Role')->firstOrNew([
            'name' => 'admin',
        ]);

        if (!$role->exists) {
            $role->fill([
                'display_name' => 'Administrator',
            ])->save();
        }

        return $role;
    }

protected function getAdministratorRole ( ) { $ role = Voyager :: model ( 'Role' ) -> firstOrNew ( [ 'name' => 'admin' , ] ) ; if ( ! $ role -> exists ) { $ role -> fill ( [ 'display_name' => 'Administrator' , ] ) -> save ( ) ; } return $ role ; }

Get the administrator role, create it if it does not exists.

@return mixed

Get the administrator role create it if it does not exists .


protected function getUser($create = false)
    {
        $email = $this->argument('email');

        $model = config('voyager.user.namespace') ?: config('auth.providers.users.model');

        // If we need to create a new user go ahead and create it
        if ($create) {
            $name = $this->ask('Enter the admin name');
            $password = $this->secret('Enter admin password');
            $confirmPassword = $this->secret('Confirm Password');

            // Ask for email if there wasnt set one
            if (!$email) {
                $email = $this->ask('Enter the admin email');
            }

            // Passwords don't match
            if ($password != $confirmPassword) {
                $this->info("Passwords don't match");

                return;
            }

            $this->info('Creating admin account');

            return $model::create([
                'name'     => $name,
                'email'    => $email,
                'password' => Hash::make($password),
            ]);
        }

        return $model::where('email', $email)->firstOrFail();
    }

Get or create user.

@param bool $create

@return \App\User


public function handle(BreadDeleted $bread)
    {
        if (config('voyager.bread.add_menu_item')) {
            $menuItem = Voyager::model('MenuItem')->where('route', 'voyager.'.$bread->dataType->slug.'.index');

            if ($menuItem->exists()) {
                $menuItem->delete();
            }
        }
    }

public function handle ( BreadDeleted $ bread ) { if ( config ( 'voyager.bread.add_menu_item' ) ) { $ menuItem = Voyager :: model ( 'MenuItem' ) -> where ( 'route' , 'voyager.' . $ bread -> dataType -> slug . '.index' ) ; if ( $ menuItem -> exists ( ) ) { $ menuItem -> delete ( ) ; } } }

Delete a MenuItem for a given BREAD.

@param BreadDeleted $bread

@return void


private function categoriesTranslations()
    {
        // Adding translations for 'categories'
        //
        $cat = Category::where('slug', 'category-1')->firstOrFail();
        if ($cat->exists) {
            $this->trans('pt', $this->arr(['categories', 'slug'], $cat->id), 'categoria-1');
            $this->trans('pt', $this->arr(['categories', 'name'], $cat->id), 'Categoria 1');
        }
        $cat = Category::where('slug', 'category-2')->firstOrFail();
        if ($cat->exists) {
            $this->trans('pt', $this->arr(['categories', 'slug'], $cat->id), 'categoria-2');
            $this->trans('pt', $this->arr(['categories', 'name'], $cat->id), 'Categoria 2');
        }
    }

private
function
categoriesTranslations
(
)
{
// Adding translations for 'categories'
//
$
cat
=
Category
::
where
(
'slug'
,
'category-1'
)
->
firstOrFail
(
)
;
if
(
$
cat
->
exists
)
{
$
this
->
trans
(
'pt'
,
$
this
->
arr
(
[
'categories'
,
'slug'
]
,
$
cat
->
id
)
,
'categoria-1'
)
;
$
this
->
trans
(
'pt'
,
$
this
->
arr
(
[
'categories'
,
'name'
]
,
$
cat
->
id
)
,
'Categoria 1'
)
;
}
$
cat
=
Category
::
where
(
'slug'
,
'category-2'
)
->
firstOrFail
(
)
;
if
(
$
cat
->
exists
)
{
$
this
->
trans
(
'pt'
,
$
this
->
arr
(
[
'categories'
,
'slug'
]
,
$
cat
->
id
)
,
'categoria-2'
)
;
$
this
->
trans
(
'pt'
,
$
this
->
arr
(
[
'categories'
,
'name'
]
,
$
cat
->
id
)
,
'Categoria 2'
)
;
}
}

Auto generate Categories Translations.

@return void


public function highestOrderMenuItem($parent = null)
    {
        $order = 1;

        $item = $this->where('parent_id', '=', $parent)
            ->orderBy('order', 'DESC')
            ->first();

        if (!is_null($item)) {
            $order = intval($item->order) + 1;
        }

        return $order;
    }

public function highestOrderMenuItem ( $ parent = null ) { $ order = 1 ; $ item = $ this -> where ( 'parent_id' , '=' , $ parent ) -> orderBy ( 'order' , 'DESC' ) -> first ( ) ; if ( ! is_null ( $ item ) ) { $ order = intval ( $ item -> order ) + 1 ; } return $ order ; }

Return the Highest Order Menu Item.

@param number $parent (Optional) Parent id. Default null

@return number Order number


public static function createName(array $columns, $type, $table = null)
    {
        $table = isset($table) ? trim($table).'_' : '';
        $type = trim($type);
        $name = strtolower($table.implode('_', $columns).'_'.$type);

        return str_replace(['-', '.'], '_', $name);
    }

public static function createName ( array $ columns , $ type , $ table = null ) { $ table = isset ( $ table ) ? trim ( $ table ) . '_' : '' ; $ type = trim ( $ type ) ; $ name = strtolower ( $ table . implode ( '_' , $ columns ) . '_' . $ type ) ; return str_replace ( [ '-' , '.' ] , '_' , $ name ) ; }

Create a default index name.

@param array  $columns
@param string $type
@param string $table

@return string


public function handle(BreadAdded $bread)
    {
        if (config('voyager.bread.add_menu_item') && file_exists(base_path('routes/web.php'))) {
            require base_path('routes/web.php');

            $menu = Voyager::model('Menu')->where('name', config('voyager.bread.default_menu'))->firstOrFail();

            $menuItem = Voyager::model('MenuItem')->firstOrNew([
                'menu_id' => $menu->id,
                'title'   => $bread->dataType->display_name_plural,
                'url'     => '',
                'route'   => 'voyager.'.$bread->dataType->slug.'.index',
            ]);

            $order = Voyager::model('MenuItem')->highestOrderMenuItem();

            if (!$menuItem->exists) {
                $menuItem->fill([
                    'target'     => '_self',
                    'icon_class' => $bread->dataType->icon,
                    'color'      => null,
                    'parent_id'  => null,
                    'order'      => $order,
                ])->save();
            }
        }
    }

public function handle ( BreadAdded $ bread ) { if ( config ( 'voyager.bread.add_menu_item' ) && file_exists ( base_path ( 'routes/web.php' ) ) ) { require base_path ( 'routes/web.php' ) ; $ menu = Voyager :: model ( 'Menu' ) -> where ( 'name' , config ( 'voyager.bread.default_menu' ) ) -> firstOrFail ( ) ; $ menuItem = Voyager :: model ( 'MenuItem' ) -> firstOrNew ( [ 'menu_id' => $ menu -> id , 'title' => $ bread -> dataType -> display_name_plural , 'url' => '' , 'route' => 'voyager.' . $ bread -> dataType -> slug . '.index' , ] ) ; $ order = Voyager :: model ( 'MenuItem' ) -> highestOrderMenuItem ( ) ; if ( ! $ menuItem -> exists ) { $ menuItem -> fill ( [ 'target' => '_self' , 'icon_class' => $ bread -> dataType -> icon , 'color' => null , 'parent_id' => null , 'order' => $ order , ] ) -> save ( ) ; } } }

Create a MenuItem for a given BREAD.

@param BreadAdded $event

@return void


public static function update($table)
    {
        if (!is_array($table)) {
            $table = json_decode($table, true);
        }

        if (!SchemaManager::tableExists($table['oldName'])) {
            throw SchemaException::tableDoesNotExist($table['oldName']);
        }

        $updater = new self($table);

        $updater->updateTable();
    }

public static function update ( $ table ) { if ( ! is_array ( $ table ) ) { $ table = json_decode ( $ table , true ) ; } if ( ! SchemaManager :: tableExists ( $ table [ 'oldName' ] ) ) { throw SchemaException :: tableDoesNotExist ( $ table [ 'oldName' ] ) ; } $ updater = new self ( $ table ) ; $ updater -> updateTable ( ) ; }


public function updateTable()
    {
        // Get table new name
        if (($newName = $this->table->getName()) != $this->originalTable->getName()) {
            // Make sure the new name doesn't already exist
            if (SchemaManager::tableExists($newName)) {
                throw SchemaException::tableAlreadyExists($newName);
            }
        } else {
            $newName = false;
        }

        // Rename columns
        if ($renamedColumnsDiff = $this->getRenamedColumnsDiff()) {
            SchemaManager::alterTable($renamedColumnsDiff);

            // Refresh original table after renaming the columns
            $this->originalTable = SchemaManager::listTableDetails($this->tableArr['oldName']);
        }

        $tableDiff = $this->originalTable->diff($this->table);

        // Add new table name to tableDiff
        if ($newName) {
            if (!$tableDiff) {
                $tableDiff = new TableDiff($this->tableArr['oldName']);
                $tableDiff->fromTable = $this->originalTable;
            }

            $tableDiff->newName = $newName;
        }

        // Update the table
        if ($tableDiff) {
            SchemaManager::alterTable($tableDiff);
        }
    }


protected function getRenamedColumnsDiff()
    {
        $renamedColumns = $this->getRenamedColumns();

        if (empty($renamedColumns)) {
            return false;
        }

        $renamedColumnsDiff = new TableDiff($this->tableArr['oldName']);
        $renamedColumnsDiff->fromTable = $this->originalTable;

        foreach ($renamedColumns as $oldName => $newName) {
            $renamedColumnsDiff->renamedColumns[$oldName] = $this->table->getColumn($newName);
        }

        return $renamedColumnsDiff;
    }

protected function getRenamedColumnsDiff ( ) { $ renamedColumns = $ this -> getRenamedColumns ( ) ; if ( empty ( $ renamedColumns ) ) { return false ; } $ renamedColumnsDiff = new TableDiff ( $ this -> tableArr [ 'oldName' ] ) ; $ renamedColumnsDiff -> fromTable = $ this -> originalTable ; foreach ( $ renamedColumns as $ oldName => $ newName ) { $ renamedColumnsDiff -> renamedColumns [ $ oldName ] = $ this -> table -> getColumn ( $ newName ) ; } return $ renamedColumnsDiff ; }

Get the table diff to rename columns.

@return \Doctrine\DBAL\Schema\TableDiff


protected function getRenamedDiff()
    {
        $renamedColumns = $this->getRenamedColumns();
        $renamedIndexes = $this->getRenamedIndexes();

        if (empty($renamedColumns) && empty($renamedIndexes)) {
            return false;
        }

        $renamedDiff = new TableDiff($this->tableArr['oldName']);
        $renamedDiff->fromTable = $this->originalTable;

        foreach ($renamedColumns as $oldName => $newName) {
            $renamedDiff->renamedColumns[$oldName] = $this->table->getColumn($newName);
        }

        foreach ($renamedIndexes as $oldName => $newName) {
            $renamedDiff->renamedIndexes[$oldName] = $this->table->getIndex($newName);
        }

        return $renamedDiff;
    }

protected function getRenamedDiff ( ) { $ renamedColumns = $ this -> getRenamedColumns ( ) ; $ renamedIndexes = $ this -> getRenamedIndexes ( ) ; if ( empty ( $ renamedColumns ) && empty ( $ renamedIndexes ) ) { return false ; } $ renamedDiff = new TableDiff ( $ this -> tableArr [ 'oldName' ] ) ; $ renamedDiff -> fromTable = $ this -> originalTable ; foreach ( $ renamedColumns as $ oldName => $ newName ) { $ renamedDiff -> renamedColumns [ $ oldName ] = $ this -> table -> getColumn ( $ newName ) ; } foreach ( $ renamedIndexes as $ oldName => $ newName ) { $ renamedDiff -> renamedIndexes [ $ oldName ] = $ this -> table -> getIndex ( $ newName ) ; } return $ renamedDiff ; }

Get the table diff to rename columns and indexes.

@return \Doctrine\DBAL\Schema\TableDiff

Get the table diff to rename columns and indexes .


protected function getRenamedColumns()
    {
        $renamedColumns = [];

        foreach ($this->tableArr['columns'] as $column) {
            $oldName = $column['oldName'];

            // make sure this is an existing column and not a new one
            if ($this->originalTable->hasColumn($oldName)) {
                $name = $column['name'];

                if ($name != $oldName) {
                    $renamedColumns[$oldName] = $name;
                }
            }
        }

        return $renamedColumns;
    }

Get columns that were renamed.

@return array


protected function getRenamedIndexes()
    {
        $renamedIndexes = [];

        foreach ($this->tableArr['indexes'] as $index) {
            $oldName = $index['oldName'];

            // make sure this is an existing index and not a new one
            if ($this->originalTable->hasIndex($oldName)) {
                $name = $index['name'];

                if ($name != $oldName) {
                    $renamedIndexes[$oldName] = $name;
                }
            }
        }

        return $renamedIndexes;
    }

Get indexes that were renamed.

@return array


public function thumbnail($type, $attribute = 'image')
    {
        // Return empty string if the field not found
        if (!isset($this->attributes[$attribute])) {
            return '';
        }

        // We take image from posts field
        $image = $this->attributes[$attribute];

        return $this->getThumbnail($image, $type);
    }

Method for returning specific thumbnail for model.

@param string $type
@param string $attribute

@return string

Method for returning specific thumbnail for model .


public function getThumbnail($image, $type)
    {
        // We need to get extension type ( .jpeg , .png ...)
        $ext = pathinfo($image, PATHINFO_EXTENSION);

        // We remove extension from file name so we can append thumbnail type
        $name = Str::replaceLast('.'.$ext, '', $image);

        // We merge original name + type + extension
        return $name.'-'.$type.'.'.$ext;
    }

Generate thumbnail URL.

@param $image
@param $type

@return string


public function editRoles(User $user, $model)
    {
        // Does this record belong to another user?
        $another = $user->id != $model->id;

        return $another && $user->hasPermission('edit_users');
    }

Determine if the given user can change a user a role.

@param \TCG\Voyager\Contracts\User $user
@param  $model

@return bool

Determine if the given user can change a user a role .


public function dimmers()
    {
        $widgetClasses = config('voyager.dashboard.widgets');
        $dimmers = Widget::group('voyager::dimmers');

        foreach ($widgetClasses as $widgetClass) {
            $widget = app($widgetClass);

            if ($widget->shouldBeDisplayed()) {
                $dimmers->addWidget($widgetClass);
            }
        }

        return $dimmers;
    }

public function dimmers ( ) { $ widgetClasses = config ( 'voyager.dashboard.widgets' ) ; $ dimmers = Widget :: group ( 'voyager::dimmers' ) ; foreach ( $ widgetClasses as $ widgetClass ) { $ widget = app ( $ widgetClass ) ; if ( $ widget -> shouldBeDisplayed ( ) ) { $ dimmers -> addWidget ( $ widgetClass ) ; } } return $ dimmers ; }

Get a collection of the dashboard widgets.

@return \Arrilot\Widgets\WidgetGroup

Get a collection of the dashboard widgets .


protected function prepareMenuTranslations(&$data)
    {
        $trans = json_decode($data['title_i18n'], true);

        // Set field value with the default locale
        $data['title'] = $trans[config('voyager.multilingual.default', 'en')];

        unset($data['title_i18n']);     // Remove hidden input holding translations
        unset($data['i18n_selector']);  // Remove language selector input radio

        return $trans;
    }

Prepare menu translations.

@param array $data menu data

@return JSON translated item


public function save()
    {
        $attributes = $this->getModifiedAttributes();
        $savings = [];

        foreach ($attributes as $key => $attribute) {
            if ($attribute['exists']) {
                $translation = $this->getTranslationModel($key);
            } else {
                $translation = VoyagerFacade::model('Translation')->where('table_name', $this->model->getTable())
                    ->where('column_name', $key)
                    ->where('foreign_key', $this->model->getKey())
                    ->where('locale', $this->locale)
                    ->first();
            }

            if (is_null($translation)) {
                $translation = VoyagerFacade::model('Translation');
            }

            $translation->fill([
                'table_name'  => $this->model->getTable(),
                'column_name' => $key,
                'foreign_key' => $this->model->getKey(),
                'value'       => $attribute['value'],
                'locale'      => $this->locale,
            ]);

            $savings[] = $translation->save();

            $this->attributes[$key]['locale'] = $this->locale;
            $this->attributes[$key]['exists'] = true;
            $this->attributes[$key]['modified'] = false;
        }

        return in_array(false, $savings);
    }

public function save ( ) { $ attributes = $ this -> getModifiedAttributes ( ) ; $ savings = [ ] ; foreach ( $ attributes as $ key => $ attribute ) { if ( $ attribute [ 'exists' ] ) { $ translation = $ this -> getTranslationModel ( $ key ) ; } else { $ translation = VoyagerFacade :: model ( 'Translation' ) -> where ( 'table_name' , $ this -> model -> getTable ( ) ) -> where ( 'column_name' , $ key ) -> where ( 'foreign_key' , $ this -> model -> getKey ( ) ) -> where ( 'locale' , $ this -> locale ) -> first ( ) ; } if ( is_null ( $ translation ) ) { $ translation = VoyagerFacade :: model ( 'Translation' ) ; } $ translation -> fill ( [ 'table_name' => $ this -> model -> getTable ( ) , 'column_name' => $ key , 'foreign_key' => $ this -> model -> getKey ( ) , 'value' => $ attribute [ 'value' ] , 'locale' => $ this -> locale , ] ) ; $ savings [ ] = $ translation -> save ( ) ; $ this -> attributes [ $ key ] [ 'locale' ] = $ this -> locale ; $ this -> attributes [ $ key ] [ 'exists' ] = true ; $ this -> attributes [ $ key ] [ 'modified' ] = false ; } return in_array ( false , $ savings ) ; }

Save changes made to the translator attributes.

@return bool

Save changes made to the translator attributes .


public function read(User $user, $model)
    {
        // Does this post belong to the current user?
        $current = $user->id === $model->author_id;

        return $current || $this->checkPermission($user, $model, 'read');
    }

Determine if the given model can be viewed by the user.

@param \TCG\Voyager\Contracts\User $user
@param  $model

@return bool

Determine if the given model can be viewed by the user .


public function create(Request $request, $table)
    {
        $this->authorize('browse_bread');

        $dataType = Voyager::model('DataType')->whereName($table)->first();

        $data = $this->prepopulateBreadInfo($table);
        $data['fieldOptions'] = SchemaManager::describeTable((isset($dataType) && strlen($dataType->model_name) != 0)
            ? app($dataType->model_name)->getTable()
            : $table
        );

        return Voyager::view('voyager::tools.bread.edit-add', $data);
    }

public function create ( Request $ request , $ table ) { $ this -> authorize ( 'browse_bread' ) ; $ dataType = Voyager :: model ( 'DataType' ) -> whereName ( $ table ) -> first ( ) ; $ data = $ this -> prepopulateBreadInfo ( $ table ) ; $ data [ 'fieldOptions' ] = SchemaManager :: describeTable ( ( isset ( $ dataType ) && strlen ( $ dataType -> model_name ) != 0 ) ? app ( $ dataType -> model_name ) -> getTable ( ) : $ table ) ; return Voyager :: view ( 'voyager::tools.bread.edit-add' , $ data ) ; }

Create BREAD.

@param Request $request
@param string  $table   Table name.

@return \Illuminate\Contracts\View\Factory|\Illuminate\View\View


public function store(Request $request)
    {
        $this->authorize('browse_bread');

        try {
            $dataType = Voyager::model('DataType');
            $res = $dataType->updateDataType($request->all(), true);
            $data = $res
                ? $this->alertSuccess(__('voyager::bread.success_created_bread'))
                : $this->alertError(__('voyager::bread.error_creating_bread'));
            if ($res) {
                event(new BreadAdded($dataType, $data));
            }

            return redirect()->route('voyager.bread.index')->with($data);
        } catch (Exception $e) {
            return redirect()->route('voyager.bread.index')->with($this->alertException($e, 'Saving Failed'));
        }
    }

public
function
store
(
Request
$
request
)
{
$
this
->
authorize
(
'browse_bread'
)
;
try
{
$
dataType
=
Voyager
::
model
(
'DataType'
)
;
$
res
=
$
dataType
->
updateDataType
(
$
request
->
all
(
)
,
true
)
;
$
data
=
$
res
$
this
->
alertSuccess
(
__
(
'voyager::bread.success_created_bread'
)
)
:
$
this
->
alertError
(
__
(
'voyager::bread.error_creating_bread'
)
)
;
if
(
$
res
)
{
event
(
new
BreadAdded
(
$
dataType
,
$
data
)
)
;
}
return
redirect
(
)
->
route
(
'voyager.bread.index'
)
->
with
(
$
data
)
;
}
catch
(
Exception
$
e
)
{
return
redirect
(
)
->
route
(
'voyager.bread.index'
)
->
with
(
$
this
->
alertException
(
$
e
,
'Saving Failed'
)
)
;
}
}

Store BREAD.

@param \Illuminate\Http\Request $request

@return \Illuminate\Http\RedirectResponse


public function edit($table)
    {
        $this->authorize('browse_bread');

        $dataType = Voyager::model('DataType')->whereName($table)->first();

        $fieldOptions = SchemaManager::describeTable((strlen($dataType->model_name) != 0)
            ? app($dataType->model_name)->getTable()
            : $dataType->name
        );

        $isModelTranslatable = is_bread_translatable($dataType);
        $tables = SchemaManager::listTableNames();
        $dataTypeRelationships = Voyager::model('DataRow')->where('data_type_id', '=', $dataType->id)->where('type', '=', 'relationship')->get();
        $scopes = [];
        if ($dataType->model_name != '') {
            $scopes = $this->getModelScopes($dataType->model_name);
        }

        return Voyager::view('voyager::tools.bread.edit-add', compact('dataType', 'fieldOptions', 'isModelTranslatable', 'tables', 'dataTypeRelationships', 'scopes'));
    }

public function edit ( $ table ) { $ this -> authorize ( 'browse_bread' ) ; $ dataType = Voyager :: model ( 'DataType' ) -> whereName ( $ table ) -> first ( ) ; $ fieldOptions = SchemaManager :: describeTable ( ( strlen ( $ dataType -> model_name ) != 0 ) ? app ( $ dataType -> model_name ) -> getTable ( ) : $ dataType -> name ) ; $ isModelTranslatable = is_bread_translatable ( $ dataType ) ; $ tables = SchemaManager :: listTableNames ( ) ; $ dataTypeRelationships = Voyager :: model ( 'DataRow' ) -> where ( 'data_type_id' , '=' , $ dataType -> id ) -> where ( 'type' , '=' , 'relationship' ) -> get ( ) ; $ scopes = [ ] ; if ( $ dataType -> model_name != '' ) { $ scopes = $ this -> getModelScopes ( $ dataType -> model_name ) ; } return Voyager :: view ( 'voyager::tools.bread.edit-add' , compact ( 'dataType' , 'fieldOptions' , 'isModelTranslatable' , 'tables' , 'dataTypeRelationships' , 'scopes' ) ) ; }

Edit BREAD.

@param string $table

@return \Illuminate\Contracts\View\Factory|\Illuminate\View\View


public function update(Request $request, $id)
    {
        $this->authorize('browse_bread');

        /* @var \TCG\Voyager\Models\DataType $dataType */
        try {
            $dataType = Voyager::model('DataType')->find($id);

            // Prepare Translations and Transform data
            $translations = is_bread_translatable($dataType)
                ? $dataType->prepareTranslations($request)
                : [];

            $res = $dataType->updateDataType($request->all(), true);
            $data = $res
                ? $this->alertSuccess(__('voyager::bread.success_update_bread', ['datatype' => $dataType->name]))
                : $this->alertError(__('voyager::bread.error_updating_bread'));
            if ($res) {
                event(new BreadUpdated($dataType, $data));
            }

            // Save translations if applied
            $dataType->saveTranslations($translations);

            return redirect()->route('voyager.bread.index')->with($data);
        } catch (Exception $e) {
            return back()->with($this->alertException($e, __('voyager::generic.update_failed')));
        }
    }

Update BREAD.

@param \Illuminate\Http\Request $request
@param number                   $id

@return \Illuminate\Contracts\View\Factory|\Illuminate\View\View


public function destroy($id)
    {
        $this->authorize('browse_bread');

        /* @var \TCG\Voyager\Models\DataType $dataType */
        $dataType = Voyager::model('DataType')->find($id);

        // Delete Translations, if present
        if (is_bread_translatable($dataType)) {
            $dataType->deleteAttributeTranslations($dataType->getTranslatableAttributes());
        }

        $res = Voyager::model('DataType')->destroy($id);
        $data = $res
            ? $this->alertSuccess(__('voyager::bread.success_remove_bread', ['datatype' => $dataType->name]))
            : $this->alertError(__('voyager::bread.error_updating_bread'));
        if ($res) {
            event(new BreadDeleted($dataType, $data));
        }

        if (!is_null($dataType)) {
            Voyager::model('Permission')->removeFrom($dataType->name);
        }

        return redirect()->route('voyager.bread.index')->with($data);
    }

Delete BREAD.

@param Number $id BREAD data_type id.

@return \Illuminate\Http\RedirectResponse


public function addRelationship(Request $request)
    {
        $relationshipField = $this->getRelationshipField($request);

        if (!class_exists($request->relationship_model)) {
            return back()->with([
                'message'    => 'Model Class '.$request->relationship_model.' does not exist. Please create Model before creating relationship.',
                'alert-type' => 'error',
            ]);
        }

        try {
            DB::beginTransaction();

            $relationship_column = $request->relationship_column_belongs_to;
            if ($request->relationship_type == 'hasOne' || $request->relationship_type == 'hasMany') {
                $relationship_column = $request->relationship_column;
            }

            // Build the relationship details
            $relationshipDetails = [
                'model'       => $request->relationship_model,
                'table'       => $request->relationship_table,
                'type'        => $request->relationship_type,
                'column'      => $relationship_column,
                'key'         => $request->relationship_key,
                'label'       => $request->relationship_label,
                'pivot_table' => $request->relationship_pivot,
                'pivot'       => ($request->relationship_type == 'belongsToMany') ? '1' : '0',
                'taggable'    => $request->relationship_taggable,
            ];

            $className = Voyager::modelClass('DataRow');
            $newRow = new $className();

            $newRow->data_type_id = $request->data_type_id;
            $newRow->field = $relationshipField;
            $newRow->type = 'relationship';
            $newRow->display_name = $request->relationship_table;
            $newRow->required = 0;

            foreach (['browse', 'read', 'edit', 'add', 'delete'] as $check) {
                $newRow->{$check} = 1;
            }

            $newRow->details = $relationshipDetails;
            $newRow->order = intval(Voyager::model('DataType')->find($request->data_type_id)->lastRow()->order) + 1;

            if (!$newRow->save()) {
                return back()->with([
                    'message'    => 'Error saving new relationship row for '.$request->relationship_table,
                    'alert-type' => 'error',
                ]);
            }

            DB::commit();

            return back()->with([
                'message'    => 'Successfully created new relationship for '.$request->relationship_table,
                'alert-type' => 'success',
            ]);
        } catch (\Exception $e) {
            DB::rollBack();

            return back()->with([
                'message'    => 'Error creating new relationship: '.$e->getMessage(),
                'alert-type' => 'error',
            ]);
        }
    }

Add Relationship.

@param Request $request


private function getRelationshipField($request)
    {
        // We need to make sure that we aren't creating an already existing field

        $dataType = Voyager::model('DataType')->find($request->data_type_id);

        $field = Str::singular($dataType->name).'_'.$request->relationship_type.'_'.Str::singular($request->relationship_table).'_relationship';

        $relationshipFieldOriginal = $relationshipField = strtolower($field);

        $existingRow = Voyager::model('DataRow')->where('field', '=', $relationshipField)->first();
        $index = 1;

        while (isset($existingRow->id)) {
            $relationshipField = $relationshipFieldOriginal.'_'.$index;
            $existingRow = Voyager::model('DataRow')->where('field', '=', $relationshipField)->first();
            $index += 1;
        }

        return $relationshipField;
    }

Get Relationship Field.

@param Request $request

@return string


public function handle()
    {
        return empty($this->request->input($this->row->field)) ? null :
            bcrypt($this->request->input($this->row->field));
    }

public function handle ( ) { return empty ( $ this -> request -> input ( $ this -> row -> field ) ) ? null : bcrypt ( $ this -> request -> input ( $ this -> row -> field ) ) ; }


public function store(Request $request)
    {
        $this->authorize('browse_database');

        try {
            $conn = 'database.connections.'.config('database.default');
            Type::registerCustomPlatformTypes();

            $table = $request->table;
            if (!is_array($request->table)) {
                $table = json_decode($request->table, true);
            }
            $table['options']['collate'] = config($conn.'.collation', 'utf8mb4_unicode_ci');
            $table['options']['charset'] = config($conn.'.charset', 'utf8mb4');
            $table = Table::make($table);
            SchemaManager::createTable($table);

            if (isset($request->create_model) && $request->create_model == 'on') {
                $modelNamespace = config('voyager.models.namespace', app()->getNamespace());
                $params = [
                    'name' => $modelNamespace.Str::studly(Str::singular($table->name)),
                ];

                // if (in_array('deleted_at', $request->input('field.*'))) {
                //     $params['--softdelete'] = true;
                // }

                if (isset($request->create_migration) && $request->create_migration == 'on') {
                    $params['--migration'] = true;
                }

                Artisan::call('voyager:make:model', $params);
            } elseif (isset($request->create_migration) && $request->create_migration == 'on') {
                Artisan::call('make:migration', [
                    'name'    => 'create_'.$table->name.'_table',
                    '--table' => $table->name,
                ]);
            }

            event(new TableAdded($table));

            return redirect()
               ->route('voyager.database.index')
               ->with($this->alertSuccess(__('voyager::database.success_create_table', ['table' => $table->name])));
        } catch (Exception $e) {
            return back()->with($this->alertException($e))->withInput();
        }
    }

Store new database table.

@param \Illuminate\Http\Request $request

@return \Illuminate\Http\RedirectResponse


public function edit($table)
    {
        $this->authorize('browse_database');

        if (!SchemaManager::tableExists($table)) {
            return redirect()
                ->route('voyager.database.index')
                ->with($this->alertError(__('voyager::database.edit_table_not_exist')));
        }

        $db = $this->prepareDbManager('update', $table);

        return Voyager::view('voyager::tools.database.edit-add', compact('db'));
    }

Edit database table.

@param string $table

@return \Illuminate\Http\RedirectResponse


public function update(Request $request)
    {
        $this->authorize('browse_database');

        $table = json_decode($request->table, true);

        try {
            DatabaseUpdater::update($table);
            // TODO: synch BREAD with Table
            // $this->cleanOldAndCreateNew($request->original_name, $request->name);
            event(new TableUpdated($table));
        } catch (Exception $e) {
            return back()->with($this->alertException($e))->withInput();
        }

        return redirect()
               ->route('voyager.database.index')
               ->with($this->alertSuccess(__('voyager::database.success_create_table', ['table' => $table['name']])));
    }

Update database table.

@param \Illuminate\Http\Request $request

@return \Illuminate\Http\RedirectResponse


public function show($table)
    {
        $this->authorize('browse_database');

        $additional_attributes = [];
        $model_name = Voyager::model('DataType')->where('name', $table)->pluck('model_name')->first();
        if (isset($model_name)) {
            $model = app($model_name);
            if (isset($model->additional_attributes)) {
                foreach ($model->additional_attributes as $attribute) {
                    $additional_attributes[$attribute] = [];
                }
            }
        }

        return response()->json(collect(SchemaManager::describeTable($table))->merge($additional_attributes));
    }

public function show ( $ table ) { $ this -> authorize ( 'browse_database' ) ; $ additional_attributes = [ ] ; $ model_name = Voyager :: model ( 'DataType' ) -> where ( 'name' , $ table ) -> pluck ( 'model_name' ) -> first ( ) ; if ( isset ( $ model_name ) ) { $ model = app ( $ model_name ) ; if ( isset ( $ model -> additional_attributes ) ) { foreach ( $ model -> additional_attributes as $ attribute ) { $ additional_attributes [ $ attribute ] = [ ] ; } } } return response ( ) -> json ( collect ( SchemaManager :: describeTable ( $ table ) ) -> merge ( $ additional_attributes ) ) ; }

Show table.

@param string $table

@return JSON


public function destroy($table)
    {
        $this->authorize('browse_database');

        try {
            SchemaManager::dropTable($table);
            event(new TableDeleted($table));

            return redirect()
                ->route('voyager.database.index')
                ->with($this->alertSuccess(__('voyager::database.success_delete_table', ['table' => $table])));
        } catch (Exception $e) {
            return back()->with($this->alertException($e));
        }
    }

Destroy table.

@param string $table

@return \Illuminate\Http\RedirectResponse


public function sortByUrl($orderBy, $sortOrder)
    {
        $params = [];
        $isDesc = $sortOrder != 'asc';
        if ($this->isCurrentSortField($orderBy) && $isDesc) {
            $params['sort_order'] = 'asc';
        } else {
            $params['sort_order'] = 'desc';
        }
        $params['order_by'] = $this->field;

        return url()->current().'?'.http_build_query(array_merge(\Request::all(), $params));
    }

public function sortByUrl ( $ orderBy , $ sortOrder ) { $ params = [ ] ; $ isDesc = $ sortOrder != 'asc' ; if ( $ this -> isCurrentSortField ( $ orderBy ) && $ isDesc ) { $ params [ 'sort_order' ] = 'asc' ; } else { $ params [ 'sort_order' ] = 'desc' ; } $ params [ 'order_by' ] = $ this -> field ; return url ( ) -> current ( ) . '?' . http_build_query ( array_merge ( \ Request :: all ( ) , $ params ) ) ; }

Build the URL to sort data type by this field.

@return string Built URL

Build the URL to sort data type by this field .


public static function display($menuName, $type = null, array $options = [])
    {
        // GET THE MENU - sort collection in blade
        $menu = \Cache::remember('voyager_menu_'.$menuName, \Carbon\Carbon::now()->addDays(30), function () use ($menuName) {
            return static::where('name', '=', $menuName)
            ->with(['parent_items.children' => function ($q) {
                $q->orderBy('order');
            }])
            ->first();
        });

        // Check for Menu Existence
        if (!isset($menu)) {
            return false;
        }

        event(new MenuDisplay($menu));

        // Convert options array into object
        $options = (object) $options;

        $items = $menu->parent_items->sortBy('order');

        if ($menuName == 'admin' && $type == '_json') {
            $items = static::processItems($items);
        }

        if ($type == 'admin') {
            $type = 'voyager::menu.'.$type;
        } else {
            if (is_null($type)) {
                $type = 'voyager::menu.default';
            } elseif ($type == 'bootstrap' && !view()->exists($type)) {
                $type = 'voyager::menu.bootstrap';
            }
        }

        if (!isset($options->locale)) {
            $options->locale = app()->getLocale();
        }

        if ($type === '_json') {
            return $items;
        }

        return new \Illuminate\Support\HtmlString(
            \Illuminate\Support\Facades\View::make($type, ['items' => $items, 'options' => $options])->render()
        );
    }

Display menu.

@param string      $menuName
@param string|null $type
@param array       $options

@return string


public function translatable()
    {
        if (isset($this->translatable) && $this->translatable == false) {
            return false;
        }

        return !empty($this->getTranslatableAttributes());
    }

public function translatable ( ) { if ( isset ( $ this -> translatable ) && $ this -> translatable == false ) { return false ; } return ! empty ( $ this -> getTranslatableAttributes ( ) ) ; }

Check if this model can translate.

@return bool


public function translations()
    {
        return $this->hasMany(Voyager::model('Translation'), 'foreign_key', $this->getKeyName())
            ->where('table_name', $this->getTable())
            ->whereIn('locale', config('voyager.multilingual.locales', []));
    }

public function translations ( ) { return $ this -> hasMany ( Voyager :: model ( 'Translation' ) , 'foreign_key' , $ this -> getKeyName ( ) ) -> where ( 'table_name' , $ this -> getTable ( ) ) -> whereIn ( 'locale' , config ( 'voyager.multilingual.locales' , [ ] ) ) ; }

Load translations relation.

@return mixed


public function getTranslatedAttribute($attribute, $language = null, $fallback = true)
    {
        list($value) = $this->getTranslatedAttributeMeta($attribute, $language, $fallback);

        return $value;
    }

public function getTranslatedAttribute ( $ attribute , $ language = null , $ fallback = true ) { list ( $ value ) = $ this -> getTranslatedAttributeMeta ( $ attribute , $ language , $ fallback ) ; return $ value ; }

Get a single translated attribute.

@param $attribute
@param null $language
@param bool $fallback

@return null


public static function scopeWhereTranslation($query, $field, $operator, $value = null, $locales = null, $default = true)
    {
        if ($locales && !is_array($locales)) {
            $locales = [$locales];
        }
        if (!isset($value)) {
            $value = $operator;
            $operator = '=';
        }

        $self = new static();
        $table = $self->getTable();

        return $query->whereIn($self->getKeyName(), Translation::where('table_name', $table)
            ->where('column_name', $field)
            ->where('value', $operator, $value)
            ->when(!is_null($locales), function ($query) use ($locales) {
                return $query->whereIn('locale', $locales);
            })
            ->pluck('foreign_key')
        )->when($default, function ($query) use ($field, $operator, $value) {
            return $query->orWhere($field, $operator, $value);
        });
    }

public static function scopeWhereTranslation ( $ query , $ field , $ operator , $ value = null , $ locales = null , $ default = true ) { if ( $ locales && ! is_array ( $ locales ) ) { $ locales = [ $ locales ] ; } if ( ! isset ( $ value ) ) { $ value = $ operator ; $ operator = '=' ; } $ self = new static ( ) ; $ table = $ self -> getTable ( ) ; return $ query -> whereIn ( $ self -> getKeyName ( ) , Translation :: where ( 'table_name' , $ table ) -> where ( 'column_name' , $ field ) -> where ( 'value' , $ operator , $ value ) -> when ( ! is_null ( $ locales ) , function ( $ query ) use ( $ locales ) { return $ query -> whereIn ( 'locale' , $ locales ) ; } ) -> pluck ( 'foreign_key' ) ) -> when ( $ default , function ( $ query ) use ( $ field , $ operator , $ value ) { return $ query -> orWhere ( $ field , $ operator , $ value ) ; } ) ; }

Get entries filtered by translated value.

@example  Class::whereTranslation('title', '=', 'zuhause', ['de', 'iu'])
@example  $query->whereTranslation('title', '=', 'zuhause', ['de', 'iu'])

@param string       $field    {required} the field your looking to find a value in.
@param string       $operator {required} value you are looking for or a relation modifier such as LIKE, =, etc.
@param string       $value    {optional} value you are looking for. Only use if you supplied an operator.
@param string|array $locales  {optional} locale(s) you are looking for the field.
@param bool         $default  {optional} if true checks for $value is in default database before checking translations.

@return Builder

Get entries filtered by translated value .


public function saveTranslations($translations)
    {
        foreach ($translations as $field => $locales) {
            foreach ($locales as $locale => $translation) {
                $translation->save();
            }
        }
    }

public function saveTranslations ( $ translations ) { foreach ( $ translations as $ field => $ locales ) { foreach ( $ locales as $ locale => $ translation ) { $ translation -> save ( ) ; } } }

Save translations.

@param object $translations

@return void


public static function describeTable($tableName)
    {
        Type::registerCustomPlatformTypes();

        $table = static::listTableDetails($tableName);

        return collect($table->columns)->map(function ($column) use ($table) {
            $columnArr = Column::toArray($column);

            $columnArr['field'] = $columnArr['name'];
            $columnArr['type'] = $columnArr['type']['name'];

            // Set the indexes and key
            $columnArr['indexes'] = [];
            $columnArr['key'] = null;
            if ($columnArr['indexes'] = $table->getColumnsIndexes($columnArr['name'], true)) {
                // Convert indexes to Array
                foreach ($columnArr['indexes'] as $name => $index) {
                    $columnArr['indexes'][$name] = Index::toArray($index);
                }

                // If there are multiple indexes for the column
                // the Key will be one with highest priority
                $indexType = array_values($columnArr['indexes'])[0]['type'];
                $columnArr['key'] = substr($indexType, 0, 3);
            }

            return $columnArr;
        });
    }

Describes given table.

@param string $tableName

@return \Illuminate\Support\Collection


public function handle(BreadAdded $bread)
    {
        if (config('voyager.bread.add_permission') && file_exists(base_path('routes/web.php'))) {
            // Create permission
            //
            // Permission::generateFor(snake_case($bread->dataType->slug));
            $role = Voyager::model('Role')->where('name', config('voyager.bread.default_role'))->firstOrFail();

            // Get permission for added table
            $permissions = Voyager::model('Permission')->where(['table_name' => $bread->dataType->name])->get()->pluck('id')->all();

            // Assign permission to admin
            $role->permissions()->attach($permissions);
        }
    }

Create Permission for a given BREAD.

@param BreadAdded $event

@return void


protected function addStorageSymlinkAlert()
    {
        if (app('router')->current() !== null) {
            $currentRouteAction = app('router')->current()->getAction();
        } else {
            $currentRouteAction = null;
        }
        $routeName = is_array($currentRouteAction) ? Arr::get($currentRouteAction, 'as') : null;

        if ($routeName != 'voyager.dashboard') {
            return;
        }

        $storage_disk = (!empty(config('voyager.storage.disk'))) ? config('voyager.storage.disk') : 'public';

        if (request()->has('fix-missing-storage-symlink')) {
            if (file_exists(public_path('storage'))) {
                if (@readlink(public_path('storage')) == public_path('storage')) {
                    rename(public_path('storage'), 'storage_old');
                }
            }

            if (!file_exists(public_path('storage'))) {
                $this->fixMissingStorageSymlink();
            }
        } elseif ($storage_disk == 'public') {
            if (!file_exists(public_path('storage')) || @readlink(public_path('storage')) == public_path('storage')) {
                $alert = (new Alert('missing-storage-symlink', 'warning'))
                    ->title(__('voyager::error.symlink_missing_title'))
                    ->text(__('voyager::error.symlink_missing_text'))
                    ->button(__('voyager::error.symlink_missing_button'), '?fix-missing-storage-symlink=1');
                VoyagerFacade::addAlert($alert);
            }
        }
    }

protected function addStorageSymlinkAlert ( ) { if ( app ( 'router' ) -> current ( ) !== null ) { $ currentRouteAction = app ( 'router' ) -> current ( ) -> getAction ( ) ; } else { $ currentRouteAction = null ; } $ routeName = is_array ( $ currentRouteAction ) ? Arr :: get ( $ currentRouteAction , 'as' ) : null ; if ( $ routeName != 'voyager.dashboard' ) { return ; } $ storage_disk = ( ! empty ( config ( 'voyager.storage.disk' ) ) ) ? config ( 'voyager.storage.disk' ) : 'public' ; if ( request ( ) -> has ( 'fix-missing-storage-symlink' ) ) { if ( file_exists ( public_path ( 'storage' ) ) ) { if ( @ readlink ( public_path ( 'storage' ) ) == public_path ( 'storage' ) ) { rename ( public_path ( 'storage' ) , 'storage_old' ) ; } } if ( ! file_exists ( public_path ( 'storage' ) ) ) { $ this -> fixMissingStorageSymlink ( ) ; } } elseif ( $ storage_disk == 'public' ) { if ( ! file_exists ( public_path ( 'storage' ) ) || @ readlink ( public_path ( 'storage' ) ) == public_path ( 'storage' ) ) { $ alert = ( new Alert ( 'missing-storage-symlink' , 'warning' ) ) -> title ( __ ( 'voyager::error.symlink_missing_title' ) ) -> text ( __ ( 'voyager::error.symlink_missing_text' ) ) -> button ( __ ( 'voyager::error.symlink_missing_button' ) , '?fix-missing-storage-symlink=1' ) ; VoyagerFacade :: addAlert ( $ alert ) ; } } }


private function registerConsoleCommands()
    {
        $this->commands(Commands\InstallCommand::class);
        $this->commands(Commands\ControllersCommand::class);
        $this->commands(Commands\AdminCommand::class);
    }

private function registerConsoleCommands ( ) { $ this -> commands ( Commands \ InstallCommand :: class ) ; $ this -> commands ( Commands \ ControllersCommand :: class ) ; $ this -> commands ( Commands \ AdminCommand :: class ) ; }

Register the commands accessible from the Console.

Register the commands accessible from the Console .


protected function cleanup($dataType, $data)
    {
        // Delete Translations, if present
        if (is_bread_translatable($data)) {
            $data->deleteAttributeTranslations($data->getTranslatableAttributes());
        }

        // Delete Images
        $this->deleteBreadImages($data, $dataType->deleteRows->where('type', 'image'));

        // Delete Files
        foreach ($dataType->deleteRows->where('type', 'file') as $row) {
            if (isset($data->{$row->field})) {
                foreach (json_decode($data->{$row->field}) as $file) {
                    $this->deleteFileIfExists($file->download_link);
                }
            }
        }

        // Delete media-picker files
        $dataType->rows->where('type', 'media_picker')->where('details.delete_files', true)->each(function ($row) use ($data) {
            $content = $data->{$row->field};
            if (isset($content)) {
                if (!is_array($content)) {
                    $content = json_decode($content);
                }
                if (is_array($content)) {
                    foreach ($content as $file) {
                        $this->deleteFileIfExists($file);
                    }
                } else {
                    $this->deleteFileIfExists($content);
                }
            }
        });
    }

protected
function
cleanup
(
$
dataType
,
$
data
)
{
// Delete Translations, if present
if
(
is_bread_translatable
(
$
data
)
)
{
$
data
->
deleteAttributeTranslations
(
$
data
->
getTranslatableAttributes
(
)
)
;
}
// Delete Images
$
this
->
deleteBreadImages
(
$
data
,
$
dataType
->
deleteRows
->
where
(
'type'
,
'image'
)
)
;
// Delete Files
foreach
(
$
dataType
->
deleteRows
->
where
(
'type'
,
'file'
)
as
$
row
)
{
if
(
isset
(
$
data
->
{
$
row
->
field
}
)
)
{
foreach
(
json_decode
(
$
data
->
{
$
row
->
field
}
)
as
$
file
)
{
$
this
->
deleteFileIfExists
(
$
file
->
download_link
)
;
}
}
}
// Delete media-picker files
$
dataType
->
rows
->
where
(
'type'
,
'media_picker'
)
->
where
(
'details.delete_files'
,
true
)
->
each
(
function
(
$
row
)
use
(
$
data
)
{
$
content
=
$
data
->
{
$
row
->
field
}
;
if
(
isset
(
$
content
)
)
{
if
(
!
is_array
(
$
content
)
)
{
$
content
=
json_decode
(
$
content
)
;
}
if
(
is_array
(
$
content
)
)
{
foreach
(
$
content
as
$
file
)
{
$
this
->
deleteFileIfExists
(
$
file
)
;
}
}
else
{
$
this
->
deleteFileIfExists
(
$
content
)
;
}
}
}
)
;
}

Remove translations, images and files related to a BREAD item.

@param \Illuminate\Database\Eloquent\Model $dataType
@param \Illuminate\Database\Eloquent\Model $data

@return void

Remove translations images and files related to a BREAD item .


public function deleteBreadImages($data, $rows)
    {
        foreach ($rows as $row) {
            if ($data->{$row->field} != config('voyager.user.default_avatar')) {
                $this->deleteFileIfExists($data->{$row->field});
            }

            if (isset($row->details->thumbnails)) {
                foreach ($row->details->thumbnails as $thumbnail) {
                    $ext = explode('.', $data->{$row->field});
                    $extension = '.'.$ext[count($ext) - 1];

                    $path = str_replace($extension, '', $data->{$row->field});

                    $thumb_name = $thumbnail->name;

                    $this->deleteFileIfExists($path.'-'.$thumb_name.$extension);
                }
            }
        }

        if ($rows->count() > 0) {
            event(new BreadImagesDeleted($data, $rows));
        }
    }

public function deleteBreadImages ( $ data , $ rows ) { foreach ( $ rows as $ row ) { if ( $ data -> { $ row -> field } != config ( 'voyager.user.default_avatar' ) ) { $ this -> deleteFileIfExists ( $ data -> { $ row -> field } ) ; } if ( isset ( $ row -> details -> thumbnails ) ) { foreach ( $ row -> details -> thumbnails as $ thumbnail ) { $ ext = explode ( '.' , $ data -> { $ row -> field } ) ; $ extension = '.' . $ ext [ count ( $ ext ) - 1 ] ; $ path = str_replace ( $ extension , '' , $ data -> { $ row -> field } ) ; $ thumb_name = $ thumbnail -> name ; $ this -> deleteFileIfExists ( $ path . '-' . $ thumb_name . $ extension ) ; } } } if ( $ rows -> count ( ) > 0 ) { event ( new BreadImagesDeleted ( $ data , $ rows ) ) ; } }

Delete all images related to a BREAD item.

@param \Illuminate\Database\Eloquent\Model $data
@param \Illuminate\Database\Eloquent\Model $rows

@return void

Delete all images related to a BREAD item .


public function order(Request $request)
    {
        $slug = $this->getSlug($request);

        $dataType = Voyager::model('DataType')->where('slug', '=', $slug)->first();

        // Check permission
        $this->authorize('edit', app($dataType->model_name));

        if (!isset($dataType->order_column) || !isset($dataType->order_display_column)) {
            return redirect()
            ->route("voyager.{$dataType->slug}.index")
            ->with([
                'message'    => __('voyager::bread.ordering_not_set'),
                'alert-type' => 'error',
            ]);
        }

        $model = app($dataType->model_name);
        if ($model && in_array(SoftDeletes::class, class_uses($model))) {
            $model = $model->withTrashed();
        }
        $results = $model->orderBy($dataType->order_column, $dataType->order_direction)->get();

        $display_column = $dataType->order_display_column;

        $dataRow = Voyager::model('DataRow')->whereDataTypeId($dataType->id)->whereField($display_column)->first();

        $view = 'voyager::bread.order';

        if (view()->exists("voyager::$slug.order")) {
            $view = "voyager::$slug.order";
        }

        return Voyager::view($view, compact(
            'dataType',
            'display_column',
            'dataRow',
            'results'
        ));
    }

public
function
order
(
Request
$
request
)
{
$
slug
=
$
this
->
getSlug
(
$
request
)
;
$
dataType
=
Voyager
::
model
(
'DataType'
)
->
where
(
'slug'
,
'='
,
$
slug
)
->
first
(
)
;
// Check permission
$
this
->
authorize
(
'edit'
,
app
(
$
dataType
->
model_name
)
)
;
if
(
!
isset
(
$
dataType
->
order_column
)
||
!
isset
(
$
dataType
->
order_display_column
)
)
{
return
redirect
(
)
->
route
(
"voyager.{$dataType->slug}.index"
)
->
with
(
[
'message'
=>
__
(
'voyager::bread.ordering_not_set'
)
,
'alert-type'
=>
'error'
,
]
)
;
}
$
model
=
app
(
$
dataType
->
model_name
)
;
if
(
$
model
&&
in_array
(
SoftDeletes
::
class
,
class_uses
(
$
model
)
)
)
{
$
model
=
$
model
->
withTrashed
(
)
;
}
$
results
=
$
model
->
orderBy
(
$
dataType
->
order_column
,
$
dataType
->
order_direction
)
->
get
(
)
;
$
display_column
=
$
dataType
->
order_display_column
;
$
dataRow
=
Voyager
::
model
(
'DataRow'
)
->
whereDataTypeId
(
$
dataType
->
id
)
->
whereField
(
$
display_column
)
->
first
(
)
;
$
view
=
'voyager::bread.order'
;
if
(
view
(
)
->
exists
(
"voyager::$slug.order"
)
)
{
$
view
=
"voyager::$slug.order"
;
}
return
Voyager
::
view
(
$
view
,
compact
(
'dataType'
,
'display_column'
,
'dataRow'
,
'results'
)
)
;
}

Order BREAD items.

@param string $table

@return \Illuminate\Contracts\View\Factory|\Illuminate\View\View


public function relation(Request $request)
    {
        $slug = $this->getSlug($request);
        $page = $request->input('page');
        $on_page = 50;
        $search = $request->input('search', false);
        $dataType = Voyager::model('DataType')->where('slug', '=', $slug)->first();

        foreach ($dataType->editRows as $key => $row) {
            if ($row->field === $request->input('type')) {
                $options = $row->details;
                $skip = $on_page * ($page - 1);

                // If search query, use LIKE to filter results depending on field label
                if ($search) {
                    $total_count = app($options->model)->where($options->label, 'LIKE', '%'.$search.'%')->count();
                    $relationshipOptions = app($options->model)->take($on_page)->skip($skip)
                        ->where($options->label, 'LIKE', '%'.$search.'%')
                        ->get();
                } else {
                    $total_count = app($options->model)->count();
                    $relationshipOptions = app($options->model)->take($on_page)->skip($skip)->get();
                }

                $results = [];
                foreach ($relationshipOptions as $relationshipOption) {
                    $results[] = [
                        'id'   => $relationshipOption->{$options->key},
                        'text' => $relationshipOption->{$options->label},
                    ];
                }

                return response()->json([
                    'results'    => $results,
                    'pagination' => [
                        'more' => ($total_count > ($skip + $on_page)),
                    ],
                ]);
            }
        }

        // No result found, return empty array
        return response()->json([], 404);
    }

Get BREAD relations data.

@param Request $request

@return mixed


protected function resolveRelations($dataTypeContent, DataType $dataType)
    {
        // In case of using server-side pagination, we need to work on the Collection (BROWSE)
        if ($dataTypeContent instanceof LengthAwarePaginator) {
            $dataTypeCollection = $dataTypeContent->getCollection();
        }
        // If it's a model just make the changes directly on it (READ / EDIT)
        elseif ($dataTypeContent instanceof Model) {
            return $dataTypeContent;
        }
        // Or we assume it's a Collection
        else {
            $dataTypeCollection = $dataTypeContent;
        }

        return $dataTypeContent instanceof LengthAwarePaginator ? $dataTypeContent->setCollection($dataTypeCollection) : $dataTypeCollection;
    }

Replace relationships' keys for labels and create READ links if a slug is provided.

@param  $dataTypeContent     Can be either an eloquent Model, Collection or LengthAwarePaginator instance.
@param DataType $dataType

@return $dataTypeContent

Replace relationships keys for labels and create READ links if a slug is provided .


protected function addSoftDelete(&$stub)
    {
        $traitIncl = $trait = '';

        if ($this->option('softdelete')) {
            $traitIncl = 'use Illuminate\Database\Eloquent\SoftDeletes;';
            $trait = 'use SoftDeletes;';
        }

        $stub = str_replace('//DummySDTraitInclude', $traitIncl, $stub);
        $stub = str_replace('//DummySDTrait', $trait, $stub);

        return $this;
    }

Add SoftDelete to the given stub.

@param string $stub

@return $this


public function validateBread($request, $data, $name = null, $id = null)
    {
        $rules = [];
        $messages = [];
        $customAttributes = [];
        $is_update = $name && $id;

        $fieldsWithValidationRules = $this->getFieldsWithValidationRules($data);

        foreach ($fieldsWithValidationRules as $field) {
            $fieldRules = $field->details->validation->rule;
            $fieldName = $field->field;

            // Show the field's display name on the error message
            if (!empty($field->display_name)) {
                $customAttributes[$fieldName] = $field->display_name;
            }

            // Get the rules for the current field whatever the format it is in
            $rules[$fieldName] = is_array($fieldRules) ? $fieldRules : explode('|', $fieldRules);

            if ($id && property_exists($field->details->validation, 'edit')) {
                $action_rules = $field->details->validation->edit->rule;
                $rules[$fieldName] = array_merge($rules[$fieldName], (is_array($action_rules) ? $action_rules : explode('|', $action_rules)));
            } elseif (!$id && property_exists($field->details->validation, 'add')) {
                $action_rules = $field->details->validation->add->rule;
                $rules[$fieldName] = array_merge($rules[$fieldName], (is_array($action_rules) ? $action_rules : explode('|', $action_rules)));
            }
            // Fix Unique validation rule on Edit Mode
            if ($is_update) {
                foreach ($rules[$fieldName] as &$fieldRule) {
                    if (strpos(strtoupper($fieldRule), 'UNIQUE') !== false) {
                        $fieldRule = \Illuminate\Validation\Rule::unique($name)->ignore($id);
                    }
                }
            }

            // Set custom validation messages if any
            if (!empty($field->details->validation->messages)) {
                foreach ($field->details->validation->messages as $key => $msg) {
                    $messages["{$fieldName}.{$key}"] = $msg;
                }
            }
        }

        return Validator::make($request, $rules, $messages, $customAttributes);
    }

Validates bread POST request.

@param \Illuminate\Http\Request $request The Request
@param array                    $data    Field data
@param string                   $slug    Slug
@param int                      $id      Id of the record to update

@return mixed


protected function getFieldsWithValidationRules($fieldsConfig)
    {
        return $fieldsConfig->filter(function ($value) {
            if (empty($value->details)) {
                return false;
            }

            return !empty($value->details->validation->rule);
        });
    }

protected function getFieldsWithValidationRules ( $ fieldsConfig ) { return $ fieldsConfig -> filter ( function ( $ value ) { if ( empty ( $ value -> details ) ) { return false ; } return ! empty ( $ value -> details -> validation -> rule ) ; } ) ; }

Get fields having validation rules in proper format.

@param array $fieldsConfig

@return \Illuminate\Support\Collection

Get fields having validation rules in proper format .


public function verifyIdToken($idToken, $audience = null)
  {
    if (empty($idToken)) {
      throw new LogicException('id_token cannot be null');
    }

    // set phpseclib constants if applicable
    $this->setPhpsecConstants();

    // Check signature
    $certs = $this->getFederatedSignOnCerts();
    foreach ($certs as $cert) {
      $bigIntClass = $this->getBigIntClass();
      $rsaClass = $this->getRsaClass();
      $modulus = new $bigIntClass($this->jwt->urlsafeB64Decode($cert['n']), 256);
      $exponent = new $bigIntClass($this->jwt->urlsafeB64Decode($cert['e']), 256);

      $rsa = new $rsaClass();
      $rsa->loadKey(array('n' => $modulus, 'e' => $exponent));

      try {
        $payload = $this->jwt->decode(
            $idToken,
            $rsa->getPublicKey(),
            array('RS256')
        );

        if (property_exists($payload, 'aud')) {
          if ($audience && $payload->aud != $audience) {
            return false;
          }
        }

        // support HTTP and HTTPS issuers
        // @see https://developers.google.com/identity/sign-in/web/backend-auth
        $issuers = array(self::OAUTH2_ISSUER, self::OAUTH2_ISSUER_HTTPS);
        if (!isset($payload->iss) || !in_array($payload->iss, $issuers)) {
          return false;
        }

        return (array) $payload;
      } catch (ExpiredException $e) {
        return false;
      } catch (ExpiredExceptionV3 $e) {
        return false;
      } catch (SignatureInvalidException $e) {
        // continue
      } catch (DomainException $e) {
        // continue
      }
    }

    return false;
  }

Verifies an id token and returns the authenticated apiLoginTicket.
Throws an exception if the id token is not valid.
The audience parameter can be used to control which id tokens are
accepted.  By default, the id token must have been issued to this OAuth2 client.

@param $audience
@return array the token payload, if successful

Verifies an id token and returns the authenticated apiLoginTicket . Throws an exception if the id token is not valid . The audience parameter can be used to control which id tokens are accepted . By default the id token must have been issued to this OAuth2 client .


private function retrieveCertsFromLocation($url)
  {
    // If we're retrieving a local file, just grab it.
    if (0 !== strpos($url, 'http')) {
      if (!$file = file_get_contents($url)) {
        throw new Google_Exception(
            "Failed to retrieve verification certificates: '" .
            $url . "'."
        );
      }

      return json_decode($file, true);
    }

    $response = $this->http->get($url);

    if ($response->getStatusCode() == 200) {
      return json_decode((string) $response->getBody(), true);
    }
    throw new Google_Exception(
        sprintf(
            'Failed to retrieve verification certificates: "%s".',
            $response->getBody()->getContents()
        ),
        $response->getStatusCode()
    );
  }

Retrieve and cache a certificates file.

@param $url string location
@throws Google_Exception
@return array certificates

Retrieve and cache a certificates file .


private function getFederatedSignOnCerts()
  {
    $certs = null;
    if ($cache = $this->getCache()) {
      $cacheItem = $cache->getItem('federated_signon_certs_v3');
      $certs = $cacheItem->get();
    }

    if (!$certs) {
      $certs = $this->retrieveCertsFromLocation(
          self::FEDERATED_SIGNON_CERT_URL
      );

      if ($cache) {
        $cacheItem->expiresAt(new DateTime('+1 hour'));
        $cacheItem->set($certs);
        $cache->save($cacheItem);
      }
    }

    if (!isset($certs['keys'])) {
      throw new InvalidArgumentException(
          'federated sign-on certs expects "keys" to be set'
      );
    }

    return $certs['keys'];
  }


private function setPhpsecConstants()
  {
    if (filter_var(getenv('GAE_VM'), FILTER_VALIDATE_BOOLEAN)) {
      if (!defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) {
        define('MATH_BIGINTEGER_OPENSSL_ENABLED', true);
      }
      if (!defined('CRYPT_RSA_MODE')) {
        define('CRYPT_RSA_MODE', constant($this->getOpenSslConstant()));
      }
    }
  }

private function setPhpsecConstants ( ) { if ( filter_var ( getenv ( 'GAE_VM' ) , FILTER_VALIDATE_BOOLEAN ) ) { if ( ! defined ( 'MATH_BIGINTEGER_OPENSSL_ENABLED' ) ) { define ( 'MATH_BIGINTEGER_OPENSSL_ENABLED' , true ) ; } if ( ! defined ( 'CRYPT_RSA_MODE' ) ) { define ( 'CRYPT_RSA_MODE' , constant ( $ this -> getOpenSslConstant ( ) ) ) ; } } }

phpseclib calls "phpinfo" by default, which requires special
whitelisting in the AppEngine VM environment. This function
sets constants to bypass the need for phpseclib to check phpinfo

@see phpseclib/Math/BigInteger
@see https://github.com/GoogleCloudPlatform/getting-started-php/issues/85

phpseclib calls phpinfo by default which requires special whitelisting in the AppEngine VM environment . This function sets constants to bypass the need for phpseclib to check phpinfo


public function fetchAccessTokenWithAuthCode($code)
  {
    if (strlen($code) == 0) {
      throw new InvalidArgumentException("Invalid code");
    }

    $auth = $this->getOAuth2Service();
    $auth->setCode($code);
    $auth->setRedirectUri($this->getRedirectUri());

    $httpHandler = HttpHandlerFactory::build($this->getHttpClient());
    $creds = $auth->fetchAuthToken($httpHandler);
    if ($creds && isset($creds['access_token'])) {
      $creds['created'] = time();
      $this->setAccessToken($creds);
    }

    return $creds;
  }

public
function
fetchAccessTokenWithAuthCode
(
$
code
)
{
if
(
strlen
(
$
code
)
==
0
)
{
throw
new
InvalidArgumentException
(
"Invalid code"
)
;
}
$
auth
=
$
this
->
getOAuth2Service
(
)
;
$
auth
->
setCode
(
$
code
)
;
$
auth
->
setRedirectUri
(
$
this
->
getRedirectUri
(
)
)
;
$
httpHandler
=
HttpHandlerFactory
::
build
(
$
this
->
getHttpClient
(
)
)
;
$
creds
=
$
auth
->
fetchAuthToken
(
$
httpHandler
)
;
if
(
$
creds
&&
isset
(
$
creds
[
'access_token'
]
)
)
{
$
creds
[
'created'
]
=
time
(
)
;
$
this
->
setAccessToken
(
$
creds
)
;
}
return
$
creds
;
}

Attempt to exchange a code for an valid authentication token.
Helper wrapped around the OAuth 2.0 implementation.

@param $code string code from accounts.google.com
@return array access token

Attempt to exchange a code for an valid authentication token . Helper wrapped around the OAuth 2 . 0 implementation .


public function fetchAccessTokenWithAssertion(ClientInterface $authHttp = null)
  {
    if (!$this->isUsingApplicationDefaultCredentials()) {
      throw new DomainException(
          'set the JSON service account credentials using'
          . ' Google_Client::setAuthConfig or set the path to your JSON file'
          . ' with the "GOOGLE_APPLICATION_CREDENTIALS" environment variable'
          . ' and call Google_Client::useApplicationDefaultCredentials to'
          . ' refresh a token with assertion.'
      );
    }

    $this->getLogger()->log(
        'info',
        'OAuth2 access token refresh with Signed JWT assertion grants.'
    );

    $credentials = $this->createApplicationDefaultCredentials();

    $httpHandler = HttpHandlerFactory::build($authHttp);
    $creds = $credentials->fetchAuthToken($httpHandler);
    if ($creds && isset($creds['access_token'])) {
      $creds['created'] = time();
      $this->setAccessToken($creds);
    }

    return $creds;
  }

Fetches a fresh access token with a given assertion token.
@param ClientInterface $authHttp optional.
@return array access token

Fetches a fresh access token with a given assertion token .


public function fetchAccessTokenWithRefreshToken($refreshToken = null)
  {
    if (null === $refreshToken) {
      if (!isset($this->token['refresh_token'])) {
        throw new LogicException(
            'refresh token must be passed in or set as part of setAccessToken'
        );
      }
      $refreshToken = $this->token['refresh_token'];
    }
    $this->getLogger()->info('OAuth2 access token refresh');
    $auth = $this->getOAuth2Service();
    $auth->setRefreshToken($refreshToken);

    $httpHandler = HttpHandlerFactory::build($this->getHttpClient());
    $creds = $auth->fetchAuthToken($httpHandler);
    if ($creds && isset($creds['access_token'])) {
      $creds['created'] = time();
      if (!isset($creds['refresh_token'])) {
        $creds['refresh_token'] = $refreshToken;
      }
      $this->setAccessToken($creds);
    }

    return $creds;
  }

Fetches a fresh OAuth 2.0 access token with the given refresh token.
@param string $refreshToken
@return array access token

Fetches a fresh OAuth 2 . 0 access token with the given refresh token .


public function authorize(ClientInterface $http = null)
  {
    $credentials = null;
    $token = null;
    $scopes = null;
    if (null === $http) {
      $http = $this->getHttpClient();
    }

    // These conditionals represent the decision tree for authentication
    //   1.  Check for Application Default Credentials
    //   2.  Check for API Key
    //   3a. Check for an Access Token
    //   3b. If access token exists but is expired, try to refresh it
    if ($this->isUsingApplicationDefaultCredentials()) {
      $credentials = $this->createApplicationDefaultCredentials();
    } elseif ($token = $this->getAccessToken()) {
      $scopes = $this->prepareScopes();
      // add refresh subscriber to request a new token
      if (isset($token['refresh_token']) && $this->isAccessTokenExpired()) {
        $credentials = $this->createUserRefreshCredentials(
            $scopes,
            $token['refresh_token']
        );
      }
    }

    $authHandler = $this->getAuthHandler();

    if ($credentials) {
      $callback = $this->config['token_callback'];
      $http = $authHandler->attachCredentials($http, $credentials, $callback);
    } elseif ($token) {
      $http = $authHandler->attachToken($http, $token, (array) $scopes);
    } elseif ($key = $this->config['developer_key']) {
      $http = $authHandler->attachKey($http, $key);
    }

    return $http;
  }

Adds auth listeners to the HTTP client based on the credentials
set in the Google API Client object

@param GuzzleHttp\ClientInterface $http the http client object.
@return GuzzleHttp\ClientInterface the http client object


public function isAccessTokenExpired()
  {
    if (!$this->token) {
      return true;
    }

    $created = 0;
    if (isset($this->token['created'])) {
      $created = $this->token['created'];
    } elseif (isset($this->token['id_token'])) {
      // check the ID token for "iat"
      // signature verification is not required here, as we are just
      // using this for convenience to save a round trip request
      // to the Google API server
      $idToken = $this->token['id_token'];
      if (substr_count($idToken, '.') == 2) {
        $parts = explode('.', $idToken);
        $payload = json_decode(base64_decode($parts[1]), true);
        if ($payload && isset($payload['iat'])) {
          $created = $payload['iat'];
        }
      }
    }

    // If the token is set to expire in the next 30 seconds.
    return ($created + ($this->token['expires_in'] - 30)) < time();
  }

Returns if the access_token is expired.
@return bool Returns True if the access_token is expired.

Returns if the access_token is expired .


public function verifyIdToken($idToken = null)
  {
    $tokenVerifier = new Google_AccessToken_Verify(
        $this->getHttpClient(),
        $this->getCache(),
        $this->config['jwt']
    );

    if (null === $idToken) {
      $token = $this->getAccessToken();
      if (!isset($token['id_token'])) {
        throw new LogicException(
            'id_token must be passed in or set as part of setAccessToken'
        );
      }
      $idToken = $token['id_token'];
    }

    return $tokenVerifier->verifyIdToken(
        $idToken,
        $this->getClientId()
    );
  }

Verify an id_token. This method will verify the current id_token, if one
isn't provided.

@throws LogicException If no token was provided and no token was set using `setAccessToken`.
@throws UnexpectedValueException If the token is not a valid JWT.
@param string|null $idToken The token (id_token) that should be verified.
@return array|false Returns the token payload as an array if the verification was
successful, false otherwise.

Verify an id_token . This method will verify the current id_token if one isn t provided .


public function addScope($scope_or_scopes)
  {
    if (is_string($scope_or_scopes) && !in_array($scope_or_scopes, $this->requestedScopes)) {
      $this->requestedScopes[] = $scope_or_scopes;
    } else if (is_array($scope_or_scopes)) {
      foreach ($scope_or_scopes as $scope) {
        $this->addScope($scope);
      }
    }
  }

public function addScope ( $ scope_or_scopes ) { if ( is_string ( $ scope_or_scopes ) && ! in_array ( $ scope_or_scopes , $ this -> requestedScopes ) ) { $ this -> requestedScopes [ ] = $ scope_or_scopes ; } else if ( is_array ( $ scope_or_scopes ) ) { foreach ( $ scope_or_scopes as $ scope ) { $ this -> addScope ( $ scope ) ; } } }

This functions adds a scope to be requested as part of the OAuth2.0 flow.
Will append any scopes not previously requested to the scope parameter.
A single string will be treated as a scope to request. An array of strings
will each be appended.
@param $scope_or_scopes string|array e.g. "profile"

This functions adds a scope to be requested as part of the OAuth2 . 0 flow . Will append any scopes not previously requested to the scope parameter . A single string will be treated as a scope to request . An array of strings will each be appended .


public function execute(RequestInterface $request, $expectedClass = null)
  {
    $request = $request->withHeader(
        'User-Agent',
        $this->config['application_name']
        . " " . self::USER_AGENT_SUFFIX
        . $this->getLibraryVersion()
    );

    // call the authorize method
    // this is where most of the grunt work is done
    $http = $this->authorize();

    return Google_Http_REST::execute(
        $http,
        $request,
        $expectedClass,
        $this->config['retry'],
        $this->config['retry_map']
    );
  }

Helper method to execute deferred HTTP requests.

@param $request Psr\Http\Message\RequestInterface|Google_Http_Batch
@throws Google_Exception
@return object of the type of the expected class or Psr\Http\Message\ResponseInterface.

Helper method to execute deferred HTTP requests .


public function setAuthConfig($config)
  {
    if (is_string($config)) {
      if (!file_exists($config)) {
        throw new InvalidArgumentException(sprintf('file "%s" does not exist', $config));
      }

      $json = file_get_contents($config);

      if (!$config = json_decode($json, true)) {
        throw new LogicException('invalid json for auth config');
      }
    }

    $key = isset($config['installed']) ? 'installed' : 'web';
    if (isset($config['type']) && $config['type'] == 'service_account') {
      // application default credentials
      $this->useApplicationDefaultCredentials();

      // set the information from the config
      $this->setClientId($config['client_id']);
      $this->config['client_email'] = $config['client_email'];
      $this->config['signing_key'] = $config['private_key'];
      $this->config['signing_algorithm'] = 'HS256';
    } elseif (isset($config[$key])) {
      // old-style
      $this->setClientId($config[$key]['client_id']);
      $this->setClientSecret($config[$key]['client_secret']);
      if (isset($config[$key]['redirect_uris'])) {
        $this->setRedirectUri($config[$key]['redirect_uris'][0]);
      }
    } else {
      // new-style
      $this->setClientId($config['client_id']);
      $this->setClientSecret($config['client_secret']);
      if (isset($config['redirect_uris'])) {
        $this->setRedirectUri($config['redirect_uris'][0]);
      }
    }
  }

public
function
setAuthConfig
(
$
config
)
{
if
(
is_string
(
$
config
)
)
{
if
(
!
file_exists
(
$
config
)
)
{
throw
new
InvalidArgumentException
(
sprintf
(
'file "%s" does not exist'
,
$
config
)
)
;
}
$
json
=
file_get_contents
(
$
config
)
;
if
(
!
$
config
=
json_decode
(
$
json
,
true
)
)
{
throw
new
LogicException
(
'invalid json for auth config'
)
;
}
}
$
key
=
isset
(
$
config
[
'installed'
]
)
'installed'
:
'web'
;
if
(
isset
(
$
config
[
'type'
]
)
&&
$
config
[
'type'
]
==
'service_account'
)
{
// application default credentials
$
this
->
useApplicationDefaultCredentials
(
)
;
// set the information from the config
$
this
->
setClientId
(
$
config
[
'client_id'
]
)
;
$
this
->
config
[
'client_email'
]
=
$
config
[
'client_email'
]
;
$
this
->
config
[
'signing_key'
]
=
$
config
[
'private_key'
]
;
$
this
->
config
[
'signing_algorithm'
]
=
'HS256'
;
}
elseif
(
isset
(
$
config
[
$
key
]
)
)
{
// old-style
$
this
->
setClientId
(
$
config
[
$
key
]
[
'client_id'
]
)
;
$
this
->
setClientSecret
(
$
config
[
$
key
]
[
'client_secret'
]
)
;
if
(
isset
(
$
config
[
$
key
]
[
'redirect_uris'
]
)
)
{
$
this
->
setRedirectUri
(
$
config
[
$
key
]
[
'redirect_uris'
]
[
0
]
)
;
}
}
else
{
// new-style
$
this
->
setClientId
(
$
config
[
'client_id'
]
)
;
$
this
->
setClientSecret
(
$
config
[
'client_secret'
]
)
;
if
(
isset
(
$
config
[
'redirect_uris'
]
)
)
{
$
this
->
setRedirectUri
(
$
config
[
'redirect_uris'
]
[
0
]
)
;
}
}
}

Set the auth config from new or deprecated JSON config.
This structure should match the file downloaded from
the "Download JSON" button on in the Google Developer
Console.
@param string|array $config the configuration json
@throws Google_Exception

Set the auth config from new or deprecated JSON config . This structure should match the file downloaded from the Download JSON button on in the Google Developer Console .


protected function createOAuth2Service()
  {
    $auth = new OAuth2(
        [
          'clientId'          => $this->getClientId(),
          'clientSecret'      => $this->getClientSecret(),
          'authorizationUri'   => self::OAUTH2_AUTH_URL,
          'tokenCredentialUri' => self::OAUTH2_TOKEN_URI,
          'redirectUri'       => $this->getRedirectUri(),
          'issuer'            => $this->config['client_id'],
          'signingKey'        => $this->config['signing_key'],
          'signingAlgorithm'  => $this->config['signing_algorithm'],
        ]
    );

    return $auth;
  }

protected function createOAuth2Service ( ) { $ auth = new OAuth2 ( [ 'clientId' => $ this -> getClientId ( ) , 'clientSecret' => $ this -> getClientSecret ( ) , 'authorizationUri' => self :: OAUTH2_AUTH_URL , 'tokenCredentialUri' => self :: OAUTH2_TOKEN_URI , 'redirectUri' => $ this -> getRedirectUri ( ) , 'issuer' => $ this -> config [ 'client_id' ] , 'signingKey' => $ this -> config [ 'signing_key' ] , 'signingAlgorithm' => $ this -> config [ 'signing_algorithm' ] , ] ) ; return $ auth ; }


public function allowedRetries($code, $errors = array())
  {
    if (isset($this->retryMap[$code])) {
      return $this->retryMap[$code];
    }

    if (
        !empty($errors) &&
        isset($errors[0]['reason'], $this->retryMap[$errors[0]['reason']])
    ) {
      return $this->retryMap[$errors[0]['reason']];
    }

    return 0;
  }

public function allowedRetries ( $ code , $ errors = array ( ) ) { if ( isset ( $ this -> retryMap [ $ code ] ) ) { return $ this -> retryMap [ $ code ] ; } if ( ! empty ( $ errors ) && isset ( $ errors [ 0 ] [ 'reason' ] , $ this -> retryMap [ $ errors [ 0 ] [ 'reason' ] ] ) ) { return $ this -> retryMap [ $ errors [ 0 ] [ 'reason' ] ] ; } return 0 ; }

Gets the number of times the associated task can be retried.

NOTE: -1 is returned if the task can be retried indefinitely

@return integer

Gets the number of times the associated task can be retried .


public function nextChunk($chunk = false)
  {
    $resumeUri = $this->getResumeUri();

    if (false == $chunk) {
      $chunk = substr($this->data, $this->progress, $this->chunkSize);
    }

    $lastBytePos = $this->progress + strlen($chunk) - 1;
    $headers = array(
      'content-range' => "bytes $this->progress-$lastBytePos/$this->size",
      'content-length' => strlen($chunk),
      'expect' => '',
    );

    $request = new Request(
        'PUT',
        $resumeUri,
        $headers,
        Psr7\stream_for($chunk)
    );

    return $this->makePutRequest($request);
  }

Send the next part of the file to upload.
@param [$chunk] the next set of bytes to send. If false will used $data passed
at construct time.

Send the next part of the file to upload .


private function parseHttpResponse($respData, $headerSize)
  {
    // check proxy header
    foreach (self::$CONNECTION_ESTABLISHED_HEADERS as $established_header) {
      if (stripos($respData, $established_header) !== false) {
        // existed, remove it
        $respData = str_ireplace($established_header, '', $respData);
        // Subtract the proxy header size unless the cURL bug prior to 7.30.0
        // is present which prevented the proxy header size from being taken into
        // account.
        // @TODO look into this
        // if (!$this->needsQuirk()) {
        //   $headerSize -= strlen($established_header);
        // }
        break;
      }
    }

    if ($headerSize) {
      $responseBody = substr($respData, $headerSize);
      $responseHeaders = substr($respData, 0, $headerSize);
    } else {
      $responseSegments = explode("\r\n\r\n", $respData, 2);
      $responseHeaders = $responseSegments[0];
      $responseBody = isset($responseSegments[1]) ? $responseSegments[1] :
                                                    null;
    }

    $responseHeaders = $this->parseRawHeaders($responseHeaders);

    return array($responseHeaders, $responseBody);
  }

Used by the IO lib and also the batch processing.

@param $respData
@param $headerSize
@return array

Used by the IO lib and also the batch processing .


private function getDataType($data)
  {
    if (is_array($data)) {
      reset($data);
      if (key($data) !== 0) {
        return self::TYPE_MAP;
      }
      return self::TYPE_LIST;
    }
    return self::TYPE_SCALAR;
  }

private function getDataType ( $ data ) { if ( is_array ( $ data ) ) { reset ( $ data ) ; if ( key ( $ data ) !== 0 ) { return self :: TYPE_MAP ; } return self :: TYPE_LIST ; } return self :: TYPE_SCALAR ; }


private function combineList(
      $vars,
      $sep,
      $parameters,
      $combine,
      $reserved,
      $tag_empty,
      $combine_on_empty
  ) {
    $ret = array();
    foreach ($vars as $var) {
      $response = $this->combine(
          $var,
          $parameters,
          $sep,
          $combine,
          $reserved,
          $tag_empty,
          $combine_on_empty
      );
      if ($response === false) {
        continue;
      }
      $ret[] = $response;
    }
    return implode($sep, $ret);
  }

private function combineList ( $ vars , $ sep , $ parameters , $ combine , $ reserved , $ tag_empty , $ combine_on_empty ) { $ ret = array ( ) ; foreach ( $ vars as $ var ) { $ response = $ this -> combine ( $ var , $ parameters , $ sep , $ combine , $ reserved , $ tag_empty , $ combine_on_empty ) ; if ( $ response === false ) { continue ; } $ ret [ ] = $ response ; } return implode ( $ sep , $ ret ) ; }

Utility function that merges multiple combine calls
for multi-key templates.

Utility function that merges multiple combine calls for multi - key templates .


private function getValue($value, $length)
  {
    if ($length) {
      $value = substr($value, 0, $length);
    }
    $value = rawurlencode($value);
    return $value;
  }

private function getValue ( $ value , $ length ) { if ( $ length ) { $ value = substr ( $ value , 0 , $ length ) ; } $ value = rawurlencode ( $ value ) ; return $ value ; }

Utility function to encode and trim values


public static function doExecute(ClientInterface $client, RequestInterface $request, $expectedClass = null)
  {
    try {
      $httpHandler = HttpHandlerFactory::build($client);
      $response = $httpHandler($request);
    } catch (RequestException $e) {
      // if Guzzle throws an exception, catch it and handle the response
      if (!$e->hasResponse()) {
        throw $e;
      }

      $response = $e->getResponse();
      // specific checking for Guzzle 5: convert to PSR7 response
      if ($response instanceof \GuzzleHttp\Message\ResponseInterface) {
        $response = new Response(
            $response->getStatusCode(),
            $response->getHeaders() ?: [],
            $response->getBody(),
            $response->getProtocolVersion(),
            $response->getReasonPhrase()
        );
      }
    }

    return self::decodeHttpResponse($response, $request, $expectedClass);
  }

Executes a Psr\Http\Message\RequestInterface

@param Google_Client $client
@param Psr\Http\Message\RequestInterface $request
@return array decoded result
@throws Google_Service_Exception on server side error (ie: not authenticated,
invalid or malformed post body, invalid url)

Executes a Psr \ Http \ Message \ RequestInterface


public static function decodeHttpResponse(
      ResponseInterface $response,
      RequestInterface $request = null,
      $expectedClass = null
  ) {
    $code = $response->getStatusCode();

    // retry strategy
    if (intVal($code) >= 400) {
      // if we errored out, it should be safe to grab the response body
      $body = (string) $response->getBody();

      // Check if we received errors, and add those to the Exception for convenience
      throw new Google_Service_Exception($body, $code, null, self::getResponseErrors($body));
    }

    // Ensure we only pull the entire body into memory if the request is not
    // of media type
    $body = self::decodeBody($response, $request);

    if ($expectedClass = self::determineExpectedClass($expectedClass, $request)) {
      $json = json_decode($body, true);

      return new $expectedClass($json);
    }

    return $response;
  }

Decode an HTTP Response.
@static
@throws Google_Service_Exception
@param Psr\Http\Message\RequestInterface $response The http response to be decoded.
@param Psr\Http\Message\ResponseInterface $response
@return mixed|null


protected function mapTypes($array)
  {
    // Hard initialise simple types, lazy load more complex ones.
    foreach ($array as $key => $val) {
      if ($keyType = $this->keyType($key)) {
        $dataType = $this->dataType($key);
        if ($dataType == 'array' || $dataType == 'map') {
          $this->$key = array();
          foreach ($val as $itemKey => $itemVal) {
            if ($itemVal instanceof $keyType) {
              $this->{$key}[$itemKey] = $itemVal;
            } else {
              $this->{$key}[$itemKey] = new $keyType($itemVal);
            }
          }
        } elseif ($val instanceof $keyType) {
          $this->$key = $val;
        } else {
          $this->$key = new $keyType($val);
        }
        unset($array[$key]);
      } elseif (property_exists($this, $key)) {
          $this->$key = $val;
          unset($array[$key]);
      } elseif (property_exists($this, $camelKey = $this->camelCase($key))) {
          // This checks if property exists as camelCase, leaving it in array as snake_case
          // in case of backwards compatibility issues.
          $this->$camelKey = $val;
      }
    }
    $this->modelData = $array;
  }

Initialize this object's properties from an array.

@param array $array Used to seed this object's properties.
@return void

Initialize this object s properties from an array .


public function toSimpleObject()
  {
    $object = new stdClass();

    // Process all other data.
    foreach ($this->modelData as $key => $val) {
      $result = $this->getSimpleValue($val);
      if ($result !== null) {
        $object->$key = $this->nullPlaceholderCheck($result);
      }
    }

    // Process all public properties.
    $reflect = new ReflectionObject($this);
    $props = $reflect->getProperties(ReflectionProperty::IS_PUBLIC);
    foreach ($props as $member) {
      $name = $member->getName();
      $result = $this->getSimpleValue($this->$name);
      if ($result !== null) {
        $name = $this->getMappedName($name);
        $object->$name = $this->nullPlaceholderCheck($result);
      }
    }

    return $object;
  }

public
function
toSimpleObject
(
)
{
$
object
=
new
stdClass
(
)
;
// Process all other data.
foreach
(
$
this
->
modelData
as
$
key
=>
$
val
)
{
$
result
=
$
this
->
getSimpleValue
(
$
val
)
;
if
(
$
result
!==
)
{
$
object
->
$
key
=
$
this
->
nullPlaceholderCheck
(
$
result
)
;
}
}
// Process all public properties.
$
reflect
=
new
ReflectionObject
(
$
this
)
;
$
props
=
$
reflect
->
getProperties
(
ReflectionProperty
::
IS_PUBLIC
)
;
foreach
(
$
props
as
$
member
)
{
$
name
=
$
member
->
getName
(
)
;
$
result
=
$
this
->
getSimpleValue
(
$
this
->
$
name
)
;
if
(
$
result
!==
)
{
$
name
=
$
this
->
getMappedName
(
$
name
)
;
$
object
->
$
name
=
$
this
->
nullPlaceholderCheck
(
$
result
)
;
}
}
return
$
object
;
}

Create a simplified object suitable for straightforward
conversion to JSON. This is relatively expensive
due to the usage of reflection, but shouldn't be called
a whole lot, and is the most straightforward way to filter.

Create a simplified object suitable for straightforward conversion to JSON . This is relatively expensive due to the usage of reflection but shouldn t be called a whole lot and is the most straightforward way to filter .


private function getSimpleValue($value)
  {
    if ($value instanceof Google_Model) {
      return $value->toSimpleObject();
    } else if (is_array($value)) {
      $return = array();
      foreach ($value as $key => $a_value) {
        $a_value = $this->getSimpleValue($a_value);
        if ($a_value !== null) {
          $key = $this->getMappedName($key);
          $return[$key] = $this->nullPlaceholderCheck($a_value);
        }
      }
      return $return;
    }
    return $value;
  }

private function getSimpleValue ( $ value ) { if ( $ value instanceof Google_Model ) { return $ value -> toSimpleObject ( ) ; } else if ( is_array ( $ value ) ) { $ return = array ( ) ; foreach ( $ value as $ key => $ a_value ) { $ a_value = $ this -> getSimpleValue ( $ a_value ) ; if ( $ a_value !== null ) { $ key = $ this -> getMappedName ( $ key ) ; $ return [ $ key ] = $ this -> nullPlaceholderCheck ( $ a_value ) ; } } return $ return ; } return $ value ; }

Handle different types of values, primarily
other objects and map and array data types.

Handle different types of values primarily other objects and map and array data types .


private function getMappedName($key)
  {
    if (isset($this->internal_gapi_mappings, $this->internal_gapi_mappings[$key])) {
      $key = $this->internal_gapi_mappings[$key];
    }
    return $key;
  }

private function getMappedName ( $ key ) { if ( isset ( $ this -> internal_gapi_mappings , $ this -> internal_gapi_mappings [ $ key ] ) ) { $ key = $ this -> internal_gapi_mappings [ $ key ] ; } return $ key ; }

If there is an internal name mapping, use that.

If there is an internal name mapping use that .


protected function isAssociativeArray($array)
  {
    if (!is_array($array)) {
      return false;
    }
    $keys = array_keys($array);
    foreach ($keys as $key) {
      if (is_string($key)) {
        return true;
      }
    }
    return false;
  }

protected function isAssociativeArray ( $ array ) { if ( ! is_array ( $ array ) ) { return false ; } $ keys = array_keys ( $ array ) ; foreach ( $ keys as $ key ) { if ( is_string ( $ key ) ) { return true ; } } return false ; }

Returns true only if the array is associative.
@param array $array
@return bool True if the array is associative.

Returns true only if the array is associative .


public static function build($cache = null, array $cacheConfig = [])
  {
    $version = ClientInterface::VERSION;

    switch ($version[0]) {
      case '5':
        return new Google_AuthHandler_Guzzle5AuthHandler($cache, $cacheConfig);
      case '6':
        return new Google_AuthHandler_Guzzle6AuthHandler($cache, $cacheConfig);
      default:
        throw new Exception('Version not supported');
    }
  }

public
static
function
build
(
$
cache
=
,
array
$
cacheConfig
=
[
]
)
{
$
version
=
ClientInterface
::
VERSION
;
switch
(
$
version
[
0
]
)
{
case
'5'
:
return
new
Google_AuthHandler_Guzzle5AuthHandler
(
$
cache
,
$
cacheConfig
)
;
case
'6'
:
return
new
Google_AuthHandler_Guzzle6AuthHandler
(
$
cache
,
$
cacheConfig
)
;
default
:
throw
new
Exception
(
'Version not supported'
)
;
}
}

Builds out a default http handler for the installed version of guzzle.

@return Google_AuthHandler_Guzzle5AuthHandler|Google_AuthHandler_Guzzle6AuthHandler
@throws Exception

Builds out a default http handler for the installed version of guzzle .


public function find_config() {

        $config = $this->fix_win32_path($this->config);

        if (!empty($config) && is_readable($config)) {
            return $config;
        }

        if (!empty($config) && !is_readable($config)) {
            throw new ConfigException("User defined config not found at '$config'");
        }

        // config.php in /user/
        if (file_exists($this->root . '/user/config.php')) {
            return $this->root . '/user/config.php';
        }

        // config.php in /includes/
        if (file_exists($this->root . '/includes/config.php')) {
            return $this->root . '/includes/config.php';
        }

        // config.php not found :(

        throw new ConfigException('Cannot find config.php. Please read the readme.html to learn how to install YOURLS');
    }

Find config.php, either user defined or from standard location

@since  1.7.3
@return string         path to found config file
@throws ConfigException

Find config . php either user defined or from standard location