phpreports-0.4.9/0000755000175000017500000000000010630304571012347 5ustar fikefikephpreports-0.4.9/AUTHORS0000755000175000017500000000141310442102124013410 0ustar fikefikeAuthor/Project Leader: Eustaquio "TaQ" Rangel Contributors: Matthew Palmer Suggestions, some code, patches, Debian packaging, PEAR DB backend Keith Willis Suggestions, some code, patches and a lot of testing on Windows (tm) environments Luis Gustavo Interbase database code and testing Robin Marlowe Patch for PHP5 David Cavanaugh Suggestions and bug reports Bertrand Revenaz Suggestions Aztek PostgreSQL interface, ADO DB interface Patrice W. TSV output plugin Langis Gagnon SQLite interface David Sowers Suggestions phpreports-0.4.9/Changelog0000755000175000017500000005365010530565322014177 0ustar fikefike------------------------- 0.4.9 - Nov 21 2006 New features: - The function isNumericType() was moved from PHPReportMaker.php to PHPReportsUtil.php. - Now we have three events on the COLs: ONCLICK, ONMOUSEOVER and ONMOUSEOUT. We can have some cool effects using those events. The effects can be applied on the ROWs also using the parentNode JavaScript property. Some samples: Changing the background when the mouse is over the COL: myfield Changing the background when the mouse is clicked on the COL: myfield Using a function to invert the COL background when clicking. First, the JavaScript function: function invertBackground(o){ var er = /yellow/i; o.style.background = er.test(o.parentNode.style.background)?"transparent":"yellow"; } Now the XML: myfield We can use the DOM to make some effects on the ROW also (not needing to create the same event handlers for ROWs), just changing the object to the parent node of the COL (ROW!): function invertBackground(o){ var er = /yellow/i; o.parentNode.style.background = er.test(o.parentNode.style.background)?"transparent":"yellow"; } This will select all the ROW where the COL is. - Included a sales.sql with sample data for you who don't want to type some data for testing. You can create the sample table and data like this: mysql -u taq -p -D phpreports < sales.sql Please don't ask me to create the database for you also. ;-) - Created the concept of input plugins, that deal with your SQL query and create a new one, sending it to the report. With this kind of thing the first input plugin created was a crosstab plugin where you can define some columns as your static columns and another one to create dynamic columns with its value and show the report using an automatic template. More about this on the PDF manual. Bugs fixed: - There was a bug when closing the page, now fixed. When you have a certain number of lines the page was closed twice. ------------------------- 0.4.8 - Aug 16 2006 New features: - When using templates the numeric data columns are right aligned now. - GROUPs COLs HEADERs are set to a 'bold' CSS class when using templates. Bugs fixed: - There was an error on db_array.php on the line count. Fixed. Thanks to Alexey for warning me! - There was an error on db_array.php db_columnType method. I forgot a "_" char there. Thanks again to Alexey! - Seems that some was breaking some stuff on PHP4. I was using this with language features, but not anymore, so I removed it. Thanks to for Stéphane Riff warning me! - The GROUPs HEADERs were not repeating on each page break. Fixed. - The template HEADERs are now capitalized correctly. ------------------------- 0.4.7 - Jun 21 2006 New features: - Added a new interface for PHP5 and Oracle. - We can now use templates files to create our reports. For example, we can have a file with fixed page HEADER and FOOTER, some logo etc. and just tell what GROUPing info we need, with a XML string like the XML file or with some PHP classes and code (more expensive but can help if you want to create it dinamically). - There is a new "database" interface, db_array.php, where you can send the report values as a multidimensional array (check the file for an example). - The TABLEs elements have now an id which allow manipulation of the report pages using DOM. - The error messages can now be translated. There is a new class called PHPReportsErrorTr() where you can translate the messages to your language. English and Brazilian Portuguese are already there. You can use ->setLanguage() to set your language. - Added again the FORM element (there was a guy crazy about it! ;-) - DATE and DATETIME data types added on the grouping functions. - There is a setBody() method on the PHPReportMaker object now where you can configure to print or not the tags or just the report data. Bugs fixed: - XHTML element does not show its tag on the result HTML file. Thanks to David Sowers for the tip! ------------------------- 0.4.6 - Dec 08 2005 Bugs fixed: - LINKs can handle HTML special chars now. - PHPReport.dtd fixed on the LINKs element. ------------------------- 0.4.5 - Nov 04 2005 Bugs fixed: - There was a bug with PHPReportPreview.xsl and PHP5. Fixed now. New features: - LINKs elements now can render an IMG element inside. - IMGs can have an explicit border of 0px (thanks to Tiago Gava for the tip). ------------------------- 0.4.4 - Oct 26 2005 Bugs fixed: - GROUPs were not reseting it's values when the GROUP breaks. So COL's with SUPPRESS="TRUE" where not showing it's values when the values were the same as the previous GROUP. New features: - Automatic GROUP NAMEs are provided now. Not a mandatory attribute anymore. - There's a new function on the PHPReportMaker object: getBenchmark(), where can be a string key to some benchmarks done while creating the report, returning the timestamp of the event, like: report_start - when the report started report_end - when the report ended sql_start - when the sql query started sql_end - when the sql query ended code_start - when the code generation started code_end - when the code generation ended code_eval_start - when the code evaluation started code_eval_end - when the code evaluation ended output_start - when the output (to a file or screen) started output_end - when the output ended If you don't request an id, the full array is returned. You can use this to make some benchmarks and see what is happening inside the report creation and perhaps make things works faster. You can use like this, AFTER $oRpt->run(): $aBench = $oRpt->getBenchmark(); foreach($aBench as $k=>$v) print "$k on $v
"; For example, if you'd like to know on how many seconds your report was created, you can use: $aBench = $oRpt->getBenchmark(); $iSec = $aBench["report_end"]-$aBench["report_start"]; print "Your report was created on $iSec seconds."; ------------------------- 0.4.3 - Oct 05 2005 New features: - Added the COL setPageNum() and resetPageNum() methods. - Added the CMD element, where you can use PHP code to eval() like a COL, but with no output on the report. For example, when opening a new group that needs the page always as 1, you can use $this->setPageNum(1); on the group HEADER. Please take care of the commands you put there. They can be all kind of stuff eval() accepts! Hope it works for you, covi. :-) Bugs fixed: - No more LINK's are created if there is an empty string on its values. This will avoid some empty . Thanks to Marcelo Reimberg for his suggestion. ------------------------- 0.4.2 - Jul 15 2005 Bugs fixed: - Seems that on some recent versions of PHP5.x there was some changes on the way you can play with $this. You can check http://bugs.php.net/search.php?cmd=display&search_for=cannot+re-assign+%24this&x=0&y=0 for more about this. To fix this, I removed some *very old* code that refers to some vars, $oValue and $header. Those vars were used on some old versions, so if you have some reference to them on your XML report layout files, you can safely change it to $this. For example, $oValue->getValue("NAME") or $header->getValue("NAME") to $this->getValue("NAME"). They were used to refer to values on the HEADER but I fixed it later. Thanks for Mark Baker for warning me about that. :-) ------------------------- 0.4.1 - Jun 29 2005 New features: - Added setPageSize(size) and getPageSize() on the PHPReportMaker object. Now you can specify the page size using code like $oRpt = new PHPReportMaker(); // new report object $oRpt->setPageSize(30); // 30 lines page for example. This method overrides the XML value. Thanks to Gladyston Pereira Batista for this suggestion. :-) ------------------------- 0.4.0 - Jun 21 2005 Bugs fixed: - Seems that self:: does not work very good on PHP 4.3.x. On the internal calls of the PHPReportsDBI creates a silent error there. I changed just two files: db_mssql.php and db_mysql.php. Thanks to Trevor Lohrbeer for warning me about that! :-) ------------------------- 0.3.9 - Jun 03 2005 New features: - Added a new way to reuse your XML data using PHP5. Thanks to Andy from Xtreme-software. Now you can use XIncludes to insert XML files insert your XML report file, as: Please notice the XML namespace declaration needed on the REPORT element to allow that. Bugs fixed: - As I changed the database interfaces on the previous release some stuff was a little broken. Thanks to Andy again for warning me. ------------------------- 0.3.8 - May 23 2005 New features: - I added a "namespace" on the database interface files, so now if you have a function on your code named like for example "db_connect" it will not conflict with PHPReportDBI::db_connect. Please if you have some problem on your database interface because of this change, revert to the old version and contact me ASAP telling me what interface you're using and what error you got. Bugs fixed: - Fixed the way PHPReports check the paths on OSX. Thanks to Martin Loitzl! - Seems that there was some problems about page breaking in some Windows/IE. I changed the code the way Martin Loitzl told me on http://sourceforge.net/forum/forum.php?thread_id=1287185&forum_id=186814 I hope everything runs fine there now. ------------------------- 0.3.7 - March 3 2005 New features: - Using NUMBERFORMAT or NUMBERFORMATEX caused null or empty values be shown as 0. Now just if the value is numeric or there is an implicit %s on the NUMBERFORMAT string, they are converted. - Using -1 as PAGE SIZE gives you unlimited page size. It will just ends when the report ends. - Added the attribute CLASS to PAGE. - Added NO_DATA_FUNC, where you can specify a function to be called if no data is returned from your query. It takes precedence over NO_DATA_MSG. You can use like: myfunc() You can send parameters to your func, but if you send strings, please escape it with ' as myfunc('report name',1,2,3) - If you want not to use ISO-8859-1 encoding, there is a encoding_change script that can change all the encodings for you. Unpack the package, go to the its root directory and call encoding_change - Added a TSV output plugin, thanks to Patrice W.! - Added a CSV output plugin. Bugs fixed: - When using the TXT output plugin, there was a chr(160) on the empty space of suppressed fields. I change it to the normal empty space char. ------------------------- 0.3.6 - January 7 2005 New features: - I added a new type of COL type: RAW_EXPRESSION. Let me explain what it does. On 0.3.5 I fixed a bug regarding some HTML special chars on the query result using the htmlspecialchars function (see bellow). But sometimes we need the result without this kind of processing. So using COL TYPE="RAW_EXPRESSION" will avoid the use of the htmlspecialchars function and allow you to get the result "as is". It's useful to insert some XHTML dynamic code into your report. Check more about it on the PDF manual, "Inserting code (XHTML/PHP) into your COL". Bugs fixed: - There was a bug on the Interbase/Firebird interface, when using for example a query like select FIELD as MY_FIELD from table it will not retrieve the value of MY_FIELD as a valid FIELD. Interbase/Firebird sees it as an alias, which is right, but if you do not refer to it as an alias on the PHP code it will not get the value (I did not see this kind of behaviour on another DBMS's, but if you find it please tell me). Thanks to Luis "Gugui" Gustavo for that. - Now the HTML result have a DOCTYPE inside: -//W3C//DTD HTML 4.01//EN This fixes, for example, empty TDs that didn't show it's borders. - Just to make sure that some browsers (you know who) will render empty TD's, I just replaced the return of SUPPRESSED fields/expression from "" to   (XML empty space entity). - When you have a DOCUMENT HEADER, it was printed AFTER the PAGE HEADER, but now it's fixed. Thanks for Mario Bertoni for warning me about that. Hey Mario, you just delayed this version for some minutes ehehe. :-) - On PHPReportGroup.php, row 584, there is some commented code about printing the DOCUMENT FOOTER after the PAGE FOOTER, on the end of the report. If you want to give a try there, give me your impressions. Maybe on the future we can add a new layer just for printing the PAGE number and stuff like that. ------------------------- 0.3.5 - November 25 2004 New features: - Now you can reuse an existing database connection on your report. Just use the new setDatabaseConnection() on your PHPReportMaker object: $oCon = ; $oRpt = new PHPReportMaker(); $oRpt->setDatabaseConnection($oCon); // new code :-) // make your adjustments on the report object $oRpt->run(); Thanks again to Matthew Palmer for his patch! :-) - Bugs fixed There was a bug on the EXPRESSIONs where if there was some kind of char like & returned from the database, it gives an error there. I just fixed it the same way that works for FIELDs COLs, with a htmlspecialchars() function. ------------------------- 0.3.4 - September 30 2004 Today is Isabella's 10 months old birthday. :-) Congratulations to my little cute daughter, the best thing that happened to my life. :-) New features: - Added a CELLCLASSEXPRESSION parameter on the COL element. Now you can say how your COL will looks like based on a PHP expression on the same way you use on . For example: VAL - To the users of previous versions, what changed: ENVIRONMENT VARS ---------------- The enviroment variables are gone. Yes, gone. I removed them. Now you don't need to use them, but you do need to tell PHP where the PHP classes are. You have two ways to do that. Let's suppose you installed the classes under /var/www/htdocs/phpreports (I have something to tell you about this soon), so you can: 1) On the PHP script that calls the PHPReportMaker object, put the path in the include_path using ini_set (note that I'm showing how to do it on Linux, if you use Windows, replace the ':' char to ';'): ini_set("include_path",ini_get("include_path").":/var/www/htdocs/phpreports/"); 2) A better way, put it on your php.ini file and restart your webserver: include_path=:/var/www/htdocs/phpreports/ PHPReports will check for its path under a call to ini_get("include_path"), breaking it on tokens (breaking with ':' or ';') and searching till find a phpreports reference. This will avoid me some trouble with people asking me how to declare environment variables on their operational system. Come on, dudes, you really need to know that! :-) TEMP DIRECTORY -------------- I used to create all the temporary stuff under /tmp. Used. Now the temporary stuff are going to your operational system temp directory. On Linux, use to be /tmp, on Windows, c:\temp. Check your return of the tempnam(). Now we only need to have a /tmp directory under your DOCUMENT_ROOT to make some output plugins result available as a web server URL. OUTPUT PLUGINS -------------- As I said above, you'll need a tmp directory where the web server can reach. My choice was to call it tmp and put it under DOCUMENT_ROOT. So if your DOCUMENT_ROOT is /var/www/htdocs, tmp will be /var/www/htdocs/tmp/. This is needed for the bookmarks and page output plugins to write their temporary files with the contents that needs to be reached via your web server address bar. WHY DID I CHANGED THAT? ----------------------- Matthew Palmer gave me some light that we can store PHPReports OUT of the web server path. For example: /usr/lib/phpreports will avoid some people trying to find your PHPReport installation using for example http://www.yourhost.com/phpreports/PHPReportMaker.php No problem with that, but they will know that you have PHPReports installed and can try to find some more things about your reports there. I don't see a clear way to mess things up but you know, if there's a way to we improve some security, let's do it. You still can store your PHPReport classes under your web server directory, but it's your choice. As with your XML layout files. Put it somewhere on /usr, /opt/, /var, out of the web server scope. PHP will find them as filesystem regular files, but the web server will not see and return them with an URL on the web browser. And using /tmp instead of /tmp will avoid users trying to guess that weird temporary file names on your browser also. Just be warned that the bookmarks and page output plugins HTML result files will still be under the web server scope, using DOCUMENT_ROOT/tmp. You need to erase them when you're sure you'll not use them anymore. Bugs fixed: - That first item below was buggy. I forgot the change one line there that avoided all the rest of what I made. Now the class name is working properly. - There was a bug in the CSS stuff on the bookmarks and page output plugins. Fixed now. ------------------------- 0.3.3 - September 27 2004 New features: - Now you can change the name of the class that will be created to run the report. On previous versions it was fixed as PHPReport, now you can change it's name using setClassName() function on the PHPReportMaker object. It's a good thing since you know what you're doing. :-) Matthew Palmer (mpalmer@hezmatt.org) requested this, you can have some more samples with him. - Created the putEnvObj() and getEnvObj() functions. Using these functions you can expose any kind of variable (a simple string or a class) to your report, making it accessible to your report. This can be useful if you need external classes and variables referenced on your COL element. Some uses are like: $sMyString = "this is my string"; ... $oRpt->putEnvObj("mystr",$sMyString); ... $this->getEnvObj("mystr"); This will print "this is my string" there. A better use will be with user defined objects (btw, functions you defined on some file that is on the scope of the PHPReportMaker works like PHP functions, available for use inside your report), but to maximize it's potential you must use PHP5. On PHP5 it will looks like this: $oClass = new MyUserDefinedClass(); ... $oRpt->putEnvObj("myclass",$oClass); ... $this->getEnvObj("myclass")->myFunction() Using PHP4 this will not work because it can't reference the object returned by the function and the function inside that object. Check about that on "Dereferencing objects returned from functions" here: http://www.php.net/zend-engine-2.php Keith Willis (keith@net-soft.com.au) suggested this. He have a cool sample of what can be done with this kind of objects. Bugs fixed: - Fixed PEAR db interface - thanks to Matthew Palmer. - Fixed setNoDataMsg() function - thanks to Keith Willis for warning me. ------------------------- 0.3.2 - September 03 2004 I hate when this happens. I just release a new version and some bugs appears ehehe. On 0.3.1 there was two bugs: 1- On the new CSS media chooser, if you didn't put any media, it should default to "screen" and "print", but was just inserting the "screen" media, so your reports was really beautiful on the screen but sucked when printed. :-) Because there was no "print" media there, and it didn't use any CSS file. Now it's ok, if you don't provide a MEDIA="" tag (as on LOTS of old XML report layout files), it will assume that you want to use the CSS on both types and will work correctly. 2- The setOutput from the PHPReportMaker was overriding the PHPReportOutputObject, even if it's null. So if you put a $oOut->setOutput() on your report output plugin it was never going to a file, and was showing on the screen. Now it works. ------------------------- 0.3.1 - September 03 2004 Thanks to Luis Gustavo "Gugui" and Keith Willis for help, suggestions and debugging. :-) New features: - New CSS elements features. Now you have put more than one CSS reference on your report, specifying the destination media if you want to. This is very good if you want to show your report with a lot of colors on the screen and when printing turns it to black and white. This is done like that: my_full_color_file.css few_colors_file.css When printing, the browser will use the second file. More about this here: http://www.w3.org/TR/REC-CSS2/media.html And don't worry, the saved reports will work. :-) - Increased the number of parameters to 10. On previous versions you was just allowed to use 5 parameters. - Help files added. Now when some error occurs and is trapped, we can put a link to a help file explaining what the error is about and trying to give some tips on how to fix it. Bugs fixed: - A possible bug was fixed, about the last page break. - There was a bug on the PHPReportMaker, if there was an output plugin it was not calling the setOutput() function, when needs to send your report to a file and not to the screen. - Removed all the ini_set commands. On Windows it was causing some problems, and I removed it and changed to use realpath() function with PHPREPORTSFILE. phpreports-0.4.9/COPYING0000755000175000017500000004307610442102124013406 0ustar fikefike GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. phpreports-0.4.9/css/0000755000175000017500000000000010630304366013141 5ustar fikefikephpreports-0.4.9/css/toolbar.css0000755000175000017500000000007510442102124015307 0ustar fikefikeBODY { margin:10px; color:#FFFFFF; background: #CAE850; } phpreports-0.4.9/css/bookmarks.css0000755000175000017500000000107010442102124015631 0ustar fikefikeBODY { margin:10px; color:#FFFFFF; background: #95CDED; } .PAGE_BOOKMARK { color:#000000; font-family:"verdana","arial","courier"; font-size:12px; font-weight:bold; margin-left:10px; padding:5px; border-style:solid; border-width:1px; } .BOOKMARK_TEXT { color:#0000F0; background:#95CDED; font-family:"verdana","arial","courier"; font-size:12px; font-weight:bold; text-decoration:none; } .CITY { color:#007500; font-family:"verdana","arial","courier"; font-size:11px; font-weight:bold; margin-left:15px; margin-top:0px; margin-bottom:0px; } phpreports-0.4.9/css/phpreports.css0000755000175000017500000000521110442102124016050 0ustar fikefikeBODY { margin:0px; color:#FFFFFF; } A { font-family:"verdana","arial","courier"; font-size:12px; font-weight:bold; color:#137BF9; } .MENUTABLE { background: #137BF9; } .MENULINK { font-family:"verdana","arial","courier"; font-size:12px; font-weight:bold; color:#FFFFFF; text-decoration:none; } A:HOVER { text-decoration:underline; } .REGULAR { font-family:"verdana","arial","courier"; font-size:12px; font-weight:normal; color:#000000; } .BOLD { font-family:"verdana","arial","courier"; font-size:12px; font-weight:bold; color:#000000; } .TITLE { font-family:"verdana","arial","courier"; font-size:20px; font-weight:bold; color:#000000; text-decoration:none; } .REALLY_BIG { font-family:"courier"; font-size:36px; font-weight:bold; color:#000000; text-decoration:none; } .DOCUMENT_LAYER { background: #7AF98D; font-family:"verdana","arial","courier"; font-size:12px; font-weight:normal; color:#000000; } .PAGE_LAYER { background: #DBF961; font-family:"verdana","arial","courier"; font-size:12px; font-weight:normal; color:#000000; } .GROUP_LAYER { background: #7CD2F4; font-family:"verdana","arial","courier"; font-size:12px; font-weight:normal; color:#000000; } .TOTAL_LAYER { background: #ADD2F4; font-family:"verdana","arial","courier"; font-size:12px; font-weight:normal; color:#000000; } .CATALOG_LAYER { background: #FFFFFF; font-family:"verdana","arial","courier"; font-size:12px; font-weight:normal; color:#000000; } .RED_ROW { background: #FF0000; font-family:"verdana","arial","courier"; font-size:12px; font-weight:normal; color:#FFFFFF; } .YELLOW_ROW { background: #FFFF00; font-family:"verdana","arial","courier"; font-size:12px; font-weight:normal; color:#000000; } .XML { font-family: "courier"; font-size: 11pt; font-weight: plain; color: #000000; } .CODE { font-family: "courier"; font-size: 10pt; font-weight: normal; color: #000000; background: #FFFFFF; } .CODE_HIGHLIGHT { font-family: "courier"; font-size: 10pt; font-weight: normal; color: #000000; background: #D4FC0A; width:500px; } .SUBMIT_BUTTON { background: #00B000; font-family:"verdana","arial","courier"; font-size:12px; font-weight:bold; color:#FFFFFF; border-style:solid; border-width:1px; border-color:#007500; padding:5px; } .PHPREPORTS_PAGE_CELL { background: #FFFFFF; font-family: "arial","verdana"; font-size:12px; font-weight: normal; } .PHPREPORTS_PAGE_LINK { color: #0000C0; font-family: "arial","verdana"; font-size:12px; font-weight: bold; } .PHPREPORTS_PAGE_LINK_BOLD { color: #000000; font-family: "arial","verdana"; font-size:12px; font-weight: bold; text-decoration:none; } phpreports-0.4.9/database/0000755000175000017500000000000010637036321014115 5ustar fikefikephpreports-0.4.9/database/db_array.php0000755000175000017500000000313610450304156016414 0ustar fikefikearray(1,2,3,4,5),"FIELD2"=>array("one","two","three","four","five")) * * Example of use: * * $a = array( "id"=>array(1,2,3,4,5), * "name"=>array("one","two","three","four","five"), * "email"=>array("1@one","2@two","3@three","4@four","5@five")); * * $r = new PHPReportMaker(); * $r->setDatabaseInterface("array"); * $r->setDatabaseConnection($a); * $r->setXML("test.xml"); * $r->run(); */ class PHPReportsDBI { var $_array; var $_pos; var $_cols; var $_rows; var $_keys; function db_connect($array) { return true; } function db_select_db($sDatabase) { } function db_query($array,$sql) { $this->_array = $array; $this->_keys = array_keys($array); $this->_pos = 0; $this->_cols = sizeof($array); $this->_rows = sizeof($array[$this->_keys[0]]); return $this->_array; } function db_colnum($oStmt) { return $this->_rows; } function db_columnName($oStmt,$iPos) { return $this->_keys[$iPos-1]; } function db_columnType($oStmt,$iPos) { return gettype($this->_array[$this->_keys[$iPos]][0]); } function db_fetch($oStmt) { if($this->_pos>=$this->_rows) return null; $a = array(); foreach($this->_keys as $key) $a[$key] = $this->_array[$key][$this->_pos]; $this->_pos++; return $a; } function db_free($oStmt) { } function db_disconnect($oCon) { } } ?> phpreports-0.4.9/database/db_odbc.php0000755000175000017500000000461110442102124016174 0ustar fikefike"4.1"){ if($rownumber<0) odbc_fetch_into($result,&$rs); else odbc_fetch_into($result, &$rs, $rownumber); }else odbc_fetch_into($result, $rownumber, &$rs); foreach($rs as $key => $value) $rs_assoc[odbc_field_name($result, $key+1)] = $value; return $rs_assoc; } } ?> phpreports-0.4.9/database/db_postgresql.php0000755000175000017500000000162710442102124017474 0ustar fikefike phpreports-0.4.9/database/db_adodb.php0000755000175000017500000000340210442102124016333 0ustar fikefikeConnect($oArray[2], $oArray[0], $oArray[1], $oArray[3]); if(!$oCon) { die($oCon->ErrorMsg()); } return $oCon; } function db_select_db($sDatabase) { // Already taken care of in the $oCon->Connect() call } function db_query($oCon, $sSQL) { $oRes = $oCon->Execute($sSQL); if(!$oRes) { die($oCon->ErrorMsg()); } return $oRes; } function db_colnum($oRes) { return $oRes->FieldCount(); } function db_columnName($oRes, $iPos) { $oField = $oRes->FetchField($iPos - 1); return $oField->name; } function db_columnType($oRes, $iPos) { $oField = $oRes->FetchField($iPos - 1); return $oField->type; } function db_fetch($oRes) { // needed nasty hack to get it to work // adodb didnt like me calling $oRes->FetchRow() // it would never move to the next row and it would infinate loop global $_gaRows, $_giCount; if($_gaRows == array()) { $_gaRows = $oRes->GetArray(); $_giCount++; return $_gaRows[0]; } else { if($_giCount >= $oRes->RowCount()) { return false; } $_giCount++; return $_gaRows[$_giCount - 1]; } } function db_free($oRes) { $oRes->Close(); return true; } function db_disconnect($oCon) { $oCon->Close(); return true; } } ?> phpreports-0.4.9/database/db_mysql.php0000755000175000017500000000161210442102124016430 0ustar fikefike phpreports-0.4.9/database/db_peardb.php0000755000175000017500000000602510442102126016525 0ustar fikefike * * A PEAR DB abstraction layer backend for PHPReports. Acts a little bit * differently to other PHPReports backends; I don't necessarily think * that's a problem at my end. * * Easiest way to use this is to pass a DSN into the report via the server * parameter. The rest of the DB parameters are ignored. * * Copyright (C) 2004 Bailey Roberts Group Pty Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation (version 2 of the License) * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ****************************************************************************/ require_once 'DB.php'; class PHPR_PEARDB_Result { var $index = 0; var $data = array(); function PHPR_PEARDB_Result($res) { while ($row = $res->fetchRow(DB_FETCHMODE_ASSOC)) { $this->data[] = $row; } $this->index = 0; } function fetchNext() { if ($this->index >= count($this->data)) { return NULL; } return $this->data[$this->index++]; } function fieldNames() { return array_keys($this->data[0]); } function numCols() { return count($this->data[0]); } } // This database type is a little different to the average. You can // either specify a DSN to connect to via the 'server' parameter, or // otherwise specify a global variable name in the 'database' // parameter which contains the PEAR database object you want to // use. 'server' trumps 'database' if both are supplied. class PHPReportsDBI { function db_connect($cdata) { if ($cdata[2]) { $DB = DB::Connect($cdata[2]); } else { global ${$cdata[3]}; $DB = ${$cdata[3]}; } if (DB::isError($DB)) { die($DB->getMessage()."\n".$DB->getUserInfo()."\n"); } return $DB; } function db_select_db($sDatabase) { // You wanna DB? Pick it in the DSN return; } function db_query(&$DB,$SQL) { $res = $DB->query($SQL); $rv = new PHPR_PEARDB_Result($res); $res->free(); return $rv; } function db_colnum($res) { return $res->numCols(); } function db_columnName($res,$i) { $names = $res->fieldNames(); return $names[$i-1]; } function db_columnType($res,$i) { // The type of a field should be irrelevant return 'INT'; } // An auto-increment fetch function db_fetch(&$res) { $row = $res->fetchNext(); return $row; } function db_free($res) { return 0; } function db_disconnect($DB) { $DB->disconnect(); } } phpreports-0.4.9/database/db_oracle_php5.php0000755000175000017500000000147210442102126017472 0ustar fikefike phpreports-0.4.9/database/db_oracle.php0000755000175000017500000000151010442102126016527 0ustar fikefike phpreports-0.4.9/database/db_sqlite.php0000755000175000017500000000164510442102126016574 0ustar fikefike";get_class($oStmt);echo "iPos: $iPos phpreports-0.4.9/database/db_interbase.php0000755000175000017500000000147710442102126017252 0ustar fikefike phpreports-0.4.9/database/db_informix.php0000755000175000017500000000242510442102126017123 0ustar fikefikeuser name:Informix install directory:Config File $oArray[1]=>password $oArray[2]=>server (from 'sqlhosts') $oArray[3]=>database name */ class PHPReportsDBI { function db_connect($oArray) { $db = $oArray[3] . '@' . $oArray[2]; list ($sUser, $sHome, $sConfig) = split (':', $oArray[0]); putenv("INFORMIXDIR=$sHome"); putenv("INFORMIXSERVER=$oArray[2]"); putenv("ONCONFIG=$sConfig"); $oCon = @ifx_connect ($db, $sUser, $oArray[1]); if(!$oCon) { die("could not connect"); } return $oCon; } function db_select_db($sDatabase) { return; } function db_query($oCon,$sSQL) { return @ifx_query($sSQL, $oCon, IFX_SCROLL); } function db_colnum($oStmt) { return @ifx_num_fields($oStmt); } function db_columnName($oStmt,$iPos) { $types = @ifx_fieldtypes ($oStmt); $keys = array_keys ($types); return $keys[$iPos-1]; } function db_columnType($oStmt,$iPos) { $types = @ifx_fieldtypes ($oStmt); $keys = array_keys ($types); $key = $keys[$iPos-1]; return $types[$key]; } function db_fetch($oStmt) { return @ifx_fetch_row($oStmt); } function db_free($oStmt) { return @ifx_free_result($oStmt); } function db_disconnect($oCon) { return @ifx_close($oCon); } } ?> phpreports-0.4.9/database/db_mssql.php0000755000175000017500000000202210442102126016420 0ustar fikefikename; } function db_columnType($oStmt,$iPos) { $oFields = mssql_fetch_field($oStmt,$iPos-1); return $oFields->type; } function db_fetch($oStmt) { $aArray = Array(); if( ($aArray = mssql_fetch_array($oStmt)) == null ) return false; return $aArray; } function db_free($oStmt) { return mssql_free_result($oStmt); } function db_disconnect($oCon) { return mssql_close($oCon); } } ?> phpreports-0.4.9/encoding_change0000755000175000017500000000063610442102126015366 0ustar fikefike#!/bin/sh # Use this script to change the default encoding # from ISO-8859-1 to other that you want. # Run it on the PHPReports root directory if [ ! -n "$1" ] then echo Please inform the encoding to use! exit 1 fi temp=/tmp/$$.phprpt default='ISO-8859-1' for file in `fgrep -Ril $default *` do echo converting $file ... sed s/$default/$1/ $file > $temp cp $temp $file done if [ -f $temp ] then rm $temp fi phpreports-0.4.9/footer.xml0000755000175000017500000000054110442102126014363 0ustar fikefike
page total $this->getSum("VALUE") "page number ".$this->getPageNum()
phpreports-0.4.9/header.xml0000755000175000017500000000107110442102126014314 0ustar fikefike
JOHN DOE ENTERPRISES powered by
phpreports
SALES REPORT

phpreports-0.4.9/help/0000755000175000017500000000000010630304366013301 5ustar fikefikephpreports-0.4.9/help/nocolumns.php0000755000175000017500000000150610442102126016023 0ustar fikefike

"; NO COLUMNS RETURNED FROM YOUR QUERY

Are you sure there is some valid columns in your query?

What happened here is that I asked the database about the information you asked me, but the database said "hey dude, there is nothing like that here, I didn't find the fields you asked for".

