Updating database value each time PHP List icon clicked

austega

Member
Hi Hugh,

Back with an additional question following on from #40725 - hopefully solvable without any TV session!

I have listed below your PHP and JS code for our PHP List plugin, together with some proposed adds/edits intending to increment a resource's hits value stored in the erd_resources table each time a user clicks on the PHP List icon. As you know my expertise in PHP/Joomla DB is limited - could you please eye-check and advise?

The ## at the start of lines indicate changes from your code.

Also if I wished to open up the resources in a new browser window/tab rather than the existing one, can I just replace " window.location.href = path; " with " window.open(path); "?

PHP Code
--------
// ADD the following to update Hits
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query = "UPDATE #__erd_resources SET hits = hits + 1 WHERE id=".$row->($id) ;
$db->setQuery($query);
$result = $db->execute();
// END ADD

$app = JFactory::getApplication();
$ids = $app->input->get('ids', array(), 'array');
$id = array_pop($ids);
$ids_str = json_encode($ids);
$row = $model->getRow($id);
$path = $row->erd_resources___link;
## $linktype = $row->erd_resources___linkTypeId;

## if (!empty($path) and $linktype=2)
{
system($path);
exit;
}
$statusMsg = "Ids: " . $ids_str . "," . $id . " Path: " . $path;

JS Code
-------
// rows is an array of objects representing the selected table rows.
// You might need to add the _raw prefix to the full element name, depending on the field type (e.g. if its a dropdown).
var linkTypeId = parseInt(rows[0].erd_resources___id_linktype, 10);
var path = rows[0].erd_resources___link;

if (linkTypeId != 2) {
window.location.href = path;
## REMOVE return false;
}
 
As far as the PHP goes, you'd need to move that new chunk of code to after where you set up $id, as you are referencing it in your new code, which you obviously can't do until you've actually assigned a value to it. And it wouldn't be $row->($id), which isn't legal syntax anyway, it's just be $id.

As for the JS ... I'm not sure if that will work. It might. I've never tried doing both - opening a new tab with a URL, and reloading the current tab with the plugin call. Try it and see. :)

-- hugh
 
Thanks Hugh.

Reporting back first on the JS opening in new window/tab -

New tab opened in IE nicely, and focus shifted to that new tab also nicely, but existing tab showed a blank page with http://ertest.sag.org.au/index.php?resetfilters=0&clearordering=0&clearfilters=0 as the url and page source code as only

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv="Content-Type"
content="text/html; charset=windows-1252"></HEAD>
<BODY></BODY></HTML>
When I removed ?resetfilters=0&clearordering=0&clearfilters=0 from the URL the page opened back as the ER listing as intended.

Any obvious thing I should be doing in Fabrik here?

Will report shortly separately on the PHP code.
 
I think so.

Here is where I am up to.

With PHP code
Code:
$app = JFactory::getApplication();
$ids = $app->input->get('ids', array(), 'array');
$id = array_pop($ids);
 
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query = "UPDATE erd_resources SET hits = hits + 1 WHERE id=".$id ;
$db->setQuery($query);
$result = $db->execute();
 
/* $ids_str = json_encode($ids);
$row = $model->getRow($id);
$path = $row->erd_resources___link;
$linktype = $row->erd_resources___linkTypeId;
 
if (!empty($path) and $linktype=2)
{
  system($path);
  exit;
}
$statusMsg = " Ids: " . $ids_str . "," . $id .  " Path: " . $path; */

and JS code
Code:
// rows is an array of objects representing the selected table rows.
// You might need to add the _raw prefix to the full element name, depending on the field type (e.g. if its a dropdown).
var linkTypeId = parseInt(rows[0].erd_resources___id_linktype, 10);
var path = rows[0].erd_resources___link;
 
if (linkTypeId != 2) {
    window.open(path);
//    return false;
}

Type 1 and 3 resources open in new tab, ERD listing displays properly in original tab, and resource hit counter increments appropriately
Type 2 resources do not open associated Windows app, ERD listing displays properly with PHP Plugin Success message, and resource hit increments appropriately

When I uncomment the last segment of the PHP code (but leave the return false; commented out in the JS code):

Type 1 and 3 resources open appropriately in a new tab, but ERD listing returns blank display in original tab with URL http://ertest.sag.org.au/index.php?resetfilters=0&clearordering=0&clearfilters=0, while resource hit counter increments appropriately
Type 2 resources do not open associated Windows app, ERD listing returns blank display in browser tab with URL http://ertest.sag.org.au/index.php?resetfilters=0&clearordering=0&clearfilters=0, while resource hit counter increments appropriately

So appears to be two remaining problems:

1. When the final php code is run the ?resetfilters=0&clearordering=0&clearfilters=0 suffix is added to the URL and the page displays as blank. I have no idea where this comes from or why it causes a blank display. Tested in both IE and Chrome. Can you suggest any solution?

