I'm a bit confused using the Cake's (2.3) Email-Class. It appears that we are able to define a "template", a "layout" and a "theme" whereas I only understand the usage of Layouts (located in /app/View/Layouts/Emails).
It seems that everything can be defined in the Layout, but the Template seems do be necessary (at least an empty file) but I don't understand the context because to me it seems that it does not matter what I put in there.
The concept of the theme is even more nebulous to me. Maybe someone can give me a hint here. I found a discussin in a mailing-list which was not really enlightning. The documentation does not reveal this too.
http://book.cakephp.org/2.0/en/core-utility-libraries/email.html
--
Edit: Fixed confusing typo.
Edit2: CakeEmail is used directly - not the component.
template is view (in terms of ordinary pages)
layout for emails is as layout for views (in terms of ordinary pages)
layout should contain some common elements like logo and etc
and you can push data to templates like push data to view from controller
Please, check following example:
from custom EmailComponent
public function restore_password($user_to_send_restore_link) {
$email = new CakeEmail('default');
$email->emailFormat('both');
$email->template('restore_password', 'emaillayout');
$email->to(array($user_to_send_restore_link['User']['email']));
$email->from(array(GENERAL_FROM_EMAIL => 'seqrd support team'));
$subject = 'Restore password link';
$email->subject($subject);
$email_data = array(
'hash' => $user_to_send_restore_link['User']['hash']);
$email->viewVars($email_data);
return $email->send();
}
app/View/Emails/html/restore_password.ctp
<p> Please, follow link <?php echo $this->Html->link('restore password link', Router::url(array('controller' => 'users', 'action' => 'restore_password_form', $hash), true)); ?> to restore password</p>
app/View/Layouts/Emails/html/emaillayout.ctp
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<title><?php echo $title_for_layout;?></title>
</head>
<body>
<?php echo $this->fetch('content');?>
</body>
</html>
Theme it's next step of abstraction, there you can fast change whole styles of all emails, but not change code significantly.
Notes: viewVars method pass variables not only into template, but in email layout too.
Related
I want to use the same Loop and Pagination for
index.php , search.php , and archive.php
However, for search.php I want a title "Search Results" to appear before the Loop
and for archive.php I want a title "Archive Page" to appear before the Loop.
Method A
Keep index.php, search.php, and archive.php
And use get_template_part() for navigation and Loop ?
Method B
Just use index.php
but how?
Or is there a simpler method since all I want is to add a title before the Loop?
Simple code for the sake of this example:
index.php
<?php
if ( have_posts() ) : while ( have_posts() ) : the_post();
the_excerpt();
endwhile; endif;
?>
code for Pagination
search.php
<h2>Search Results</h2>
code for The Loop
code for Pagination
archive.php
<h2>Archive Page</h2>
code for The Loop
code for Pagination
I don't know the exact structure of your pages, but I would place the code in header.php. Here is my thought on this
The header is common to all of these templates, and I would suspect that you are going to need these titles between your header stuff and the content area
Target pages with conditional tags . Open your header, and right down at the bottom, add something like this
if(is_search()) {
//your title for search page etc
} elseif(is_archive()) {
//your title for archive page
} else {
//display nothing if you don't need to display any custom title
}
Just add the necessary mark up and style accordingly
EDIT
It seems that you are still very new to php. From your comment
Weird. I put <?php if(is_search()) { <h2>Search Results</h2> } ?> at very bottom of header.php but got White Screen. So instead, I put it in index.php and deleted search.php but still White Screen. I tested it in my theme and Twentytwelve. ---------- Can you help me understand... Does less php files equal to a faster website? Is reducing the amount of php files considered best practice? So if index.php , search.php , archive.php uses the same code except for a title "Search Results" and "Archive Page" - is it best practice to simply have one php file and do conditional statements for titles?
Your problem is switching between php and html elements. Whenever you switch from php to html, you need to close your php tag (?>)before your html element. On the otherhand, you need to open a new php tag (<?php) right after your last html element and before your first php element.
Not doing this correctly will lead to a synatx error, which causes a white screen of death.
So in short, your code will need to look like this for it to work properly. Note the php tags
<?php
if(is_search()) { // this part is php
?> <!-- Close php because whe're switching to html -->
<h2>Search Results</h2> <!-- this part is html -->
<?php // open new php tag as we're switching to php again
} elseif(is_archive()) { //same sequence above applied
?>
<h2>Archive Page</h2>
<?php
} else {
//display nothing if you don't need to display any custom title
}
?>
Less php files does not mean a faster website, speed is determined by content, content type, database queries, amount of queries, etc etc. A one page website can be slower than a 10 page website.
What I've done with this code and why I placed it in the header is just to keep the code together. You can split it up as you wish. There is no best practice. What really counts is readability, accesibility, not repeating code over and over, and keeping a proper file system
You could output the title before you start the loop. The contents of the loop would be called using get_template_part(). For example:
if ( have_posts() ) {
// Output the title.
the_title();
// Begin loop.
while ( have_posts() ) {
the_post();
get_template_part( 'loop', 'index' );
}
}
Update: Using just index.php to display a title conditionally, you would do this:
if ( is_search() ) {
// Display the search page title here.
} else if ( is_category() ) {
// Display the category title here.
}
Ref: http://codex.wordpress.org/Function_Reference/get_template_part
HTMLPurifier by default allows a lot of tags that I don't want to allow. According to the documentation you have to add definitions like this:
$config = HTMLPurifier_Config::createDefault();
if ($def = $config->maybeGetRawHTMLDefinition()) {
$def->addAttribute('a', 'target', new HTMLPurifier_AttrDef_Enum(array('_blank','_self','_target','_top')));
}
$purifier = new HTMLPurifier($config);
The problem is that I can't find a way to remove all tags that comes from HTMLPurifier_Config::createDefault();.
For example the HTML <div>Sometext</div> will keep the DIV tag using the above initialization code.
How can I set HTMLPurifier to only allow <strong>, <a href="*"> and <p>?
You say: "According to the documentation you have to add definitions like this".
Unless something fundamental has changed since the last time I checked the library (a year ago, about), that's not quite true - that part exists for if you want to teach HTML Purifier new attributes that it isn't natively aware of. For example, if you wanted to teach your HTML Purifier to accept non-standard <font> attributes, like align="", you'd need to alter the raw HTML definition.
However, if your whitelist consists purely of regular HTML elements (and yours does!), you just need to use the $config object:
$config = HTMLPurifier_Config::createDefault();
$config->set('HTML.AllowedElements', array(
'strong','a','p'
));
$config->set('HTML.AllowedAttributes', array(
'a.href'
));
$purifier = new HTMLPurifier($config);
That should work. Are you running into problems with that constellation?
(Check out this document, too: http://htmlpurifier.org/live/INSTALL )
The solution I found was to use the old way of configuring HTMLPurifier;
if($def = $config->maybeGetRawHTMLDefinition()) {
$config->set('HTML.AllowedElements', array(
'strong','a','p'
));
$config->set('HTML.AllowedAttributes', array(
'a.href'
));
}
How this works in relation with the HTMLDefinition I don't know. Maybe they have a compatability layer.
The biggest concern I have is that this is not using the $def variable returned - and that the changes I do to the config is not cached.
I have a module, which includes multistep form. I decided to make one of these steps work like this: free times per employee are rendered as html elements, and when element is clicked, Javascript will apply the value to hidden input field.
So I found this tutorial: http://drupal.org/node/1092122 but it didn't work for me, maybe I made a error, maybe not.
My module name is reservation. My template file is named reservation_select_time_week_page.tpl.php and its in the reservation/theme folder.
I have these functions:
function reservation_theme() {
// basic things
$module_path = drupal_get_path('module', 'reservation');
$base = array(
'path' => "$module_path/theme",
);
// define themes
return array(
'reservation_select_time_form' => $base + array(
'render element' => 'form',
'template' => 'reservation_select_time_week_page',
),
);
}
function template_preprocess_reservation_select_time_week_page(&$variables) {
echo "this works!";
}
function template_preprocess_select_time_form(&$variables) {
echo "this works!";
}
I dont know which of those preprocess functions is right (should it be named based on template name or form id?
Anyhow, custom template is not applying.
I also have tried using the:
$form['start_time'] => array('#theme' => 'reservation_select_time_week_page');
I got it working, so that the static html is rendered in template file, but I dont know how I can render the form elements in template file. Using:
drupal_render($form)
caused the form to go infinite loop I think.
Is Drupal even able to handle complex forms and form layouts?
I seem to be beaten at the very first hurdle on this one, I can't seem to get a basic "Hello world" going on in cake PHP.
in /app/Controller/MyController.php I have:
public $helpers = array('Js' => array('Jquery'), 'Html', 'Form');
public $components = array('RequestHandler');
in /app/View/Layouts/default.ctp I have:
echo $this->Html->script('//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js');
echo $this->fetch('script');
echo $this->Js->writeBuffer();
?></head>
in /app/View/My/index.ctp I have:
$this->Js->alert('HelloWorld');
but I get no alerts! If I try:
echo $this->Js->alert('HelloWorld');
it prints out to the browser: (double quotes instead of the typed single quotes!?)
alert("HelloWorld");
but not wrapped in < script > tags or even a $(document).ready(function(){});
Have I missed something out?
JsHelper is pretty useless to be honest. I don't even bother with it properly, I just include JavaScript in my site as I would normally, but using Cake's methods to keep it within the framework.
Example layout would have jQuery included in the <head> like this:
app/View/Layouts/default.ctp
<head>
<?php
// Include jQuery
echo $this->Html->script('jquery-1.8.2.min');
// Want to send some glabal values to your scripts?
$this->Js->set(array(
'TEST' => 'Hello World',
'ROOT' => $this->Html->url( '/', true)
));
echo $this->Js->writeBuffer(array('onDomReady' => false));
// Include any other scripts you've set
echo $this->fetch('script');
?>
</head>
Then in your view, you might want to include a specific script for that page:
app/View/Pages/test.ctp
<?php echo $this->Html->script('test.js'); ?>
And you just keep all your JavaScript as usual in an external script:
app/webroot/js/test.js
$(document).ready(function() {
/**
* Alert the value we set in our layout. All JS vars that have been
* set are available in your JavaScript via the window.app object.
*/
alert(window.app.TEST + ' sent from ' + window.app.ROOT);
});
The general consensus is don't bother using the JsHelper, and is likely being removed in Cake 3 in any case.
I would put echo $this->Js->writeBuffer(); before </body>
I am not sure on the exact workings but I think your JS is working with echo because it is being output in the middle of your view, so when the page loads, it alerts. (The JS will be in the middle of your HTML output) rather than in the <head> or before </body>
The writeBuffer is being called before the view file is processed; so your view js does not get added to the buffer. I could be incorrect however.
Set the write buffer at the end of each ctp file and it should work
I can do this in any of my View file in Cake PHP:
<?php echo $this->Html->script('myjs.js', false); ?>
but if I do the same thing in my default view (default.ctp) then the JS files don't load i.e. they don't get echoed. I have tried moving includes above and below <?php echo $scripts_for_layout ?> in the default view but they still don't get printed:
<?php echo $scripts_for_layout ?>
<?php echo $this->Html->script('myjs.js'); ?>
<?php echo $this->Html->script('myjs.js'); ?>
<?php echo $scripts_for_layout ?>
Any ideas?
Thank you :).
with or without an extension - this is not the reason why the script do not get echoed,
as mensch mentioned before it makes no difference because of:
source of html helper cakephp 2
if (strpos($url, '?') === false && substr($url, -3) !== '.js') {
$url .= '.js';
}
the reason is:
you have already inserted this script inside your view,
cake checks if the script is already inserted on the page
options - 'once' - Whether or not the script should be checked for uniqueness. If true scripts will only be included once, use false to allow
the same script to be included more than once per request.
by default the value of once is set to TRUE
remove the script from your view first and then try it with or without '.js'
P.S.: why the petervaz answer has worked for you:
because this check:
if ($options['once'] && isset($this->__includedScripts[$url])) {
return null;
}
made before check for file extension
so isset(__includedScripts['myjs']) == false // because first key was __includedScripts['myjs.js']
and you've got your script included
I have a project with scripts added just before $scripts_for_layout and they are displayed fine. The only difference is that I'm not adding the extension .js to the call, like this:
default.ctp:
<head>
<?php echo $this->Html->charset(); ?>
<title>
<?php echo "Site > $title_for_layout"; ?>
</title>
<?php
echo $this->Html->script('jquery-1.6.4');
echo $this->Html->script('jquery-ui-1.8.16.custom.min');
echo $this->Html->script('mercado');
echo $scripts_for_layout;
?>
</head>
Another thing I'd DEFINITELY recommend is to check that loading your JS in a view is 100% OK with everything.
Do NOT use $this->Html->script if you are unsure about:
--- the dependency of scripts on each other
--- the dependency of some plugins on other scripts
--- how many different layouts and/or views you want to use in the future.
For example, some plugins use jQuery but they require jQuery to be loaded BEFORE the plugin itself.
So if you put jQuery in a view or layout, the plugin's JS loads before jQuery and plugin may not work. If you want to make sure some script loads first, you can try this:
in your app/View/Helper/AppHelper.php:
class AppHelper extends Helper {
public $helpers = array('Html', 'Session');
public function beforeRender($viewFile){
echo $this->Html->script('jquery', array('inline'=>false));
}
}
Therefore you don't have to include jQuery in multiple views and it loads first.
$scripts_for_layout in a layout is a placeholder for all the scripts included in views, so if you include it or don't won't have any effect if you load scripts directly in the default.ctp.
That being said, adding the extension or leaving it out of the $this->Html->script() call shouldn't make a difference. What could be the case is that the HtmlHelper isn't called correctly (it's called by default in Cake 2.0), but you should be receiving error messages. Is debug set to 2 in /app/Config/core.php?