Usin joomla 3.1 with SEF and mod rewrite.
How can I get the link of the menu item that a "menu item alias" references ?
Using the code below renders the alias field of the menu items alias and not the "menu alias" destination.
$menu->getItem($men->id)->route
I don't think this would be the best approach but you could load this from the database, for example...
$menuLink=""; //to be used to store the result of our query
$alias='somealias'; //I am guessing you will already have the alias ready from some source
//query the database to find the link corresponding to this alias
$db=JFactory::getDbo();
$query=$db->getQuery(true);
$query->select('link');
$query->from('#__menu');
$query->where("alias='" . $alias . "'");
$db->setQuery($query);
try
{
$result=$db->loadObject();
$menuLink=$result->link;
}
catch(RuntimeException $e)
{
JError::raiseError(500, $e->getMessage());
}
If someone comes up with a better way then that would also be good :) This is how I usually do it though, it works fine for me. Hope this helps.
Related
I am very much new to drupal 8, I am trying to alter a form under custom content type "Question". The form has an id "node-question-form".
I have setup a module and trying to add hook_FORM_ID_alter() but its never getting called. Even the simplest hook is not working. eg:
function constellator_form_alter(&$form, &$form_state, $form_id){
echo "alter the form"; exit;
}
where 'constellator' is the module name.
I have been stuck with since morning and nothing is working for me, Any help will be greatly appriciated.
Cheers
hook_form_alter() and hook_FORM_ID_alter() are called while a form is being created and before displaying it on the screen.
These functions are written in the .module file.
Always clear the cache after writing any hook function. This makes Drupal understand that such a function has been declared.
Use drush cr if using drush version 8 else click on Manage->Drupal 8 logo->Flush all Caches to clear the caches.
Now you can check if the function is being called or not.
The best way to check that is to install the Devel module, enable it. Along with Devel, Kint is installed. Enable Kint too from the Admin UI.
After doing that,you can check whether the hook is being called or not in the following way:
function constellator_form_alter(&$form, &$form_state, $form_id){
kint($form);
}
This will print all the form variables for all forms in the page.
If you want to target a particular form in the page, for eg. you form, node-question-form, type:
function node_question_form_form_alter(&$form, &$form_state, $form_id){
kint($form);
}
Using echo, the way you did, you can confirm whether the function is being called or not, without any hassle, by viewing the Source Code for the page and then searching for the text that you have echoed, using some search option of browser, like, Ctrl+f in case of Google Chrome.
If you want to change sorting options and/or direction (ASC / DESC), you can use this example (tested with Drupal 9).
Here I force the sorting direction according to the "sort by option" set by the user in an exposed filter. (if the user want to sort by relevance, we set the order to ASC, if the user want to sort by date, we set the order to DESC to have the latest content first).
/**
* Force sorting direction for search by date
*
*/
function MYTHEME_form_alter(&$form, &$form_state, $form_id)
{
if (!$form_id == 'views_exposed_form"' || !$form['#id'] == 'views-exposed-form-search-custom-page-1') {
return;
}
$user_input = $form_state->getUserInput();
if (empty($user_input['sort_by'])) {
return;
}
if ($user_input['sort_by'] == 'relevance') {
$user_input['sort_order'] = 'ASC';
} elseif ($user_input['sort_by'] == 'created') {
$user_input['sort_order'] = 'DESC';
}
$form_state->setUserInput($user_input);
}
Note that "views-exposed-form-search-custom-page-1" is the id of my form,
"relevance" and "created" are the sort field identifier set in drupal admin.
function hook_form_alter(&$form, \Drupal\Core\Form\FormStateInterface &$form_state, $form_id) {
echo 'inside form alter';
}
I am new to Ionic2, and I am trying to build dynamic tabs based on current menu selection. I am just wondering how can I get current page using navigation controller.
...
export class TabsPage {
constructor(navParams: NavParams,navCtrl:NavController) {
//here I want to get current page
}
}
...
From api documentation I feel getActiveChildNav() or getActive() will give me the current page, but I have no knowledge on ViewController/Nav.
Any help will be appreciated. Thanks in advance.
Full example:
import { NavController } from 'ionic-angular';
export class Page {
constructor(public navCtrl:NavController) {
}
(...)
getActivePage(): string {
return this.navCtrl.getActive().name;
}
}
Method to get current page name:
this.navCtrl.getActive().name
More details here
OMG! This Really Helped mate, Tons of Thanks! #Deivide
I have been stuck for 1 Month, Your answer saved me. :)
Thanks!
if(navCtrl.getActive().component === DashboardPage){
this.showAlert();
}
else
{
this.navCtrl.pop();
}
My team had to build a separate custom shared menu bar, that would be shared and displayed with most pages. From inside of this menu component.ts calling this.navCtrl.getActive().name returns the previous page name. We were able to get the current page name in this case using:
ngAfterViewInit() {
let currentPage = this.app.getActiveNav().getViews()[0].name;
console.log('current page is: ', currentPage);
}
this.navCtrl.getActive().name != TheComponent.name
or
this.navCtrl.getActive().component !== TheComponent
is also possible
navCtrl.getActive() seems to be buggy in certain circumstances, because it returns the wrong ViewController if .setRoot was just used or if .pop was just used, whereas navCtrl.getActive() seems to return the correct ViewController if .push was used.
Use the viewController emitted by the viewDidEnter Observable instead of using navCtrl.getActive() to get the correct active ViewController, like so:
navCtrl.viewDidEnter.subscribe(item=> {
const viewController = item as ViewController;
const n = viewController.name;
console.log('active page: ' + n);
});
I have tested this inside the viewDidEnter subscription, don't know about other lifecycle events ..
Old post. But this is how I get current page name both in dev and prod
this.appCtrl.getActiveNav().getActive().id
Instead of
...
...
//In debug mode alert value is 'HomePage'
//In production/ signed apk alert value is 'n'
alert(activeView.component.name);
if (activeView.component.name === 'HomePage') {
...
...
Use this
...
...
//In debug mode alert value is 'HomePage'
//In production/ signed apk alert value is 'HomePage'
alert(activeView.id);
if (activeView.id === 'HomePage') {
...
...
Source Link
You can use getActive to get active ViewController. The ViewController has component and its the instance of current view. The issue is the comparsion method. I've came up to solution with settings some field like id:string for all my Page components and then compare them. Unfortunately simple checking function name so getActive().component.name will break after minification.
Is there any way to parametise the Datasource for the 'source' field in the Template Builder?
We have a multisite setup. As part of this it would save a lot of time and irritation if we could point our Droptrees and Treelists point at the appropriate locations rather than common parents.
For instance:
Content
--Site1
--Data
--Site2
--Data
Instead of having to point our site at the root Content folder I want to point it at the individual data folders, so I want to do something like:
DataSource=/sitecore/content/$sitename/Data
I can't find any articles on this. Is it something that's possible?
Not by default, but you can use this technique to code your datasources:
http://newguid.net/sitecore/2013/coded-field-datasources-in-sitecore/
You could possibly use relative paths if it fits with the rest of your site structure. It could be as simple as:
./Data
But if the fields are on random items all over the tree, that might not be helpul.
Otherwise try looking at:
How to use sitecore query in datasource location? (dynamic datasouce)
You might want to look at using a Querable Datasource Location and plugging into the getRenderingDatasource pipeline.
It's really going to depend on your use cases. The thing I like about this solution is there is no need to create a whole bunch of controls which effectively do he same thing as the default Sitecore ones, and you don't have to individually code up each datasource you require - just set the query you need to get the data. You can also just set the datasource query in the __standard values for the templates.
This is very similar to Holger's suggestion, I just think this code is neater :)
Since Sitecore 7 requires VS 2012 and our company isn't going to upgrade any time soon I was forced to find a Sitecore 6 solution to this.
Drawing on this article and this one I came up with this solution.
public class SCWTreeList : TreeList
{
protected override void OnLoad(EventArgs e)
{
if (!String.IsNullOrEmpty(Source))
this.Source = SourceQuery.Resolve(SContext.ContentDatabase.Items[ItemID], Source);
base.OnLoad(e);
}
}
This creates a custom TreeList control and passes it's Source field through to a class to handle it. All that class needs to do is resolve anything you have in the Source field into a sitecore query path which can then be reassigned to the source field. This will then go on to be handled by Sitecore's own query engine.
So for our multi-site solution it enabled paths such as this:
{A588F1CE-3BB7-46FA-AFF1-3918E8925E09}/$sitename
To resolve to paths such as this:
/sitecore/medialibrary/Product Images/Site2
Our controls will then only show items for the correct site.
This is the method that handles resolving the GUIDs and tokens:
public static string Resolve(Item item, string query)
{
// Resolve tokens
if (query.Contains("$"))
{
MatchCollection matches = Regex.Matches(query, "\\$[a-z]+");
foreach (Match match in matches)
query = query.Replace(match.Value, ResolveToken(item, match.Value));
}
// Resolve GUIDs.
MatchCollection guidMatches = Regex.Matches(query, "^{[a-zA-Z0-9-]+}");
foreach (Match match in guidMatches)
{
Guid guid = Guid.Parse(match.Value);
Item queryItem = SContext.ContentDatabase.GetItem(new ID(guid));
if (item != null)
query = query.Replace(match.Value, queryItem.Paths.FullPath);
}
return query;
}
Token handling below, as you can see it requires that any item using the $siteref token is inside an Site Folder item that we created. That allows us to use a field which contains the name that all of our multi-site content folders must follow - Site Reference. As long at that naming convention is obeyed it allows us to reference folders within the media library or any other shared content within Sitecore.
static string ResolveToken(Item root, string token)
{
switch (token)
{
case "$siteref":
string sRef = string.Empty;
Item siteFolder = root.Axes.GetAncestors().First(x => x.TemplateID.Guid == TemplateKeys.CMS.SiteFolder);
if (siteFolder != null)
sRef = siteFolder.Fields["Site Reference"].Value;
return sRef;
}
throw new Exception("Token '" + token + "' is not recognised. Please disable wishful thinking and try again.");
}
So far this works for TreeLists, DropTrees and DropLists. It would be nice to get it working with DropLinks but this method does not seem to work.
This feels like scratching the surface, I'm sure there's a lot more you could do with this approach.
I am very new to opencart but I think this is easy and best solution out there. Although playing with templates is not a joy...
I am struggling to create some additional template pages. For example I have two types of products and category pages. I want to different templates for different products. In opencart you have only one layout for products.
What I thought to do is to make a duplicate of product layout. I got some help online but I am still not sure what more is needed. This is what I've done so far...
1 - Copy the controller file of catalog/controller/product/product.php and changed to catalog/controller/product/product-2.php. Then I changed this in controller:
if (file_exists(DIR_TEMPLATE . $this->config->get('config_template') . '/template/product/product-2.tpl')) {
$this->template = $this->config->get('config_template') . '/template/product/product-2.tpl';
} else {
$this->template = 'default/template/product/product-2.tpl';
}
2 - Then I copied the product language file and save as product-2
3 - After that I copied the actual tpl file and save as product-2
It was looking fine but if I try to make some changes to product-2.tpl nothing changes. Do I have to copy some more files to complete it?
After search and doing lot of research and mind-boggling, i found a very useful method to do what i want to do. in this way i have fully control of the opencart theme system. i can make as many different layouts as i wanted. i dont have to use VQmod neither have to make any controller but you have to use the existing controllers like product, category etc. if you are making your own controller even then it works.
here are the steps to follow to achieve different template for different categories, products and common pages.
i am here doing the example of products.
1- create custom template of product in product folder of the theme. e.g customproduct.tpl
2- now customize it as you wanted.create a product and take the id of it. id is very important here.
3- go to the controller catalog/controller/product/product.php
4- find this code
if (file_exists(DIR_TEMPLATE . $this->config->get('config_template') . '/template/product/product.tpl')) {
$this->template = $this->config->get('config_template') . '/template/product/customproduct.tpl';
} else {
$this->template = 'default/template/product/product.tpl';
}
5- now you have to use the simple if else condition. for example
//42 is the id of the product
if($this->request->get['product_id'] == 42){
if (file_exists(DIR_TEMPLATE . $this->config->get('config_template') . '/template/product/customproduct.tpl')) {
$this->template = $this->config->get('config_template') . '/template/product/customproduct.tpl';
} else {
$this->template = 'default/template/product/customproduct.tpl';
}
}
else{
if (file_exists(DIR_TEMPLATE . $this->config->get('config_template') . '/template/product/product.tpl')) {
$this->template = $this->config->get('config_template') . '/template/product/product.tpl';
} else {
$this->template = 'default/template/product/customproduct.tpl';
}
}
that's it job Done ;)
you can do the same thing for other controllers.
As you can see here ;
http://pranshuarya.com/jaal/Development/opencart-creating-a-new-viewtemplate.html
This was the second option of the real solution for "completely new layout" request.
Both can be used. Your solution is time saver if you will not need a new controller routine.But that way is more flexible.
Here are the steps ;
Add a new controller file to /catalog/controller. call something like new_layout.php... copy if there is a similar controller already. Be sure to change controller name as i told in my comment below.
Add a new view file in your theme folder ... like controller if you wish you can copy a simiplar view files content and modify as you wish.
Add the new layout either from admin panel System/Design/Layouts or from MYSQL table directly as explained in the link above.
It's ok now. Just add some modules in this layout view and enjoy.
From another forum I found the following example:
"I was looking for a way to pull node data via ajax and came up with the following solution for Drupal 6. After implementing the changes below, if you add ajax=1 in the URL (e.g. mysite.com/node/1?ajax=1), you'll get just the content and no page layout.
in the template.php file for your theme:
function phptemplate_preprocess_page(&$vars) {
if ( isset($_GET['ajax']) && $_GET['ajax'] == 1 ) {
$vars['template_file'] = 'page-ajax';
}
}
then create page-ajax.tpl.php in your theme directory with this content:
<?php print $content; ?>
"
This seems like the logical way to do it and I did this, but the phptemplate_preprocess_page function is never called ... any suggestions?
I figured it out for myself from a Drupal Support Theme Development page:
"Maybe this helps
leahcim.2707 - May 29, 2008 - 05:40
I was trying to get the same thing done and for me this works, but I'm not sure if it is the correct way as I'm still new to Drupal:
in "template.php" I added the following function:
function phptemplate_preprocess_page(&$vars)
{
$css = $vars['css'];
unset($css['all']['module']['modules/system/system.css']);
unset($css['all']['module']['modules/system/defaults.css']);
$vars['styles'] = drupal_get_css($css);
}
I think after adding the function you need to go to /admin/build/themes so that Drupal recognises the function."
The part in bold is what did the trick ... you have to re-save the configuration so it recognizes that you've added a new function to the template.