vendor/pimcore/pimcore/models/User.php line 150

Open in your IDE?
  1. <?php
  2. /**
  3.  * Pimcore
  4.  *
  5.  * This source file is available under two different licenses:
  6.  * - GNU General Public License version 3 (GPLv3)
  7.  * - Pimcore Commercial License (PCL)
  8.  * Full copyright and license information is available in
  9.  * LICENSE.md which is distributed with this source code.
  10.  *
  11.  *  @copyright  Copyright (c) Pimcore GmbH (http://www.pimcore.org)
  12.  *  @license    http://www.pimcore.org/license     GPLv3 and PCL
  13.  */
  14. namespace Pimcore\Model;
  15. use Pimcore\File;
  16. use Pimcore\Helper\TemporaryFileHelperTrait;
  17. use Pimcore\Model\User\Role;
  18. use Pimcore\Tool;
  19. /**
  20.  * @method \Pimcore\Model\User\Dao getDao()
  21.  */
  22. final class User extends User\UserRole
  23. {
  24.     use TemporaryFileHelperTrait;
  25.     /**
  26.      * @var string
  27.      */
  28.     protected $type 'user';
  29.     /**
  30.      * @var string
  31.      */
  32.     protected $password;
  33.     /**
  34.      * @var string
  35.      */
  36.     protected $firstname;
  37.     /**
  38.      * @var string
  39.      */
  40.     protected $lastname;
  41.     /**
  42.      * @var string
  43.      */
  44.     protected $email;
  45.     /**
  46.      * @var string
  47.      */
  48.     protected $language 'en';
  49.     /**
  50.      * @var bool
  51.      */
  52.     protected $admin false;
  53.     /**
  54.      * @var bool
  55.      */
  56.     protected $active true;
  57.     /**
  58.      * @var array
  59.      */
  60.     protected $roles = [];
  61.     /**
  62.      * @var bool
  63.      */
  64.     protected $welcomescreen false;
  65.     /**
  66.      * @var bool
  67.      */
  68.     protected $closeWarning true;
  69.     /**
  70.      * @var bool
  71.      */
  72.     protected $memorizeTabs true;
  73.     /**
  74.      * @var bool
  75.      */
  76.     protected $allowDirtyClose false;
  77.     /**
  78.      * @var string|null
  79.      */
  80.     protected $contentLanguages;
  81.     /**
  82.      * @var string|null
  83.      */
  84.     protected $activePerspective;
  85.     /**
  86.      * @var null|array
  87.      */
  88.     protected $mergedPerspectives null;
  89.     /**
  90.      * @var null|array
  91.      */
  92.     protected $mergedWebsiteTranslationLanguagesEdit null;
  93.     /**
  94.      * @var null|array
  95.      */
  96.     protected $mergedWebsiteTranslationLanguagesView null;
  97.     /**
  98.      * @var int
  99.      */
  100.     protected $lastLogin;
  101.     /**
  102.      * @var string
  103.      */
  104.     protected $keyBindings;
  105.     /**
  106.      * @var array
  107.      */
  108.     protected $twoFactorAuthentication;
  109.     /**
  110.      * @return string
  111.      */
  112.     public function getPassword()
  113.     {
  114.         return $this->password;
  115.     }
  116.     /**
  117.      * @param string $password
  118.      *
  119.      * @return $this
  120.      */
  121.     public function setPassword($password)
  122.     {
  123.         if (strlen($password) > 4) {
  124.             $this->password $password;
  125.         }
  126.         return $this;
  127.     }
  128.     /**
  129.      * Alias for getName()
  130.      *
  131.      * @return string
  132.      */
  133.     public function getUsername()
  134.     {
  135.         return $this->getName();
  136.     }
  137.     /**
  138.      * @param string $username
  139.      *
  140.      * @return $this
  141.      */
  142.     public function setUsername($username)
  143.     {
  144.         $this->setName($username);
  145.         return $this;
  146.     }
  147.     /**
  148.      *
  149.      * @return string
  150.      */
  151.     public function getFirstname()
  152.     {
  153.         return $this->firstname;
  154.     }
  155.     /**
  156.      * @param string $firstname
  157.      *
  158.      * @return $this
  159.      */
  160.     public function setFirstname($firstname)
  161.     {
  162.         $this->firstname $firstname;
  163.         return $this;
  164.     }
  165.     /**
  166.      *
  167.      * @return string
  168.      */
  169.     public function getLastname()
  170.     {
  171.         return $this->lastname;
  172.     }
  173.     /**
  174.      * @param string $lastname
  175.      *
  176.      * @return $this
  177.      */
  178.     public function setLastname($lastname)
  179.     {
  180.         $this->lastname $lastname;
  181.         return $this;
  182.     }
  183.     /**
  184.      *
  185.      * @return string
  186.      */
  187.     public function getEmail()
  188.     {
  189.         return $this->email;
  190.     }
  191.     /**
  192.      * @param string $email
  193.      *
  194.      * @return $this
  195.      */
  196.     public function setEmail($email)
  197.     {
  198.         $this->email $email;
  199.         return $this;
  200.     }
  201.     /**
  202.      * @return string
  203.      */
  204.     public function getLanguage()
  205.     {
  206.         return $this->language;
  207.     }
  208.     /**
  209.      * @param string $language
  210.      *
  211.      * @return $this
  212.      */
  213.     public function setLanguage($language)
  214.     {
  215.         if ($language) {
  216.             $this->language $language;
  217.         }
  218.         return $this;
  219.     }
  220.     /**
  221.      * @see getAdmin()
  222.      *
  223.      * @return bool
  224.      */
  225.     public function isAdmin()
  226.     {
  227.         return $this->getAdmin();
  228.     }
  229.     /**
  230.      * @return bool
  231.      */
  232.     public function getAdmin()
  233.     {
  234.         return $this->admin;
  235.     }
  236.     /**
  237.      * @param bool $admin
  238.      *
  239.      * @return $this
  240.      */
  241.     public function setAdmin($admin)
  242.     {
  243.         $this->admin = (bool)$admin;
  244.         return $this;
  245.     }
  246.     /**
  247.      * @return bool
  248.      */
  249.     public function getActive()
  250.     {
  251.         return $this->active;
  252.     }
  253.     /**
  254.      * @param bool $active
  255.      *
  256.      * @return $this
  257.      */
  258.     public function setActive($active)
  259.     {
  260.         $this->active = (bool)$active;
  261.         return $this;
  262.     }
  263.     /**
  264.      * @return bool
  265.      */
  266.     public function isActive()
  267.     {
  268.         return $this->getActive();
  269.     }
  270.     /**
  271.      * @param string $key
  272.      * @param string $type
  273.      *
  274.      * @return bool
  275.      */
  276.     public function isAllowed($key$type 'permission')
  277.     {
  278.         if ($this->isAdmin()) {
  279.             return true;
  280.         }
  281.         if ($type == 'permission') {
  282.             if (!$this->getPermission($key)) {
  283.                 // check roles
  284.                 foreach ($this->getRoles() as $roleId) {
  285.                     /** @var Role $role */
  286.                     $role User\Role::getById($roleId);
  287.                     if ($role->getPermission($key)) {
  288.                         return true;
  289.                     }
  290.                 }
  291.             }
  292.             return $this->getPermission($key);
  293.         } elseif ($type == 'class') {
  294.             $classes $this->getClasses();
  295.             foreach ($this->getRoles() as $roleId) {
  296.                 /** @var Role $role */
  297.                 $role User\Role::getById($roleId);
  298.                 $classes array_merge($classes$role->getClasses());
  299.             }
  300.             if (!empty($classes)) {
  301.                 return in_array($key$classes);
  302.             } else {
  303.                 return true;
  304.             }
  305.         } elseif ($type == 'docType') {
  306.             $docTypes $this->getDocTypes();
  307.             foreach ($this->getRoles() as $roleId) {
  308.                 /** @var Role $role */
  309.                 $role User\Role::getById($roleId);
  310.                 $docTypes array_merge($docTypes$role->getDocTypes());
  311.             }
  312.             if (!empty($docTypes)) {
  313.                 return in_array($key$docTypes);
  314.             } else {
  315.                 return true;
  316.             }
  317.         } elseif ($type == 'perspective') {
  318.             //returns true if required perspective is allowed to use by the user
  319.             return in_array($key$this->getMergedPerspectives());
  320.         }
  321.         return false;
  322.     }
  323.     /**
  324.      *
  325.      * @param string $permissionName
  326.      *
  327.      * @return bool
  328.      */
  329.     public function getPermission($permissionName)
  330.     {
  331.         if ($this->isAdmin()) {
  332.             return true;
  333.         }
  334.         return parent::getPermission($permissionName);
  335.     }
  336.     /**
  337.      * @param string|array $roles
  338.      *
  339.      * @return $this
  340.      */
  341.     public function setRoles($roles)
  342.     {
  343.         if (is_string($roles) && !empty($roles)) {
  344.             $this->roles explode(','$roles);
  345.         } elseif (is_array($roles)) {
  346.             $this->roles $roles;
  347.         } elseif (empty($roles)) {
  348.             $this->roles = [];
  349.         }
  350.         return $this;
  351.     }
  352.     /**
  353.      * @return array
  354.      */
  355.     public function getRoles()
  356.     {
  357.         if (empty($this->roles)) {
  358.             return [];
  359.         }
  360.         return $this->roles;
  361.     }
  362.     /**
  363.      * @param bool $welcomescreen
  364.      *
  365.      * @return $this
  366.      */
  367.     public function setWelcomescreen($welcomescreen)
  368.     {
  369.         $this->welcomescreen = (bool)$welcomescreen;
  370.         return $this;
  371.     }
  372.     /**
  373.      * @return bool
  374.      */
  375.     public function getWelcomescreen()
  376.     {
  377.         return $this->welcomescreen;
  378.     }
  379.     /**
  380.      * @param bool $closeWarning
  381.      *
  382.      * @return $this
  383.      */
  384.     public function setCloseWarning($closeWarning)
  385.     {
  386.         $this->closeWarning = (bool)$closeWarning;
  387.         return $this;
  388.     }
  389.     /**
  390.      * @return bool
  391.      */
  392.     public function getCloseWarning()
  393.     {
  394.         return $this->closeWarning;
  395.     }
  396.     /**
  397.      * @param bool $memorizeTabs
  398.      *
  399.      * @return $this
  400.      */
  401.     public function setMemorizeTabs($memorizeTabs)
  402.     {
  403.         $this->memorizeTabs = (bool)$memorizeTabs;
  404.         return $this;
  405.     }
  406.     /**
  407.      * @return bool
  408.      */
  409.     public function getMemorizeTabs()
  410.     {
  411.         return $this->memorizeTabs;
  412.     }
  413.     /**
  414.      * @param bool $allowDirtyClose
  415.      *
  416.      * @return $this
  417.      */
  418.     public function setAllowDirtyClose($allowDirtyClose)
  419.     {
  420.         $this->allowDirtyClose = (bool)$allowDirtyClose;
  421.         return $this;
  422.     }
  423.     /**
  424.      * @return bool
  425.      */
  426.     public function getAllowDirtyClose()
  427.     {
  428.         return $this->allowDirtyClose;
  429.     }
  430.     /**
  431.      * @internal
  432.      *
  433.      * @return string
  434.      */
  435.     protected function getOriginalImageStoragePath(): string
  436.     {
  437.         return sprintf('/user-image/user-%s.png'$this->getId());
  438.     }
  439.     /***
  440.      * @internal
  441.      * @return string
  442.      */
  443.     protected function getThumbnailImageStoragePath(): string
  444.     {
  445.         return sprintf('/user-image/user-thumbnail-%s.png'$this->getId());
  446.     }
  447.     /**
  448.      * @param string|null $path
  449.      */
  450.     public function setImage($path)
  451.     {
  452.         $storage Tool\Storage::get('admin');
  453.         $originalFileStoragePath $this->getOriginalImageStoragePath();
  454.         $thumbFileStoragePath $this->getThumbnailImageStoragePath();
  455.         if ($storage->fileExists($originalFileStoragePath)) {
  456.             $storage->delete($originalFileStoragePath);
  457.         }
  458.         if ($storage->fileExists($thumbFileStoragePath)) {
  459.             $storage->delete($thumbFileStoragePath);
  460.         }
  461.         if ($path) {
  462.             $handle fopen($path'rb');
  463.             $storage->writeStream($originalFileStoragePath$handle);
  464.             fclose($handle);
  465.         }
  466.     }
  467.     /**
  468.      * @param int|null $width
  469.      * @param int|null $height
  470.      *
  471.      * @return resource
  472.      */
  473.     public function getImage($width null$height null)
  474.     {
  475.         if (!$width) {
  476.             $width 46;
  477.         }
  478.         if (!$height) {
  479.             $height 46;
  480.         }
  481.         $storage Tool\Storage::get('admin');
  482.         if ($storage->fileExists($this->getOriginalImageStoragePath())) {
  483.             if (!$storage->fileExists($this->getThumbnailImageStoragePath())) {
  484.                 $localFile self::getLocalFileFromStream($storage->readStream($this->getOriginalImageStoragePath()));
  485.                 $targetFile File::getLocalTempFilePath('png');
  486.                 $image \Pimcore\Image::getInstance();
  487.                 $image->load($localFile);
  488.                 $image->cover($width$height);
  489.                 $image->save($targetFile'png');
  490.                 $storage->write($this->getThumbnailImageStoragePath(), file_get_contents($targetFile));
  491.                 unlink($targetFile);
  492.             }
  493.             return $storage->readStream($this->getThumbnailImageStoragePath());
  494.         }
  495.         return fopen($this->getFallbackImage(), 'rb');
  496.     }
  497.     /**
  498.      * @return array
  499.      */
  500.     public function getContentLanguages()
  501.     {
  502.         if (strlen($this->contentLanguages)) {
  503.             return explode(','$this->contentLanguages);
  504.         }
  505.         return [];
  506.     }
  507.     /**
  508.      * @param null|string|array $contentLanguages
  509.      */
  510.     public function setContentLanguages($contentLanguages)
  511.     {
  512.         if ($contentLanguages && is_array($contentLanguages)) {
  513.             $contentLanguages implode(','$contentLanguages);
  514.         }
  515.         $this->contentLanguages $contentLanguages;
  516.     }
  517.     /**
  518.      * @return null|string
  519.      */
  520.     public function getActivePerspective()
  521.     {
  522.         if (!$this->activePerspective) {
  523.             $this->activePerspective 'default';
  524.         }
  525.         return $this->activePerspective;
  526.     }
  527.     /**
  528.      * @param null|string $activePerspective
  529.      */
  530.     public function setActivePerspective($activePerspective)
  531.     {
  532.         $this->activePerspective $activePerspective;
  533.     }
  534.     /**
  535.      * Returns array of perspectives names related to user and all related roles
  536.      *
  537.      * @return array|string[]
  538.      */
  539.     private function getMergedPerspectives()
  540.     {
  541.         if (null === $this->mergedPerspectives) {
  542.             $this->mergedPerspectives $this->getPerspectives();
  543.             foreach ($this->getRoles() as $role) {
  544.                 /** @var User\UserRole $userRole */
  545.                 $userRole User\UserRole::getById($role);
  546.                 $this->mergedPerspectives array_merge($this->mergedPerspectives$userRole->getPerspectives());
  547.             }
  548.             $this->mergedPerspectives array_values($this->mergedPerspectives);
  549.             if (!$this->mergedPerspectives) {
  550.                 // $perspectives = \Pimcore\Config::getAvailablePerspectives($this);
  551.                 $allPerspectives \Pimcore\Perspective\Config::get()->toArray();
  552.                 $this->mergedPerspectives = [];
  553.                 $this->mergedPerspectives array_keys($allPerspectives);
  554.             }
  555.         }
  556.         return $this->mergedPerspectives;
  557.     }
  558.     /**
  559.      * Returns the first perspective name
  560.      *
  561.      * @internal
  562.      *
  563.      * @return string
  564.      */
  565.     public function getFirstAllowedPerspective()
  566.     {
  567.         $perspectives $this->getMergedPerspectives();
  568.         if (!empty($perspectives)) {
  569.             return $perspectives[0];
  570.         } else {
  571.             // all perspectives are allowed
  572.             $perspectives \Pimcore\Perspective\Config::getAvailablePerspectives($this);
  573.             return $perspectives[0]['name'];
  574.         }
  575.     }
  576.     /**
  577.      * Returns array of website translation languages for editing related to user and all related roles
  578.      *
  579.      * @return array
  580.      */
  581.     private function getMergedWebsiteTranslationLanguagesEdit(): array
  582.     {
  583.         if (null === $this->mergedWebsiteTranslationLanguagesEdit) {
  584.             $this->mergedWebsiteTranslationLanguagesEdit $this->getWebsiteTranslationLanguagesEdit();
  585.             foreach ($this->getRoles() as $role) {
  586.                 /** @var User\UserRole $userRole */
  587.                 $userRole User\UserRole::getById($role);
  588.                 $this->mergedWebsiteTranslationLanguagesEdit array_merge($this->mergedWebsiteTranslationLanguagesEdit$userRole->getWebsiteTranslationLanguagesEdit());
  589.             }
  590.             $this->mergedWebsiteTranslationLanguagesEdit array_values($this->mergedWebsiteTranslationLanguagesEdit);
  591.         }
  592.         return $this->mergedWebsiteTranslationLanguagesEdit;
  593.     }
  594.     /**
  595.      * Returns array of languages allowed for editing. If edit and view languages are empty all languages are allowed.
  596.      * If only edit languages are empty (but view languages not) empty array is returned.
  597.      *
  598.      * @internal
  599.      *
  600.      * @return array|null
  601.      */
  602.     public function getAllowedLanguagesForEditingWebsiteTranslations()
  603.     {
  604.         $mergedWebsiteTranslationLanguagesEdit $this->getMergedWebsiteTranslationLanguagesEdit();
  605.         if (empty($mergedWebsiteTranslationLanguagesEdit) || $this->isAdmin()) {
  606.             $mergedWebsiteTranslationLanguagesView $this->getMergedWebsiteTranslationLanguagesView();
  607.             if (empty($mergedWebsiteTranslationLanguagesView)) {
  608.                 return Tool::getValidLanguages();
  609.             }
  610.         }
  611.         return $mergedWebsiteTranslationLanguagesEdit;
  612.     }
  613.     /**
  614.      * Returns array of website translation languages for viewing related to user and all related roles
  615.      *
  616.      * @return array
  617.      */
  618.     private function getMergedWebsiteTranslationLanguagesView(): array
  619.     {
  620.         if (null === $this->mergedWebsiteTranslationLanguagesView) {
  621.             $this->mergedWebsiteTranslationLanguagesView $this->getWebsiteTranslationLanguagesView();
  622.             foreach ($this->getRoles() as $role) {
  623.                 /** @var User\UserRole $userRole */
  624.                 $userRole User\UserRole::getById($role);
  625.                 $this->mergedWebsiteTranslationLanguagesView array_merge($this->mergedWebsiteTranslationLanguagesView$userRole->getWebsiteTranslationLanguagesView());
  626.             }
  627.             $this->mergedWebsiteTranslationLanguagesView array_values($this->mergedWebsiteTranslationLanguagesView);
  628.         }
  629.         return $this->mergedWebsiteTranslationLanguagesView;
  630.     }
  631.     /**
  632.      * Returns array of languages allowed for viewing. If view languages are empty all languages are allowed.
  633.      *
  634.      * @internal
  635.      *
  636.      * @return array|null
  637.      */
  638.     public function getAllowedLanguagesForViewingWebsiteTranslations()
  639.     {
  640.         $mergedWebsiteTranslationLanguagesView $this->getMergedWebsiteTranslationLanguagesView();
  641.         if (empty($mergedWebsiteTranslationLanguagesView) || $this->isAdmin()) {
  642.             return Tool::getValidLanguages();
  643.         }
  644.         return $mergedWebsiteTranslationLanguagesView;
  645.     }
  646.     /**
  647.      * @return int
  648.      */
  649.     public function getLastLogin()
  650.     {
  651.         return (int)$this->lastLogin;
  652.     }
  653.     /**
  654.      * @param int $lastLogin
  655.      *
  656.      * @return $this
  657.      */
  658.     public function setLastLogin($lastLogin)
  659.     {
  660.         $this->lastLogin = (int)$lastLogin;
  661.         return $this;
  662.     }
  663.     /**
  664.      * @internal
  665.      *
  666.      * @return string
  667.      */
  668.     public static function getDefaultKeyBindings()
  669.     {
  670.         return json_encode(
  671.             [
  672.                 [
  673.                     'action' => 'save',
  674.                     'key' => ord('S'),
  675.                     'ctrl' => true,
  676.                 ],
  677.                 [
  678.                     'action' => 'publish',
  679.                     'key' => ord('P'),
  680.                     'ctrl' => true,
  681.                     'shift' => true,
  682.                 ],
  683.                 [
  684.                     'action' => 'unpublish',
  685.                     'key' => ord('U'),
  686.                     'ctrl' => true,
  687.                     'shift' => true,
  688.                 ],
  689.                 [
  690.                     'action' => 'rename',
  691.                     'key' => ord('R'),
  692.                     'alt' => true,
  693.                     'shift' => true,
  694.                 ],
  695.                 [
  696.                     'action' => 'refresh',
  697.                     'key' => 116,
  698.                 ],
  699.                 [
  700.                     'action' => 'openAsset',
  701.                     'key' => ord('A'),
  702.                     'ctrl' => true,
  703.                     'shift' => true,
  704.                 ],
  705.                 [
  706.                     'action' => 'openObject',
  707.                     'key' => ord('O'),
  708.                     'ctrl' => true,
  709.                     'shift' => true,
  710.                 ],
  711.                 [
  712.                     'action' => 'openDocument',
  713.                     'key' => ord('D'),
  714.                     'ctrl' => true,
  715.                     'shift' => true,
  716.                 ],
  717.                 [
  718.                     'action' => 'openClassEditor',
  719.                     'key' => ord('C'),
  720.                     'ctrl' => true,
  721.                     'shift' => true,
  722.                 ],
  723.                 [
  724.                     'action' => 'openInTree',
  725.                     'key' => ord('L'),
  726.                     'ctrl' => true,
  727.                     'shift' => true,
  728.                 ],
  729.                 [
  730.                     'action' => 'showMetaInfo',
  731.                     'key' => ord('I'),
  732.                     'alt' => true,
  733.                 ],
  734.                 [
  735.                     'action' => 'searchDocument',
  736.                     'key' => ord('W'),
  737.                     'alt' => true,
  738.                 ],
  739.                 [
  740.                     'action' => 'searchAsset',
  741.                     'key' => ord('A'),
  742.                     'alt' => true,
  743.                 ],
  744.                 [
  745.                     'action' => 'searchObject',
  746.                     'key' => ord('O'),
  747.                     'alt' => true,
  748.                 ],
  749.                 [
  750.                     'action' => 'showElementHistory',
  751.                     'key' => ord('H'),
  752.                     'alt' => true,
  753.                 ],
  754.                 [
  755.                     'action' => 'closeAllTabs',
  756.                     'key' => ord('T'),
  757.                     'alt' => true,
  758.                 ],
  759.                 [
  760.                     'action' => 'searchAndReplaceAssignments',
  761.                     'key' => ord('S'),
  762.                     'alt' => true,
  763.                 ],
  764.                 [
  765.                     'action' => 'glossary',
  766.                     'key' => ord('G'),
  767.                     'shift' => true,
  768.                     'alt' => true,
  769.                 ],
  770.                 [
  771.                     'action' => 'redirects',
  772.                     'key' => ord('R'),
  773.                     'ctrl' => false,
  774.                     'alt' => true,
  775.                 ],
  776.                 [
  777.                     'action' => 'sharedTranslations',
  778.                     'key' => ord('T'),
  779.                     'ctrl' => true,
  780.                     'alt' => true,
  781.                 ],
  782.                 [
  783.                     'action' => 'recycleBin',
  784.                     'key' => ord('R'),
  785.                     'ctrl' => true,
  786.                     'alt' => true,
  787.                 ],
  788.                 [
  789.                     'action' => 'notesEvents',
  790.                     'key' => ord('N'),
  791.                     'ctrl' => true,
  792.                     'alt' => true,
  793.                 ],
  794.                 [
  795.                     'action' => 'applicationLogger',
  796.                     'key' => ord('L'),
  797.                     'ctrl' => true,
  798.                     'alt' => true,
  799.                 ],
  800.                 [
  801.                     'action' => 'reports',
  802.                     'key' => ord('M'),
  803.                     'ctrl' => true,
  804.                     'alt' => true,
  805.                 ],
  806.                 [
  807.                     'action' => 'tagManager',
  808.                     'key' => ord('H'),
  809.                     'ctrl' => true,
  810.                     'alt' => true,
  811.                 ],
  812.                 [
  813.                     'action' => 'seoDocumentEditor',
  814.                     'key' => ord('S'),
  815.                     'ctrl' => true,
  816.                     'alt' => true,
  817.                 ],
  818.                 [
  819.                     'action' => 'robots',
  820.                     'key' => ord('J'),
  821.                     'ctrl' => true,
  822.                     'alt' => true,
  823.                 ],
  824.                 [
  825.                     'action' => 'httpErrorLog',
  826.                     'key' => ord('O'),
  827.                     'ctrl' => true,
  828.                     'alt' => true,
  829.                 ],
  830.                 [
  831.                     'action' => 'customReports',
  832.                     'key' => ord('C'),
  833.                     'ctrl' => true,
  834.                     'alt' => true,
  835.                 ],
  836.                 [
  837.                     'action' => 'tagConfiguration',
  838.                     'key' => ord('N'),
  839.                     'ctrl' => true,
  840.                     'alt' => true,
  841.                 ],
  842.                 [
  843.                     'action' => 'users',
  844.                     'key' => ord('U'),
  845.                     'ctrl' => true,
  846.                     'alt' => true,
  847.                 ],
  848.                 [
  849.                     'action' => 'roles',
  850.                     'key' => ord('P'),
  851.                     'ctrl' => true,
  852.                     'alt' => true,
  853.                 ],
  854.                 [
  855.                     'action' => 'clearAllCaches',
  856.                     'key' => ord('Q'),
  857.                     'ctrl' => false,
  858.                     'alt' => true,
  859.                 ],
  860.                 [
  861.                     'action' => 'clearDataCache',
  862.                     'key' => ord('C'),
  863.                     'ctrl' => false,
  864.                     'alt' => true,
  865.                 ],
  866.                 [
  867.                     'action' => 'quickSearch',
  868.                     'key' => ord('F'),
  869.                     'ctrl' => true,
  870.                     'shift' => true,
  871.                 ],
  872.             ]);
  873.     }
  874.     /**
  875.      * @return string
  876.      */
  877.     public function getKeyBindings()
  878.     {
  879.         return $this->keyBindings $this->keyBindings self::getDefaultKeyBindings();
  880.     }
  881.     /**
  882.      * @param string $keyBindings
  883.      */
  884.     public function setKeyBindings($keyBindings)
  885.     {
  886.         $this->keyBindings $keyBindings;
  887.     }
  888.     /**
  889.      * @param string|null $key
  890.      *
  891.      * @return array|mixed|null|string
  892.      */
  893.     public function getTwoFactorAuthentication($key null)
  894.     {
  895.         if (!is_array($this->twoFactorAuthentication) || empty($this->twoFactorAuthentication)) {
  896.             // set defaults if no data is present
  897.             $this->twoFactorAuthentication = [
  898.                 'required' => false,
  899.                 'enabled' => false,
  900.                 'secret' => '',
  901.                 'type' => '',
  902.             ];
  903.         }
  904.         if ($key) {
  905.             if (isset($this->twoFactorAuthentication[$key])) {
  906.                 return $this->twoFactorAuthentication[$key];
  907.             } else {
  908.                 return null;
  909.             }
  910.         } else {
  911.             return $this->twoFactorAuthentication;
  912.         }
  913.     }
  914.     /**
  915.      * You can either pass an array for setting the entire 2fa settings, or a key and a value as the second argument
  916.      *
  917.      * @param array|string $key
  918.      * @param mixed $value
  919.      */
  920.     public function setTwoFactorAuthentication($key$value null)
  921.     {
  922.         if (is_string($key) && $value === null && strlen($key) > 3) {
  923.             $this->twoFactorAuthentication json_decode($keytrue);
  924.         } elseif (is_array($key)) {
  925.             $this->twoFactorAuthentication $key;
  926.         } else {
  927.             if (!is_array($this->twoFactorAuthentication)) {
  928.                 // load defaults
  929.                 $this->getTwoFactorAuthentication();
  930.             }
  931.             $this->twoFactorAuthentication[$key] = $value;
  932.         }
  933.     }
  934.     public function hasImage()
  935.     {
  936.         return Tool\Storage::get('admin')->fileExists($this->getOriginalImageStoragePath());
  937.     }
  938.     /**
  939.      * @internal
  940.      *
  941.      * @return string
  942.      */
  943.     protected function getFallbackImage()
  944.     {
  945.         return PIMCORE_WEB_ROOT '/bundles/pimcoreadmin/img/avatar.png';
  946.     }
  947. }