How to get object of specific page in Grav plugin - plugins

I've tried a lot of ways, but without success
For example
use Grav\Common\Page\Pages;
public function onPagesInitialized()
{
$pages = $this->grav['pages'];
print_r($pages->get('/about'));
// or
print_r($pages->find('/about', true));
}
returns nothing
The plugin of flex objects is enabled
EDITED
Adding the function onPluginsInitialized() with enabling onPagesInitialized() also doesn't help:
public function onPluginsInitialized(): void
{
$this->enable([
'onPagesInitialized' => ['onPagesInitialized', 0],
]);
}

The following is a sample of how one can get a specific page object.
When using the following folder structure: (from Blog skeleton)
user/pages
└── 01.blog
   ├── blog.md
   ├── ...
   ├── hero-classes
   │   ├── item.md
   │   └── unsplash-overcast-mountains.jpg
   ├── london-at-night
   │   ├── item.md
  │   ├── unsplash-london-night.jpg
   │   └── unsplash-xbrunel-johnson.jpg
└── ...
Assuming event 'onPagesInitialized' has been subscribed to, the following code correctly returns the sought pages:
public function onPagesInitialized(Event $event) {
/** #var Pages */
$pages = $event['pages']; // or $this->grav['pages'];
$p1 = $pages->find('/blog');
$p2 = $pages->find('/blog/london-at-night');
$p3 = $pages->find('/blog/hero-classes');
}
Note:
When the request is made by plugin Admin, pages will not be initialized. One needs to call $this->grav['admin']->enablePages(); first.
public function onPagesInitialized(Event $event) {
$this->grav['admin']->enablePages();
/** #var Pages */
$pages = $event['pages']; // or $this->grav['pages'];
$p1 = $pages->find('/blog');
$p2 = $pages->find('/blog/london-at-night');
$p3 = $pages->find('/blog/hero-classes');
}

Related

zend session namespace not working

I am unable to access zend session in included file via layout.
what i have done so far -
//bootstrap
public function _initSession()
{
Zend_Session::start();
$test = new Zend_Session_Namespace('test');
}
//controller
public function init(){
$test = new Zend_Session_Namespace('test');
$test->abc = 'defghi';
}
//layout include file
<?php include_once( APPLICATION_PATH . '/data/ga_test.php');?>
//ga_test.php
$test = new Zend_Session_Namespace('test');
echo 'this is ' . $test->abc;
I am not able to access the variable in ga_test file. I am getting an empty variable. But if I include ga_test end of each view file then it works. Obviously I don't want to go to every view file and include ga_test.php. Can I do this via layout.
I am sure, I am doing something wrong here. Any help would be really appreciated.
Thanks

execution of module bootstrap

Is there a way to have base bootstrap and module bootstrap?
this is my app structure
- application
- modules
- admin
- controllers
- Bootstrap.php
- public
- controllers
- Bootstrap.php
- Bootstrap.php
- libraries
When I test my app only the base bootstrap is executed.
I forced the execution of the modules bootstrap with this (in the base bootstrap):
$modules = array('admin', 'public');
foreach ($modules as $module) {
$path = APP_PATH . '/modules/' . $module . '/Bootstrap.php';
$class = ucfirst($module) . '_Bootstrap.php';
include_once $path;
$bootstrap = new $class($this);
$bootstrap->bootstrap();
}
Only with this I can execute bootstrap of modules.
Is there another way?
The module resource runs the module bootstraps. This is triggered by the presence of:
resources.modules[] = ""
in your application.ini, or you can manually bootstrap the modules in your main bootstrap class as you have.

Hide and show navigator menu items, buttons and anchors using ACL

