Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple improvements from IPPF related to layouts. #1081

Merged
merged 4 commits into from
Sep 16, 2017

Conversation

sunsetsystems
Copy link
Member

A summary of what's new:

o Layout groups may be nested, i.e. each group can have sub-groups.
o Layouts and their groups have properties that may be edited in the layout editor.
o Encounter LBFs may specify sections for direct entry of services, products and diagnoses.
o "Case Management" feature including the ability to link encounter forms to issues,
and in the issue window a tab for each related encounter form.
o New layout edit option to specify initially-open groups.
o Implemented design-time ACO for LBF encounter forms.
o Improved printing of encounter LBFs.
o Feature to print a demographics profile with data filled in for a specified patient.
o Improvements to printed referrals.
o Provider attribute and selector for LBF encounter forms.
o New layout field type for a single checkbox.
o Support for demographics/history values in LBF static text fields.
o Auto-delete of shared attributes not used by any other form when a form is deleted.
o Assorted layout editor improvements.
o Added "Save and Continue" button to LBF visit forms.
o Added sorting to export of lists and layouts.
o Condition tests in LBF fields now support setting a value instead of just skipping the field.
o Added field condition support to demographics and history.
o Assorted bug fixes.

@sunsetsystems
Copy link
Member Author

I see travis-ci reported a couple of syntax errors. I'll fix those along with whatever else comes up in the next day or two.

@bradymiller
Copy link
Sponsor Member

wow. that is a lot of code/features :)
Also lots of PSR2 fails in travis-ci. I'm glad to help out on this part when needed. Or if your up for it, can see here for commands:
https://gist.github.com/bradymiller/ae5069a058683b5a02c58b6afbcdace8

// Modified by Rod to be invoked from the custom/ directory by the normal
// demographics_print.php script when MSI Rapid Workflow is activated.

//The code below is copied from the original report, and fetches each data item in the demographic layout (if not 'unused')
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See here for the new sleek headers we are using:
http://www.open-emr.org/wiki/index.php/How_to_Document_Your_Code_Properly#File-Level_DocBlock
(keep all the comments at the top of it)


//The code below is copied from the original report, and fetches each data item in the demographic layout (if not 'unused')

