SilverStripe 4 custom error page not shown - php

In my last project on SS 4, I'm trying to create my usual custom error pages - with same approach used on v. 3:
Creating ErrorPage.ss inside /themes/mysite/templates/Layout;
Including $Content inside template;
After a successful /dev/build?flush=all I don't see any content, neither right template (I see the default Page.ss one instead).
In back-end there are error pages saved and published. In /assets/ there are the static ones too.
Maybe the procedure is changed in this new version? Any advice?
Thanks in advance everyone.

Your ErrorPage.ss folder structure needs to match the core PHP class's namespace (SilverStripe\ErrorPage\ErrorPage), i.e. themes/mytheme/templates/SilverStripe/ErrorPage/Layout/ErrorPage.ss

For Silverstripe 4 ErrorPage.
To display the ErrorPage you need to match the namespace of ErrorPage into your template by adding this into your app folder. E.g.template/SilverStripe/ErrorPage/ErrorPage.ss
Don't forget to dev/build?flush afterwards

Related

Changing the behaviour of view in Codeigniter

I am using codeigniter for a project that is used by a variety of companies.
The default version of our software is up and running and works fine - however some of our customers want slightly different view files for their instance of the system.
Ideally what I would like to do is set a variable (for example VIEW_SUFFIX) and whenever a view file is loaded it would first check if there was a suffix version available if there was use that instead.
For example if the system had a standard view file called 'my_view.php' but one client had a VIEW_SUFFIX of 'client_1' - whenever I called $this->load->view('my_view') if the VIEW_SUFFIX was set it would first check if my_view_client_1 existed (and if it did use that) or if not use the default my_view.php.
I hope that my question is clear enough... If anyone has done this before or can think of a way to do it I would really appreciate it.
EDIT:
Ideally I would like a solution that works without me changing every place that I am calling the view files. Firstly because there are a few files that may want different client versions and also because the view files are called from a lot of controllers
I had a similar requirement for which I created a helper function. Among other things, this function can check for a suffix before loading the specified view file. This function can check for the suffix and check if the file exists before loading it.
Unfortunately, the file checking logic would be a bit brittle. As an alternative, you can implement a MY_Loader class that will override the basic CI_Loader class.
Something like this in your application/core/MY_Loader.php:
class MY_Loader extends CI_Loader {
protected function _ci_load($_ci_data)
{
// Copy paste code from CI with your modifications to check prefix.
}
}
Could you not do this
// some method of creating $client
// probably created at login
$_SESSION['client'] = 'client_1';
$client = (isset($_SESSION['client'])) ? $_SESSION['client'] : '';
$this->load->view("your_view{$client}", $data);

how to override files in [mysite]/concrete5/core

