Read about OpenEMR's Response to the COVID-19 Pandemic at https://www.open-emr.org/covid19/

CMS Portal update and Frontend PM to replace cartpauj-pm

I do not know how many are actually using the CMS portal but I have been using it for a couple years now and would not go without it. But it needs an update.

Cartpauj-pm is looking a little dated. A newer plugin that appears to have been modeled after cartpauj-pm is Frontend PM. It has a lot more features and is built on a responsive design.

Issues:
The free version does not restrict communication with admin only. This is how cartpauj-pm is set up and to do that you either need to modify the code yourself or buy the pro version for $29. I did the pro version. And set it up for admin only in the settings>recipients tab. Unless this is setup for admin only the patient can send messages to any patient on the site which is not good. With admin only set up, they do not have that field accessible to them anymore.

Next, as with cartpauj-pm, the display name is an issue. If you want to see the client, first/last name and with an email address afterward (as I do) you need to set up the display name to look like that in wordpress. I used the Force First Last plugin to change all the display names to be first last name plus email. I had to modify this to include the email address in the display name with the patient’s name. So within the plugin file, force-first-last.php on line 40 I changed it to this:

$display_name = trim($_POST['first_name'] . " " . $_POST['last_name'] . "--" .  $_POST['user_email']);

On line 60 I changed it to this:

$display_name = trim($info->first_name . ' ' . $info->last_name . '--' . $info->user_email);

This allows me to search for the client/patient by any part of their name or email.

Then there are some formatting issues. I added some custom CSS in the settings>general tab to make the participants field a little smaller to accommodate the longer user names:

.fep-message-title-heading.participants {
font-size: 10px !important;	
}

And I added this to make messages be expanded by default rather than hid:

div.fep-message-content.fep-message-content-2258.fep-hide-if-js{
    display: block !important;
}

I modified the email notices so that they only state that a message is available for them on the site. I removed all message content fields from the notification.

This sets it up similar to cartpauj-pm

The main problem to fix is that database is not compatible with cartpauj-pm. So, the sunset portal webserver.php queries need to be rewritten to accommodate it. That is my next project. Forntend PM saves messages in the wp_posts table and this is linked to some settings in wp_postmeta through the post_id in the wp_posts table.

If anyone else is using the CMS portal and is looking for a method to upgrade the private messaging please comment on this. If you look at Frontend PM and see any security issues that I have not already addressed let me know.

I am not looking to translate the cartpauj-pm database to Frontend PM. I am just going to use a legacy button for a few years and disable posting on cartpauj-pm.

I will get the webserver.php worked out, but I am very slow at this. So if anyone else is willing and interested let’s work together.

I have most of the modifications needed for the webserver and I have posted them here:

Modifications for Sunset Patient Portal and Frontend PM

The part I am now working on is the import of documents from OpenEMR into Frontend PM.

The current function for cartpauj-pm is this:

// Logic to process the "putmessage" action.
// Sends a message to the designated user with an optional attachment.
//
function action_putmessage(&$args) {
  global $wpdb, $out, $admin_user_login;
  $sender = convertToID($admin_user_login);
  if (!$sender) {
    $out['errmsg'] = "No such sender '$admin_user_login'";
    return;
  }
  $recipient = convertToID($args['user']);
  if (!$recipient) {
    $out['errmsg'] = "No such recipient '{$args['user']}'";
    return;
  }

  $tmp = $wpdb->insert("{$wpdb->prefix}cartpauj_pm_messages", array(
    'from_user'        => $sender,
    'to_user'          => $recipient,
    'message_title'    => $args['title'],
    'message_contents' => $args['message'],
    'last_sender'      => $sender,
    'date'             => current_time('mysql', 1),
    'last_date'        => current_time('mysql', 1),
  ), array('%d', '%d', '%s', '%s', '%d', '%s', '%s'));
  if ($tmp === false) {
    $out['errmsg'] = "Message insert failed";
    return;
  }

  if (!empty($args['contents'])) {
    $message_id = $wpdb->insert_id;
    $tmp = $wpdb->insert("{$wpdb->prefix}cartpauj_pm_attachments", array(
      'message_id' => $message_id,
      'filename'   => $args['filename'],
      'mimetype'   => $args['mimetype'],
      'contents'   => base64_decode($args['contents']),
    ), array('%d', '%s', '%s', '%s'));
    if ($tmp === false) {
      $out['errmsg'] = "Attachment insert failed";
    }
  }
}

