I’m trying to process a menu in the controller as follows:
/**
* Renders the html output for the navigation items
*/
function _render_nav_items($current, $base_url) {
$nav_items = '';
foreach($this->_get_nav_items() as $nav_item) {
$nav_items .= $this->load->view(
'admin/nav/nav_item',
array(
'nav_item' => $nav_item,
'base_url' => $base_url
),
true
);
}
return $nav_items;
}
nav_item.php :
<li><?=$nav_item['name']?></li>
But I get the following output:
http://i.imgur.com/YMJ5kYU.png?2
Any ideas of why that is, I’ve tried running trim and compress on the output but I can’t get those extra characters/whitespace removed from the output.
I have ignored this issue for some time but can't seem to solve it however it seems to occur wherever I have php-code in the view I load, when the php code is removed it loads fine with no extra spaces/characters.
Related
I have a custom extension in Typo3.
Does anyone know how to add in a template ?
Ive had some success with adding in
call_user_func(
function($extKey)
{
//other init code goes here
$GLOBALS['TBE_STYLES']['skins'][$extKey] = array();
$GLOBALS['TBE_STYLES']['skins'][$extKey]['name'] = $extKey;
$GLOBALS['TBE_STYLES']['skins'][$extKey]['stylesheetDirectories'] = array(
'structure' => 'EXT:'. $extKey. '/Resources/Public/css/',
);
},
$_EXTKEY
);
Ive looked at typo3 docs but cant get it to work when adding to ext_tables.php
It is a Front End Plug in and I want the reference to be contained within the Extension for ease of installation and management.
Anyone had success with this ?
put following in this file your_extension/Configuration/TypoScript/setup.ts
page = PAGE
page {
# CSS files to be included
includeCSS {
yourCss = EXT:your_extension/Resources/Public/Css/yourCss.css
}
}
and then call it in your ext_tables.php
/***************
* Include TypoScript
*/
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addStaticFile(
$_EXTKEY, 'Configuration/TypoScript', 'Your Package'
);
you'll find this voice in your template in the backend so that you can include it ...
I have the below function to create active trail functionality. So if I were to have /blog as a "parent" and a post of /blog/mypost, when on mypost the blog link would show as highlighted. I don't want to have to make menu items for all the blog posts. The problem is when caching is turned on (not using settings.local.php and debug turned off) the getRequestUri isn't changing on some pages. It seems to be cached depending on the page. It works fine with page caching turned off but I'd like to get this working with caching. Is there a better way to check for the current path and apply the active class?
function mytheme_preprocess_menu(&$variables, $hook) {
if($variables['theme_hook_original'] == 'menu__main'){
$node = \Drupal::routeMatch()->getParameter('node');
if($node){
$current_path = \Drupal::request()->getRequestUri();
$items = $variables['items'];
foreach ($items as $key => $item) {
// If current path starts with a part of another path i.e. a parent, set active to li.
if (0 === strpos($current_path, $item['url']->toString())) {
// Add active link.
$variables['items'][$key]['attributes']['class'] .= ' menu-item--active-trail';
}
}
}
}
}
I've also tried putting this into a module to try and see if I can get the current path to then do the twig logic in the menu--main.twig.html template but I have the same problem.
function highlight_menu_sections_template_preprocess_default_variables_alter(&$variables) {
$variables['current_path'] = $_SERVER['REQUEST_URI'];
}
After a very long time trying all sorts of things, I found an excellent module which addresses exactly this problem. Install and go, not configuration, it just works:
https://www.drupal.org/project/menu_trail_by_path
Stable versions for D7 and D8.
I tried declaring an active path as part of a custom menu block, and even then my declared trail gets cached. Assuming it's related to the "There is no way to set the active link - override the service if you need more control." statement in this changelog, though why MenuTreeParameters->setActiveTrail() exists is anybody's guess.
For the curious (and for me when I search for this later!), here's my block's build() function:
public function build() {
$menu_tree = \Drupal::menuTree();
$parameters = new MenuTreeParameters();
$parameters->setRoot('menu_link_content:700c69e6-785b-4db7-be49-73188b47b5a3')->setMinDepth(1)->setMaxDepth(1)->onlyEnabledLinks();
// An array of routes and menu_link_content ids to set as active
$define_active_mlid = array(
'view.press_releases.page_1' => 385
);
$route_name = \Drupal::request()->get(RouteObjectInterface::ROUTE_NAME);
if (array_key_exists($route_name, $define_active_mlid)) {
$menu_link = \Drupal::entityTypeManager()->getStorage('menu_link_content')->loadByProperties(array('id' => $define_active_mlid[$route_name]));
$link = array_shift($menu_link);
$parameters->setActiveTrail(array('menu_link_content:' . $link->uuid()));
}
$footer_tree = $menu_tree->load('footer', $parameters);
$manipulators = array(
array('callable' => 'menu.default_tree_manipulators:checkAccess'),
array('callable' => 'menu.default_tree_manipulators:generateIndexAndSort'),
);
$tree = $menu_tree->transform($footer_tree, $manipulators);
$menu = $menu_tree->build($tree);
return array(
'menu' => $menu,
);
}
[adding a new answer since this is a completely different approach than my earlier one]
If a CSS-based solution is acceptable, this seems to work okay:
.page-node-type-press-release {
a[data-drupal-link-system-path="press-room/press-releases"] {
// active CSS styles here
}
}
I'm trying to make a function for including pages.
In fact For the beginning I used to work with a long code that checked for all pages:
if (isset($_GET]['p']) && $_GET['p']=='something') {include 'something.php'};
Now I work with more than 600 pages and this code is too long and I would like to simplify it.
Sometimes I do have pages that are note entitled like they are used, for example home will correspond to accueil.php etc.
So I've done an array in which I listed all exceptions:
like that:
$paramListepages = array(
'corbeille' => array(
'libelle' => 'corbeille',
'page' => 'php/trash.php'
),
'nouveaumessage' => array(
'libelle' => 'nouveaumessage',
'page' => 'php/envoyer.php'
),
etc...
In this array I have about 20 pages.
Now I've tried to create a function for including pages so here is my code:
function getPage($var)
{
if (isset($var)) {
$key = array_search($var, $paramListepages);
if ($key == false()) {
include('php/'.$var.'.php');
} else {
}
}
}
I do not understand why the first part does not work.
I first of all check if the var does exist in the array, if not I include the page corresponding to the var.
I do still do not know how to do the second part, but for now the first one does not work.
I have no message error, even if in my ubunto I activated the displaying of all errors.
In the main page index.php I call the function getPage($_GET['p'])
Any kind of help will be much appreciated.
I'd suggest accessing the entries in your array directly:
function getPage($var) {
if (empty($var))
// no page specified => default page
inlude('index.php')
elseif (array_key_exists($var,$paramListepages))
// page found => include it!
include (sprintf('php/%s.php', $paramListepages[$var]['page']));
else
// page not found => default page
inlude ('index.php')
}
It is possible to delay the output of the headers to the browser until the entire php script has finished executing?
The headers will be sent once the first piece of code is sent from php to the webserver.
So you can just "not echo anything" until the end of the script or use output buffering to achieve the same thing
This is the way most professional programmers would advise, the reasons you should always do it this way is that you can manage errors and error pages effectively.
If your application is already built to display output as the script is executed then i would advise you to start from scratch.
the way I usually manage output is with a small template's system, the template's system does not have to parse templates etc, it just needs to be passed a set of data and then include the required template.
you should create a class that acccepts data in the form of $template->set(key[,value = true]) and then a function that would display such as $template->display(filename), when this function executes you should extract the variables and then include the template file, after that has been done you then call exit(0) so no further code is executed.
a simple template system can be like so:
class Template
{
private $_data = array();
public function set($key,$value = true)
{
$this->_data[$key] = $value;
}
public function display($template)
{
//Check template exuists
extract($this->_data);
require_once $template;
exit(0);
}
}
then use pretty simply like so:
$template = new Template();
$template->set("title","Practical home Page");
$template->set("header","My Home Page");
$lists = array(
array(
"value" => "list item 1",
"id" => "list_item_1",
"class" => "item"
),
array(
"value" => "list item 2",
"id" => "list_item_2",
"class" => "item"
)
);
$template->set("menu",$lists);
$template->display("templates/homepage.php");
you may also would like to read the following answer I had answered previously!
PHP Looping Template Engine - From Scratch
A node loads a profile of a user (external database + views). All of this works when I visit: node/123/profile/id/3. Now I have implemented hook_menu() in order to load any profile page and have nicer URLs.
When I load it myself for some reason $left in page.tpl.php is suddenly empty and many more variables seem not to be loading. I have tried many different functions to render and create the correct $output but realized that node_show() seems to be the function of choice.
Testing has shown now that for some reason hook_nodeapi() calls are ignored.
My code:
/**
* Implementation of hook_menu
*/
function modulename_menu() {
$items = array();
$items['my/nice/url/profile'] = array(
'description' => 'This page holds a view that shows profiles based on the %',
'page callback' => 'website_profile_load',
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
return $items;
}
/**
* Menu path wildcard callback
*/
function website_profile_load() {
$output = node_show(node_load(1221), false, true);
return $output;
}
So what is the correct way to do this and get Panels (see comment below) to load correctly?
UPDATE:
I am using table wizard and Views 2 to connect to another database with information about people that aren't users of the system. This is an alumni page, the page is administered externally and showed internally (nothing I can do about, have to make this work :)
Just discovered that Panels aren't loaded at all. So even if the node I am trying to load is uses panels for some reason none of that is loaded.
/**
* Menu path wildcard callback
*/
function website_profile_load($uid = null) {
if (!$uid) {
global $user; // if no user passed in argument, show current user profile
$uid = $user->uid;
}
$output = drupal_render(content_profile_show_profiles($uid));
}
There are many reasons why rendering the result of a node_load is different from going to the stock Drupal path /node. It is way too much to go over here honestly but the short answer is that you have to define a template/theme and blocks etc for each page you create. Just because you make a new path and do a node_load in the callback for that path doesn't mean Drupal can automagically know how you want to display that content. It simply loads data from the node and it is available to do whatever you please with it after that. This is why you get a blankish looking page instead of what you'd expect from going through /node.
However I will offer this simple solution since it sounds like you want the exact same page you'd get when you go to 'node/123/profile/id/3' but accessible through a link you define yourself. You just need to setup a redirect in your hook_menu like so:
$items['my/nice/url/profile'] = array(
'description' => 'This page holds a view that shows profiles based on the %',
'page callback' => 'drupal_goto',
'page arguments' => 'node/123/profile/id/3',
'access callback' => TRUE,
'type' => MENU_CALLBACK);
This is essentially saying that when you navigate to 'my/nicer/url/profile' it runs: drupal_goto('node/123/profile/id/3');
I found the answer to be that apparently somewhere in the pipeline of creating a node Drupal uses $path (that is originally set by $_GET['q']) and sometimes also $_GET['q'] to determine how to render the page. NOTE that I am using Panels and Ctools Page Manager modules in order to get my things working correctly.
It turns out Panels, if you search the code, looks at $_GET['q'] for quite an amount of things.
Here is what I ended up with:
/**
* Implementation of hook_menu
*/
function modulename_menu() {
$items = array();
// For department and having nice URL's for their profile pages.
$items['my/nice/url/profile/%'] = array(
'description' => 'This page holds a view that shows profiles based on the %',
'page callback' => 'website_profile_load',
'page arguments' => arg(4),
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
return $items;
}
/**
* Menu path callback
*/
function website_profile_load($id = NULL) {
// Rename the query internally since other functions base the design
// on the way the query is structured and not simply by the node which
// is currently loading.
if(!empty($id)) {
$path = $_GET['q'] = 'node/1221/profile/id/' . $id;
}
// Use ctools function to correctly display node view since
// this site heavily uses ctools rendering for panels and
// web parts / web pages.
drupal_load('module', 'page_manager');
ctools_include('node_view', 'page_manager', 'plugins/tasks');
if(function_exists('page_manager_node_view')) {
$output = page_manager_node_view(node_load(1221));
} else {
// Will display incorrectly but still load the UI
$output = node_page_view(node_load(1221));
}
return $output;
}
And it works :)