How insert and publish news in joomla 3.0 from PHP script - php

I try insert some articles from a PHP script but i don´t get it. I need to know what fields are required and how I can create the query to do it.
Now, I´m write the next code:
foreach($RSS_DOC->channel->item as $RSSitem){
$alias = md5($RSSitem->title);
$fetch_date = date("Y-m-j G:i:s"); //NOTE: we don't use a DB SQL function so its database independent
$item_title = $RSSitem->title;
$item_description = $RSSitem->description;
$item_date = date("Y-m-j G:i:s", strtotime($RSSitem->pubDate));
$item_url = $RSSitem->link;
// Does record already exist? Only insert if new item...
$item_exists_sql = "SELECT alias FROM jos_content where alias = ".$alias;
$item_exists = mysqli_query($enlace,$item_exists_sql);
if(mysqli_num_rows($item_exists)<1){
$mensaje = "<p>".$item_description."</p>Publicado: ".$item_date."<br/><a href='".$item_url."'>Ver noticia original</a>";
$item_insert_sql = "INSERT INTO jos_content(title, alias, introtext, state, catid, created, created_by, access,featured) VALUES ('" .$item_title. "', '" . $alias. "', '" . $mensaje. "',1, 10,'".$fetch_date."',448,1,1)";
$insert_item = mysqli_query($enlace,$item_insert_sql);
}
}

First order of business is to create the article data object. I use a method to scrub out an existing id or asset_id references in case I'm migrating article data from one instance to another. This could be replaced by your logic to build out the article data object as well. Just be sure to use an associative array:
function processArticleData($obj) {
$data = array();
foreach ($obj as $key => $value) {
$data[$key] = $value;
}
$data['id'] = 0;
unset($data['asset_id']);
return $data;
}
Next you load the JTable content class, bind the data and save. Joomla does all the rest:
function addArticle($obj) {
// Initialise variables;
$data = processModuleData($obj);
$table = &JTable::getInstance('content');
// Bind the data.
if (!$table->bind($data))
{
echo "<h1>Error Binding Article Data</h1>";
return false;
}
// Check the data.
if (!$table->check())
{
echo "<h1>Error Checking Article Data</h1>";
return false;
}
// Store the data.
if (!$table->store())
{
echo "<h1>Error Storing Article Data</h1>";
return false;
}
return $table->get('id');
}
The benefits of this approach is it removes any "guessing" about required fields or potential errors, as if there is an issue with the data Joomla will throw an exception or error stating what the issue was. If you wanted/needed to get real fancy, you could even load the JForm object for content, bind your data to it and then validate before binding to the JTable object.
Creating the data object has only two requirements. The first is to use an associative array and the second all key names match columns in the #__content table. An example data object would look like this:
$data = array(
'title' => $title,
'alias' => $alias,
'introtext' => $introtext,
'fulltext' => $fulltext,
'catid' => $catid,
'images' => '',
'urls' => '',
'attribs' => '',
'metakey' => '',
'metadesc' => '',
'metadata' => '',
'language' => '',
'xreference' => '',
'created' => JFactory::getDate()->toSql(),
'created_by' => JFactory::getUser()->id,
'publish_up' => JFactory::getDate()->toSql(),
'publish_down' => JFactory::getDbo()->getNullDate(),
'state' => 1
);
I use some more Joomla helper functions to make my job easier, but this should provide a good starting point for you to get the ball rolling.
* EDIT *
Noticed a typo which I corrected. Not sure if you copy/pasted but switch the below line for the array declaration above and test again:
$data = processModuleData($obj);