So there is nothing to work with there in your query. Please run it on some database tool to make sure it is ok before sending it to PHPReports.

phpreports-0.4.9/help/queryerror.php0000755000175000017500000000112010442102126016215 0ustar fikefike

"; QUERY ERROR

I was connected on your database but there was some kind of error when running the SQL query.

Please check if it is a valid query using some database interface program, and then return here again.

phpreports-0.4.9/help/missingfield.php0000755000175000017500000000270710442102126016467 0ustar fikefike

"; Missing field

Seems that you're trying to retrieve the value of (or a function based on) a field called , but it is not on the fields your query returned to me.

Note that when the query returns (programmer stuff here now), it returns is an associative array, a array which the elements can be reached using their names not their numbers (yes, you can do that, but calling 0 and not MYFIELD will be confuse).

Check your SQL query fields and the fields you put on your XML layout file, on the FIELDS element (inside the ROWs there, on COLs of TYPE="FIELD"). Check if they are equal on your query and on your XML file.

One thing that can make this happens when the fields are the same on the SQL query and the XML file is the case sensitive thing.
Note that myfield is different from MYFIELD on some databases, and it's a good idea you put the fields on your query and XML file the way your database works, and with same case on both places.

phpreports-0.4.9/help/nopage.php0000755000175000017500000000141410442102126015255 0ustar fikefike

"; NO PAGE ELEMENT DEFINED

This error happens because you didn't insert a PAGE element in your report layout file.

The PAGE element controls how your report count lines and break pages. You need to put it before your GROUPS element.

If not specified the PAGE size, the default will be 50 rows.
So, please, open your XML layout file and insert it to fix this error. ;-)

phpreports-0.4.9/help/contactdeveloper.php0000755000175000017500000000157710442102126017357 0ustar fikefike

";

This is an error that is kind of rare (thanks Lord!). Seems that something inside the code is not working well, and when I say that is rare is not because the code is perfect but some stuff will not be running well if this happens often. :-)

Please send a message on the PHPReports web site forum:

https://sourceforge.net/forum/forum.php?forum_id=186814

Thank you.

phpreports-0.4.9/help/noxsltprocessor.php0000755000175000017500000000365510442102126017304 0ustar fikefike

"; No XSLT processor found

Oh boy, this is bad. Stop the press! You REALLY need a XSLT processor do make all this stuff here works. Let me explain why.

All the idea of PHPReports is based on transform XML data on something else.

On a first moment, it transforms your XML layout file (that one you put your FIELDS etc) in PHP code that uses the PHP classes provided on the package to create another XML file with all your report data inside of it, and transform it again using an output plugin to the format you choose.

I can see that you're using PHP .
With this version is recommended to use Sablotron processor, you'll ". "need to download, install it and compile PHP again.

I must warn you that Sablotron have some problems ". "when running on Windows enviroments, so if you think in use PHPReports on this kind of environment ". "it's better migrate to PHP5 and use the PHP XSL extension there."; else print "the PHP XSL extension, and it's very easy to configure."; $sOS = strtoupper(trim(substr(php_uname(),0,strpos(php_uname()," ")))); if($sOS=="LINUX") print "

I can see that you're running GNU/Linux, so you'll have no problems with this. ;-)"; ?>

phpreports-0.4.9/help/connectionrefused.php0000755000175000017500000000166410442102126017530 0ustar fikefike

"; CONNECTION REFUSED

The database specified by you refused your connection.

I mean, it does not recognize the user name, the password and some other parameter you're trying to use there.

Please make a PHP code file and try to connect to your database. If it works, please check the database interface file on <PHPReports_dir>/database/db_<your_database_name_here>.php to see if you find something weird. If you find, please contact me on the PHPReports website and I'll be glad to help you to fix it.

