Where to specify cache context to operate on all pages? - caching

I would like to configure my Drupal 8 website so that any time query parameter "refcode" is used to visit my site, that value is replicated on all menu links on that page. For example, using https://www.example.com?refcode=joe would add "?refcode=joe" to all menu links on that page. Once someone enters the site using a particular refcode, then using menu links to navigate around the site would preserve that refcode and using menu links to navigate away from the site would also preserve that refcode on external menu links.
When the cache is empty, this code works:
function mymodule_link_alter( &$variables )
{
if ( $refcode = \Drupal::request( )->query->get( 'refcode' ) )
$variables['options']['query']['refcode'] = $refcode;
}
When the page is cached, it doesn't. I have tried adding this:
$variables['#cache']['contexts'][] = 'url.query_args:refcode';
but that does not work. I think I have to add this caching directive somewhere else, but I don't know where. Is there a place where I can instruct Drupal 8 to take "refcode" into account when retrieving any cached page?

I finally figured this out. I have to determine which block types and which node types might reference the refcode query parameter and update the cache settings for them:
function mymodule_preprocess_block( &$variables )
{
if ( $variables['base_plugin_id'] == 'system_menu_block' )
$variables['#cache']['contexts'][] = 'url.query_args:refcode';
}
function mymodule_preprocess_node( &$variables )
{
if ( $variables['node']->bundle( ) == 'main' )
$variables['#cache']['contexts'][] = 'url.query_args:refcode';
}

Related

Google Sitemap issue Contao 4.4

I am using contao 4.4 instance.I have a problem in google sitemap generation.
I have a newsletter page (page type = regular ) . In that page I have some newsletter articles (with teaser) . When I generate the sitemap, the url of these articles generated twice. When I checked the core I found a class which creates the page array for generating sitemap
vendor/contao/core-bundle/src/Resources/contao/classes/Backend.php
line no 662 - 680 .
Which append 'articles/' to the articles with teaser. So the sitemap generates url
with articles/
List item
without articles/
The first one is the correct url.Second Url generate 404. How I fix the issue ?
My siteconfiguration is as follows
->created a regular page with hidden in navigation and created articles with configuration show teaser
->created another page and created elements as 'teaser articles' and select articles from the above page
So your site structure is like this?
Page 1 with multiple articles
Page 2 with one article containing an „article teaser“ element, this page should be excluded from the sitemap
Is that correct? If yes this might be the solution:
In your „site structur“ you can EDIT Page 2: Scroll down to „Expert settings“, there is an option „Show in sitemap“ and you can select „Never show“.
I resolved the issue.
The url's were regenerated from the newsletter-bundle. In core bundle, the url of the article with teaser is generated. The newsletter-bundle is also contain hook for creating searchable page array. The hook regenerates the url. I wrote a function in vendor/contao/newsletter-bundle/src/Resources/contao/classes/Newsletter.php to check whether the array contain any duplicate url.
Modified function getSearchablePages() ( line 889-897
)
if($this->checkValidUrl($arrPages, $objItem, $strUrl)){
$arrPages[] = sprintf($strUrl, ($objItem->alias ?: $objItem->id));
}
Defining new function for finding duplicate
public function checkValidUrl($arrPages, $objItem, $strUrl)
{
$alias = $objItem->alias ?: $objItem->id;
$urlExplode = explode('%s', $strUrl);
$articleUrl = $urlExplode[0] . 'articles';
foreach ($arrPages as $arrPage) {
$validarticleUrl = $articleUrl . '/' . $alias;
if (strcasecmp($arrPage,$validarticleUrl) == 0) {
return false;
}
}
return true;
}

ALERT SESSION VALUE FROM first page to 2nd page using JQuery,ajax, or javascript

hi guyz this is my first time here. ahmmm i'd like to ask some question regarding session. ahmm
how i cant alert session value from first page to 2nd page using jquery,ajax, or javascript??
please help, im new on that language. ):
You can pass value from one page to other using url query string.
one link to second page add data as parameter like http://your-url.com?data=user-session-value
in the second page call the below javascript function in onload or where you need value
function getParameterByName(name) {
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
results = regex.exec(location.search);
return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}
you can alert the value like alert(getParameterByName('data'));
In this way your data will show in url. if you don't want to show it then use localstorage. But you need to be in same domain. I mean u can't pass data from one website to other.
In page one just set the data in local storage like localStorage.setItem('data', 'user-session-value');To alert the data in second page call alert(localStorage.getItem('data'));
Hope this can solve your issue... Happy coding...

Removing id variables in joomla v1.5 router