This script should do it....assuming it exists in the root of your site:
if (!defined('_JEXEC')) {
define( '_JEXEC', 1 );
define ('JPATH_BASE', 'c:\\wamp\\www\\mysiteroot');
require_once ( JPATH_BASE .'/includes/defines.php' );
require_once ( JPATH_BASE .'/includes/framework.php' );
$mainframe = JFactory::getApplication('site');
}
function getContentTable($type = 'Content', $prefix = 'JTable', $config = array())
{
return JTable::getInstance($type, $prefix, $config);
}
function addArticle($title, $alias)
{
$table = getContentTable();
$table->title = $title;
$table->alias = $alias;
$table->catid = 2;
$table->state = 1;
// and so on!
// then save it
$table->store();
}
$result = addArticle("foo", "bar");

Related

Codeigniter transferring data from one table to another using for loop

I am trying to move data from one table to another in my model. In the first two lines I am getting all of the rows in my 'cart' table that match the username. I am now trying to iterate through all of these and match the product ID to the product ID in my 'product' table. I am then trying to format the data to fit my new table called 'sold'. However I am getting an error. I think the syntax of $q->id, $q->product_name etc is wrong. I know you can usually use that in the view but it does not work in the model. Do you know what the correct syntax would be to do this?
function checkout($username){
$this->db->where('username', $username);
$query = $this->db->get('cart');
//$data = array();
foreach ($query as $q){
$product = $this->db->get_where('product', array('id' => $q->id));
$arr['product_id'] = $product->id;
$arr['product_brand'] = $product->item_brand;
$arr['product_name'] = $product->item_name;
$arr['product_image'] = $product->item_image_url;
$arr['product_price'] = $product->item_price;
$arr['product_size'] = $product->item_size;
$arr['name_of_seller'] = $product->name_of_lister;
$arr['name_of_buyer'] = $this->session->userdata('username');
$this->db->insert('sold', $arr);
}
//Deletes the items out of the cart
// $this->db->delete('cart');
}
This is the error message I am getting
You have to use result() to get the data in the the $query variable.
$query = $this->db->get('cart')->result();
In the same way, also change the second query.
$product = $this->db->get_where('product', array('id' => $q->id))->result();
See if this helps you.
function checkout($username){
$this->db->where('username', $username);
$query = $this->db->get('cart');
if ($query->num_rows()>0) {
$qdata = $query->result_array();
foreach ($qdata as $key => $qdvalue) {
$this->db->where('id', $qdvalue['id']);
$product = $this->db->get('product');
$pdata = $product->row_array()
$inarray = array(
'product_id' => $pdata['id'],
'product_brand' => $pdata['item_brand'],
'product_name' => $pdata['item_name'],
'product_image' => $pdata['item_image_url'],
'product_price' => $pdata['item_price'],
'product_size' => $pdata['item_size'],
'name_of_seller' => $pdata['name_of_lister'],
'name_of_buyer' => $this->session->userdata('username')
);
$this->db->insert('sold', $inarray);
}//end of foreach
}//end of if query
}//end of checkout function
I rewrite your function if all the column values right then It will work.
And I will suggest you to use transactions for this type of db events.

mysqli_real_escape_string deleting values