phpreports-0.4.9/img/0000755000175000017500000000000010630304366013125 5ustar fikefikephpreports-0.4.9/img/warning.png0000755000175000017500000003520710442102126015301 0ustar fikefike‰PNG  IHDR¢ÆQ—[WbKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÔ57@rª7 IDATxœíy|TÕùÿßwöd²¯„•dQ‘ÅQÀ±VmÝÚj­ mµZí·µZ¿Z´ß²—*µêÏ ‚âÎ&Ⱦ¯²%!„„ìûdf2Ûýýq’@`’ÌÌ–”÷ë5¯ÀÌÝæÎç>çœç<çy$Y–e.àsL&‡æ‡~ ??Ÿ¼¼< ¨®®Æd2a2™°X,èõz"""ˆˆˆ &&†¬¬,²³³ÉÎÎfðàÁ :”ØØØ`¿#]¢ohnnæÈ‘#|ùå—lذ½{÷RSSƒÍfóú˜†ØØX† Âĉ¹á†1bF£Ñ‡W\b7p¹\ðþûï³råJ8Ð-áu…Z­fРAL™2…»îº‹áÇ£V«ýv¾€"_@1‡C^³f>^þàƒzDS}Aˆçàr¹ä7ß|SŽŽŽº|ñÒëõòŸþô'ÙápûÖvÊ!ž…Ëå’çÍ›'k4š  È—/I’ä9sæÈv»=Ø·¸Cz¬].—Oçp8ä¹s熌[ÆbüÕ¯~%[,ŸÞ7_ÑcgVŠŠÞ¢OŸ[Ðéâº},Y–yã7xôÑG±ÛíŠ÷×ëõ$''‡Ñh¤¬¬ŒššêêêðæöJ’D\\111¤¤¤ÐØØHmm-eeeÝš¹Q©T<ñļð ¡7#ÜçÀ;š›«äU«Rå£GŸóÉñV­Z%GFF*¶2aaaòC=$oܸ±Ýì†Óé” ä È Pdµ†*¿þúëòÉ“'ÛY}³Ù,oذA¾÷Þ{»5›£ÕjåÅ‹ûä¾ù’)ÄcÇž—×®EþöÛdÙb)éÖ±Ž?.'&&*þAÇ'ïÛ·¯Ëã744ÈO=õ”¬R©:=^xx¸ü?ÿó?ùÿ¶nÝ*3Æk1êõzùûï¿ïÖ}ó5=NˆK‰¼zuª\Q¼mòáÃÏtãXyòäÉŠÈiÓ¦ÉUUUŸÇårÉóçÏïpV&<<\~çw¹Y***ä‰'z-Æ!C†È•••ÞÜ6¿Ðã„xôè³ò–-È.ru5òêÕɲÙ\äÕ±æÏŸ/K’¤è=z´W? Ëå’Ÿ{î¹ó,£J¥’çÏŸïÕà«¢¢B8p ×b|øá‡CÆÇØ£„h±”Ê«V%ÉUUÈâÒ‘·oGþá‡'ëèÑ£r\\œâ>áöíÛϺ‹\[[+WTTȧOŸ–+**äššš›×¦¦&ùšk®9ϺºƒÃá䪪*¹¬¬L.--•«ªªäúúúv>ÁU«VÉááá^7Ñ«W¯V|ïüA59ò4/rñÅ I⽺:ر#š‰ÖÏãcÝ}÷ݼûÎÿàƒ2oÞ<ªªª¨««£¹¹Ùí¨X’$t:111$$$`0Ú>Ûºu+—_~9‡£ÑÈÆ9r$²,S__OUU&“ §Óéö:Ôj5F£‘øøxbbb¸ë®»øðÃ}—VÆÏwß}‡V«õj_Ñc„hµ–±~ý`.½´Ž³#çeöì½þ7 ò R«B;açÎ\y啘ÍfÏÍÒ¥KILLÄáp´ûL’$$Ij3Óg£V«‰§oß¾¨ÕjÓ¦McÕªULŸ>O>ù•J…Éd¢¤¤„¦¦¦óŽ¡R©ˆ{.áááœ:uŠ›nºÉ+׎N§cÅŠL:Uñ¾¾DÔ³+àĉyÄÅÕÓþ}I‚œزe1YY–ÞéqdYæ•W^Q$¾}ûòÇ?þ‘ØØØ6êõzbbbˆŒŒD«Õ¢R©p¹\8©¯¯Çb±àt:©¨¨Àd2‘‘‘AXX?þñY³f wÜq*•ŠŠŠ NŸ>ÝfU*‘‘‘DGGÖæós:X­VhhhÀétb6›‰åg?û¯¿þº[±ºC«Õ2qâDfÍšEll,N§3¨¾ÅaÍæB6nÃØ±5DG»ßfÏÐjfذ…«´´”)S¦pàÀœÍ}ûöåÕW_¥_?Ñì RRRˆíÒúÖÕÕQZZÚ&z­VKnn.ÅÅÅŒ?ž;w¢Óé8}ú4 ,k||<)))ètºNm·Û)//§²²²M|ï¿ÿ> ,è°IHHH`Ê”)Ìž=›ÔÔÔvß3%%¥Ëûá/z„šƒÕ:Ÿ1c:Þ¦¡¶m‹aܸ­DD ìp»íÛ·ãt:Ùµkü1;vìÀjµºÝ6""‚7ÞxƒÅñbccIOOG£iߘÍfÊ+*h4YШUÄDG’””„F£ÁétRRRBee% „œ››ËÍ7ßÌ[o½EEE²,£ÕjIOO'&&—ËEuu 5µµX›íÃô$&&íæ)lhhàäÉ“Øl6\. ,àý÷ßo÷©T* À-·Ü¤I“ÜG£Ñ0|øð¶n@  ù¦¹©)ÒÒ÷¸øâη‹Š‚ÄÄ: æ1bÄkn·±X,X­VŒF#ãÆcìØ±äåå±téRV¯^MCCCÛ¶’$qÏ=÷´afff;+h±Xذe7…Õjä°4úd— ‡µí8J`øÐÁ¤¥¥!Ë2UUUX­VJKKéׯÕÕÕȲŒZ­&++ £ÑHáÉS|¿+“”„:,µZ‹ÃnEÞW@‚®ŽIG¶[^Evv6yyyØívî¿ÿ~¶lÙB~~>ƒ±cÇ2kÖ,ÆŒƒ^¯ow?dY¦¶¶–¯¾úŠ 6°råÊ YÅ·ˆ<ŒÝ¾ˆÑ£»ÞVXÅHÆÛNDÄ ó>?xð sæÌáöÛogäÈ‘íDUYYÉ_|Á²eË(--%33“wÞy‡ððpjjj>|8}úôiÛ¾¦¦–¥ßìF×÷2´z÷Ë;MÕEôQàÆë&"IÇÇd2!I%%%ôíÛ€ŒŒ âããÙ´u{KtĤw{<Ùå¤þäV®¿´/9Ù™í>+--mkâ7mÚĶmÛ˜9s&n»yyy,[¶Œo¿ý–úúz–/_ÎŒ3:»Å~#¤…ØÔ”ÏÆ#7ÎLT”gûìß.×=ŒùöyŸÍ;—'Ÿ|•JÅ!C¸í¶Û¸òÊ+Û­nnnfݺuL™2Y–Y±b÷ß?™™âÇ7›Í|°r+†ô«»ì'67ÕÒÇuˆi“'b2™8~üx»EDDdÏþCl?FDbV—ß±îävn¹"””3ÆÑ£GÙ»w/999îgµZÙ¾};K—.eÛ¶mçõ%ï¿ÿ~Þzë­.ÏïB¶i–e™üü—IN6éù~YY°iÓ˜L¿'"b@»ÏV­Z7ÈÁƒ9tè©©©Ì˜1ƒ©S§’””„^¯gÊ”)mûTUUqêÔ),KÛ{›wìGt‰G®"½1–‚âN—–’Ò§F£‘ÆÆÆ¶Ï1›Íl=\GTÿ¡}Ǩ~£Y³ewÎLn»†ÚÚZöïßOvvöy×U]]ͪU«X¾|9………f6lØ€ÝnŠO18=Shj:ÎéÓï‘“sÆyí з¯¼¼‘å3–Çl6süøñvÛʲLqq1ÿøÇ?¸óÎ;y饗(((hg± ±Ûíœ:u 3¯\FæùÓÛo(ÛvA’¤vFCdd$Á4Ìãã©Ô¤ÊÊÊÚÞ«¬¬¤¸¸¸í‘e™ÂÂB^yåî¸ã^yåòóó;Q·º‘‚AH Q–eòò^¢o_3Ê÷ÏÉòòhh8ÐöÞéÓ§©©©épŸºº:–-[ÆücæÎÛö~ë>‡n9N)’1Õí1:F¢Æ¢Ãn··›eQ«ÕhµZŠÊ›Ð˜}ÀŸAA¡x8dYæàÁƒØívL& ú€·ß~;}ôÕÕÕ³±±‘ÂÂBE×á+BRˆ û©¬üY]w—ÜýúYÉÏÿk›U,**jû‘:£ÕÝÒJ«…9|ø0&“‰&³.\ñ5Ùd=v»½ë§u6ÆæT!IÊ~ •ZC£EX·ššNœ8ÑîzµZ­ÇÎíV\.GU´¯9!ʲLAÁßHN6ye [ÉÌ„êêO©¯ß Ðæ¯ó„úúú¶1,, Ù½6n܈Z¥ò*êZ%ÉH’DsssÛ{f³™††$¼/Ê2•è³lذ¡í!k½Þúúz¯®³¼¼\ùµø€bCÃ>ªª–ym [ ‡ÔT3ùùm9nC{œ} m–%>>È×_F«Áa©U|=:ÉÒnÀf³±cÇŒp9ì}>»…˜(=µµµ¬Y³FœC§#²edWYYé••Ü'_rBÌË{Áë¾á¹dfBMÍgÔÖnStƒËËË)..n9FfÛ(²¢¢‚5«W£¶+º§½™´8Gm;.ˆY–]»v¡q6bmPf‰LåG“Í{ï½×ÖMKKkëƒîÚµKÑñZ¹ D ¾~/ÕÕ+ÈÌìz[O ƒ´4yy/a·{™b·ÛY¿~=qqqddd´}¶iÓ&j‹÷ÑXuÒ³ƒÉ2õEÛHë›È—_~I\\ûÅ^C‡eÝÚ5ÔøÞc«h³4×Ìš5kؾ}; ú›­Nz³ÙÌæÍ›=»¾s87²(P„ŒeÙI^Þÿ’šê \ùX C22 ¶v%²|LÑ~_ý5H’Ä„ Ú,ÓédÿÞ]ÛøÍæú.S_úéQ¼þúë 8µZÝngëÖ­¤¤¤Ï‘]«)ÚÿM—Í©ÓÑŒµx#Õ¥'X¶lY[_677·íÙ´iS»—"•8m}Hȱ®n'UU+èdbÀ+ èß߉Á°%QNEEE|ðÁ€è'N:µmÄër¹(?u”­Ëž£²h¿[ñ8íVŠ|CéÞÿ°â“¥Œ3¦mJoùòå<ÿüómW_}5II‰Þü×-¦Ù\çöšL5Ålúy{×ðÍ7ß´‰055•É“'bòÚkîçÚ=Á]@D ‰™•Vk˜žnçœyyŸ™ ƒ×3d8Ðõö­¼÷Þ{Œ;–‘#G’••ÅôéÓùöÛoillD–eLµ¥ìüì¢û“6Œðèd\N5%TíÃÖTƒA¯ãÚk¯eÐ 1÷]˜Œßy s]o½6Ÿ'~ÿG´Z7Þx#ë×GaÞzvŸÚIbÿ‹‹KGÒEbkª¡®ì•ÅÇpØ­íÜ2 `Ò¤I ÿøÇ?(**òú^+_wHÌ5WWÏž=×1a‚•ïƒÏ9v >úþügPâ^KJJbþüùäææÂâìØ±ƒ#GŽÐÜÜŒ„i%âj’#Õ$Gªˆ SnÐâŠÎD›:’ð(Ñ/ÔšOc^õGL•bÀ¢RI$]| ¶á÷!Kjd— Keѵ{18kq8ØœÂ×è’%ê-2§\”›\”6G0lä† ‚Z­Æår±xñbÞ|óMÅþÃV$IâóÏ?gÚ´i^íßBBˆÛ¶M%:úk0ã3š›aÝ:xê)Ø·OÙ¾ÉÉÉ<ýôÓL˜0¡í½úúzŠŠŠO3(¶™¾Æf -*]8Mºté4kÎ4sÆÆ}dÃ9#nY‚ê¤(Îü Nµ¾PÉŒöR¢l' sV¢u‰ÀZ»Y•Hµ:æ°P‰Íjµ²hÑ"–,YⵌF#;vì`ðàÁ^Ã[‚.ĪªµìÛ7… ìœ5ûåòóaéRøýïÅZ%h4n¿ývî¸ã’’’Ül!çOŠkìµ$”BßSo!ɧ3±„çRÒÿab.C–Îí̶^ì9Ç—]èª÷ó·y¯òÎ×»•|·¤¦¦räÈ"|á;SHP…èr9ؾ}qq«0 ëí»‹Í6Àï~'–xCÿ”x^zd:#Æ^ŽÍ˜‰Ssþ¦všÑ[ ‰©Ù@|Ågèl[–4˜"‡S•| ¦¨‘ØuIç‰R’hm•Pñ)ÆÚƒì,0pçûõäW)ÏÛs67ß|3Ÿ~úi·Žá-A¬ÔÔ|Ocã·A¯«VÁ‚Þ÷àÆÏ_§—ٳŠE©ËL’àÒ¤&ÆZÿ‡ÞÆfè‹MŸ‚]CÆÙˆÆV®¹}s ’¬¬™”d‘ {ˆl؃SmÄ–Ž]—ˆ]Hhí5hm•,E¨-¡dŒJ‡û/5òô—îGÛžrvø[  š].Çÿ…ÌLîÖ :Ÿîݱ¯»®ãÏú÷‡K.‘#açNeÇM0ªùÉ%gGBFo-AoõÎ_×jgFÓaàp—Ûê´nÇßÖ«©nê8Ì«3 “&Mòj__4?beåjššÖÓ¿`Ï«Ñ@v6Üvn€Îœ¤ââþvÔª ïÎÁIJ´“ÜïZ/»ì²¶ô`!º\vòó_"3ÓI0 ¤¥Á¨Qtº*ð\T î#æý¨ÔŸD¤Dy¿.ù¾ûî j¶‡ ±¢â+¬Ö-¤¥ãìÂ*æäˆ¾¢§³-’)Ñ2zm¨YCF-©WÊ~ÉÉÉA[4ÕJÀ…(ËNŽŽÌL‡â¦Ñ—ôë'ú‰g¹;Eu¡)Bdpyqy’$ñÈ#m޹•€ ±¬ìSŽÝôó<_’_hí+Þz«øwW¸€fGè ±Ù¡¢Ö¬¼Û––ÆC=ä‡+RF@GÍN§ßÏÌ”ƒÒ7<—¾}aøp?^ø;C–¡ÎÒâ÷®ô+»Š:«Bw‘$1ç7sІi)­+¥ÑÚˆÃé )*‰0]­µ*0ùp*Äòò•ØlÛƒÖ7<—³­âöíÐAæ@ðT­ŒÍaAìR¸GÂbSQgQ&Du5¯žz•?<ö̲ô€’Y"FÈ´\5è*¦ŸÊ%™—ø5IÀ„èp4‘Ÿÿ99žAjª°Š&@KĽ[d  Z¦É.r}E‰z‹Š²F>Ä(p<ë oD$Ú:j²S¦ÖTËúÂõ¬?¾žÖ¿À˜¸1ϻѩ?±Ûul)T ŒYÀXà  Ôƒí#€q ?,³ÿÒýÜúޭܲðNzº\Â"Ä’’÷‘¤h Pöo“R©Tà68¦Ôj0@̶t˜ë’aÍ1hβŽilÖ±³ØC!^üp/0 ø'pÈÃiqàzÜÅ_0ê¹Q¼¿å}œ.ï¦ÏÆïBt:-äçÏUd ’“½;Ÿ^Þ'%Á AÐÕtë®S2oPd5E5*ò<‰¼ ,ÂÍó$`:° Øxª§0`ÔΪåžÿÜÃo>ü &k×É :ÃïB,)yµúget󈈼ZRªÓy'DµZôgÎ켯xª¶œPÏè/œ.=ò]TFïg·JRËûw›€•€§Ö^ Ç[Èm¯ÞFEƒgánÎoØí äç¿âÕHY£„åçôÖ"‚°ÂƒÁ¤étè+tº`ñ0û¶¯î55&Ÿ´vþ`\ |tÔÝéüÈV ¼÷ž’òÏe¾Ò|Åä—'sªú”‚ÏàW!–”¼‡FsÔ«þž·BŒŠ£û¼™]"I› 3~ Q­þÂ>ÀYã6€m¾ë§{¬e_‰Š]ÅÍî?WwK€®pñˆ~ãIàSÚcç6wkÝ#ÊîHF8¾¿”®×׳am/y»£ë§ÕçB´Ùj8qb>ÙÙݳ†à}aââ +n,ã|!èÁþkxb&öCvŠÎ(kÐñïí6J\¸ø ˜ýJ-×ê‹@òAÀUˆ·ÒuYzàvø×Áñæú7»ÜÜçBbssEE‹|j [QÒ狌ô½¢£!+¦—z¾\Å)Áÿ †©WÃaË·¹£Ù!ñ1j^¼ÜIE¯þp)i€[€m(w錇íÖí¼½ñüòtÝ¢(Gñwbcë}Þ?eBŒï^dwG´ú§VynAhac¢hª—¥ q*Áb‡%.šàâT¦Óó§ÀÆ™yr_ÓǸ åb׃ëz/~ù"õç¤}î¶­ÖSý“|o A™}9b>—¨(ÈJ„™^T«0Àíá·£=U×Z$^Õªøõ$E9.d%÷Ö‚˜köWe€7µÀéØÓ¼¾îõvow[ˆ'>¾ãÊòÝ%T„ØÚWœ\}ÝLïv…C‚áêIp¨“{esÂ~‹Ä/2à™)25i²òå«fü+Ä(`"ð5Êû¢¯•™·j^»¹èn ±µ¨·¯°ŸM¨D47Iô½AvÄÃÕ×ÂýÅàSnÉÐ`vÀ!ü9¦]#óÉå2Íq^vôümAÄ86 ³ïe1e,ݹ´í­nõ¨NœX@ll511Ý9Jç(—/æ™»"+ &mƒÏ,Pâå]©‡{.ƒ¯#`LœŽ‡ °' êb@înÿ.B CŒ¢× b5•\³¸þµñ_Ü=ánôZ½÷±©)ŸÓ§ßö«51»âißÓßD_1' fyYMVo†ËÞƒk†š§á¥ðÚfX[µq>¡ hB4Ÿþf biA×)Ïç"ØY¹“…"I¥W±µ¨wR’ÉãÊòÞ#Ö˜Ïw=G „";ĵ›a™B«¨o€Çï…± Aý¢ N_|_΄¦{èž5³ šÌ@QL¶ÃQÖÑ3€s “OwÊ„Ü ÞYD³9ŸÒÒ÷ÈÎöÏHùl¢£»^øâ:Ñ4ƒXÔ•‘·–x>Ž\0ãy¸d=Œ–Å$ÅX`’ 7XáW»á·¯Aä»tÏmFt>!D‹¯ªðnêo|qà N‡r‹(Šzÿ•>}Ì"“Yl,Üy'Ôu†¤Óáwë|6ÙÙpõXn†"¦Ó6ÁŒ÷apv² "©Âx@w¬oÀËcAéå…U"–‹úÁ±ï–HÄ—ÚŠˆÒQB:Z 9ZvT¹P^þ‘Çy»Kx8ÌŸ˜s)!<rÒà¶ø[nç¾]U3üäÏkßîÐ"–×ÁÖE°aÞ‰é$b^8\¼ Ô#¢Ä=%Ì‘fTÖ4‹¾á+ôécòËTZO#3&6Bvk˧¼Wí…atÞ”ë]­Ÿ| q$„ê”B”[¦îҧ奠¼ nF?ØU¸K™öQ]ýI·‹z÷ÂÃ!§oç#èø˜ýªèJyÈ n‚k?:I“ç–:DÓèß§e±=Q>í'ªN(b^Þ‹ôéÓä“¢Þ½…¬,¸¼ t`o™ƒ«E?ÐSr€I[Á¨´(ÑQÄ*<F@yÌPÄ€Ei¶4#T›ª=]saXIDATb}ýª«—_°†çY©0ÛÍ:ý\û1(­l—äš`ìxna\ˆÃ‚“¢? HÃó„N­ ÁÒàÙ`E”±}‰ÔT»ÏO;bß>øâ ïö½î:¸øbß^OgdfÂÄb!žcgµã—C†I¹'E…èæ]ó¬-²=Ø)áȾHáÉ|… a"/ž> ˆöLˆõõ{¨ªZÁ•Wzy‘^°k<óŒwûFFVˆd¤ÁmÅðâ@î¥vÀÄåÂHxC 0¬R¿€’Gè|”c¾Aø€ü=µ×CS~x>z6Abdb׺å(þBzºÍïÕC{2YY0Þ ƒ[Ö Ø™'•õ Ï& èë‚«>£ë ÔÕˆ&¼‹D£~'árRRîŒJÕµkj6S_ÿ A¬ŽÕ#Ðé »¿˜mQ7CúRˆu*Ïøq6ý+Cø2ÄŒ‰;v»‹áƒZâ³… „ É, -Örù€Ë;¢ð¾D¿~Ö ÖÐú÷‡K›aا| û“ @v\²±®øìÕ˜N`'ð9b¹§‡¹ÉýNž ñ 1atÆèΟ¡êêõ44¬fĈî^Ýz=äö‡UÁ—€¼¿{ÇS™ˆ`Üï×ˈ‹!]Èô€Z×ÓÑ_5#¦;ÂÒ:‰Çg<ŽAkèXˆ²ì"/ï… }C…¤§ÃÅEД¨ÜíŽD ­¢¦@ 1:v"¦`²Üœ²§Ä#º刧ÈN`Ÿ:èd]]½žÆÆµ/cÛÓÑé «? Ê„jˆÈê ¢ VDó{%" u8¡'B²Ét<`±#rõ¬Ój;·‰xD·Bt¹läå½HF†«Ó,ûpOÿþœ–QàeülvÀ¦GÈU»ê„$DhعÔï!2Œ} ˜áó–êðn›æªªµ46® ¨/î\î½î¹Ç»}ý#Ù ädîŸÀþkoWST's¡Î‹¤¥A#áØnÅŒX ½Ødµ$tZ³f &“é|!¶Zì,—_Ö{Š$_PÝ!- òÞ{Aú'\b*J¾’8"Áš;ÁE4=&a‹®¥½À1ÄB«2ÚM[VWWsüøñó…XYù Vëæ)ÜØSÑh ' ŽNƒ’o@ÎBÌA¤åîÌo&ÕÀ> ¾½Öý8WìCâ€àà¢ZAn#Ï›››ÉËËk/ÄÖY”`õî-¤¦ÂàB8=Rò„7c¢?”€h®œéÙ¢*Y=`ÑÃÒßö0kb„†($TßŶÀÚ ±¬ìSìöA/êÝ[Ðj…U´^£¿S$a­EˆrÄZ'¹å¥Aü~ýÏ+Ìyþô 4x;W tˆ%a(♢ޮ(êÝ[èÛN ‡ŠñÐ÷{!¶DΔ=qqFˆjÚ÷! ?ÀÏ~ó_g(Láy‚!FuTRRr¦«RQñ%6Ûö ÖÐÇh4" "ïVpºq…©¿›†ó2*Dd÷U+a¤7©à‚… !BœÆÆF!D‡£‰¼¼ÈÉñO6­ÿvúõ×(õbÁ™>aÝ«»Xtx,Äúúz!IJ²ŠŠz_@­ií n‡ñ‚iÀEGáÚ÷|~iþCAÓÜÐЀªµŒmV–²2¶PFJ Hàԋ˜A5+ÃÔÅ  rÙ5Ñã±ElnnFuúô$é ¢¢ÞPŽZ Ù¹÷»" È)„Ñ«}}e~BAÓ‰æøñ${÷úõ².¸\`M…S“ ãKeûjnëÿ »¯W¨·^N<^ø…&3ó¿^;ìvÏ?ÿ<õõ–3Òƒá";èc‡Êk|v‰^f‚[çÁ0³d¸#0ÔâUžë4`èfˆ©„š%œòWhâ£~½wÈ²ÌæÍ‹((ðPˆá"‰‘Nñ,ÊÙǼ("éKF¯‚¨ÿÀW§õ¼& Hn‚ÛaËÍ~8/iF¤¬ó€èèè ¬€E’$rss=ßÁ…ï*)ù‘‰+ ÕO"l%™ÒOT` ! :´ëZ‘QÔç*'ŒYíÿ¥#IÀm ó"wÀ"ôÐ"6¬‡±XÄ~Ç ¡ÖÿAÓ@B%ÄVøùDÝÁ…ÇBT©T :4xB6l’§‡­_,„° ¢]Ý[>ê  ºQ$w Yˆh턇‡“Žõ*B¤ö}¿ŠÑ®‡šhÌ÷ѧF 2 ªB-‚Q@ü¤h†?ùä&OžìñîAoš—,YÂË/¿ì{¶Rü‚.¬Ý¡Ù…C»tù„*àØ(°„ZºbD ´ ÚåqdU AbYY?þ8‡‡¡¼Þrx‘îäî Ž]8! v=w@ˆÑ)šåd…U܃*ÄÅ‹SR Ïñëàåøh¨Syï B ‡Æûñ$Þ`EÔà;)þ›žžN”Â*îAbSS~øaàN؈pëø‰ã£¡8I¤œóÅÀC©'µùÉ ‘ؘ0a‚çÑ÷-MˆÅÅÅ9r$°'Ýà¿C;tðý,ÿ]¢ ¶áÖKÜé6!ÄØÒõ?^¹Éš‹ŠŠü7@éˆSø¯ŸlšÅzÿ 5¥aâ!Å)DèBñß°°0F­ø0AbU•»ú~ÆŒXÔã' FÀÁÑm]%Ÿ!#~ëoïS¬Þ]¶"rd·Ü׬¬,RR”g:šSƒ‘/šÎËru—Þé}Ç[I€ÏÓ9uˆRGϼ5fÌ”‡MˆýúõCèjBýñ{˜ÌÑK`Ý-ð¾™òs!üÄŸÿ ªC)c› ¬B”d;+Z|Ê”)^.¨Ñ›¾D·ðî)Â¥†%O¡Ï‹tvÆ1`çpøê~Ì—”;5TZž¸ˆˆ®¿þz¯4!êõz~úÓŸÀÔÀœª²¼¼¶G´y4¼¢Ø †XßÐ…¨@zv°×^{-11Þ-ª ªCû®»îj[Ååw~…H M€Eƒ­QlI)µÀ5üëy(æë«ë&yÀÚ•9“$‰™3gv]ÓAbDD‹-ÂhôóŠàqÀÏü{ wlœ _†ï¢à8ž§ï©6jáß…`Õ)¢ ãAÚÈ"""¸îºë¼>lЃ&L˜À¢E‹¼iyÄàu:ΜéGd•ÒŸ>†/ÁFDSÝÙ ¦!Â7ž…¥¿Ñß!Å&„5‹Ö]mßSÀàÎ[âx.pŸ#¢kvà6|îÑGõYðJ"Àˆ#:Nowq3ßC¤?¾@×ÈÀZ`5ðn×?¤§§3gΟ²WQ’$žzê)÷󜭋î¿G,+ á<‹!Œߊ–¿nî—$I<ñÄí²yu—^!D™>ø ûíˆeëb d~ž„Œ˜9Y¬ABºaذa>Xéñƒ•³©­­åŠ+®ààÁƒî7ÐW× FÓ‡ y6K‘5•î7Ñjµ|õÕWLš4ɧ§î5D*ä… b0t0±lC47ß!úŒ!œ > ¸}Âÿ ‚];!ÀC=ä6›WwéU„Ïñw¿û]ç¾-=bzp¢ÀÝ+͈Ññ*D÷¥“ŠVdëÖ­^ÇvF¯"€Édb̘1;ÖIU5"—â8D3jk… øÑ$¯§Ó=ƒO?ý´[¡^Ñ«šæV"""X¼x1D<8“÷_!¦¯6ã×¥¦!G1°ñý¿¡Ë*Q>ú¨ßD½Ô"‚˜«~íµ×xì±ÇºÎ­“L@XÇ鮄T0°#œü_ Và¤ËˆÝn¸%K–ø5€¹× Äôßc=Æ«¯¾ÚõÆáÀDúºéÀpz_{Qðî@´å]ï’““Ã÷ßß­ WOèÕB0›ÍÜxã¬s—€ÛÀe 9 ±º§ãDÌ.}‰ˆ®ÞƒGÕ^cbbX½z5cÆŒñëåÁNŸ>Í•W^I^^žg;„ƒ âǸB{¾Ä‰X`½ 1Õ¹eíÁ/n0xûí·¹ýöÛýy…müWàÀ̘1ƒ‚‚Ïv«þF!yBœ=Á îB,ªþ‘·p?"-ˆ‡1Æ:ŽyóæñÀx½*O)ÿ5BD–ÙûÝçÜtËlŠëÌñ©ád#‚‡g(Ö9q!VäoAˆo"ˆ’¯+Á¼™™üê‰? >Âã@aŠ9oèýB´6À¾e°ýßP´™C ®[§•UT!bé1^Úòï`G€×!2.lEä),@PaÂ)­æÞsF·ìë ƒ×ÁØû`Ðõ ñ_sÐ{…hª‚-ÿ„-o‚ù¤(ûh`×)˜õœô&«¦ áÞ€p‚çC[þŸD`Öȸ+ðO ú€-IÔ9‚XêÅ2½^¸~}µ°ŠÈˆð/Ф†ø¡pÅ£0êvÐû¾ÃÜû„è°Áž%ðͳÐT DÆyVëH9üä=ØÙÌšaˆu¡ý¾È¾q¶ZÍáwË Ô*Âýr±Z¿1ð(Fd­Ãë¬OQxýGð£Ñ-"<"–³^‚ä‹aÚó0àZPùn¥WïbU¬˜G?‡ø ØI³Yc†Ÿ}Ë÷ûàÜ„Eì‹e ‡¨w‘Ôò^,b¡¿þœ—ÑkF„ç7#,Q9Bl•ˆLñõ-ï•´üõA oÿXøè^¸,ÃeD¤{½.¹nø_0Æuÿ"è-B”eøá øè>PU xh…Nxæsøûw`÷U[ 1—‰_LËßV ©mù«iÙÎ…ãÙ/+BxµkW°Š>œ†¼<Þý d(Õ’‘Å8îþR»Ÿ¿¨ç Ñå„M¯Á翃h‹øñâtÁG»áÉO¡ÄŸ•áU¼d„Àœ-[_~B§_Œ‡ç¦A¬·£ñ€8’à¶·`èÝ]÷l!Ê2¬Ÿ_= ¶nç·)¬†G–—?€«çÞ•NɈƒ·ÂM¾Ê0Ö˜¢áŽwaØÍ^¦g qÛÛ°ìH´û,É’K†·¶À>‡Ê."RzjÜ;^ºâ}=è5õðÀ7é]˜ž+Ä­ðúdˆ5ùŹ|¼žû –î«îPA%Á¨~ðçi0e°¤_¨\ðȈMS¼{Ï¢µ^Ö}~ Ù’eØ|žûÖ›ž‚d%Àï'Ãí£Áèï©I1ºÏ¹ îú VV ¦g ñëgá»? WIf5œ.øöüù+Ø~2°Õê½!9æ\].|„à ”¨á®%pÑ,E»öQpÓP!À‘ý„ ƒJpzù†{^&«gYD—^¾äC!hsÂá2Xw¾8[N€Ù.ú—þ@£‚AÉbà1e0ŒI‡?e}öšZ ÿmp÷wéYB<µþ1RlbF"©³À†<Øy •B^%œ¨†F/²KhT Ù 0¸ ï ×äBfBð~:ÅTDÀó óì)éYMsÉP‡®AX§›‡‹— Ø`¶Aa œ¬z Ô[¡¡åej½¢ã!2¢ }"!7I 6´#„*@6Céè©Ç»ôNïéTÄç"!«ô1•6ªŸ›š éô´_£cT€Æ¥Hˆ=kš©2¤­¡W¨ŠíIÏÔˆßËCzŽeš{Ò{Fo{°ZQ!&lÞ3$ÐCß›¬”Þš]BFQ$wÏ"€1Þó:b='âGëm˜0zžÈ³g 1e¸p ô&lçüí ¸‡ úxkÖ³„Øo8´½«9³†ñ··à0(ŠÜîYBL Qý{Ïæl˜ü XT½§y69WƒÞóús=Kˆ=Œ˜Õ{2½6ý.…ñ¿}rïxÀdÀ$Á(eõ}{–ÆýäØžŸÝ4ªáêÇÁã)Ö€ôtš€˜A0|º¢Ýzžã³à⟊å•=¹)«úŽ…!-¥e/» é=»Œ ¨SÁÕ¿UÔ,CO¢$ÁµOCxV—YNC–fÀb„›_>“Æ#º/Lyª¥žë¢ª2®Ñw(Þµç  2 n}êt=¯_åDdl¸êw1®ýgcî€á?!÷=ÍÚ›GÌZäqÄÍÙôL!‚H 4õ¡JÝs|p.„‡Ì†IO¿X­…Ù¯CÜh±€½§ˆÑ Ô…Á߆¤^¢ç DR ‰¿…Š F'P.Aÿ)𣂦ƒ0¢°h‘=!|XÏ£¨ ƒéóÄ"{/éÙBTkaÚ_àŠ§ TRœ†-`Ø9l2§ÁO?„°.–&dÃýŸ‚q„° ¡êÀoª 0óÂ›Ñ zV„vGÈ2ìx–? a "ïu¨dïb+'·Á'Aùv‘ ,X+Ù@XÁZ@›7Í…‹fƒ7i€Ͱa¬y´µbw°BÇdZšb5äÞ3þ Y>9tï"ˆ¸ïÿë^u°ŽÌ{í@,©lÒè;áú?B\ÿî·d/|þ4ä QN±Z.P‚”Þ‰:@ŸSþcî긟ë½Oˆ­Ôž‚µsaç{ ªYÂÂðO“-#|ƒ€U§Áuÿi£}®C_ÀÚ¿BÑ&0ºÄ÷ò×ò 'Â6†T÷€ †ù¾æGï"ˆ¾cCl[ {?†ªÃ`pˆ\9z΄é{ƒ1R7f "Ò`èÍ0þHìÓlªçŸÛ.º!›^ƒã«ÁV!¾SB”Þ>l­Ùi­ˆïe7@Ê(¸ônõ£®YÝ w ñllf(Þ-zýªóÀe‹|t´OœÙº†¤5`õìDšv„¥pˆì'¢L†LƒÌ‰>ËžªˆúR8¾'¾sHÍâ;µ&U#Äyö÷jÍÇèäLÆZ‡´QÐg œ Cn•›àŽøïâÙÈ2Ôž„Š£P²Ê€ºS¢9·Ô Ñ:¬ Ö.ô‘ ±é˜+ÂÑ’AâP‡ÐÒ;›*Ž@ùaѧ¬.€Ú"h(…fØÍ"I6L|/cĤ‰ï•2 úŽß+Ê¿åÎÜñÿ§™cø¹5d?IEND®B`‚phpreports-0.4.9/img/runbetter.png0000755000175000017500000003422210442102126015642 0ustar fikefike‰PNG  IHDR¢¹«ãäCbKGDÿÿÿ ½§“ pHYs  d_‘tIMEÔ,éI¤Ú IDATxœíw|TUöÀ¿o&½I tB饂€*TÔÕÕÕÕuEY;¿]u­ˆ‹Š WDV\šR¥#J(!BéÉ$SÞï“!u&ozLø~>ó™dæ¾wï{ï̹çž{:ožJyôzh×n¸‚‚ä3“ >ø²³á®» yó²òK–@J üñа!9ß}]»ÂäÉeå.\€O>!C`Ī”_~Yñ3E˜˜0š6•Ï á­·ªoeôhÐéàÿ³]¦];¹¦3gl—™0Z·†÷Þ³]füxèÕ 6l€]»*~ cÆ@ûö¶·räÌ›;wBHLšû›ÜO+Àÿ ½{Ãõ×—}~æŒ<ƒ‘#aРªç6›á•WäïGˆˆªeV­‚ÇaØ0:T®eÃ9ßÈ‘eåaùr7úô„X¹Räá®»ÊÊ¥¥É³îЦMƒ¯¿†'äÞsOY¹‚¹¿ññ ‚ZíküxU5TUUUµ°PUÛ´QUEQÕíÛÕ Œ¥ª~~ªzâ„ü¿l™ߪ•geï^ùü™gÔjÙ°¡úv€ª6mªªGŽH¹Œ Ûå@U_]UçÏ·_fÂU9Ò~™>RÕS§ì—ùàiÓOTÿ}D„ªnÙRýõZ9xPU7®zì Aªš—WVîÃåóTÕb)û|ãFùüÕW«?qqÙ9Ïž­¾Ìí·Ë÷/¾(ÿ¿ñ†üß§OźV®”ÏÿýoùÿË/ËÚZžýûUU§SÕ©Såÿ·Þ’rªš–VVÎ*+}¤êÑ ;C§N(ÒúðqcÍ¿f[$'Ö-Ž ݺ‰F‰‘Ï.\€×_¯Z¶K)[þÕ¸1DE•ýoÕ¤ááeŸµjmÚ”ý*eš5+û¬¼6RiOåº5ªØž&MäóØXù?7^zÉöµ–”À@f¦3oüéOàï/Úñÿ¨zLbbUíë)~ýrý<7Ý$š¾¸X´£•E‹äyMžŒaa°m›Üü¤$QÏ©©òÙøñÎ7`ñb;Ö±cúõƒM›äo³zH¼w/X,ËîÜ)VE‘÷[o•÷ùóá±Ç`øpøþûêë9~ú ^|±¬ëP8}Zþ „={ÊL•ÊuYùË_àÉ'¥ÝO}ÄN±ŽlËóÔSÿŸ2Å3‚h4Ê ¡§•êºXëgÕ=ë}õt÷¬×‹©»ŠNWæPÿåÈÏ¿ò•hÄÀ@Rgg‹ê<~\QQRÊY5JØ‘#â~ÑB¿~°y³üš 3fˆaþç?‹½YžÝ»«ºoû¬ìŠrŨÄdªxr³YÞ­ß—'8Xœ™_|áxÃãâàÍ7åA¬\éy›ÈUÆŽÛð‘Gäÿ>s§:˺¦óç«~o½ÖêìǨ(ñ着½'‰‹…R\,Ó{å±ÚÌ•{;«)QY&>ùD<1Öž«œLTü©…„ÀÝwËß‹‰c­Ðß_.<'§âÉóòDPËÊ3s¦4h÷n[—jŸ>}äÜ……Ž z|ÉwH””«WW_&8¸¬ÛNH¨ú½õ³Ž«?þöÛåêì}u„;îg\¹.«“>?¿L!È„ªVtâgfÊÀsðà2Û~ëV¹GTç¾¹ãéîáÇå3½¾lº-1±¬ln®ürýüªzÿ­ôê%®gm™’’²c­>ÅÚNLŒØµ £íê®]¯‡äïuë*–9wNº0E©>ÄðoÝÚó.AYLLÕºbcåÇ‘!f•ãÇ¥lttÙg+WŠ0Ξ-Á0¢\V¬ªÄ-dfEUáý÷ËÔlÏžòþÝweªxËq/´mkÛ~ ;Ï,yeeÁ¿þUÖ½5iR}¹Ê/Oàh]³gËtûv‰œ©Ž)SÊ´šuZSUaÁÑ*ÑÑSAAeÂîÊ5hä2«<;J;._.‹K0›ÅËe#z“IL½Òyeš5+‹êYºŒFí?ýIÞ7n,3†§M“îyÇùûé§e^VUaêTû2c†í®»2[·ŠFûäù祎6m$¬¨ùD4ÿ¬YeÇ/?n³¾ü?ÞxCºO«¤‚ܼùó¥Ë°ú}ER;v„eËÄ>ìßž}¶¢-У¼ñ†h„Ê Þ¾ýÊÜbÚ·—ã*&šÃj´‡…U_ÎJåQæÐ¡RÞÞtåCÉôSå¶EEÙ¯Ë:ؘ8Q´óС¿Ÿ:UÙ\ÁgV®]%°áÕWe&)4T\&᪠º“ÉDBB«V­bÛ¶mìß¿ŸœœL•DìàïïOTT `øðáLš4‰6mÚ û½Ž äê¨Ù’’’øôÓOY¾|9ǬË+Ü„N§£OŸ>ÜvÛmÜvÛmÄXçúë*öÖ~_¥zöï߯Μ9S S¿¢¢¢ÔG}TMJJòõ¥{Œ«‚è)))ê½÷Þ«zE+¿4h Î™3GÍÊÊòõ­p;WQ%%%êÂ… ÕÈÈHŸ`åWË–-ÕU«V©f³Ù×·Æm\ÄHMMU'L˜ *Šâs,ÿòóóSgÏž­æççûú¹…«‚h‡½{÷ªíÚµó¹ÐÙ{ }úïBΞ=Ëõ×_Ï!wdîòW5b%¶lÙ 7Ü@^^ž¦òŠ¢Ð´iSºtéB@@§OŸæÄ‰˜µœz½žøøxâãã1;vŒÔÔT,.{hÑ¢›7o&>>Þ¡ãj¾µ j'OžTccc5Ùf:N½þúëÕ­[·V½?~\}ôÑGÕàà`»ç Rzè!õˆ5 i)f³Yݱc‡zà 7¨z½Þ!›±W¯^ê¥K—¼yÛÜÂUA,¥  @íß¿¿¦‡¨¾ûÑh´{Î-[¶Ø옘uãÆª¥|FÖJ˜L&õƒ>Pƒ‚‚Æ3fØ=omäª –òÜsÏirÑèõzõý÷ß×ü ÷îÝ[Åÿ®îÞ½[sÛ/^ìûH§Ó©_}õ•³·Â'\DUUwïÞ­YëÌœ9SUUé> ÕììlõâÅ‹ê¥K—ÔÜÜ\µ¤¤¤Êù?þøcU§Ó]’[sP—b±XTƒÁ æä䨙™™jff¦š““£_øÙ³g;¤›4i¢¦¦¦zþ湉z?XQU•ñãdznݺˆ……qàÀ‚ƒƒÉÊÊ¢¸št":ŽÐÐP¢££‰ŒŒDQŒF#C‡e×®]ôêÕ‹;v„Éd"33“Ë—/c0¨ü(E!88˜Æc0èÑ£Y¤‡{üñÇyÃÞ©ZD½wßlÞ¼™­-ì Óé¸óÎ;ÉÏÏ'--âââ+‚AXXX,òòò8}ú4ÇÇ`0àïïÏC=„¢(<øàƒ‘ÍÑ£G9þnݺ]Y'röìYâââ°X,|ýõ×¼ôÒK„……q1óßmO'4ÖvþjUµ ËÜÍ-ú“‘‘ÁùÒdœŠ¢Ð±cG’’ϳë\$A¶—˜J i¦eôPÉoS\\Ì‚ QÍ^†ééé|ÿý÷¬^½úŠýi¥U«V=z”àê6ª%Ô[ñСCWF«ƒuëÖ±aúwïÎŒ3>|8-J“9s†ÌÌL  cÏ¡3„Äô²{~EÑQÜžS§ÏТy©©©¨ªJPP!!!ìIÌ&¨‰ýA„_@§Ò‚˜ŸOXXyyy=z”^é†X¾|9?ýô“Í ÔÔTRRRèh+ég- Þºo>\å3“ÉÄþýû™3gÓ¦M#¡4kkFF&“‰“'Ob6›¹§CQj¾uAaQœ<{™€€€+ÝkPP—/_¦ØOÛb¨ÀÈ$%‹6=}ú4………W\2óçÏçî»ïfÍš5v#…ŒF#Ç+ï×R˨·‚xôèQ›ß©ªÊ¹sç¸PšJÎê¸Þ·o&³ƒI{Gb0éÐétWº{EQ¸|9‹ÀPv+áFn¾lA¶·4!~ù–Öw¯2t7õV35ì3h-Zºʾ}ûHOKÃO§=›ž±fbè ¡88Žìƒ¢…мßhyäEü WÎUÔ¨'ÉŸÇ…¢š 7$Ó°ø!¦tôæ",ªŽB5Œ4sSÒüÚÓNÇÙ³gyæ™g캞l±aÃFåðqÞ¢Þ âæÍ›iÝtF#;vä‰'ž gÏžeéâT3:䪊µÔÚÑ› ˆNû†¦g¡³T•6ålëÇÉi4U‘ŽIÁŒ¢V=—b1’|3ÿúçÒ/ æÈ‘#´nÝÚác½E½ÄÌÌL:tèàPÄ3@ ŸŽ×îÿ7\?ŒÂ†}0ùEbÑ£¨&tæ"‚Š’‰ÈÞNTÆZJ2j<_AX.7G^dŒјu!€ŠÞRD€!•ˆì_htñô¹é¼ôƒÿؘãð®g×\s ¨;Y›¨·6bTTýû÷×]ž¾-ü˜ó -“¶ žñÇä~EõæBô¦|@»¤„æ!4ÿª¢ÇìŽY‚‚ŠÎ\ˆÞœ‡¢–:ÏýîØÏ÷úq6[ûhàºë®«ÕBõxÔ¬( 'Ntè?ÂM=š7”‚¢ñ7^&Ðpž€âtô¦< íQÍø³ ,N% ø~¦œ2!@¥YÃb¶Ò¸•œõ¼ŠÂ¤I“œj“7©·‚póÍ7Óкg²B¶1£sruW ð3Ò1ƱN¬sçÎ µµ+U-¢^ bLL 7U·ë¦ ‚ý!.—&µ…†ÁŽý î»ï¾ßEîÚßBóä“O¨qçÔ=H_¡`0i¯¿yóæÜu×]lû¨÷‚Ø¡Cf—ßÀÐ…F³‡¶ƒÖ‚ŠŽ ¹Ú ( O?ý´C¦‡/©ó£æóYçÙr| ?û‰¤Ì$2r3ðÓùÑ ¤m£ÛÒ%® £fŒbÙ×Ëȼh?T*¿.B+m¡„nÇdÖ“Y MƒbƒØ¡îàÛ×¾%§0“j":,šÖ[3¢Ó†uF‹¨n±vê¤QUUvžÜÉ»ßeuòj â   „ ÈÒ@J²YÁ´ÁdwЫ×Áw(ÜÒÇ7·,¯(œ Ùzº†È¡àu ;ÐAú¾à"pBO…2¾ùxõ0hÿŸÛ‘uN]8ÆÜoç²òÒJ,Ã,ÐÐâBËžjØÐý¡?(¼{³ê“‘ó©ôF z'‡‹ùvr/*À(à_€=…gŽ€²UaRƒIÌ›2nÍ»Ù9À³ÔÑh2òƺ7ðîVtZåA‹h­~Ü`ÐÊ~±ŸOBcñnBÇ¡TÈ*¬!è4à`pÐîé ¨¨¬êºŠA ñêÚW)1ùäâ¼£sssY¼x1;wî$oÖ¬Yn MÊÌËdæ‡3Yï¿õFUº_‡| 4®AfRõEý`Ç_ ·—Í+‹%9«ù×f;‘åƒë.K€NÀhDSÚ£”Õ # GòÅý_ФA÷4\#Ä}ûöqë­·VȞϒ%K0`€Kçÿ5åW¦/šNâÀD@Í7¼2iÈûпôød`:pªúC^sÇâÕîùR^Æ,4°ÿœ¨îÁÈu„—ûÌ,ü›Jßkb7ÄogÙìeôiÝǵF;€G»æääd¦NZEN:ÅÔ©S9uÊÆÓÖÀÖã[óþÇ'Â@œÂ/€¨(Ä­hcýü’½UèT“DÇÞ?§Ùè6GŸSQ‚€Û€@äz´LQ÷‡S“N1æÃ1l>ºÙù&;ˆGñ‰'ž %%Åæ÷©©©<öØcUòjaËñ-LútÓ3À™dW” auëÎ[+ñ¥ÿwA´Ž‰á¿ NÔé$fsËSRÙ™­Ÿ‘6Ö“(F-ÞŸx¸|ëe&6™ÿþŸ³Ív âÁƒ5…³ÿøãìٳǡsï:µ‹ÉŸN&ûŽlû#C[d‹ ˆ e‹FÀ§À³@ ð2ðPƒaáv(ôŠ]¯r9˜uÇ*-~ ÞþÑ|öÐS®y9 eÃ8È•ËÍKnfËñ-5—w â7ß|£)œÝh4²|ùrÍç=váÓ>™FÖ´,pÆž.D4áõ@g åõÀ£ÈFܬ€]°Ö Z±ÄÀ'¿˜¸[*=:D‹ßŒqàD:DÍÀz´ Å@îŒ\¦/žÎásU3c¸ âÏ?ÿ¬¹ìÖ­[5uÏyEyLÿ`:çÆžƒ6N4Ê |ƒ¸uu™ùQv·ú‚e5üÝ.8ѨªÂ³A|²«4H`)ð1ÐmÝlyôÀTà$ uo >1éLçr¾ç²ÏzD ÕtZHOO§°Ð¾õo4¹÷Ó{ù­Ûoâ¤v†õˆ¿p„ÇZ¨x·AâÿÁƒý ÇC¥ÙEþÌÿÅHjw3üø0(Ž "” `~Îk<¦í{”»?¹›b£¶äŽâ1A,(Ю*rssk\¾póB¾)þ†;Ù¨DLƹ«6SÕ9®À×=aÔ(HpójM³EaâÏÚW ðbJ”¯_‡6[¯:!îœeÈ´ŸÃje5ï¬ÇÉJíãA´¦ÝÕJ```•üÑåI8ŸÀ³›žE¬:×â|`-ât6ƒoeXŽ}Q0ô:XÒÚÙøìª$ðÚ¨rºYªwKéqN#Z‰Gœ÷ëÐÖh¨“T^Üú"SìMÙ8‡Û±¤¤„… V›ÚŠ¢ØLb¶˜¹ÿóûÉŸ 5¯‰¯Š ¬Ff´e‚«;‚w‚û@®DZÎéy¾$´2Ú.äl×\žÀ Qcù0(œTÈ}‹ïs{íVA,..föìÙÌ™3§Ú=Hl‘ššÊ¸qãHKK«òÝâm‹Ù²SÛ·:yˆ ºB ‚`Qàãx1ÙòëÕ@v±Â+Môü·o ª=½;ÑI¯A¢‘´Ðö5ÚÇ¢Ÿ¹XyEÜ&ˆF£‘G}”/¾øÂ)õ¯¿þÊ7ÞX!ÕÚ¥üK<ÿÃó¨TÇgMJ€€ñjäå†"ŒŸ¶u¬«.(Vøg¤ž‡) ôRPT3Ä‹°^û!êõ*ó6Î#-§ªâp· âÇ̇~è”ZÙ½{7=öØ•ä“ïm|s]ϳAÆ?##ìX§›TF´Tà~IDATÚµÒUß;P^ÙºêÌb…¿Fëxç:3EaîaÎÛ»•ŽtÏ5/Ã@z¯t毟隸IÏœ9Ãܹs]B+K—.åûï¿çbîEìZ Áήu¹IB0 "ˆ6ü´-  ûmü˜LØW¢pk'X4ÚL±!¤´-îỀ㴫ð°pßBÒs´ìáA|î¹çܶՖÉdâ©§žâ³­Ÿq±ãŪùZù ‰¦ qK³œD+‡µ£aQ¼˜uŠMpÌOEø1*¨˜µj8 `DÈ]ôD¦>µ¦\ …ìk²ùtÛ§n©Þå0°äädºvíêß°&E!lby¯æIx¿£\BF&ûÝÁv$¬ÊÙiÇáèïÚvÙ„_¼x±[…dÍIÞ'…`Ð÷ !@$lÌ "ÓàιÐ|`‚Ó ¿/ïF4‘£‘Á›‹n¢*tBfo. Sˆ5 §žfkâVFwíRÕ.uÍ‹Åá„‘š9vã¹.ÐËtþ:¤»ÏJhô¬)bÛ˜‘û[ƒ ºº¯Ç;µ‘#GzvóêZ¢¯Ÿ¡»h tß 5lDêq4 b‡ÎlvS†ÇQQÞxã zôp-‚×&µ@#*è³Ù½ ëô@› ˆ«ºi—wÑðC&>>Þ¥j¼b懇‡³dÉÏì¦^Œö„ä"6šg¸ßÙÐ Íœß!Î=‘ûkG#ÆÅÅåR5^ovíÚ•÷Þ{ÏnÒv§ÈC2ùÐbœ‰„­p Åq÷Ÿ×!r‘e½vîo¿~ý tÍ:öªãã–[náé§Ÿvo ­™”÷¡ ¶ùÍù¤¶öEfj|J&5¦Y™4i’ËÕxUEáùçŸçá‡vï‰/ãØb|7}Î}ù@Ë„ùðº‰õ´#ˆaaa\{­ëiy½î Öëõ¼þúëî,©”qî¢ñ9ϬÛòB}-ˆ—±+ˆãǧI×ÔødN" €… r÷Ýw»§›ÎÇî‚wO¢3C£ ÷åU/ôê¾Ð•°©ØDNÇ“O>é–ª|69È¢E‹xöÙg]À\¤æõ·Bg½Ù3q¹ Ä—²$aªøqãèÝÛ=Q}:K«×ëyá…øàƒ\Ë£“ $ãú8N X@ï¡zMøxÙÀy$"¾š=ÿ6lÈ›o¾é¶ >P…{íÛ·Ó·o_çNbD4¢ìDE•—'0†0Ïœ[g¨v]¬^¯ç•W^¡cÇŽn«Êç‚h¥W¯^lÙ²…^xÁ¹HŽTOìéŒPìe\døj½6@bö”C¯×3oÞ<î»ï>·VUkdªèùçŸçàÁƒüå/q,¢ã’¨È˨:Ènì™YÆà‚7KUGr?Ë­ˆŒŒdÁ‚<õÔSnOªàÅê´Ó¦MÞ|óMž~úiV®\É?þHBB¹¹¹DEE1lØ0ú÷ïÏO?ýÄ™3gHOOçÈÉ#²˜j žÂÚ!+Vìzw÷¢y@ªkS¸ÎsÉ僞ëÆ]ǵ×^ËwÞéWMu¸e]³¯ùöÛo™6m æ!ÉȽȌ×௹?+ÞŠp¸g7ä8»ßŒ+|¼MÕ¦?~ÜãÑöµªkv–¶mÛJW‘Œöt»n$±\r³ÿ&8ÑÑGBX€ä Ï€˜˜ÂÂ&ÐZDÊkX¥¸S‹ZúJ} èyÜôr #Ì%àç¹£º!ˆyé¿‹+Ñ)¥ZÎ:ÓRÛ…¤…™`ñ¬« n¬â3<·i²'ø= °”\DM5ËïèéZðêÖ.¡a ól—S7±Q+0ÿúf+FœŽªñ:f ¢è=;l¯‚Ñ]~× è@ñïäÖ—q½=>çü;¹èz£¶þ¾Æt™ Ñ=½¾‹ªS K Ú þð'¯TWKï‚“4j“Þ‚‹:¯ï×l¸¨ÀÈç Eï²Ï{΀.·»oÇqwarÂ`ÆGèÉûº%ˆ ]Þ ¿B¦R;ìEÉ£Óé6¸ö¯¿Óé`Ú{Ð``í±ÍÀE˜ô.´òΦáP`ü<èýgHW|«UdU^›é0ýÃê] apÏ*é'6™/1~0þmèw—W«®;Ñ7•±X`óë°ñYhTâý!F Sýÿ 7¼~5dq*ʆ¥³áô ˆR½ETˆì~~Ó"è9ÍË•×eA´rìGøî0žÅõžîT¤›µÄÁ ¯C¯[´‡Ø˜ðóÛ°ùeÉsiñ—fLˆ5¦-„f=¼PiUê¾ \‚M¯ÁŽùjïîHqåùAÏY0öˆlæÜ¹.†5OÃ鵩ÊÂ}wcFv0GÁȹ0ø໽>ê‡ Z¹|~~|J¦hœœJ™ÉLÐífþhÚÕ=í=µ~zNý‚‹$úÜç£w,ˆ[&_ÿ0èü„ú>³~ ¢•üL8².‡s¿€å²ØȃÖSU8-¥/"|Åд/t¿I¦ÁœÕ€öPU¸x~] ßÃÅC 7”µW_úRJ_j¹—¹´½Å¥¯À8h= zÍ€ö£ ÈÓ«¯´S?ÑŠªÊ áÜ8·RÂå$È9Å9PR¨àÑ ¶‚f=¡Y/hÑB{/ÌÚb†Ü4HÙçBêoy©P’Æ" × àFР9Dµ“¶¶ì ±]j•ð•çÿEC*!™ÞsIEND®B`‚phpreports-0.4.9/img/error.png0000755000175000017500000002515310442102126014764 0ustar fikefike‰PNG  IHDRz¡ «bKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÔ"€Ñ)› IDATxœíyxTÕÝÇ?w–Ìd’ɾBvm±"jËR´Õbߪ(õ}Qû¾u©[]k«RÑZ­Uªµua)RDŠKed D –$da’Lf½sÞ?NÈ:w’™LÐ~Ÿç>¢®®ÎïóŠ¢––Ƶ×^ËÈ‘#‰¥¢¢‚Í›7óùçŸãr¹íÿZ`>Òðòt$¤UÊïìÑétâÆo%%%Âçó‰ö¨¨¨‹/F£±Ë6,‹xì±Ç„Ífë𼪪âÀ⪫®Š¢:³—öÍpÐCÃ@FñÜsÏuJp{¼óÎ;Âl6wh#66V|úé§~Ÿ÷x<âž{î ”lp}_ ÜÙ†Ðhyà4‘Ü‚eË–µ!Êh4Š?üPóó^¯W,X° ÐY] è³Ñ;K”¡aÇ'‡p:¢ªªJŠ#GŽˆüü|QPP ÊÊÊDCCC›‚Ûí3fÌhmcÑ¢E>¯®®EEE­m;vL”””›Í&TU•••"###P²ÿDÊHgƒ0öð°¿›t:Ë—/gÊ”)Øl6„]Þk2™HMM%11NÇæÍ›™6mf³™½{÷2dÈœN'ÔÖÖvÛ–Á` 55•7Þxƒ|0ïå2“=Ïž@ê)ú;Ñ©@Ò_Ü%ôz= .ä¶ÛnC¯×£( QQQX­V"""P¯×‹Ýn§¡¡¯× H©|РA &L˜ÀàÁƒY¹r%555””” ª*‹«ÕŠÉdB¯×ãõzq8Ô××ãv»°ÛíÜqÇäååùýR \sÍ5Ìš5ëËAƒ]2a„ޒBþ†^àÚk¯½iÛ¶m ÕÕÕ]Þ£( ÷ÜsóçÏGQâããIOO'22²ÓûUU¥ººšŠŠ 8|ø0#FŒàòË/gذaTUUQZZŠ«ÕÊ€ˆŠŠBQ:Î ŸÏG]]ååå¼üòËÜyç…h³žaƒÓIMIÁétrìØ1œN'‹…œœbcc0`BRSS8p ä-¦¶Aª¾ñV3ç Í"&æ´ƒÊãñpüøq¨ªªâ–[n¡²²ÛÄÅ_Ìüùó™8q":®MÿöïßÿÚm·Ýv{(Çú1Ñ ,˜2þü-YYY ÈÁܽ{7ï½÷Û¶mÃëõ2pà@Þzë-bbbˆgèС­Ï+(dÓ¾Z„u&K>Õƒ£®”‘ULÿÎ8„äççãñxÈÏÏgàÀDGG“””DVV;rðu©BDü` ¼n®ºãŒàaòÄó[ßçõz9|ø0‡ƒ?üeË–qÍ5×0{öl²³³Û¬õõõ|üñǬ^½š£GBŒEj!C¿%xØd2=6uêTn¸áF^¯GAaa!ï¿ÿ>Æ cΜ9”••‘œœÌäÉ“8VPÄ'ûÝD§ ï´aÕëÂlÛÍœ«/âÔ©SâóùÐétDDD0jÔ(¶íÚÏᆠÌÖ¤NÛpÙkYÈÔ)ã[ÿ¶yóf"##QU·ÛÅbiýLAqq1+W®dݺuØl¶–ÜÀxà@ƬKèCÙx/ O¨ªšuìØ1>üðCvìØAdd$$99™K/½”Ñ£GðÙgŸ‘Àˆ#p»Ý¬ÝRˆ%õ¼.×é 8•XT[CeRWW׺%¤¥¥átºØ”/ˆJÈè² CD$'j¤[]X­Ñ­ýðx<ÄÇÇc4Jï¤ÛífçÎ<ÿüó¼ðÂ äææ¶7êƒÀŽ^Œ—_ôWaÌ´2%„ 77—ÜÜ\²²²˜={6×]wqqqx<JJJÈÊÊàðÑB”ØÎgò™ˆˆŒ!¯ØÁÄq:¬V+.— EQˆeÓW°¦ø—„£‘{(‡éi”––RWWGff&‡ƒþóŸ¬ZµŠ£Gv«¢çw÷a0 óKX4”t@qq1/¾ø"÷ß? Õ¯×Ë¡C‡ðz½œ¨i$"R›GÐæŠÀëõb2É`NN‡Á` Æ®qX…»‚‚úúzJJJZ—ä‚‚ž}öYŽ9âd€s 1ý•è!þnp:¥Ü"äTTT——‡'‘FoŒÀív·áõzq¹\¸Uímø„$zÇŽ466¶þ½E׈„8t¸¿íwJ¶¨/QQQF„¬]»–(“@ŸŸ§%„ÇŽÙl¦¦¦¦õo»wï&:BÛó&ƒ¼>þøcâã㨪ªÒ2“[Mˆ·Ñ³–躺:ŠŠŠ0 dgg——GqÁ!ìÕ…þß q*¹¹¹­D+ŠÂ¡C‡ðÔãu7ùmÂënbpŠ™>ø ÕhÒ¢âíÙeÓ·”h¿SÁãñðÙgŸ0iÒ¤VÕëÓO6R~`=ª§û ûÉ|b¶lÙBtt4̲9r$;¿ÚJé¾ ÝÏH!ðÕ짬ø6l ;;›ôôtœN'›7oÖú]ûýU½ŒL£éEEE̘1ƒ¤$©ë–––¢ª*§N–a?UArötúŽA˜¶ò4|Â×¹9\vÙe ^~ùeRRRHMM%ÂhdǦ…øôá(JÛù „꣛8U°…M›¾ÀçóÍÌ™3±X,¬^½º•|°!Ó|Ü<BN´^))‰aV+ÉÑÑ$µ\ I^/ªÚ©E(ø‰¿¶ív;6›K/½”ÌÌLÊËËñù|4Ô–Rvh ^—ÕëÁí¨§¦4£;VR˜³ÕëbÆŒDEEñõžÝ,}î·/àòiÓHMKÃb±°ÿ« œ,Øâó zÝ8ª©.Ì!oóÛø‚'ÊBǬY³HJJ¢¸¸˜Gy‡ÃÈ0UË¡u,ä–±¨(F_u{##ÛnN'bëV&VT°·“Ç2‘ÎyMX´h?ýéOÑét±}ûvÊËËQ„ + ²Bv ¤DB„%𯔠ÐeŽGo0yê0Ñÿ¼ O} (`;“ªÉ"tFDCI_ÓTH“[Åãƒ.(·ÃÁ3®äÑLšt‹…êêjî¸ãŽ?è0mF=j–ÞEÈ &Š‚°XÐY,mWŸ¡ë·W #=5EM¾öÚkTUUq÷Ýw“Mf¦´vYKbªÇ ¨xŒšÌiØMiõR“‰«ý‚ì#O`È>#PP¬ÃšŠÂa൦PcE£×F´§³z ½ÏžH"tÉ$™â5H/Ù¾}ûxä‘G(.Öüû<y„dè¿–1/ð5ð=-7û|>V­ZÅÎ;Yrû-\>m‰‰‰˜È‰v÷*‹¥1´²åÄÕ~"Ôv˜ ¶n £÷. rÀ¨I¹—1—¡£ýF>LŽbÒŽ¾ÍÖQ^Úã-6§§jE%ZÿB#Ñ-¨,/᢯͹æ—iL¿{ô¹x"’:w-&g1VÛ."’àn`ôÔQô"éeoÒh=ŸFëX<ɨú( ÞS˜œåXm»°4FQÝüx,ü#V ø»:‘þ!E%dNÕ“ .SF€QC|ͧÄ×|ÚëNè½ ÄÖm!¶nK×7) K€ÛÆÂ?޼AæY‡#:Íæº[}DU0´“' ^Èö`þP :à#8þì÷ÁØ3ÿÞ]äûOFƒ®,§˜’F=™P¿#“êCŠ€¤îIÊ˸\ëƒ0:¢Ho‰#D6Qa]뎧 Á!̓€×€ÐqÖX#àðO!máó²—BêKPåߨÖ'Ò®ß^”:4Ïèi–ü{ ÌH%À±´wùIZ ͨH½+x“¶d[e ´cA†æÀ,+è’A#Ñ90P•épQ8‹uè‘ÉW ÃB—rÚ (ò '|*ÔhϪ²‡®7má—覃3`TØRÏ€i]Œ\bž@“œˆ„gVû ®)€ýÙ æaBa*r{jD¦²í‹¿FtIt³bwÖ ‚¬þ”É­CV…¹¹ŒßØ\PÝIa$ºÒª‘;¸ydòc¢Ñc\€ eT³­Èúu€‡å½ï^§D7“<Íï ‚ÄèÎn 3dÊ #]@ç!Ý¡…öT‚ÏÑ:à%`F§Ú†/ég._1—Cáäò–ñ¼=:n‡9&xwÄEõ¦õ>@40`–— § …-Äh€—¶CNU7÷(œNHç/tHÃïXà|âp1“*f0–Ã\@a§ž hCt(·ÃmføÓ0°˜{ÖfŸÃ‚ŒÅI¨‡ø,0¦÷}Ô¸ÿ ¨înÞÍ~$yòWÚtkAF“ 'ÐH°•½{¹Z‰n6„< ¿ g[)3«Bq>˜³ÀÔy8vhà…#ðÌðvµt_¼Œìh<²éZ¤ìM×r…‚Ü›&`ÀÅ¥”òÎg#{i¤‹z€ˆ~ ÷ ]¶‹v‡ Ú %ûÀ 怴ô^ þølìÊqu5ð:m·”Hdï6à8pÝ ‘úæ{bÄ1®c _°—J­]ÔçÈW¾ž·¥¿Æi…°z¡t(V°d†þ®Jøù'g,Ûä¨zªÁót. õ÷¢ì 4‹ò˜Íy|Á”kÙ·u ¬I…g…ßÞ4˜€a^¨}ª> ñËœ°­Öžñ·4d´ß¿¡{-Àü©E¯E¾ð‡áÀÏHÇÊz`’–nê 0}ý; «'0>°íñ‹lðRû•„Œx»mk@’} ømî¯làf’°°Š…ŒðwûÙ¾Rw‹9'ì,€5ÍÿOFšê~MàÑxFdaª#È - ÜÀ@Œüƒ…$wwë7šèPC­…G¶7øR°º¹TkÏ8 3p#2ä¢Tã3£€k…ÂrÒ¥FüÍ'º¥jw°ÑŸ»`ã]ÀV¤¶%ÚHGψ©zÍÞê5>s10‰Àƒ,ìü–o<уŒš&|Ðdƒÿý/ðþ„Žé€zzN4È%ùb¤ã]K;:àZ`¿¾ÓÕ-ßh|õÐ;Kq;ÔÀÃÞ®ôôÞÌè\„4•jÍì1ó1Áë,$¾³.}£Qg†ù×CMÁɃ¨‡õ©ðÜÅÝÜ ¢õÀlàS¤4®ÀTF÷·_¿ñDìOy³ÁVGïȶÃ>üt&¸»“ªƒA4ÈèŠË€5h—3¦),¦]r}@D«:öèhê©OJ¢1&·ÉÔÚ¯Nç÷j—ÉD}B¶ÄD‘‘~UQ:¶E`2Öçƒ`ÖठzäÖo€Ã*\7*üùm=¯îþ¤¯:_ãýfàj,èø5 OkñšÌÚ> ò{ßCÏ=˜ÇŒA-‹´94VUáxâ W¯¦êõ׉Òu»ýða.^ŒÑã¡)&†ºE‹0/X€9#t:\UUÔ­[‡åw¿#®ò´·äç?'jΜ¶y½¨55¨ŸNÒ›obÒPRù‹løÞðÞj8·)Dùû©  vDÃÜ9P¢¥˜‚ƒàùÄuÀtà#¤EL‹~~.ÁLŠ™HsmMDWNœHÒÚµøT•š_D9|X~œŒnâD|±Ò±ª––¶úÏ,_Lì¨QÔíßsçN|%%àóÑGý»ï2àÊ+©ÏÍÅöè£(.Æ H¿÷^l3gR;}: ¥¥Àå?.„¢ìõ×;|®‚hêä¹òW^BQ¾lY‡ÏJzH!D}~¾¨Ž‹ký»ÝlUëÖ !„8ñî»Â­(ÂâÄóÏ˶žzªõ^§¢ˆ²§žBQ»oŸp(J‡÷8A¼v ‚êίsòxQô(B}á~ÑôB<€8ñ0â­?#Æäuý|—×V÷à¹î®<÷#(×xÿIÿG ÷è–…Þ4a'Ï;ß{­ŽÀV)‡ÉDÔÂ…4,[Fâ©Ó"¥ÅéÄûüóøT•„3°evíz2 ’› €>2²Gðù‰pç÷aòlXd‡Å[aîN¸Ø£¾7Ï‚}šjý·C#gD£ )@ÚÍ£ p‘ÀM h«Wã­¯'ñüó‰Ù¶Ê5k(Ÿ?{BBÀ>¯úÔTb›KQ([·vøÜ”›‹§±‘«ϨQ]¶ãˆŠB™;€¦={ˆÔ^/¤ â‹áW3á–ßÃÿ| w-ƒK~úí=jRæv[¦¶‡¸ifÕú«˜ÍB"4ÍèÔœª¦M£ö“O0šL¤ÏœÉ€wßÅ““CÙ}÷á´j?¸Í—€N¯Ç§ªèlMV— oS³XœÔ6LÄðÝïrâ™g8ñÒK4}ù%isæà¨¬„'žè‘ž¨óÀ¢;a\©´Oœ‹üwŽ~µÞº@³¢|HK\§Å³z‰t¤T]¨ñþ8 ƒÑÀpMã£ìÚEäÕWS9y2'^xGy9qÙÙ xòIj^yÕ¨MŸPE§CDt”n„^Ò’8ÝÔVŠ>ó÷¿iÊÔêjN<ù$S¦Ú¼„ŠóVôíR¾9s ÌÈLoÞ“^"°Ì(Góý¡ˆªT¦Ñ/5Þ¯†¢&4"U•ôÝ»I½ç#FPñ›ß ( É×_OÝ AšÚˆ8qgc#Š¢ Ftt£ºÓÓ‰°ZåŒ/,lóYÝ›o9~fUŤªè…èy°„€yÏÃeUÝ1g&ÙáûF{u‘H×a¨`D’í¿þ»D" c˜_¢PpÍ5œ˜;—“YY4ÄÄ`Œ¤&5ßí·£3h,)ÁRPà¯)@þHt?ŽËf#å?àÄ/~A]Bõqq”ýèG$Þ}7BU©øa¬Ÿ+¥ ™ù0ë]©žúÃ`àÊMyHÃÍ^äÙñ~ã=z‰ó€}ï54-0‘S¦vß}¨n7N› ÕëÅK¼ÙŒíÐ!šn½•ôú¶ÎSáóáóù¾ŽFß”={(¿þzbþøG2ž~ç}÷áSUÄÇ㪬¤ô®»H_½út[Bȶz(Y·Çì—`¬CÛêjÆ7ÀÄ¿Á¦'é>4hR õ¡ÂÙÈŒëñ_zOôÊ>]<–8™’‚wôhÈÌ„äd©RUW£:DTn.VgÇÂʬ,HJB©®&¥‹.õ öK.sΑm;†iëVâm¶6ãY•™‰HNF©¬$¥¬ÌOoOüu ܶæôßLMðÎh¸®Q»9ºX–¿^b`7/{ø}s>üdÖÂD?÷^à3M3:¹ª ªºË5éˆÔâbðS¡'¦©‰˜aãÆnïK))’’€ÞßƯ‡Á 2ècr9¤¬Ê;;¹¡¥âÊ9ô É ·‡½ø'ºðqà[á¦lE ~?p[†êƒ+WÐyý ¯UѦ÷¶ƒ I¢?ÕOÊÿ:[“2´ÃT"kó}ñ6ºŽ ë™ÀUÇ`Å:pT#­N*ò´Ì£È:‡ZÁ€¹,Ùèú—[äq4.Ýg5j€ÕH=êZ°WƒgWà͘€M0r,ìÈ`{Røú)}ŸÁ©CîÑ¥tN´X ³œõ4}ó‰,:ýߣ㡚;B`° H­AÛ0(¢]Ý&dàà àŸÀ©ì}»öh`çUß]ýœ®áìý©ôC*òW{&ª }o#CÓ€¨oÑ. ¼ò4ìÒ>æŠÍ79T=ë¬H—hs "3Eþ ì¤%Ö* ýÍ_º;ÁæÀ_ö€óU)S¥ÑýÒæö*ð·ÅPÓŸŽB.M¯ U­CÀaÚ›k`Ü·’h¡ƒ²árJã“„4 G#IpRÞ90V. S‡»‚©B¼F‹¾ÜÆ|+‰Î<·<-=~V¤g±š–ÚO§ÇË„$ `Í“Î5?C‡»Crê>¼ø\ƒ •õªí¤¨³I^E»Ãèô^X¼.«9m&¶ 7²¬nÚ› àŽ'!Ò”‘ÜG0£EO×ùàŠB8Rç÷Þ³>ärûÎ,xæ7m?»ú ¸bW€µ)‘«äxüäQ0†Æ©Ö3Hï”?ÄèÆÃ~¦ÁÞ®Oi>{àC.¿¯Þ ¿zšÎÒ‹¯„ýDpùNøÎÊ^w3xˆ@Ñã¡HÀå¥ðæáëá·ÿ Oÿ<í–´«ß€ñµ=?2NF ¸þ`ðô²³Á‚6¢Í­ZÅx¨0«V”rö‘íá±'àÕÿ_»Œk-\ó¶¶`ƒî`.<çjÛ 5Œh!º±ú8^º²oª†× NžX_À ì„ÿ[ïþ D'Á¯…1UÁ9r00ý/Ah(ð¢%x±¾ƒ`¼·E§àÉPCzLy`vÅÃâ·aý\ºŒ™ºªgöíÎ \¸Y1„n´Ä³u$`¼\¹n€{;dÇ«õ6`{Üñl¿¬ëûËaÂWÁ µÖƒNÁˆÝAj°7p#Ý£¨KËßx¹r¿Ø·…N‚…‹Zà‹!pë*Øï'ñlܧ0ÐÜ[©Æô‡ã']h™Ñû»uj4Ï쿹`öQ¨í‰Ç'ØH³äú àgkฆˆËQ_IÕ(˜ˆ²µ†Ü†.´Ìè¯ýz¯ÆËkƒ®9åZ å„ë¶j*,~Nj¨â«óÁ9»ƒŸ d“–¶°¢>WÈÑlëÛs`ÚqX›ÃÂqL­X1 û}[CHwˆ¯€¬òàGù€´“eƒúpAáEFÐt_ˆ'(È©1åÀÔ“0PvÀÐÁ/»Ó¹u Lšíô·víïtàJmïwZ`ãlðÐëØ“éX¬MÌjGÂŽôÄt¯¯Ü{¯ÆK‡ØëÍÿ•§CtãÐ)`í3vššà9à¹Y 5DH*K¬? éS8¥ÔF¤TÚõ÷ó #ÇzJTü©ÇO_BHIH. ]Üžˆ ¨=‡·h}´7D‡Ö%äÔµ‹`¿±÷³:xïÂdûé]–_B4—¥í Ñ6zêÌЂ zh¬ýA‹ Ó3Ø€-£aÓ¼`õ*Ô#ÍQ§ëöU£½¬\¯ˆv2{Aßý…þ~?lMé™îvaù#2™¾Ïñ ²úÑ鼯upÈSoˆÀ›„"Î?yærq2ž~6Ev~Š@ª®Ëï‚=Ó‚ß/¿¨@ú¡Ž´ùëŠ@šèí>[\€,C(ÈãxÏ÷wcÏp2J³!s#¤ªÚ27\¯= ¾¾6y dU¥Õœ¹QV#-bší}½%Ú‡\´›Œ˜ ìIDAT¾¯!µ °¸‹–Ñ) û/„˜­Ý ã¡:ˆ–2boÏ„^w°N¾ ¿»9Ó]ô>ðA ÍCrn@Vݺ Y#¾gзº3P9>ŸunðÕ%C×|ÕÛ°|!¼ò|˜HnDj}Ä™»±Šô5$WÓ' <ØÜ‰ÀŽ÷²O!Ô C¤ø ˜¸ÎÿFìƒÔP’ ¯=-õåÎ’öBœ·@Ö?¯ä¦ ÅW ܉t<¦¡e~f#©·jíÜ/t>PT@ s<Ø>¤7ïcÎwrs{+ÐæBù[5!kÑO@.é‰HWE5òœ’›Ûôb 2ÚdFˆ{u6  )®¤½.X†¬!pvT(³.¤{|o'Ÿ¥ß§Å„* RBó'†°Wý¤ðµÎþeô¬èaØÊÆæO>ö!¯N`4¡9N¨¿Ã ü x3-`-(@Æåõ(„"œ;â~ä>~:ÿ̓,¹ìFV” Å‘Bý>¤îò..€{è"LH ÂI´ ©šÍjóW;Òyì@Îìp˜ûiÐ|yR]G[ãnd<^s7Ã,ã²¥ÒÖ…Q |kDŠmßd²}œ&ù :s¯¹‘‚ëÑÞ¼&ÜD ärô#Ú[#ë‘3ÛŽ‰LbZÜ};÷ÿ9Șí^£¿­"¯ÒÙ"íBÆ:¶ÌýAôíA%Á‚@J%B&/éöÎÇ€¿ëÕý…h€SHãÊ<:³•{‘qdEHÿl*g×RnGÎà·5º?Fì¤2h¾þþD4Èy[‹ ;èèÞh)I”$\EîÝáÊhÔçõ*Ò¤¹ ;î.`.AÎ$êoDƒ aGÖMïN¤èxó¿z¤5½¿•™?†´r½ŒS÷_0›à†¡ýW¬1è^Q?ó{g$ÒŠ6)·_Hx÷o4ånDJ»[ŸÓxŽ‹Ò™¾~6_*Kƒ_s·_-–  E­Ý‚îÚĹÚ+s¬ý"IøyHOØD¤ƒ¤¯¾¡é7ÞŠ”¤óóSCß3â`ý p^.¼|ŠT¼Ö*K5îý†h±„ÑÀý™M4ÑDƒ[»VÀk”L6#*#‘dŸ G&öûÛ6!ËKB’»© Õ ¹vf¬¹ Æe4?ãDZíâãUàeiïSÇÂN´XB,ðFn% Qm{åõÁ3á׃'è{ÒžÔ½‡#ÉÏFÎô$äž®eRþµ#—ár$¡ùH9¡¹\hÖ—+ÿ wV΋´Ú(Dððž²´çRx؈òh¡ï¢ã bJ\÷½Y±ný;œêi7 §Ãâ>³ äLDJîææUäÌj¹ê‘DV"ƒÉN! ¯¡G ¢Àœóáõ!Ö_±Pƒ ‰UÀÊR?ŠYWïìÉC½Eó^|+Fž'…(­êÑÎbøÉÛp°2Ð! n9eÆxÆ¿*r€[J$»{pRy#ôpÿ•ðÀtˆÐª%ä­–<ó•¥í¢È4 Ï‰nžÉ÷`æ7¤bTÁ³9à¡uðʹ¬ŸM¯þ.ÚÚ€*Êð1Ø«,Õþh8Φ¼ 3¿#-p’b#áŹðÑ"º\Π"Âw¶ßÛ ’An?© DÇZ¤´¡}:£ÅÆcàs ãF]üa3<ÿ9Ôö‡cÚA§À•#á‘«áâÁAl¸8ÉW(Kµ‰€}F´X‚…ÏHer° NÔKÉüÏÛÀÞÎ…Ð)0>žš —}(ÖÍ“¸xVËÞ—DßD4o‘ºwÖÂÛ௻ °¦ït²DÀ•çÀ­—È™l寍¥œDe¬²´“ŠcíÐ'D‹%((ä21}ažltÁ¿ÁëÛ`ÓÑÐÎr8'惛&°¾”ê€:P–ò´¿[ûŠèñ˜ÙÅ€>– Ô9`ó1Xw@’_QnoÏg»^#\4fŒ†«GIrápy€Rö!§,í¾˜C_ù{¦cé{UNQ Á³ÆÈË' ¤WA^ì?5RektÓ .è…,Nk‰€3¤Z¥jtn:ŒJ…¡IÝ\£R÷ƒ‹øIºë+¢ÇõŸ±NìyMo—Ñ-¸¼àn} ˜†€¡?:qÛ#p1Ž~Bô€~ç+nE³ÌQHÃÄÙ@2´08Àßm}e0±„Å4ÓS„ÝÕä¸úUXûjømg͉¦pöœ¾ -}õ{Y_]ìêº!ƒé"<[ÎU–ãê·h_½3$E³C' °÷>d¾ ^:KËk‡¾"z=M=Oë3ÀAð\@õ©Ây¤ðf4öë+¢‹pói¿¼&ÀÃGÀK4Rßï÷êz@ð-Á„}Bt³ÑýN¡öÛ½O§p!‹JœÄ˃Zä;ØpBca¹¾Tz6ãä=ÿòa˜`\¼ìhþa>‡¢`ˆ*PŠàe©¶R}Ft³-ö^j9Öï3PG>ðË–ePYJ>î¤ W¿[Âë'oÿÐúHŸš1”¥T ø!UØúT모jŽÅª;ó#e)áæA*ñõ²m€wèßçö*e)»ñr=•œ ûÌv•œDeò¤ŠÎð¥_HNJ u@-›ÌÕºd· \Q ¢ð.‰ ÃÚÇ=È™QÇÁæAËëöö%Íç‡YJ2Qôõy”*PÀÎ{Àm=Éà«UW,!x‘Hæ’€®O<\. '~¡,íæÏvK˜ŒÂ«Ä0†8BïøȤZlxyxIYÚ3{DØÍ÷b z`6 OÍb M’œxoç‚_ë{’ù –ü7þ—b°Âí€ “ÕÀ¯€ƒ„÷¶G؉nXBpðs"ƒ=‘ônU¤¤{€ß#S[zeyoÞzÒ€ÿFÇB¢H'™åÑS©G íÖv ‘&<¬ž¶#»²ßݱ#27z:¦ÁPÌèˆ@Îô–:ËJó%8Õ’aá\¨¸8‚`²N.{~ú‹J‘¥Ì÷;€ãZ㞃ÐW5ÞÇ"³´/@a( (Ä7÷W84 (GP„”ö÷"ËpUô&‘®;ü?“ý‚FÛÍIEND®B`‚phpreports-0.4.9/img/penguin.png0000755000175000017500000000744310442102126015302 0ustar fikefike‰PNG  IHDR00Wù‡bKGD ‡Å~K pHYs  ÒÝ~ütIMEÓ6óÔ*8°IDATxœÕšyl]ezÆg¹›·ØdÁ ¦!$ØI`–a”,Ј¨D+HQ±©ˆeJÕÂ0E*S•Fü‘¡C‚HÕ²*D¡h&™*eœD@\±lcÇq®}÷{–ï,oÿ¸÷\nŒ³Á¨í|Ò‘î9>>÷yÞ÷y·ï\MDøm^úÿ5€ïºÌßÄCžçáº.žçáû>Åb‘={öÐÓÓ^~ùåï\pÁ½eË–Ï«DÎÌ·"ðÜsÏÝ."[ ÃhijjbæÌ™Äb1r¹¹\Ž Ž# ”Âq\×%úúúؾ};cëÖ­{ò¥—^z°ÏÔgL`ãÆ®”ú»¦¦&ãâ‹/æ’K.aÆŒhš†RŠ/¾ø‚îîn&''Ñ4­&#Çq°,‹r¹ŒeYˆ‡âã?&™LúwÞyçßlݺõg@ñLHœ§Ÿ~ú˲~–J¥X½z5×\sÍ´÷MNNòæ›o’N§ŠÅ"žçÑÜÜLkk+žç1<<ÌÐÐÝÝÝ LÓ”xàÉçŸ~3P8]§M`Ó¦MÔÓÓó/íííæÜ¹s¹ï¾ûH¥R„axœþ£Õ××Çk¯½†eY´··³zõj/^L*•BD°m›Ï>ûŒM›6ñÆo0gΜܚ5kn{ýõ×wåÓŠ 9åñÄO¬Z»vmîÁ”‡zH>øàQJ‰çyâû¾ø¾/AHýÚ²e‹lÚ´IlÛ®] ÃP‚ ÏóDD$—Ëɽ÷Þ+€²dÉ’¾»îºk<l§,d/¼ðÂŒ÷Þ{ïç---3”Rtttà8¾ïãû>A"‚RŠýû÷ÓÓÓÃÂ… ¹úê«I&“µÌäû>J)òù<º®óØc±hÑ"<Øéûþ“ÀLMÓNY§NI`çÎæóù S©–eáû>†aÔ2K”ƒ Cº»»q]—;vpàÀúúúظq#™L¨¤Ø(;yžG±X$³|ùr Ãàí·ß^ÿè£þЬMÕæ”uR†Ï>ûìÙ»vízpæÌ™(¥Ãx<ŽeYÄãqt]¯¦iŸ|ò ø¾O"‘ CŽ9Âúõë™1cžçJ©Zv²m»C¦ibYVìðáÃ?þ °÷[y §§çŽ£GÎK&“5‹—ËeÆÇÇki1Êí¶m¤ÓiÊå2†aÐÑÑÁÍ7ß̼yó°, ¥®ëâºníétšþþþÚ÷666²wïÞ+î¿ÿþï'ó =ðÔSOÅ>þøãÛ#]»®[Ëë`Ö¬Yˆ¦ibš&†a ”ÇW¬Â4Û0 ƒ={öÐÚz.·ÿ`¶ãSv\B_á)·öLÏóxÿý÷9pຮ£iñxœR©SJ­~ ”uF†††¾766v‰¦iäóyZZZjnþðÃéì줱±±&ÓŒ‹A{û^Ö¯7Ðuƒ5kfáûyBµ™¸ò0³ŠcÞJmˆO¹\æí·ßfóæÍA€išµ”Ç9tèЕíýýýé3&011±¦\.Ç4Mcrr’Ù³gc¦i2<?ç¸6¢¾»®K†d³Y~øa8묳ˆÅbxžG©Tbbb`xø7êæ½üOêÁC¥ì×¼ñƹá†Èçó5@Q Qo•0 +×B-tk®×Ol¾ïcY ÜrË-˜¦‰®ë„aX3 iš³€R)n:€®iZBÓ´~z²øH&“Ü}÷ݵ^¦L(9•HdŒú{ë{¢hÔ\ºt)µ‰N×uD¤v^ æ¿þ hÑ4ÍЗ€€ ªóo¸úê«Y²d årù¤€O>}Ž$u¦ŽãÐØØÈe—]F5ijš&š¦9@±*£Q`0H˜ÀFàŸó€Ù@c2™œ©iÚŸ(¥’ˆ5kÖÔZ‰È­AÔbDÓ4Â0¬¹_Dj×"ðõƒ~ÔÉFGÔÜuuu±oß>‰J)®ºêªÏz{{7æ•Rà6 º ôGCTê‚î8ŽyöÙg¯J§Ó]mmm\tÑEX–…a50õÝh4™ÕŽ‹•zðõçQ0;ŽCkk+óæÍ#ŸÏã8mmm£ýýý‡¡ªÂê¡×¤R2@®ÊJô†††OE¤KDX¸p!---(¥j-räæz©Ôg¡HFõ¢ÏSg¥Tí\Ó4æÌ™C6›´?\Åv(Te]“ºMz"⋈'"JDœöööÝÑM .Ä0Œã€ÔË¢þ|êµzà‘æë%T/¥ès´Ë¡ëº?11ÑOe&PÑXZ£'h~•H$\Çqííí5pÑDfš&¾ï£ëz- #ùÔg¯p4ÄÔë¾x4#xžG<G)E[[ÛÈîÝ»¿ÊUíc°™ëíí=0gΜn¨ ‘õê Ñt–î¾é¬i>:"®ë"" æÏŸ¿7“Éd¿l6ëwtt¼`š¦Çétj5h”§Z9·mû8"¶m“ÏçI¥R¹¾¾¾@°N´ÅrB""GŽy¯½½}_4.Öƒ›jýz­G`£ÔX/©#eý¶£çy8ŽÃØØ]]]¿þ裆IÀ9ΓõƒƒƒÖÊ•+7zž÷¦çyF¤÷8|]a£t:µÕË&:U:x×u™œœ$‹åGFF~¤¼ˆL+ŸS‘PÓ´_¬X±â]˲þ ¡¡¡¸õýŠçy†1õ Ã𤚷mû8O”J%FGGY¼xñ¿¿ûî»_T X'Ãx:/8TKKËO|ß¿ÜuÝs¢!GD¾Ñ…Â×ÓUÔÃÔ©HãSeãº.–eqôèQ,XðÉ‹/¾ø0dNfýÓ"PõBÿË/¿ügJ©2M3‹¬ _±h‡""àû>¶mׂµž@O®ë’Éd‘ÜöíÛÿѶíÑ*ûTøN{sWÓ´† þøžë¯¿þYÃ0ã¾ïáû^-F£`"‘ ‹Õâ! Ìh[ݶí*ø *1E¡P¤X,y‡õoéí=ø.•ö戈L»ñm è@ãÚµ«þtݺõ?ÖôXK¡`S,YCÌÔH&b¤R©Úì¬ë:žçaÛ6år™RÙ¢T*c•m@ǦXÈ•ûû½>4ôÕ;À0,"åÓÂu2aøy[(î÷ó¹=ËvïÚõ;ž*šÎ='qqC¼avfÂàȨơAørÔD…IΚÑDSS#©T Ã0‚ÇqÈl,«ÀY­!]]çrî¹sinŠ£i%,k(7<øÑ€&#™ÉcNßøp°ÿÊó»oýñ¡Ãœâeà´B÷Ò¸çŸwŸa^û#] Ï×8qÀÉ€}ò½`9ˆ•Ä.Ä3ùÕ§Iö|ÕLCC ˜¦‰ˆP*»ÌnËsÃ5Šï]ºŠ†¶%T6BÀ)€ŒAñCÂñÿƇ‘ªøÕAµó³>ûÙGþcèCNðmÚ Vy힘‘û¹¦„ÐL 1A<®Mh• Ò~ÖÇ/8–G›2øÃ6 w4Ç{ƒÍÌhn fš(_hM:Üq}Žù³ Ž}›ÍƒžMGQ|+ƒ3ž¦<¢( ™A¯ùØ€÷ûêX¸²«1ym_Ùù’i Ú´JC2Þ/Ø…”„1$4O'$(ù„"ÄÍ€Ê8Øù§*e"Ù¾7‘ˆeôJZõc¦!~ «ÑO¬Kå³cçÆ0ºÑ€¦'Ð0¼€@9¨²…SP”2MûŒõ9æQ"È¥]¿86i%¤iZüõŸ.¼qq[òþ9)órÝ×Bİ~^p3‚› ±òÙbà÷–Ê»ý`Ç¿í¦Ò¿T"µ²äÊ®sÚ6t?˜ŸjZÕ(úÙ¾„„ |°!_ (”²^9¦ù{·rï[ês _D²§K@€9TÆÌ檷Nö²! ²‹_default["SUM"] = 0; $this->_default["COUNT"] = "null"; $this->_default["MIN"] = "null"; $this->_default["MAX"] = "null"; // first step - find what columns we have, let's make a query that returns nothing but the columns $stmt = PHPReportsDBI::db_query($this->_con,"select * from (".$this->_sql.") crosstab_table where 1=2"); $cols = Array(); for($i=1; $i<=PHPReportsDBI::db_colnum($stmt); $i++) array_push($cols,PHPReportsDBI::db_columnName($stmt,$i)); PHPReportsDBI::db_free($stmt); // find a delimiter $deli = isNumericType($cols[$this->_group_key]) ? "" : "'"; // now we find the colums to work with the aggregated values - those are the values we'll create the columns $cagr = array_diff(array_values($cols),array_merge($this->_group_desc,Array($this->_group_key))); // ok, now we know that columns to work with, we need to know the values of the group key $stmt = PHPReportsDBI::db_query($this->_con,"select distinct ".$this->_group_key." from (".$this->_sql.") crosstab_table order by ".$this->_group_key); $keys = Array(); while($row=PHPReportsDBI::db_fetch($stmt)) array_push($keys,$row[$this->_group_key]); PHPReportsDBI::db_free($stmt); // create the sql query // check if there is another default operation other than SUM $oper = "SUM"; if($this->_options["DEFAULT_OPERATION"]) $oper = strtoupper($this->_options["DEFAULT_OPERATION"]); // check if there is an order $order = ""; if($this->_options["ORDER"]) $order = "order by ".$this->_options["ORDER"]; // first the description columns $sql = ""; foreach($this->_group_desc as $col) $sql .= $col.","; $group = substr($sql,0,strlen($str)-1); $sql = "select ".$sql; $coln = Array(); // store the used column names $apcn = $this->_options["APPEND_COLUMNS_NAMES"]; // then the aggregated values foreach($keys as $key){ // here the key to compare foreach($cagr as $col){ // here the column to manipulate $op = $oper; // default operation // if there is a customized function for this column ... if($this->_options["COLUMNS_FUNCTIONS"][$col]) $op = $this->_options["COLUMNS_FUNCTIONS"][$col]; // check the default value of the aggregation function - convert to uppercase because they're uppercase there if(!array_key_exists(strtoupper($op),$this->_default)){ print "THERE IS NO DEFAULT VALUE FOR $op!"; return; } $defv = $this->_default[strtoupper($op)]; // check if there is some alias to the function - some translation, for example $alias= $this->_options["FUNCTIONS_ALIASES"][$op] ? $this->_options["FUNCTIONS_ALIASES"][$op] : $op; // create the column name $name = strtoupper($alias)."_".strtoupper($key).($apcn?"_$col":""); // check if there is already a column name like this, if so create a new // one based on how many times it was repeated. if($coln[$name]){ $coln[$name] = $coln[$name]+1; $name = strtoupper($alias)."_".$coln[$name]."_".strtoupper($key).($apcn?"_$col":""); }else $coln[$name] = 1; $sql .= "$op(case when ".$this->_group_key."=$deli$key$deli then $col else $defv end) as $name,"; } } $sql = substr($sql,0,strlen($sql)-1)." from (".$this->_sql.") crosstab_table group by $group $order"; if($this->_options["SHOW_SQL"]) print $sql; return $sql; } } ?> phpreports-0.4.9/INSTALL0000755000175000017500000000024110442102126013371 0ustar fikefikeYou can find a really good tutorial on how to install and configure PHPReports on http://sourceforge.net/project/showfiles.php?group_id=55870&package_id=116673 phpreports-0.4.9/outmenu.php0000755000175000017500000000305210442102126014550 0ustar fikefikesetUser("taq"); $oRpt->setPassword("******"); $oRpt->setXML("sales.xml"); $oRpt->setXMLOutputFile($sXML); $oOut = $oRpt->createOutputPlugin("default"); $oOut->setClean(false); $oOut->setOutput("/dev/null"); $oRpt->setOutputPlugin($oOut); $oRpt->run(); ?> PHPReports exchanging formats

$sBase to

"; print "default html
"; print "page to page
"; print "text file
"; print "bookmarks file
"; ?>

phpreports-0.4.9/output/0000755000175000017500000000000010630304366013711 5ustar fikefikephpreports-0.4.9/output/csv/0000755000175000017500000000000010442102127014474 5ustar fikefikephpreports-0.4.9/output/csv/csv.xsl0000755000175000017500000000251310442102126016022 0ustar fikefike "" , phpreports-0.4.9/output/csv/PHPReportOutput.php0000755000175000017500000000330510442102126020254 0ustar fikefike_bJump is true, it will print the report on the screen. * * * *********************************************************************************/ class PHPReportOutput extends PHPReportOutputObject { function run() { $sPath = getPHPReportsFilePath(); $sTmp = getPHPReportsTmpPath(); $sXSLT = $sPath."/output/csv/csv.xsl"; $sXML = $this->getInput(); // create a new filename if its empty if(is_null($this->getOutput())){ $sOut = tempnam($sTmp,"csv"); unlink($sOut); $sOut .= ".csv"; }else $sOut = $this->getOutput(); // XSLT processor $oProcFactory = new XSLTProcessorFactory(); $oProc = $oProcFactory->get(); $oProc->setXML($sXML); $oProc->setXSLT($sXSLT); $oProc->setOutput($sOut); $oProc->setParms(array("body"=>($this->getBody()?"true":"false"))); $sRst = $oProc->run(); $fHand = fopen($sOut,"rb"); $sText = fread($fHand,filesize($sOut)); fclose($fHand); if(strpos($sText,chr(160))) { $sText = str_replace(chr(160)," ",$sText); $fHand = fopen($sOut,"wb"); fwrite($fHand,$sText); fclose($fHand); } // if needs to jump to show the file, show it if($this->isJumping()) print $sText; // check if needs to clean the XML data file if($this->isCleaning()) unlink($sXML); } } ?> phpreports-0.4.9/output/tsv/0000755000175000017500000000000010442102127014515 5ustar fikefikephpreports-0.4.9/output/tsv/tsv.xsl0000755000175000017500000000241010442102126016060 0ustar fikefike " "__tab__ phpreports-0.4.9/output/tsv/PHPReportOutput.php0000755000175000017500000000367310442102126020305 0ustar fikefike_bJump is true, it will print the report on the screen. * * Thanks to Patrice W. (patrice at sden.org) for share this with us. :-) * * * *********************************************************************************/ class PHPReportOutput extends PHPReportOutputObject { function run() { $sPath = getPHPReportsFilePath(); $sTmp = getPHPReportsTmpPath(); $sXSLT = $sPath."/output/tsv/tsv.xsl"; $sXML = $this->getInput(); // create a new filename if its empty if(is_null($this->getOutput())){ $sOut = tempnam($sTmp,"tsv"); unlink($sOut); $sOut .= ".tsv"; }else $sOut = $this->getOutput(); // XSLT processor $oProcFactory = new XSLTProcessorFactory(); $oProc = $oProcFactory->get(); $oProc->setXML($sXML); $oProc->setXSLT($sXSLT); $oProc->setOutput($sOut); $oProc->setParms(array("body"=>($this->getBody()?"true":"false"))); $sRst = $oProc->run(); /* Read file to pre-processing, replacing the __tab__ indicator for a chr(9), and write it again */ $fHand = fopen($sOut,"rb"); $sText = fread($fHand,filesize($sOut)); fclose($fHand); if(strpos($sText,"__tab__")) { $sText = str_replace("__tab__",chr(9),$sText); $sText = str_replace(chr(160)," ",$sText); $fHand = fopen($sOut,"wb"); fwrite($fHand,$sText); fclose($fHand); } // if needs to jump to show the file, show it if($this->isJumping()) print $sText; // check if needs to clean the XML data file if($this->isCleaning()) unlink($sXML); } } ?> phpreports-0.4.9/output/txt/0000755000175000017500000000000010442102127014520 5ustar fikefikephpreports-0.4.9/output/txt/txt.xsl0000755000175000017500000000240710442102126016074 0ustar fikefike __formfeed__ phpreports-0.4.9/output/txt/PHPReportOutput.php0000755000175000017500000000360410442102126020302 0ustar fikefike_bJump is true, it will print the report on the screen. * * * *********************************************************************************/ class PHPReportOutput extends PHPReportOutputObject { function run() { $sPath = getPHPReportsFilePath(); $sTmp = getPHPReportsTmpPath(); $sXSLT = $sPath."/output/txt/txt.xsl"; $sXML = $this->getInput(); // create a new filename if its empty if(is_null($this->getOutput())){ $sOut = tempnam($sTmp,"txt"); unlink($sOut); $sOut .= ".txt"; }else $sOut = $this->getOutput(); // XSLT processor $oProcFactory = new XSLTProcessorFactory(); $oProc = $oProcFactory->get(); $oProc->setXML($sXML); $oProc->setXSLT($sXSLT); $oProc->setOutput($sOut); $oProc->setParms(array("body"=>($this->getBody()?"true":"false"))); $sRst = $oProc->run(); /* Read file to pre-processing, replacing the __formfeed__ indicator for a chr(12), and write it again */ $fHand = fopen($sOut,"rb"); $sText = fread($fHand,filesize($sOut)); fclose($fHand); if(strpos($sText,"__formfeed__")){ $sText = str_replace("__formfeed__",chr(12),$sText); $sText = str_replace(chr(160)," ",$sText); $fHand = fopen($sOut,"wb"); fwrite($fHand,$sText); fclose($fHand); } // if needs to jump to show the file, show it if($this->isJumping()) print $sText; // check if needs to clean the XML data file if($this->isCleaning()) unlink($sXML); } } ?> phpreports-0.4.9/output/none/0000755000175000017500000000000010442102127014640 5ustar fikefikephpreports-0.4.9/output/none/PHPReportOutput.php0000755000175000017500000000030110442102126020411 0ustar fikefike phpreports-0.4.9/output/page/0000755000175000017500000000000010446254700014626 5ustar fikefikephpreports-0.4.9/output/page/page.php0000755000175000017500000000203510442102126016244 0ustar fikefike$incr) { $l1=$curpage-(($curpage%$incr==0?$incr:$curpage%$incr))+1; $l2=$l1+($incr-1); }else if($curpage<=$incr){ $l1=1; $l2=$l1+($incr-1); } $aParm["xmlfile"] = $_REQUEST["xmlfile"]; $aParm["curpage"] = $curpage; $aParm["incr"] = $incr; $aParm["l1"] = $l1; $aParm["l2"] = $l2; $aParm["first"] = $_REQUEST["first"]; $aParm["last"] = $_REQUEST["last"]; $aParm["next"] = $_REQUEST["next"]; $aParm["prev"] = $_REQUEST["prev"]; $aParm["url"] = $_REQUEST["url"]; $oProcFactory = new XSLTProcessorFactory(); $oProc = $oProcFactory->get(); $oProc->setXML($sXML); $oProc->setXSLT($sXSLT); $oProc->setParms($aParm); $sRst = $oProc->run(); print $sRst; ?> phpreports-0.4.9/output/page/page.xsl0000755000175000017500000001206210442102126016264 0ustar fikefike <xsl:value-of select="@TITLE"/>
?curpage=1 ?curpage= ?curpage= ?curpage= PHPREPORTS_PAGE_LINK_BOLD PHPREPORTS_PAGE_LINK ?curpage= &xmlfile= &incr= &first= &last= &next= &prev= &l1= &l2=
phpreports-0.4.9/output/page/PHPReportOutput.php0000755000175000017500000000410710442102126020376 0ustar fikefike_iCurPage = 1; $this->_iIncr = 10; $this->_sFirst = "<< "; $this->_sLast = " >>"; $this->_sNext = " >"; $this->_sPrev = "< "; } function setIncr($iIncr_=10) { $this->_iIncr=$iIncr_; } function setFirst($sFirst_) { $this->_sFirst=$sFirst_; } function setLast($sLast_) { $this->_sLast=$sLast_; } function setNext($sNext_) { $this->_sNext=$sNext_; } function setPrev($sPrev_) { $this->_sPrev=$sPrev_; } function run() { // get the files paths $sPath = getPHPReportsFilePath(); $sXSLT = "$sPath/output/page/page.xsl"; $sXML = $this->getInput(); // get the DOCUMENT_ROOT path, for temporary copy $sRoot = $_SERVER["DOCUMENT_ROOT"]; // copy the page.php file to the temporary dir if(!copy(realpath($sPath."/output/page/page.php"),realpath($sRoot."/tmp")."/page.php")){ $oError = new PHPReportsErrorTr(); $oError->showMsg("PAGEPARSER"); } // get the HOST root URL $sHost = "http://".$_SERVER["HTTP_HOST"]; $aParm = Array(); $aParm["curpage"]=1; $aParm["incr"] = $this->_iIncr; $aParm["l1"] = 1; $aParm["l2"] = $this->_iIncr; $aParm["first"] = $this->_sFirst; $aParm["last"] = $this->_sLast; $aParm["next"] = $this->_sNext; $aParm["prev"] = $this->_sPrev; $aParm["xmlfile"] = $this->getInput(); $aParm["url"] = $sHost."/tmp/page.php"; $aParm["body"] = $this->getBody()?"true":"false"; $oProcFactory = new XSLTProcessorFactory(); $oProc = $oProcFactory->get(); $oProc->setXML($sXML); $oProc->setXSLT($sXSLT); $oProc->setOutput($this->getOutput()); $oProc->setParms($aParm); $sRst = $oProc->run(); print $sRst; } } ?> phpreports-0.4.9/output/default/0000755000175000017500000000000010530316637015340 5ustar fikefikephpreports-0.4.9/output/default/default.xsl0000755000175000017500000000077510442102126017514 0ustar fikefike phpreports-0.4.9/output/default/PHPReportOutput.php0000755000175000017500000000144010442102126021103 0ustar fikefikegetInput(); $sXSLT = "$sPath/output/default/default.xsl"; $oProcFactory = new XSLTProcessorFactory(); $oProc = $oProcFactory->get(); $oProc->setXML($sXML); $oProc->setXSLT($sXSLT); $oProc->setOutput($this->getOutput()); $oProc->setParms(array("body"=>($this->getBody()?"true":"false"))); $sRst = $oProc->run(); unset($oProc); if(is_null($this->getOutput())) print $sRst; if($this->isCleaning()) unlink($sXML); } } ?> phpreports-0.4.9/output/common/0000755000175000017500000000000010527110535015177 5ustar fikefikephpreports-0.4.9/output/common/PHPReportCSS.xsl0000755000175000017500000000073710442102126020126 0ustar fikefike phpreports-0.4.9/output/common/PHPReportXHTML.xsl0000755000175000017500000000033010442102126020357 0ustar fikefike phpreports-0.4.9/output/common/PHPReportImg.xsl0000755000175000017500000000140710442102126020205 0ustar fikefike phpreports-0.4.9/output/common/PHPReportPage.xsl0000755000175000017500000000257710443323350020363 0ustar fikefike pg


 

phpreports-0.4.9/output/common/PHPReportBookmark.xsl0000755000175000017500000000035610442102126021240 0ustar fikefike phpreports-0.4.9/output/common/PHPReportCol.xsl0000755000175000017500000000657210527062510020224 0ustar fikefike <SPAN CLASS=" "> </SPAN> <a HREF=" " TITLE="" TARGET="" > </a> phpreports-0.4.9/output/common/PHPReportRow.xsl0000755000175000017500000000026210442102126020236 0ustar fikefike phpreports-0.4.9/output/common/PHPReport.xsl0000755000175000017500000000446610443565320017572 0ustar fikefike <xsl:value-of select="@TITLE"/>
phpreports-0.4.9/output/bookmarks/0000755000175000017500000000000010442102127015671 5ustar fikefikephpreports-0.4.9/output/bookmarks/bookmarks.xsl0000755000175000017500000000362010442102126020414 0ustar fikefike
javascript:// goToBookmark();
phpreports-0.4.9/output/bookmarks/PHPReportOutput.php0000755000175000017500000000450210442102126021451 0ustar fikefike_sCSS=$sCSS_; } /** Return the CSS file */ function getCSS(){ return $this->_sCSS; } /** Run the output plugin */ function run() { $sPath = getPHPReportsFilePath(); $sXML = $this->getInput(); $sCSS = $this->getCSS(); // parameter array with CSS info $aParm = Array(); $aParm["css"] = $sCSS; $aParm["body"] = $this->getBody()?"true":"false"; // get the tmp directory under the DocumentRoot $sDocRoot = $_SERVER["DOCUMENT_ROOT"]; // get the host path $sHost = "http://".$_SERVER["HTTP_HOST"]; // create some tempnames there $sBook = tempnam(realpath($sDocRoot."/tmp"),"bookmark"); unlink($sBook); $sBook .= ".html"; $sRepo = tempnam(realpath($sDocRoot."/tmp"),"report"); unlink($sRepo); $sRepo .= ".html"; // create the bookmarks file $oProcFactory = new XSLTProcessorFactory(); $oProc = $oProcFactory->get(); $oProc->setXML($sXML); $oProc->setXSLT(realpath($sPath."/output/bookmarks/bookmarks.xsl")); $oProc->setOutput($sBook); $oProc->setParms($aParm); $oProc->run(); unset($oProc); $aParm = Array(); $aParm["body"] = $this->getBody()?"true":"false"; // create the report file $oProcFactory = new XSLTProcessorFactory(); $oProc = $oProcFactory->get(); $oProc->setXML($sXML); $oProc->setXSLT(realpath($sPath."/output/default/default.xsl")); $oProc->setOutput($sRepo); $oProc->setParms($aParm); $oProc->run(); unset($oProc); // code of the framed content $sFrame = "\n". "\n". "\n". ""; // if there is not an output file, write to browser window if(is_null($this->getOutput())) print $sFrame; else{ // or open the file and store the frames there $fHandle = fopen($this->getOutput(),"w"); fputs($fHandle,$sFrame); fclose($fHandle); } if($this->isCleaning()) unlink($sXML); } } ?> phpreports-0.4.9/php/0000755000175000017500000000000010630304366013140 5ustar fikefikephpreports-0.4.9/php/sabtest.php0000755000175000017500000000072610442102126015315 0ustar fikefike=5)){ print "THIS IS A WARNING MESSAGE!!!\n"; print "Sablotron support on PHP5 is deprecated.\n"; print "Please use the PHP XSL extension on PHP >= 5.\n"; print "Script will continue, but may fail.\n"; } $oXSLT = xslt_create(); $aArg = Array(); $aParm = Array(); $aParm["html"] = "ok"; print xslt_process($oXSLT,"file://../sabtest.xml","file://../xslt/sabtest.xsl",null,$aArg,$aParm); xslt_free($oXSLT); ?> phpreports-0.4.9/php/PHPReportEvent.php0000755000175000017500000000034310442102126016470 0ustar fikefike phpreports-0.4.9/php/PHPReportLink.php0000755000175000017500000000400110442102126016277 0ustar fikefike_sType =$sType_; $this->_sExpr =$sExpr_; $this->_sTitle =$sTitle_; $this->_sTarget=$sTarget_; } /** Set the type It can be of three types: 1) DYNAMIC - get the link value from the field value specified on the LINK element text 2) STATIC - get the link value from the LINK element text 3) EXPRESSION - get the link value from the evaluated LINK element text */ function setType($sType_="STATIC") { $this->_sType=strtoupper($sType_); } /** Get the type */ function getType() { return $this->_sType; } /** Set the expression that will be evaluated on the link */ function setExpr($sExpr_="") { $this->_sExpr=$sExpr_; } /** Get the expression */ function getExpr() { return $this->_sExpr; } /** Set the title (it's the tooltip the browser shows) */ function setTitle($sTitle_="") { $this->_sTitle=$sTitle_; } /** Return the title */ function getTitle() { return $this->_sTitle; } /** Set the target frame Same funcionality as the HTML target */ function setTarget($sTarget_="") { $this->_sTarget=$sTarget_; } /** Returns the target frame */ function getTarget() { return $this->_sTarget; } /** Returns this link value based on it's expression and type */ function getLinkValue($oCol_) { $sVal = ""; $oError = new PHPReportsErrorTr(); if($this->_sType=="STATIC") $sVal=$this->_sExpr; else if($this->_sType=="DYNAMIC") { if(!isset($oCol_)) $oError->showMsg("DYNLINK"); $sVal=$oCol_->getValue($this->_sExpr); }else if($this->_sType=="EXPRESSION") { if(!isset($oCol_)) $oError->showMsg("EXPLINK"); $sVal = htmlspecialchars($oCol_->availExpr($this->_sExpr)); } return $sVal; } } ?> phpreports-0.4.9/php/PHPReportColParm.php0000755000175000017500000000112610442102126016744 0ustar fikefike_sName=$sName_; $this->_sValue=$sValue_; } // returns the parameter name function getName() { return strtoupper($this->_sName); } // returns the parameter value function getValue() { return $this->_sValue; } } ?> phpreports-0.4.9/php/PHPReportGroup.php0000755000175000017500000004415010442102126016507 0ustar fikefike_sName = $sName_; $this->_oFields = null; $this->_oFieldRows = null; $this->_bPageBreak = false; $this->_oChild = null; $this->_bHeader = false; $this->_bReprintHeader = false; $this->_bResetSup = false; $this->_bFooter = false; $this->_bOpen = false; $this->_iRowCount = 0; $this->_oOldExpr = null; $this->_oLastData = null; $this->_bFirst = true; $this->_bDebug = false; $this->_oError = new PHPReportsErrorTr(); } /** Return the group name @return String name */ function getName() { return $this->_sName; } /** Sets the main report object @param Object report object */ function setReport(&$oRpt_) { $this->_oReport =& $oRpt_; } /** Returns the main report object (use like this $oRpt =& $this->getReport();) @return Object report object */ function &getReport() { return $this->_oReport; } /** Sets if when the group breaks it will make a page break @param String YES,NO,TRUE,FALSE,BREAK,NOBREAK */ function setPageBreak($sBreak_=false) { if(strlen($sBreak_)<1){ $this->_bPageBreak=false; return; } $this->_bPageBreak = stristr("YES,TRUE,BREAK",$sBreak_); } /** Return if this is a page breaking group @return boolean */ function isBreakingPage() { return $this->_bPageBreak; } /** Sets the break expression @param String expression */ function setBreakExpr($sExpr_=null) { $this->_sExpr=$sExpr_; } /** Returns the break expression @return String expression */ function getBreakExpr() { return $this->_sExpr; } /** Set fields Here its a copy (not reference, each group have its own copy and values) of the values array. @param Object fields */ function setFields($oFields_=null) { /* Thanks to Robin Marlowe for warning me about a bug that was here. If using PHP5, now we need to use clone method. I need to use the eval function because if you're running in a PHP4 computer it will gives you an error with the "clone" method (PHP4 don't know what the hell is that :-). */ if(intval(substr(phpversion(),0,1))<5) $this->_oFields=$oFields_; else{ $this->_oFields=null; if(!$oFields_) return; foreach($oFields_ as $k=>$f) eval("\$this->_oFields[\$k] = clone \$f;"); } } /** Set child group @param Object child group */ function addChild(&$oChild_) { $this->_oChild=&$oChild_; } /** Returns child group @return Object child group */ function &getChild() { return $this->_oChild; } /** Sets the header Array @param Array header */ function setHeader($oHeader_=null) { $this->_oHeader=$oHeader_; } /** Returns the header object @return Array header */ function &getHeader() { return $this->_oHeader; } /** Prints the header rows */ function printHeader() { if($this->isDebugging()) print "(".$this->getName()."):printHeader:flag ".($this->_bHeader?"ON":"OFF").":first field value:".$this->getValueByPos(0)."
"; //$this->_bFirst=false; if(!$this->_bHeader&&sizeof($this->_oHeader)>0) { $this->printRows($this->_oHeader,true,true); $this->_bHeader=true; $this->_bFooter=false; } } function setReprintHeader($sReprint_="FALSE") { if(strlen($sReprint_)<1){ $this->_bReprintHeader=false; return; } $this->_bReprintHeader=stristr("YES,TRUE,REPRINT",$sReprint_); } function isReprintingHeader() { return $this->_bReprintHeader; } function setResetSuppress($sReset_="FALSE") { if(strlen($sReset_)<1){ $this->_bResetSup=false; return; } $this->_bResetSup=stristr("YES,TRUE,RESET",$sReset_); } function isResetingSuppress() { return $this->_bResetSup; } /** Sets the footer array @param Array footer */ function setFooter($oFooter_=null) { $this->_oFooter=$oFooter_; } /** Returns the footer array @return Array footer */ function &getFooter() { return $this->_oFooter; } /** Prints the footer @param $bCount - count on the page the lines of the footer The parameter above is set to FALSE on the PHPReportPage class, because we don't need to count the page lines if we are printing it's footer! */ function printFooter($bCount_=true) { if($this->isDebugging()) print "(".$this->getName()."):printFooter:flag ".($this->_bFooter?"ON":"OFF").":first field value:".$this->getValueByPos(0)."
"; if(!$this->_bFooter&&sizeof($this->_oFooter)>0) { $oPage =& $this->getPage(); $this->_bFooter=true; // isso estava duas linhas abaixo $this->printRows($this->_oFooter,$bCount_); $this->_bHeader=false; } } /** Returns the page object used to print all stuff in here - if its the page layer, returns itself @return Object page */ function &getPage() { $oPage=null; if(get_class($this)=="phpreportpage") return $this; else { if(!isset($this->_oReport)) { print "REPORT ELEMENT IS NOT OK (".$this->getName().")
"; return; } $oPage =& $this->_oReport->getPage(); } // checks the page element if(!isset($oPage)) { print "PAGE ELEMENT IS NOT OK"; return; } return $oPage; } /** Print this group rows */ function printRows($oRows_=null,$bCount_=true,$bConsumed_=false) { if(!isset($oRows_)) return; $oPage =& $this->getPage(); $iRow = $oPage->getNextRow(); $iSize=sizeof($oRows_); for($i=0;$i<$iSize;$i++,$iRow++) { $oObj=& $oRows_[$i]; $oPage->printRow($oObj->getRowValue($iRow),$bCount_,$bConsumed_); } } /** Sets the field rows array @param Array field rows */ function setFieldRows($oFieldRows_=null) { $this->_oFieldRows=&$oFieldRows_; } function &getFieldRows() { return $this->_oFieldRows; } /** Return if this group is a group with the field rows defined @param boolean */ function isFieldGroup() { return isset($this->_oFieldRows); } /** Here the values are just inserted on the page to make sense to print headers, for example. @param data row */ function putValues($oDataRow_=null) { $this->_oLastData = $oDataRow_; $oKeys = array_keys($this->_oFields); $iColNum = sizeof($oKeys); for($i=0;$i<$iColNum;$i++) { $sKey = $oKeys[$i]; $oObj =&$this->_oFields[$sKey]; $sName = $oObj->getName(); $oVal = $oDataRow_[$sName]; $oObj->setVal($oVal); // here's the trick part - no stats here, just value } } /** Evaluate the current expression from the fields row values */ function evalExpr($oRow_){ if(is_null($oRow_) || is_null($this->_sExpr) || !$this->_sExpr) return null; $aExpr = explode(",",$this->_sExpr); $iSize = sizeof($aExpr); $sCurExp = ""; for($i=0;$i<$iSize;$i++) $sCurExp .= $oRow_[$aExpr[$i]]; return $sCurExp; } /** Process fields values @param Array data row returned by SQL query */ function processValues($oDataRow_=null) { $this->_oLastData = $oDataRow_; // DONT move this! // you MUST evaluate the current expression here! // it was a bug till 0.2.9 $sCurRowExpr = $this->evalExpr($oDataRow_); // if there is a break expression but the current value is null ... if(!is_null($this->_sExpr) && $this->_sExpr!="" && is_null($this->_oOldExpr)) //$this->_oOldExpr=$oDataRow_[$this->_sExpr]; $this->_oOldExpr=$sCurRowExpr; // check the expression break - if its different, // close the current group if(!is_null($this->_sExpr) && $this->_sExpr!="" && $this->_oOldExpr!=$sCurRowExpr) { $this->_oOldExpr =$sCurRowExpr; $this->eventHandler(GROUP_CLOSE); } // DONT MOVE THIS ALSO! // we need to have the the values before the group is // opened, because maybe we need to use it on the group HEADER $this->processStats($oDataRow_); // if the group is not open, open it please! if(!$this->isOpen()) $this->eventHandler(GROUP_OPEN); $this->_iRowCount++; // print the fields if it is a field group if($this->isFieldGroup()) { $oPage =& $this->getPage(); $oPage->processValues($oDataRow_); $this->printRows($this->_oFieldRows); } $this->_bFirst=false; // if have a child ... if(isset($this->_oChild)) $this->_oChild->processValues($oDataRow_); } /** Process all stats about the numeric fields. @param Array data row returned by the SQL query */ function processStats($oDataRow_=null) { // get the field values here // you could be thinking why I dont use list/each here ... // I need the array element by reference, so to be safe I get // all the array keys and make a loop on it // process values $oKeys = array_keys($this->_oFields); $iColNum = sizeof($oKeys); for($i=0;$i<$iColNum;$i++) { $sKey = $oKeys[$i]; $oObj =&$this->_oFields[$sKey]; // get the field object $sName = $oObj->getName(); // get the field name $oVal = $oDataRow_[$sName]; // get the field value, returned from the query $oObj->set($oVal); // set the field object value } } /** Returns a field value @return Object field value */ function getValue($sField_) { if(is_null($this->_oFields[$sField_])) $this->_oError->showMsg("NOFIELD",array($sField_)); return $this->_oFields[$sField_]->getVal(); } function getValueByPos($iPos_=0){ $oKeys = array_keys($this->_oFields); return $this->_oFields[$oKeys[$iPos_]]->getVal(); } /** Returns the sum of a field value @return Object sum */ function getSum($sField_) { if(is_null($this->_oFields[$sField_])) $this->_oError->showMsg("NOFIELDSUM",array($sField_)); return $this->_oFields[$sField_]->getSum(); } /** Returns the max field value @return Object max */ function getMax($sField_) { if(is_null($this->_oFields[$sField_])) $this->_oError->showMsg("NOFIELDMAX",array($sField_)); return $this->_oFields[$sField_]->getMax(); } /** Returns the min field value @return Object min */ function getMin($sField_) { if(is_null($this->_oFields[$sField_])) $this->_oError->showMsg("NOFIELDMIN",array($sField_)); return $this->_oFields[$sField_]->getMin(); } /** Returns the average field value @return Object average */ function getAvg($sField_) { if(is_null($this->_oFields[$sField_])) $this->_oError->showMsg("NOFIELDAVG",array($sField_)); return $this->_oFields[$sField_]->getSum()/$this->getRowCount(); } /** Returns how many rows this group have @return int row count */ function getRowCount() { return $this->_iRowCount; } /** Open the group */ function open() { if(!$this->isOpen()) $this->eventHandler(GROUP_OPEN); } /** Sets if the group is opened @param boolean open */ function setOpen($bOpen_=true) { $this->_bOpen=$bOpen_; } /** Returns if the group is opened @return boolean */ function isOpen() { return $this->_bOpen; } /** Close the group */ function close() { if($this->isOpen()) $this->eventHandler(GROUP_CLOSE); } /** Run this when THE FULL REPORT begins */ function initialize() { } /** Run this when THE FULL REPORT ends */ function finalize() { $this->close(); } function getLastData(){ return $this->_oLastData; } /** Event handler @param int event */ function eventHandler($iEvent_=-1,$oObj_=null) { $oPage =& $this->getPage(); $oRepo =& $this->getReport(); switch($iEvent_) { case PUT_DATA: $this->putValues($oObj_); break; case PROCESS_DATA: if($this->isFirst()) $this->putValues($oObj_); if(!$oPage->isOpen()) $oPage->eventHandler(PAGE_OPEN,$oObj_); if(!$this->isOpen()) $this->eventHandler(GROUP_OPEN,$oObj_); $this->processValues($oObj_); break; case REPORT_OPEN: $this->initialize(); break; case REPORT_CLOSE: if(!is_null($oRepo)) $oRepo->setReportEnd(true); $this->finalize(); break; case GROUP_OPEN: if($this->isDebugging()) print "(".$this->getName()."):GROUP_OPEN:first field value:".$this->getValueByPos(0)."
"; $this->_iRowCount=0; $this->setOpen(true); // RULE: everytime a GROUP_OPEN arrives, the group is marked as open if(!$this->isFirst()){ $this->_bHeader=false; $this->_bFooter=false; } if(!$oPage->isOpen()){ $oPage->eventHandler(PAGE_OPEN); return; } if($this->isResetingSuppress()) $this->resetOldValues(); $this->printHeader(); if(!is_null($this->_oChild)) { $this->_oChild->putValues($this->getLastData()); $this->_oChild->eventHandler($iEvent_); } break; case GROUP_CLOSE: if($this->isDebugging()) print "(".$this->getName()."):GROUP CLOSE:first field value:".$this->getValueByPos(0)."
"; $oRepo =& $this->getReport(); $oPage =& $this->getPage(); if(!is_null($this->_oChild)){ $this->_oChild->eventHandler($iEvent_); $this->_oChild->resetOldExpr(); } /* Uncomment the next two lines of code if you want the DOCUMENT FOOTER being printed AFTER the PAGE FOOTER I think it becomes a little weird when you have for example "page number 10" and then "GRAND TOTAL" there, but it's a kind of taste. To make this a little more beauty we'll need another layer of detail, for example, PAGE NUMBER_FOOTER. But that's another history. :-) if($this->getName()=="DOCUMENT LAYER") $oPage->printFooter(); */ $this->printFooter(); $this->reset(); $this->_bHeader=true; // check if breaks the page on the group close if($this->isBreakingPage()&&!$oRepo->isReportEnd()) $oPage->eventHandler(PAGE_CLOSE); break; case PAGE_OPEN: if($this->isDebugging()) print "(".$this->getName()."):PAGE_OPEN:first field value:".$this->getValueByPos(0)."
"; if($this->isDebugging()&&$this->isReprintingHeader()) print "(".$this->getName()."):PAGE_OPEN:need to reprinting header
"; if($this->isDebugging()&&$this->isFirst()) print "(".$this->getName()."):PAGE_OPEN:is first time
"; if($this->isReprintingHeader()&&$this->isOpen()) //||$this->isFirst()) $this->_bHeader=false; if($this->isDebugging()) print "(".$this->getName()."):HEADER is ".($this->_bHeader?"ON":"OFF").", FOOTER is ".($this->_bFooter?"ON":"OFF")."
"; if(!$this->_bHeader&&!$this->_bFooter){ $oRepo =& $this->getReport(); if(!is_null($oRepo)&&!$oRepo->isReportEnd()){ if($this->isDebugging()) print "(".$this->getName()."):PAGE_OPEN:printing header
"; $this->printHeader(); } } // here we need to tell the groups that the page starts, BUT, // we need to tell them what are the current data being processed // right now to put on their headers if(!is_null($this->_oChild)) { if($this->_oChild->isFirst()) $this->_oChild->putValues($this->getLastData()); $this->_oChild->eventHandler($iEvent_); } break; case PAGE_CLOSE: if($this->isResetingSuppress()) $this->resetOldValues(); if(!is_null($this->_oChild)) $this->_oChild->eventHandler($iEvent_); break; } } /** Reset this group and fields values too. */ function reset($bOnlyStats_=false) { $oKeys = array_keys($this->_oFields); $iColNum = sizeof($oKeys); for($i=0;$i<$iColNum;$i++) { $sKey = $oKeys[$i]; $oObj =&$this->_oFields[$sKey]; if($bOnlyStats_) $oObj->resetStats(); else $oObj->reset(); } $this->_bOpen =false; $this->_bHeader =false; $this->_bFooter =false; if($this->isDebugging()) print "(".$this->getName()."):RESETED
"; } function resetOldValues() { $iRowNum = sizeof($this->_oFieldRows); for($i=0;$i<$iRowNum;$i++) $this->_oFieldRows[$i]->resetOldValue(); } function resetOldExpr(){ $this->_oOldExpr=null; } /** Returns the header size @return int header size */ function getHeaderSize() { return sizeof($this->_oHeader); } /** Returns the footer size @return int footer size */ function getFooterSize() { return sizeof($this->_oFooter); } function getParameter($oKey_){ $oRepo =& $this->getReport(); return $oRepo->getParameter($oKey_); } function isFirst(){ return $this->_bFirst; } function setDebug($sDebug_="FALSE"){ $sDebug_ = strtoupper($sDebug_); $this->_bDebug=($sDebug_=="TRUE"||$sDebug_=="YES"); } function isDebugging(){ return $this->_bDebug; } function getXMLOutputFile(){ return $this->_oReport->getXMLOutputFile(); } function listFields(){ $sStr="Available fields:
"; foreach($this->_oFields as $f) $sStr .= $f->getName()." "; return $sStr; } function getEnvObj($sKey_){ return $this->_oReport->getEnvObj($sKey_); } function setForm($oForm_=null){ $this->_oForm=$oForm_; } function getForm(){ return $this->_oForm; } } ?> phpreports-0.4.9/php/PHPReportImg.php0000755000175000017500000000164310442102126016127 0ustar fikefike_sURL=$sURL_; $this->_iWidth=$iWidth_; $this->_iHeight=$iHeight_; $this->_iBorder_=$iBorder_; $this->_sAlt=$sAlt_; } function setURL($sURL_=null){ $this->_sURL=$sURL_; } function getURL(){ return $this->_sURL; } function setWidth($iWidth_=-1){ $this->_iWidth=$iWidth_; } function getWidth(){ return $this->_iWidth; } function setHeight($iHeight_=-1){ $this->_iHeight=$iHeight_; } function getHeight(){ return $this->_iHeight; } function setBorder($iBorder_=-1){ $this->_iBorder=$iBorder_; } function getBorder(){ return $this->_iBorder; } function setAlt($sAlt_=-1){ $this->_sAlt=$sAlt_; } function getAlt(){ return $this->_sAlt; } } ?> phpreports-0.4.9/php/PHPReportXMLElement.php0000755000175000017500000000030210442102130017347 0ustar fikefike"; } function getXMLClose() { return ""; } } ?> phpreports-0.4.9/php/PHPReportPage.php0000755000175000017500000002271110527053726016305 0ustar fikefike_sTemp = getPHPReportsTmpPath(); $this->_sName = "PAGE LAYER"; $this->_sTag = "PG"; $this->_bOpen = false; $this->_iPageNum = 0; $this->_iSize = 50; $this->_iRow = 1; $this->_iLimit = 2500; $this->_sBuffer = ""; $this->_iBcount = 0; $this->_fHandle = null; $this->_iCurBehaviour = $this->_iBUFFER; $this->_iPosition = 1; $this->_iWidth = -1; $this->_iHeight = -1; $this->_iCellPadding = -1; $this->_iCellSpacing = -1; $this->_iBorder = -1; $this->_sAlign = "LEFT"; $this->_oGroups = null; $this->_sFile = $sXMLOutputFile; $this->_bReprintHeader= true; $this->_oDoc = null; $this->_sClass = null; $this->_oError = new PHPReportsErrorTr(); $this->createFileName(); } function setDocument(&$oDoc_){ $this->_oDoc=&$oDoc_; } function setGroups(&$oGroups_) { $this->_oGroups=&$oGroups_; } function setClass($sClass_=null){ $this->_sClass=$sClass_; } function getClass(){ return $this->_sClass; } function setWidth($iWidth_=800) { $this->_iWidth=$iWidth_; } function getWidth() { return $this->_iWidth; } function setHeight($iHeight_=800) { $this->_iHeight=$iHeight_; } function getHeight() { return $this->_iHeight; } function setCellPadding($iCellPadding_=-1) { $this->_iCellPadding=$iCellPadding_; } function getCellPadding() { return $this->_iCellPadding; } function setCellSpacing($iCellSpacing_=-1) { $this->_iCellSpacing=$iCellSpacing_; } function getCellSpacing() { return $this->_iCellSpacing; } function setBorder($iBorder_=-1) { $this->_iBorder=$iBorder_; } function getBorder() { return $this->_iBorder; } function setAlign($sAlign_="LEFT") { $this->_sAlign=$sAlign_; } function getAlign() { return $this->_sAlign; } function setSize($iSize_=50) { $this->_iSize=$iSize_; } function getSize() { return $this->_iSize; } function setLimit($iLimit_=2500) { $this->_iLimit=$iLimit_; } function getLimit() { return $this->_iLimit; } function printTag($sRow_) { $this->printRow($sRow_); } function getTemp() { return $this->_sTemp; } function getBufferRows() { return $this->_iBcount; } function getName() { return "PAGE"; } function printRow($sRow_,$bCount_=true,$bConsumed_=false) { if(!$this->isOpen()){ $this->eventHandler(PAGE_OPEN); if($bConsumed_){ if($this->isDebugging()) print "(".$this->getName()."):CONSUMED
"; return; } } if($this->isDebugging()) print "PAGE:printRow:".$sRow_."
"; if($bCount_) $this->_iBcount++; $this->_iRow+=($bCount_?1:0); $this->output($sRow_); // check if the buffer limit was reached // if so, open the temp file and flush the buffer if($this->_iCurBehaviour==$this->_iBUFFER && $this->_iBcount>$this->_iLimit) { $this->openFile(); $this->writeFile($this->_sBuffer); $this->_iCurBehaviour = $this->_iFILE; } // check if have a page break here if($this->_iSize>0 && $this->_iRow+$this->getFooterSize()>$this->_iSize) $this->eventHandler(PAGE_CLOSE); } /** Returns the current page number @return int page number */ function getPageNum() { return $this->_iPageNum; } /** * Set the page number */ function setPageNum($iNum_=0){ $this->_iPageNum=$iNum_; return $this->_iPageNum; } function &getPage() { return $this; } /** Return the number of the current row */ function getRowNum() { return $this->_iRow; } /** Return the number of the next row */ function getNextRow() { return $this->getRowNum()+1; } function output($sStr_) { // store the result, according to the current behaviour if($this->_iCurBehaviour==$this->_iBUFFER) $this->_sBuffer .= $sStr_; else $this->writeFile($sStr_); } function getBuffer() { return $this->_sBuffer; } function createFileName(){ if(is_null($this->_sFile)){ // tempnam returns a temp file name and create it - but without the suffix $this->_sFile = tempnam($this->_sTemp,"phprpt"); // so we delete it unlink($this->_sFile); // put the .xml stuff at the end $this->_sFile .=".xml"; } } function openFile() { $this->_iCurBehaviour=$this->_iFILE; if(is_null($this->_sFile)) $this->createFileName(); $this->_fHandle=@fopen($this->_sFile,"w"); if(!$this->_fHandle) $this->_oError->showMsg("CANTWRITEPAGE",array($this->_sFile)); } function writeFile($sStr_) { if(!fputs($this->_fHandle,$sStr_)) $this->_oError->showMsg("CANTWRITEPAGE",array($sStr_)); } function getFileName() { return $this->_sFile; } function closeFile() { fflush($this->_fHandle); fclose($this->_fHandle); } /** Don't fire a PAGE_OPEN event here. The page will be opened when the first row arrives. */ function initialize($oDoc_=null) { $oRepo = $this->getReport(); $sTitle = $oRepo->getTitle(); $sColor = $oRepo->getBackgroundColor(); $sImage = $oRepo->getBackgroundImage(); $sBCSS = $oRepo->getBookmarksCSS(); $sParm = (strlen($sTitle)>0?" TITLE=\"".$oRepo->getTitle()."\"":""); $sParm .= (strlen($sColor)>0?" BGCOLOR=\"".$oRepo->getBackgroundColor()."\"":""); $sParm .= (strlen($sImage)>0?" BACKGROUND=\"".$oRepo->getBackgroundImage()."\"":""); $sParm .= (strlen($sBCSS)>0?" BOOKMARKS_CSS=\"".$oRepo->getBookmarksCSS()."\"":""); $this->output("\n"); $this->output("\n"); $aCSS = $oRepo->getCSS(); for($i=0;$ioutput("\t0?"MEDIA=\"".$aCSS[$i][1]."\"":"").">$sCSSFile\n"); } $oForm = $oRepo->getForm(); if($oForm) $this->output("\t".$oForm->getXMLOpen()); } function finalize() { // if is only on the buffer yet ... if($this->_iCurBehaviour==$this->_iBUFFER){ $this->openFile(); $this->writeFile($this->_sBuffer); } if($this->isOpen()) $this->printFooter(false); if($this->isOpen()){ $this->writeFile("_sTag.">\n"); $this->setOpen(false); } // check for a form $oRepo = $this->getReport(); $oForm = $oRepo->getForm(); if($oForm) $this->output($oForm->getXMLClose()); $this->writeFile("\n"); $this->closeFile(); } function getIniTag() { $sTag = "<".$this->_sTag." SZ=\"".$this->_iSize."\" AL=\"".$this->_sAlign."\" PN=\"".$this->_iPageNum."\""; $sTag .= ($this->_iWidth >0?" WI=\"".$this->_iWidth."\"":""); $sTag .= ($this->_iHeight>0?" HE=\"".$this->_iHeight."\"":""); $sTag .= ($this->_iCellPadding>=0?" PA=\"".$this->_iCellPadding."\"":""); $sTag .= ($this->_iCellSpacing>=0?" SP=\"".$this->_iCellSpacing."\"":""); $sTag .= ($this->_iBorder>0?" BO=\"".$this->_iBorder."\"":""); $sTag .= (!is_null($this->_sClass)?" CL=\"".$this->_sClass."\"":""); $sTag .= ">\n"; return $sTag; } /** Event handler @param int event */ function eventHandler($iEvent_=-1,$oObj_=null) { switch($iEvent_) { case REPORT_OPEN: $this->initialize($oObj_); break; case REPORT_CLOSE: $this->finalize(); break; case PUT_DATA: $this->putValues($oObj_); break; case PROCESS_DATA: $this->processValues($oObj_); break; case PAGE_OPEN: if($this->isDebugging()) print "(PAGE):PAGE_OPEN:first field value:".$this->getValueByPos(0)."
"; $this->_iPageNum++; $this->output($this->getIniTag()); $this->setOpen(); // now check here if the DOCUMENT layer was opened // it not, print it if(!$this->_oDoc->isOpen()) $this->_oDoc->printHeader(); // print the PAGE HEADER $this->printHeader(); if(!is_null($this->_oGroups)) { $oGroup =& $this->_oGroups; if($oGroup->isFirst()){ if($this->isDebugging()) print "(".$this->getName()."):PAGE_OPEN:putting data to ".$oGroup->getName()."
"; $oGroup->eventHandler(PUT_DATA,$this->getLastData()); } $oGroup->eventHandler(PAGE_OPEN); } break; case PAGE_CLOSE: if($this->_bOpen){ $this->_iRow=-100; $this->printFooter(false); $this->_iRow=1; $this->output("_sTag.">\n"); $this->_bOpen=false; $this->reset(true); if($this->isDebugging()) print "(PAGE):PAGE_CLOSE:first field value:".$this->getValueByPos(0)."

