Joomla Component error - Fatal error - arrays

I have installed a ticket module on my Joomla website, I get the following error when a ticket is submitted
Fatal error: Call to undefined method JRegistry::getValue() in /home/xboxfifa/public_html/HD/components/com_jtaghelpdesk/controller.php on line 300
function mailme($formData){
$version = new JVersion();
$body = "A new inquiry has been recieved: <br /> Name : ". $formData['inqName']. "<br /> Email ID : ". $formData['inqEmail']. "<br/> Message : ".$formData['inqMessage'] ;
$mailer =& JFactory::getMailer();
$config =& JFactory::getConfig();
if($version->RELEASE==3.0)
{
$recipient = array(
$config->get('mailfrom'),
$config->get('fromname'));
}else
{
$recipient = array(
$config->getValue( 'config.mailfrom' ),
$config->getValue( 'config.fromname' ));
}
$mailer->addRecipient($recipient);
$subject=$formData['inqSubject'];
$mailer->setSubject($subject);
$mailer->isHTML(true);
$mailer->Encoding = 'base64';
$mailer->setBody($body);
$send =& $mailer->Send();
if ( $send !==true )
{ $msg = 'Reply not Sent!';
} else
{
$msg = 'Reply Sent Successfully!';
}
}
If anyone could help me I would appreciate it.

JRegistry::getvalue() was removed in Joomla 3.x so make sure you use JRegistry::get() instead.
As for your version compare, you should use this:
if (version_compare(JVERSION, '3.0.0', 'ge')){
// code here
}

Editing this answer because I realized the issue is something else. The problem here is the $version check you're doing looks for the release to be EXACTLY == 3.0. When really you want that get() method to be used for 3.0 and up. You should change your if-statement to:
if($version->RELEASE >= 3.0)
{ ... }
Because you're using 3.2.1 this will use the proper method gets for that version.

Related

GetLowestPricedOffersForSKU failed processing arguments