I'm getting null values after I run the DBEscape($data) function that is for SQL injection protection. Can someone help?
My inputs are all multiple arrays, ex: name="quote[][dt_flight]", name="quote[][acft]", etc.
Method is POST.
function DBEscape($data){
$link = DBConect();
if(!is_array($data)){
$data = mysqli_real_escape_string($link,$data);
}
else {
$arr = $data;
foreach ($arr as $key => $value){
$key = mysqli_real_escape_string($link, $key);
$value = mysqli_real_escape_string($link, $value);
$data[$key] = $value;
}
}
DBClose($link);
return $data;
}
function DBCreate($table, array $data, $insertId = false){
$table = DB_PREFIX.'_'.$table;
$data = DBEscape($data);
var_dump($data);
$fields = implode(", ", array_keys($data));
$values = "'".implode("', '", $data)."'";
$query = "INSERT INTO {$table} ({$fields}) VALUES ({$values});";
var_dump($query);
return DBExecute($query, $insertId);
}
if(isset($_POST["quote"]) && is_array($_POST["quote"])){
foreach($_POST["quote"]["dt_flight"] as $key => $text_field){
$last_id = DBCreate('quote',$_POST['quote'],true);
$i++;
}
}
The connection works since it is inserting the rows into the tables. I used vardump before and after the DBEscape to figure out that it is deleting the values, the keys are fine.
PS: The proposed answer is for a single variable not an array.
As you can see in your var_dump-result, the data you sent to DBCreate and thus to DBEscape looks like
array(
'dt_flight' => array(0 => '2018-06-13'),
'acft' => array(0 => 'VQ-BFD',
// and so on
)
Therfore the data you sent to
// $value = array(0 => '2018-06-13') here
$value = mysqli_real_escape_string($link, $value);
And well, mysqli_real_escape_string doesn't like arrays very much, thus will return NULL and thus inserting empty data in your table.
You most likely want to resolve this error within your foreach($_POST["quote"]["dt_flight"]) loop, since I suppose you sent multiple flight-data:
foreach($_POST["quote"]["dt_flight"] as $key => $text_field) {
// $key would be 0, for $_POST["quote"]["dt_flight"][0] = '2018-06-13'
$keyData = [];
foreach($_POST["quote"] as $field => $allFieldValues) {
// Walk over every field, and add the value for the same $key
if (is_array($data) && isset($allFieldValues[$key])) {
// Would add for example $keyData['acft'] = $_POST['quote']['acft'][0] = 'VQ-BFD';
$keyData[$field] = $allFieldValues[$key];
}
}
var_dump($keyData);
// Would look like array(
// 'dt-flight' => '2018-06-13',
// 'acft' => 'VQ-BFD',
// and so on
// )
$last_id = DBCreate('quote',$keyData,true);
$i++;
}
Although this is not part of your question, I really suggest you also take care of my comment on your question about mysqli_real_escape_string not being a safe way to escape column-names (or table-names and so on). For example with following solution:
function DBCreate($table, array $data, $insertId = false) {
// For each table the known columns
$columns = array( 'quote' => array('dt_flight', 'acft', '...') );
// Verify valid table given
if (!isset($columns[$table])) {
throw new InvalidArgumentException('No such table: ' . $table);
}
// Remove everything from data where the key is not in $columns[$table]
// = Remove everything where the column-name is non-existing or even an attempt to hack your system
$data = array_intersect_key($data, array_fill_keys($columns[$table], null));
if (!count($data)) {
throw new InvalidArgumentException('No (valid) data given at all');
}
// Next, continue with your implementation
}

CakePHP 3 fast insertion/updating of records

I am trying to insert/update +/- 10k rows with a foreach loop. The complete loop duration is about 3-5minutes. Are there any tips on my code to do the insertion of update faster? The $rows are retrieved from a xls file converted to domdocument.
foreach($rows as $key => $row)
{
if($key < 1){continue;}
$cells = $row -> getElementsByTagName('td');
foreach ($cells as $cell) {
$project_id = $cells[0]->nodeValue;
$title = $cells[1]->nodeValue;
$status = $cells[2]->nodeValue;
$projectmanager = $cells[3]->nodeValue;
$engineer = $cells[4]->nodeValue;
$coordinator = $cells[5]->nodeValue;
$contractor_a = $cells[6]->nodeValue;
$contractor_b = $cells[7]->nodeValue;
$gsu = $cells[9]->nodeValue;
$geu = $cells[10]->nodeValue;
$query = $this->Projects->find('all')->select(['project_id'])->where(['project_id' => $project_id]);
if ($query->isEmpty()) {
$project = $this->Projects->newEntity();
$project->title = $title;
$project->project_id = $project_id;
$project->status = $status;
$project->projectmanager = $projectmanager;
$project->engineer = $engineer;
$project->coordinator = $coordinator;
$project->contractor_a = $contractor_b;
$project->contractor_b = $contractor_a;
$project->gsu = date("Y-m-d H:i:s");
$project->geu = date("Y-m-d H:i:s");
$project->gsm = date("Y-m-d H:i:s");
$project->gem = date("Y-m-d H:i:s");
if ($this->Projects->save($project)) {
//$this->Flash->success(__('The project has been saved.'));
continue;
}else{
debug($project->errors());
}
}else{
continue;
$query->title = $title;
$query->status = $status;
$query->projectmanager = $projectmanager;
$query->engineer = $engineer;
$query->coordinator = $coordinator;
$query->contractor_a = $contractor_b;
$query->contractor_b = $contractor_a;
$query->gsu = $gsu;
$query->geu = $geu;
if ($this->Projects->save($query)) {
//$this->Flash->success(__('The project has been saved.'));
continue;
}
}
}
//$this->Flash->error(__('The project could not be saved. Please, try again.'));
}
For faster bulk inserts don't use entities but rather generate insert queries directly.
https://book.cakephp.org/3.0/en/orm/query-builder.html#inserting-data
Ello, my vriend.
The TableClass->save() method is useful when saving one single record, in your case, you should use TableClass->saveMany() instead.
For this to happen, you need to treat your entities as arrays inside your foreach.
After the foreach, you will use another method from the tableclass (newEntities) to convert the array into entities before finally save them.
Basic example:
//Lets supose our array after our foreach become something like this:
$all_records =
[
//Each item will be an array, not entities yet
[
'name' => 'I.N.R.I.',
'year' => '1987',
'label' => 'Cogumelo',
'country' => 'Brazil',
'band' => 'Sarcófago',
'line_up' => '[{"name":"Wagner Antichrist","role":"Vomits, Insults"},{"name":"Gerald Incubus","role":"Damned Bass"},{"name":"Z\u00e9der Butcher","role":"Rotten Guitars"},{"name":"D.D. Crazy","role":"Drums Trasher"}]'
],
//Another record coming in..
[
'name' => 'Eternal Devastation',
'year' => '1986',
'label' => 'Steamhammer',
'country' => 'Germany',
'band' => 'Destruction',
'line_up' => '[{"name":"Marcel Schmier","role":"Vocals, Bass"},{"name":"Mike Sifringer","role":"Guitars"},{"name":"Tommy Sandmann","role":"Drums"}]'
]
];
//Time to get the tableclass...
$albums = TableRegistry::get('Albums');
//Time to transform our array into Album Entities
$entities = $albums->newEntities($all_records);
//Now, we have transformed our array into entities on $entities, this is the variable we need to save
if(!$albums->saveMany($entities))
{
echo "FellsBadMan";
}
else
{
echo "FellsGoodMan";
}
You can read more about here

i have an array in an array that contains 3 items, how do I make it go through every item in both arrays?

I am pulling results from an LDAP query with php. One of the items in the array of results is an array with 3 sets of information. How do I make it display all three sets instead of just the first? See my code below:
if ($ds) { $ds=ldap_connect("ldap-server");
$r=ldap_bind($ds);
$sr=ldap_search($ds, "DC=,DC=co,DC=uk",$search);
$info = ldap_get_entries($ds, $sr)or die('get info fail');
$header = array(
t('Picture'),
t('First Name'),
t('Last Name'),
t('Role'),
t('Email')
);
$rows = array();
for ($i=0; $i<$info["count"]; $i++) {
//Handle Image
if(isset($info[$i]["jpegphoto"][0])){
$tempFile = tempnam(sys_get_temp_dir(), 'image');
file_put_contents($tempFile, $info[$i]["jpegphoto"][0]);
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime = explode(';', $finfo->file($tempFile));
$jpeg = '<img src="data:' . $mime[0] . ';base64,' . base64_encode($info[$i]["jpegphoto"][0]) . '"/>';
}else{
$path = drupal_get_path('module','search_engine');
$jpeg = '<img src="'.$path.'/images/userImage.jpg" />';
}
$rows[$i] = array(
'picture' => $jpeg,
'first' => $info[$i]["givenname"][0],
'last' => $info[$i]["sn"][0],
'role' => $info[$i]["memberof"][0],
'mail' => $info[$i]["mail"][0],
);
}
ldap_close($ds);
return theme('table', array('header'=>$header,'rows'=>$rows));
I'm showing picture, first, last, role, and email in my table. Role contains an array with 3 items, how do I make it go through every item in the array? I know I can't just throw a foreach into the middle of an array.
I need to display all of these.
If you don't need to do anything with the individual roles in that sub-array, e.g. display it only, then simply implode() it into a string:
$rows[$i] = array(
...
'roles' => implode(',', $info[$i]['memberof'])
...
);
If you do need do some with the individual components, then deal with it separately:
$rows[$i] = array(...normal non-array data here);
foreach($info[$i]['memberof'] as $key => $value) {
$rows[$i]['role'][$key] = $value;
}
Are you looking for something like implode()?
$roles = array("role1","role2","role3");
$imploded = implode(",", $roles);
echo $imploded; //should return "role1,role2,role3"

Drupal PHP serialize and unserialize

In Drupal, I first serialized emails that appear in the body of private messages and stored them is MySQL like this:
function prvtmsg_list($body) {
$notify = array();
if (isset($body->emails)) {
$notify['mid'] = $body->mid;
$notify['emails'] = serialize($body->emails);
}
if (isset($body->vulgar_words) {
$notify['mid'] = $body->mid;
$notify['vulgar_words'] = serialize($message->vulgar_words);
}
if (isset($notify['mid'])) {
drupal_write_record('prvtmsg_notify', $notify);
}
}
When I later try to retrieve them, email userialization fails, I retrieve them like this:
function prvtmsg_list_notify() {
// Select fields from prvtmsg_notify and Drupal pm_message tables
$query = db_select('prvtmsg_notify', 'n');
$query->leftJoin('pm_message', 'm', 'n.mid = m.mid');
$query->fields('n', array('mid', 'emails', 'vulgar_words'));
$query->fields('m', array('mid', 'author', 'subject', 'body', 'timestamp'));
orderBy('timestamp', 'DESC');
$query = $query->extend('PagerDefault')->limit(20);
$result = $query->execute()->fetchAll();
$rows = array();
foreach ($result as $notify) {
$rows[] = array(
$notify->author,
$notify->subject,
implode(', ', unserialize($notify->emails)),
implode(', ', unserialize($notify->vulgar_words)),
);
}
$build = array();
$build['table'] = array(
'#theme' => 'table',
'#header' => array(
t('Author'),
t('Message subject'),
t('Emails captured'),
t('Vulgar Words Captured'),
),
'#rows' => $rows,
);
$build['pager']['#theme'] = 'pager';
return $build;
}
Maybe the way I serialized the emails is wrong? because:
dpm(unserialize($notify->emails);
gives Array, Array, Array - which means:
Array(
[0] => Array() [1] => Array() [2] => Array() [3] => Array()
)
Surprisingly, the unserialized vulgar words are showing okay! I'm not sure is it possible to serialize the emails like this:
$notify['emails'] = serialize (array($body->emails));
I faced the exact situation in the past where unserialization did not work for me, there is something not clear to me and I need to learn it. Could anyone confirm or tell me what's wrong?
N.B. The above code is from memory and may not be accurate as I currently don't have access to it.
if i am reading this correctly you are writing an array into a db
drupal_write_record('prvtmsg_notify', $notify);
should be:
drupal_write_record('prvtmsg_notify', serialize($notify));
you will most likely no longer need
$notify['emails'] = serialize($body->emails);
and can instead write:
$notify['emails'] = $body->emails;
after retrieving it from the db you can unserialize the array and iterate over it ex:
$array = unserialize(someFunctionToGetPrvtmsg_notifyFromTheDb());
//the array should be the same as the one you serialized

Categories