"; if(!is_null($this->_oGroups)) { $oGroup =& $this->_oGroups; $oGroup->eventHandler($iEvent_); } } break; } } } ?> phpreports-0.4.9/php/PHPReportBookmark.php0000755000175000017500000000335410442102130017154 0ustar fikefike_sType =$sType_; $this->_sExpr =$sExpr_; $this->_iId =$iId_; $this->_sCellClass =$sCellClass_; } function setType($sType_="STATIC") { $this->_sType=strtoupper($sType_); } function getType() { return $this->_sType; } function setExpr($sExpr_="") { $this->_sExpr=$sExpr_; } function getExpr() { return $this->_sExpr; } function setId($iId_) { $this->_iId=$iId_; } function getId() { return $this->_iId; } function setCellClass($sCellClass_) { $this->_sCellClass=$sCellClass_; } function getCellClass() { return $this->_sCellClass; } function setTextClass($sTextClass_) { $this->_sTextClass=$sTextClass_; } function getTextClass() { return $this->_sTextClass; } function getBookmarkValue($oCol_=null) { $sVal = ""; $oError = new PHPReportsErrorTr(); if($this->_sType=="STATIC") $sVal=$this->_sExpr; else if($this->_sType=="DYNAMIC") { if(!isset($oCol_)) $oError->showMsg("DYNBOOK"); $sVal=$oCol_->getValue($this->_sExpr); }else if($this->_sType=="EXPRESSION") if(!isset($oCol_)) $oError->showMsg("EXPBOOK"); $sVal = $oCol_->availExpr($this->_sExpr); return $sVal; } } ?> phpreports-0.4.9/php/PHPReportCol.php0000755000175000017500000003134210527064434016144 0ustar fikefike_aParms = Array(); $this->_sType = "UNDEFINED"; $this->_sExpr = null; $this->_oGroup = null; $this->_sNform = null; $this->_iNformX = -1; $this->_sDecSep = ","; $this->_sThoSep = "."; $this->_bSuppr = false; $this->_oCurVal = null; $this->_oOldVal = null; $this->_sEvenClass = null; $this->_sOddClass = null; $this->_oLink = null; $this->_oBookmark = null; $this->_oImg = null; $this->_sClassExpr = null; $this->_sOnClick = ""; $this->_sOnMouseOver = ""; $this->_sOnMouseOut = ""; $this->_oError = new PHPReportsErrorTr(); $this->makeTranslationArray(); } function makeTranslationArray(){ $this->_aTrans["TYPE"] ="TP"; $this->_aTrans["NUMBERFORMAT"] ="NF"; $this->_aTrans["NUMBERFORMATEX"] ="NE"; $this->_aTrans["CELLCLASS"] ="CC"; $this->_aTrans["TEXTCLASS"] ="TC"; $this->_aTrans["ROWSPAN"] ="RS"; $this->_aTrans["COLSPAN"] ="CS"; $this->_aTrans["WIDTH"] ="WI"; $this->_aTrans["HEIGHT"] ="HE"; $this->_aTrans["ALIGN"] ="AL"; $this->_aTrans["VALIGN"] ="VA"; $this->_aTrans["ONCLICK"] ="OC"; $this->_aTrans["ONMOUSEOVER"] ="MO"; $this->_aTrans["ONMOUSEOUT"] ="MT"; } /** Add a parameter @param PHPReportColParm - parameter object */ function addParm($aParm_=null) { if($aParm_->getName()=="VISIBLE") return; if(is_null($this->_aTrans[$aParm_->getName()])) $this->_oError->showMsg("NOXMLTRANS",array($aParm_->getName())); $this->_aParms[$this->_aTrans[$aParm_->getName()]]=$aParm_; } /** Gets a parameter value @param String parameter name @return Object parameter value */ function getParm($sParm_=null) { $oObj=$this->_aParms[$sParm_]; if(is_null($oObj)) return null; return $oObj->getValue(); } /* Returns the parameters array - we dont need a method to set it, it MUST be set using the addParm to add the parameters one by one. @return Object[] parameters */ function getParms() { return $this->$_aParms; } /* Returns the XML open tag @param int row - row number to check about odd and even styles @return String XML open tag */ function getXMLOpen($iRow_=0) { $sStr = "_sEvenClass)&&$iRow_%2==0) $sStr .="CC=\"".$this->_sEvenClass."\" "; else if(!is_null($this->_sOddClass)&&$iRow_%2>0) $sStr .="CC=\"".$this->_sOddClass."\" "; // check for expression on the CELLCLASS parameter if(!is_null($this->_sCellClassExpr)) $sStr .= "CC=\"".eval($this->_sCellClassExpr)."\" "; // check if the CELLCLASS was processed $bClassProcessed = strpos($sStr,"CC")>0; // loop on the parameters array $aKeys=array_keys($this->_aParms); $iSize=sizeof($aKeys); for($i=0;$i<$iSize;$i++) { $oParm=$this->_aParms[$aKeys[$i]]; // get the parameter object $sName=$aKeys[$i]; // get the parameter name $oVal =$oParm->getValue(); // and the parameter value // if its the CELLCLASS parm, check if it // it was not processed above if($sName!="CC" || ($sName=="CC" && !$bClassProcessed)) { $sParm="$sName=\"$oVal\""; $sStr.=$sParm.($i==($iSize-1)?"":" "); } } $sStr =trim($sStr).">"; // if you mind about processing, trim is return $sStr; // here just to beautify stuff, you can remove it } /** Returns the XML close tag @return String XML closing tag */ function getXMLClose() { return ""; } /** Sets the column type @param String type */ function setType($sType_="REGULAR") { $this->_sType=$sType_; } /** Returns the column type @return String type */ function getType() { return $this->_sType; } /** Sets the column expression @param Object expression */ function setExpr($sExpr_=null) { $this->_sExpr=$sExpr_; } /** Gets the column value This function will be always called from a PHPReportRow, that must provide the row number for checking if we must use an odd or even class (if its configured that way) @param int row number @return Object value */ function getColValue($iRow_=0) { // if it's a command, run and return an empty string if($this->_sType=="CMD"){ $this->availExpr($this->_sExpr); return ""; } $sBookmark = ""; $sLinkOpen = ""; $sLinkClose = ""; $sImg = ""; $oBm = $this->_oBookmark; $oLink = $this->_oLink; $oImg = $this->_oImg; // check if there is some bookmark if(!is_null($oBm)) $sBookmark = "getNextBookmark()."\" CC=\"".$oBm->getCellClass()."\" TC=\"".$oBm->getTextClass()."\">".$oBm->getBookmarkValue($this).""; // check if there is some link if(!is_null($oLink)) { $sLinkOpen = "
  • getTitle()."\" TARGET=\"".$oLink->getTarget()."\" HREF=\"".$oLink->getLinkValue($this)."\">"; $sLinkClose= "
  • "; } // check if there is some image if(!is_null($oImg)){ $iWidth = $oImg->getWidth(); $iHeight = $oImg->getHeight(); $iBorder = $oImg->getBorder(); $sAlt = $oImg->getAlt(); $sImg = "0?" WIDTH=\"$iWidth\"":"").($iHeight>0?" HEIGHT=\"$iHeight\"":"").($iBorder>0?" BORDER=\"$iBorder\"":"").(!empty($sAlt)?" ALT=\"$sAlt\"":"").">".$oImg->getURL().""; } // column value $this->avail(); return $this->getXMLOpen($iRow_).$sBookmark.$sLinkOpen.$sImg.($this->isSuppressed()&&strcmp($this->_oCurVal,$this->_oOldVal)==0?" ":$this->_oCurVal).$sLinkClose.$this->getXMLClose(); } /** Returns the last value processed on this column @return Object value */ function getOldValue() { return $this->_oOldVal; } function resetOldValue() { $this->_oOldVal=null; $this->resetCurValue(); } function resetCurValue() { $this->_oCurVal=null; } /** Returns the column expression @return String expression */ function getExpr() { return $this->_sExpr; } /** Returns the column evaluated value @return Object value */ function avail() { // stores the old value $this->_oOldVal=$this->_oCurVal; // get the column value here $this->_oCurVal = $this->availValue($this->_sExpr); // if its not null and have some special stuff on it if(!is_null($this->_oCurVal)) { // number format exists if(!is_null($this->_sNform)){ // needs to be a string or a numeric value to apply the formatting if(strpos($this->_sNform,"%s") || is_numeric($this->_oCurVal)) $this->_oCurVal = sprintf($this->_sNform,$this->_oCurVal); } // number format extended if($this->_iNformX>=0 && is_numeric($this->_oCurVal)) $this->_oCurVal = number_format($this->_oCurVal,$this->_iNformX,$this->_sDecSep,$this->_sThoSep); } return $this->_oCurVal; } /** Return the column value @param String value */ function availValue($sExpr_=null){ if(is_null($sExpr_)) return $sExpr_; if($this->_sType=="EXPRESSION") return htmlspecialchars($this->availExpr($sExpr_),ENT_NOQUOTES); else if($this->_sType=="RAW_EXPRESSION") return $this->availExpr($sExpr_); else if($this->_sType=="FIELD") return htmlspecialchars($this->getValue($sExpr_),ENT_NOQUOTES); else return $sExpr_; } /** Evaluate the column, if it's the EXPRESSION type @param String expression */ function availExpr($sExpr_=null){ if(is_null($sExpr_)) return $sExpr_; return eval($sExpr_); } /** Returns a field value inside the column group @param String field */ function getValue($sField_) { return $this->_oGroup->getValue($sField_); } /** Returns the sum of a field inside the column group @param String field */ function getSum($sField_) { return $this->_oGroup->getSum($sField_); } /** Returns the max value of a field inside the column group @param String field */ function getMax($sField_) { return $this->_oGroup->getMax($sField_); } /** Returns the min value of a field inside the column group @param String field */ function getMin($sField_) { return $this->_oGroup->getMin($sField_); } function getAvg($sField_) { return $this->_oGroup->getAvg($sField_); } function getRowCount() { return $this->_oGroup->getRowCount(); } function getRowNum() { $oPage =& $this->_oGroup->getPage(); return $oPage->getRowNum(); } function getPageNum() { $oPage =& $this->_oGroup->getPage(); return $oPage->getPageNum(); } function setPageNum($iNum_=0) { $oPage =& $this->_oGroup->getPage(); return $oPage->setPageNum($iNum_); } function resetPageNum(){ return $this->setPageNum(0); } /** Sets the column group @param Object group */ function setGroup(&$oGroup_) { $this->_oGroup=&$oGroup_; $oRpt=$oGroup_->getReport(); if(!is_null($oRpt)) { $this->_sDecSep=$oRpt->getDecSep(); $this->_sThoSep=$oRpt->getThoSep(); } } /** Set the number format @param String format (printf like) */ function setNumberFormat($sFormat_=null) { $this->_sNform=$sFormat_; } /** Return the number format @return String format */ function getNumberFormat() { return $this->_sNform; } /** Set the number format decimal places @param int - number of decimal places */ function setNumberFormatEx($iNum_=0) { $this->_iNformX=$iNum_; } /** Return the number of decimal places @return int - number of decimal places */ function getNumberFormatEx() { return $this->_iNformX; } /** Set if the column will print blank values when the current value is the same of the last printed value @param String YES,NO,TRUE,FALSE */ function suppress($sStr_="FALSE") { $sStr = strtoupper($sStr_); // don't use strpos here, there's some bug there to check this ... if($sStr=="TRUE"||$sStr=="YES") $this->_bSuppr=true; } /** Return if its a suppressed values column @return boolean */ function isSuppressed() { return $this->_bSuppr; } /** Set the even row class this column will fit on @param String class */ function setEvenClass($sClass_=null) { $this->_sEvenClass=$sClass_; } /** Set the odd row class this column will fit on @param String class */ function setOddClass($sClass_=null) { $this->_sOddClass=$sClass_; } function setCellClassExpr($sExpr_=null){ $this->_sCellClassExpr=$sExpr_; } /** Add a link object in this column @param PHPReportLink link */ function addLink($oLink_) { $this->_oLink=$oLink_; } /** Add a bookmark object in this column @param PHPReportBookmark link */ function addBookmark($oBm_) { $this->_oBookmark=$oBm_; } function addImg($oImg_){ $this->_oImg=$oImg_; } function getNextBookmark() { $oRpt=&$this->_oGroup->getReport(); return $oRpt->getNextBookmark(); } function getParameter($oKey_) { return $this->_oGroup->getParameter($oKey_); } function getFileName(){ $oPage =& $this->_oGroup->getPage(); return basename($oPage->getFileName()); } function getEnvObj($sKey_){ return $this->_oGroup->getEnvObj($sKey_); } function setOnClick($sEvent_){ $this->_sOnClick=$sEvent_; } function setOnMouseOver($sEvent_){ $this->_sOnMouseOver=$sEvent_; } function setOnMouseOut($sEvent_){ $this->_sOnMouseOut=$sEvent_; } } ?> phpreports-0.4.9/php/PHPReportForm.php0000755000175000017500000000136310442102130016310 0ustar fikefikesName=null; $this->sMethod=null; $this->sAction=null; } function setName($sName_) { $this->sName=$sName_; } function getName(){ return $this->sName; } function setMethod($sMethod_) { $this->sMethod=$sMethod_; } function getMethod(){ return $this->sMethod; } function setAction($sAction_) { $this->sAction=$sAction_; } function getAction(){ return $this->sAction; } function getXMLOpen() { return "
    "; } function getXMLClose() { return "
    "; } } ?> phpreports-0.4.9/php/PHPReportField.php0000755000175000017500000000615110442102130016430 0ustar fikefikesName = $sName_; $this->sType = $sType_; $this->dVal = -1; $this->dMin = null; $this->dMax = null; $this->dSum = 0; $this->bNum = $this->checkNumeric(); } /** Reset field values */ function reset() { $this->dVal = (is_numeric($this->dVal)?0:""); $this->resetStats(); } /** Reset statistics */ function resetStats() { $this->dMin = null; $this->dMax = null; $this->dSum = 0; } /* Field name */ function getName() { return $this->sName; } /* Field type */ function getType() { return $this->sType; } /** Is a numeric field? */ function isNumeric(){ return $this->bNum; } /** Returns if its a numeric field @param */ function checkNumeric() { // just make statistics on the numeric fields - change here if your // database treats numeric fields with other description // there is a workaround on numeric fields that some // databases don't return the correct type (some ODBC databases) // and I return UNDEFINED as the type and presume they are numeric $sStr = "NUMBER,NUMERIC,INT,DOUBLE,DECIMAL,REAL,TINY,SHORT,LONG,FLOAT,LONGLONG,INT24,YEAR,CID,FLOAT4,FLOAT8,INT2,". "INT4,MONEY,OID,RELTIME,XID,DOUBLE PRECISION,SMALLINT,TINYINT,BIGINT,INT64,INT8,DATE,DATETIME"; return stristr($sStr,$this->sType); } /** Set the values and statistics about this field here. @param value */ function set($oVal_=-1) { $this->setVal($oVal_); /* If not numeric, don't make statistics, or if the type is UNDEFINED, tries to make statistics for all kind of data. note that is a bug on the way the database returns the data type, and not a PHPReports bug. */ if($this->isNumeric($oVal_) || $this->sType=="UNDEFINED") { $this->setMin($oVal_); $this->setMax($oVal_); $this->setSum($oVal_); } } /** Set the value */ function setVal($oVal_=-1) { $this->dVal=$oVal_; } /** Return the value */ function getVal() { return $this->dVal; } /** Set the minimum value */ function setMin($oVal_=0) { if(is_null($this->dMin)){ $this->dMin=$oVal_; return; } $this->dMin=$oVal_<$this->dMin?$oVal_:$this->dMin; } /** Returns the minimum value */ function getMin() { return $this->dMin; } /** Sets the maximum value @param value */ function setMax($oVal_=0) { if(is_null($this->dMax)){ $this->dMax=$oVal_; return; } $this->dMax=$oVal_>$this->dMax?$oVal_:$this->dMax; } /** Returns the maximum value */ function getMax() { return $this->dMax; } /** Set the field sum */ function setSum($oVal_=0) { $this->dSum+=$oVal_; } /** Returns the field sum */ function getSum() { return $this->dSum; } } ?> phpreports-0.4.9/php/PHPReportRow.php0000755000175000017500000000311010442102130016144 0ustar fikefike_aCols=Array(); } /* Add a column in the row */ function addCol(&$oCol_) { array_push($this->_aCols,&$oCol_); } function &getCols() { return $this->_aCols; } /* Returns the XML open tag */ function getXMLOpen() { return ""; } /* Returns the XML close tag */ function getXMLClose() { return ""; } /** Prints the row (and all the columns inside of it) @param tabs - the tabs that must be inserted before this element @param row number - this row number */ function getRowValue($iRow_=0) { $sTabs=""; //"\t\t"; $sStr = $sTabs.$this->getXMLOpen(); // there was a \n here on the end $iSize=sizeof($this->_aCols); $sSep1=""; // \t $sSep2=""; // \n for($i=0;$i<$iSize;$i++) { $oCol =& $this->_aCols[$i]; $oVal = $oCol->getColValue($iRow_); $sStr .= $sSep1.$sTabs.$oVal.$sSep2; } $sStr.= $sTabs.$this->getXMLClose()."\n"; return $sStr; } /** Returns the row expression */ function getExpr(){ $sStr = ""; $iSize=sizeof($this->_aCols); for($i=0;$i<$iSize;$i++) { $oCol =& $this->_aCols[$i]; $sStr .= $oCol->getExpr(); } return $sStr; } function resetOldValue() { $iSize=sizeof($this->_aCols); for($i=0;$i<$iSize;$i++) { $oCol =& $this->_aCols[$i]; $oCol->resetOldValue(); } } function debug() { $iSize=sizeof($this->_aCols); for($i=0;$i<$iSize;$i++) { $oCol =& $this->_aCols[$i]; $oCol->debug(); } } } ?> phpreports-0.4.9/php/PHPReportRpt.php0000755000175000017500000000744110442102130016155 0ustar fikefikesTitle = "untitled"; $this->sPath = ""; $this->sBackgroundColor = "#FFFFFF"; $this->sBackgroundImage = null; $this->sCSS = null; $this->sBookmarksCSS = null; $this->sSQL = null; $this->sNoDataMsg = "NO DATA FOUND"; $this->bCaseSensitive = true; $this->_iBookmarkCtrl = 0; $this->_bReportEnd = false; $this->_iMaxRowBuffer = 2500; $this->_aCSS = Array(); $this->_aEnv = $aEnv_; $this->configSep(); } // title function setTitle($sTitle_="untitled") { $this->sTitle=$sTitle_; } function getTitle() { return $this->sTitle; } // path function setPath($sPath_="") { $this->sPath=$sPath_; } function getPath() { return $this->sPath; } // background color function setBackgroundColor($sColor_="") { $this->sBackgroundColor=$sColor_; } function getBackgroundColor() { return $this->sBackgroundColor; } // background image function setBackgroundImage($sImg_) { $this->sBackgroundImage=$sImg_; } function getBackgroundImage() { return $this->sBackgroundImage; } // no data found message function setNoDataMsg($sMsg_="NO DATA FOUND") { $this->sNoDataMsg=$sMsg_; } function getNoDataMsg() { return $this->sNoDataMsg; } function addCSS($sCSS_,$sMedia_=""){ array_push($this->_aCSS,Array($sCSS_,$sMedia_)); } function getCSS() { return $this->_aCSS; } // bookmarks css file function setBookmarksCSS($sCSS_) { $this->sBookmarksCSS=$sCSS_; } function getBookmarksCSS() { return $this->sBookmarksCSS; } // page function setPage(&$oPage_) { $this->oPage=&$oPage_; } function &getPage() { return $this->oPage; } // form function setForm(&$oForm_) { $this->oForm=&$oForm_; } function &getForm() { return $this->oForm; } // margin width function setMarginWidth($iWidth_) { $this->iMarginWidth=$iWidth_; } function getMarginWidth() { return $this->iMarginWidth; } // margin height function setMarginHeight($iHeight_) { $this->iMarginHeight=$iHeight_; } function getMarginHeight() { return $this->iMarginHeight; } // parameters function setParameters($aParms_) { $this->aParameters=$aParms_; } function getParameters() { return $this->aParameters; } function getParameter($oKey_){ return $this->aParameters[$oKey_]; } /* Configure numeric separators */ function configSep() { $oLocale = localeconv(); $this->sDecSep = $oLocale["mon_decimal_point"]; $this->sThoSep = $oLocale["mon_thousands_sep"]; if(strlen($this->sDecSep)<1) $this->sDecSep = "."; if(strlen($this->sThoSep)<1) $this->sThoSep = ","; } function getDecSep() { return $this->sDecSep; } function getThoSep() { return $this->sThoSep; } function getNextBookmark() { return $this->_iBookmarkCtrl++; } function setReportEnd($bEnd_) { $this->_bReportEnd=$bEnd_; } function isReportEnd() { return $this->_bReportEnd; } function setMaxRowBuffer($iBuffer_=2500){ $this->_iMaxRowBuffer=$iBuffer_; } function getMaxRowBuffer(){ return $this->_iMaxRowBuffer; } function getEnvObj($sKey_){ if(!array_key_exists($sKey_,$this->_aEnv)) return null; return $this->_aEnv[$sKey_]; } } ?> phpreports-0.4.9/php/xsltest.php0000755000175000017500000000076610442102130015355 0ustar fikefikeload("../xsltest.xml"); $oXSL = new DomDocument(); $oXSL->load("../xslt/xsltest.xsl"); $oProc = new XSLTProcessor(); $oProc->importStyleSheet($oXSL); $oProc->setParameter("","html","ok"); print $oProc->transformToXML($oXML); ?> phpreports-0.4.9/PHPReportConvert.php0000755000175000017500000000140210442102130016230 0ustar fikefikecreateOutputPlugin($sOut); $oOut->setInput($sURL); $oOut->setClean(false); $oOut->run(); ?> phpreports-0.4.9/PHPReport.dtd0000755000175000017500000000637110527055330014702 0ustar fikefike phpreports-0.4.9/PHPReportInputObject.php0000755000175000017500000000075510530633132017061 0ustar fikefike_group_desc= $group_desc; $this->_group_key = $group_key; $this->_options = $options; } function setSQL($sql){ $this->_sql = $sql; } function setConnection($con){ $this->_con = $con; } function run(){ } } ?> phpreports-0.4.9/PHPReportMaker.php0000755000175000017500000007600710530401056015673 0ustar fikefikesetXML("test.xml"); * * $oRpt->setXSLT("test.xsl"); * * $oRpt->setUser("john"); * * $oRpt->setPassword("doe"); * * $oRpt->setConnection("mydatabaseaddr"); * * $oRpt->setDatabaseInterface("oracle"); * * $oRpt->setSQL("select * from mytable"); * * $oRpt->run(); * * * ******************************************************************************/ class PHPReportMaker { var $_sPath; // PHPReports path var $sXML; // XML report file var $sXSLT; // XSLT file var $sUser; // user name var $sPass; // password var $sCon; // connection name var $sDataI; // database interface var $sSQL; // sql query command var $_oParm; // parameters var $sDatabase; // database var $sCodeOut; // code output var $sOut; // HTML result file var $bDebug; // debug report var $_sNoDataMsg; // no data message - NEW!!! on 0.2.0 var $_sOutputPlugin; // output plugin name - NEW!!! on 0.2.0 var $_oOutputPlugin; // output plugin - NEW!!! on 0.2.0 var $_sXMLOutputFile;// XML output file with the data var $_sSaveTo; // save to file - NEW!!! 0.2.0 var $_oProc; // XSLT processor var $_aEnv; // enviroment vars var $_sClassName; // report class name to create var $_sTmp; // temporary dir var $_oCon; // database connection handle var $_oQuery; // executed query var $_iPageSize; // page size var $_aBench; // benchmark registers var $_sLang; // language var $_bBody; // no HTML BODY shown on the report var $_bDeleteXML; // if needs to delete the XML file after using it var $_oError; var $_oInput; // input plugins /*************************************************************************** * * * Constructor - remember to set the PHPREPORTS * * environment variable * * * ***************************************************************************/ function PHPReportMaker() { $this->_sPath = getPHPReportsFilePath(); $this->_sTmp = getPHPReportsTmpPath(); $this->sXML = null; $this->sXSLT = $this->_sPath."/xslt/PHPReport.xsl"; $this->sUser = null; $this->sPass = null; $this->sCon = null; $this->sDataI = null; $this->sSQL = null; $this->_oParm = Array(); $this->sDatabase = null; $this->sCodeOut = null; $this->sOut = null; $this->bDebug = false; $this->_sNoDataMsg = ""; $this->_sNoDataFunc = ""; $this->_sOutputPlugin = "default"; $this->_oOutputPlugin = null; $this->_sSaveTo = null; $this->_aEnv = Array(); $this->_sClassName = "PHPReport"; $this->_iPageSize = 0; $this->_aBench = Array(); $this->_sLang = "default"; $this->_bBody = true; $this->_bDeleteXML = false; $this->_oError = new PHPReportsErrorTr(); $this->_oInput = Array(); /* Now we get the XSLT processor new code on the 0.2.8 version, because PHP5 have XSL support with libxslt, by default */ $oProcFactory = new XSLTProcessorFactory(); $this->_oProc = $oProcFactory->get(); if(is_null($this->_oProc)) $this->_oError->showMsg("NOXSLT"); // check path stuff if(is_null(getPHPReportsFilePath())) $this->_oError->showMsg("NOPATH"); } /****************************************************************************** * * * Create a quick report from a layout file and some parameters. * * * ******************************************************************************/ function createFromTemplate($sTitle="NO DEFINED TITLE",$sFile=null,$oParms=null,$oDocument=null,$oGroups=null){ $sPath = getPHPReportsFilePath(); $oError = new PHPReportsErrorTr(); $sIf = $this->getDatabaseInterface(); $sFile = $sFile ? $sFile : realpath($sPath."/template.xml"); // if the file does not exist if(!file_exists($sFile)) $oError->showMsg("NOTEMPLATE",$sFile); // get the template contents $sFileContents = file_get_contents($sFile); // check if there are some parameters here ... if($oParms){ $sParms = null; if(is_object($oParms)) $sParms = $oParms->write(); if(is_string($oParms)) $sParms = $oParms; if($sParms) $sFileContents = str_replace("",$sParms,$sFileContents); } // check if there is some document info if($oDocument){ $sDocument = null; if(is_object($oDocument)) $sDocument = $oDocument->write(); if(is_string($oDocument)) $sDocument = $oDocument; if($sDocument) $sFileContents = str_replace("",$sDocument,$sFileContents); } // if no groups info was specified, follow the default behaviour: all the fields from the query, // with no group break if(!$oGroups){ // include the database interface and try to open the connection and execute the query $sIfFile = realpath($sPath."/database/db_".$sIf.".php"); if(!file_exists($sIfFile)) $oError->showMsg("NOIF",$sIf); include_once $sIfFile; // if the database connection is null, open it if(is_null($this->_oCon)) $this->_oCon = @PHPReportsDBI::db_connect(Array($this->sUser,$this->sPass,$this->sCon,$this->sDatabase)) or $oError->showMsg("REFUSEDCON"); // if there are some input filters ... if($this->_oInput){ foreach($this->_oInput as $oFilter){ $oFilter->setConnection($this->_oCon); $oFilter->setSQL(trim($this->sSQL)); $this->sSQL = trim($oFilter->run()); } // there is no need to run the filters again $this->_oInput = null; } // run the query $this->_oQuery = @PHPReportsDBI::db_query($this->_oCon,trim($this->sSQL)) or $oError->showMsg("QUERYERROR"); // insert the column names $sNames = ""; $sReplacedNames = ""; $iColNum = PHPREportsDBI::db_colnum($this->_oQuery); for($i=1; $i<=$iColNum; $i++){ $sName = PHPReportsDBI::db_columnName($this->_oQuery,$i); $sExtra = isNumericType(PHPReportsDBI::db_columnType($this->_oQuery,$i))?" ALIGN=\"RIGHT\"":""; $sReplacedNames .= "".ucfirst(strtolower(str_replace("_"," ",$sName))).""; $sNames .= "$sName"; } // build the group info $sGroup = "
    "; $sGroup = str_replace("",$sReplacedNames,$sGroup); $sGroup = str_replace("",$sNames,$sGroup); $sFileContents = str_replace("",$sGroup,$sFileContents); }else{ $sGroups = null; if(is_object($oGroups)) $sGroups = $oGroups->write(); if(is_string($oGroups)) $sGroups = $oGroups; if($sGroups) $sFileContents = str_replace("",$sGroups,$sFileContents); } // replace the report title $sFileContents = str_replace("",$sTitle,$sFileContents); // print htmlspecialchars($sFileContents); // create the temporary XML file $sTemp = tempnam($this->_sTmp,"tempphprpt"); // this is just for PHP4 compability $fHand = fopen($sTemp,"w"); fwrite($fHand,$sFileContents); fclose($fHand); $this->_bDeleteXML = true; // flag to delete the temporary file $this->sXML = $sTemp; // the XML layout file is the temporary file now } /****************************************************************************** * * * Run report * * Here is where things happens. :-) * * * ******************************************************************************/ function run() { $iReportStart = time(); // create the parameters array $aParm["user" ] = $this->sUser; // set user $aParm["pass" ] = $this->sPass; // set password $aParm["conn" ] = $this->sCon; // set connection name $aParm["interface"] = $this->sDataI; // set database interface $aParm["database" ] = $this->sDatabase; // set database $aParm["classname"] = $this->_sClassName; // ALWAYS use this class to run the report $aParm["sql" ] = $this->sSQL; // set the sql query $aParm["nodatamsg"] = $this->_sNoDataMsg; // no data msg $aParm["nodatafunc"] = $this->_sNoDataFunc; // no data function $aParm["pagesize"] = $this->_iPageSize>0?$this->_iPageSize:""; $aParm["language"] = $this->_sLang; // create the parameters keys array - with element numbers or element keys $aKeys = null; if(is_array($this->_oParm)){ $aKeys = array_keys($this->_oParm); $iSize = sizeof($this->_oParm); for($i=0; $i<$iSize; $i++){ $sOkey = $aKeys[$i]; // original key $sKey = $sOkey; // reference key // check if its a numeric key - if so, add 1 to // it to keep the parameters based on 1 and not on 0 if(is_numeric($sOkey)) $sKey = intval($sOkey)+1; $aParm["parameter".($i+1)] = $this->_oParm[$sOkey]; $aParm["reference".($i+1)] = $sKey; } } // if there is not a file to create the code, // create it on the memory (faster, use file just for // debugging stuff) if(is_null($this->sCodeOut)) { $sOut = null; $aParm["output_format"]="memory"; }else{ $sOut = $this->sCodeOut; $aParm["output_format"]="file"; } // XSLT processing $this->_aBench["code_start"] = time(); $this->_oProc->setXML($this->sXML); $this->_oProc->setXSLT($this->sXSLT); $this->_oProc->setOutput($sOut); $this->_oProc->setParms($aParm); $sRst = $this->_oProc->run(); $this->_aBench["code_end"] = time(); $this->_aBench["code_eval_start"] = time(); // if its created on the memory ... if(is_null($sOut)) eval($sRst); else { // include the generated classes, if it was created if(!file_exists($sOut)) $this->_oError->showMsg("NOCODE",array($sOut)); require_once($sOut); } $this->_aBench["code_eval_end"] = time(); // include the generated class $oReport = new $this->_sClassName; // set the database connection handle, if there is one $oReport->setDatabaseConnection($this->_oCon); $oReport->setInputFilters($this->_oInput); $oReport->setQuery($this->_oQuery); // run the generated class $this->_sXMLOutputFile = $oReport->run($this->_sXMLOutputFile,$this->_aEnv); $this->_aBench = array_merge($this->_aBench,$oReport->getBenchmarks()); // check if the XML file exists, we need data! if(!file_exists($this->_sXMLOutputFile)) $this->_oError->showMsg("NOXML",array($this->_sXMLOutputFile)); /* Now we have a XML file with the report contents ... what to to with it??? Let's call the output plugin! */ // if there is no one, create a new default plugin $oOut = null; if(is_null($this->_oOutputPlugin)) { $oOut = $this->createOutputPlugin("default"); $oOut->setInput ($this->_sXMLOutputFile); $oOut->setOutput($this->sOut); $oOut->setBody($this->_bBody); $this->setOutputPlugin($oOut); }else{ $oOut = $this->_oOutputPlugin; $oOut->setBody($this->_bBody); $oOut->setInput($this->_sXMLOutputFile); if(!is_null($this->sOut)) $oOut->setOutput($this->sOut); } // if need to save it if(!is_null($this->_sSaveTo)) $this->save(); // run $oOut->run(); $this->_aBench["output_end"] = time(); $this->_aBench["report_start"] = $iReportStart; $this->_aBench["report_end"] = time(); // if needs to delete the XML file if($this->_bDeleteXML) unlink($this->sXML); return $this->_sXMLOutputFile; } /****************************************************************************** * Return a (or all) benchmark index. * ******************************************************************************/ function getBenchmark($sId=null){ if(!$sId) return $this->_aBench; return $this->_aBench[$sId]; } /****************************************************************************** * Set the page size (overrides XML value) * ******************************************************************************/ function setPageSize($iSize=50){ $this->_iPageSize=$iSize; } function getPageSize(){ return $this->_iPageSize; } /****************************************************************************** * * * Set the XML file path * * @param String file path * * * ******************************************************************************/ function setXML($sXML_) { if(!file_exists($sXML_)) $this->_oError->showMsg("NOXMLSET",array($sXML_)); $this->sXML = $sXML_; } /****************************************************************************** * * * Returns the XML file path * * @return String file path * * * ******************************************************************************/ function getXML() { return $this->sXML; } /****************************************************************************** * * * Sets the XSLT file path * * @param String file path * * * ******************************************************************************/ function setXSLT($sXSLT_) { if(!file_exists($sXSLT_)) $this->_oError->showMsg("NOXSLTSET",array($sXSLT_)); $this->sXSLT = $sXSLT_; } /****************************************************************************** * * * Returns the XSLT file path * * @return String file path * * * ******************************************************************************/ function getXSLT() { return $this->sXSLT; } /****************************************************************************** * * * Set the user name * * @param String user name * * * ******************************************************************************/ function setUser($sUser_) { $this->sUser = $sUser_; } /****************************************************************************** * * * Returns the user name * * @return String user name * * * ******************************************************************************/ function getUser() { return $this->sUser; } /****************************************************************************** * * * Sets the password * * * ******************************************************************************/ function setPassword($sPass_) { $this->sPass = $sPass_; } /****************************************************************************** * * * Returns the password * * * ******************************************************************************/ function getPassword() { return $this->sPass; } /****************************************************************************** * * * Sets the database connection * * * ******************************************************************************/ function setConnection($sCon_) { $this->sCon = $sCon_; } /****************************************************************************** * * * Returns the password * * * ******************************************************************************/ function getConnection() { return $this->sCon; } /****************************************************************************** * * * Sets the database interface * * * ******************************************************************************/ function setDatabaseInterface($sData_) { $this->sDataI = $sData_; } /****************************************************************************** * * * Returns the database interface * * * ******************************************************************************/ function getDatabaseInterface() { return $this->sDataI; } /****************************************************************************** * * * Sets the SQL query * * * ******************************************************************************/ function setSQL($sSQL_) { $this->sSQL = $sSQL_; } /****************************************************************************** * * * Returns the SQL query * * * ******************************************************************************/ function getSQL() { return $this->sSQL; } /****************************************************************************** * * * Sets the parameters * * * ******************************************************************************/ function setParameters($oParm_) { $this->_oParm = $oParm_; } /****************************************************************************** * * * Returns the parameters * * * ******************************************************************************/ function getParameters() { return $this->_oParm; } /****************************************************************************** * * * Sets the database * * * ******************************************************************************/ function setDatabase($sData_) { $this->sDatabase = $sData_; } /****************************************************************************** * * * Returns the database * * * ******************************************************************************/ function getDatabase() { return $this->sDatabase; } /****************************************************************************** * * * Sets the code output file * * * ******************************************************************************/ function setCodeOutput($sFile_) { $this->sCodeOut = $sFile_; } /****************************************************************************** * * * Returns the database * * * ******************************************************************************/ function getCodeOutput() { return $this->sCodeOut; } /****************************************************************************** * * * Sets the output path * * * ******************************************************************************/ function setOutput($sOut_) { $this->sOut = $sOut_; } /****************************************************************************** * * * Returns output path * * * ******************************************************************************/ function getOutput() { return $this->sOut; } /****************************************************************************** * * * Sets if the report will generate debug info after it runs * * * ******************************************************************************/ function setDebug($bDesc) { $this->bDebug = $bDesc; } /****************************************************************************** * * * Returns if will debug * * * ******************************************************************************/ function getDebug() { return $this->bDebug; } /****************************************************************************** * * * Sets message to be shown when no data returns from the query * * @param String message * * * ******************************************************************************/ function setNoDataMsg($sMsg_="") { $this->_sNoDataMsg=$sMsg_; } /****************************************************************************** * * * Returns the no data message * * @return String message * * * ******************************************************************************/ function getNoDataMsg() { return $this->_sNoDataMsg; } function setNoDataFunc($sFunc=""){ $this->_sNoDataFunc=$sFunc; } function getNoDataFunc(){ return $this->_sNoDataFunc; } /****************************************************************************** * * * Create the output plugin * * @param name * * * ******************************************************************************/ function createOutputPlugin($sName_) { $sFullPath = $this->_sPath."/output/$sName_/PHPReportOutput.php"; // check if the required plugin exists if(!file_exists($sFullPath)) $this->_oError->showMsg("NOPLUGIN",array($sName_,$sFullPath)); include $sFullPath; $oOut = new PHPReportOutput($this->sXML); return $oOut; } function addInputPlugin($sName_,$oGroupDesc_,$sGroupKey_,$oOptions_=null){ $sName = ucwords(strtolower($sName_)); $sClass = "PHPReportInput$sName"; $sFullPath = $this->_sPath."/input/PHPReportInput$sName.php"; // check if the required plugin exists if(!file_exists($sFullPath)) $this->_oError->showMsg("NOPLUGIN",array($sName_,$sFullPath)); include $sFullPath; $oIn = new $sClass($oGroupDesc_,$sGroupKey_,$oOptions_); array_push($this->_oInput,$oIn); } /****************************************************************************** * * * Output plugin for the final format * * @param plugin * * * ******************************************************************************/ function setOutputPlugin($oPlugin_) { $this->_oOutputPlugin=$oPlugin_; } /****************************************************************************** * * * Returns the output plugin * * @return plugin * * * ******************************************************************************/ function getOutputPlugin() { return $this->_oOutputPlugin; } /****************************************************************************** * * * Set the XML output/data file * * * ******************************************************************************/ function setXMLOutputFile($sFile_=null){ $this->_sXMLOutputFile=$sFile_; } /****************************************************************************** * * * Returns the XML output/data file * * * ******************************************************************************/ function getXMLOutputFile(){ return $this->_sXMLOutputFile; } /****************************************************************************** * * * File path to save the report * * Please remember to use a writable path! * * * ******************************************************************************/ function saveTo($sFile_=null){ if(is_null($sFile_)) return; $this->_sSaveTo=$sFile_; } /****************************************************************************** * * * Save report * * * ******************************************************************************/ function save(){ if(is_null($this->_sSaveTo)) return; $sIn = $this->_sXMLOutputFile; $sMD5 = md5_file($sIn); // calculate the md5 checksum $sMD5 = str_pad($sMD5,50); // padding $sOut = "compress.zlib://".$this->_sSaveTo; $fIn = fopen($sIn,"r"); $fOut = fopen($sOut,"w"); // write the md5sum fwrite($fOut,$sMD5); while($sStr=fread($fIn,1024)) fwrite($fOut,$sStr); fclose($fOut); fclose($fIn); } /****************************************************************************** * * * Preview report * * * ******************************************************************************/ function preview($sXML_=null){ if(is_null($sXML_)) return; if(!file_exists($sXML_)){ print "The file $sXML_ doesn't exists.
    "; return; } $sPath = getPHPReportsFilePath(); $sXSLT = "$sPath/xslt/PHPReportPreview.xsl"; // XSLT processing $this->_oProc->setXML($sXML_); $this->_oProc->setXSLT($sXSLT); print $this->_oProc->run(); } /****************************************************************************** * * * Put an object to the environment array. * * You can use this function to expose any kind of variable or class to your * * report (using $this->getEnv("id")). Note that for using objects * * returned by this function directly as * * $this->getEnv("id")->myFunction() * * you'll need PHP5. * * * ******************************************************************************/ function putEnvObj($sKey_=null,$oObj_=null){ if(is_null($sKey_) || is_null($oObj_)) return; $this->_aEnv[$sKey_]=$oObj_; } /****************************************************************************** * * * Returns an object from the environment array. * * * ******************************************************************************/ function getEnvObj($sKey_){ return $this->_aEnv[$sKey_]; } /****************************************************************************** * * * Set the name of the class that will be created * * to run the report. * * To see where this name is used, please check xslt/PHPReport.xsl * * * ******************************************************************************/ function setClassName($sClassName_="PHPReport"){ $this->_sClassName=$sClassName_; } /****************************************************************************** * * * Returns the name of the class that will be created * * to run the report. * * * ******************************************************************************/ function getClassName(){ return is_null($this->_sClassName)?"PHPReport":$this->_sClassName; } /****************************************************************************** * * * Set the database connection handle * * * ******************************************************************************/ function setDatabaseConnection(&$_oCon){ $this->_oCon =& $_oCon; } /****************************************************************************** * * * Here's the deal: if the user have a session opened, the language will be * * stored there. If more than one user is using the system with different * * languages, each one will see the specified language (no way to run two * * reports with different languages for each user). If no session is opened, * * the language value is already there on GLOBALS, so we can retrieve from * * there, but this will allow just one language for all the reports. * * * ******************************************************************************/ function setLanguage($sLang_="default"){ $this->_sLang=$sLang_; $_SESSION["phpReportsLanguage"] = $sLang_; $GLOBALS["phpReportsLanguage"] = $sLang_; } function getLanguage(){ return $this->_sLang; } function setBody($b=true){ $this->_bBody=$b; } function getBody(){ return $this->_bBody; } } class PHPReportTemplateElement { var $_aAttrs; var $_aChildren; var $_sType; function PHPReportTemplateElement($sType=null,$aAttrs=null){ $this->_sType = $sType; $this->_aChildren = array(); $this->_aAttrs = $aAttrs ? $aAttrs : array(); } function addAttr($sKey,$sValue){ $this->_aAttrs[$sKey]=$sValue; } function addChild($oChild){ array_push($this->_aChildren,$oChild); } function write(){ if($this->_sType){ $sStr = "<".$this->_sType; foreach($this->_aAttrs as $sKey=>$sValue) $sStr .= strtoupper($sKey)=="VALUE"?"":" $sKey=\"$sValue\" "; $sStr .= ">"; } $sStr .= $this->_aAttrs["VALUE"]; foreach($this->_aChildren as $oChild) $sStr .= $oChild->write(); if($this->_sType) $sStr .= "_sType.">"; return $sStr; } } ?> phpreports-0.4.9/PHPReportOutputObject.php0000755000175000017500000001316210442102130017245 0ustar fikefike_sInput = null; $this->_sOutput = null; $this->_bClean = true; $this->_bJump = true; $this->_bBody = true; } /*************************************************************************** * * * Sets the XML input file path * * This is the XML layout file, not the data one. * * @param String path * * * ***************************************************************************/ function setInput($sInput_=null){ $this->_sInput=$sInput_; } /*************************************************************************** * * * Returns the XML input file path * * @return String path * * * ***************************************************************************/ function getInput(){ return $this->_sInput; } /*************************************************************************** * * * Sets the path of the plugin result file. * * @param String path * * * ***************************************************************************/ function setOutput($sOutput_=null){ $this->_sOutput=$sOutput_; } /*************************************************************************** * * * Returns the path of the plugin result file. * * @return String path * * * ***************************************************************************/ function getOutput(){ return $this->_sOutput; } /*************************************************************************** * * * Set the file erasing (after the report is rendered) flag * * Erases (or not) the XML data file, not the plugin result. * * @param boolean clean * * * ***************************************************************************/ function setClean($bClean_=true){ $this->_bClean=$bClean_; } /*************************************************************************** * * * Returns if this class will erase the file * * after the report is rendered * * @return boolean erase * * * ***************************************************************************/ function isCleaning(){ return $this->_bClean; } /*************************************************************************** * * * If true, makes the current URL "jumps" and show the plugin result. * * * ***************************************************************************/ function setJump($bJump_=true){ $this->_bJump=$bJump_; } /*************************************************************************** * * * Returns if it's "jumping". * * * ***************************************************************************/ function isJumping(){ return $this->_bJump; } /*************************************************************************** * * * This function needs to be defined on every plugin. * * * ***************************************************************************/ function run(){ } function setBody($b=true){ $this->_bBody=$b; } function getBody(){ return $this->_bBody; } /*************************************************************************** * * * Load a saved report from a file. * * @param file path * * * ***************************************************************************/ function loadFrom($sPath_=null){ if(is_null($sPath_)) return; if(!file_exists($sPath_)){ $oError = new PHPReportsErrorTr(); $oError->showMsg("NOLOAD",array($sPath_)); } $sTemp = tempnam(getPHPReportsTmpPath(),"xml"); $fIn = fopen("compress.zlib://".$sPath_,"r"); $fOut = fopen($sTemp,"w"); // read the md5sum $sMD5 = trim(fread($fIn,50)); while($sStr=fread($fIn,1024)) fwrite($fOut,$sStr); fclose($fOut); fclose($fIn); $sMD5chk = md5_file($sTemp); if(strcmp($sMD5,$sMD5chk)!=0){ unlink($sTemp); print "ERROR: the report stored in $sPath_ is corrupted."; return; } //$sTemp = substr(strrchr($sTemp,"/"),1); $this->setInput($sTemp); $this->run(); } } ?> phpreports-0.4.9/PHPReportsTest.php0000755000175000017500000000565210442102130015725 0ustar fikefikesetXML("sales.xml"); $oRpt->setUser($sUser); $oRpt->setPassword($sPass); $oRpt->setDatabase($sData); $oRpt->setDatabaseInterface($sInte); $oRpt->setConnection($sConn); $oRpt->setCodeOutput($sCode); $oRpt->setXMLOutputFile($sXMLOut); $oRpt->setOutput($sHTMLOut); print "Creating the default output plugin ...\n"; $oOut = $oRpt->createOutputPlugin("default"); if(is_null($oOut)){ print "ERROR: could not create an output plugin."; return; } $oOut->setClean(false); $oRpt->setOutputPlugin($oOut); print "Running the report, please wait ...\n"; $oRpt->run(); // check if everything was ok if(!file_exists($sCode)) print "ERROR: code file $sCode does not exists, no code to process."; if(filesize($sCode)<=0) print "ERROR: code file $sCode does not have a valid size, no code to process."; if(!file_exists($sXMLOut)) print "ERROR: XML data file $sXMLOut does not exists, no data to process."; if(filesize($sXMLOut)<=0) print "ERROR: XML data file $sXMLOut does not have a valid size, no data to process."; if(!file_exists($sHTMLOut)) print "ERROR: HTML result file $sHTMLOut does not exists, no result to show."; if(filesize($sHTMLOut)<=0) print "ERROR: HTML result file $sHTMLOut does not have a valid size, no result to show."; // show the result files print "Report done, here are the files:\n"; print "Code : $sCode\n"; print "XML data : $sXMLOut\n"; print "HTML result : $sHTMLOut\n"; ?> phpreports-0.4.9/PHPReportsUtil.php0000755000175000017500000004314110530350472015732 0ustar fikefike_sXML =null; $this->_sXSLT =null; $this->_sOutput=null; $this->_aParms =null; } /** Sets the XML data file path */ function setXML($sXML_=null){ $this->_sXML=$sXML_; } /** Returns the XML data file path */ function getXML(){ return $this->_sXML; } /** Sets the style sheet file path */ function setXSLT($sXSLT_=null){ $this->_sXSLT=$sXSLT_; } /** Returns the style sheet file path */ function getXSLT(){ return $this->_sXSLT; } /** Specify the output file path A null just returns the result on the run method */ function setOutput($sOutput_=null){ $this->_sOutput=$sOutput_; } /** Return the output file path */ function getOutput(){ return $this->_sOutput; } /** Specify the parameters array */ function setParms($aParms_=null){ if(is_null($aParms_)) return; if(!is_array($aParms_)) return; $this->_aParms=$aParms_; } /** Insert a parameter sParm_ - parameter name oVal_ - parameter value */ function setParm($sParm_=null,$oVal_=null){ if(is_null($sParm_)) return; $this->_aParms[$sParm_]=$oVal_; } /** Returns a parameter value sParm_ - parameter name */ function getParm($sParm_){ if(!array_key_exists($sParm_)) return null; return $this->_aParms[$sParm_]; } /** Remove a parameter sParm_ - parameter name */ function removeParm($sParm_=null){ if(is_null($sParm_)) return; if(!array_key_exists($sParm_,$this->_aParms)) return; unset($this->_aParms[$sParm_]); } /** This method MUST be overwritten on every subclass to reflect the behaviour of the desired XSLT processor. It MUST return the result, and if defined an output, save it. */ function run(){ } } /****************************************************************************** * * * Sablotron processor * * http://www.gingerall.com/charlie/ga/xml/p_sab.xml * * http://www.php.net/manual/en/ref.xslt.php * * Used on PHP4 or installed from the PECL modules. * * * ******************************************************************************/ class Sablotron_xp extends XSLTProcessorClass{ function run(){ if(is_null($this->_sXML)){ print "ERROR: no XML file specified"; return; } if(is_null($this->_sXSLT)){ print "ERROR: no XSLT file specified"; return; } $oXSLT = xslt_create(); $sRst = xslt_process($oXSLT,$this->_sXML,$this->_sXSLT,$this->_sOutput,null,$this->_aParms); xslt_free($oXSLT); return $sRst; } } /****************************************************************************** * * * PHP5 XSL processing * * Uses libxslt * * http://www.php.net/manual/en/ref.xsl.php * * * ******************************************************************************/ class PHPXSL_xp extends XSLTProcessorClass{ function run(){ // xml document $oXML = new DomDocument(); $oXML->load($this->_sXML); $oXML->xinclude(); // xslt document $oXSL = new DomDocument(); $oXSL->load($this->_sXSLT); // xslt processor $oProc = new XSLTProcessor(); $oProc->importStyleSheet($oXSL); // set all the parameters if(!is_null($this->_aParms)){ foreach($this->_aParms as $k => $v) $oProc->setParameter("",$k,$v); } // make the transformation $sRst = $oProc->transformToXML($oXML); unset($oProc); unset($oXSL); unset($oXML); // if output is not null, save the result there if(!is_null($this->_sOutput)){ $fHand = @fopen($this->_sOutput,"w"); @fputs($fHand,$sRst); @fclose($fHand); } return $sRst; } } /****************************************************************************** * * * XSLT Processor factory * * Returns a XSLT processor based on the current environment * * or the user choice (need to hack the code below). * * * ******************************************************************************/ class XSLTProcessorFactory{ function get(){ // PHP major version number $iVer = intval(substr(phpversion(),0,1)); // if PHP4 and Sablotron is installed if($iVer<=4 && function_exists("xslt_create")) return new Sablotron_xp(); // if PHP5 and Sablotron is installed else if($iVer>=5 && function_exists("xslt_create")) return new Sablotron_xp(); // if PHP5, Sablotron is not installed and XSL support is compiled else if($iVer>=5 && !function_exists("xslt_create") && class_exists("XSLTProcessor")) return new PHPXSL_xp(); // there is no XSLT processor installed! else return null; } } /****************************************************************************** * * * PHPReportsError * * Process error messages * * * ******************************************************************************/ class PHPReportsError{ function PHPReportsError($sMsg_=null,$sURL_=null){ if(is_null($sMsg_)) return; print "

    "; print "OOOOPS, THERE'S AN ERROR HERE.

    "; print $sMsg_."

    "; if(!is_null($sURL_)) print "More about this error here.

    "; print "This error message was generated by PHPReports"; print "

    "; exit(); } } class PHPReportsErrorTr { var $_aMsgs; function PHPReportsErrorTr(){ $this->_aMsgs = Array(); // default English messages $this->_aMsgs["OPS"]["default"] = "OOOOPS, THERE'S AN ERROR HERE."; $this->_aMsgs["ERROR"]["default"] = "This error message was generated by phpReports."; $this->_aMsgs["NODATA"]["default"] = "No data was found."; $this->_aMsgs["NOPAGE"]["default"] = "No PAGE element was found on your XML file."; $this->_aMsgs["NOIF"]["default"] = "No database interface '%s' available."; $this->_aMsgs["REFUSEDCON"]["default"] = "Connection refused."; $this->_aMsgs["QUERYERROR"]["default"] = "There's an error on your SQL query."; $this->_aMsgs["NOCOLUMNS"]["default"] = "No columns returned from your query."; $this->_aMsgs["PAGEPARSER"]["default"] = "Could not copy the temporary page parser to the temporary directory."; $this->_aMsgs["DYNLINK"]["default"] = "Specified a dynamic link but no COLUMN element found"; $this->_aMsgs["EXPLINK"]["default"] = "Specified an expression link but no COLUMN element found"; $this->_aMsgs["NOFIELD"]["default"] = "You're trying to retrieve the VALUE of a field called %s, but it is not on your SQL query. Please check your query."; $this->_aMsgs["NOFIELDSUM"]["default"] = "You're trying to retrieve the SUM of a field called %s, but it is not on your SQL query. Please check your query."; $this->_aMsgs["NOFIELDMAX"]["default"] = "You're trying to retrieve the MAX VALUE of a field called %s, but it is not on your SQL query. Please check your query."; $this->_aMsgs["NOFIELDMIN"]["default"] = "You're trying to retrieve the MIN VALUE of a field called %s, but it is not on your SQL query. Please check your query."; $this->_aMsgs["NOFIELDAVG"]["default"] = "You're trying to retrieve the AVERAGE of a field called %s, but it is not on your SQL query. Please check your query."; $this->_aMsgs["CANTWRITEPAGE"]["default"] = "Can't write file %s to the disk. Check your disk quota/space and rights."; $this->_aMsgs["DYNBOOK"]["default"] = "Specified a dynamic bookmark but no COLUMN element found"; $this->_aMsgs["EXPBOOK"]["default"] = "Specified an expression bookmark but no COLUMN element found"; $this->_aMsgs["NOXMLTRANS"]["default"] = "COL parameter %s not found on XML translation."; $this->_aMsgs["NOXSLT"]["default"] = "There is no XSLT processor available. Check if you compiled PHP with --enable-xslt and the Sablotron library (for PHP4) or with --enable-xsl (for PHP5)."; $this->_aMsgs["NOPATH"]["default"] = "Seems that you didn't specified the phpReports path on the PHP include_path statement or php.ini. I don't know there the classes are."; $this->_aMsgs["NOCODE"]["default"] = "Could not create the output code to run your report. Please check if the webserver user have rights to write in your %s directory."; $this->_aMsgs["NOXML"]["default"] = "Could not find the XML file with your data (%s) to run your report. Please check the filename and if the webserver user have rights to write in your temporary directory."; $this->_aMsgs["NOXMLSET"]["default"] = "The XML input file %s was not found."; $this->_aMsgs["NOXSLTSET"]["default"] = "The XSLT input file %s was not found."; $this->_aMsgs["NOPLUGIN"]["default"] = "There is no %s output plugin (%s)."; $this->_aMsgs["NOLOAD"]["default"] = "Could not find file %s for report loading."; $this->_aMsgs["NOTEMPLATE"]["default"] = "The template file %s was not found."; $this->_aMsgs["INVALIDCON"]["default"] = "Your database connection handle is not valid."; // Brazilian Portuguese messages $this->_aMsgs["OPS"]["pt_BR"] = "OOOOPS, OCORREU UM ERRO AQUI."; $this->_aMsgs["ERROR"]["pt_BR"] = "Essa mensagem de erro foi gerada pelo phpReports."; $this->_aMsgs["NODATA"]["pt_BR"] = "Não foram encontrados dados."; $this->_aMsgs["NOPAGE"]["pt_BR"] = "Não há um elemento PAGE (página) no seu relatório."; $this->_aMsgs["NOIF"]["pt_BR"] = "Não há disponível a interface '%s' para banco de dados."; $this->_aMsgs["REFUSEDCON"]["pt_BR"] = "Conexão recusada."; $this->_aMsgs["QUERYERROR"]["pt_BR"] = "Erro na consulta SQL."; $this->_aMsgs["NOCOLUMNS"]["pt_BR"] = "Não foram retornados colunas de dados na sua consulta."; $this->_aMsgs["PAGEPARSER"]["pt_BR"] = "Não consegui copiar o conversor de páginas para o diretório temporário."; $this->_aMsgs["DYNLINK"]["pt_BR"] = "Foi especificado um link dinâmico mas não existe um elemento COLUMN."; $this->_aMsgs["EXPLINK"]["pt_BR"] = "Foi especificado um link com uma expressão mas não existe um elemento COLUMN."; $this->_aMsgs["NOFIELD"]["pt_BR"] = "Você está tentando recuperar o VALOR de um campo chamado %s, mas ele não existe na sua consulta. Por favor revise sua consulta."; $this->_aMsgs["NOFIELDSUM"]["pt_BR"] = "Você está tentando recuperar a SOMA de um campo chamado %s, mas ele não existe na sua consulta. Por favor revise sua consulta."; $this->_aMsgs["NOFIELDMAX"]["pt_BR"] = "Você está tentando recuperar o VALOR MÁXIMO de um campo chamado %s, mas ele não existe na sua consulta. Por favor revise sua consulta."; $this->_aMsgs["NOFIELDMIN"]["pt_BR"] = "Você está tentando recuperar o VALOR MÍNIMO de um campo chamado %s, mas ele não existe na sua consulta. Por favor revise sua consulta."; $this->_aMsgs["NOFIELDAVG"]["pt_BR"] = "Você está tentando recuperar o VALOR MÉDIO de um campo chamado %s, mas ele não existe na sua consulta. Por favor revise sua consulta."; $this->_aMsgs["CANTWRITEPAGE"]["pt_BR"] = "Não consegui escrever o arquivo %s no disco. Verifique suas permissões e espaço em disco."; $this->_aMsgs["DYNBOOK"]["pt_BR"] = "Foi especificado um bookmark dinâmico mas não existe um elemento COLUMN."; $this->_aMsgs["EXPBOOK"]["pt_BR"] = "Foi especificado um bookmark com uma expressão mas não existe um elemento COLUMN."; $this->_aMsgs["NOXMLTRANS"]["pt_BR"] = "O parâmetro %s de COL não foi encontrado na tradução para XML."; $this->_aMsgs["NOXSLT"]["pt_BR"] = "Não há um processador XSLT disponível. Verifique se você compilou o PHP com --enable-xslt e a library Sablotron (para o PHP4) ou com --enable-xsl (para o PHP5)."; $this->_aMsgs["NOPATH"]["pt_BR"] = "Parece que você não especificou o path do phpReports com o comando include_path ou no php.ini. Não sei onde as classes estão."; $this->_aMsgs["NOCODE"]["pt_BR"] = "Não pude criar o código de saída para rodar seu relatório. Por favor verifique se o usuário do servidor web tem direitos para escrever no diretório %s."; $this->_aMsgs["NOXML"]["pt_BR"] = "Não pude encontrar o arquivo XML com seus dados (%s) para rodar seu relatório. Por favor verifique o nome do arquivo e se o usuário do servidor web tem direitos de escrita no seu diretório de arquivos temporários."; $this->_aMsgs["NOXMLSET"]["pt_BR"] = "O arquivo XML de entrada %s não foi encontrado."; $this->_aMsgs["NOXSLTSET"]["pt_BR"] = "O arquivo XSLT de entrada %s não foi encontrado."; $this->_aMsgs["NOPLUGIN"]["pt_BR"] = "O plugin de saída %s não existe (%s)."; $this->_aMsgs["NOLOAD"]["pt_BR"] = "Não encontrei o arquivo %s para carregar o relatório."; $this->_aMsgs["NOTEMPLATE"]["pt_BR"] = "O arquivo de template %s não foi encontrado."; $this->_aMsgs["INVALIDCON"]["pt_BR"] = "A variável da conexão com o banco de dados não é válida. %s"; } function showMsg($sMsg_=null,$oParms_=null){ if(!sMsg_) return; if($_SESSION["phpReportsLanguage"]) $sLang = $_SESSION["phpReportsLanguage"]; else $sLang = $GLOBALS["phpReportsLanguage"]; if(!$sLang) $sLang = "default"; $sTitle = $this->_aMsgs["OPS"][$sLang]; $sError = $this->_aMsgs["ERROR"][$sLang]; $sMsg = $this->_aMsgs[$sMsg_][$sLang]; // if the message have no translation if(!$sMsg) $sMsg = $this->_aMsgs[$sMsg_]["default"]; // if the message is still null ... if(!$sMsg) $sMsg = "$sMsg_?"; if($oParms_) $sMsg = vsprintf($sMsg,$oParms_); print "

    "; print "$sTitle

    "; print "$sMsg

    "; print "$sError"; print "

    "; exit(); } } function isNumericType($sType=null){ $sStr = "NUMBER,NUMERIC,INT,DOUBLE,DECIMAL,REAL,TINY,SHORT,LONG,FLOAT,LONGLONG,INT24,YEAR,CID,FLOAT4,FLOAT8,INT2,". "INT4,MONEY,OID,RELTIME,XID,DOUBLE PRECISION,SMALLINT,TINYINT,BIGINT,INT64,INT8,DATE,DATETIME"; return stristr($sStr,$sType); } ?> phpreports-0.4.9/PHPReport.xsd0000755000175000017500000001662510527055374014740 0ustar fikefike PHPReports validation schema phpreports-0.4.9/README0000755000175000017500000000036510442102130013222 0ustar fikefikePHPReports is an easy way to use PHP and XML to create reports. The main purpose is see the report on a web browser, but you can run it as a command line script to make the reports. You can find more info on http://phpreports.sourceforge.net phpreports-0.4.9/sabtest.xml0000755000175000017500000000021610442102130014524 0ustar fikefike Congratulations! Sablotron is working properly. phpreports-0.4.9/sales.css0000755000175000017500000000151310442102130014157 0ustar fikefike.HEADER { font-family: "arial","verdana"; font-size: 10px; color: #505050; background: #DDDDDD; } .FOOTER { font-family: "arial","verdana"; font-size: 10px; color: #505050; background: #CCCCCC; } .FIELDS { font-family: "arial","verdana"; font-size: 10px; color: #000000; background: #FEFEFE; } .EVEN { font-family: "arial","verdana"; font-size: 10px; color: #000000; background: #95CDED; } .ODD { font-family: "arial","verdana"; font-size: 10px; color: #000000; background: #BDDFF3; } .BOLD { font-weight: bold; } .BOLDRED { color: #FF0000; font-weight: bold; } .PHPREPORTS_PAGE_CELL { font-family:"verdana","arial"; font-size:12px; color:#000000; } .PHPREPORTS_PAGE_LINK { font-family:"verdana","arial"; font-size:12px; color:#000000; } .PHPREPORTS_PAGE_LINK_BOLD { font-size:16px; font-weight:bold; } phpreports-0.4.9/sales.php0000755000175000017500000000124310446274620014200 0ustar fikefikesetUser("taq"); $oRpt->setPassword("******"); $oRpt->setXML("sales.xml"); $oOut = $oRpt->createOutputPlugin("default"); $oRpt->setOutputPlugin($oOut); $oRpt->run(); ?> phpreports-0.4.9/sales.sql0000755000175000017500000000222610530565450014210 0ustar fikefikecreate table if not exists sales ( id int(5), name varchar(50), city varchar(50), type varchar(10), item varchar(50), value decimal(15,2) ); insert into sales values (1,"Eustaquio Rangel","Sao Jose do Rio Preto, SP","Book","Linux Programming",25); insert into sales values (1,"Eustaquio Rangel","Sao Jose do Rio Preto, SP","Book","Design Patterns",35); insert into sales values (1,"Eustaquio Rangel","Sao Jose do Rio Preto, SP","CD","Primus - Antipop",12); insert into sales values (1,"Eustaquio Rangel","Sao Jose do Rio Preto, SP","CD","Machine Head - Elegies",12); insert into sales values (1,"Eustaquio Rangel","Sao Jose do Rio Preto, SP","DVD","V for Vendetta",20); insert into sales values (2,"Ana Carolina" ,"Sao Jose do Rio Preto, SP","Book","Photoshop",22.5); insert into sales values (2,"Ana Carolina" ,"Sao Jose do Rio Preto, SP","Book","Learning Ubuntu Linux",15); insert into sales values (2,"Ana Carolina" ,"Sao Jose do Rio Preto, SP","CD","Ramones - Loco Live",12); insert into sales values (3,"Andre Kada" ,"Sao Paulo, SP","CD","Kreator - Violent Revolutions",15); insert into sales values (3,"Andre Kada" ,"Sao Paulo, SP","CD","Kreator - Enemy of God",15); phpreports-0.4.9/sales.xml0000755000175000017500000001050310446000030014166 0ustar fikefike Sales Report #FFFFFF sales.css select CITY,NAME,TYPE,ITEM,VALUE from sales order by CITY,NAME,TYPE,ITEM localhost mysql phpreports No data was found, check your query
    GRAND TOTAL $this->getSum("VALUE")
    JOHN DOE ENTERPRISES powered by
    phpreports
    SALES REPORT

    page total $this->getSum("VALUE") "page number ".$this->getPageNum()
    http://www.whatisacity.comcity: $this->getValue("CITY")$this->getValue("CITY")
    "total of ".$this->getValue("CITY") $this->getSum("VALUE")
    customer: "http://localhost/getcustomerinfo.php?name=".$this->getValue("NAME")$this->getValue("NAME") type title $
    TYPE ITEM VALUE
    "total of ".$this->getValue("NAME") $this->getSum("VALUE") ($this->getSum("VALUE")>200?"*** Free shipping bonus!***":"Regular shipping charging")
    phpreports-0.4.9/template.php0000755000175000017500000000357610446274632014722 0ustar fikefike". "from". "\$this->getParameter('from')". "". "". "till". "\$this->getParameter('till')". ""; $sGroup = "". "
    ". "\$this->getValue('city')". "
    ". "". "". "name". "type". "item". "value". "". "". "
    ". "". "total". "\$this->getSum('value')". "". "
    ". "
    "; $sDoc = "". "
    ". "". "GRAND TOTAL". "\$this->getSum('value')". "". "
    ". "
    "; $oRpt = new PHPReportMaker(); $oRpt->setUser("taq"); $oRpt->setPassword("******"); $oRpt->setSQL("select * from sales order by city,name"); $oRpt->setDatabaseInterface("mysql"); $oRpt->setDatabase("phpreports"); $oRpt->setParameters(array("from"=>"today","till"=>"tomorrow")); $oRpt->createFromTemplate("Template report","template.xml",$sParms,$sDoc,$sGroup); $oRpt->run(); ?> phpreports-0.4.9/template.xml0000755000175000017500000000241610446026230014710 0ustar fikefike <REPLACE_WITH_TITLE/> #FFFFFF sales.css No data was found, check your query
    JOHN DOE ENTERPRISES powered by
    phpreports

    "page number ".$this->getPageNum()
    phpreports-0.4.9/THANKS0000755000175000017500000000062710442102130013256 0ustar fikefikeMany people further contributed to PHPReports by reporting problems, suggesting various improvements or submitting actual code. You know who you are! Thank you so much! :-) I'd like to thank my wife and my daughter for their patience on the hours I spend at home with this project. Thanks girls! :-) Also a big thanks to all the people that create, maintain and use free software on all whole the world. phpreports-0.4.9/xslt/0000755000175000017500000000000010630304366013343 5ustar fikefikephpreports-0.4.9/xslt/sabtest.xsl0000755000175000017500000000054410442102130015530 0ustar fikefike   phpreports-0.4.9/xslt/PHPReportXHTML.xsl0000755000175000017500000000323410442102130016522 0ustar fikefike // inserting here the XHTML element ... $oCol->setExpr( " "); < > </ > =\" \" phpreports-0.4.9/xslt/PHPReportLink.xsl0000755000175000017500000000241710442102130016525 0ustar fikefike // link here $oLink = new PHPReportLink(); $oLink->setType (""); $oLink->setTitle (""); $oLink->setTarget(""); $oLink->setExpr( "return $ \$ " \" ;" " " ); $oCol->addLink($oLink); phpreports-0.4.9/xslt/PHPReportUtil.xsl0000755000175000017500000000131410442102130016540 0ustar fikefike phpreports-0.4.9/xslt/PHPReportGroup.xsl0000755000175000017500000000430510442102130016722 0ustar fikefike gn_ gn_ // creating a new group here ... $oGrp_=new PHPReportGroup(""); $oGrp_->setReport($oReport); $oGrp_->setFields($oFields); $oGrp_->setPageBreak(""); $oGrp_->setBreakExpr(""); $oGrp_->setReprintHeader(""); $oGrp_->setResetSuppress(""); $oGrp_->setDebug(""); $oGroup =& $oGrp_; $oGrpMain_ =& $oGrp_; $oGrp_->addChild(&$oGrp_); phpreports-0.4.9/xslt/PHPReportImg.xsl0000755000175000017500000000104310442102130016336 0ustar fikefike // image here $oImg = new PHPReportImg(); $oImg->setURL(""); $oImg->setWidth(); $oImg->setHeight(); $oImg->setBorder(); $oImg->setAlt(""); $oCol->addImg($oImg); phpreports-0.4.9/xslt/PHPReportFooter.xsl0000755000175000017500000000147610442102130017072 0ustar fikefike gn_ $oFooter = Array(); $oDoc->setFooter($oFooter); $oPage->setFooter($oFooter); $oGrp_->setFooter($oFooter); phpreports-0.4.9/xslt/PHPReportPreview.xsl0000755000175000017500000001606210442102130017252 0ustar fikefike <xsl:value-of select="TITLE"/>
    [link] [bookmark]
    phpreports-0.4.9/xslt/PHPReportPage.xsl0000755000175000017500000000317110442102130016502 0ustar fikefike // inserting here the page element ... $oPage = new PHPReportPage($sXMLOutputFile); $oPage->setReport(&$oReport); $oPage->setLimit($oReport->getMaxRowBuffer()); // page attributes $oPage->setClass(); $oPage->setSize(); $oPage->setWidth(); $oPage->setHeight(); $oPage->setCellPadding(); $oPage->setCellSpacing(); $oPage->setBorder(); $oPage->setAlign(); $oPage->setDebug(""); $oGroup =& $oPage; $oReport->setPage($oPage); phpreports-0.4.9/xslt/PHPReportBookmark.xsl0000755000175000017500000000244110442102130017372 0ustar fikefike // bookmark here $oBm = new PHPReportBookmark(); $oBm->setType (""); $oBm->setCellClass(""); $oBm->setTextClass(""); $oBm->setExpr( "return $ \$ " \" ;" " " ); $oCol->addBookmark($oBm); phpreports-0.4.9/xslt/PHPReportCol.xsl0000755000175000017500000001606410527056154016372 0ustar fikefike // creating a new command here $oCmd=new PHPReportCol(); $oCmd->setType("CMD"); $oCmd->setExpr( "return $ \$ " \" ;" ); $oCmd->setGroup(&$oGroup); $oRow->addCol(&$oCmd); // creating a new column here - column of $oCol=new PHPReportCol(); $oCol->setType(""); $oCol->addParm(new PHPReportColParm("","")); $oCol->suppress(""); $oCol->setNumberFormat(""); $oCol->setNumberFormatEx(); $oCol->setEvenClass(""); $oCol->setOddClass(""); $oCol->setOnClick(""); $oCol->setOnMouseOver(""); $oCol->setOnMouseOut(""); $oCol->setCellClassExpr( "return $ \$ " \" ;" ); $oCol->setExpr( "return $ \$ " \" ;" " " ); $oCol->setGroup(&$oGroup); $oRow->addCol(&$oCol); phpreports-0.4.9/xslt/PHPReportHeader.xsl0000755000175000017500000000147610442102130017024 0ustar fikefike gn_ $oHeader = Array(); $oDoc->setHeader($oHeader); $oPage->setHeader($oHeader); $oGrp_->setHeader($oHeader); phpreports-0.4.9/xslt/PHPReportForm.xsl0000755000175000017500000000146610442102130016536 0ustar fikefike // create the report form element here ... $oForm=new PHPReportForm(); $oReport->setForm($oForm); $oForm->setName(" "); $oForm->setMethod(" "); $oForm->setAction(" "); phpreports-0.4.9/xslt/PHPReportRow.xsl0000755000175000017500000000127210442102130016375 0ustar fikefike // adding a new row ... $oRow = new PHPReportRow(); array_push($oHeader,$oRow); array_push($oFooter,$oRow); array_push($oFieldRows,$oRow); // unknow element: phpreports-0.4.9/xslt/PHPReport.xsl0000755000175000017500000000504610530375670015733 0ustar fikefike <?php class { // An array to store the benchmarks var $_aBench; // And a function to return it function getBenchmarks(){ return $this->_aBench; } // A pre-existing database connection to use instead of connecting // to the database ourselves var $_oCon = NULL; var $_oQuery = NULL; var $_oFilters = NULL; function setDatabaseConnection(&$_oCon){ $this->_oCon =& $_oCon; } function setQuery(&$_oQuery){ $this->_oQuery =& $_oQuery; } function setInputFilters(&$_oFilters){ $this->_oFilters =& $_oFilters; } function run($sXMLOutputFile=null,$aEnv_=null) { $sPath = getPHPReportsFilePath(); if(is_null($sPath)) exit("I can't find the paths needed to run. Please refer to the PDF manual to see how to set it."); include_once $sPath."/php/PHPReportEvent.php"; include_once $sPath."/php/PHPReportRpt.php"; include_once $sPath."/php/PHPReportXMLElement.php"; include_once $sPath."/php/PHPReportForm.php"; include_once $sPath."/php/PHPReportRow.php"; include_once $sPath."/php/PHPReportColParm.php"; include_once $sPath."/php/PHPReportLink.php"; include_once $sPath."/php/PHPReportBookmark.php"; include_once $sPath."/php/PHPReportImg.php"; include_once $sPath."/php/PHPReportCol.php"; include_once $sPath."/php/PHPReportField.php"; include_once $sPath."/php/PHPReportGroup.php"; include_once $sPath."/php/PHPReportPage.php"; return $oPage->getFileName(); } } ?> phpreports-0.4.9/xslt/PHPReportRpt.xsl0000755000175000017500000002305510530401062016402 0ustar fikefike $oReport = new PHPReportRpt($aEnv_); $oReport->setMarginWidth( ); $oReport->setMarginHeight( ); $oReport->setMaxRowBuffer( ); // create a default error object for translation, if needed $oError = new PHPReportsErrorTr(); // create a default page element $oPage = null; // document layer $oDoc = new PHPReportGroup("DOCUMENT LAYER"); $oDoc->setFields($oFields); $oDoc->setReport(&$oReport); $oGroup =& $oDoc; // if there is a form if($oForm) $oDoc->setForm($oForm); // there must be a PAGE element here if(is_null($oPage)) $oError->showMsg("NOPAGE"); // if dinamically defined the page size (this overrides the XML value) ... $oPage->setSize(); $oPage->setFields($oFields); $oPage->setGroups(&$oGrpMain_); $oDoc->setReport($oReport); $oDoc->addChild($oGrpMain_); $oPage->setDocument(&$oDoc); $oPage->eventHandler(REPORT_OPEN); $oDoc->eventHandler(REPORT_OPEN); $bFound=false; $this->_aBench["output_start"] = time(); // looping on the sql result here ... while($aResult=PHPReportsDBI::db_fetch($oStmt)) { $bFound=true; $oPage->eventHandler(PUT_DATA,$aResult); $oDoc->eventHandler(PROCESS_DATA,$aResult); } $oDoc->eventHandler(REPORT_CLOSE); $oPage->eventHandler(REPORT_CLOSE); PHPReportsDBI::db_free($oStmt); PHPReportsDBI::db_disconnect($oCon); // no data found if(!$bFound){ if(strlen($sNoDataFoundFunc)>0) eval($sNoDataFoundFunc.";"); else{ if(strlen($sNoDataFoundMsg)>0) new PHPReportsError(strlen($sNoDataFoundMsg)>0?$sNoDataFoundMsg:"NO DATA FOUND"); else $oError->showMsg("NODATA"); } } $oReport->setTitle(" "); $oReport->setPath(" "); $oReport->setBackgroundColor(" "); $oReport->setBackgroundImage(" "); $oReport->addCSS(" " ,"" ); $oReport->setBookmarksCSS(" "); // connecting to the database $sSQL = ""; $sUser = ""; $sPass = ""; $sConn = ""; $sData = ""; $sIf = ""; $sSQL = ""; $sUser = ""; $sPass = ""; $sConn = ""; $sData = ""; $sIf = ""; // include the database interface file $sIfFile = realpath($sPath."/database/db_".$sIf.".php"); if(!file_exists($sIfFile)) $oError->showMsg("NOIF",$sIf); include_once $sIfFile; // open database connection if(is_null($this->_oCon)) $oCon = @PHPReportsDBI::db_connect(Array($sUser,$sPass,$sConn,$sData)) or $oError->showMsg("REFUSEDCON"); else $oCon = $this->_oCon; if(!is_resource($oCon)) $oError->showMsg("INVALIDCON"); // input filters if($this->_oFilters){ foreach($this->_oFilters as $oFilter){ $oFilter->setConnection($oCon); $oFilter->setSQL(trim($sSQL)); $sSQL = trim($oFilter->run()); } } $this->_aBench["sql_start"] = time(); if(is_null($this->_oQuery)) $oStmt = @PHPReportsDBI::db_query($oCon,trim($sSQL)) or $oError->showMsg("QUERYERROR"); else $oStmt = $this->_oQuery; $this->_aBench["sql_end"] = time(); // get info about the fields $oFields = Array(); $iColNum = @PHPReportsDBI::db_colnum($oStmt); // if no columns were returned, weird! if($iColNum<=0){ @PHPReportsDBI::db_free($oStmt); $oError->showMsg("NOCOLUMNS"); } for($i=1;$i<=$iColNum;$i++) $oFields[PHPReportsDBI::db_columnName($oStmt,$i)]=new PHPReportField(PHPReportsDBI::db_columnName($oStmt,$i),PHPReportsDBI::db_columnType($oStmt,$i)); $oParameters = Array(); $oParameters[0] = null; // nothing here $oParameters[]=""; $oParameters[]=""; $oParameters[]=""; $oParameters[]=""; $oParameters[]=""; $oParameters[]=""; $oParameters[]=""; $oParameters[]=""; $oParameters[]=""; $oParameters[]=""; $oReport->setParameters($oParameters); // no data found message $sNoDataFoundMsg=""; $sNoDataFoundMsg=""; // no data found function $sNoDataFoundFunc=""; $sNoDataFoundFunc=""; phpreports-0.4.9/xslt/PHPReportFields.xsl0000755000175000017500000000121310442102130017027 0ustar fikefike gn_ // here starts the sql fields rows ... $oFieldRows = Array(); $oGrp_->setFieldRows($oFieldRows); phpreports-0.4.9/xslt/xsltest.xsl0000755000175000017500000000054410442102130015571 0ustar fikefike   phpreports-0.4.9/xsltest.py0000755000175000017500000000043110442102130014414 0ustar fikefikeimport libxml2 import libxslt styledoc = libxml2.parseFile("xslt/xsltest.xsl") style = libxslt.parseStylesheetDoc(styledoc) doc = libxml2.parseFile("xsltest.xml") result = style.applyStylesheet(doc, None) print result.content style.freeStylesheet() doc.freeDoc() result.freeDoc() phpreports-0.4.9/xsltest.xml0000755000175000017500000000021010442102130014557 0ustar fikefike Congratulations! XSL is working properly.