I have custom Joomla(v1.5) component and currently working with component's router. The problem is I can't remove id numbers from SEF url. I get:
http://myaddress.com/componentalias/17-city-alias/130-item-alias
What I want to get:
http://myaddress.com/componentalias/city-alias/item-alias
Take a look at router.php methods below:
function ComponentnameBuildRoute(&$query) {
$segments = array();
if(isset($query['city_id'])){
$segments[] = $query['city_id'];
unset($query['city_id']);
}
if(isset($query['item_id'])){
$segments[] = $query['item_id'];
unset($query['item_id']);
}
if(isset($query['task'])){
switch($query['task']){
case 'pay':
$segments[] = JText::_('payment');
unset($query['task']);
break;
}
}
unset($query['view']);
return $segments;
}
/*
* Function to convert a SEF URL back to a system URL
*/
function ComponentnameParseRoute($segments) {
$var = array();
if(isset($segments[0])){
$cityData = explode(':',$segments[0]);
if(isset($cityData[0])){
$vars['city_id'] = $cityData[0];
}
}
if(isset($segments[1])){
$itemData = explode(':',$segments[1]);
if(isset($itemData[0])){
$vars['item_id'] = $itemData[0];
}
}
if(isset($segments[2])){
switch($segments[2]){
case JText::_('payment'):
$vars['task'] = 'pay';
break;
}
}
return $vars;
}
Any ideas? Your help would be appreciated.
The best place to start with your router.php file is reading this article (it's a bit dated but still good) and then reviewing the com_content's router.php file (components/com_content/router.php). You will notice that articles do achieve what you want so best to look at working code and got from there.
Longer answer:
You can only get rid of the item ID variables in a path to a content element if a menu item exists that points directly to the item, otherwise there is no way to find the item.
SEF URLs in Joomla! 1.5 etc are made from the alias' of the individual elements
eg. If I have this menu structure:
Recipes (The menu)
-- Seafood (<-- Category blog where category alias is `seafood` )
-- Grilled Snapper (<-- Recipe Item where item alias is `grilled-snapper` )
-- 'Other category' (<-- Another Category blog )
Full ID Removal
In the case where you're building the SEF URL for a recipe you can build the route by looking for the menu item it might appear in by getting the site menu $menu = &JSite::getMenu(); and comparing the query id in the current menu item against id value in the $query array passed in.
If you have a match you can build the segments up using the alias from the menu path and the recipe alias. (And reverse the process in your ParseRoute($segments) method).
So, from this example above you could build a SEF URL to the Grilled Snapper recipe that looks something like: recipes/seafood/grilled-snapper.
Partial ID Removal
Now say you also have another recipe (e.g. 'Garlic Prawns' alias garlic-prawns) that isn't directly linked to a menu but will appear in the 'Seafood' category blog page. In this situation you would end up with recipes/seafood/2:garlic-prawns
If you don't have a match (like the Garlic Prawns), you can build up partial match if your component has list views like category blogs or in our example Recipe category pages... Essentially in this case you look at the current menu item and determine if it's a list/category view that would contain the content item.
If it is then the path to the category/list view form you initial segments, but as there is no menu item for the article you will still have to use the ID of the item in the last element of the URL.
No Menu Item for content item or a list/category view
When the content item is being linked to directly (e.g. from an article, module or search result) and there are no menu items that point to it or could contain it then you can still create a URL without id's in it but you will be providing the path in the form of direct component access URL.
eg. /component/recipes/recipe/ice-cream-sundae where recipes is the name of the component, recipe is the view and ice-cream-sundae is the alias of the article.

Override Joomla Menu Itemid parameter from frontend

We know that Joomla 1.6 and up has access levels groups settings but this little hack could help everyone from 1.5 and up
this there outputs the params from specific Joomla menu item
$menus = &JSite::getMenu();
print_r($menus ->_items[170]);
where 170 are the parameters for menu item id 170 , now
there is a setting called published , what I am trying to achieve is show menu item to visitors only by globally setting the $menus ->_items[170]->published to 0 instead 1 when user is logged in
but changing that array value is hard so if you could please just check if you can change the value output from 1 to 0 by using provided info.
f we can get that to work than code snippet could be something like
if ( !$user->id ) {
$menus = &JSite::getMenu(); $menus ->_items[170]->set('published',0); }
but set() does not work for menu item id's
Thank you!
Why not just set the menu item access to registered in the menu parameters? Then the item only displays when the user is logged in. This is a built in behavior in Joomla.

codeigniter category -> subcategory -> subsubcategory system

ok, so i'm very new to codeigniter and from what i have learned by now i can't figure out how can i create a dynamic category -> subcategory -> subsubcategory system. Can you give me some guidelines please...some references, anything to guide me on what should i learn to accomplish that? thanks
i should get my URL like this www.site.com/category/subcategory/subsubcategory/etc... , you know what i mean.
I have done this for the page manager in PyroCMS but it is no easy task.
Each page has its own slug and parent_id, then to read the correct page it loops through each of the page slugs and joins the child. It knows how many children there are so if there are 5 children it selects the 5th self-joined table.
Here is an example of the code:
public function get_by_path($segments = array())
{
// If the URI has been passed as a string, explode to create an array of segments
if(is_string($segments))
{
$segments = explode('/', $segments);
}
// Work out how many segments there are
$total_segments = count($segments);
// Which is the target alias (the final page in the tree)
$target_alias = 'p'.$total_segments;
// Start Query, Select (*) from Target Alias, from Pages
$this->db->select($target_alias.'.*');
$this->db->from('pages p1');
// Loop thorugh each Slug
$level = 1;
foreach( $segments as $segment )
{
// Current is the current page, child is the next page to join on.
$current_alias = 'p'.$level;
$child_alias = 'p'.($level - 1);
// We dont want to join the first page again
if($level != 1)
{
$this->db->join('pages '.$current_alias, $current_alias.'.parent_id = '.$child_alias.'.id');
}
// Add slug to where clause to keep us on the right tree
$this->db->where($current_alias . '.slug', $segment);
// Increment
++$level;
}
// Can only be one result
$this->db->limit(1);
return $this->db->get()->row();
}
It's a bit nuts but it works perfectly. This can be really slow so PyroCMS also maintains a look-up table which has id and the page URI to match quickly.
You can see the whole model here:
http://github.com/philsturgeon/pyrocms/blob/master/application/modules/core/pages/models/pages_m.php
you could:
create controller category, reroute some URIs to it and use it's internal logic to parse it's arguments to pick whatever article client requested:
About URLs:
http://codeigniter.com/user_guide/general/urls.html
About URI routing:
http://codeigniter.com/user_guide/general/routing.html
I agree with Phil's idea and I was also envisioning that you can create a separate module (if you use modular extensions for example) to handle the categories in a generic way. Then you can reuse that module in any other projects. Basically the new module may be able to handle categories and sub-categories (the hierarchy).

Resources