I have a slight issue when trying to call GetLowestPricedOffersForSKU, I get the response :
Failed processing arguments of org.jboss.resteasy.spi.metadata
I can call other functions in the Product Api and they work fine, just get the above error on this function.
I have looked round the net for the answer but can't find anything that is related to this, does anybody have any idea why I'm getting this ?
By the way it all works fine in the MWS Scratchpad !
Posting in case anyone else comes to this and is as confused as I was. There is a fundamental difference with how nearly all Amazon MWS requests work except this particular one. All other requests technically accept the parameters as query parameters instead of POST data. The scratchpad even suggests this is how it is actually working (although the MWS Scratchpad actually sends the data as Post Data Fields also).
MWS needs the POST data passed as form params instead of as a query string for some operations. Otherwise, it pukes a Failed processing arguments of org.jboss.resteasy.spi.metadata style 400 Bad Request error for some operations such as this one (GetMyFeesEstimate is another that suffers from this).
For instance, if you did the following POST request in Guzzle 6 then you'd likely get the error:
$response = $client->request('POST', 'https://mws.amazonservices.com/Products/2011-10-01/?AWSAccessKeyId=YOURAWSACCESSKEY&Action=GetLowestPricedOffersForASIN&SellerId=YOURSELLERID&MWSAuthToken=amzn.mws.fghsffg-4t44e-hfgh-dfgd-zgsdbfe5erg&SignatureVersion=2&Timestamp=2017-07-09T15%3A45%3A18%2B00%3A00&Version=2011-10-01&Signature=bCasdxXmYDCasdaXBhsdgse4pQ6hEbevML%2FJvzdgdsfdy2o%3D&SignatureMethod=HmacSHA256&MarketplaceId=ATVPDKIKX0DER&ASIN=B007EZK19E');
To fix this you'd submit it as form data as in this Guzzle 6 example:
$response = $client->request('POST', 'https://mws.amazonservices.com/Products/2011-10-01', [
'form_params' => [
'AWSAccessKeyId' => 'YOURAWSACCESSKEY',
'Action' => 'GetLowestPricedOffersForASIN',
'SellerId' => 'YOURSELLERID',
'MWSAuthToken' => 'amzn.mws.fghsffg-4t44e-hfgh-dfgd-zgsdbfe5erg',
'SignatureVersion' => 2,
'Timestamp' => '2017-07-09T15%3A45%3A18%2B00%3A00',
'Version' => '2011-10-01',
'Signature' => 'bCasdxXmYDCasdaXBhsdgse4pQ6hEbevML%2FJvzdgdsfdy2o%3D',
'SignatureMethod' => 'HmacSHA256',
'MarketplaceId' => 'ATVPDKIKX0DER',
'ASIN' => 'B007EZK19E',
]
]);
This code worked for me. Hope it will help someone.
<?php
require_once('.config.inc.php');
// More endpoints are listed in the MWS Developer Guide
// North America:
$serviceUrl = "https://mws.amazonservices.com/Products/2011-10-01";
// Europe
//$serviceUrl = "https://mws-eu.amazonservices.com/Products/2011-10-01";
// Japan
//$serviceUrl = "https://mws.amazonservices.jp/Products/2011-10-01";
// China
//$serviceUrl = "https://mws.amazonservices.com.cn/Products/2011-10-01";
$config = array (
'ServiceURL' => $serviceUrl,
'ProxyHost' => null,
'ProxyPort' => -1,
'ProxyUsername' => null,
'ProxyPassword' => null,
'MaxErrorRetry' => 3,
);
$service = new MarketplaceWebServiceProducts_Client(
AWS_ACCESS_KEY_ID,
AWS_SECRET_ACCESS_KEY,
APPLICATION_NAME,
APPLICATION_VERSION,
$config);
// #TODO: set request. Action can be passed as MarketplaceWebServiceProducts_Model_GetLowestPricedOffersForSKU
$request = new MarketplaceWebServiceProducts_Model_GetLowestPricedOffersForSKURequest();
$request->setSellerId(MERCHANT_ID);
$request->setMWSAuthToken(MWSAUTH_TOKEN);
$request->setMarketplaceId(MARKETPLACE_ID);
$request->setSellerSKU($sellerSKU);
$request->setItemCondition($ItemCondition);
// object or array of parameters
invokeGetLowestPricedOffersForSKU($service, $request);
function invokeGetLowestPricedOffersForSKU(MarketplaceWebServiceProducts_Interface $service, $request)
{
try {
$response = $service->GetLowestPricedOffersForSKU($request);
echo ("Service Response\n");
echo ("=============================================================================\n");
$dom = new DOMDocument();
$dom->loadXML($response->toXML());
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
echo $dom->saveXML();
echo("ResponseHeaderMetadata: " . $response->getResponseHeaderMetadata() . "\n");
} catch (MarketplaceWebServiceProducts_Exception $ex) {
echo("Caught Exception: " . $ex->getMessage() . "\n");
echo("Response Status Code: " . $ex->getStatusCode() . "\n");
echo("Error Code: " . $ex->getErrorCode() . "\n");
echo("Error Type: " . $ex->getErrorType() . "\n");
echo("Request ID: " . $ex->getRequestId() . "\n");
echo("XML: " . $ex->getXML() . "\n");
echo("ResponseHeaderMetadata: " . $ex->getResponseHeaderMetadata() . "\n");
}
}
?>
As #eComEvoFor stated, for this particularly method, Amazon demands you specify the params in the body of the request. In node.js using axios library you can do this:
const paramsSorted = {}
Object.keys(params)
.sort()
.forEach((key) => {
paramsSorted[key] = params[key]
})
const data = new URLSearchParams(paramsSorted)
url = urljoin(this.marketplace.url, this.api, this.api.Version)
const response = await axios.post(url, data)

How to get MIME type of a file in PHP 5.5?