2. The system($path); code segment is not causing the script to run for Type 2 resources. Looking at the first test Type 2 resource "*2*Australasian Genealogical Computer Index Vol 1", the value of the erd_resources___link is C:/TSapplications/Scripts/A245CD1.bat. I have tested that this file exists and its contents are
"Echo OFF
cd "Data\Programs\%username%\SAG\AGCI Search Vol 1\AGCI Search"
agcisrch.exe"

(Note that above script starts with @ followed by ECHO OFF - but this editor wants to replace it with some User on the system)

I have also confirmed that C:/TSapplications/Scripts/A245CD1.bat runs as intended when entered into a Windows PowerShell window on the server on which the browser is running.

I am not sure how to progress this one. Do we need another remote session, this time with you TV into my machine and its remote connections to the server?

Finally is there any easy way for me to display the $statusMsg variable that you constructed at the end during debugging?
 
Yeah, we'll have to do a TV session. Much as I hate them.

Those query string args (clearfilters, etc) are just part of our standard routing for list URL's. Can't really remove them.

What you are trying to do is so far outside what list plugins were built to do, I'm really not sure if we can get this going or not. But I'll give it one more go.

As usual my "schedule" is totally unpredictable, I've seem to be on about a 27 hour day cycle atm, so can't really predict when our working hours will intersect. So just look out for me on Skype.

-- hugh
 
OK - will look for you now, and if that doesn't suit will look for you tomorrow - I am here most of the day sydney time.
 
OK.

TBH, I don't know how much help I'm going to be. As I said, this is way outside the envelope for the list pugin, and is trying to do things I've never tried before. I'll do my best, but I'm not a magician. :)

-- hugh
 
Hi Hugh/others,

given we were not able to make successful contact via my contacting you via Skype during my limited time in the office, and your doubt that a TV session will actually achieve much, I wonder if we can do this better by asynchronous discussion of the issues here. I can do any testing of options and report back. Others may also be able to chip in this way.

I'll start with responding to your latest substantive comments:

1. Showing blank page after PHP List plugin run

You said "Those query string args (clearfilters, etc) are just part of our standard routing for list URL's. Can't really remove them."

What doesn't make sense to me here is that with part but not all of the PHP code commented out, the list does reload nicely without those query string args. It is only when the final bit of PHP code
Code:
$ids_str = json_encode($ids);
$row = $model->getRow($id);
$path = $row->erd_resources___link;
$linktype = $row->erd_resources___linkTypeId;
 
if (!empty($path) and $linktype=2)
{
  system($path);
  exit;
}
$statusMsg = " Ids: " . $ids_str . "," . $id .  " Path: " . $path;

is included that the query string args turn up and (apparently) cause the list display to not reload normally. Can you or others share some understanding here?

2. The system($path); code segment is not causing the script to run

This is the cross over point from Fabrik to the external resource. C:/TSapplications/Scripts/A245CD1.bat runs as intended when entered into a Windows PowerShell window on the server on which the browser is running. Yet the PHP code system($path); with $path set to C:/TSapplications/Scripts/A245CD1.bat does not.

Obviously something is muddying the water. Any guidance on what alternatives I should try?

You mentioned "What you are trying to do is so far outside what list plugins were built to do..." I don't understand what you mean by this. I thought the PHP List plugin was intended to run PHP (and JS) code in response to a user click action, and that is all we are trying to do. Am I missing something?

I will try a little blind trial and error testing and report back on anything interesting, but any suggestions would be very welcome!

David
 
Quick report before I need to leave this for a time.

With only
Code:
  system($path);
  exit;
commented out, the ERD list display appears properly and the Message on screen which used to show PHP List Plugin Success now shows

Ids: [],1 Path: C:/TSapplications/Scripts/A245CD1.bat

Is this useful? Is the lack of showing any value in the $1ds_str variable illuminating?
 
Well, $id_str will be empty if you only have one row selected, as your code does an array_pop($ids) before it
json_encode()'s the id_str, which pops last value off the array, which leaves the array empty if it only had one value.

When I say this is outside our scope, I mean we never considered exec'ing external binaries, or anything else which terminates execution of the current thread. And I still don't understand what that binary is supposed to do or how it would interact with the browser. What the PHP plugin expects is for you to take some self contained action, which has no output (other than maybe some simple status you can collect), then return a simple status message which gets shown either as an enqueued J! msg, or in a JS popup, depending on whether you have AJAX-ified your list links or not.

-- hugh
 
Well, $id_str will be empty if you only have one row selected, as your code does an array_pop($ids) before it
json_encode()'s the id_str, which pops last value off the array, which leaves the array empty if it only had one value.