I want to override the guestbook functionality. To be exact, I want to override the action_form_save_entry() function on [mysite]/concrete5/core/controllers/blocks/guestbook.php
I've tried to override it these ways:
[mysite]/controllers/blocks/guestbook.php
[mysite]/core/controllers/blocks/guestbook.php
noe of them works. I can't find any way how to override that file. The documentation here and here doesn't show how to override that /core/ directory. Their forum never helps. Google result also just get misled with the 'core' keyword. All the result just take the 'core' meaning as just what's exist on the /concrete5/ directory, not the exact true /concrete5/core
Looks like that /concrete5/core/ directory appear only on the newer version. CMIIW.
Btw, maybe I should also tell you what I want to do with that function. Probably you have another workaround for this instead of simply overriding it. I want to add SMS notification functionality to it. So whenever someone submit a new comment, an SMS would be sent to the admin of a particular page.
Yes, the /concrete/core directory structure is new to 5.6. Tutorials and documentation on c5 can be ... lacking ... but in this case it's just a matter of them being behind a bit.
The "real" guestbook controller is at /concrete/blocks/guestbook/controller.php. You'll notice that it's just a shell of a class:
class GuestbookBlockController extends Concrete5_Controller_Block_Guestbook {}
The file that you referenced defines Concrete5_Controller_Block_Guestbook.
So, the solution is to override the real controller, not whatever it extends (ie, the file that you were looking at). Thinking in this way, it should be clearer that you need to create a file at /blocks/guestbook/controller.php. In fact, just copy the controller.php that I referenced above because you need to keep the (sometimes multiple) classes. Then, you can override the particular function. (Don't forget to call parent::action_save_form_entry()).

How can I get Drupal module name programmatically?

I'm working on my own module. I realize I constantly need to manually type my module name in different places. Most popular usage is with drupal_get_path($type, $name) function (I have more then 10 of these in my code). Where $name is theme or module name. During that time I need to already change my module name 3 times. As you can surmise I also need change all module names hard-coded in my project. So I thought it would be nice to have some convenient function to grab this name automatically.
How can I get machine module name programmatically?
For example if you have your module in following directory..
sites/all/modules/my_module/
..then you can grab it in this way
drupal_get_current_module_name(); // return my_module
Generally, you should know by convention - if you have: sites/all/modules/my_module/ then the machine name of the module should match the folder name - my_module.
Virtually all contributed modules follow this convention, and you should too.
It is possible to have your .info and .module file not match the name of the folder, but this isn't correct.
If you are already executing code inside your module, you should already know the machine name of the module by virtue of the name of the file you're editing - unless you're trying to do something that I'm not understanding.
Edit: Since we've determined you're just trying to call your module's theme function, you don't actually need to know the name.
If you have:
/** Implements theme_table **/
function my_really_long_module_name_table() {}
Your function might get called like this:
theme('table');
There is a little more to it than that, but the theme engine will make a determination about which theme functions get called based on what is implementing them.
It sounds like you may want to read up on some of the basics of the Drupal theme system.
Here's a good start for learning the Drupal 6 theme layer: http://drupal.org/node/165706
I figure out something like this:
function get_current_module_name() {
return array_shift(explode('.', end(explode(DIRECTORY_SEPARATOR, __FILE__))));
}
but don't know is't the best way to do it..
UPDATE:
I see now it's better to use basename
$name = basename(__FILE__, '.module');
UPDATE 2:
I think if this is needed across whole module then it could be accessible via constant defined in the very beginning of the module e.g.:
define('MODULE_NAME', basename(__FILE__, '.module'));
Then you could use all the time in all your function like this:
drupal_get_path('module', MODULE_NAME);

Modifying Zend_ViewHelper_Pagination_Controller Partial-Path

I've got a Zend-Framework application. I'm using the module-structure which Zend_Controller_Frontprovides. Here is a small excerpt from my directory-structure (only the important parts for this question):
root-directory
- modules
- blog
- views
- scripts
- index_index.phtml
- views
- pagination_control.phtml
As you can see I've got view-scripts that are specific to a module/controller/action. These views are located in the corresponding path (in this case like modules/blog/views. I've also got a more general view-directory located in the root-direcetory of my application.
What I am doing now is to call the PaginationControl-ViewHelper in modules/blog/views/scripts/index_index.phtml. This View-Helper however renders a partial-view, as you know. The ViewHelper tries to locate the partial-view within the same directory (meaning modules/blog/views/scripts. Since I want to use the same view-partial-script (pagination_control.phtml) in different modules I want to make this view-partial accessable from each module. So I want to put that file in the general views-folder in the root-directory.
However this doesn't work. The ViewHelper always looks for the view-script in the corresponding module-folder.
Anyone can help to make it accessable from my general views-directory?
As you can see here, since ZF 1.6.2 pagination control can take an array instead of a string for the partial argument, and in this array you set 1st the name of the partial and in 2nd the module name. This is still undocumented.
Using an array you can specify a module ('common'?) for the partial to use.
The real call will be (with $partial your 3rd argument to the paginationControl() view helper ):
$this->view->partial($partial[0], $partial[1], $pages);
This is usefull if you have a 'common' module.
Now here you are using a shared folder. You shoudl have installed it as a shared folder for your Zend_View this way (in a Boostrap or ressource code):
$view->addScriptPath("/root-directory/views");
or better:
$view->addScriptPath("/root-directory/views/partials");
And then you should'nt be required to specify any module directory. Zend_View should always check for a partial in this folder.

widget within module in Yii

I'm trying to create a widget within the module and then load that widget from 'outside' of the module. More particularly I'm using user module written by someone else. I don't want to have a separate page for displaying a login form, therefore I tried to make a CPortlet/widget (confusion) displaying the login form. Basically, I've moved the code from LoginController into that widget. Then I try to display the widget on some random page by
<?php $this->widget('user.components.LoginForm'); ?>
However, I get an error
CWebApplication does not have a method named "encrypting".
in UserIdentity class in this line:
else if(Yii::app()->controller->module->encrypting($this->password)!==$user->password)
This happens, because I'm basically trying to execute this code within context of the app and not the module. Thus the "Yii::app()->controller->module" trick doesn't really work as expected.
What am I doing wrong:-\
Is there a better way to achieve this. I.e. display that login form in some other page, which is normally displayed by accessing login controller within user module (user/login) or is a widget the right way of doing it?
Thanks.
The quick solution
Ok, so I simply ended up doing
Yii::app()->getModule('user')->encrypting($this->password)
instead of
Yii::app()->controller->module->encrypting($this->password)
Notice that now the module must be called 'user' in the main config, but I think this allows for more flexibility. I.e. we're not bound to only use module functionality within the module.
Additional insight on displaying widget outside of the module scope
After playing more with it that's what I did. In the UserModule.php I've created a method
public static function id() {
return 'user';
}
Then everywhere where I need the module I use
Yii::app()->getModule(UserModule::id())->encrypting($this->password)
I don't like having many imports related to the module like:
'application.modules.user.models.*',
'application.modules.user.components.*',
Because we already have those imports in the UserModule.php:
public function init()
{
// this method is called when the module is being created
// you may place code here to customize the module or the application
// import the module-level models and components
$this->setImport(array(
'user.models.*',
'user.components.*',
));
}
Therefore whenever you know that some piece of functionality will be used outside of the module it's important to make sure the module is loaded. For example, in the LoginForm widget that I am trying to display NOT in one of the module controllers, I have this line of code:
$model = new UserLogin;
However, UserLogin is a model inside of the User module, and in order to be able to autoload this model we first have to make sure the module was initialised:
$module = Yii::app()->getModule(UserModule::id());
$model = new UserLogin;
I hope this will be helpful if you were stuck with the whole modules concept the way I was.
http://www.yiiframework.com/forum/index.php?/topic/6449-access-another-modules-model/ was useful but hard to find =)
You better move that encrypting() into a MyUserIdentiy class which extends CUserIdentity. Whatever the code you take to use, they putting the method in controller is a bad idea and as a result you cannot reuse that code.
The login form should still post to User/Login controller but I guess they use Yii's standard login code and you might want to modify it to use the MyUserIdentity.

Categories