I am using ACL to grant resources to roles in the system, the allowed actions is excuted and denied actions are routed to custom page, I want to show and hide menu elements at run time using resources at ACL, and also I want to show and hide anchors, buttons in views.
I make a helper class
class Zend_View_Helper_Permission extends Zend_View_Helper_Abstract
{
private $_acl;
public function hasAccess($role, $action, $controller)
{
if (!$this->_acl) {
$this->_acl = Zend_Registry::get("Acl");
}
return $this->_acl->isAllowed($role, $controller, $action);
}
}
I define the view helper in config.ini file like this
resources.view.helperPath.Zend_View_Helper = APPLICATION_PATH "/modules/privileges/views/helpers"
how can I use this helper to make views created at run time?
Your method name should match class name hence it should be permission instead of hasAccess.
I myself use a global method show() instead of using view helper
function show($action = null)
{
$request = Zend_Controller_Front::getInstance()->getRequest();
$action = $action === null ? $request->getActionName() : $action;
$module = $request->getModuleName();
$controller = $request->getControllerName();
if(!Zend_Registry::isRegistered('acl')) throw new Exception('Show function can only be called inside view after preDispatch');
$acl = Zend_Registry::get('acl');
$resource = $module . '#' . $controller;
return $acl->isAllowed(Zend_Auth::getInstance()->getIdentity(),$resource,$action);
}
To keep it simple it takes controller , module name from request object .
To hide edit action link in list action view simply doo
list.phtml code as follow
<h2>Listing page Only superadmin can see edit link</h2>
<?php if(show('edit')): ?>
Edit
<?php endif;?>
Update
The global function show was defined inside library/Util.php which was loaded inside
public/index.php
require_once 'Zend/Application.php';
require_once 'Util.php';

zend, i cant call any view helpers

i have a got a helpers folder in my views folder with a helper called Log.php
/views/helpers/log.php
which contains:
class Zend_View_Helper_Log extends Zend_View_Helper_Abstract
{
public function loggedAs ()
{
$auth = Zend_Auth::getInstance();
if ($auth->hasIdentity()) {
$username = $auth->getIdentity()->uname;
$logoutUrl = $this->view->url(array('controller'=>'auth', 'action'=>'logout'), null, true);
return 'Hello' . $username . '. Logout?';
}
}
}
how can i call this from layouts? or views? i tried $this->_helpers->log->loggedAs();
but doesnt display anything, just an error:Fatal error: Call to a member function loggedAs() on a non-object in ...
I have a little experience in ZF. Yesterday I have the same problem and I decided its with the following code.
In the main Bootstrap.php I defined helper Path and Prefix
protected function _initDoctype()
{
$this->bootstrap('view');
$view = $this->getResource('view');
$view->doctype('XHTML1_STRICT');
$view->addHelperPath(APPLICATION_PATH . "/../library/My/Helper/View", "My_Helper_View");
}
After that in view file I used next syntax
$this->getPhoneString($value['per_telephone_number']);
where getPhoneString method in my Helper Class My_Helper_View_GetPhoneString
Hope this example will be useful for you :)
Your helper class should have a method that matches the name of the helper, and this is what you call. So if you want to call loggedAs() from your templates then this is what you should name your helper:
class Zend_View_Helper_LoggedAs extends Zend_View_Helper_Abstract
{
public function loggedAs()
{
$auth = Zend_Auth::getInstance();
if ($auth->hasIdentity()) {
$username = $auth->getIdentity()->uname;
$logoutUrl = $this->view->url(array('controller'=>'auth', 'action'=>'logout'), null, true);
return 'Hello' . $username . '. Logout?';
}
}
}
this should then live in a file at application/views/helpers/LoggedAs.php, and you'd call it from within your templates like this:
<?=$this->loggedAs()?>
I'd also recommend using your own namespace instead of Zend in the class name, but the way you've done it should work as well.

Zend Layout - A "Smart" layout selector

