2014-08-05 13:06:38 -07:00
< ? php
2016-11-07 09:54:10 -07:00
namespace Grav\Plugin\Admin ;
2014-08-05 13:06:38 -07:00
2014-12-11 19:57:57 -07:00
use Grav\Common\Cache ;
2014-10-01 22:28:16 +03:00
use Grav\Common\Config\Config ;
2016-04-15 16:18:02 -06:00
use Grav\Common\File\CompiledYamlFile ;
2014-08-05 13:06:38 -07:00
use Grav\Common\Filesystem\Folder ;
2017-02-17 16:01:14 -07:00
use Grav\Common\GPM\GPM as GravGPM ;
2015-08-07 13:31:15 -07:00
use Grav\Common\GPM\Installer ;
2014-08-29 11:27:53 +03:00
use Grav\Common\Grav ;
2014-08-05 13:06:38 -07:00
use Grav\Common\Data ;
2016-07-18 15:42:38 -06:00
use Grav\Common\Page\Media ;
2018-05-10 10:14:18 +03:00
use Grav\Common\Page\Medium\Medium ;
2016-01-21 09:46:38 +02:00
use Grav\Common\Page\Page ;
2015-10-21 19:46:51 +02:00
use Grav\Common\Page\Pages ;
2015-04-20 20:41:34 +02:00
use Grav\Common\Page\Collection ;
2015-04-11 16:01:27 +02:00
use Grav\Common\User\User ;
2015-04-27 13:37:22 +02:00
use Grav\Common\Utils ;
2018-09-28 12:27:40 -06:00
use Grav\Common\Backup\Backups ;
2018-05-10 10:34:56 +03:00
use Grav\Plugin\Admin\Twig\AdminTwigExtension ;
use Grav\Plugin\Login\TwoFactorAuth\TwoFactorAuth ;
2018-08-22 12:45:39 -06:00
use Grav\Common\Yaml ;
2016-01-14 17:59:00 -07:00
use RocketTheme\Toolbox\Event\Event ;
2015-08-19 17:28:39 +02:00
use RocketTheme\Toolbox\File\File ;
2015-04-27 13:37:22 +02:00
use RocketTheme\Toolbox\File\JsonFile ;
2018-05-08 13:11:41 +03:00
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator ;
2018-08-22 12:45:39 -06:00
2014-08-05 13:06:38 -07:00
2016-02-12 10:16:28 +01:00
/**
* Class AdminController
2016-11-07 09:54:10 -07:00
*
2016-02-12 10:16:28 +01:00
* @ package Grav\Plugin
*/
2016-11-07 09:54:10 -07:00
class AdminController extends AdminBaseController
2014-08-05 13:06:38 -07:00
{
2014-08-29 11:27:53 +03:00
/**
* @ var Grav
*/
public $grav ;
2014-08-05 13:06:38 -07:00
/**
* @ var string
*/
public $view ;
/**
* @ var string
*/
public $task ;
/**
* @ var string
*/
public $route ;
/**
* @ var array
*/
public $post ;
2016-03-16 11:09:48 +02:00
/**
* @ var array | null
*/
public $data ;
2014-08-05 13:06:38 -07:00
/**
* @ var Admin
*/
protected $admin ;
/**
* @ var string
*/
protected $redirect ;
2016-11-07 09:54:10 -07:00
/**
* @ var \Grav\Common\Uri $uri
*/
protected $uri ;
2014-08-05 13:06:38 -07:00
/**
* @ var int
*/
protected $redirectCode ;
2016-05-17 16:46:00 -06:00
protected $upload_errors = [
0 => " There is no error, the file uploaded with success " ,
1 => " The uploaded file exceeds the max upload size " ,
2 => " The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML " ,
3 => " The uploaded file was only partially uploaded " ,
4 => " No file was uploaded " ,
6 => " Missing a temporary folder " ,
7 => " Failed to write file to disk " ,
8 => " A PHP extension stopped the file upload "
];
2014-08-05 13:06:38 -07:00
/**
2016-07-07 18:55:52 +02:00
* @ param Grav $grav
2014-08-05 13:06:38 -07:00
* @ param string $view
* @ param string $task
* @ param string $route
2016-07-07 18:55:52 +02:00
* @ param array $post
2014-08-05 13:06:38 -07:00
*/
2016-11-07 09:54:10 -07:00
public function initialize ( Grav $grav = null , $view = null , $task = null , $route = null , $post = null )
2014-08-05 13:06:38 -07:00
{
2014-08-29 11:27:53 +03:00
$this -> grav = $grav ;
2014-08-05 13:06:38 -07:00
$this -> view = $view ;
$this -> task = $task ? $task : 'display' ;
2016-03-16 11:09:48 +02:00
if ( isset ( $post [ 'data' ])) {
$this -> data = $this -> getPost ( $post [ 'data' ]);
unset ( $post [ 'data' ]);
2016-04-07 13:09:22 +02:00
} else {
// Backwards compatibility for Form plugin <= 1.2
$this -> data = $this -> getPost ( $post );
2016-03-16 11:09:48 +02:00
}
2016-11-07 09:54:10 -07:00
$this -> post = $this -> getPost ( $post );
2014-08-05 13:06:38 -07:00
$this -> route = $route ;
2014-08-29 11:27:53 +03:00
$this -> admin = $this -> grav [ 'admin' ];
2016-11-07 09:54:10 -07:00
$this -> grav -> fireEvent ( 'onAdminControllerInit' , new Event ([ 'controller' => & $this ]));
2014-08-05 13:06:38 -07:00
}
2018-05-10 10:34:56 +03:00
/**
* Handle login .
*
* @ return bool True if the action was performed .
*/
protected function taskLogin ()
{
2018-05-10 20:04:14 +03:00
$this -> admin -> authenticate ( $this -> data , $this -> post );
2018-05-10 10:34:56 +03:00
return true ;
}
/**
2018-05-10 20:04:14 +03:00
* @ return bool True if the action was performed .
2018-05-10 10:34:56 +03:00
*/
2018-05-10 20:04:14 +03:00
protected function taskTwofa ()
2018-05-10 10:34:56 +03:00
{
2018-05-10 20:04:14 +03:00
$this -> admin -> twoFa ( $this -> data , $this -> post );
2018-05-10 10:34:56 +03:00
2018-05-10 20:04:14 +03:00
return true ;
}
2018-05-10 10:34:56 +03:00
2018-05-10 20:04:14 +03:00
/**
* Handle logout .
*
* @ return bool True if the action was performed .
*/
protected function taskLogout ()
{
$this -> admin -> logout ( $this -> data , $this -> post );
2018-05-10 10:34:56 +03:00
return true ;
}
/**
* @ param null $secret
* @ return bool
*/
public function taskRegenerate2FASecret ()
{
if ( ! $this -> authorizeTask ( 'regenerate 2FA Secret' , [ 'admin.login' ])) {
return false ;
}
try {
/** @var User $user */
2018-05-10 11:51:27 +03:00
$user = $this -> grav [ 'user' ];
2018-05-10 10:34:56 +03:00
/** @var TwoFactorAuth $twoFa */
$twoFa = $this -> grav [ 'login' ] -> twoFactorAuth ();
2018-05-10 12:13:04 +03:00
$secret = $twoFa -> createSecret ();
2018-05-10 10:34:56 +03:00
$image = $twoFa -> getQrImageData ( $user -> username , $secret );
2018-05-10 11:51:27 +03:00
// Save secret into the user file.
2018-05-10 10:34:56 +03:00
$file = $user -> file ();
if ( $file -> exists ()) {
$content = $file -> content ();
2018-05-10 11:51:27 +03:00
$content [ 'twofa_secret' ] = $secret ;
2018-05-10 10:34:56 +03:00
$file -> save ( $content );
$file -> free ();
}
2018-05-10 11:51:27 +03:00
// Change secret in the session.
$user -> twofa_secret = $secret ;
$this -> admin -> json_response = [ 'status' => 'success' , 'image' => $image , 'secret' => preg_replace ( '|(\w{4})|' , '\\1 ' , $secret )];
2018-05-10 10:34:56 +03:00
} catch ( \Exception $e ) {
$this -> admin -> json_response = [ 'status' => 'error' , 'message' => $e -> getMessage ()];
return false ;
}
return true ;
}
2014-08-05 13:06:38 -07:00
/**
2016-11-07 09:54:10 -07:00
* Handle the reset password action .
2015-07-30 12:20:25 +02:00
*
2016-11-07 09:54:10 -07:00
* @ return bool True if the action was performed .
2014-08-05 13:06:38 -07:00
*/
2016-11-07 09:54:10 -07:00
public function taskReset ()
2014-08-05 13:06:38 -07:00
{
2016-11-07 09:54:10 -07:00
$data = $this -> data ;
2016-03-19 11:54:19 +01:00
2016-11-07 09:54:10 -07:00
if ( isset ( $data [ 'password' ])) {
$username = isset ( $data [ 'username' ]) ? strip_tags ( strtolower ( $data [ 'username' ])) : null ;
2018-05-10 10:34:56 +03:00
$user = $username ? User :: load ( $username ) : null ;
2016-11-07 09:54:10 -07:00
$password = isset ( $data [ 'password' ]) ? $data [ 'password' ] : null ;
$token = isset ( $data [ 'token' ]) ? $data [ 'token' ] : null ;
2016-03-19 11:54:19 +01:00
2018-05-10 10:34:56 +03:00
if ( $user && $user -> exists () && ! empty ( $user -> reset )) {
2016-11-07 09:54:10 -07:00
list ( $good_token , $expire ) = explode ( '::' , $user -> reset );
2016-03-19 11:54:19 +01:00
2016-11-07 09:54:10 -07:00
if ( $good_token === $token ) {
if ( time () > $expire ) {
$this -> admin -> setMessage ( $this -> admin -> translate ( 'PLUGIN_ADMIN.RESET_LINK_EXPIRED' ), 'error' );
$this -> setRedirect ( '/forgot' );
2016-03-19 11:54:19 +01:00
2016-11-07 09:54:10 -07:00
return true ;
2016-03-19 11:54:19 +01:00
}
2018-05-10 10:34:56 +03:00
unset ( $user -> hashed_password , $user -> reset );
2016-11-07 09:54:10 -07:00
$user -> password = $password ;
2016-03-05 12:11:13 +01:00
2016-11-07 09:54:10 -07:00
$user -> validate ();
$user -> filter ();
$user -> save ();
$this -> admin -> setMessage ( $this -> admin -> translate ( 'PLUGIN_ADMIN.RESET_PASSWORD_RESET' ), 'info' );
$this -> setRedirect ( '/' );
return true ;
2015-11-17 11:56:21 +01:00
}
2015-11-10 17:53:09 +01:00
}
2015-11-06 15:32:26 +01:00
2016-11-07 09:54:10 -07:00
$this -> admin -> setMessage ( $this -> admin -> translate ( 'PLUGIN_ADMIN.RESET_INVALID_LINK' ), 'error' );
$this -> setRedirect ( '/forgot' );
return true ;
2015-12-11 17:25:52 +01:00
2018-05-10 10:34:56 +03:00
}
2016-11-07 09:54:10 -07:00
2018-05-10 10:34:56 +03:00
$user = $this -> grav [ 'uri' ] -> param ( 'user' );
$token = $this -> grav [ 'uri' ] -> param ( 'token' );
2014-10-10 13:41:27 +03:00
2018-05-10 10:34:56 +03:00
if ( empty ( $user ) || empty ( $token )) {
$this -> admin -> setMessage ( $this -> admin -> translate ( 'PLUGIN_ADMIN.RESET_INVALID_LINK' ), 'error' );
$this -> setRedirect ( '/forgot' );
return true ;
}
$this -> admin -> setMessage ( $this -> admin -> translate ( 'PLUGIN_ADMIN.RESET_NEW_PASSWORD' ), 'info' );
$this -> admin -> forgot = [ 'username' => $user , 'token' => $token ];
return true ;
}
/**
* Handle the email password recovery procedure .
*
* @ return bool True if the action was performed .
* @ todo LOGIN
*/
protected function taskForgot ()
{
$param_sep = $this -> grav [ 'config' ] -> get ( 'system.param_sep' , ':' );
$post = $this -> post ;
$data = $this -> data ;
$login = $this -> grav [ 'login' ];
$username = isset ( $data [ 'username' ]) ? strip_tags ( strtolower ( $data [ 'username' ])) : '' ;
$user = ! empty ( $username ) ? User :: load ( $username ) : null ;
if ( ! isset ( $this -> grav [ 'Email' ])) {
$this -> admin -> setMessage ( $this -> admin -> translate ( 'PLUGIN_ADMIN.FORGOT_EMAIL_NOT_CONFIGURED' ), 'error' );
$this -> setRedirect ( $post [ 'redirect' ]);
return true ;
}
if ( ! $user || ! $user -> exists ()) {
$this -> admin -> setMessage ( $this -> admin -> translate ( 'PLUGIN_ADMIN.FORGOT_INSTRUCTIONS_SENT_VIA_EMAIL' ),
'info' );
$this -> setRedirect ( $post [ 'redirect' ]);
return true ;
}
if ( empty ( $user -> email )) {
$this -> admin -> setMessage ( $this -> admin -> translate ( 'PLUGIN_ADMIN.FORGOT_INSTRUCTIONS_SENT_VIA_EMAIL' ),
'info' );
$this -> setRedirect ( $post [ 'redirect' ]);
return true ;
}
$count = $this -> grav [ 'config' ] -> get ( 'plugins.login.max_pw_resets_count' , 0 );
$interval = $this -> grav [ 'config' ] -> get ( 'plugins.login.max_pw_resets_interval' , 2 );
if ( $login -> isUserRateLimited ( $user , 'pw_resets' , $count , $interval )) {
$this -> admin -> setMessage ( $this -> admin -> translate ([ 'PLUGIN_LOGIN.FORGOT_CANNOT_RESET_IT_IS_BLOCKED' , $user -> email , $interval ]), 'error' );
$this -> setRedirect ( $post [ 'redirect' ]);
return true ;
}
$token = md5 ( uniqid ( mt_rand (), true ));
$expire = time () + 604800 ; // next week
$user -> reset = $token . '::' . $expire ;
$user -> save ();
$author = $this -> grav [ 'config' ] -> get ( 'site.author.name' , '' );
$fullname = $user -> fullname ? : $username ;
$reset_link = rtrim ( $this -> grav [ 'uri' ] -> rootUrl ( true ), '/' ) . '/' . trim ( $this -> admin -> base ,
'/' ) . '/reset/task' . $param_sep . 'reset/user' . $param_sep . $username . '/token' . $param_sep . $token . '/admin-nonce' . $param_sep . Utils :: getNonce ( 'admin-form' );
$sitename = $this -> grav [ 'config' ] -> get ( 'site.title' , 'Website' );
$from = $this -> grav [ 'config' ] -> get ( 'plugins.email.from' );
if ( empty ( $from )) {
$this -> admin -> setMessage ( $this -> admin -> translate ( 'PLUGIN_ADMIN.FORGOT_EMAIL_NOT_CONFIGURED' ), 'error' );
$this -> setRedirect ( $post [ 'redirect' ]);
return true ;
}
$to = $user -> email ;
$subject = $this -> admin -> translate ([ 'PLUGIN_ADMIN.FORGOT_EMAIL_SUBJECT' , $sitename ]);
$content = $this -> admin -> translate ([
'PLUGIN_ADMIN.FORGOT_EMAIL_BODY' ,
$fullname ,
$reset_link ,
$author ,
$sitename
]);
$body = $this -> grav [ 'twig' ] -> processTemplate ( 'email/base.html.twig' , [ 'content' => $content ]);
$message = $this -> grav [ 'Email' ] -> message ( $subject , $body , 'text/html' ) -> setFrom ( $from ) -> setTo ( $to );
2014-10-10 13:41:27 +03:00
2018-05-10 10:34:56 +03:00
$sent = $this -> grav [ 'Email' ] -> send ( $message );
if ( $sent < 1 ) {
$this -> admin -> setMessage ( $this -> admin -> translate ( 'PLUGIN_ADMIN.FORGOT_FAILED_TO_EMAIL' ), 'error' );
} else {
$this -> admin -> setMessage ( $this -> admin -> translate ( 'PLUGIN_ADMIN.FORGOT_INSTRUCTIONS_SENT_VIA_EMAIL' ),
'info' );
2014-08-05 13:06:38 -07:00
}
2016-03-05 12:11:13 +01:00
2018-05-10 10:34:56 +03:00
$this -> setRedirect ( '/' );
2016-11-07 09:54:10 -07:00
return true ;
2014-08-05 13:06:38 -07:00
}
2015-07-30 12:20:25 +02:00
/**
2016-11-07 09:54:10 -07:00
* Enable a plugin .
*
* @ return bool True if the action was performed .
2015-07-30 12:20:25 +02:00
*/
2016-11-07 09:54:10 -07:00
public function taskEnable ()
2014-08-05 13:06:38 -07:00
{
2016-11-07 09:54:10 -07:00
if ( ! $this -> authorizeTask ( 'enable plugin' , [ 'admin.plugins' , 'admin.super' ])) {
return false ;
2014-08-05 13:06:38 -07:00
}
2018-05-10 10:14:18 +03:00
if ( $this -> view !== 'plugins' ) {
2016-11-07 09:54:10 -07:00
return false ;
2015-08-19 17:27:57 +02:00
}
2016-11-07 09:54:10 -07:00
// Filter value and save it.
$this -> post = [ 'enabled' => true ];
$obj = $this -> prepareData ( $this -> post );
$obj -> save ();
2014-08-05 13:06:38 -07:00
2016-11-07 09:54:10 -07:00
$this -> post = [ '_redirect' => 'plugins' ];
$this -> admin -> setMessage ( $this -> admin -> translate ( 'PLUGIN_ADMIN.SUCCESSFULLY_ENABLED_PLUGIN' ), 'info' );
return true ;
2014-08-05 13:06:38 -07:00
}
2015-08-26 10:25:14 +02:00
/**
2016-11-07 09:54:10 -07:00
* Gets the configuration data for a given view & post
*
* @ param array $data
2015-08-26 10:25:14 +02:00
*
2016-11-07 09:54:10 -07:00
* @ return object
2015-08-26 10:25:14 +02:00
*/
2016-11-07 09:54:10 -07:00
protected function prepareData ( array $data )
2016-01-10 17:17:04 +01:00
{
2016-11-07 09:54:10 -07:00
$type = trim ( " { $this -> view } / { $this -> admin -> route } " , '/' );
$data = $this -> admin -> data ( $type , $data );
return $data ;
2015-08-26 10:25:14 +02:00
}
2014-08-05 13:06:38 -07:00
/**
2016-11-07 09:54:10 -07:00
* Disable a plugin .
2014-08-05 13:06:38 -07:00
*
* @ return bool True if the action was performed .
*/
2016-11-07 09:54:10 -07:00
public function taskDisable ()
2014-08-05 13:06:38 -07:00
{
2016-11-07 09:54:10 -07:00
if ( ! $this -> authorizeTask ( 'disable plugin' , [ 'admin.plugins' , 'admin.super' ])) {
return false ;
2014-08-29 15:03:06 +03:00
}
2014-08-05 13:06:38 -07:00
2018-05-10 10:14:18 +03:00
if ( $this -> view !== 'plugins' ) {
2016-11-07 09:54:10 -07:00
return false ;
}
2014-08-05 13:06:38 -07:00
2016-11-07 09:54:10 -07:00
// Filter value and save it.
$this -> post = [ 'enabled' => false ];
$obj = $this -> prepareData ( $this -> post );
$obj -> save ();
2016-05-03 13:36:06 -06:00
2016-11-07 09:54:10 -07:00
$this -> post = [ '_redirect' => 'plugins' ];
$this -> admin -> setMessage ( $this -> admin -> translate ( 'PLUGIN_ADMIN.SUCCESSFULLY_DISABLED_PLUGIN' ), 'info' );
2014-08-05 13:06:38 -07:00
2014-12-11 19:57:57 -07:00
return true ;
}
2016-04-15 16:18:02 -06:00
/**
2016-11-07 09:54:10 -07:00
* Set the default theme .
*
* @ return bool True if the action was performed .
2016-04-15 16:18:02 -06:00
*/
2016-11-07 09:54:10 -07:00
public function taskActivate ()
2016-04-15 16:18:02 -06:00
{
2016-11-07 09:54:10 -07:00
if ( ! $this -> authorizeTask ( 'activate theme' , [ 'admin.themes' , 'admin.super' ])) {
2016-04-15 16:18:02 -06:00
return false ;
}
2018-05-10 10:14:18 +03:00
if ( $this -> view !== 'themes' ) {
2016-11-07 09:54:10 -07:00
return false ;
2016-04-15 16:18:02 -06:00
}
2016-11-07 09:54:10 -07:00
$this -> post = [ '_redirect' => 'themes' ];
2016-04-15 16:18:02 -06:00
2016-11-07 09:54:10 -07:00
// Make sure theme exists (throws exception)
$name = $this -> route ;
$this -> grav [ 'themes' ] -> get ( $name );
2016-04-15 16:18:02 -06:00
2016-11-07 09:54:10 -07:00
// Store system configuration.
$system = $this -> admin -> data ( 'config/system' );
$system -> set ( 'pages.theme' , $name );
$system -> save ();
2016-04-15 16:18:02 -06:00
2016-11-07 09:54:10 -07:00
// Force configuration reload and save.
/** @var Config $config */
$config = $this -> grav [ 'config' ];
$config -> reload () -> save ();
2016-04-20 15:59:46 -07:00
2016-11-07 09:54:10 -07:00
$config -> set ( 'system.pages.theme' , $name );
2016-07-07 18:55:52 +02:00
2016-11-07 09:54:10 -07:00
$this -> admin -> setMessage ( $this -> admin -> translate ( 'PLUGIN_ADMIN.SUCCESSFULLY_CHANGED_THEME' ), 'info' );
2016-04-15 16:18:02 -06:00
2016-11-07 09:54:10 -07:00
return true ;
2014-12-11 19:57:57 -07:00
}
2016-09-02 18:29:47 +02:00
/**
2016-11-07 09:54:10 -07:00
* Handles updating Grav
*
* @ return bool True if the action was performed
2016-09-02 18:29:47 +02:00
*/
2016-11-07 09:54:10 -07:00
public function taskUpdategrav ()
2016-09-02 18:29:47 +02:00
{
2016-11-07 09:54:10 -07:00
if ( ! $this -> authorizeTask ( 'install grav' , [ 'admin.super' ])) {
2016-10-27 11:28:09 +02:00
return false ;
2016-09-02 18:29:47 +02:00
}
2016-11-07 09:54:10 -07:00
$gpm = Gpm :: GPM ();
$version = $gpm -> grav -> getVersion ();
$result = Gpm :: selfupgrade ();
2016-09-02 18:29:47 +02:00
2016-11-07 09:54:10 -07:00
if ( $result ) {
$this -> admin -> json_response = [
'status' => 'success' ,
'type' => 'updategrav' ,
'version' => $version ,
'message' => $this -> admin -> translate ( 'PLUGIN_ADMIN.GRAV_WAS_SUCCESSFULLY_UPDATED_TO' ) . ' ' . $version
];
2016-09-05 15:12:27 +02:00
} else {
2016-09-02 18:29:47 +02:00
$this -> admin -> json_response = [
2016-11-07 09:54:10 -07:00
'status' => 'error' ,
'type' => 'updategrav' ,
'version' => GRAV_VERSION ,
'message' => $this -> admin -> translate ( 'PLUGIN_ADMIN.GRAV_UPDATE_FAILED' ) . ' <br>' . Installer :: lastErrorMsg ()
2016-09-02 18:29:47 +02:00
];
2016-10-27 11:28:09 +02:00
}
2016-09-02 18:29:47 +02:00
2016-11-07 09:54:10 -07:00
return true ;
}
2016-10-02 14:00:53 -07:00
2016-11-07 09:54:10 -07:00
/**
* Handles uninstalling plugins and themes
*
* @ deprecated
*
* @ return bool True if the action was performed
*/
public function taskUninstall ()
{
$type = $this -> view === 'plugins' ? 'plugins' : 'themes' ;
if ( ! $this -> authorizeTask ( 'uninstall ' . $type , [ 'admin.' . $type , 'admin.super' ])) {
return false ;
2016-09-02 18:29:47 +02:00
}
2016-11-07 09:54:10 -07:00
$package = $this -> route ;
2016-10-02 14:00:53 -07:00
2016-11-07 09:54:10 -07:00
$result = Gpm :: uninstall ( $package , []);
2016-10-02 14:00:53 -07:00
2016-11-07 09:54:10 -07:00
if ( $result ) {
$this -> admin -> setMessage ( $this -> admin -> translate ( 'PLUGIN_ADMIN.UNINSTALL_SUCCESSFUL' ), 'info' );
} else {
$this -> admin -> setMessage ( $this -> admin -> translate ( 'PLUGIN_ADMIN.UNINSTALL_FAILED' ), 'error' );
2016-10-02 14:00:53 -07:00
}
2016-11-07 09:54:10 -07:00
$this -> post = [ '_redirect' => $this -> view ];
2016-10-02 14:00:53 -07:00
return true ;
}
2016-11-07 09:54:10 -07:00
/**
* Handles creating an empty page folder ( without markdown file )
*
* @ return bool True if the action was performed .
*/
public function taskSaveNewFolder ()
2016-10-02 14:00:53 -07:00
{
2016-11-07 09:54:10 -07:00
if ( ! $this -> authorizeTask ( 'save' , $this -> dataPermissions ())) {
return false ;
2016-10-02 14:00:53 -07:00
}
2016-11-07 09:54:10 -07:00
$data = ( array ) $this -> data ;
2016-08-11 19:17:02 +02:00
2018-05-10 10:14:18 +03:00
if ( $data [ 'route' ] === '/' ) {
2016-11-07 09:54:10 -07:00
$path = $this -> grav [ 'locator' ] -> findResource ( 'page://' );
} else {
$path = $this -> grav [ 'page' ] -> find ( $data [ 'route' ]) -> path ();
2016-08-11 19:17:02 +02:00
}
2016-11-07 09:54:10 -07:00
$orderOfNewFolder = $this -> getNextOrderInFolder ( $path );
2017-02-26 19:36:01 +01:00
$new_path = $path . '/' . $orderOfNewFolder . '.' . $data [ 'folder' ];
2016-08-11 19:17:02 +02:00
2016-12-07 05:46:43 -07:00
Folder :: create ( $new_path );
2016-11-07 09:54:10 -07:00
Cache :: clearCache ( 'standard' );
2016-08-11 19:17:02 +02:00
2016-12-07 05:46:43 -07:00
$this -> grav -> fireEvent ( 'onAdminAfterSaveAs' , new Event ([ 'path' => $new_path ]));
2016-11-07 09:54:10 -07:00
$this -> admin -> setMessage ( $this -> admin -> translate ( 'PLUGIN_ADMIN.SUCCESSFULLY_SAVED' ), 'info' );
2016-08-11 19:17:02 +02:00
2016-11-07 09:54:10 -07:00
$multilang = $this -> isMultilang ();
$admin_route = $this -> admin -> base ;
$redirect_url = '/' . ( $multilang ? ( $this -> grav [ 'session' ] -> admin_lang ) : '' ) . $admin_route . '/' . $this -> view ;
$this -> setRedirect ( $redirect_url );
2016-08-11 19:17:02 +02:00
2016-11-07 09:54:10 -07:00
return true ;
2016-08-11 19:17:02 +02:00
}
/**
2016-11-07 09:54:10 -07:00
* Get the next available ordering number in a folder
*
* @ param $path
2016-08-11 19:17:02 +02:00
*
2016-11-07 09:54:10 -07:00
* @ return string the correct order string to prepend
2016-08-11 19:17:02 +02:00
*/
2017-03-26 19:46:02 -07:00
public static function getNextOrderInFolder ( $path )
2016-08-11 19:17:02 +02:00
{
2016-11-07 09:54:10 -07:00
$files = Folder :: all ( $path , [ 'recursive' => false ]);
2016-08-11 19:17:02 +02:00
2016-11-07 09:54:10 -07:00
$highestOrder = 0 ;
foreach ( $files as $file ) {
preg_match ( PAGE_ORDER_PREFIX_REGEX , $file , $order );
if ( isset ( $order [ 0 ])) {
2018-05-10 10:14:18 +03:00
$theOrder = ( int ) trim ( $order [ 0 ], '.' );
2016-11-07 09:54:10 -07:00
} else {
$theOrder = 0 ;
}
if ( $theOrder >= $highestOrder ) {
$highestOrder = $theOrder ;
2016-08-11 19:17:02 +02:00
}
}
2016-11-07 09:54:10 -07:00
$orderOfNewFolder = $highestOrder + 1 ;
if ( $orderOfNewFolder < 10 ) {
$orderOfNewFolder = '0' . $orderOfNewFolder ;
2016-08-11 19:17:02 +02:00
}
2016-11-07 09:54:10 -07:00
return $orderOfNewFolder ;
2016-08-11 19:17:02 +02:00
}
/**
2016-11-07 09:54:10 -07:00
* Handles form and saves the input data if its valid .
2016-08-11 19:17:02 +02:00
*
2016-11-07 09:54:10 -07:00
* @ return bool True if the action was performed .
2016-08-11 19:17:02 +02:00
*/
2016-11-07 09:54:10 -07:00
public function taskSave ()
2016-08-11 19:17:02 +02:00
{
2016-11-07 09:54:10 -07:00
if ( ! $this -> authorizeTask ( 'save' , $this -> dataPermissions ())) {
return false ;
}
2016-08-11 19:17:02 +02:00
2016-11-07 09:54:10 -07:00
$reorder = true ;
$data = ( array ) $this -> data ;
2016-08-11 19:17:02 +02:00
2018-09-29 21:18:45 -06:00
$this -> grav [ 'twig' ] -> twig_vars [ 'current_form_data' ] = $data ;
2017-01-28 16:48:11 +01:00
// Special handler for user data.
2018-05-10 10:14:18 +03:00
if ( $this -> view === 'user' ) {
2018-05-16 16:33:20 -06:00
if ( ! $this -> grav [ 'user' ] -> exists ()) {
$this -> admin -> setMessage ( $this -> admin -> translate ( 'PLUGIN_ADMIN.NO_USER_EXISTS' ), 'error' );
return false ;
}
2017-01-28 16:48:11 +01:00
if ( ! $this -> admin -> authorize ([ 'admin.super' , 'admin.users' ])) {
2018-05-16 16:33:20 -06:00
// no user file or not admin.super or admin.users
2017-01-28 16:48:11 +01:00
if ( $this -> prepareData ( $data ) -> username !== $this -> grav [ 'user' ] -> username ) {
2018-05-16 16:33:20 -06:00
$this -> admin -> setMessage ( $this -> admin -> translate ( 'PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK' ) . ' save.' , 'error' );
2017-01-28 16:48:11 +01:00
return false ;
}
}
}
2016-11-07 09:54:10 -07:00
// Special handler for pages data.
2018-05-10 10:14:18 +03:00
if ( $this -> view === 'pages' ) {
2016-11-07 09:54:10 -07:00
/** @var Pages $pages */
$pages = $this -> grav [ 'pages' ];
2016-08-11 19:17:02 +02:00
2016-11-07 09:54:10 -07:00
// Find new parent page in order to build the path.
$route = ! isset ( $data [ 'route' ]) ? dirname ( $this -> admin -> route ) : $data [ 'route' ];
2016-08-11 19:17:02 +02:00
2016-11-07 09:54:10 -07:00
/** @var Page $obj */
$obj = $this -> admin -> page ( true );
2016-08-11 19:17:02 +02:00
2017-07-17 18:36:22 +02:00
if ( ! isset ( $data [ 'folder' ]) || ! $data [ 'folder' ]) {
2017-06-30 21:11:56 +02:00
$data [ 'folder' ] = $obj -> slug ();
$this -> data [ 'folder' ] = $obj -> slug ();
}
2017-06-30 21:09:54 +02:00
2016-11-07 09:54:10 -07:00
// Ensure route is prefixed with a forward slash.
$route = '/' . ltrim ( $route , '/' );
2016-08-11 19:17:02 +02:00
2018-09-29 21:18:45 -06:00
// XSS Checks for page content
$xss_whitelist = $this -> grav [ 'config' ] -> get ( 'security.xss_whitelist' , []);
if ( ! $this -> admin -> authorize ( $xss_whitelist )) {
if ( $issue = Utils :: detectXss ( $data [ 'content' ])) {
$this -> admin -> setMessage ( 'Save failed: Found potential XSS code of type: <strong>' . $issue . '</strong>, please remove or disable the XSS filter in <strong>Configuration</strong> / <strong>Security</strong>.' ,
'error' );
return false ;
}
}
2016-11-07 09:54:10 -07:00
if ( isset ( $data [ 'frontmatter' ]) && ! $this -> checkValidFrontmatter ( $data [ 'frontmatter' ])) {
$this -> admin -> setMessage ( $this -> admin -> translate ( 'PLUGIN_ADMIN.INVALID_FRONTMATTER_COULD_NOT_SAVE' ),
'error' );
2016-07-07 18:55:52 +02:00
2016-11-07 09:54:10 -07:00
return false ;
}
2016-03-14 17:52:11 +01:00
2016-03-07 11:33:23 +01:00
2018-05-10 10:14:18 +03:00
$parent = $route && $route !== '/' && $route !== '.' && $route !== '/.' ? $pages -> dispatch ( $route , true ) : $pages -> root ();
$original_order = ( int ) trim ( $obj -> order (), '.' );
2016-03-09 21:19:13 +01:00
2016-11-07 09:54:10 -07:00
try {
2017-04-14 11:24:48 -06:00
// Change parent if needed and initialize move (might be needed also on ordering/folder change).
$obj = $obj -> move ( $parent );
$this -> preparePage ( $obj , false , $obj -> language ());
2016-11-07 09:54:10 -07:00
$obj -> validate ();
2017-04-14 11:24:48 -06:00
2016-11-07 09:54:10 -07:00
} catch ( \Exception $e ) {
$this -> admin -> setMessage ( $e -> getMessage (), 'error' );
2016-03-07 11:33:23 +01:00
2016-11-07 09:54:10 -07:00
return false ;
}
$obj -> filter ();
2016-03-07 11:33:23 +01:00
2016-11-07 09:54:10 -07:00
// rename folder based on visible
2018-05-10 10:14:18 +03:00
if ( $original_order === 1000 ) {
2016-11-07 09:54:10 -07:00
// increment order to force reshuffle
$obj -> order ( $original_order + 1 );
}
2016-07-07 18:55:52 +02:00
2017-03-21 20:19:35 -06:00
if ( isset ( $data [ 'order' ]) && ! empty ( $data [ 'order' ])) {
2017-03-21 15:35:33 -06:00
$reorder = explode ( ',' , $data [ 'order' ]);
}
2016-11-07 09:54:10 -07:00
// add or remove numeric prefix based on ordering value
if ( isset ( $data [ 'ordering' ])) {
if ( $data [ 'ordering' ] && ! $obj -> order ()) {
$obj -> order ( $this -> getNextOrderInFolder ( $obj -> parent () -> path ()));
$reorder = false ;
} elseif ( ! $data [ 'ordering' ] && $obj -> order ()) {
$obj -> folder ( $obj -> slug ());
}
}
2016-03-07 11:33:23 +01:00
} else {
2016-11-07 09:54:10 -07:00
// Handle standard data types.
$obj = $this -> prepareData ( $data );
2016-03-07 11:33:23 +01:00
2016-11-07 09:54:10 -07:00
try {
$obj -> validate ();
} catch ( \Exception $e ) {
$this -> admin -> setMessage ( $e -> getMessage (), 'error' );
2016-03-07 11:33:23 +01:00
2016-11-07 09:54:10 -07:00
return false ;
}
2016-07-07 18:55:52 +02:00
2016-11-07 09:54:10 -07:00
$obj -> filter ();
2016-03-07 11:33:23 +01:00
}
2016-11-07 09:54:10 -07:00
$obj = $this -> storeFiles ( $obj );
2016-07-07 18:55:52 +02:00
2016-11-07 09:54:10 -07:00
if ( $obj ) {
// Event to manipulate data before saving the object
$this -> grav -> fireEvent ( 'onAdminSave' , new Event ([ 'object' => & $obj ]));
$obj -> save ( $reorder );
$this -> admin -> setMessage ( $this -> admin -> translate ( 'PLUGIN_ADMIN.SUCCESSFULLY_SAVED' ), 'info' );
2016-12-07 05:46:43 -07:00
$this -> grav -> fireEvent ( 'onAdminAfterSave' , new Event ([ 'object' => $obj ]));
2016-03-14 17:52:11 +01:00
}
2016-03-07 11:33:23 +01:00
2018-05-10 10:14:18 +03:00
if ( $this -> view !== 'pages' ) {
2016-11-07 09:54:10 -07:00
// Force configuration reload.
/** @var Config $config */
$config = $this -> grav [ 'config' ];
$config -> reload ();
if ( $this -> view === 'user' ) {
2018-05-10 10:14:18 +03:00
if ( $obj -> username === $this -> grav [ 'user' ] -> username ) {
2017-01-31 11:11:27 +01:00
//Editing current user. Reload user object
2017-03-29 22:41:24 -07:00
unset ( $this -> grav [ 'user' ] -> avatar );
2017-01-31 11:11:27 +01:00
$this -> grav [ 'user' ] -> merge ( User :: load ( $this -> admin -> route ) -> toArray ());
}
2016-11-07 09:54:10 -07:00
}
2016-03-07 11:33:23 +01:00
}
2016-11-07 09:54:10 -07:00
// Always redirect if a page route was changed, to refresh it
if ( $obj instanceof Page ) {
if ( method_exists ( $obj , 'unsetRouteSlug' )) {
$obj -> unsetRouteSlug ();
}
2016-03-07 11:33:23 +01:00
2016-11-07 09:54:10 -07:00
$multilang = $this -> isMultilang ();
2016-03-05 18:46:41 +01:00
2016-11-07 09:54:10 -07:00
if ( $multilang ) {
if ( ! $obj -> language ()) {
$obj -> language ( $this -> grav [ 'session' ] -> admin_lang );
}
2016-03-17 15:57:10 +01:00
}
2016-11-07 09:54:10 -07:00
$admin_route = $this -> admin -> base ;
2016-03-17 15:57:10 +01:00
2017-11-06 19:38:00 -07:00
$route = $obj -> rawRoute ();
2016-11-07 09:54:10 -07:00
$redirect_url = ( $multilang ? '/' . $obj -> language () : '' ) . $admin_route . '/' . $this -> view . $route ;
$this -> setRedirect ( $redirect_url );
2016-08-11 19:17:02 +02:00
}
return true ;
}
2015-07-30 12:20:25 +02:00
/**
2016-11-07 09:54:10 -07:00
* @ param string $frontmatter
2015-07-30 12:20:25 +02:00
*
2016-11-07 09:54:10 -07:00
* @ return bool
2015-07-30 12:20:25 +02:00
*/
2016-11-07 09:54:10 -07:00
public function checkValidFrontmatter ( $frontmatter )
2015-04-27 13:37:22 +02:00
{
2015-05-04 11:53:29 +02:00
try {
2018-08-22 12:45:39 -06:00
Yaml :: parse ( $frontmatter );
} catch ( \RuntimeException $e ) {
2016-11-07 09:54:10 -07:00
return false ;
2015-04-20 20:41:34 +02:00
}
2016-11-07 09:54:10 -07:00
return true ;
2015-04-20 20:41:34 +02:00
}
2015-07-30 12:20:25 +02:00
/**
2016-11-07 09:54:10 -07:00
* Continue to the new page .
2015-07-30 12:20:25 +02:00
*
* @ return bool True if the action was performed .
*/
2016-11-07 09:54:10 -07:00
public function taskContinue ()
2014-09-22 15:49:53 -06:00
{
2016-11-07 09:54:10 -07:00
$data = ( array ) $this -> data ;
2018-05-10 10:14:18 +03:00
if ( $this -> view === 'users' ) {
2016-11-07 09:54:10 -07:00
$username = strip_tags ( strtolower ( $data [ 'username' ]));
$this -> setRedirect ( " { $this -> view } / { $username } " );
return true ;
2015-05-11 16:37:43 +02:00
}
2018-05-10 10:14:18 +03:00
if ( $this -> view === 'groups' ) {
2016-11-07 09:54:10 -07:00
$this -> setRedirect ( " { $this -> view } / { $data [ 'groupname' ] } " );
2014-09-22 15:49:53 -06:00
2016-11-07 09:54:10 -07:00
return true ;
}
2016-03-05 12:11:13 +01:00
2018-05-10 10:14:18 +03:00
if ( $this -> view !== 'pages' ) {
2014-10-01 22:28:16 +03:00
return false ;
2014-09-22 17:13:19 -06:00
}
2018-05-10 10:14:18 +03:00
$route = $data [ 'route' ] !== '/' ? $data [ 'route' ] : '' ;
2017-05-16 17:31:57 +02:00
$folder = $data [ 'folder' ];
// Handle @slugify-{field} value, automatically slugifies the specified field
2018-05-10 10:14:18 +03:00
if ( 0 === strpos ( $folder , '@slugify-' )) {
2017-05-16 17:31:57 +02:00
$folder = \Grav\Plugin\Admin\Utils :: slug ( $data [ substr ( $folder , 9 )]);
}
$folder = ltrim ( $folder , '_' );
2016-11-07 09:54:10 -07:00
if ( ! empty ( $data [ 'modular' ])) {
$folder = '_' . $folder ;
2014-09-22 15:49:53 -06:00
}
2016-11-07 09:54:10 -07:00
$path = $route . '/' . $folder ;
$this -> admin -> session () -> { $path } = $data ;
// Store the name and route of a page, to be used pre-filled defaults of the form in the future
$this -> admin -> session () -> lastPageName = $data [ 'name' ];
$this -> admin -> session () -> lastPageRoute = $data [ 'route' ];
$this -> setRedirect ( " { $this -> view } / " . ltrim ( $path , '/' ));
2014-09-22 15:49:53 -06:00
return true ;
}
2016-11-07 09:54:10 -07:00
/**
* Toggle the gpm . releases setting
*/
protected function taskGpmRelease ()
{
if ( ! $this -> authorizeTask ( 'configuration' , [ 'admin.configuration' , 'admin.super' ])) {
2016-01-21 09:46:38 +02:00
return false ;
2014-10-07 15:32:07 -06:00
}
2014-09-22 16:35:11 -06:00
2016-11-07 09:54:10 -07:00
// Default release state
$release = 'stable' ;
$reload = false ;
2016-03-05 12:11:13 +01:00
2016-11-07 09:54:10 -07:00
// Get the testing release value if set
2018-05-10 10:14:18 +03:00
if ( $this -> post [ 'release' ] === 'testing' ) {
2016-11-07 09:54:10 -07:00
$release = 'testing' ;
}
2016-03-05 12:11:13 +01:00
2016-11-07 09:54:10 -07:00
$config = $this -> grav [ 'config' ];
$current_release = $config -> get ( 'system.gpm.releases' );
2016-10-10 13:07:14 +02:00
2016-11-07 09:54:10 -07:00
// If the releases setting is different, save it in the system config
2018-05-10 10:14:18 +03:00
if ( $current_release !== $release ) {
2016-11-07 09:54:10 -07:00
$data = new Data\Data ( $config -> get ( 'system' ));
$data -> set ( 'gpm.releases' , $release );
2016-03-05 12:11:13 +01:00
2016-11-07 09:54:10 -07:00
// Get the file location
2018-05-10 10:14:18 +03:00
$file = CompiledYamlFile :: instance ( $this -> grav [ 'locator' ] -> findResource ( 'config://system.yaml' ));
2016-11-07 09:54:10 -07:00
$data -> file ( $file );
// Save the configuration
$data -> save ();
$config -> reload ();
$reload = true ;
2014-10-07 15:32:07 -06:00
}
2014-09-22 16:35:11 -06:00
2016-11-07 09:54:10 -07:00
$this -> admin -> json_response = [ 'status' => 'success' , 'reload' => $reload ];
2016-03-05 12:11:13 +01:00
2016-11-07 09:54:10 -07:00
return true ;
}
/**
* Keep alive
*/
protected function taskKeepAlive ()
{
exit ();
}
protected function taskGetNewsFeed ()
{
2018-07-11 15:30:11 -06:00
if ( ! $this -> authorizeTask ( 'dashboard' , [ 'admin.login' , 'admin.super' ])) {
return false ;
}
2016-11-07 09:54:10 -07:00
$cache = $this -> grav [ 'cache' ];
2018-05-10 10:14:18 +03:00
if ( $this -> post [ 'refresh' ] === 'true' ) {
2016-11-07 09:54:10 -07:00
$cache -> delete ( 'news-feed' );
2014-09-22 16:35:11 -06:00
}
2014-10-07 15:32:07 -06:00
2016-11-07 09:54:10 -07:00
$feed_data = $cache -> fetch ( 'news-feed' );
2014-10-07 15:32:07 -06:00
2016-11-07 09:54:10 -07:00
if ( ! $feed_data ) {
try {
$feed = $this -> admin -> getFeed ();
if ( is_object ( $feed )) {
2016-01-16 18:49:42 +01:00
2018-05-10 10:14:18 +03:00
require_once __DIR__ . '/../classes/Twig/AdminTwigExtension.php' ;
$adminTwigExtension = new AdminTwigExtension ;
2016-11-07 09:54:10 -07:00
$feed_items = $feed -> getItems ();
// Feed should only every contain 10, but just in case!
if ( count ( $feed_items ) > 10 ) {
$feed_items = array_slice ( $feed_items , 0 , 10 );
}
foreach ( $feed_items as $item ) {
$datetime = $adminTwigExtension -> adminNicetimeFilter ( $item -> getDate () -> getTimestamp ());
2017-02-26 19:36:01 +01:00
$feed_data [] = '<li><span class="date">' . $datetime . '</span> <a href="' . $item -> getUrl () . '" target="_blank" title="' . str_replace ( '"' ,
'″' , $item -> getTitle ()) . '">' . $item -> getTitle () . '</a></li>' ;
2016-11-07 09:54:10 -07:00
}
}
// cache for 1 hour
$cache -> save ( 'news-feed' , $feed_data , 60 * 60 );
} catch ( \Exception $e ) {
$this -> admin -> json_response = [ 'status' => 'error' , 'message' => $e -> getMessage ()];
2017-02-26 19:36:01 +01:00
2016-11-07 09:54:10 -07:00
return ;
}
2016-01-16 18:49:42 +01:00
}
2014-10-07 15:32:07 -06:00
2016-11-07 09:54:10 -07:00
$this -> admin -> json_response = [ 'status' => 'success' , 'feed_data' => $feed_data ];
}
2016-03-05 12:11:13 +01:00
2017-02-16 15:03:30 -07:00
/**
* Get update status from GPM
*/
protected function taskGetUpdates ()
{
2018-07-11 15:30:11 -06:00
if ( ! $this -> authorizeTask ( 'dashboard' , [ 'admin.login' , 'admin.super' ])) {
return false ;
}
2017-02-26 19:36:01 +01:00
$data = $this -> post ;
2018-05-10 10:14:18 +03:00
$flush = ( isset ( $data [ 'flush' ]) && $data [ 'flush' ] == true ) ? true : false ;
2017-02-16 15:03:30 -07:00
if ( isset ( $this -> grav [ 'session' ])) {
$this -> grav [ 'session' ] -> close ();
}
try {
2017-02-17 16:01:14 -07:00
$gpm = new GravGPM ( $flush );
2017-02-16 15:03:30 -07:00
$resources_updates = $gpm -> getUpdatable ();
if ( $gpm -> grav != null ) {
$grav_updates = [
2018-05-10 10:14:18 +03:00
'isUpdatable' => $gpm -> grav -> isUpdatable (),
'assets' => $gpm -> grav -> getAssets (),
'version' => GRAV_VERSION ,
'available' => $gpm -> grav -> getVersion (),
'date' => $gpm -> grav -> getDate (),
'isSymlink' => $gpm -> grav -> isSymlink ()
2017-02-16 15:03:30 -07:00
];
$this -> admin -> json_response = [
2018-05-10 10:14:18 +03:00
'status' => 'success' ,
'payload' => [
'resources' => $resources_updates ,
'grav' => $grav_updates ,
'installed' => $gpm -> countInstalled (),
2017-02-16 15:03:30 -07:00
'flushed' => $flush
]
];
} else {
2018-05-10 10:14:18 +03:00
$this -> admin -> json_response = [ 'status' => 'error' , 'message' => 'Cannot connect to the GPM' ];
2017-02-16 15:03:30 -07:00
}
} catch ( \Exception $e ) {
2018-05-10 10:14:18 +03:00
$this -> admin -> json_response = [ 'status' => 'error' , 'message' => $e -> getMessage ()];
2017-02-16 15:03:30 -07:00
}
}
2016-11-07 09:54:10 -07:00
/**
* Get Notifications from cache .
*
*/
protected function taskGetNotifications ()
{
2018-07-11 15:30:11 -06:00
if ( ! $this -> authorizeTask ( 'dashboard' , [ 'admin.login' , 'admin.super' ])) {
return false ;
}
2016-11-07 09:54:10 -07:00
$cache = $this -> grav [ 'cache' ];
if ( ! ( bool ) $this -> grav [ 'config' ] -> get ( 'system.cache.enabled' ) || ! $notifications = $cache -> fetch ( 'notifications' )) {
//No notifications cache (first time)
$this -> admin -> json_response = [ 'status' => 'success' , 'notifications' => [], 'need_update' => true ];
2017-02-26 19:36:01 +01:00
2016-11-07 09:54:10 -07:00
return ;
2014-10-07 15:32:07 -06:00
}
2016-11-07 09:54:10 -07:00
$need_update = false ;
if ( ! $last_checked = $cache -> fetch ( 'notifications_last_checked' )) {
$need_update = true ;
} else {
if ( time () - $last_checked > 86400 ) {
$need_update = true ;
}
}
2016-03-05 12:11:13 +01:00
2016-11-07 09:54:10 -07:00
try {
$notifications = $this -> admin -> processNotifications ( $notifications );
} catch ( \Exception $e ) {
$this -> admin -> json_response = [ 'status' => 'error' , 'message' => $e -> getMessage ()];
2017-02-26 19:36:01 +01:00
2016-11-07 09:54:10 -07:00
return ;
}
2017-02-26 19:36:01 +01:00
$this -> admin -> json_response = [
'status' => 'success' ,
'notifications' => $notifications ,
'need_update' => $need_update
];
2016-11-07 09:54:10 -07:00
}
/**
* Process Notifications . Store the notifications object locally .
*
* @ return bool
*/
protected function taskProcessNotifications ()
{
2018-07-11 15:30:11 -06:00
if ( ! $this -> authorizeTask ( 'notifications' , [ 'admin.login' , 'admin.super' ])) {
return false ;
}
2016-11-07 09:54:10 -07:00
$cache = $this -> grav [ 'cache' ];
$data = $this -> post ;
$notifications = json_decode ( $data [ 'notifications' ]);
try {
$notifications = $this -> admin -> processNotifications ( $notifications );
} catch ( \Exception $e ) {
$this -> admin -> json_response = [ 'status' => 'error' , 'message' => $e -> getMessage ()];
2017-02-26 19:36:01 +01:00
2016-01-21 09:46:38 +02:00
return false ;
2014-10-07 15:32:07 -06:00
}
2016-11-07 09:54:10 -07:00
$show_immediately = false ;
if ( ! $cache -> fetch ( 'notifications_last_checked' )) {
$show_immediately = true ;
}
$cache -> save ( 'notifications' , $notifications );
$cache -> save ( 'notifications_last_checked' , time ());
2014-10-07 15:32:07 -06:00
2017-02-26 19:36:01 +01:00
$this -> admin -> json_response = [
'status' => 'success' ,
'notifications' => $notifications ,
'show_immediately' => $show_immediately
];
2016-01-21 09:46:38 +02:00
return true ;
2014-09-22 17:13:19 -06:00
}
2015-07-30 12:20:25 +02:00
/**
2016-11-07 09:54:10 -07:00
* Handle getting a new package dependencies needed to be installed
2015-07-30 12:20:25 +02:00
*
2016-11-07 09:54:10 -07:00
* @ return bool
2015-07-30 12:20:25 +02:00
*/
2016-11-07 09:54:10 -07:00
protected function taskGetPackagesDependencies ()
2014-09-22 17:13:19 -06:00
{
2016-11-07 09:54:10 -07:00
$data = $this -> post ;
$packages = isset ( $data [ 'packages' ]) ? explode ( ',' , $data [ 'packages' ]) : '' ;
$packages = ( array ) $packages ;
try {
$this -> admin -> checkPackagesCanBeInstalled ( $packages );
$dependencies = $this -> admin -> getDependenciesNeededToInstall ( $packages );
} catch ( \Exception $e ) {
$this -> admin -> json_response = [ 'status' => 'error' , 'message' => $e -> getMessage ()];
2016-01-21 09:46:38 +02:00
return false ;
2015-05-11 16:37:43 +02:00
}
2016-11-07 09:54:10 -07:00
$this -> admin -> json_response = [ 'status' => 'success' , 'dependencies' => $dependencies ];
2014-09-22 17:27:48 -06:00
2016-11-07 09:54:10 -07:00
return true ;
}
protected function taskInstallDependenciesOfPackages ()
{
$data = $this -> post ;
$packages = isset ( $data [ 'packages' ]) ? explode ( ',' , $data [ 'packages' ]) : '' ;
$packages = ( array ) $packages ;
$type = isset ( $data [ 'type' ]) ? $data [ 'type' ] : '' ;
if ( ! $this -> authorizeTask ( 'install ' . $type , [ 'admin.' . $type , 'admin.super' ])) {
2016-03-05 12:11:13 +01:00
$this -> admin -> json_response = [
2016-07-07 18:55:52 +02:00
'status' => 'error' ,
2016-11-07 09:54:10 -07:00
'message' => $this -> admin -> translate ( 'PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK' )
2016-03-05 12:11:13 +01:00
];
2014-10-01 22:28:16 +03:00
return false ;
2014-09-22 17:27:48 -06:00
}
2014-09-22 17:13:19 -06:00
2016-11-07 09:54:10 -07:00
try {
$dependencies = $this -> admin -> getDependenciesNeededToInstall ( $packages );
} catch ( \Exception $e ) {
$this -> admin -> json_response = [ 'status' => 'error' , 'message' => $e -> getMessage ()];
2015-08-28 18:55:23 +02:00
2016-10-27 11:12:01 +02:00
return false ;
}
2016-01-16 18:30:26 +01:00
2018-05-10 10:14:18 +03:00
$result = Gpm :: install ( array_keys ( $dependencies ), [ 'theme' => $type === 'theme' ]);
2015-08-28 18:55:23 +02:00
2016-11-07 09:54:10 -07:00
if ( $result ) {
$this -> admin -> json_response = [ 'status' => 'success' , 'message' => 'Dependencies installed successfully' ];
} else {
2016-10-27 11:12:01 +02:00
$this -> admin -> json_response = [
'status' => 'error' ,
2016-11-07 09:54:10 -07:00
'message' => $this -> admin -> translate ( 'PLUGIN_ADMIN.INSTALLATION_FAILED' )
2016-10-27 11:12:01 +02:00
];
}
2016-11-07 09:54:10 -07:00
return true ;
}
2016-10-27 11:12:01 +02:00
2017-02-19 19:16:03 +01:00
protected function taskInstallPackage ( $reinstall = false )
2016-11-07 09:54:10 -07:00
{
$data = $this -> post ;
$package = isset ( $data [ 'package' ]) ? $data [ 'package' ] : '' ;
$type = isset ( $data [ 'type' ]) ? $data [ 'type' ] : '' ;
if ( ! $this -> authorizeTask ( 'install ' . $type , [ 'admin.' . $type , 'admin.super' ])) {
2016-03-05 12:11:13 +01:00
$this -> admin -> json_response = [
2016-07-07 18:55:52 +02:00
'status' => 'error' ,
2016-11-07 09:54:10 -07:00
'message' => $this -> admin -> translate ( 'PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK' )
2016-03-05 12:11:13 +01:00
];
2016-10-27 11:12:01 +02:00
return false ;
2014-09-22 17:27:48 -06:00
}
2015-07-30 12:20:25 +02:00
2016-11-07 09:54:10 -07:00
try {
2018-05-10 10:14:18 +03:00
$result = Gpm :: install ( $package , [ 'theme' => $type === 'theme' ]);
2016-11-07 09:54:10 -07:00
} catch ( \Exception $e ) {
$this -> admin -> json_response = [ 'status' => 'error' , 'message' => $e -> getMessage ()];
2016-10-27 11:12:01 +02:00
2016-11-07 09:54:10 -07:00
return false ;
2016-10-27 11:12:01 +02:00
}
2016-11-07 09:54:10 -07:00
if ( $result ) {
$this -> admin -> json_response = [
'status' => 'success' ,
2018-03-10 00:56:35 +01:00
'message' => $this -> admin -> translate ( is_string ( $result ) ? $result : sprintf ( $this -> admin -> translate ( $reinstall ? : 'PLUGIN_ADMIN.PACKAGE_X_REINSTALLED_SUCCESSFULLY' ,
2017-02-26 19:36:01 +01:00
null ), $package ))
2016-11-07 09:54:10 -07:00
];
} else {
$this -> admin -> json_response = [
'status' => 'error' ,
2018-03-10 00:56:35 +01:00
'message' => $this -> admin -> translate ( $reinstall ? : 'PLUGIN_ADMIN.INSTALLATION_FAILED' )
2016-11-07 09:54:10 -07:00
];
}
2016-10-27 11:12:01 +02:00
2014-09-22 17:27:48 -06:00
return true ;
2014-09-22 16:35:11 -06:00
}
2015-07-30 12:20:25 +02:00
/**
2016-11-07 09:54:10 -07:00
* Handle removing a package
2016-01-21 09:46:38 +02:00
*
2016-11-07 09:54:10 -07:00
* @ return bool
2015-07-30 12:20:25 +02:00
*/
2016-11-07 09:54:10 -07:00
protected function taskRemovePackage ()
2015-07-29 14:04:06 -06:00
{
2016-11-07 09:54:10 -07:00
$data = $this -> post ;
$package = isset ( $data [ 'package' ]) ? $data [ 'package' ] : '' ;
$type = isset ( $data [ 'type' ]) ? $data [ 'type' ] : '' ;
2015-07-29 14:04:06 -06:00
2016-11-07 09:54:10 -07:00
if ( ! $this -> authorizeTask ( 'uninstall ' . $type , [ 'admin.' . $type , 'admin.super' ])) {
2017-01-11 20:05:07 -07:00
$json_response = [
2016-11-07 09:54:10 -07:00
'status' => 'error' ,
'message' => $this -> admin -> translate ( 'PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK' )
];
2017-02-26 19:36:01 +01:00
echo json_encode ( $json_response );
exit ;
2016-11-07 09:54:10 -07:00
}
2016-03-05 12:11:13 +01:00
2016-11-07 09:54:10 -07:00
//check if there are packages that have this as a dependency. Abort and show which ones
$dependent_packages = $this -> admin -> getPackagesThatDependOnPackage ( $package );
if ( count ( $dependent_packages ) > 0 ) {
if ( count ( $dependent_packages ) > 1 ) {
2018-05-10 10:14:18 +03:00
$message = 'The installed packages <cyan>' . implode ( '</cyan>, <cyan>' ,
$dependent_packages ) . '</cyan> depends on this package. Please remove those first.' ;
2016-11-07 09:54:10 -07:00
} else {
2018-05-10 10:14:18 +03:00
$message = 'The installed package <cyan>' . implode ( '</cyan>, <cyan>' ,
$dependent_packages ) . '</cyan> depends on this package. Please remove it first.' ;
2015-07-29 14:04:06 -06:00
}
2017-01-11 20:05:07 -07:00
$json_response = [ 'status' => 'error' , 'message' => $message ];
2017-02-26 19:36:01 +01:00
echo json_encode ( $json_response );
exit ;
2016-11-07 09:54:10 -07:00
}
2015-07-30 19:53:06 -06:00
2016-11-07 09:54:10 -07:00
try {
$dependencies = $this -> admin -> dependenciesThatCanBeRemovedWhenRemoving ( $package );
$result = Gpm :: uninstall ( $package , []);
2015-07-30 19:53:06 -06:00
} catch ( \Exception $e ) {
2017-01-11 20:05:07 -07:00
$json_response = [ 'status' => 'error' , 'message' => $e -> getMessage ()];
2017-02-26 19:36:01 +01:00
echo json_encode ( $json_response );
exit ;
2015-07-29 14:04:06 -06:00
}
2016-01-21 09:46:38 +02:00
2016-11-07 09:54:10 -07:00
if ( $result ) {
2017-01-11 20:05:07 -07:00
$json_response = [
2016-11-07 09:54:10 -07:00
'status' => 'success' ,
'dependencies' => $dependencies ,
'message' => $this -> admin -> translate ( is_string ( $result ) ? $result : 'PLUGIN_ADMIN.UNINSTALL_SUCCESSFUL' )
];
2017-02-26 19:36:01 +01:00
echo json_encode ( $json_response );
exit ;
2016-11-07 09:54:10 -07:00
}
2018-05-10 10:14:18 +03:00
$json_response = [
'status' => 'error' ,
'message' => $this -> admin -> translate ( 'PLUGIN_ADMIN.UNINSTALL_FAILED' )
];
echo json_encode ( $json_response );
exit ;
2015-07-29 14:04:06 -06:00
}
2017-02-19 19:16:03 +01:00
/**
* Handle reinstalling a package
*/
protected function taskReinstallPackage ()
{
2017-02-26 20:09:50 +01:00
$data = $this -> post ;
$slug = isset ( $data [ 'slug' ]) ? $data [ 'slug' ] : '' ;
$type = isset ( $data [ 'type' ]) ? $data [ 'type' ] : '' ;
$package_name = isset ( $data [ 'package_name' ]) ? $data [ 'package_name' ] : '' ;
$current_version = isset ( $data [ 'current_version' ]) ? $data [ 'current_version' ] : '' ;
2018-07-11 15:30:11 -06:00
if ( ! $this -> authorizeTask ( 'install ' . $type , [ 'admin.' . $type , 'admin.super' ])) {
$json_response = [
'status' => 'error' ,
'message' => $this -> admin -> translate ( 'PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK' )
];
echo json_encode ( $json_response );
exit ;
}
2017-02-26 20:09:50 +01:00
$url = " https://getgrav.org/download/ { $type } s/ $slug / $current_version " ;
$result = Gpm :: directInstall ( $url );
if ( $result === true ) {
$this -> admin -> json_response = [
'status' => 'success' ,
'message' => $this -> admin -> translate ( sprintf ( $this -> admin -> translate ( 'PLUGIN_ADMIN.PACKAGE_X_REINSTALLED_SUCCESSFULLY' ,
null ), $package_name ))
];
} else {
$this -> admin -> json_response = [
'status' => 'error' ,
'message' => $this -> admin -> translate ( 'PLUGIN_ADMIN.REINSTALLATION_FAILED' )
];
}
2017-02-19 19:16:03 +01:00
}
2015-08-06 09:34:55 +02:00
/**
2016-11-07 09:54:10 -07:00
* Clear the cache .
2015-08-06 09:34:55 +02:00
*
2016-11-07 09:54:10 -07:00
* @ return bool True if the action was performed .
2015-08-06 09:34:55 +02:00
*/
2016-11-07 09:54:10 -07:00
protected function taskClearCache ()
2015-08-06 09:34:55 +02:00
{
2016-12-31 11:21:38 +01:00
if ( ! $this -> authorizeTask ( 'clear cache' , [ 'admin.cache' , 'admin.super' , 'admin.maintenance' ])) {
2015-12-18 13:42:57 -08:00
return false ;
2015-08-06 15:16:22 +02:00
}
2015-08-06 09:34:55 +02:00
2016-11-07 09:54:10 -07:00
// get optional cleartype param
$clear_type = $this -> grav [ 'uri' ] -> param ( 'cleartype' );
2016-04-29 16:23:45 +02:00
2016-11-07 09:54:10 -07:00
if ( $clear_type ) {
$clear = $clear_type ;
} else {
$clear = 'standard' ;
}
2015-08-06 09:34:55 +02:00
2016-11-07 09:54:10 -07:00
$results = Cache :: clearCache ( $clear );
if ( count ( $results ) > 0 ) {
2016-03-05 12:11:13 +01:00
$this -> admin -> json_response = [
2016-07-07 18:55:52 +02:00
'status' => 'success' ,
2017-02-26 19:36:01 +01:00
'message' => $this -> admin -> translate ( 'PLUGIN_ADMIN.CACHE_CLEARED' ) . ' <br />' . $this -> admin -> translate ( 'PLUGIN_ADMIN.METHOD' ) . ': ' . $clear . ''
2016-03-05 12:11:13 +01:00
];
2015-08-06 09:34:55 +02:00
} else {
2016-03-05 12:11:13 +01:00
$this -> admin -> json_response = [
2016-07-07 18:55:52 +02:00
'status' => 'error' ,
2016-11-07 09:54:10 -07:00
'message' => $this -> admin -> translate ( 'PLUGIN_ADMIN.ERROR_CLEARING_CACHE' )
2016-03-05 12:11:13 +01:00
];
2015-08-06 09:34:55 +02:00
}
return true ;
}
2015-04-13 21:37:12 +02:00
/**
2016-11-07 09:54:10 -07:00
* Clear the cache .
2016-04-20 18:55:58 +02:00
*
2016-11-07 09:54:10 -07:00
* @ return bool True if the action was performed .
2015-04-13 21:37:12 +02:00
*/
2016-11-07 09:54:10 -07:00
protected function taskHideNotification ()
2015-04-13 21:37:12 +02:00
{
2016-11-07 09:54:10 -07:00
if ( ! $this -> authorizeTask ( 'hide notification' , [ 'admin.login' ])) {
2016-01-21 09:46:38 +02:00
return false ;
2015-05-11 16:37:43 +02:00
}
2016-11-07 09:54:10 -07:00
$notification_id = $this -> grav [ 'uri' ] -> param ( 'notification_id' );
2015-04-13 21:37:12 +02:00
2016-11-07 09:54:10 -07:00
if ( ! $notification_id ) {
$this -> admin -> json_response = [
'status' => 'error'
];
2017-02-26 19:36:01 +01:00
2016-11-07 09:54:10 -07:00
return false ;
2015-04-13 21:37:12 +02:00
}
2017-02-26 19:36:01 +01:00
$filename = $this -> grav [ 'locator' ] -> findResource ( 'user://data/notifications/' . $this -> grav [ 'user' ] -> username . YAML_EXT ,
true , true );
2016-11-07 09:54:10 -07:00
$file = CompiledYamlFile :: instance ( $filename );
$data = $file -> content ();
$data [] = $notification_id ;
$file -> save ( $data );
$this -> admin -> json_response = [
'status' => 'success'
];
2015-04-13 21:37:12 +02:00
2015-04-04 14:49:40 +02:00
return true ;
}
2016-01-21 09:51:35 +02:00
/**
2016-11-07 09:54:10 -07:00
* Handle the backup action
2016-01-15 12:57:09 +01:00
*
2016-11-07 09:54:10 -07:00
* @ return bool True if the action was performed .
2016-01-15 12:57:09 +01:00
*/
2016-11-07 09:54:10 -07:00
protected function taskBackup ()
2016-01-15 12:57:09 +01:00
{
2016-11-07 09:54:10 -07:00
$param_sep = $this -> grav [ 'config' ] -> get ( 'system.param_sep' , ':' );
if ( ! $this -> authorizeTask ( 'backup' , [ 'admin.maintenance' , 'admin.super' ])) {
return false ;
}
2016-01-15 12:57:09 +01:00
2016-11-07 09:54:10 -07:00
$download = $this -> grav [ 'uri' ] -> param ( 'download' );
2016-01-15 12:57:09 +01:00
2016-11-07 09:54:10 -07:00
if ( $download ) {
$file = base64_decode ( urldecode ( $download ));
$backups_root_dir = $this -> grav [ 'locator' ] -> findResource ( 'backup://' , true );
2016-01-15 12:57:09 +01:00
2018-05-10 10:14:18 +03:00
if ( 0 !== strpos ( $file , $backups_root_dir )) {
2016-11-07 09:54:10 -07:00
header ( 'HTTP/1.1 401 Unauthorized' );
exit ();
2016-01-15 12:57:09 +01:00
}
2016-11-07 09:54:10 -07:00
Utils :: download ( $file , true );
2016-01-16 17:22:08 +01:00
}
2016-11-07 09:54:10 -07:00
$log = JsonFile :: instance ( $this -> grav [ 'locator' ] -> findResource ( " log://backup.log " , true , true ));
2016-06-07 23:10:34 +02:00
2016-11-07 09:54:10 -07:00
try {
2018-09-28 12:27:40 -06:00
$backup = Backups :: backup ();
2016-11-07 09:54:10 -07:00
} catch ( \Exception $e ) {
$this -> admin -> json_response = [
'status' => 'error' ,
'message' => $this -> admin -> translate ( 'PLUGIN_ADMIN.AN_ERROR_OCCURRED' ) . '. ' . $e -> getMessage ()
];
2016-06-07 23:10:34 +02:00
2016-11-07 09:54:10 -07:00
return true ;
2016-06-07 23:10:34 +02:00
}
2016-11-07 09:54:10 -07:00
$download = urlencode ( base64_encode ( $backup ));
$url = rtrim ( $this -> grav [ 'uri' ] -> rootUrl ( true ), '/' ) . '/' . trim ( $this -> admin -> base ,
'/' ) . '/task' . $param_sep . 'backup/download' . $param_sep . $download . '/admin-nonce' . $param_sep . Utils :: getNonce ( 'admin-form' );
2016-01-15 12:57:09 +01:00
2016-11-07 09:54:10 -07:00
$log -> content ([
'time' => time (),
'location' => $backup
]);
$log -> save ();
2016-01-15 12:57:09 +01:00
2016-11-07 09:54:10 -07:00
$this -> admin -> json_response = [
'status' => 'success' ,
2017-02-26 19:36:01 +01:00
'message' => $this -> admin -> translate ( 'PLUGIN_ADMIN.YOUR_BACKUP_IS_READY_FOR_DOWNLOAD' ) . '. <a href="' . $url . '" class="button">' . $this -> admin -> translate ( 'PLUGIN_ADMIN.DOWNLOAD_BACKUP' ) . '</a>' ,
2016-11-07 09:54:10 -07:00
'toastr' => [
'timeOut' => 0 ,
'extendedTimeOut' => 0 ,
'closeButton' => true
]
];
2016-01-15 12:57:09 +01:00
return true ;
}
2017-03-05 17:45:10 -07:00
protected function taskGetChildTypes ()
{
if ( ! $this -> authorizeTask ( 'get childtypes' , [ 'admin.pages' , 'admin.super' ])) {
2018-05-10 10:14:18 +03:00
return false ;
2017-03-05 17:45:10 -07:00
}
$data = $this -> post ;
$rawroute = ! empty ( $data [ 'rawroute' ]) ? $data [ 'rawroute' ] : null ;
if ( $rawroute ) {
2018-05-10 10:14:18 +03:00
/** @var Page $page */
2017-03-05 17:45:10 -07:00
$page = $this -> grav [ 'pages' ] -> dispatch ( $rawroute );
if ( $page ) {
$child_type = $page -> childType ();
if ( isset ( $child_type )) {
$this -> admin -> json_response = [
'status' => 'success' ,
'child_type' => $child_type
];
return true ;
}
}
}
$this -> admin -> json_response = [
2017-04-10 15:07:14 -06:00
'status' => 'success' ,
2017-04-12 14:09:50 +02:00
'child_type' => '' ,
'message' => $this -> admin -> translate ( 'PLUGIN_ADMIN.NO_CHILD_TYPE' )
2017-03-05 17:45:10 -07:00
];
return true ;
}
2016-02-12 10:16:28 +01:00
/**
2016-11-07 09:54:10 -07:00
* Handles filtering the page by modular / visible / routable in the pages list .
2016-01-21 09:51:35 +02:00
*/
2016-11-07 09:54:10 -07:00
protected function taskFilterPages ()
2016-01-16 16:24:38 +01:00
{
2016-11-07 09:54:10 -07:00
if ( ! $this -> authorizeTask ( 'filter pages' , [ 'admin.pages' , 'admin.super' ])) {
return ;
2016-01-16 16:24:38 +01:00
}
2016-02-04 21:05:00 +01:00
2016-11-07 09:54:10 -07:00
$data = $this -> post ;
2016-08-29 11:12:09 -07:00
2016-11-07 09:54:10 -07:00
$flags = ! empty ( $data [ 'flags' ]) ? array_map ( 'strtolower' , explode ( ',' , $data [ 'flags' ])) : [];
$queries = ! empty ( $data [ 'query' ]) ? explode ( ',' , $data [ 'query' ]) : [];
2016-10-10 13:07:34 +02:00
2016-11-07 09:54:10 -07:00
/** @var Collection $collection */
$collection = $this -> grav [ 'pages' ] -> all ();
2016-10-10 13:07:34 +02:00
2016-11-07 09:54:10 -07:00
if ( count ( $flags )) {
// Filter by state
$pageStates = [
'modular' ,
'nonmodular' ,
'visible' ,
'nonvisible' ,
'routable' ,
'nonroutable' ,
'published' ,
'nonpublished'
2016-08-29 11:12:09 -07:00
];
2016-11-07 09:54:10 -07:00
if ( count ( array_intersect ( $pageStates , $flags )) > 0 ) {
2018-05-10 10:14:18 +03:00
if ( in_array ( 'modular' , $flags , true )) {
2016-11-07 09:54:10 -07:00
$collection = $collection -> modular ();
}
2016-08-29 11:12:09 -07:00
2018-05-10 10:14:18 +03:00
if ( in_array ( 'nonmodular' , $flags , true )) {
2016-11-07 09:54:10 -07:00
$collection = $collection -> nonModular ();
}
2016-08-29 11:12:09 -07:00
2018-05-10 10:14:18 +03:00
if ( in_array ( 'visible' , $flags , true )) {
2016-11-07 09:54:10 -07:00
$collection = $collection -> visible ();
}
2016-08-29 11:12:09 -07:00
2018-05-10 10:14:18 +03:00
if ( in_array ( 'nonvisible' , $flags , true )) {
2016-11-07 09:54:10 -07:00
$collection = $collection -> nonVisible ();
}
2016-08-29 11:12:09 -07:00
2018-05-10 10:14:18 +03:00
if ( in_array ( 'routable' , $flags , true )) {
2016-11-07 09:54:10 -07:00
$collection = $collection -> routable ();
}
2016-08-29 11:12:09 -07:00
2018-05-10 10:14:18 +03:00
if ( in_array ( 'nonroutable' , $flags , true )) {
2016-11-07 09:54:10 -07:00
$collection = $collection -> nonRoutable ();
}
2016-08-29 11:12:09 -07:00
2018-05-10 10:14:18 +03:00
if ( in_array ( 'published' , $flags , true )) {
2016-11-07 09:54:10 -07:00
$collection = $collection -> published ();
}
2016-08-29 11:12:09 -07:00
2018-05-10 10:14:18 +03:00
if ( in_array ( 'nonpublished' , $flags , true )) {
2016-11-07 09:54:10 -07:00
$collection = $collection -> nonPublished ();
}
2016-08-29 11:12:09 -07:00
}
2016-11-07 09:54:10 -07:00
foreach ( $pageStates as $pageState ) {
2018-05-10 10:14:18 +03:00
if (( $pageState = array_search ( $pageState , $flags , true )) !== false ) {
2016-11-07 09:54:10 -07:00
unset ( $flags [ $pageState ]);
}
2016-08-29 11:12:09 -07:00
}
2016-11-07 09:54:10 -07:00
// Filter by page type
2018-05-10 10:14:18 +03:00
if ( $flags ) {
2016-11-07 09:54:10 -07:00
$types = [];
2016-08-29 11:12:09 -07:00
2016-11-07 09:54:10 -07:00
$pageTypes = array_keys ( Pages :: pageTypes ());
foreach ( $pageTypes as $pageType ) {
if (( $pageKey = array_search ( $pageType , $flags )) !== false ) {
$types [] = $pageType ;
unset ( $flags [ $pageKey ]);
}
}
2016-08-29 11:12:09 -07:00
2016-11-07 09:54:10 -07:00
if ( count ( $types )) {
$collection = $collection -> ofOneOfTheseTypes ( $types );
}
}
2016-08-29 11:12:09 -07:00
2016-11-07 09:54:10 -07:00
// Filter by page type
2018-05-10 10:14:18 +03:00
if ( $flags ) {
2016-11-07 09:54:10 -07:00
$accessLevels = $flags ;
$collection = $collection -> ofOneOfTheseAccessLevels ( $accessLevels );
}
2016-08-29 11:12:09 -07:00
}
2016-11-07 09:54:10 -07:00
if ( ! empty ( $queries )) {
foreach ( $collection as $page ) {
foreach ( $queries as $query ) {
$query = trim ( $query );
2017-02-26 19:36:01 +01:00
if ( stripos ( $page -> getRawContent (), $query ) === false && stripos ( $page -> title (),
2017-08-03 01:04:59 +02:00
$query ) === false && stripos ( $page -> slug (), \Grav\Plugin\Admin\Utils :: slug ( $query )) === false && stripos ( $page -> folder (),
2016-11-07 09:54:10 -07:00
$query ) === false
) {
$collection -> remove ( $page );
}
}
2016-08-29 11:12:09 -07:00
}
}
2016-11-07 09:54:10 -07:00
$results = [];
foreach ( $collection as $path => $page ) {
$results [] = $page -> route ();
}
2016-08-29 11:12:09 -07:00
$this -> admin -> json_response = [
2016-11-07 09:54:10 -07:00
'status' => 'success' ,
'message' => $this -> admin -> translate ( 'PLUGIN_ADMIN.PAGES_FILTERED' ),
'results' => $results
2016-08-29 11:12:09 -07:00
];
2016-11-07 09:54:10 -07:00
$this -> admin -> collection = $collection ;
2016-08-29 11:12:09 -07:00
}
2016-09-02 18:29:47 +02:00
2016-08-29 11:12:09 -07:00
/**
2016-11-07 09:54:10 -07:00
* Determines the file types allowed to be uploaded
2016-08-29 11:12:09 -07:00
*
* @ return bool True if the action was performed .
*/
2016-11-07 09:54:10 -07:00
protected function taskListmedia ()
2016-08-29 11:12:09 -07:00
{
2016-11-07 09:54:10 -07:00
if ( ! $this -> authorizeTask ( 'list media' , [ 'admin.pages' , 'admin.super' ])) {
2016-08-29 11:12:09 -07:00
return false ;
}
2018-05-08 13:11:41 +03:00
$media = $this -> getMedia ();
if ( ! $media ) {
2016-11-07 09:54:10 -07:00
$this -> admin -> json_response = [
2018-05-08 13:11:41 +03:00
'status' => 'error' ,
2016-11-07 09:54:10 -07:00
'message' => $this -> admin -> translate ( 'PLUGIN_ADMIN.NO_PAGE_FOUND' )
];
2016-08-29 11:12:09 -07:00
2016-11-07 09:54:10 -07:00
return false ;
2016-08-29 11:12:09 -07:00
}
2016-11-07 09:54:10 -07:00
$media_list = [];
2018-05-10 10:14:18 +03:00
/**
* @ var string $name
* @ var Medium $medium
*/
2016-11-07 09:54:10 -07:00
foreach ( $media -> all () as $name => $medium ) {
2017-06-02 16:28:52 +02:00
$metadata = [];
2017-11-28 12:54:02 -07:00
$img_metadata = $medium -> metadata ();
if ( $img_metadata ) {
$metadata = $img_metadata ;
2017-06-02 16:28:52 +02:00
}
2017-06-21 15:44:16 -06:00
// Get original name
$source = $medium -> higherQualityAlternative ();
2017-06-02 16:28:52 +02:00
2017-06-21 15:44:16 -06:00
$media_list [ $name ] = [ 'url' => $medium -> display ( $medium -> get ( 'extension' ) === 'svg' ? 'source' : 'thumbnail' ) -> cropZoom ( 400 , 300 ) -> url (), 'size' => $medium -> get ( 'size' ), 'metadata' => $metadata , 'original' => $source -> get ( 'filename' )];
2016-08-29 11:12:09 -07:00
}
2017-11-28 12:54:02 -07:00
2016-11-07 09:54:10 -07:00
$this -> admin -> json_response = [ 'status' => 'success' , 'results' => $media_list ];
2016-08-29 11:12:09 -07:00
return true ;
}
2018-05-08 13:11:41 +03:00
/**
2018-05-10 10:14:18 +03:00
* @ return Media
2018-05-08 13:11:41 +03:00
*/
protected function getMedia ()
{
$this -> uri = $this -> uri ? : $this -> grav [ 'uri' ];
$uri = $this -> uri -> post ( 'uri' );
2018-06-01 10:03:40 -07:00
$order = $this -> uri -> post ( 'order' ) ? : null ;
2018-05-31 20:00:43 +03:00
2018-05-08 13:11:41 +03:00
if ( $uri ) {
/** @var UniformResourceLocator $locator */
$locator = $this -> grav [ 'locator' ];
$media_path = $locator -> isStream ( $uri ) ? $uri : null ;
} else {
$page = $this -> admin -> page ( true );
$media_path = $page ? $page -> path () : null ;
}
2018-05-31 20:00:43 +03:00
if ( $order ) {
$order = array_map ( 'trim' , explode ( ',' , $order ));
}
2018-05-08 13:11:41 +03:00
2018-05-31 20:00:43 +03:00
return $media_path ? new Media ( $media_path , $order ) : null ;
2018-05-08 13:11:41 +03:00
}
2014-08-05 13:06:38 -07:00
/**
2016-11-07 09:54:10 -07:00
* Handles adding a media file to a page
2014-08-05 13:06:38 -07:00
*
* @ return bool True if the action was performed .
*/
2016-11-07 09:54:10 -07:00
protected function taskAddmedia ()
2014-08-05 13:06:38 -07:00
{
2016-11-07 09:54:10 -07:00
if ( ! $this -> authorizeTask ( 'add media' , [ 'admin.pages' , 'admin.super' ])) {
2016-01-21 09:46:38 +02:00
return false ;
2015-05-11 16:37:43 +02:00
}
2016-11-07 09:54:10 -07:00
/** @var Config $config */
2016-01-21 09:46:38 +02:00
$config = $this -> grav [ 'config' ];
2016-11-07 09:54:10 -07:00
if ( ! isset ( $_FILES [ 'file' ][ 'error' ]) || is_array ( $_FILES [ 'file' ][ 'error' ])) {
$this -> admin -> json_response = [
'status' => 'error' ,
'message' => $this -> admin -> translate ( 'PLUGIN_ADMIN.INVALID_PARAMETERS' )
];
2015-08-20 15:17:45 +02:00
2016-11-07 09:54:10 -07:00
return false ;
}
2016-02-27 07:54:17 +00:00
2016-11-07 09:54:10 -07:00
// Check $_FILES['file']['error'] value.
switch ( $_FILES [ 'file' ][ 'error' ]) {
case UPLOAD_ERR_OK :
break ;
case UPLOAD_ERR_NO_FILE :
$this -> admin -> json_response = [
'status' => 'error' ,
'message' => $this -> admin -> translate ( 'PLUGIN_ADMIN.NO_FILES_SENT' )
];
2016-03-05 12:11:13 +01:00
2016-01-16 16:24:38 +01:00
return false ;
2016-11-07 09:54:10 -07:00
case UPLOAD_ERR_INI_SIZE :
case UPLOAD_ERR_FORM_SIZE :
$this -> admin -> json_response = [
'status' => 'error' ,
'message' => $this -> admin -> translate ( 'PLUGIN_ADMIN.EXCEEDED_FILESIZE_LIMIT' )
];
2016-07-07 18:55:52 +02:00
2016-05-05 10:35:40 -06:00
return false ;
2016-11-07 09:54:10 -07:00
case UPLOAD_ERR_NO_TMP_DIR :
$this -> admin -> json_response = [
'status' => 'error' ,
'message' => $this -> admin -> translate ( 'PLUGIN_ADMIN.UPLOAD_ERR_NO_TMP_DIR' )
];
2016-07-07 18:55:52 +02:00
2016-05-05 10:35:40 -06:00
return false ;
2016-11-07 09:54:10 -07:00
default :
$this -> admin -> json_response = [
'status' => 'error' ,
'message' => $this -> admin -> translate ( 'PLUGIN_ADMIN.UNKNOWN_ERRORS' )
];
2016-05-17 16:46:00 -06:00
2016-11-07 09:54:10 -07:00
return false ;
2015-08-05 18:10:15 -06:00
}
2015-08-05 15:30:30 -06:00
2016-11-07 09:54:10 -07:00
$grav_limit = $config -> get ( 'system.media.upload_limit' , 0 );
// You should also check filesize here.
if ( $grav_limit > 0 && $_FILES [ 'file' ][ 'size' ] > $grav_limit ) {
$this -> admin -> json_response = [
'status' => 'error' ,
'message' => $this -> admin -> translate ( 'PLUGIN_ADMIN.EXCEEDED_GRAV_FILESIZE_LIMIT' )
];
2016-08-29 11:12:09 -07:00
2016-11-07 09:54:10 -07:00
return false ;
2016-08-29 11:12:09 -07:00
}
2014-08-05 13:06:38 -07:00
2016-11-07 09:54:10 -07:00
// Check extension
$fileParts = pathinfo ( $_FILES [ 'file' ][ 'name' ]);
2015-04-11 16:01:27 +02:00
2016-11-07 09:54:10 -07:00
$fileExt = '' ;
if ( isset ( $fileParts [ 'extension' ])) {
$fileExt = strtolower ( $fileParts [ 'extension' ]);
2014-10-07 12:12:21 +03:00
}
2016-11-07 09:54:10 -07:00
// If not a supported type, return
if ( ! $fileExt || ! $config -> get ( " media.types. { $fileExt } " )) {
$this -> admin -> json_response = [
'status' => 'error' ,
'message' => $this -> admin -> translate ( 'PLUGIN_ADMIN.UNSUPPORTED_FILE_TYPE' ) . ': ' . $fileExt
];
2015-08-26 10:25:14 +02:00
2016-11-07 09:54:10 -07:00
return false ;
}
2015-12-29 19:31:02 +01:00
2018-05-08 13:11:41 +03:00
$media = $this -> getMedia ();
if ( ! $media ) {
$this -> admin -> json_response = [
'status' => 'error' ,
'message' => $this -> admin -> translate ( 'PLUGIN_ADMIN.NO_PAGE_FOUND' )
];
return false ;
}
2018-05-22 10:58:35 +03:00
/** @var UniformResourceLocator $locator */
$locator = $this -> grav [ 'locator' ];
$path = $media -> path ();
if ( $locator -> isStream ( $path )) {
$path = $locator -> findResource ( $path , true , true );
}
2016-11-07 09:54:10 -07:00
// Upload it
if ( ! move_uploaded_file ( $_FILES [ 'file' ][ 'tmp_name' ],
2018-05-22 10:58:35 +03:00
sprintf ( '%s/%s' , $path , $_FILES [ 'file' ][ 'name' ]))
2016-11-07 09:54:10 -07:00
) {
$this -> admin -> json_response = [
'status' => 'error' ,
'message' => $this -> admin -> translate ( 'PLUGIN_ADMIN.FAILED_TO_MOVE_UPLOADED_FILE' )
];
2015-12-29 19:31:02 +01:00
2016-11-07 09:54:10 -07:00
return false ;
2014-08-05 13:06:38 -07:00
}
2017-06-02 16:28:52 +02:00
// Add metadata if needed
$include_metadata = Grav :: instance ()[ 'config' ] -> get ( 'system.media.auto_metadata_exif' , false );
$filename = $fileParts [ 'basename' ];
$filename = str_replace ([ '@3x' , '@2x' ], '' , $filename );
$metadata = [];
if ( $include_metadata && isset ( $media [ $filename ])) {
$img_metadata = $media [ $filename ] -> metadata ();
if ( $img_metadata ) {
$metadata = $img_metadata ;
}
}
2017-05-12 12:54:08 -06:00
2018-05-08 13:11:41 +03:00
$page = $this -> admin -> page ( true );
if ( $page ) {
$this -> grav -> fireEvent ( 'onAdminAfterAddMedia' , new Event ([ 'page' => $page ]));
}
2016-12-07 05:46:43 -07:00
2016-11-07 09:54:10 -07:00
$this -> admin -> json_response = [
'status' => 'success' ,
2017-06-02 16:28:52 +02:00
'message' => $this -> admin -> translate ( 'PLUGIN_ADMIN.FILE_UPLOADED_SUCCESSFULLY' ),
'metadata' => $metadata ,
2016-11-07 09:54:10 -07:00
];
2014-08-05 13:06:38 -07:00
return true ;
}
/**
2016-11-07 09:54:10 -07:00
* Handles deleting a media file from a page
2014-08-05 13:06:38 -07:00
*
* @ return bool True if the action was performed .
*/
2016-11-07 09:54:10 -07:00
protected function taskDelmedia ()
2014-08-05 13:06:38 -07:00
{
2016-11-07 09:54:10 -07:00
if ( ! $this -> authorizeTask ( 'delete media' , [ 'admin.pages' , 'admin.super' ])) {
return false ;
}
2016-04-27 19:48:16 +02:00
2018-05-08 13:11:41 +03:00
$media = $this -> getMedia ();
if ( ! $media ) {
2016-11-07 09:54:10 -07:00
$this -> admin -> json_response = [
'status' => 'error' ,
'message' => $this -> admin -> translate ( 'PLUGIN_ADMIN.NO_PAGE_FOUND' )
];
return false ;
2014-10-10 15:25:07 +03:00
}
2016-11-07 09:54:10 -07:00
$filename = ! empty ( $this -> post [ 'filename' ]) ? $this -> post [ 'filename' ] : null ;
2016-03-05 12:11:13 +01:00
2016-11-07 09:54:10 -07:00
if ( ! $filename ) {
$this -> admin -> json_response = [
'status' => 'error' ,
'message' => $this -> admin -> translate ( 'PLUGIN_ADMIN.NO_FILE_FOUND' )
];
2015-10-20 16:36:39 +02:00
2014-08-05 13:06:38 -07:00
return false ;
}
2018-05-23 13:01:58 +03:00
/** @var UniformResourceLocator $locator */
$locator = $this -> grav [ 'locator' ];
2018-05-08 13:11:41 +03:00
$targetPath = $media -> path () . '/' . $filename ;
2018-05-23 13:01:58 +03:00
if ( $locator -> isStream ( $targetPath )) {
$targetPath = $locator -> findResource ( $targetPath , true , true );
}
2017-02-26 19:36:01 +01:00
$fileParts = pathinfo ( $filename );
2016-11-07 09:54:10 -07:00
2017-02-06 18:03:14 +01:00
$found = false ;
2016-11-07 09:54:10 -07:00
2017-02-06 18:03:14 +01:00
if ( file_exists ( $targetPath )) {
2017-02-26 19:36:01 +01:00
$found = true ;
2017-02-06 18:03:14 +01:00
$result = unlink ( $targetPath );
if ( ! $result ) {
$this -> admin -> json_response = [
'status' => 'error' ,
'message' => $this -> admin -> translate ( 'PLUGIN_ADMIN.FILE_COULD_NOT_BE_DELETED' ) . ': ' . $filename
];
return false ;
}
2014-10-10 11:57:57 +03:00
}
2014-08-05 13:06:38 -07:00
2017-05-12 12:54:08 -06:00
// Remove Extra Files
2018-05-08 13:11:41 +03:00
foreach ( scandir ( $media -> path (), SCANDIR_SORT_NONE ) as $file ) {
2017-06-02 16:28:52 +02:00
if ( preg_match ( " / { $fileParts [ 'filename' ] } @ \ d+x \ . { $fileParts [ 'extension' ] } (?: \ .meta \ .yaml)? $ | { $filename } \ .meta \ .yaml $ / " , $file )) {
2018-07-18 05:25:20 -06:00
$targetPath = $media -> path () . '/' . $file ;
if ( $locator -> isStream ( $targetPath )) {
$targetPath = $locator -> findResource ( $targetPath , true , true );
}
$result = unlink ( $targetPath );
2017-02-06 18:03:14 +01:00
if ( ! $result ) {
$this -> admin -> json_response = [
'status' => 'error' ,
'message' => $this -> admin -> translate ( 'PLUGIN_ADMIN.FILE_COULD_NOT_BE_DELETED' ) . ': ' . $filename
];
return false ;
}
$found = true ;
}
}
if ( ! $found ) {
2016-11-07 09:54:10 -07:00
$this -> admin -> json_response = [
'status' => 'error' ,
2017-02-06 18:03:14 +01:00
'message' => $this -> admin -> translate ( 'PLUGIN_ADMIN.FILE_NOT_FOUND' ) . ': ' . $filename
2016-11-07 09:54:10 -07:00
];
2015-10-01 15:33:33 +02:00
2016-11-07 09:54:10 -07:00
return false ;
}
2018-05-08 13:11:41 +03:00
$page = $this -> admin -> page ( true );
if ( $page ) {
$this -> grav -> fireEvent ( 'onAdminAfterDelMedia' , new Event ([ 'page' => $page ]));
}
2016-12-07 05:46:43 -07:00
2016-11-07 09:54:10 -07:00
$this -> admin -> json_response = [
'status' => 'success' ,
'message' => $this -> admin -> translate ( 'PLUGIN_ADMIN.FILE_DELETED' ) . ': ' . $filename
];
2014-08-05 13:06:38 -07:00
return true ;
}
2016-06-07 23:10:34 +02:00
/**
2016-11-07 09:54:10 -07:00
* Process the page Markdown
2016-06-07 23:10:34 +02:00
*
2016-11-07 09:54:10 -07:00
* @ return bool True if the action was performed .
2016-06-07 23:10:34 +02:00
*/
2016-11-07 09:54:10 -07:00
protected function taskProcessMarkdown ()
2016-06-07 23:10:34 +02:00
{
2018-07-11 15:30:11 -06:00
if ( ! $this -> authorizeTask ( 'process markdown' , [ 'admin.pages' , 'admin.super' ])) {
2016-11-07 09:54:10 -07:00
return ;
2018-07-11 15:30:11 -06:00
}
2016-06-07 23:10:34 +02:00
2016-11-07 09:54:10 -07:00
try {
$page = $this -> admin -> page ( true );
2016-07-07 18:55:52 +02:00
2016-11-07 09:54:10 -07:00
if ( ! $page ) {
$this -> admin -> json_response = [
'status' => 'error' ,
'message' => $this -> admin -> translate ( 'PLUGIN_ADMIN.NO_PAGE_FOUND' )
];
2016-06-07 23:10:34 +02:00
2016-11-07 09:54:10 -07:00
return false ;
}
2016-07-07 18:55:52 +02:00
2016-11-07 09:54:10 -07:00
$this -> preparePage ( $page , true );
$page -> header ();
2018-06-20 23:37:58 +01:00
$page -> templateFormat ( 'html' );
2016-07-07 18:55:52 +02:00
2016-11-07 09:54:10 -07:00
// Add theme template paths to Twig loader
$template_paths = $this -> grav [ 'locator' ] -> findResources ( 'theme://templates' );
$this -> grav [ 'twig' ] -> twig -> getLoader () -> addLoader ( new \Twig_Loader_Filesystem ( $template_paths ));
2016-06-07 23:10:34 +02:00
2016-11-07 09:54:10 -07:00
$html = $page -> content ();
2016-07-07 18:55:52 +02:00
2016-11-07 09:54:10 -07:00
$this -> admin -> json_response = [ 'status' => 'success' , 'preview' => $html ];
} catch ( \Exception $e ) {
$this -> admin -> json_response = [ 'status' => 'error' , 'message' => $e -> getMessage ()];
2016-07-07 18:55:52 +02:00
2016-11-07 09:54:10 -07:00
return false ;
}
2016-06-07 23:10:34 +02:00
2016-11-07 09:54:10 -07:00
return true ;
}
2016-06-07 23:10:34 +02:00
2016-11-07 09:54:10 -07:00
/**
* Prepare a page to be stored : update its folder , name , template , header and content
*
* @ param \Grav\Common\Page\Page $page
* @ param bool $clean_header
* @ param string $language
*/
protected function preparePage ( Page $page , $clean_header = false , $language = '' )
{
$input = ( array ) $this -> data ;
2016-06-07 23:10:34 +02:00
2018-05-10 10:14:18 +03:00
if ( isset ( $input [ 'folder' ]) && $input [ 'folder' ] !== $page -> value ( 'folder' )) {
2017-03-21 20:19:35 -06:00
$order = $page -> value ( 'order' );
$ordering = $order ? sprintf ( '%02d.' , $order ) : '' ;
$page -> folder ( $ordering . $input [ 'folder' ]);
}
2016-11-07 09:54:10 -07:00
if ( isset ( $input [ 'name' ]) && ! empty ( $input [ 'name' ])) {
2018-05-10 10:14:18 +03:00
$type = strtolower ( $input [ 'name' ]);
2016-11-07 09:54:10 -07:00
$name = preg_replace ( '|.*/|' , '' , $type );
if ( $language ) {
$name .= '.' . $language ;
} else {
$language = $this -> grav [ 'language' ];
if ( $language -> enabled ()) {
$name .= '.' . $language -> getLanguage ();
}
}
$name .= '.md' ;
$page -> name ( $name );
$page -> template ( $type );
}
// Special case for Expert mode: build the raw, unset content
2018-05-10 10:14:18 +03:00
if ( isset ( $input [ 'frontmatter' ], $input [ 'content' ])) {
2016-11-07 09:54:10 -07:00
$page -> raw ( " --- \n " . ( string ) $input [ 'frontmatter' ] . " \n --- \n " . ( string ) $input [ 'content' ]);
unset ( $input [ 'content' ]);
2018-03-08 18:07:07 -07:00
// Handle header normally
} elseif ( isset ( $input [ 'header' ])) {
2016-11-07 09:54:10 -07:00
$header = $input [ 'header' ];
foreach ( $header as $key => $value ) {
2018-05-10 10:14:18 +03:00
if ( $key === 'metadata' && is_array ( $header [ $key ])) {
2016-11-07 09:54:10 -07:00
foreach ( $header [ 'metadata' ] as $key2 => $value2 ) {
if ( isset ( $input [ 'toggleable_header' ][ 'metadata' ][ $key2 ]) && ! $input [ 'toggleable_header' ][ 'metadata' ][ $key2 ]) {
$header [ 'metadata' ][ $key2 ] = '' ;
}
}
2018-05-10 10:14:18 +03:00
} elseif ( $key === 'taxonomy' && is_array ( $header [ $key ])) {
2016-11-07 09:54:10 -07:00
foreach ( $header [ $key ] as $taxkey => $taxonomy ) {
if ( is_array ( $taxonomy ) && count ( $taxonomy ) == 1 && trim ( $taxonomy [ 0 ]) == '' ) {
unset ( $header [ $key ][ $taxkey ]);
}
}
} else {
if ( isset ( $input [ 'toggleable_header' ][ $key ]) && ! $input [ 'toggleable_header' ][ $key ]) {
$header [ $key ] = null ;
}
}
}
if ( $clean_header ) {
$header = Utils :: arrayFilterRecursive ( $header , function ( $k , $v ) {
2018-05-10 10:14:18 +03:00
return ! ( null === $v || $v === '' );
2016-11-07 09:54:10 -07:00
});
}
$page -> header (( object ) $header );
2018-03-08 17:11:10 -07:00
$page -> frontmatter ( Yaml :: dump (( array ) $page -> header ()), 20 );
2016-11-07 09:54:10 -07:00
}
// Fill content last because it also renders the output.
if ( isset ( $input [ 'content' ])) {
$page -> rawMarkdown (( string ) $input [ 'content' ]);
}
2016-06-07 23:10:34 +02:00
}
2014-08-05 13:06:38 -07:00
/**
* Save page as a new copy .
*
* @ return bool True if the action was performed .
* @ throws \RuntimeException
*/
protected function taskCopy ()
{
2015-09-11 15:00:03 +02:00
if ( ! $this -> authorizeTask ( 'copy page' , [ 'admin.pages' , 'admin.super' ])) {
2016-01-21 09:46:38 +02:00
return false ;
2015-05-11 16:37:43 +02:00
}
2014-08-05 13:06:38 -07:00
// Only applies to pages.
2018-05-10 10:14:18 +03:00
if ( $this -> view !== 'pages' ) {
2014-08-05 13:06:38 -07:00
return false ;
}
try {
2016-01-21 09:46:38 +02:00
/** @var Pages $pages */
2014-08-29 11:27:53 +03:00
$pages = $this -> grav [ 'pages' ];
2014-08-05 13:06:38 -07:00
2016-06-07 23:10:34 +02:00
// Get the current page.
2016-06-15 13:55:13 +02:00
$original_page = $this -> admin -> page ( true );
2015-08-03 17:07:12 +02:00
// Find new parent page in order to build the path.
2016-06-15 13:55:13 +02:00
$parent = $original_page -> parent () ? : $pages -> root ();
2014-08-05 13:06:38 -07:00
// Make a copy of the current page and fill the updated information into it.
2016-06-15 13:55:13 +02:00
$page = $original_page -> copy ( $parent );
2016-06-07 23:10:34 +02:00
2016-11-07 09:54:10 -07:00
$order = 0 ;
2016-06-07 23:10:34 +02:00
if ( $page -> order ()) {
$order = $this -> getNextOrderInFolder ( $page -> parent () -> path ());
}
2015-04-27 17:43:58 +02:00
// Make sure the header is loaded in case content was set through raw() (expert mode)
$page -> header ();
2016-06-07 23:10:34 +02:00
if ( $page -> order ()) {
$page -> order ( $order );
2014-08-05 13:06:38 -07:00
}
2016-06-07 23:10:34 +02:00
$folder = $this -> findFirstAvailable ( 'folder' , $page );
2016-11-07 09:54:10 -07:00
$slug = $this -> findFirstAvailable ( 'slug' , $page );
2016-06-07 23:10:34 +02:00
$page -> path ( $page -> parent () -> path () . DS . $page -> order () . $folder );
$page -> route ( $page -> parent () -> route () . '/' . $slug );
$page -> rawRoute ( $page -> parent () -> rawRoute () . '/' . $slug );
2016-11-07 09:54:10 -07:00
// Append progressive number to the copied page title
$match = preg_split ( '/(\d+)(?!.*\d)/' , $original_page -> title (), 2 , PREG_SPLIT_DELIM_CAPTURE );
2016-06-15 13:55:13 +02:00
$header = $page -> header ();
if ( ! isset ( $match [ 1 ])) {
$header -> title = $match [ 0 ] . ' 2' ;
} else {
$header -> title = $match [ 0 ] . (( int ) $match [ 1 ] + 1 );
}
2016-06-21 15:38:34 +02:00
2016-06-15 13:55:13 +02:00
$page -> header ( $header );
2016-06-07 23:10:34 +02:00
$page -> save ( false );
2016-11-07 09:54:10 -07:00
$redirect = $this -> view . $page -> rawRoute ();
$header = $page -> header ();
if ( isset ( $header -> slug )) {
$match = preg_split ( '/-(\d+)$/' , $header -> slug , 2 , PREG_SPLIT_DELIM_CAPTURE );
$header -> slug = $match [ 0 ] . '-' . ( isset ( $match [ 1 ]) ? ( int ) $match [ 1 ] + 1 : 2 );
}
$page -> header ( $header );
$page -> save ();
2016-12-07 05:46:43 -07:00
$this -> grav -> fireEvent ( 'onAdminAfterSave' , new Event ([ 'page' => $page ]));
2016-11-07 09:54:10 -07:00
// Enqueue message and redirect to new location.
$this -> admin -> setMessage ( $this -> admin -> translate ( 'PLUGIN_ADMIN.SUCCESSFULLY_COPIED' ), 'info' );
$this -> setRedirect ( $redirect );
} catch ( \Exception $e ) {
throw new \RuntimeException ( 'Copying page failed on error: ' . $e -> getMessage ());
}
return true ;
}
/**
* Find the first available $item ( 'slug' | 'folder' ) for a page
* Used when copying a page , to determine the first available slot
*
* @ param string $item
* @ param Page $page
*
* @ return string The first available slot
*/
protected function findFirstAvailable ( $item , $page )
{
if ( ! $page -> parent () -> children ()) {
return $page -> $item ();
}
$withoutPrefix = function ( $string ) {
$match = preg_split ( '/^[0-9]+\./u' , $string , 2 , PREG_SPLIT_DELIM_CAPTURE );
return isset ( $match [ 1 ]) ? $match [ 1 ] : $match [ 0 ];
};
$withoutPostfix = function ( $string ) {
$match = preg_split ( '/-(\d+)$/' , $string , 2 , PREG_SPLIT_DELIM_CAPTURE );
return $match [ 0 ];
};
/* $appendedNumber = function ( $string ) {
$match = preg_split ( '/-(\d+)$/' , $string , 2 , PREG_SPLIT_DELIM_CAPTURE );
$append = ( isset ( $match [ 1 ]) ? ( int ) $match [ 1 ] + 1 : 2 );
return $append ;
}; */
$highest = 1 ;
$siblings = $page -> parent () -> children ();
$findCorrectAppendedNumber = function ( $item , $page_item , $highest ) use (
$siblings ,
& $findCorrectAppendedNumber ,
& $withoutPrefix
) {
foreach ( $siblings as $sibling ) {
if ( $withoutPrefix ( $sibling -> $item ()) == ( $highest === 1 ? $page_item : $page_item . '-' . $highest )) {
$highest = $findCorrectAppendedNumber ( $item , $page_item , $highest + 1 );
2014-08-05 13:06:38 -07:00
2016-11-07 09:54:10 -07:00
return $highest ;
}
2016-06-07 23:10:34 +02:00
}
2016-06-21 15:38:34 +02:00
2016-11-07 09:54:10 -07:00
return $highest ;
};
2016-06-07 23:10:34 +02:00
2016-11-07 09:54:10 -07:00
$base = $withoutPrefix ( $withoutPostfix ( $page -> $item ()));
2014-08-05 13:06:38 -07:00
2016-11-07 09:54:10 -07:00
$return = $base ;
$highest = $findCorrectAppendedNumber ( $item , $base , $highest );
if ( $highest > 1 ) {
$return .= '-' . $highest ;
2014-08-05 13:06:38 -07:00
}
2016-11-07 09:54:10 -07:00
return $return ;
2014-08-05 13:06:38 -07:00
}
/**
* Reorder pages .
*
* @ return bool True if the action was performed .
*/
protected function taskReorder ()
{
2015-09-11 15:00:03 +02:00
if ( ! $this -> authorizeTask ( 'reorder pages' , [ 'admin.pages' , 'admin.super' ])) {
2016-01-21 09:46:38 +02:00
return false ;
2015-05-11 16:37:43 +02:00
}
2014-08-05 13:06:38 -07:00
// Only applies to pages.
2018-05-10 10:14:18 +03:00
if ( $this -> view !== 'pages' ) {
2014-08-05 13:06:38 -07:00
return false ;
}
2015-08-17 10:26:35 +02:00
$this -> admin -> setMessage ( $this -> admin -> translate ( 'PLUGIN_ADMIN.REORDERING_WAS_SUCCESSFUL' ), 'info' );
2016-03-05 12:11:13 +01:00
2014-08-05 13:06:38 -07:00
return true ;
}
/**
* Delete page .
*
* @ return bool True if the action was performed .
* @ throws \RuntimeException
*/
protected function taskDelete ()
{
2015-09-11 15:00:03 +02:00
if ( ! $this -> authorizeTask ( 'delete page' , [ 'admin.pages' , 'admin.super' ])) {
2016-01-21 09:46:38 +02:00
return false ;
2015-05-11 16:37:43 +02:00
}
2014-08-05 13:06:38 -07:00
// Only applies to pages.
2018-05-10 10:14:18 +03:00
if ( $this -> view !== 'pages' ) {
2014-08-05 13:06:38 -07:00
return false ;
}
try {
$page = $this -> admin -> page ();
2015-08-21 15:54:08 +02:00
if ( count ( $page -> translatedLanguages ()) > 1 ) {
$page -> file () -> delete ();
} else {
Folder :: delete ( $page -> path ());
}
2016-12-07 05:46:43 -07:00
$this -> grav -> fireEvent ( 'onAdminAfterDelete' , new Event ([ 'page' => $page ]));
2016-02-12 10:16:28 +01:00
Cache :: clearCache ( 'standard' );
2015-08-05 19:11:09 -06:00
2014-09-30 17:41:45 -06:00
// Set redirect to either referrer or pages list.
2015-08-21 15:54:21 +02:00
$redirect = 'pages' ;
2014-08-05 13:06:38 -07:00
2015-08-17 10:26:35 +02:00
$this -> admin -> setMessage ( $this -> admin -> translate ( 'PLUGIN_ADMIN.SUCCESSFULLY_DELETED' ), 'info' );
2014-08-05 13:06:38 -07:00
$this -> setRedirect ( $redirect );
} catch ( \Exception $e ) {
throw new \RuntimeException ( 'Deleting page failed on error: ' . $e -> getMessage ());
}
return true ;
}
2015-08-19 17:28:39 +02:00
/**
* Switch the content language . Optionally redirect to a different page .
*
*/
2016-01-10 17:17:04 +01:00
protected function taskSwitchlanguage ()
{
2018-07-11 15:30:11 -06:00
if ( ! $this -> authorizeTask ( 'switch language' , [ 'admin.pages' , 'admin.super' ])) {
return false ;
}
2016-07-07 18:55:52 +02:00
$data = ( array ) $this -> data ;
2015-08-21 18:01:20 +02:00
if ( isset ( $data [ 'lang' ])) {
$language = $data [ 'lang' ];
} else {
$language = $this -> grav [ 'uri' ] -> param ( 'lang' );
}
if ( isset ( $data [ 'redirect' ])) {
$redirect = 'pages/' . $data [ 'redirect' ];
} else {
$redirect = 'pages' ;
}
2015-08-14 19:12:04 +02:00
if ( $language ) {
$this -> grav [ 'session' ] -> admin_lang = $language ? : 'en' ;
}
2015-08-17 10:26:35 +02:00
$this -> admin -> setMessage ( $this -> admin -> translate ( 'PLUGIN_ADMIN.SUCCESSFULLY_SWITCHED_LANGUAGE' ), 'info' );
2015-08-20 17:00:46 +02:00
2016-09-27 18:21:11 +03:00
$admin_route = $this -> admin -> base ;
2015-09-18 10:07:49 -06:00
$this -> setRedirect ( '/' . $language . $admin_route . '/' . $redirect );
2015-08-14 19:12:04 +02:00
}
2018-07-11 15:30:11 -06:00
/**
* Handle direct install .
*/
protected function taskDirectInstall ()
{
if ( ! $this -> authorizeTask ( 'install' , [ 'admin.super' ])) {
return false ;
}
$file_path = isset ( $this -> data [ 'file_path' ]) ? $this -> data [ 'file_path' ] : null ;
if ( isset ( $_FILES [ 'uploaded_file' ])) {
// Check $_FILES['file']['error'] value.
switch ( $_FILES [ 'uploaded_file' ][ 'error' ]) {
case UPLOAD_ERR_OK :
break ;
case UPLOAD_ERR_NO_FILE :
$this -> admin -> setMessage ( $this -> admin -> translate ( 'PLUGIN_ADMIN.NO_FILES_SENT' ), 'error' );
return false ;
case UPLOAD_ERR_INI_SIZE :
case UPLOAD_ERR_FORM_SIZE :
$this -> admin -> setMessage ( $this -> admin -> translate ( 'PLUGIN_ADMIN.EXCEEDED_FILESIZE_LIMIT' ), 'error' );
return false ;
case UPLOAD_ERR_NO_TMP_DIR :
$this -> admin -> setMessage ( $this -> admin -> translate ( 'PLUGIN_ADMIN.UPLOAD_ERR_NO_TMP_DIR' ), 'error' );
return false ;
default :
$this -> admin -> setMessage ( $this -> admin -> translate ( 'PLUGIN_ADMIN.UNKNOWN_ERRORS' ), 'error' );
return false ;
}
$file_path = $_FILES [ 'uploaded_file' ][ 'tmp_name' ];
}
$result = Gpm :: directInstall ( $file_path );
if ( $result === true ) {
$this -> admin -> setMessage ( $this -> admin -> translate ( 'PLUGIN_ADMIN.INSTALLATION_SUCCESSFUL' ), 'info' );
} else {
$this -> admin -> setMessage ( $this -> admin -> translate ( 'PLUGIN_ADMIN.INSTALLATION_FAILED' ) . ': ' . $result ,
'error' );
}
$this -> setRedirect ( '/tools' );
return true ;
}
2015-08-19 17:28:39 +02:00
/**
* Save the current page in a different language . Automatically switches to that language .
*
* @ return bool True if the action was performed .
*/
2016-01-10 17:17:04 +01:00
protected function taskSaveas ()
{
2015-09-11 15:00:03 +02:00
if ( ! $this -> authorizeTask ( 'save' , $this -> dataPermissions ())) {
2016-01-21 09:46:38 +02:00
return false ;
2015-08-19 17:28:39 +02:00
}
2016-11-07 09:54:10 -07:00
$data = ( array ) $this -> data ;
2015-08-19 17:28:39 +02:00
$language = $data [ 'lang' ];
if ( $language ) {
$this -> grav [ 'session' ] -> admin_lang = $language ? : 'en' ;
}
$uri = $this -> grav [ 'uri' ];
$obj = $this -> admin -> page ( $uri -> route ());
$this -> preparePage ( $obj , false , $language );
$file = $obj -> file ();
if ( $file ) {
2016-10-13 16:38:02 +02:00
$filename = $this -> determineFilenameIncludingLanguage ( $obj -> name (), $language );
2015-10-01 14:59:07 +02:00
2016-11-07 09:54:10 -07:00
$path = $obj -> path () . DS . $filename ;
2015-08-19 17:28:39 +02:00
$aFile = File :: instance ( $path );
$aFile -> save ();
2016-01-21 09:46:38 +02:00
$aPage = new Page ();
2016-03-05 12:11:13 +01:00
$aPage -> init ( new \SplFileInfo ( $path ), $language . '.md' );
2015-08-19 17:28:39 +02:00
$aPage -> header ( $obj -> header ());
$aPage -> rawMarkdown ( $obj -> rawMarkdown ());
2017-02-13 18:30:45 +01:00
$aPage -> template ( $obj -> template ());
2015-08-19 17:28:39 +02:00
$aPage -> validate ();
$aPage -> filter ();
$aPage -> save ();
2016-12-07 05:46:43 -07:00
$this -> grav -> fireEvent ( 'onAdminAfterSave' , new Event ([ 'page' => $obj ]));
2015-08-19 17:28:39 +02:00
}
$this -> admin -> setMessage ( $this -> admin -> translate ( 'PLUGIN_ADMIN.SUCCESSFULLY_SWITCHED_LANGUAGE' ), 'info' );
2015-08-20 17:00:46 +02:00
$this -> setRedirect ( '/' . $language . $uri -> route ());
2015-08-19 17:28:39 +02:00
return true ;
}
2016-10-13 16:38:02 +02:00
/**
* The what should be the new filename when saving as a new language
*
* @ param string $current_filename the current file name , including . md . Example : default . en . md
2016-11-07 09:54:10 -07:00
* @ param string $language The new language it will be saved as . Example : 'it' or 'en-GB' .
2016-10-13 16:38:02 +02:00
*
* @ return string The new filename . Example : 'default.it'
*/
public function determineFilenameIncludingLanguage ( $current_filename , $language )
{
2018-05-10 10:14:18 +03:00
$filename = substr ( $current_filename , 0 , - strlen ( '.md' ));
2016-10-13 16:38:02 +02:00
2018-05-10 10:14:18 +03:00
if ( substr ( $filename , - 3 , 1 ) === '.' ) {
2016-10-13 16:38:02 +02:00
$filename = str_replace ( substr ( $filename , - 2 ), $language , $filename );
2018-05-10 10:14:18 +03:00
} elseif ( substr ( $filename , - 6 , 1 ) === '.' ) {
2016-10-13 16:38:02 +02:00
$filename = str_replace ( substr ( $filename , - 5 ), $language , $filename );
} else {
$filename .= '.' . $language ;
}
return $filename . '.md' ;
}
2017-02-22 21:34:21 +01:00
2017-03-31 13:39:39 -06:00
2014-08-05 13:06:38 -07:00
}