joomla: use API inside an article - api

I am using the Sourcerer plugin to use PHP code inside my articles. I would like to use the Joomla API/framework inside my article to dynamically set the HTML meta tags and other stuff. I found the setHeadData method that should allow me do that but I have simply no idea as to how calling it.
[Q] Can someone give me 1 example or point me to a tutorial that would help me get started on using that joomla API/framework please?
Answer
Based on the numerous feedbacks all pointing in the same direction, using a content plugin to modify the head data is properly better than doing this via an article. If like me you want to do this in an article here is what I did:
(1) I used the snippet provided by ezpresso to set the head data inside my article.
(2) I modified the libraries/joomla/document/html/renderer/head.php file to change the way the head data was set there.
For instance you can set the title meta tag at step (1) and then at step (2) replace the following line:
$strHtml .= $tab.'<title>'.htmlspecialchars($document->getTitle()).'</title>'.$lnEnd;
with this one:
$strHtml .= $tab.'<title>'.htmlspecialchars($document['metaTags']['standard']['title']).'</title>'.$lnEnd;
You might also want to look into libraries/joomla/document/html/renderer/head.php to do some more cleanup in the head, like getting rid of the generator meta tag that Joomla inserts.

Here is the source code of the method you are referring to:
/**
* Set the html document head data
*
* #access public
* #param array $data The document head data in array form
*/
function setHeadData($data)
{
$this->title = (isset($data['title'])) ? $data['title'] : $this->title;
$this->description = (isset($data['description'])) ? $data['description'] : $this->description;
$this->link = (isset($data['link'])) ? $data['link'] : $this->link;
$this->_metaTags = (isset($data['metaTags'])) ? $data['metaTags'] : $this->_metaTags;
$this->_links = (isset($data['links'])) ? $data['links'] : $this->_links;
$this->_styleSheets = (isset($data['styleSheets'])) ? $data['styleSheets'] : $this->_styleSheets;
$this->_style = (isset($data['style'])) ? $data['style'] : $this->_style;
$this->_scripts = (isset($data['scripts'])) ? $data['scripts'] : $this->_scripts;
$this->_script = (isset($data['script'])) ? $data['script'] : $this->_script;
$this->_custom = (isset($data['custom'])) ? $data['custom'] : $this->_custom;
}
It is implemented in a JDocumentHtml class, which is located in a libraries/joomla/document/html/html.php directory.
Below is the links to some of the examples of how to use it:
setHeadData difference between j1.5 and j1.6
Remove Mootools From Joomla Header
I guess you may call the setHeadData method like this:
$doc =& JFactory::getDocument();
$options = $doc->getHeadData();
$options['metaTags'] = array("tag1", "tag2", "tag3"); // you may change the meta tags here
$doc->setHeadData($options);

Putting PHP in the article is not a very good way to accomplish what you are trying to do. Joomla frameworks has an order of operation that determines when various functions and plugins run. Due to the order of operation, there are numerous functions that will happen after an article is rendered, probably negating any changes you make from within the article. You would be better off either using an extension to handle titles and meta tags rather than trying to do it inside the article.

Related

How to properly create and use dynamic Xpath in JSON (Page Object Model) - Karate DSL

For example, I have this sample JSON object in pages folder which contains all the XPaths for specific page.
{
"pageTitle1": "//*[#class='page-title' and text()='text1']",
"pageTitle2": "//*[#class='page-title' and text()='text2']",
"pageTitle_x" : "//*[#class='page-title' and text()='%s']"
}
* def pageHome = read('classpath:/pages/pageHome.json')
* click(pageHome.pageTitle_x) <-- how to properly replace %s in the string?
Update: I tried the replace function, not sure if this is the proper way.
* click(pageHome.pageTitle_x.replace("%s","new value"))
First a bit of advice. Trying to be "too clever" like this causes maintainability problems in the long run. I have said a lot about this here, please read it: https://stackoverflow.com/a/54126724/143475
That said, you can write re-usable JS functions that will do all these things:
* def pageTitle = function(x){ return "//*[#class='page-title' and text()='" + x "']" }
Now using that you can do this:
* click(pageTitle('foo'))
If you redesign the function even this may be possible:
* click(pageTitle(pageHome.pageTitle_x, 'foo'))
But see how things become more complicated and less readable. The choice is yours. Note that anything you can do in JS (e.g. String.replace()) will be possible, it is up to you and your creativity.

where is "PS_META_DESCRIPTION" and "PS_META_KEYWORDS" and how can i change it?