Frontend PM does not store attachments in the database but as files on the server. Also, Frontend PM does not use different tables for attachments and messages. Rather it uses flags in the postmeta table. How to make all this work is very confusing. Any tips would be appreciated.

Thanks for posting your progress @Craig_Tucker. You use the @ username function to send an email alert to a registered user like @sunsetsystems (rod roark developer of the wordpress portal enjoys feedback and likes to help)

I think I should put the portal’s Wordpress plug-in on github so others can more easily contribute to it.

@brady.miller what do you think is a good place in the OpenEMR repository for this?

1 Like

Hi @sunsetsystems ,
Would just place this repo with the other repos in the OpenEMR github group:


-brady

Currently the following is working to replace all the cartpauj-pm functions with the portal:

Problems: My queries seem too long and complicated for what needs to be done. I wrote the queries to be able to model what was happening with the cartpaug-pm tables. I was probably complicating things because of this. If any one knows how to simplify my long queries to work OpenEMR–your input would be appreciated.

Although file attachments are importing into OpenEMR they are not showing up in the pdf viewer in the browser but will launch into the Adobe pdf program if I click on the file in the document window. I am not sure what I have done to inhibit the viewer and influence the launch into the Adobe PDF. Can anyone spot what I may be doing wrong to inhibit the viewer from working?

The putmessage action works but I need to be able to launch an email notice saying that a file has been placed in the discussion board. I have talked to the program author about any functions or hooks that I may be able to use for this. He is taking a look.

OK I’ve created the sunset-patient-portal repository in the openemr group and added the same teams to it that openemr has. @brady.miller Let me know if I screwed anything up. :slight_smile:

Should be OK to receive pull requests. I still need to amend the license.

thanks @sunsetsystems !
-brady

I have solved the problem of the email notification. The only issue now is getting the PDF viewer in OpenEMR to work with the file. It is uploading and the file is accurate. I see it in the appropriate patient folder ie:

\openemr\sites\default\documents\xxx

But the file is not showing up in the viewer. I am not sure about the procedure with openemr, is it also saving a blob to the db? I may not be handling that correctly. The following is my upload code.

function action_getmsgup($uploadid) {
  global $wpdb, $out;
  $query = $wpdb->prepare("SELECT ID, post_mime_type, guid FROM {$wpdb->prefix}posts WHERE ID = %d", array($uploadid));
  $rows = $wpdb->get_results($query, ARRAY_A);

  foreach ($rows as $row) {
	$url = $row['guid'];
	$filename = basename($url);
	$path  = parse_url($url, PHP_URL_PATH); // just the path part of the URL
	$parts = explode('/', $path);           // all the components
	$parts = array_slice($parts, -6);       // the last six
	$path  = implode('/', $parts);  
	$filepath = ABSPATH . $path;

	// Get file contents and make a blob.
	$tmpfile = fopen($filepath, "r");
	$contents = fread($tmpfile, filesize($filepath));

    $out['filename'] = $filename;
	$out['mimetype'] = $row['mimetype'];
	$out['contents'] = $contents;
  }
}

What may I be missing here that is not permitting the file to show up in the pdf viewer. Am I not handling the BLOB appropriately in $contents?

Don’t know this module but is this through ajax call? By viewer do you mean browser pdf or an object viewer? If file is uploaded to browser for an object it may need to be converted to base64.

Thanks, this is not ajax. I tried base64_decode($contents) and that did not work. I have also tried using:

file_get_contents(base64_decode($filepath))

and

file_get_contents($filepath)

What is working best is:

$tmpfile = fopen($filepath, "r"); $contents = fread($tmpfile, filesize($filepath));

This uploads the file into the documents directory within OpenEMR, the pdf will load into a pdf reader but not onto the object viewer in the browser with in OpenEMR. If I upload the file directly to the documents it will show up in the document viewer within OpenEMR. When I compare the two files (the one uploaded through the webserve.php and the one uploaded directly in OpenEMR documents) they look identical. So something is missing in the procedure here that is not allowing it to work in the viewer within the browser.