I currently have Zend setup to look for a layout script in each module's view/scripts/layout.phtml file (ie: /application/modules/moduleName/scripts/layout.phtml). This is by setting layout[] to nothing (blank) in the application.ini file (resources.layout[] = )
The issue is that many modules may share the same layout. I don't want to copy the same exact layout into each module that uses it. I know I can set everything to use one layout script by setting a specific path like resources.layout.layoutpath = /layoutPath and everything would use /layoutpath/layout.phtml, and I know I can set individual pages (or whole Controllers, in the init) by using $this->_helper->layout->setLayout('foobaz');
The issue is that some modules will have different layouts, other than the 'standard' one, and I don't want to set it on a by Controller or by Action basis. I want to set it for the entire module, set in one place (or intuitively figured out by code/Zend automatically). Ideally, it would be setup how it is currently, but if a module doesn't have its own layout.phtml, it would use the default module's layout.
So... how do I do it?
There are several solutions, choose their own strategy
1 extending the action controller
class App_Controller_Action extends Zend_Controller_Action
{
public function init()
{
parent::init();
$moduleName = $this->getRequest()->getModuleName();
$layoutPath = APPLICATION_PATH . '/modules/' . $moduleName . '/layouts';
if (is_dir($layoutPath)) {
$this->view->addScriptPath($layoutPath);
}
}
}
and then do as usual IndexController extends App_Controller_Action ...
if layout file exists in APPLICATION_PATH . '/modules/' . $moduleName . '/layouts' directory - it will ne used instead of default layout
2 you can write frontcontroller plugin
class App_Controller_Plugin_ModuleSwitcher extends Zend_Controller_Plugin_Abstract
{
protected $_view = null;
public function routeShutdown(Zend_Controller_Request_Abstract $request)
{
$moduleName = $request->getModuleName();
Zend_Layout::startMvc();
$layout = Zend_Layout::getMvcInstance();
$layout->setLayoutPath(APPLICATION_PATH . '/modules/' . $moduleName . '/layouts')->setLayout($moduleName);
return $request;
}
}
and dont forget to google for another solutions ;)
you can set own layout selector in few steps
step 1:
make module admin and default.
step 2:
create layout folder in each module as admin/layouts/scripts
and default/layouts/scripts
put into layout.phtml
step 3:
delete the layout.phtml file from Application/layouts/scripts.
step 4:
make the the Plugin folder inside library and make Plugin.php
as
class Plugin_Layout extends Zend_Controller_Plugin_Abstract
{
public function preDispatch(Zend_Controller_Request_Abstract $request)
{
$layoutPath = APPLICATION_PATH . '/modules/' . $request->getModuleName() . '/layouts/scripts/';
Zend_Layout::getMvcInstance()->setLayoutPath($layoutPath);
}
}
step 5:
open Application/configs/Appication.ini file
and edit it
as
;resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts/"
resources.layout.layout = "layout"
;register your plugin
autoloaderNamespaces[] = "Plugin"
resources.frontController.plugins[] = "Plugin_Layout"
Step 6:
open bootstrap file Application/Bootstrap
put the code inside
protected function _initAutoload()
{
$loader = new Zend_Application_Module_Autoloader(array(
'namespace' => '',
'basePath' => APPLICATION_PATH . '/modules/'
));
return $loader;
}
protected function _initPlugins()
{
$this->bootstrap('frontcontroller');
$fc = $this->getResource('frontcontroller');
$fc->registerPlugin(new Plugin_Layout());
}
The quickest solution might be to create a symlink to point what would be a module layout file to the default layout. This won't work on Windows and is harder to maintain.
Better, create a method in your Bootstrap to set the layout.
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
public function _initLayoutScript(){
//ensure layout is setup
$this->bootstrap(array('layout', 'FrontController'));
$layout= $this->getResource('layout');
$front = $this->getResource('FrontController');
//do something with $layout and $front - set layout script/path etc based on request
//You could use file_exists to detect module layout scripts
}
}
See http://framework.zend.com/manual/en/zend.application.quick-start.html#zend.application.quick-start.resources for more details.
Finally, you could write your own application resource for use with Zend_Application.