in classes/Meta.php i found this lines in "completeMetaTags" function:
if (empty($meta_tags['meta_description'])) {
$meta_tags['meta_description'] = Configuration::get('PS_META_DESCRIPTION', $context->language->id) ? Configuration::get('PS_META_DESCRIPTION', $context->language->id) : '';
}
if (empty($meta_tags['meta_keywords'])) {
$meta_tags['meta_keywords'] = Configuration::get('PS_META_KEYWORDS', $context->language->id) ? Configuration::get('PS_META_KEYWORDS', $context->language->id) : '';
}
it seems, when a page doesn't have any keywords or description, it tries to set "PS_META_KEYWORDS" and "PS_META_DESCRIPTION" to those.
but the value of "PS_META_DESCRIPTION" and "PS_META_KEYWORDS" are empty for me and i don't know where can i change these values ?
i searched "configuration" table but i can't find "PS_META_DESCRIPTION" and "PS_META_KEYWORDS" values.
I cannot find what you are searching for in the whole raw Prestashop 1.6 repository, except the legacy code you are talking about.
A way to set this could be to make a simple module with these fields to custom, you can find an helper here : https://validator.prestashop.com
Anyway it's not possible with the actual version, it surely was in the past.

can there be a tooltip with data from the database

I need to know can there be a tooltip populated with data from database to be displayed in the tooltip.
something like the tooltip should contain
name stauts
abc active
xyz active
pqr active
name and status are retrived from db
I need this tooltip onmouseover, am using CJSON decoded to render the content
i did go google but hardly did find that i would throughly understand and implement.
can anyone out there has any ideas for what am looking.
There is a extension named yii-bootstrap, which described clearly here.
For using tooltip easily in this extension, just look here.
I use cluetip for this. Its not related to Yii but will give you some idea :
JS
function renderInfoTips(opts){
var elements=$('#'+opts.form).get(0).elements;
for(i=0; i<opts.tips.length;i++){
$(elements[opts.tips[i].field]).parent().prepend(opts.tips[i].tip);
}
var clue_opts={arrows:true,splitTitle: '|',closePosition: 'title',sticky:true,dropShadow:false,mouseOutClose:true,
onShow:function(ct, ci){
if(!$.browser.webkit) $(ct).css('top',$(ct).position().top- 30+'px');
}
}
$('#'+opts.form).find(".infotip").cluetip(clue_opts);
}
PHP
function setInfoTipsJavascript($form_id,infotips){
if (count($this->infotips) <1 ) return '';
//get all tip names
$names_csv=join(',',array_keys(infotips));
//get tips details from db
$query="select name, description from infotips where FIND_IN_SET(name ,'$names_csv')";
//run the query, in Yii you have to use InfoTipsModel , I have skipped that portion
//$infotipS , lets say this is query object
$tips=array();
while($tip=$infotipS->Assoc()){
$this->infotips[$tip['name']]['tip']="<a href='javascript:void(0)' class='infotip' title='|{$tip['description']}'> </a>";
$tips[]=$this->infotips[$tip['name']];
}
$tips=json_encode($tips);
$script="\nrenderInfoTips({\"form\":'{$form_id}', \"tips\":{$tips}});\n\n";
echo $script;
}
I am sharing this hoping this will give u some idea. Its obvious you have to : create infotips table, a model for that, and create a widget etc to fetch infotips related to your form fields . As someone suggested, if you are using Bootstrap, you have better way to do that.

Check if an existing value is in a database