For an object you need to convert to base64 not decode. Also, for binary files and not streaming, I prefer get_file_content especially for reading into string. I still don’t understand viewer. Does the portal have a viewer or are you relying on browser pdf plugin?

Thanks for looking at this. Yes, base64_encode($contents) makes more sense. It does not work either unfortunately. And I would rather use file_get_contents(base64_encode($contents)) but nothing works with this (with or without base64_encode). So, I am sure I am misunderstanding something about the application here. But fopen approach at least gets the file uploaded. Unfortunately, I do not know why. This was trial and error that got me to this point.

Regarding the viewer. If you look in OpenEMR in the patient demographics view, documents tab, you will see the tree of documents a clinic can upload for each patient. This is where my file is uploading to. If you click on a file in the tree on the left, on the right side at the bottom you see a contents heading and a viewer below where images and pdf’s can be previewed on first click. On second click it will download to the pc and launch into the associated program. This is built into the standard build. It is how it works if I upload it normally in OpenEMR or if I use cartpauj-pm. I am getting my file to upload into the tree. But it does not show up in the viewer on first click. It just downloads and launches the program i.e. Acrobat etc.

Cartpaug-pm is transferring over a blob. Frontend PM is transferring over a file located on the server. So the procedure used in cartpauj-pm cannot just be copied here unfortunately for a moderately knowledgeable hobiest like me.

Oh I see, Okay, I did some work in that module recently plus the U.I has been cleaned up so maybe something is amidst. I’ll poke around some.
Edit -what version OpenEMR?

Main thing is that Documents is using an IFrame for content where, I think, it use to use an object. My experience has been that if you wish to force content in page, use an object viewer. With IFrames, pdf plugin looks at it as if a pdf download and overrides the frame. If you reconfig/remove/disable the plugin from browser then it will display in content frame of document viewer.
Document content viewer really should be an object if we want to force viewing pdf’s there. Try using Edge or Chrome to see if different results.
Solution, Not sure!

Edge does the same thing. At the very least it appears that upload is working. I can download and delete the file from openemr. Preview is not working. I am going to try to follow the full process through all components to see what may be missing. I need to look at the openEMR upload procedure and I will model on that.

As I said as long as the browser has a pdf plugin the document viewer in OpenEMR most likely won’t work. It needs to be rewritten as an object viewer if we want to ensure document displays in content viewer. Don’t know if I want to do right now.

I am now trying to model the upload on what was done for Ninja Forms. This is what I have tried:

function action_getmsgup($uploadid) {
  global $wpdb, $out;
  $query = $wpdb->prepare("SELECT ID, post_mime_type, guid FROM {$wpdb->prefix}posts WHERE ID = %d", array($uploadid));
  $rows = $wpdb->get_results($query, ARRAY_A);

  foreach ($rows as $row) {
	$url = $row['guid'];
    $filename = basename($url);
	$path  = parse_url($url, PHP_URL_PATH); // just the path part of the URL
    $parts = explode('/', $path);           // all the components
	$parts = array_slice($parts, -6);       // the last six
	$path  = implode('/', $parts);  
    $filepath = ABSPATH . $path;
    $contents = file_get_contents($filepath);
    if ($contents === false) {
      $out['errmsg'] = "Unable to read \"$filepath\"";
      return;
    }
	$out['filename'] = $filename;
	$out['mimetype'] = $row['mimetype'];
    $out['datetime'] = $row['post_date'];
    $out['contents'] = base64_encode($contents);
  }
}

Still I am just getting the upload of the file and it will not show up in the object viewer. I have also tried it without the base64_encode and still no object viewer is responding. The good news is the upload works with file_get_contents() now.

Are you windows? Check properties on uploaded file and see if it is blocked and for now you don’t need base64 for Document viewer however I’m going to patch the viewer for an object instead of iframe for display. What version OpenEMR are you working with?

Version Number: v5.0.0 (3)

I have compared two uploads of the same file: one from cartpauj-pm and the other from Frontend PM. Looking at the results in \openemr\sites\default\documents\922 – With the exception of their names, both are identical when compared in Notepad ++. Checking properties does not show any blocks. The file uploaded from cartpauj-pm – file1.pdf shows up in the viewer the file from Frontend PM does not. Then, I reversed their names. Regardless, file1.pdf shows up in the viewer. So, I do not think the problem is on OpenEMR’s side but on mine. I must be missing something in the upload.