I am guessing this is related to whether the query string args turn up or not (and prevent the list display appearing or not)? If so does this point to a way of avoiding the list display problem?

When I say this is outside our scope, I mean we never considered exec'ing external binaries, or anything else which terminates execution of the current thread. And I still don't understand what that binary is supposed to do or how it would interact with the browser. What the PHP plugin expects is for you to take some self contained action, which has no output (other than maybe some simple status you can collect), then return a simple status message which gets shown either as an enqueued J! msg, or in a JS popup, depending on whether you have AJAX-ified your list links or not.

I am not at all confident with the use of the words thread or terminate, but I think we want to have the list "thread" continue to display the list of resources. The execution of the associated binary should open it in a new window (with the focus) on top of the browser window. When the user finishes with that binary/windows app, and closes it, they should then see the browser with the list display underneath.

Does that clarify anything or am I misunderstanding you?

David
 
I am guessing this is related to whether the query string args turn up or not (and prevent the list display appearing or not)? If so does this point to a way of avoiding the list display problem?

Well, it's why $id_str is empty, because you are popping the value out of the $id array, before you encode it into $id_str.

http://php.net/array_pop

So array_pop() is a "destructive" function that actually removes the last array item. If you are expecting just one entry in the $ids array, then just do ...

$id = $ids[0];

... rather than array_pop()'ing it.

I am not at all confident with the use of the words thread or terminate, but I think we want to have the list "thread" continue to display the list of resources. The execution of the associated binary should open it in a new window (with the focus) on top of the browser window. When the user finishes with that binary/windows app, and closes it, they should then see the browser with the list display underneath.


So does the application need to interact with the user in any way, or is it just some static output they look at?

-- hugh
 
So does the application need to interact with the user in any way, or is it just some static output they look at?

The user uses the fabrik application search and filtering options to identify/find a genealogical resource they are interested in. They then click on the displayed resource link to access the resource. After finishing with that resource they would then generally identify another resource via the Fabrik filtering/search functionality.

Accessing the resource can mean either displaying a pdf or html file on the client machine (LinkType 1), accessing an external web site (LinkType 3), or opening and interacting with a Windows application on the server (LinkType 2). There is no information flow from these resources back into the Fabrik application so interaction between Fabrik and the resource is purely identifying the appropriate resource and then accessing/launching it.

Does that help?

Thanks for the explanation about the id array - this will be one resource at a time being accessed so I will try your suggested alternate code to see whether it fixes the list display issue - as soon as I can access the server where my remote connection is currently playing up.
 
OK, it's the linktype 2 which I have no clue how to do, as it depends entirely on how that app on the server is built. But what you can't do it what you are trying to do, which is exec() it from the server side. There is no way to simply "connect" an exec()'ed process through to the browser and have the user interact with it. Which is where my confusion has been, as I assumed you knew this. The PHP is just running on the server. It has no kind of interactive session going with the browser. The browser makes a request to the server, the PHP on the server runs, "does stuff", and returns output to the browser. So you can (say) collect the output from an exec()'ed app on the server, and return that to the browser. But it's not an "interactive" thing.

I believe the MS .NET framework has some ways of doing this, but vanilla PHP doesn't. The only way that could work is if the app had it's own built in web server logic, running on some other port than 80, and the browser was redirected to talk to it.

-- hugh
 
Thanks for that - should have warned you about assuming what I know - though reading what you say I am not sure why I did not know it!

What is interesting is that a previous incarnation of this type of application (using DBQ Manager version 1.4.1 RC2 on a Joomla 1.0.11 site and with some undocumented custom code that no-one understands) does seem to be achieving the desired outcome for the linktype 2 resources.

I will get back to you if appropriate - thanks for the help to date, with the understanding of the problem if not providing a magical solution!

David
 
Back again.

We have managed to get the win app to open as expected in a separate window on top of the browser via running the following html in an IE browser window on a client (does not work in Chrome).

HTML:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Application</title>
<meta name="description" content="">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<nav>
<ul>
<input type="button" value="Launch Application" onclick="window.open('file:///C:/TSapplications/Scripts/A245CD1.bat')" />
</ul>
</nav>
</header>
</body>
</html>

This code displays a page with a Launch button, which when pressed then displays, at the browser page bottom, a security warning asking if the app should be opened, which if agreed then opens the app in a new window on top of the browser window.

In terms of integrating this into the Fabrik list filter/search functionality:

1. Do you see any way of incorporating the effect of this code into the Fabrik PHP plugin's PHP/JS code so that clicking on the PHP Plugin icon initiates (for ListType 2 resources) the equivalent of clicking on the button in the code above?
2. Any other comments/ideas sparked by this?

A second best approach would I guess be to have the Fabrik list plugin click directing the user to such a page as produced by the code above.

Thanks - David
 
We are in need of some funding.
More details.

Thank you.

Members online

Back
Top