I was wondering how I would go about checking to see if a table contains a value in a certain column.
I need to check if the column 'e-mail' contains an e-mail someone is trying to register with, and if something exists, do nothing, however, if nothing exists, insert the data into the database.
All I need to do is check if the e-mail column contains the value the user is registering with.
I'm using the RedBeanPHP ORM, I can do this without using it but I need to use that for program guidelines.
I've tried finding them but if they don't exist it returns an error within the redbean PHP file. Here's the error:Fatal error: Call to a member function find() on a non-object in /home/aeterna/www/user/rb.php on line 2433
Here's the code that I'm using when trying this:
function searchDatabase($email) {
return R::findOne('users', 'email LIKE "' . $email . '"');
}
My approach on the function would be
function searchDatabase($email) {
$data = array('email' => $email);
$user = R::findOne('users', 'email LIKE :email, $data);
if (!empty($user)) {
// do stuff here
} // end if
} // end function
It's a bit more clean and in your function
Seems like you are not connected to a database.
Have you done R::setup() before R::find()?
RedBeanPHP raises this error if it can't find the R::$redbean instance, the facade static functions just route calls to the $redbean object (to hide all object oriented fuzzyness for people who dont like that sort of thing).
However you need to bootstrap the facade using R::setup(). Normally you can start using RB with just two lines:
require('rb.php'); //cant make this any simpler :(
R::setup(); //this could be done in rb.php but people would not like that ;)
//and then go...
R::find( ... );
I recommend to check whether the $redbean object is available or whether for some reason the code flow has skipped the R::setup() boostrap method.
Edited to account for your updated question:
According to the error message, the error is happening inside the function find() in rb.php on line 2433. I'm guessing that rb.php is the RedBean package.
Make sure you've included rb.php in your script and set up your database, according to the instructions in the RedBean Manual.
As a starting point, look at what it's trying to do on line 2433 in rb.php. It appears to be calling a method on an invalid object. Figure out where that object is being created and why it's invalid. Maybe the find function was supplied with bad parameters.
Feel free to update your question by pasting the entirety of the find() function in rb.php and please indicate which line is 2433. If the function is too lengthy, you can paste it on a site like pastebin.com and link to it from here.
Your error sounds like you haven't done R::setup() yet.
My approach to performing the check you want would be something like this:
$count = count(R::find('users', 'email LIKE :email', array(':email' => $email)));
if($count === 0)
{
$user = R::dispense('users');
$user->name = $name;
$user->email = $email;
$user->dob = $dob;
R::store($user);
}
I don't know if it is this basic or not, but with SQL (using PHP for variables), a query could look like
$lookup = 'customerID';
$result = mysql_fetch_array(mysql_query("SELECT columnName IN tableName WHERE id='".$lookup."' LIMIT 1"));
$exists = is_null($result['columnName'])?false:true;
If you're just trying to find a single value in a database, you should always limit your result to 1, that way, if it is found in the first record, your query will stop.
Hope this helps

drupal bootstrap script: how to get list of all nodes of type x?

I create a custom import and export, at the moment as an external script (via bootstrap), i plan to create a module in a more generic fashion lateron.
I am building a frontend for nagios and for our host management and nagios configuration btw. Maybe it might become useful for other environments (networkmanagement)
Now i need to know how to get list of all nodes of type x?
I want to avoid direct SQL.
A suggestion i got was to make an rss and parse it
but i acess the drupal db a dozen times to extract various nodes, so it feels strange to do a web request for one thing
So what i am looking for as newbie drupal dev is just a pointer to basic search module api for this task
TIA
florian
Why do you want to avoid using SQL?
If you want to get info about what's in your db, like all the nodes of type x, the only way to get it, is through a SQL query, unless you have the data extracted already.
A query like
db_query("SELECT title, nid FROM {node} WHERE type = 'x';");
shouldn't be the thing that ruins your performance.
Edit:
The link you provided is a from Drupal 7, so you have to be be careful reading this. The reason is that in Drupal 7 it is not only possible to use db_query which basically is wrapper for the php functions mysql_query, pg_query. It's a bit different and using it, you wont have to use db_specific code. Anyways new in Drupal 7 is something that is a bit like an ORM. I haven't read about it in detail, but the idea is that you can build a query using commands on an object. This is probably what you are after. However, Drupal 7 is not ready at all for production sites. There are still a lot of critical issues and security issues. So this wont be a possibility for quite some time.
Edit 2:
If you want to get the node title and body, this is what you should do:
$type = 'x';
$query = db_query("SELECT r.nid, r.title, r.body FROM {node} AS n
LEFT JOIN {node_revisions} AS r ON r.nid = n.nid
WHERE type = '%s';", array($type));
$nodes = array();
while ($node = db_fetch_object($query)) {
$nodes[$node->nid] = $node;
}
You can use db_fetch_array instead of db_fetch_object` if you want to extract arrays instead of objects from the db.
This is a pretty old question, but for anyone coming across this page now, in Drupal 7.x best practise is to use dynamic queries.
So if you wanted to select all the nodes of type x, you could do the following:
$articles = db_select('node')
->fields('node', array('nid', 'title'))
->condition('type', 'x', '=')
->execute()
->fetchAllKeyed();
The $articles variable should then be an array of all x type nodes, keyed by nid with the arrays corresponding value set to the node title. Hope that can help.
Views is generally how you create database queries without writing them in Drupal, but this query is so simple I'm not sure it's worth the overhead of learning views, barely 5 lines after you've bootstrapped Drupal:
$nodes = array();
$results = db_query("SELECT nid FROM {node} WHERE type = '%s'", $type);
while ($result = db_fetch_object($result)) {
$nodes[] = node_load($result->nid);
}
Gotta use SQL do to this.
http://api.drupal.org/api/function/node_get_types/6
Node counts =
$node_types = node_get_types();
$type_count = array();
foreach ($node_types as $type) {
$result = db_fetch_object(db_query('SELECT count(nid) AS node_count FROM {node} WHERE type = "%s"'), $type);
$type_count[$type] = $result['count(nid)'];
}
print_r($type_count);
Nodes and their type:
$node_types = node_get_types();
$nodes = array();
foreach ($node_types as $type) {
$result = db_query('SELECT nid, title FROM {node} WHERE type = "%s"'), $type);
while ($node = db_fetch_object($result)) {
$nodes[] = array('Type' => $type, 'Title' => $node->title);
}
}
print_r($nodes);
Something like that. I am eating lunch so I didn't test that but I have done this before so it should work. Drupal 6.
The migrate module may be of interest to you. It also supports drush so you can script things fairly easily.