I am using Joomla 2.5 and I want to change the canonical link in the header.
I do this in category view (components/com_content/category/tmpl/default.php)
$url = JURI::root();
$sch = parse_url($url, PHP_URL_SCHEME);
$server = parse_url($url, PHP_URL_HOST);
$canonical = $this->escape($_SERVER['REQUEST_URI']);
$document->addCustomTag('<link rel="canonical" href="'.$sch.'://'.$server.$canonical.'"/>');
It prints the right canonical, but it also leaves the old canonical link there so that I have 2 canonical links in the header.
How can I change or delete the old canonical link?
I have found the following to work for me with Joomla! 3.2.1. You can directly modify the
$_links
variable in the JHtmlDocument object.
I'm doing a subset of the following in a particular view of my component because the URL that Joomla! is coming up with is not correct.
Hope this helps.
$document = JFactory::getDocument();
foreach($document->_links as $key=> $value)
{
if(is_array($value))
{
if(array_key_exists('relation', $value))
{
if($value['relation'] == 'canonical')
{
// we found the document link that contains the canonical url
// change it!
$canonicalUrl = 'http://www.something.com/index.php/component/my-component-name-here/?view=viewNameHere¶meterNameHere=parameterValueUsedInTheViewRightNow
$document->_links[$canonicalUrl] = $value;
unset($document->_links[$key]);
break;
}
}
}
}
What you probably want to do instead is something like the following:
$doc_data = $document->getHeadData();
$url = JURI::root();
$sch = parse_url($url, PHP_URL_SCHEME);
$server = parse_url($url, PHP_URL_HOST);
$canonical = $this->escape($_SERVER['REQUEST_URI']);
$newtag = '<link rel="canonical" href="'.$sch.'://'.$server.$canonical.'"/>'
$replaced = false;
foreach ($doc_data['custom'] as $key=>$c) {
if (strpos($c, 'rel="canonical"')!==FALSE) {
$doc_data['custom'][$key] = $newtag;
$replaced = true;
}
}
if (!$replaced) {
$doc_data['custom'][] = $newtag;
}
$document->setHeadData($doc_data);
This will grab all of the current head data from the document, including the canonical link that you want to replace. It will search through the custom set (where I'm guessing this will be) and if it finds it, replace it with yours. If it doesn't find it, then it tacks it on at the end. Just in case.
Potential problems with this that I can see right away:
If the tag contained rel='canonical' with single quotes it would not be found, so you may have to adjust that.
The tag may have been placed in a different section of what I've termed $doc_data. You may want to do a var_dump($doc_data}; to confirm the location of the variable in this array.
Related
I have a code set on Laravel. This is doing dns verification, I want to verify a specific field in the meta tag I want.
Example code
public function verifyDomainDns()
{
$fqdn = sprintf('%s.%s', $this->getVerificationTxtName(), $this->name);
$results = collect(dns_get_record($fqdn, DNS_TXT));
$results = $results->where('type', 'TXT')
->where('txt', $this->verification_token);
$this->domain_verified = $results->isEmpty() ? self::UNVERIFIED : self::VERIFIED;
$this->save();
}
verification_token Auto-generated numbers registered in database
The meta tag I want to verify.
<meta name="book" content="verification_token" />
There is no correlation between what your code is already doing and what you want to do.
One way you can achieve this is to get the contents of the URL with something like file_get_contents(), which will result in you getting the HTML content of the URL.
Once you have this, you can use something like DOMXpath to parse it and get the meta tag's contents.
$html = file_get_contents('https://example.com');
$dom = new DomDocument();
$dom->loadHTML($html);
$xpath = new DomXPath($dom);
$contents = $xpath->query('/html/head/meta[#name="book"]/#content');
if ($contents->length === 0) {
echo 'No tag found';
} else {
foreach ($contents as $content) {
echo $content->value;
}
}
I have spent nearly two days going in circles on this one.
I seem to have difficulty using $_SESSION or $_POST as strings in any query or converting them to strings to use.
I am using a simple hash approach to login to a site.
Extract from script is
<?php
session_start();
echo "******Running Authenticate<br>";
echo "data submitted<br>".$_POST['site_login']."<br>".$_POST['site_password']."<br><br>";
$SiteLogin = $_POST['site_login']
$_SESSION['site_login'] = $_POST['site_login'];
$_SESSION['site_password'] = $_POST['site_password'];
$_SESSION['session_id'] = session_id();
$_SESSION['Now_val'] = date('Y-m-d H:i:s');
//include 'showallvars.php';
include 'dbconfig.php';
// Prepare our SQL
if ($stmt = $con->prepare('SELECT site_index, site_password FROM web_sites WHERE site_login = ?')) {
// Bind parameters (s = string, i = int, b = blob, etc), hash the password using the PHP password_hash function.
$stmt->bind_param('s', $_POST['site_login']);
$stmt->execute();
$stmt->store_result();
// Store the result so we can check if the account exists in the database.
if ($stmt->num_rows > 0) {
$stmt->bind_result($id, $password);
$stmt->fetch();
echo "account exists";
}
else
{
header('Location: badindex.php');
}
if (password_verify($_POST['site_password'], $password)) {
// Verification success! User has loggedin!
echo "password good";
}
else
{
header('Location: badindex.php');
}
}
$_SESSION['loggedin'] = TRUE;
?>
that works fine
BUT there is another field ( 'site_name') in the record which i want to carry forward.
This should be easy !!
and there is a dozen ways of doing it
for example the "standard" example is something like
$name = $mysqli->query("SELECT site_name FROM web_sites WHERE site_login = 'fred'")->fetch_object()->site_name;
That works fine
but no matter how i try - concatenating or or ... I cannot get $_SESSION['site_login'] or $_POST['site_login'] to replace 'fred'.
There seems to be white space added in.
Assistance or guidance ?
It should be possible to as easy as doing the following:
So:
if ($stmt = $con->prepare('SELECT site_index, site_password
FROM web_sites WHERE site_login = ?')) {
becomes:
if ($stmt = $con->prepare('SELECT site_index, site_password, site_login
FROM web_sites WHERE site_login = ' . $SiteLogin)) {
Do note, it is bad practice to do directly parse $SiteLogin to a query, because now someone can SQL Inject this and hack your website. All they need to do is use your form and figure out that which field is responsible for $SiteLogin. You would need to escape your $SiteLogin. Assuming Mysqli, it would become:
if ($stmt = $con->prepare('SELECT site_index, site_password, site_login
FROM web_sites WHERE site_login = ' . $con->real_escape_string($SiteLogin))) {
Thank you for that BUT the instant I saw the curly brackets in your answer - it all came flooding back to me. I had forgotten that PHP has problems with the square brackets
$sql = ("SELECT site_name FROM web_sites WHERE site_login = '". $_SESSION{'site_login'} ."' LIMIT 1");
I KNEW it was easy !
Your comments on injection are of course correct but this was an edited code excerpt and $SiteLogin was just added in as a "temporary working variable if needed"
I have a content type of resource that has five different resource types (video, article, book, etc.). Each of these resources has a main image field (field_image). If the user doesn't provide an image I want to fallback to a default image. However, I would like the default image to be based on the type of resource (video, article, book, etc.). Is there a module or solution to do this within the Drupal UI? I need the image to be attached to the content type (not hard coded in templates) so that it displays properly on detail, list, and other view pages.
Expected Functionality
Resource: field_type = article; field_image = default_article.jpg
Resource: field_type = book; field_image = default_book.jpg
Resource: field_type = video; field_image = default_video.jpg
What I've tried
Google: I've tried but failed to find anything that would make this possible. I understand by default Drupal allows only one default image per content type. I could make a new content type for each of my five types, but that seems unnecessary and clunky.
Hard code: I have a template for my resource detail page where I've hard coded the relevant default image to show if there is no image present, but this doesn't scale well as I have many views (resource list, related resources, etc.) where I am displaying resource images.
Conditional Fields: I've tried the module Field Dependencies (e.g., when field_type = x, set field_image = y), but it doesn't appear to work with files.
Thanks!
The hook_field_attach_view_alter() is your way to go, if your view uses the content display (and not field by field). If your view relies on field display, you can try hook_field_attach_load().
function yourmodule_field_attach_view_alter(&$output, $context) {
// Append RDF term mappings on displayed taxonomy links.
if ($context['entity_type'] == 'node' && $context['entity']->type == 'resource') {
foreach (element_children($output) as $field_name) {
if ($field_name == 'field_resource') {
$element = &$output[$field_name];
foreach ($element ['#items'] as $delta => $item) {
yourmodule_defaultimg($item, $node->field_resource_type['und'][0]['value']);
}
}
}
}
}
function yourmodule_defaultimg(&$item, $resource_type) {
switch($resource_type) {
case "Article":
$filename = 'default_resource_article.jpg';
$uri = 'public://default_images/default_resource_article.jpg';
break;
case "Book":
$filename = 'default_resource_book.jpg';
$uri = 'public://default_images/default_resource_book.jpg';
break;
case "Video":
$filename = 'default_resource_video.jpg';
$uri = 'public://default_images/default_resource_video.jpg';
break;
case "Tool":
$filename = 'default_resource_tool.jpg';
$uri = 'public://default_images/default_resource_tool.jpg';
break;
case "Picture of Practice":
$filename = 'default_resource_picture-of-practice.jpg';
$uri = 'public://default_images/default_resource_picture-of-practice.jpg';
break;
}
$item['uri'] = $uri;
$item['filename'] = $filename;
}
Here's what I managed to do to solve this. If anyone has a better suggestion I would love to hear it.
I have two places where I render resources: the node page and within a view.
I added the following functions to my template.php file for my theme.
This function to preprocess the node page:
function MYTHEME_preprocess_page(&$vars) {
if($vars['node']->type == 'resource') {
renderResourceDefaultImg($vars['node'], 'node');
}
}
and this function to prerender the view block:
function MYTHEME_views_pre_render(&$view) {
if($view->current_display == 'BLOCKID') {
foreach($view->result as $resource) {
renderResourceDefaultImg($resource, 'view');
}
}
}
Here is the renderResourceDefaultImg function that I added to the bottom of my template.
function renderResourceDefaultImg($resource, $displayType) {
$resource_type_view = $resource->field_field_resource_type[0]['rendered']['#markup'];
$resource_type_node = $resource->field_resource_type['und'][0]['value'];
$resource_type = (!empty($resource_type_view)) ? $resource_type_view : $resource_type_node;
switch($resource_type) {
case "Article":
$filename = 'default_resource_article.jpg';
$uri = 'public://default_images/default_resource_article.jpg';
break;
case "Book":
$filename = 'default_resource_book.jpg';
$uri = 'public://default_images/default_resource_book.jpg';
break;
case "Video":
$filename = 'default_resource_video.jpg';
$uri = 'public://default_images/default_resource_video.jpg';
break;
case "Tool":
$filename = 'default_resource_tool.jpg';
$uri = 'public://default_images/default_resource_tool.jpg';
break;
case "Picture of Practice":
$filename = 'default_resource_picture-of-practice.jpg';
$uri = 'public://default_images/default_resource_picture-of-practice.jpg';
break;
}
if($displayType == 'view') {
$resource->field_field_image[0]['rendered']['#item']['filename'] = $filename;
$resource->field_field_image[0]['rendered']['#item']['uri'] = $uri;
} elseif($displayType == 'node') {
$resource->field_image['und'][0]['uri'] = $uri;
$resource->field_image['und'][0]['filename'] = $filename;
}
}
You could derive your default image from your field type with a rewrite in a view:
if you have a field field_type = article/video/... specified in a taxonomy. you could get the default image by specifying it as:
default_[field_type].jpg
(where field_type is a token). You'd want to do this if there were 'No results' for your image name.
The solutions above would be much more generally applicable.
I'm having trouble with my component and Joomla's SEF links. I'm trying to use JRequest::getVar to get the variables from the original URL (specified with JRoute::_)
My router.php file looks like this:
function PortfolioBuildRoute(&$query)
{
$segments = array();
if (isset($query['category'])) {
$segments[] = $query['category'];
unset($query['category']);
}
if (isset($query['subcategory'])) {
$segments[] = $query['subcategory'];
unset($query['subcategory']);
}
return $segments;
}
function PortfolioParseRoute($segments)
{
$vars = array();
$count = count($segments);
if ($count) {
$count--;
$segment = array_shift($segments);
if (is_numeric($segment)) {
$vars['subcategory'] = $segment;
} else {
$vars['category'] = $segment;
}
}
if ($count) {
$count--;
$segment = array_shift($segments) ;
if (is_numeric($segment)) {
$vars['subcategory'] = $segment;
}
}
return $vars;
}
The URL I'm encoding originally looks like:
index.php?option=com_portfolio&category=x&subcategory=y and JRoute::_ turns it into /portfolio/x/y. What I need now is some way of getting the variables x and y after the url is encoded?
----EDIT----
Ok so I figured it out - I changed the ParseRoute part of the router.php file to:
function PortfolioParseRoute($segments)
{
$vars = array();
$vars['category'] = str_replace(":", "-", $segments[0]);
$vars['subcategory'] = str_replace(":", "-", $segments[1]);
return $vars;
}
I feel I've got a slightly better understanding of the router.php file now. It turns out JRoute converts hyphens in your url to colons! Don't quite know why it picks on the poor hyphens, big JRoute bully. I could use underscores in the URL and it would function fine but hyphens are better SEO than underscores.
I used str_replace on each of the segments in ParseRoute to sort this out.
I'm not sure if this is the correct and standards way to go about this but I'm a Joomla and PHP noob so it will have to do until I'm advised otherwise.
At least it works!
:)
I want to create some kind of sitemap in extbase/fluid (based on the pagetree). I have loaded the pages table into a model:
config.tx_extbase.persistence.classes.Tx_MyExt_Domain_Model_Page.mapping.tableName = pages
I have created a controller and repository, but get stuck on the part wich can load the subpages as relation into my model.
For example:
$page = $this->pageRepository->findByPid($rootPid);
Returns my rootpage. But how can I extend my model that I can use $page->getSubpages() or $page->getNestedPages()?
Do I have to create some kind of query inside my model? Or do I have to resolve this with existing functions (like the object storage) and how?
I tried a lot of things but can simply figure out how this should work.
you have to overwrite your findByPid repository-method and add
public function findByPid($pid) {
$querySettings = $this->objectManager->create('Tx_Extbase_Persistence_Typo3QuerySettings');
$querySettings->setRespectStoragePage(FALSE);
$this->setDefaultQuerySettings($querySettings);
$query = $this->createQuery();
$query->matching($query->equals('pid', $pid));
$pages = $query->execute();
return $pages;
}
to get all pages. Than you can write your own getSubpages-method like
function getSubpages($currentPid) {
$subpages = $this->pagesRepository->findByPid($currentPid);
if (count($subpages) > 0) {
$i = 0;
foreach($subpages as $subpage) {
$subpageUid = $subpage->getUid();
$subpageArray[$i]['page'] = $subpage;
$subpageArray[$i]['subpages'] = $this->getSubpages($subpageUid);
$i++;
}
} else {
$subpageArray = Array();
}
return $subpageArray;
}
i didn't test this method, but it looks like this to get alle subpages.
i wonder that i couldĀ“t find a typo3 method that return the complete Page-Tree :( So i write a little function (you can use in an extbase extension), for sure not the best or fastes way, but easy to extend or customize ;)
first you need an instance of the PageRepository
$this->t3pageRepository = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\Page\\PageRepository');
this->t3pageRepository->init();
make the init, to set some basic confs, like "WHERE deletet = 0 AND hidden = 0..."
then with this function you get an array with the page data and subpages in. I implement yust up to three levels:
function getPageTree($pid,$deep=2){
$fields = '*';
$sortField = 'sorting';
$pages = $this->t3pageRepository->getMenu($pid,$fields,$sortField);
if($deep>=1){
foreach($pages as &$page) {
$subPages1 = $this->t3pageRepository->getMenu($page['uid'],$fields,$sortField);
if(count($subPages1)>0){
if($deep>=2){
foreach($subPages1 as &$subPage1){
$subPages2 = $this->t3pageRepository->getMenu($subPage1['uid'],$fields,$sortField);
if(count($subPages2>0)){
$subPage1['subpages'] = $subPages2;
}
}
}
$page['subpages'] = $subPages1;
}
}
}
return $pages;
}