I can't get this to work, I need to retrieve an CSRF token via an object inside a Session object but it isn't displaying no matter what I try.
I have developed a system that will generate a template from properties from an object, it looks like this:
public function render(){
if(method_exists($this->controller, $this->action)){
//We need to check if the method is used in the controller and not in the parents AppController and/or Controller
$f = new ReflectionClass($this->controller);
$methods = array();
foreach($f->getMethods() as $m){
if($m->name == $this->action){
if($m->class == $this->controller){
$this->controller->{$this->action}();
}
}
}
$this->view_body = $this->render_view();
}else{
$this->error->show('Method ' . $this->action . ' not found in ' . $this->controller, $this->action, $this->controller);
}
$this->_set_render_view();
$this->_set_controller_layout();
if(!file_exists($this->config->paths->root . $this->layouts_path."/".$this->controller->layout)){
$this->error->show('Layout not found', $this->action, $this->controller);
}
if(!file_exists($this->config->paths->root . $this->views_path.'/'. $this->view_root . "/" . $this->controller->view)){
$this->error->show('View not found', $this->action, $this->controller);
}
$layout_content = file_get_contents($this->config->paths->root . $this->layouts_path."/".$this->controller->layout);
$view_content = file_get_contents($this->config->paths->root . $this->views_path.'/'. $this->view_root . "/" . $this->controller->view);
$bind_content = "{% extends \"layout.tmpl\" %} ";
$templates = array();
$bind_content .= '{% block view %}' . $view_content . " {% endblock %}";
$templates['layout.tmpl'] = $layout_content;
foreach($this->controller->snippets as $snippet_name => $snippet){
if(!file_exists($this->config->paths->root.$this->snippets_path ."/" . $snippet)){
$this->error->show('Snippet not found', $this->action, $this->controller);
}
$snippet_content = file_get_contents($this->config->paths->root.$this->snippets_path ."/" . $snippet);
$bind_content .= "{% block ". $snippet_name . " %}" . $snippet_content . " {% endblock %}";
}
$templates[$this->controller->view] = $bind_content;
$loader = new Twig_Loader_Array($templates);
$processwire_vars = array('user', 'pages', 'page', 'sanitizer', 'files', 'input', 'permissions', 'roles', 'templates', 'session', 'config', 'controller', 'wire');
foreach($this->controller->vars as $key=>$val){
$vars[$key] = $val;
}
$twig = new Twig_Environment($loader);
$twig->addGlobal('this', $this);
foreach($processwire_vars as $key => $pw_v){
if(!isset($vars[$pw_v])){
//$vars[$pw_v] = $this->$pw_v;
$twig->addGlobal($pw_v, $pw_v);
}
}
echo $twig->render($this->controller->view, $vars);
}
Now I thought I could access the properties of the session by doing:
{{ session.CSRF.getTokenValue() }}
or
{{ session['CSRF'].getTokenValue() }}
But nothing is displaying.
When I used <?php echo $session->CSRF->getTokenValue(); ?> It worked, so its not the object/method that is failing,
What am I doing wrong here?
EDIT:
It could also be noteworthy that accesing properties like user (user.title, user.name) is possible
Related
I am trying to understand the MVC method with the use of OOP. However it seems like I've hit the wall here.
I am trying to pass multiple objects to the view. But all I can do so far is pass just one object. The ideal result would be passing multiple objects, while keeping the names that are assigned to them in the controller.
The render, start and end functions in the View class go something like this:
public function render($viewName, $data){
$viewAry = explode('/', $viewName);
$viewString = implode(DS, $viewAry);
if(file_exists(ROOT . DS . 'app' . DS . 'views' . DS . $viewString . '.php')){
include(ROOT . DS . 'app' . DS . 'views' . DS . $viewString . '.php');
include(ROOT . DS . 'app' . DS . 'views' . DS . 'layouts' . DS . $this->_layout . '.php');
}else{
die('The view \"' . $viewName . '\" does not exist.');
}
}
public function content($type){
if($type == 'head'){
return $this->_head;
}elseif ($type == 'body'){
return $this->_body;
}
return false;
}
public function start($type){
$this->_outputBuffer = $type;
ob_start();
}
public function end(){
if($this->_outputBuffer == 'head'){
$this->_head = ob_get_clean();
}elseif($this->_outputBuffer == 'body'){
$this->_body = ob_get_clean();
}else{
die('You must first run the start method.');
}
}
And this is how would the controller look like:
public function indexAction(){
$items = $this->PortalModel->getItems();
$collections = $this->PortalModel->getCollections();
$this->view->render('home/index', $items);
}
So this is how I get the one $data object to the view and loop trough it.
But how could I store multiple results from the database to the view?
You should pass an array of variables into view instead of one variable.
public function indexAction(){
$variables = [
'items' => $this->PortalModel->getItems(),
'collections' => $this->PortalModel->getCollections()
];
$this->view->render('home/index', $variables);
}
I am trying to render product_list.tpl file in home.tpl but it's giving me NULL
Controller File:
/controller/product/product_list.php
Code:
class ControllerProductProductList extends Controller {
public function index() {
$this->load->model('catalog/category');
$this->load->model('catalog/product');
$this->load->model('tool/image');
$filter_data = array(
'filter_tag' => 'featured',
'limit' => 9
);
$data['results'] = $this->model_catalog_product->getProducts($filter_data);
if (file_exists(DIR_TEMPLATE . $this->config->get('config_template') . '/template/common/productlist.tpl')) {
$this->response->setOutput($this->load->view($this->config->get('config_template') . '/template/common/productlist.tpl', $data));
} else {
$this->response->setOutput($this->load->view('default/template/common/productlist.tpl', $data));
}
}
}
Template to render
/template/product/productlist.tpl
Code:
<?php var_dump($results); ?>
<h2>Product are here</h2>
Then adding this line in home.php controller
$data['special_mod'] = $this->load->controller('product/product_list');
and printing $special_mod in common/home.tpl file
The problem was in /controller/product/product_list.php
the method $this->response->setOutput doesn't just return the value but send the user to the different page while what I wanted was to just output the productlist.tpl as string so for that I had to replace the code
if (file_exists(DIR_TEMPLATE . $this->config->get('config_template') . '/template/common/productlist.tpl')) {
$this->response->setOutput($this->load->view($this->config->get('config_template') . '/template/common/productlist.tpl', $data));
} else {
$this->response->setOutput($this->load->view('default/template/common/productlist.tpl', $data));
}
with
if (file_exists(DIR_TEMPLATE . $this->config->get('config_template') . '/template/common/productlist.tpl')) {
return $this->load->view($this->config->get('config_template') . '/template/common/productlist.tpl', $data);
} else {
return $this->load->view('default/template/common/productlist.tpl', $data);
}
I just learning Twig templating and I am having trouble figuring out how to load a template part that is in a directory outside of the current themes' directory so they can be reused by other themes.
I am starting with just a simple loading of a head.html template part located in the core/tpls/ directory. With the variouse methodes I have tried, I get the following error:
PHP Fatal error: Uncaught exception 'Twig_Error_Loader' with message
'Unable to find template "/home/ubuntu/workspace/core/tpls/head.html"
(looked into: /home/ubuntu/workspace/themes/core) in "base.html" at
line 5.
The file is in the directory and the path is correct despite that the log error says otherwise.
My base.html located in the themes/core/ directory contains the custom Twig function to include the head.html template located outside of the theme directory:
<html lang="en" class="no-js">
<head>
{% include core.head %} // This is line 5 and throws the error and need to work correctly
// {% include core_head %} // This throws the error and should function the same as {% include core_head %}
// {% include tpl.head %} <-- If I use this, my function for grabbing templates from the theme works since I have a copy of the head.html in the theme dir too //
</head>
<body>
<header id="header">
{% include tpl.header %} // This works via the get_tpl() function
</header>
{% include tpl.breadcrumbs %} // This works too
[. . .]
I hate to clutter this with an entire class but it may be helpful for someone to see what I have wrong. The get_core_tpl() function is what I cannot get working where my other get_*() functions work as they should. See my comments there and also, take note to my comments in the befor_rendor() function:
<?php
class Get_TPLs {
private $tpl_name,
$theme = 'core',
$tpl_array = array(
'breadcrumbs',
'content',
'cover',
'footer',
'head',
'header',
'sidebar'
);
public function before_load_content(&$file) {
$this->tpl_name = basename($file, '.md');
}
public function config_loaded(&$settings) {
if (isset($settings['core_tpl']))
$this->core_tpl = $settings['core_tpl'];
if (isset($settings['tpl_array']))
$this->tpl_array = $settings['tpl_array'];
if (isset($settings['theme']))
$this->theme = THEMES_DIR . $settings['theme'];
}
public function file_meta(&$meta) {
$config = $meta;
if (isset($config['slug'])):
$this->tpl_name = strtolower($config['slug']);
endif;
}
public function before_render(&$twig_vars, &$twig) {
//// ==== THIS IS CALLED WITH {% include core.[TEMPLATE_NAME] %} SEE Base.html ==== ////
// core/tpl/file
$twig_vars['core'] = $this->get_core_tpl();
//// === THIS IS A SIMPLIFIED VERSION OF THE ABOVE VAR - IT'S CALLED WITH {% include core_head %} but It throws the same error ==== ////
$twig_vars['core_head'] = CORE_TPL . '/head.html';
// theme/tpl/file
$twig_vars['tpl'] = $this->get_tpl();
// theme/tpl/views/file
$views = $this->get_views();
$twig_vars['views'] = $views;
// theme/content/file
$theme = $this->get_theme_content();
$twig_vars['theme'] = $theme;
//var_dump($twig_vars['theme']);
}
//// ==== THIS IS THE FUNCTION IN QUESTION ==== ////
private function get_core_tpl() {
foreach ($this->tpl_array as $value) {
$pattern = array('/ /', '/_/');
$name = preg_replace($pattern, '_', $value);
$core[$name] = CORE_TPL . $value . '.html';
}
return $core;
}
private function get_tpl() {
foreach ($this->tpl_array as $value) {
$pattern = array('/ /', '/_/');
$name = preg_replace($pattern, '_', $value);
$tpl[$name] = 'tpl/' . $value . '.html';
$page_tpl = $this->theme . '/tpl/' . $this->tpl_name . '-' . $value . '.html';
if (file_exists($page_tpl))
$tpl[$name] = '/tpl/' . $this->tpl_name . '-' . $value . '.html';
}
return $tpl;
}
private function get_theme_content() {
$content = $this->get_files($this->theme . '/content', '.md');
$content_data = array();
if (empty($content))
return;
foreach ($content as $key) {
$file = $this->theme . '/content/' . $key . '.md';
$pattern = array('/ /', '/-/');
$title = preg_replace($pattern, '_', strtolower($key));
$data = file_get_contents($file);
$content_data[$title] = \Michelf\MarkdownExtra::defaultTransform($data);
}
return $content_data;
}
private function get_views() {
$view_dir = $this->theme . '/tpl/views';
$views = $this->get_files($view_dir);
if (empty($views))
return;
$pattern = array('/ /', '/-/');
foreach ($views as $key) {
$name = preg_replace($pattern, '_', $key);
$view[$name] = 'tpl/views/' . $key . '.html';
if (file_exists($this->theme . '/tpl/' . $this->tpl_name . '-' . $key . '.html'))
$view[$name] = 'tpl/views/' . $this->tpl_name . '-' . $key . '.html';
}
if (!isset($view))
return array(0);
return $view;
}
// scrive.php lib
private function get_files($directory, $ext = '.html') {
if (!is_dir($directory))
return false;
$array_items = array();
if ($handle = opendir($directory)) {
while (false !== ($file = readdir($handle))) {
$file = $directory . "/" . $file;
if (!$ext || strstr($file, $ext))
$array_items[] = basename($file, $ext);
}
closedir($handle);
}
return $array_items;
}
} ?>
Any help will be greatly appreciated! Thnx
I'm making a little PHP function that will show the avatar of all the administrators in my database. For some reason, I get the following error when I try to call the function $backend->addSnippet('login: show-admins');. Here is the PHP Class.
<?php
class zBackend {
private $adminCount;
final public function fetchAdminInfo() {
global $zip, $db, $tpl;
$query = $db->prepare('SELECT first_name, last_name FROM zip__admins');
$query->execute();
$result = $query->fetchAll();
$id = 1;
foreach($result as $row) {
$tpl->define('admin: first_name-' . $id, $row['first_name']);
$tpl->define('admin: last_name-' . $id, $row['last_name']);
$id++;
}
$this->adminCount = $id;
}
final public function addSnippet($z) {
global $tpl;
if(isset($z) && !empty($z)) {
$this->fetchAdminInfo();
switch($z) {
case 'login: show-admins':
$tpl->write('<ul id="users">');
$id = 0;
while($this->adminCount > $id) {
$tpl->write('<li data-name="{admin: first_name-' . $id + 1 . '} {admin: last_name-' . $id + 1 . '}">');
$tpl->write('<div class="av-overlay"></div><img src="{site: backend}/img/avatars/nick.jpg" class="av">');
$tpl->write('<span class="av-tooltip">{admin: first_name-' . $id + 1 . '} {admin: last_name-' . $id + 1 . '}</span>');
$tpl->write('</li>');
}
break;
}
} else {
return false;
}
}
}
?>
Here is where I set the function:
final public function __construct() {
global $zip, $core, $backend;
$this->Define('site: title', $zip['Site']['Title']);
$this->Define('site: location', $zip['Site']['Location']);
$this->Define('site: style', $zip['Site']['Location'] . '/_zip/_templates/_frontend/' . $zip['Template']['Frontend']);
$this->Define('site: backend', $zip['Site']['Location'] . '/_zip/_templates/_backend/' . $zip['Template']['Backend']);
$this->Define('social: email', $zip['Social']['Email']);
$this->Define('social: twitter', $zip['Social']['Twitter']);
$this->Define('social: youtube', $zip['Social']['Youtube']);
$this->Define('social: facebook', $zip['Social']['Facebook']);
$this->Define('snippet: show-admins', $backend->addSnippet('login: show-admins'));
}
And here is where I call the function:
<ul id="users">
{snippet: show-admins}
<br class="clear">
</ul>
Here is where I declare $backend
<?php
session_start();
error_reporting(E_ALL);
ini_set('display_errors', '1');
define('D', DIRECTORY_SEPARATOR);
define('Z', '_zip' . D);
define('L', '_lib' . D);
define('C', '_class'. D);
require Z . 'config.php';
require Z . L . 'common.php';
try {
$db = new PDO($zip['Database']['Data']['Source']['Name'], $zip['Database']['Username'], $zip['Database']['Password']);
} catch(PDOException $e) {
die(zipError('ZipDB: Connection Failed', $e->getMessage()));
}
require Z . C . 'class.ztpl.php';
require Z . C . 'class.zcore.php';
require Z . C . 'class.zbackend.php';
require Z . C . 'class.zmail.php';
$tpl = new zTpl();
$backend = new zBackend();
$core = new zCore();
?>
It works just fine if I put the code into the file, but that limits what I can do. I want to be able to do it in a class and use functions to call it. Any ideas?
$backend isn't defined when your constructor fires. It's unclear from the code you've posted what class your __construct is constructing, but I'm guessing it's within zTpl. Consider moving your snippet definition call to a separate method, which you can call once all dependent objects have been constructed.
In class zTpl:
final public function __construct() {
global $zip; //note that we don't need $core or
//$backend, since they aren't yet defined
//Personally, I would pass the $zip array
//as a parameter to this constructor.
$this->Define('site: title', $zip['Site']['Title']);
//...
}
public function defineShowAdminsSnippet($backend) {
$this->Define('snippet: show-admins', $backend->addSnippet('login: show-admins'));
}
Where you define your objects:
$tpl = new zTpl();
$backend = new zBackend();
$core = new zCore();
//new:
$tpl->defineShowAdminsSnippet();
In my opinion, it is easier to avoid dependency problems like this if you eliminate use of the global keyword.
<?php
/** Check if environment is development and display errors **/
function setReporting() {
if (DEVELOPMENT_ENVIRONMENT == true) {
error_reporting(E_ALL);
ini_set('display_errors','On');
} else {
error_reporting(E_ALL);
ini_set('display_errors','Off');
ini_set('log_errors', 'On');
ini_set('error_log', ROOT.DS.'tmp'.DS.'logs'.DS.'error.log');
}
}
/** Check for Magic Quotes and remove them **/
function stripSlashesDeep($value) {
$value = is_array($value) ? array_map('stripSlashesDeep', $value) : stripslashes($value);
return $value;
}
function removeMagicQuotes() {
if ( get_magic_quotes_gpc() ) {
$_GET = stripSlashesDeep($_GET );
$_POST = stripSlashesDeep($_POST );
$_COOKIE = stripSlashesDeep($_COOKIE);
}
}
/** Check register globals and remove them **/
/*function unregisterGlobals() {
if (ini_get('register_globals')) {
$array = array('_SESSION', '_POST', '_GET', '_COOKIE', '_REQUEST', '_SERVER', '_ENV', '_FILES');
foreach ($array as $value) {
foreach ($GLOBALS[$value] as $key => $var) {
if ($var === $GLOBALS[$key]) {
unset($GLOBALS[$key]);
}
}
}
}
}*/
/** Routing **/
function routeURL($url) {
global $routing;
foreach ( $routing as $pattern => $result ) {
if ( preg_match( $pattern, $url ) ) {
return preg_replace( $pattern, $result, $url );
}
}
return ($url);
}
/** Main Call Function **/
function callHook() {
global $url;
global $default;
global $sent;
$queryString = array();
if (!isset($url)) {
$controller = $default['controller'];
$action = $default['action'];
} else {
$url = routeURL($url);
$urlArray = array();
$urlArray = explode("/",$url);
$controller = $urlArray[0];
array_shift($urlArray);
if (isset($urlArray[0])) {
$action = $urlArray[0];
array_shift($urlArray);
} else {
$action = 'view'; // Default Action
}
$queryString = $urlArray;
if(isset($queryString[0]))
$sent=$queryString[0];
//echo $sent;
}
$controllerName = $controller;
$controller = ucwords($controller);
$model = rtrim($controller, 's');
$controller .= 'Controller';
//echo($model);
//echo($controllerName);
//echo($action);
//echo phpinfo();
**$dispatch = new $controller($model,$controllerName,$action);**
if ((int)method_exists($controller, $action)) {
//call_user_func_array(array($dispatch,"beforeAction"),$queryString);
call_user_func_array(array($dispatch,$action),$queryString);
//call_user_func_array(array($dispatch,"afterAction"),$queryString);
} else {
/* Error Generation Code Here */
}
}
/** Autoload any classes that are required **/
function __autoload($className) {
if (file_exists(ROOT . DS . 'library' . DS . strtolower($className) . '.class.php')) {
include_once(ROOT . DS . 'library' . DS . strtolower($className) . '.class.php');
} else if (file_exists(ROOT . DS . 'application' . DS . 'controller' . DS . strtolower($className) . '.php')) {
include_once(ROOT . DS . 'application' . DS . 'controller' . DS . strtolower($className) . '.php');
} else if (file_exists(ROOT . DS . 'application' . DS . 'model' . DS . strtolower($className) . '.php')) {
include_once(ROOT . DS . 'application' . DS . 'model' . DS . strtolower($className) . '.php');
} else {
/* Error Generation Code Here */
}
}
setReporting();
removeMagicQuotes();
//unregisterGlobals();
callHook();
*****//
When I uploaded this file on server it is showing the error
Fatal error: Cannot instantiate non-existent class:updatescontroller on line 97
pointing to the line
$dispatch =new $controller($model,$controllerName,$action);
Please help me determine what is going wrong.
Also the same server is also not allowing me to run the unregisterGlobals() function and showing “too many errors for undefined index”.
The complete project is running very well on my localhost server.
From the error message I guess you are missing an included file that declares the updatescontroller class. Maybe you need to upload the entire project?
It also seems that your local PHP configuration doesn't match the remote configuration. Try matching your local php.ini with the remote server to make local testing more realistic.
If at all possible try to match the PHP version on your local server with the remote server. There can be subtle differences between versions.