I am using mime_content_type() in PHP 5.5 to get a MIME type, but it throws fatal: error function not found.
How can I achieve this on PHP 5.5?
Make use of the finfo() functions.
A simple illustration:
<?php
$finfo = finfo_open(FILEINFO_MIME_TYPE);
echo finfo_file($finfo, "path/to/image_dir/image.gif");
finfo_close($finfo);
OUTPUT :
image/gif
Note : Windows users must include the bundled php_fileinfo.dll DLL file in php.ini to enable this extension.
I've spent too much time trying to get the finfo functions to work, properly. I finally just ended up creating my own function to match the file extension to any array of mime types. It's not a full-proof way of assuring that the files are truly what the extension denotes them to be, but that problem can be mitigated by how you process I/O of said files on your server(s).
function mime_type($file) {
// there's a bug that doesn't properly detect
// the mime type of css files
// https://bugs.php.net/bug.php?id=53035
// so the following is used, instead
// src: http://www.freeformatter.com/mime-types-list.html#mime-types-list
$mime_type = array(
"3dml" => "text/vnd.in3d.3dml",
"3g2" => "video/3gpp2",
"3gp" => "video/3gpp",
"7z" => "application/x-7z-compressed",
"aab" => "application/x-authorware-bin",
"aac" => "audio/x-aac",
"aam" => "application/x-authorware-map",
"aas" => "application/x-authorware-seg",
"abw" => "application/x-abiword",
"ac" => "application/pkix-attr-cert",
"acc" => "application/vnd.americandynamics.acc",
"ace" => "application/x-ace-compressed",
"acu" => "application/vnd.acucobol",
"adp" => "audio/adpcm",
"aep" => "application/vnd.audiograph",
"afp" => "application/vnd.ibm.modcap",
"ahead" => "application/vnd.ahead.space",
"ai" => "application/postscript",
"aif" => "audio/x-aiff",
"air" => "application/vnd.adobe.air-application-installer-package+zip",
"ait" => "application/vnd.dvb.ait",
"ami" => "application/vnd.amiga.ami",
"apk" => "application/vnd.android.package-archive",
"application" => "application/x-ms-application",
// etc...
// truncated due to Stack Overflow's character limit in posts
);
$extension = \strtolower(\pathinfo($file, \PATHINFO_EXTENSION));
if (isset($mime_type[$extension])) {
return $mime_type[$extension];
} else {
throw new \Exception("Unknown file type");
}
}
Edit:
I'd like to address Davuz's comment (since it keeps getting up-voted) and remind everyone that I put in the pseudo disclaimer at the top that this isn't "full-proof." So, please keep that in mind when considering the approach I've offered in my answer.
mime_content_type() is not deprecated and works fine.
Why is mime_content_type() deprecated in PHP?
http://php.net/manual/en/function.mime-content-type.php
As of PHP 5.3, it's even built-in.
$finfo = finfo_open(FILEINFO_MIME_TYPE); should do it.
Taken from the php.net docs. Your function is deprecated and probably already removed.
http://www.php.net/manual/en/function.finfo-file.php
You should understand that file_get_contents will upload whole file to the memory, it is not good way to get only mime type. You don't need to use buffer method and file_get_contents function in this case.
To prevent any errors and warnings, better do like this.
$filename = 'path to your file';
if (class_exists('finfo')) {
$finfo = new finfo(FILEINFO_MIME_TYPE);
if (is_object($finfo)) {
echo $finfo->file($filename);
}
} else {
echo 'fileinfo did not installed';
}
Also you should know $finfo->file will throw PHP Warning if it fail.
If fileinfo is not installed properly, and you have a fresh version of PHP, you can get mime type from headers.
You can use cURL to get mime type from headers.
$ch = curl_init();
curl_setopt_array($ch, array(
CURLOPT_HEADER => true,
CURLOPT_NOBODY => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 1,
CURLOPT_URL => $link)
);
$headers = curl_exec($ch);
curl_close($ch);
if (preg_match('/Content-Type:\s(.*)/i', $headers, $matches)) {
echo trim($matches[1], "\t\n\r");
}else {
echo 'There is no content type in the headers!';
}
Also you can use get_headers function, but it more slow than cURL request.
$url = 'http://www.example.com';
$headers = get_headers($url, 1);
echo $headers['Content-Type'];
Get the image size using:
$infFil=getimagesize($the_file_name);
and
echo $infFil["mime"]
The getimagesize returns an associative array which have a MIME key and obviously the image size too
I used it and it works
I use the MimeTypeTool from Bat (https://github.com/lingtalfi/Bat)
It uses fileinfo if available, and defaults back to an "extension => mime type" mapping otherwise.
This is the best solution I found by combining two very good posts
// Thanks to http://php.net/manual/en/function.mime-content-type.php#87856
function getMimeContentType($filename, $ext)
{
if(!function_exists('mime_content_type'))
{
if($mime_types = getMimeTypes())
{
if (array_key_exists($ext, $mime_types))
{
return $mime_types[$ext];
}
elseif (function_exists('finfo_open'))
{
$finfo = finfo_open(FILEINFO_MIME);
$mimetype = finfo_file($finfo, $filename);
finfo_close($finfo);
return $mimetype;
}
}
return 'application/octet-stream';
}
return mime_content_type($filename);
}
// Thanks to http://php.net/manual/en/function.mime-content-type.php#107798
function getMimeTypes()
{
$url = 'http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types';
$mimes = array();
foreach(#explode("\n",#file_get_contents($url)) as $x)
{
if(isset($x[0]) && $x[0]!=='#' && preg_match_all('#([^\s]+)#', $x, $out) && isset($out[1]) && ($c = count($out[1])) > 1)
{
for($i=1; $i < $c; $i++)
{
$mimes[$out[1][$i]] = $out[1][0];
}
}
}
return (#sort($mimes)) ? $mimes : false;
}
Use it link this:
$filename = '/path/to/the/file.pdf';
$ext = strtolower(array_pop(explode('.',$filename)));
$content_type = getMimeContentType($filename, $ext);
Will continue to work even if the mime_content_type function is no longer supported in php.

Add wordpress custom post type data to an external db

This function adds custom post 'event' data into a Salesforce db. I've tested the function outside of Wordpress and it works flawlessly. When I test it inside Wordpress by adding a new event, no error is generated and a the data is not inserted into the SF db. I've also tested this by printing out the $_POST and saw that the data is being collected. How can I get this display some errors so that I can trouble shoot this?
function add_campaign_to_SF( $post_id) {
global $SF_USERNAME;
global $SF_PASSWORD;
if ('event' == $_POST['post-type']) {
try {
$mySforceConnection = new SforceEnterpriseClient();
$mySoapClient = $mySforceConnection->createConnection(CD_PLUGIN_PATH . 'Toolkit/soapclient/enterprise.wsdl.xml');
$mySFlogin = $mySforceConnection->login($SF_USERNAME, $SF_PASSWORD);
$sObject = new stdclass();
$sObject->Name = get_the_title( $post_id );
$sObject->StartDate = date("Y-m-d", strtotime($_POST["events_startdate"]));
$sObject->EndDate = date("Y-m-d", strtotime($_POST["events_enddate"]));
$sObject->IsActive = '1';
$createResponse = $mySforceConnection->create(array($sObject), 'Campaign');
$ids = array();
foreach ($createResponse as $createResult) {
error_log($createResult);
array_push($ids, $createResult->id);
}
} catch (Exception $e) {
error_log($mySforceConnection->getLastRequest());
error_log($e->faultstring);
die;
}
}
}
add_action( 'save_post', 'add_campaign_to_SF');
I would use get_post_type() to check for "event" posts. Use error_log() to write to the PHP error log for additional debugging - check the status of your Salesforce login, etc.
Keep in mind that save_post will run every time a post is saved - created or updated - so you might want to do some additional checking (like setting a meta value) before creating a new Campaign in Salesforce, otherwise you will end up with duplicates.
function add_campaign_to_SF( $post_id ) {
$debug = true;
if ($debug) error_log("Running save_post function add_campaign_to_SF( $post_id )");
if ( 'event' == get_post_type( $post_id ) ){
if ($debug) error_log("The post type is 'event'");
if ( false === get_post_meta( $post_id, 'sfdc_id', true ) ){
if ($debug) error_log("There is no meta value for 'sfdc_id'");
// add to Salesforce, get back the ID of the new Campaign object
if ($debug) error_log("The new object ID is $sfdc_id");
update_post_meta( $post_id, 'sfdc_id', $sfdc_id );
}
}
}
add_action( 'save_post', 'add_campaign_to_SF' );

How can I convert validation error field names to input names in CakePHP?

I have a CakePHP (latest version) web app with forms and validation all working properly using traditional postback, but now I'm switching some of the forms to submit via ajax. When there are validation errors, I would like to get them back on the client as JSON formatted like so:
{
"success":false,
"errors":{
"data[User][username]":["This is not a valid e-mail address"],
"data[User][password]":["You must choose a password"]
}}
The keys for the errors array need to correspond to the name attribute on the form fields. We have some prebuilt client script that is expecting JSON formatted in this way. The good news is that this is very close to what the validationErrors object looks like in CakePHP. So I'm currently doing this in my controller:
if ($this->User->save($this->request->data)) {
} else {
if ($this->request->is('ajax')) {
$this->autoRender = $this->layout = false;
$response['success'] = false;
$response['errors'] = $this->User->validationErrors;
echo json_encode($response);
exit(0);
}
}
However, this is what the JSON response looks like:
{
"success":false,
"errors":{
"username":["This is not a valid e-mail address"],
"password":["You must choose a password"]
}}
Note that the errors keys have just the basic database table field names in them. They are not converted into data[User][username] format, which the FormHelper usually takes care of.
Is there some easy way to adjust the array before I return it? I don't want to simply loop through and prepend "data[User]" because that is not robust enough. I'd like some code I can put in one place and call from various controllers for various models. What does FormHelper use to come up with the input name attributes? Can I tap into that? Should I somehow use a JSON view?
That's because that's the way the $validationErrors array is formatted. To obtain the output you want you will have to loop through, there's no way around it.
foreach ($this->User->validationErrors as $field => $error) {
$this->User->validationErrors["data[User][$field]"] = $error;
unset($this->User->validationErrors[$field]);
}
I would suggest instead passing all errors to json_encode(). $this->validationErrors is a combined list of all model validation errors for that request available on the view (compiled after render). You should move your display logic (echoing json) into your view, and loop through it there.
in the view
$errors = array();
foreach ($this->validationErrors as $model => $modelErrors) {
foreach ($modelErrors as $field => $error) {
$errors["data[$model][$field]"] = $error;
}
}
$response['errors'] = $errors;
echo json_encode($response);
This would output something like this:
{
"success":false,
"errors": [
"data[User][username]": "This is not a valid e-mail address",
"data[User][password]": "This is not a valid password",
"data[Profile][name]": "Please fill in the field"
]
}
I have created a small recursive function to create validation error as a string with column name so that can be passed as json object.
/**
* prepare erorr message to be displayed from js
*
* #param array $errors validation error array
* #param stringn $message refernce variable
*
* #return void
*/
public function parseValidationErrors($errors, &$message)
{
foreach ($errors as $columnName => $error) {
$message .= "<strong>$columnName:</strong> ";
foreach ($error as $i => $msg) {
if (is_array($msg)) {
$this->_parseValidationErrors($msg, $message);
} else {
$message .= str_replace("This field", "", $msg . " ");
isset($error[$i + 1]) ? $message .= " and " : $message;
}
}
}
}
and controller code goes like this.
if (!$this->YourModel->saveAll($modelObject)) {
$errors = $this->YourModel->validationErrors;
$message = '';
$this->parseValidationErrors($errors, $message);
$response = array('status' => 'error', 'message' => $message);
}
$response['errors']['User'] = $this->User->validationErrors;

How do I use fixed fields in CakeDC's csvUpload behavior in Util plugin

I am using the csvUpload behavior of the Utils plugin by CakeDC, on a CakePHP 2.2.1 install.
I have it working great it's processing a rather large csv successfully. However there are two fields in my table / Model that would be considered fixed, as they are based on ID's from from associated models that are not consistent. So I need to get these fixed values via variables which is easy enough.
So my question is, how do I use the fixed fields aspect of csvUpload? I have tried that following and many little variation, which obviously didn't work.
public function upload_csv($Id = null) {
$unique_add = 69;
if ( $this->request->is('POST') ) {
$records_count = $this->Model->find( 'count' );
try {
$fixed = array('Model' => array('random_id' => $Id, 'unique_add' => $unique_add));
$this->Model->importCSV($this->request->data['Model']['CsvFile']['tmp_name'], $fixed);
} catch (Exception $e) {
$import_errors = $this->Model->getImportErrors();
$this->set( 'import_errors', $import_errors );
$this->Session->setFlash( __('Error Importing') . ' ' . $this->request->data['Model']['CsvFile']['name'] . ', ' . __('column name mismatch.') );
$this->redirect( array('action'=>'import') );
}
$new_records_count = $this->Model->find( 'count' ) - $records_count;
$this->Session->setFlash(__('Successfully imported') . ' ' . $new_records_count . ' records from ' . $this->request->data['Model']['CsvFile']['name'] );
$this->redirect(array('plugin'=>'usermgmt', 'controller'=>'users', 'action'=>'dashboard'));
}
}
Any help would be greatly appreciated as I have only found 1 post concerning this behavior when I searching...
I made my custom method to achieve the same task. Define the following method in app\Plugin\Utils\Model\Behavior
public function getCSVData(Model &$Model, $file, $fixed = array())
{
$settings = array(
'delimiter' => ',',
'enclosure' => '"',
'hasHeader' => true
);
$this->setup($Model, $settings);
$handle = new SplFileObject($file, 'rb');
$header = $this->_getHeader($Model, $handle);
$db = $Model->getDataSource();
$db->begin($Model);
$saved = array();
$data = array();
$i = 0;
while (($row = $this->_getCSVLine($Model, $handle)) !== false)
{
foreach ($header as $k => $col)
{
// get the data field from Model.field
$col = str_replace('.', '-', trim($col));
if (strpos($col, '.') !== false)
{
list($model,$field) = explode('.', $col);
$data[$i][$model][$field] = (isset($row[$k])) ? $row[$k] : '';
}
else
{
$col = str_replace(' ','_', $col);
$data[$i][$Model->alias][$col] = (isset($row[$k])) ? $row[$k] : '';
}
}
$is_valid_row = false;
foreach($data[$i][$Model->alias] as $col => $value )
{
if(!empty($data[$i][$Model->alias][$col]))
{
$is_valid_row = true;
}
}
if($is_valid_row == true)
{
$i++;
$data = Set::merge($data, $fixed);
}
else
{
unset($data[$i]);
}
}
return $data;
}
And you can use it using:
$csv_data = $this->Model->getCSVData($this->request->data['Model']['CsvFile']['tmp_name'], $fixed);
Here $csv_data will contain an array of all of those records from the csv file which are not empty and with the fixed field in each record index.
So as I was telling Arun, I answered my own question and figured it out. I was looking to broad instead of really examining what was in front of me. I started running some debugging and figured it out.
First of all, $unique_add = 69 is seen as an int, duh. In order for it to be added to the csv it need to viewed as a string. So it simply becomes, $unique_add = '69'.
I couldn't enter the value of $Id directly into the fixed array. So I just had to perform a simple find to get the value I needed.
$needed_id = $this->Model->find('first', array(
'condition'=>array('Model.id'=>$Id)
)
);
$random_id = $needed_id['Model']['id'];
Hopefully this won't be needed to help anyone because hopefully no one else will make this silly mistake. But one plus... Now there's actually more than one post on the internet documenting the use of fixed fields in the CakeDC Utils plugin.

Resources