After migrating a Joomla 3 (PHP 7.4) website to Joomla 4.2.9 (PHP 8.2.1) I've stumbled upon this issue in a custom plugin.
obj = jQuery.parseJSON(response.data[0]);
The plugin stopped writing a filed in a database table.
The code is able to read and render values from the DB but it's not albe to write new values.
There must be some logic error in the PHP code itself, but I cannot figure this out.
I'm no PHP programmer and I really don't know how to adapt this PHP code to 8.2 / J4 version.
This is a sample live site with the error. https://www.joom-dev.it/tgw/index.php?option=com_content&view=article&id=236&catid=38&Itemid=559
Code extract:
if(($user->guest == 0) || ($this->params->get("ccv_registerd_required", "true") == "false")) {
$ajax = "
function currentTime()
{
var now = new Date();
return now.getHours() + now.getMinutes() + now.getSeconds();
}
function sendVote(id, action, request)
{
jQuery('.status').html('${loading}');
" .
/* request.data += '&stamp=' + currentTime() */
" jQuery.ajax({
type : 'GET',
data : request,
success: function (response) {
" .
/* console.log(response.data[0]); */
" obj = jQuery.parseJSON(response.data[0]);
" .
/*
console.log(obj);
console.log(obj['likes']);
console.log(obj['unlikes']);
*/
" jQuery('#cLike-{$art_id}').html(' ' + obj['pct_likes'] + ' %');
jQuery('#cUnlike-{$art_id}').html(' ' + obj['pct_unlikes'] + ' %');
jQuery('.status').html(obj['message']);
},
error: function(response) {
obj = jQuery.parseJSON(response.responseText);
var data2 = 'err: ';
for(key in obj)
{
data2 = data2 + ' ' + obj[key] + '<br/>';
}
jQuery('.status').html(data2);
}
});
}
jQuery(document).ready( function() {
jQuery('.like img').on( 'click', function(event) {
var request = {
'option' : 'com_ajax',
'plugin' : 'ccvote',
'group' : 'content',
'cmd' : 'like',
'data' : { id: {$art_id} },
'art_id' : '{$art_id}',
'user_id': '{$user->id}',
'user_name': '{$user->username}',
'format' : '{$format}'
};
sendVote( {$art_id}, 'like', request);
});
jQuery('.unlike img').on( 'click', function(event) {
var request = {
'option' : 'com_ajax',
'plugin' : 'ccvote',
'group' : 'content',
'cmd' : 'unlike',
'data' : { id: {$art_id} },
'art_id' : '{$art_id}',
'user_id': '{$user->id}',
'user_name': '{$user->username}',
'format' : '{$format}'
};
sendVote( {$art_id}, 'unlike', request);
});
});
";
} else {
$ajax = "
var msg = '<b>You must be logged in to vote.</b>';
jQuery(document).ready( function() {
jQuery('.like img').on( 'click', function(event) {
jQuery('.status').html(msg);
});
jQuery('.unlike img').on( 'click', function(event) {
jQuery('.status').html(msg);
});
});
";
}
How can I do to fix the PHP code to allow the correct addition of new fileds or values?
This is the error log from the console "console.log(response.data[0]);"
PHP Warning: Attempt to read property "id" on null in /web/htdocs/www.joom-dev.it/home/tgw/libraries/src/Updater/Adapter/ExtensionAdapter.php on line 303"
Line 303 below:
$this->latest->client_id = ApplicationHelper::getClientInfo($this->latest->client, true)->id;
Full PHP plugin code:
<?php
/**
* @package Joomla.Plugin
* @subpackage content.plg_ccvote
* @copyright Copyright (C) 2015 CCVote.com, Inc. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
// no direct access
defined("_JEXEC") or die;
/**
* CCVote Folder Plugin
*
* @package Joomla.Plugin
* @subpackage content.ccvote
* @since 1.0
*/
class plgContentCCVote extends JPlugin
{
/**
* CCVote after title content method
*/
/*
public function onContentAfterTitle($context, &$article, &$params, $page=0)
{
if ( $this->params->get("ccv_display") == "onContentAfterTitle" )
{
return $this->renderThumbs($context, $article, $params, $page);
}
}
*/
/**
* CCVote before display content method
*/
public function onContentBeforeDisplay($context, &$article, &$params, $page=0)
{
// if ( $this->params->get("ccv_display") == "onContentBeforeDisplay" )
// {
return $this->renderThumbs($context, $article, $params, $page);
// }
}
public function onAjaxCCVote()
{
jimport("joomla.application.module.helper");
jimport("joomla.database.database");
jimport("joomla.database.table");
$plugin = JPluginHelper::getPlugin("content","ccvote");
$pluginParams = new JRegistry($plugin->params);
$input = JFactory::getApplication()->input;
$user_nm = $input->get("user_name", "guest");
$user_id = $input->get("user_id", 0);
$db = JFactory::getDBO();
$query = $db->getQuery(true);
$game_id = $this->params->get("ccv_site", "unknown");
$art_id = $input->get("art_id", 0);
$conditions = array( ( $db->quoteName("content_id") . " = " . $art_id )
, ( $db->quoteName("game_id") . " = " . $db->quote($game_id)) );
$query ->select(array("like_count", "unlike_count"))
->from($db->quoteName("#__content_ccvote"))
->where($conditions);
$db->setQuery($query);
$resultRows = $db->loadObjectList();
// $rowCount = count($resultRows);
// $rowCount = $db->getNumRows(); // - No Idea why this doesn't work but it was not.
// $query->dump();
// if ($rowCount == 0)
if (count($resultRows) == 0)
{
$values = array($art_id, $db->quote($game_id), 0, 0, $db->quote($this->getIpAddr()), $db->quote(gmdate("Ymd")), $db->quote($user_nm));
$query = $db->getQuery(true);
$query ->insert($db->quoteName("#__content_ccvote"))
->columns($db->quoteName(array( "content_id","game_id","like_count","unlike_count","last_ip","last_date","last_user")))
->values(implode(",", $values));
// Set the query using our newly populated query object and execute it.
$db->setQuery($query);
$db->execute();
}
$query = $db->getQuery(true);
$fields = array($db->quoteName("last_ip") . " = " . $db->quote($this->getIpAddr())
, $db->quoteName("last_date") . " = NOW()"
, $db->quoteName("last_user") . " = " . $db->quote($user_nm));
switch( $input->get("cmd", "undefined") )
{
case "like":
$fields[] = $db->quoteName("like_count") . " = " . $db->quoteName("like_count") . " + 1 ";
break;
case "unlike":
$fields[] = $db->quoteName("unlike_count") . " = " . $db->quoteName("unlike_count") . " + 1 ";
break;
default:
$query = null;
break;
}
if ($query != null)
{
$query->update($db->quoteName("#__content_ccvote"))->set($fields)->where($conditions);
$db->setQuery($query);
// $query->dump();
$result = $db->execute();
}
$results = $this->renderResults($art_id, $game_id);
$stat_conditions = array( ( $db->quoteName("content_id") . " = " . $art_id )
, ( $db->quoteName("game_id") . " = " . $db->quote($game_id) )
, ( $db->quoteName("user_id") . " = " . $user_id ) );
$query = $db->getQuery(true);
$query ->select("*")
->from($db->quoteName("#__content_ccvote_player_stats"))
->where($stat_conditions);
$db->setQuery($query);
$resultRows = $db->loadObjectList();
if (count($resultRows) == 0)
{
$values = array($art_id, $db->quote($game_id), $user_id, $db->quote($user_nm), 0, 0);
$query = $db->getQuery(true);
$query ->insert($db->quoteName("#__content_ccvote_player_stats"))
->columns($db->quoteName(array( "content_id","game_id","user_id","user_name","like_count","unlike_count",)))
->values(implode(",", $values));
$db->setQuery($query);
$db->execute();
}
$fields = array($db->quoteName("user_name") . " = " . $db->quote($user_nm));
$query = $db->getQuery(true);
switch( $input->get("cmd", "undefined") )
{
case "like":
$fields[] = $db->quoteName("like_count") . " = " . $db->quoteName("like_count") . " + 1 ";
break;
case "unlike":
$fields[] = $db->quoteName("unlike_count") . " = " . $db->quoteName("unlike_count") . " + 1 ";
break;
default:
$query = null;
break;
}
if ($query != null)
{
$query->update($db->quoteName("#__content_ccvote_player_stats"))->set($fields)->where($stat_conditions);
$db->setQuery($query);
// $query->dump();
$result = $db->execute();
}
$msg = $results["msg"];
return json_encode(array("pct_likes"=>$results["pct_like"], "pct_unlikes"=>$results["pct_unlike"], "user_name"=>$user_nm, "ip"=>$this->getIpAddr(), "art_id"=>$art_id, "message"=>$msg));
}
protected function renderResults($art_id, $game_id)
{
$db = JFactory::getDBO();
$conditions = array( ( $db->quoteName("content_id") . " = " . $art_id )
, ( $db->quoteName("game_id") . " = " . $db->quote($game_id)) );
$query = $db->getQuery(true);
$query ->select("*")
->from($db->quoteName("#__content_ccvote"))
->where($conditions);
$db->setQuery($query);
$resultRows = $db->loadObjectList();
$results = array("total_plays"=>0,"pct_like"=>0,"pct_unlike"=>0,"likes"=>0,"unlikes"=>0,"user_nm"=>"","last_date"=>"1970-01-01 00:00:00", "msg"=>"Stat Recorded. Thank you for your vote.");
if (count($resultRows) == 1)
{
$results["total_plays"] = $resultRows[0]->like_count + $resultRows[0]->unlike_count;
if ( $results["total_plays"] > 0 )
{
$results["pct_like"] = round( ( $resultRows[0]->like_count / $results["total_plays"] ) * 100 );
$results["pct_unlike"] = round( ( $resultRows[0]->unlike_count / $results["total_plays"] ) * 100 );
}
$results["likes"] = $resultRows[0]->like_count;
$results["unlikes"] = $resultRows[0]->unlike_count;
$results["user_nm"] = $resultRows[0]->last_user;
$results["last_date"] = $resultRows[0]->last_date;
$results["msg"] = "Total plays <b>" . $results["total_plays"] . "</b> - Last reported by <b>" . $results["user_nm"] . "</b> on <b>" . $results["last_date"] . "</b>";
}
return $results;
}
protected function getIpAddr()
{
$ip = $_SERVER["REMOTE_ADDR"];
if (empty($_SERVER["HTTP_CLIENT_IP"]) === false)
{
$ip = $_SERVER["HTTP_CLIENT_IP"];
}
else if (empty($_SERVER["HTTP_X_FORWARDED_FOR"]) === false)
{
$ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
}
return (string)$ip;
}
protected function renderThumbs($context, &$article, &$params, $page = 0)
{
$document = JFactory::getDocument(); // set document for next usage
$document->addStyleSheet(JURI::base() . "/plugins/content/ccvote/assets/ccvote.css");
$input = JFactory::getApplication()->input;
$enabled_for = $this->params->get( "ccv_enable_view", "all" );
// echo "<hr /> Enabled for:'".$enabled_for."' View Type: '". $input->get("view", false ) . "'<br /><hr />";
if ($enabled_for !== "all")
{
if ( strcasecmp($enabled_for, $input->get( "view", "-unknown-" )) != 0 )
{
return;
}
}
if ( $this->params->get("ccv_match_style", "ids") == "aliases")
{
$matches = array(strtolower($article->parent_alias), strtolower($article->category_alias));
}
else
{
$matches = array($article->parent_id, $article->catid);
}
// var_dump($article);
// var_dump($matches);
// echo "<br />";
$enabled_categories = explode(",", trim(strtolower($this->params->get("ccv_enable_categorylist" , "all"))));
$disabled_categories = explode(",", trim(strtolower($this->params->get("ccv_disable_categorylist" , "all"))));
// var_dump($enabled_categories);
// echo "<br />";
// var_dump($disabled_categories);
// echo "<br />";
// $r0 = (in_array($matches, $enabled_categories) === true ? "true" : "false");
// $r0 = count(array_uintersect($matches, $enabled_categories, "strcasecmp"));
// $r1 = (in_array($matches, $disabled_categories) === true ? "true" : "false");
// $r1 = count(array_uintersect($matches, $disabled_categories, "strcasecmp"));
// echo " # in enabled = '" . $r0 . "'<br />";
// echo " # in disabled = '" . $r1 . "'<br />";
if ( ($enabled_categories[0] !== "all") && (count(array_uintersect($matches, $enabled_categories, "strcasecmp")) == 0) ) //- If *NOT* enabled, check to see if disabled
{
if ( ($disabled_categories[0] === "all") || (count(array_uintersect($matches, $disabled_categories, "strcasecmp")) == 0) ) //- If disabled, do not render on this object
{
return;
}
}
$game_id = $this->params->get("ccv_site", "unknown");
$art_id = $article->id;
$voting_style = $this->params->get("ccv_style", "default");
$format = $params->get("format", "json");
$content_alignment = $params->get("content_alignment", "left");
$loading = '<span class="status-img"><img class="spin-img" src="' . JURI::base() . '/plugins/content/ccvote/assets/images/loading.gif"/></span>';
$loading .= '<span class="status-msg">' . JText::_(" Logging vote ...") . "</span>";
$user = JFactory::getUser();
//4 $user = JFactory::getApplication()->getIdentity($userId);
// var_dump($user);
if ( ($user->guest == 0) || ($this->params->get("ccv_registerd_required", "true") == "false") )
{
$ajax = "
function currentTime()
{
var now = new Date();
return now.getHours() + now.getMinutes() + now.getSeconds();
}
function sendVote(id, action, request)
{
jQuery('.status').html('{$loading}');
".
/* request.data += '&stamp=' + currentTime() */
" jQuery.ajax({
type : 'GET',
data : request,
success: function (response) {
console.log(response.data[0]);
obj = jQuery.parseJSON(response.data[0]);
".
/*
console.log(obj);
console.log(obj['likes']);
console.log(obj['unlikes']);
*/
" jQuery('#cLike-{$art_id}').html(' ' + obj['pct_likes'] + ' %');
jQuery('#cUnlike-{$art_id}').html(' ' + obj['pct_unlikes'] + ' %');
jQuery('.status').html(obj['message']);
},
error: function(response) {
obj = jQuery.parseJSON(response.responseText);
var data2 = 'err: ';
for(key in obj)
{
data2 = data2 + ' ' + obj[key] + '<br/>';
}
jQuery('.status').html(data2);
}
});
}
jQuery(document).ready( function() {
jQuery('.like img').on( 'click', function(event) {
var request = {
'option' : 'com_ajax',
'plugin' : 'ccvote',
'group' : 'content',
'cmd' : 'like',
'data' : { id: {$art_id} },
'art_id' : '{$art_id}',
'user_id': '{$user->id}',
'user_name': '{$user->username}',
'format' : '{$format}'
};
sendVote( {$art_id}, 'like', request);
});
jQuery('.unlike img').on( 'click', function(event) {
var request = {
'option' : 'com_ajax',
'plugin' : 'ccvote',
'group' : 'content',
'cmd' : 'unlike',
'data' : { id: {$art_id} },
'art_id' : '{$art_id}',
'user_id': '{$user->id}',
'user_name': '{$user->username}',
'format' : '{$format}'
};
sendVote( {$art_id}, 'unlike', request);
});
});
";
}
else
{
$ajax = "
var msg = '<b>You must be logged in to vote.</b>';
jQuery(document).ready( function() {
jQuery('.like img').on( 'click', function(event) {
jQuery('.status').html(msg);
});
jQuery('.unlike img').on( 'click', function(event) {
jQuery('.status').html(msg);
});
});
";
}
$document->addScriptDeclaration( $ajax );
$msg = "";
$results = $this->renderResults($art_id, $game_id);
if ($results["total_plays"] > 0)
{
$msg = $results["msg"];
}
$alt_base = trim( $this->params->get("ccv_alt_text", "Record a victory for") );
$votingBlock = '
<div id="ccv_container">
<div id="ccv_votes" style="float:' . $content_alignment . ';" >
<div id="ccv_title">' . $this->params->get("ccv_prefix_text") . '</div>
<div id="ccv_like">
<span class="like"><img class="button" src="' . JURI::base() . '/plugins/content/ccvote/assets/images/pixel.gif" alt="' . $alt_base . ' TOP ARMY" title="' . $alt_base . ' TOP ARMY" /></span>
<span id="cLike-' . $art_id . '" class="ccv_count green"> ' . $results["pct_like"] . ' %</span>
</div>
<div id="ccv_unlike">
<span class="unlike"><img class="button" src="' . JURI::base() . '/plugins/content/ccvote/assets/images/pixel.gif" alt="' . $alt_base . ' BOTTOM ARMY" title="' . $alt_base . ' BOTTOM ARMY" /></span>
<span id="cUnlike-' . $art_id . '" class="ccv_count red"> ' . $results["pct_unlike"] . ' %</span>
</div>
</div>
<div id="status-' . $art_id . '" class="status" style="float:' . $content_alignment . ';" >' . $msg .'</div>
</div>
<div id="clear"></div>';
return $votingBlock ; //. ">>" . $this->params->get("ccv_registerd_required") . "<<";
}
}