// require_once("../interface/globals.php");
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this a security issue?

Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or are you using $encounter to control this (since I think there is no way to run this script unless it's included by another script that has the $encounter value set)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually this entire file should be omitted. I just realized it covers an obsolete case and will never even be invoked.

require_once("$srcdir/formdata.inc.php");
require_once("$srcdir/formatting.inc.php");

if (empty($encounter)) die("Please select or create a visit!");
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

xlt

$tmp = '';
if ($currvalue) {
$lrow = sqlQuery("SELECT title FROM list_options " .
"WHERE list_id = '$list_id' AND option_id = '$currvalue' AND activity = 1");
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sql binding

if ($currvalue) {
$lrow = sqlQuery("SELECT title FROM list_options " .
"WHERE list_id = '$list_id' AND option_id = '$currvalue' AND activity = 1");
$tmp = xl_list_label($lrow['title']);
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

text()

$lrow = sqlQuery("SELECT title FROM list_options " .
"WHERE list_id = '$list_id' AND option_id = '$currvalue' AND activity = 1");
$tmp = xl_list_label($lrow['title']);
if (empty($tmp)) $tmp = "($currvalue)";
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

either use text() or use $currescaped

// long or multi-line text field
else if ($data_type == 3) {
$s .= "<textarea" .
" cols='$fld_length'" .
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

attr()

Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and would be good to put quote around this so it is cols='12' for example

else if ($data_type == 3) {
$s .= "<textarea" .
" cols='$fld_length'" .
" rows='" . $frow['max_length'] . "'>" .
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

attr()

$tmp = '';
if ($currvalue) {
$urow = sqlQuery("SELECT fname, lname, specialty FROM users " .
"WHERE id = '$currvalue'");
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sql binding

if ($currvalue) {
$urow = sqlQuery("SELECT fname, lname, specialty FROM users " .
"WHERE id = '$currvalue'");
$tmp = ucwords($urow['fname'] . " " . $urow['lname']);
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

best to not cap stuff since breaks with UTF8 encoding
should escpae this with text()

$urow = sqlQuery("SELECT fname, lname, specialty FROM users " .
"WHERE id = '$currvalue'");
$tmp = ucwords($urow['fname'] . " " . $urow['lname']);
if (empty($tmp)) $tmp = "($currvalue)";
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

either use text() or use $currescaped

if ($currvalue == $key) {
$tmp = $prow['name'] . ' ' . $prow['area_code'] . '-' .
$prow['prefix'] . '-' . $prow['number'] . ' / ' .
$prow['line1'] . ' / ' . $prow['city'];
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

escape all these with text()

$prow['line1'] . ' / ' . $prow['city'];
}
}
if (empty($tmp)) $tmp = "($currvalue)";
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

either use text() or use $currescaped

}
if (empty($tmp)) $tmp = "($currvalue)";
}
if ($tmp === '') $tmp = '&nbsp;';
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the rest of this script needs adequate sql binding and html escaping

}

function warehouse_changed(sel) {
if (!confirm('<?php echo xl('Do you really want to change Warehouse?'); ?>')) {
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

xls()

while ($irow = sqlFetchArray($ires)) {
$issueid = $irow['id'];
$issuedate = oeFormatShortDate(empty($irow['begdate']) ? $irow['date'] : $irow['begdate']);
echo " <option value='$issueid'";
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

attr() around $issueid

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's always numeric but I'll change these to avoid anyone having to think about it.

$issuedate = oeFormatShortDate(empty($irow['begdate']) ? $irow['date'] : $irow['begdate']);
echo " <option value='$issueid'";
if ($issueid == $form_issue_id) echo " selected";
echo ">$issuedate " . text($irow['title']) . "</option>\n";
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

text() around $issuedate

if ($subtitle) {
// There is a group subtitle so show it.
echo "<tr><td class='bold' style='color:#0000ff' colspan='$CPR'>" . text($subtitle) . "</td></tr>\n";
echo "<tr><td class='bold' style='height:4pt' colspan='$CPR'></td></tr>\n";
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

attr() around $CPR in 2 lines above

if ($count) echo " </tr>\n";
echo " <tr>\n";
}
echo " <td width='$tdpct%'>";
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

attr() around $tdpct

list($codetype, $code) = explode(':', $codestring);
$crow = sqlQuery("SELECT code_text FROM codes WHERE " .
"code_type = ? AND code = ? AND active = 1 " .
"ORDER BY id LIMIT 1",
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What kind of codes is this for. If possibly includes external type codes, then should be using function in custom/code_types.inc.php
(in this case, the lookup_code_descriptions() function)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. I assume this also works for native (internal) code types?

Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, it works for all code types (internal and external) :)

" <input type='checkbox' name='form_fs_bill[$lino][del]' " .
"value='1'" . ($li['del'] ? " checked" : "") . " />\n";
foreach ($li['hidden'] as $hname => $hvalue) {
echo " <input type='hidden' name='form_fs_bill[$lino][$hname]' value='" . attr($hvalue) . "' />\n";
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

attr() around $hname

" <input type='checkbox' name='form_fs_prod[$lino][del]' " .
"value='1'" . ($li['del'] ? " checked" : "") . " />\n";
foreach ($li['hidden'] as $hname => $hvalue) {
echo " <input type='hidden' name='form_fs_prod[$lino][$hname]' value='" . attr($hvalue) . "' />\n";
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

attr() around $hname

if ($count) echo " </tr>\n";
echo " <tr>\n";
}
echo " <td width='$tdpct%'>";
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wrap $tdpct with attr()

list($codetype, $code) = explode(':', $codestring);
$crow = sqlQuery("SELECT code_text FROM codes WHERE " .
"code_type = ? AND code = ? AND active = 1 " .
"ORDER BY id LIMIT 1",
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What kind of codes is this for. If possibly includes external type codes, then should be using function in custom/code_types.inc.php
(in this case, the lookup_code_descriptions() function)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks (as above).

" <input type='checkbox' name='form_fs_bill[$lino][del]' " .
"value='1'" . ($li['del'] ? " checked" : "") . " />\n";
foreach ($li['hidden'] as $hname => $hvalue) {
echo " <input type='hidden' name='form_fs_bill[$lino][$hname]' value='" . attr($hvalue) . "' />\n";
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

attr() around $hname

td {
font-family: Arial;
font-weight: normal;
font-size: <?php echo $FONTSIZE; ?>pt;
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

text() around $FONTSIZE

$sanitize_all_escapes = true;

require_once("../../interface/globals.php");
require_once("$srcdir/formdata.inc.php");
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove above line

"WHERE list_id = 'warehouse' AND activity = 1 ORDER BY seq, title");
$wh .= "<option value=''></option>";
while ($lrow = sqlFetchArray($lres)) {
$wh .= "<option value='" . $lrow['option_id'] . "'";
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

attr()

// Disable this warehouse option if not selected and has no inventory.
if (!$has_inventory) $wh .= " disabled";
}
$wh .= ">" . xl_list_label($lrow['title']) . "</option>";
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

text()

"WHERE c.code_type = ? AND c.code = ? LIMIT 1",
array($pricelevel, $code_types[$codetype]['id'], $code));
$desc = $crow['code_text'];
$price = empty($crow['pr_price']) ? 0 : (0 + $crow['pr_price']);
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this use the standard code collector mechanism in custom/code_types.inc.php

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep another one of these. A bit concerning is that external codes do not seem to support price levels.

if ($count) echo "</tr>";
echo "<tr>";
}
echo "<td width='$tdpct%'>";
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

attr()

"ct.ct_key = '$codetype' AND " .
"c.code_type = ct.ct_id AND " .
"c.code = '$code' AND c.active = 1 " .
"ORDER BY c.id LIMIT 1";
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like another place where should be using custom/code_types.inc.php function here in order to support external codes

grp_products varchar(4095) not null default '',
grp_diags varchar(4095) not null default '',
PRIMARY KEY (grp_form_id, grp_group_id)
) ENGINE=MyISAM;
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use InnoDB and not MyISAM

sql/database.sql Outdated
grp_products varchar(4095) not null default '',
grp_diags varchar(4095) not null default '',
PRIMARY KEY (grp_form_id, grp_group_id)
) ENGINE=MyISAM;
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

InnoDB

sql/database.sql Outdated
INSERT INTO `list_options` (`list_id`, `option_id`, `title`, `seq`, `is_default`) VALUES ('Sexual_Orientation','Les','Lesbian' ,40,0);
INSERT INTO `list_options` (`list_id`, `option_id`, `title`, `seq`, `is_default`) VALUES ('Sexual_Orientation','Msm','MSM' ,50,0);
INSERT INTO `list_options` (`list_id`, `option_id`, `title`, `seq`, `is_default`) VALUES ('Sexual_Orientation','Oth','Other' ,60,0);
INSERT INTO `list_options` (`list_id`, `option_id`, `title`, `seq`, `is_default`) VALUES ('Sexual_Orientation','NS' ,'Not Specified',70,0);
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the Gender List and Sexual_Orientation List supposed to be here. It's not in the upgrade script?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Evidently not since not in any layouts.

@bradymiller
Copy link
Sponsor Member

review done

@sunsetsystems
Copy link
Member Author

I have added a commit with changes for review comments and a few other things. PSR4 for new scripts is not addressed yet, would prefer to do that afterwards to make it easier to see what's just been changed.

@bradymiller
Copy link
Sponsor Member

@sunsetsystems ,
When you are ready to bring this into the codebase, just let me know, and I'll do the PSR2 commit before you bring it in (this is really easy for me to do since had to do this in much more complicated settings in the past).

@sunsetsystems
Copy link
Member Author

@bradymiller that's fine but with the master being a moving target there are now some conflicts. Do you want me to rebase my branch locally and make a new PR?

@bradymiller
Copy link
Sponsor Member

hi @sunsetsystems ,
Rec doing a rebase and then pushing it to the same PR (git push --force origin lbf)

A summary of what's new:

o Layout groups may be nested, i.e. each group can have sub-groups.
o Layouts and their groups have properties that may be edited in the layout editor.
o Encounter LBFs may specify sections for direct entry of services, products and diagnoses.
o "Case Management" feature including the ability to link encounter forms to issues,
  and in the issue window a tab for each related encounter form.
o New layout edit option to specify initially-open groups.
o Implemented design-time ACO for LBF encounter forms.
o Improved printing of encounter LBFs.
o Feature to print a demographics profile with data filled in for a specified patient.
o Improvements to printed referrals.
o Provider attribute and selector for LBF encounter forms.
o New layout field type for a single checkbox.
o Support for demographics/history values in LBF static text fields.
o Auto-delete of shared attributes not used by any other form when a form is deleted.
o Assorted layout editor improvements.
o Added "Save and Continue" button to LBF visit forms.
o Added sorting to export of lists and layouts.
o Condition tests in LBF fields now support setting a value instead of just skipping the field.
o Added field condition support to demographics and history.
o Assorted bug fixes.
@sunsetsystems
Copy link
Member Author

@bradymiller OK this has been done.

@sunsetsystems
Copy link
Member Author

BTW I had to do a lot of repetitive changes for the new themes. Can't we reduce a lot of the redundancy among the different style_*.css files?

@bradymiller
Copy link
Sponsor Member

regarding the theme overload, hopefully will get SCSS up and running soon (so would be a central upstream script for those themes to change in 1 place, that would then spit out all the themes). @robertdown may have more to say on this.

@bradymiller
Copy link
Sponsor Member

btw, the recent new themes and theme cleanup are basically the first step in a complete codebase responsive bootstrap revolution that @zbig01 is working on. Very exciting and should start bringing in those changes into the codebase very soon.

@bradymiller
Copy link
Sponsor Member

hi @sunsetsystems ,
PSR2 changes went well. Did a code scan and things went well (note that we have found no bugs yet from when did this to entire codebase, so it's a very stable process; of course, it's best in the future to keep code PSR2 compliant via the code editor to avoid needing to do this). Since I want to ensure @zbig01 has the theme changes in his next PR, I'm going to bring this into the codebase now.
thanks for yet another awesome expansion of the layouts!
-brady

@bradymiller bradymiller merged commit db79047 into openemr:master Sep 16, 2017
@@ -617,3 +617,47 @@ UPDATE `user_settings` SET `setting_value`='style_light.css' WHERE `setting_labe
OR `setting_value`='style_purple.css'
OR `setting_value`='style_radiant.css'
OR `setting_value`='style_sky_blue.css');

#IfNotColumnType facility country_code varchar(30)
ALTER TABLE `facility` CHANGE `country_code` `country_code` varchar(30) NOT NULL default '';
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(right after brought into codebase noted the following :) )
It doesn't look like this change is addressed in database.sql ?
-brady

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll push a fix for it. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants