codeigniter - convert html to pdf - html

I have a little problem. I have html page and I want to convert to pdf. My index page has a list that will get to the database and click on "Download PDF", I put this list in a PDF file.
My controller:
<?php
class pdf_c extends CI_Controller{
function __construct() {
parent::__construct();
$this->load->helper(array('url', 'mediatutorialpdf'));
}
function index($download_pdf = ''){
$ret = '';
$ID = 1;
$pdf_filename = 'user_info_'.$ID.'.pdf';
$link_download = ($download_pdf == TRUE)?'':anchor(base_url().'index.php/true', 'Download PDF');
$query = $this->db->query("SELECT * FROM `ci_pdf_user` WHERE `id` = '{$ID}' LIMIT 1");
if($query->num_rows() > 0)
{
$user_info = $query->row_array();
}
$data_header = array(
'title' => 'Convert codeigniter to pdf'
);
$data_userinfo = array(
'user_info' => $user_info,
'link_download' => $link_download
);
$header = $this->load->view('header',$data_header, true);
$user_info = $this->load->view('user_table', $data_userinfo, true);
$footer = $this->load->view('footer','', true);
$output = $header.$user_info.$footer;
if($download_pdf == TRUE)
{
generate_pdf($output, $pdf_filename);
}
else
{
echo $output;
}
}
}
?>
The problem is when I click the button "Download PDF" should redirect me to the function index () and get the $ download_pdf = true. And so called generate_pdf function () that will generate the PDF.
I think the problem is in the variable $ link_download, but can not solve the problem.
Thanks

I think that you could try with:
function index(pdf = 0)...
Then check that optional parameter with:
$pdf = $this->uri->segment(2, 0); //not sure, should be 2? try it...`
And then, if $pdf=='1' (send nummber rather than string 'true') ...etc,etc...

Related

MediaWiki - Hook to edit/alter page title on creation

I'm looking to (programmatically) edit/alter the title of a page when its created and before its saved. I've tried a couple hooks to no avail. I can access the title being saved along with other info which ill be used to alter the title, but can not find the right call to save the altered title.
It is for a private/local lan wiki (currently MediaWiki version 1.38.1 ).
When a new article is created with in a certon category I want to number it with a prefix of #### - based on the number of articles already in the category. At the top of the category page itself I have a <inputbox> which pulls a template that has the wiki syntax for the category in it [[Category:BlaBla]]. When the article is saved I'm doing a check to make sure its a new article and some ofther checks for the info I need, which is working fine, but I can not save the new altered page name.
I've tried the following hooks to no avail.
onMultiContentSave
onArticlePrepareTextForEdit
https://www.mediawiki.org/wiki/Manual:Hooks/MultiContentSave
https://www.mediawiki.org/wiki/Manual:Hooks/ArticlePrepareTextForEdit
Heres acouple snippets ive been testing with, both do as i want, aside from saving the altered page name.
public static function onArticlePrepareTextForEdit( WikiPage $wikiPage, ParserOptions $parserOptions ) {
return;
$exists = $wikiPage->exists();
if ($exists == 1) {
#return true;
}
$getTitle = $wikiPage->getTitle();
# check if title starts with 0000, exit if so, no work needs to be done
if (self::titleCheck($getTitle)) {
#return true;
}
$checkCategories = $wikiPage->getCategories();
$inMalak = false;
foreach ($checkCategories as $value) {
if ($value == "Category:Malak") {
$inMalak = true;
}
}
if ($inMalak == 1) {
$newTitle = self::newTitlePre() . $getTitle;
#$wikiPage->setTitle($newTitle);
print(">" . $newTitle . "<br>");
}
self::pr($newTitle);
}
public static function onMultiContentSave(RenderedRevision $renderedRevision, UserIdentity $user, CommentStoreComment $summary, $flags, Status $hookStatus){
#return;
$revision = $renderedRevision->getRevision();
$getTitle = $revision->getPageAsLinkTarget();
if (self::titleCheck($getTitle)) {
return true;
}
#$titleOBJ = $revision->Title();
$title = $revision->getId();
$parent_id = $revision->getId();
$content = $revision->getContent( SlotRecord::MAIN );
$new_content = $content->getText();
#$test = $revision->ParserOutput();
$parent_id = "";
if ($parent_id == "") {
$pos = strpos($new_content, "[[Category:Malak]]");
if ($pos) {
$newTitle = self::newTitlePre() . $getTitle;
#$wikiPage->setTitle($newTitle);
}
}
self::pr($newTitle);
}
EDIT........
Still have not found the proper way to do this, but came up with a work around (hackery) which works for my needs.
Using the onEditFormPreloadText hook, change the url and added a new parameter ('MalakHere'), edited the 'title' parameter to the altered title, then do a redirect with the new page name. In the hook function there is a check for the 'MalakHere' parameter, if found (only cause of redirect) then it will exit the function so not to create a loop.
public static function onEditFormPreloadText(string &$text, Title &$title ) {
global $wgOut;
if ( isset( $_GET["MalakHere"] ) ) {
return true;
}
$pos = strpos($text, "[[Category:Malak]]");
if ($pos) {
$url = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
$urlTitle = urlencode($_GET["title"]);
$newURL = str_replace("title=" . $urlTitle,"MalakHere=yes",$url);
$newTitle = self::newTitlePre() . $title->prefixedText;
$url = $newURL . "&title=" . $newTitle;
return $wgOut->redirect($url);
}
return true;
}
Still have not found the proper way to do this, but came up with a work around (hackery) which works for my needs.
Using the onEditFormPreloadText hook, change the url and added a new parameter ('MalakHere'), edited the 'title' parameter to the altered title, then do a redirect with the new page name. In the hook function there is a check for the 'MalakHere' parameter, if found (only cause of redirect) then it will exit the function so not to create a loop.
public static function onEditFormPreloadText(string &$text, Title &$title ) {
global $wgOut;
if ( isset( $_GET["MalakHere"] ) ) {
return true;
}
$pos = strpos($text, "[[Category:Malak]]");
if ($pos) {
$url = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
$urlTitle = urlencode($_GET["title"]);
$newURL = str_replace("title=" . $urlTitle,"MalakHere=yes",$url);
$newTitle = self::newTitlePre() . $title->prefixedText;
$url = $newURL . "&title=" . $newTitle;
return $wgOut->redirect($url);
}
return true;
}

Yii2 ActiveRecord add a new record with unique text field

I am using Yii2 and ActiveRecord. I have a field called "code" and for each record, it is meant to have a unique value like this: "REC0001", "REC0002", "REC0003" in a sequencial manner.
All works and I can generate a record code as described. However if I refresh my page request fast in a multiple manner (trying to test multiple requests at the same time in a very raw manner hehe), then some of the records end up with the same record code. In other words I found "REC007" a few times.
I generate the code looking at the last code and increase it by one, then I do a while foundFlag == true by checking to see if it already exists in the database.
I am suspecting there is a delay in writing to the database and hence it assumes that it is not there.
Here is a portion of the code:
static function createCode($rec){
if ($rec->code){
return $rec->code;
}
if ($rec->id){ // find it by id if one passed and record exists
$tmpRec = $rec->find()
->where([
'id' => $rec->id,
])
->one();
if ($tmpRec && $tmpRec->code){
return $tmpRec->code;
}
}
$prefix = 'REC';
if (!$prefix){
$prefix = 'REC';
}
$maxDecimals = 12;
$codeLength = $maxDecimals+strlen($prefix);
$query = $rec->find();
$query = $query->where([
'archived' => '0'
]);
// look under an organization if it exists in the model and there is one
if ($rec->hasField('organization_id') && $organization_id){
$query = addQueryWhere($query, [
'organization_id' => $organization_id,
]);
}
$query = addQueryWhere($query, [
'LENGTH(code)' => $codeLength*1,
]);
$query = $query->orderBy('code desc');
$lastRec = $query->one();
$tmpNumber = 0;
if ($lastRec && $lastRec->id){
// check what it returns
$tmpNumber = str_replace($prefix, '', $lastRec->code);
}
$tmpNumber++;
$leftDecimals = $maxDecimals - strlen($tmpNumber.'');
for ($k=0; $k <= $leftDecimals-1 ; $k++){
$tmpNumber = '0'. $tmpNumber;
}
$ret = $prefix . $tmpNumber;
return $ret;
}
public function generateCode($rec){
$foundFlag = true;
$break = 1000; // safe break point - no continuous loop
$cnt = 0;
$code = static::createCode($rec);
while ($foundFlag === true || $cnt < $break){
$tmpRec = $rec->find()
->where([
'code' => $code,
])
->one();
if (!$tmpRec->id){
$foundFlag = false;
break;
}
$time = getCurrentTimestamp();
$code = static::createCode($rec);
$cnt++;
}
$ret = $code;
return $ret;
}
So I simply call: $this->code = $this->generateCode();
Like I said it does work in generating the code, but it creates duplicates when it shouldn't!
Thank you for your assistance.

Memory Efficient reading + writing of .csv and .xlsx data

I am looking to implement memory efficient reading and writing of .xlsx/.csv files.
I am currently using phpExcel and am having trouble with large files. (Known issue)
I found the following library for reading: https://github.com/nuovo/spreadsheet-reader
This seems that it will work.
For writing files currently I create an array and then loop the array to output the file. Is this why it uses a lot of memory? What is the best way to not use a lot of memory when writing csv/xlsx when getting data from mysql database using code igniter?
This is what I do now:
/* added for excel expert */
function excel_export() {
$data = $this->Customer->get_all($this->Customer->count_all())->result_object();
$this->load->helper('report');
$rows = array();
$header_row = $this->_excel_get_header_row();
$header_row[] = lang('customers_customer_id');
$rows[] = $header_row;
foreach ($data as $r) {
$row = array(
$r->first_name,
$r->last_name,
$r->email,
$r->phone_number,
$r->address_1,
$r->address_2,
$r->city,
$r->state,
$r->zip,
$r->country,
$r->comments,
$r->account_number,
$r->taxable ? 'y' : '',
$r->company_name,
$r->person_id
);
$rows[] = $row;
}
$content = array_to_spreadsheet($rows);
force_download('customers_export.'.($this->config->item('spreadsheet_format') == 'XLSX' ? 'xlsx' : 'csv'), $content);
exit;
}
function array_to_spreadsheet($arr)
{
$CI =& get_instance();
$objPHPExcel = new PHPExcel();
//Default all cells to text
$objPHPExcel->getDefaultStyle()->getNumberFormat()->setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_TEXT);
for($k = 0;$k < count($arr);$k++)
{
for($j = 0;$j < count($arr[$k]); $j++)
{
$objPHPExcel->getActiveSheet()->setCellValueExplicitByColumnAndRow($j, $k+1, $arr[$k][$j]);
}
}
if ($CI->config->item('spreadsheet_format') == 'XLSX')
{
$objWriter = new PHPExcel_Writer_Excel2007($objPHPExcel);
}
else
{
$objWriter = new PHPExcel_Writer_CSV($objPHPExcel);
}
ob_start();
$objWriter->save('php://output');
$excelOutput = ob_get_clean();
return $excelOutput;
}

No data from the database after the files downloaded

I want to display the data on a particular condition of the table after the user enters the data you want to display.
But always failed to display the data. I am confused where the fault lies.
It looks like the variable $thn = $ _POST['thn'], $bln = $ _POST['bln'], $periode = $ _POST['periode'] is empty.
please help.
I have four files.
Here the codes:
1.absen_xls.php:
<?php
include '../../inc/inc.koneksi.php';
ini_set('display_errors', 1); ini_set('error_reporting', E_ERROR);
include '../../excel/PHPExcel.php';
include '../../excel/PHPExcel/IOFactory.php';
$table = 'absen_karyawan';
$bln = $_POST['bln']; //this not work, I don't know why?
$thn = $_POST['thn']; //this not work, I don't know why?
$periode = $_POST['periode']; //this not work, I don't know why?
$where = "WHERE tahun = '$thn' AND bulan = '$bln' AND periode = '$periode'";
// Create new PHPExcel object
$objPHPExcel = new PHPExcel();
$sql = "SELECT namakaryawan,tahun,bulan,periode,absen FROM $table $where";
$query = mysql_query($sql);
// bold
$objPHPExcel->getActiveSheet()->getStyle("A2:C2")->applyFromArray(array("font" => array( "bold" => true)));
// Add some data
$objPHPExcel->setActiveSheetIndex(0)
->setCellValue('A2', 'No')
->setCellValue('B2', 'Nama')
->setCellValue('C2', 'Kehadiran');
$baris = 3;
$no = 0;
while($row=mysql_fetch_array($query)){
$no = $no +1;
$objPHPExcel->setActiveSheetIndex(0)
->setCellValue("A$baris", $no)
->setCellValue("B$baris", $row['namakaryawan'])
->setCellValue("C$baris", $row['absen']);
$baris = $baris + 1;
}
//border
$border = $baris - 1;
$styleArray = array(
'borders' => array(
'allborders' => array(
'style' => PHPExcel_Style_Border::BORDER_THIN
)
)
);
$objPHPExcel->getActiveSheet()->getStyle('A2:C'.$border)->applyFromArray($styleArray);
unset($styleArray);
//width
$objPHPExcel->getActiveSheet()->getColumnDimension("A")->setWidth(5);
$objPHPExcel->getActiveSheet()->getColumnDimension("B")->setWidth(20);
$objPHPExcel->getActiveSheet()->getColumnDimension("C")->setWidth(15);
//align center
$objPHPExcel->getActiveSheet()->getStyle('A2:C'.$border)->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
// Rename sheet
$objPHPExcel->getActiveSheet()->setTitle('Absen');
// Set active sheet index to the first sheet, so Excel opens this as the first sheet
$objPHPExcel->setActiveSheetIndex(0);
// Redirect output to a client’s web browser (Excel5)
header('Content-Type: application/vnd.ms-excelformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename="absen.xlsx"');
header('Cache-Control: max-age=0');
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
$objWriter->save('php://output');
exit;
?>
2.ajax.php:
// JavaScript Document
$(document).ready(function(){
$(function(){
$('button').hover(
function() { $(this).addClass('ui-state-hover'); },
function() { $(this).removeClass('ui-state-hover'); }
);
});
$("#tampil_data").load('modul/lap-absen/tampil_data.php');
$("#print").click(function(){
var thn = $("#thn").val();
var bln = $("#bln").val();
var periode = $("#periode").val();
cetakabsen(thn,bln,periode);
});
function cetakabsen(c1,c2,c3){
var thn = c1;
var bln = c2;
var periode = c3;
$.ajax({
type : "POST",
url : "modul/lap-absen/absen_xls.php",
data : "thn="+thn+"&bln="+bln+"&periode="+periode,
success : function(data){
window.open('http://localhost/gudang/modul/lap-absen/absen_xls.php');
}
});
}
});
Change your function to this one:
function cetakabsen(c1,c2,c3){
var thn = c1;
var bln = c2;
var periode = c3;
var data = "thn="+thn+"&bln="+bln+"&periode="+periode;
window.open('http://localhost/gudang/modul/lap-absen/absen_xls.php?'+data);
}
And receive your values like this in absen_xls.php:
$bln = mysql_real_escape_string($_GET['bln']);
$thn = mysql_real_escape_string($_GET['thn']);
$periode = mysql_real_escape_string($_GET['periode']);
PS: Go for mysqli or PDO, dont use the mysql extension.

code igniter active records - help streamlining process

I am currently using the below code to get a list of uuid's then split them into groups of 1000, then insert those groups into the database.
This works fine except this has to work on at times, over a million uuid's
The issue is this uses a massive amount of memory, so I need help to streamline this process to use less memory...
public function send_daily_email($dealId) {
set_time_limit(0);
$deal = $this->ci->deal->get($dealId);
if ($deal == false)
throw new exception('Unknown Deal Specified');
$users = $this->db->select('uuid')->from('userRegionLink')->where('regionId', $deal->region)->get();
if ($users->num_rows() == 0)
throw new exception('No users in region');
$message = $this->ci->load->view('emails/daily', array('name' => $deal->title, 'content' => $deal->snippet), true);
$uuids = array();
foreach ($users->result() as $u)
$uuids[] = $u->uuid;
$uuids = array_chunk($uuids, 1000);
$sendId = 0;
foreach ($uuids as $batch) {
$count = count($batch);
$this->db->set('dealId', $dealId)->set('content', $message)->set('regionId', $deal->region)->set('recipients', $count)->set('created', 'NOW()', false)->set('status', 'Creating');
if ($sendId === 0) {
$this->db->insert('dealEmailParent');
$sendId = $this->db->insert_id();
$this->db->set('sendId', $sendId)->where('id', $sendId)->update('dealEmailParent');
}
else
$this->db->set('sendId', $sendId)->insert('dealEmailParent');
$insert = array();
foreach ($batch as $uuid)
$insert[] = array('parentId' => $sendId, 'uuid' => $uuid);
$this->db->insert_batch('dealEmailChild', $insert);
}
}
I hate to say this, but from what I know about CodeIgniter, the only way it knows to fetch results is to fetch the entire resultset at once, even if you only need one row, or even if you want to fetch a row at a time and do some processing. It doesn't operate with cursors as the native mysql(i)/PDO functionality does.
For this large a dataset, I'd suggest sticking to the native PHP database functions and foregoing CodeIgniter's active record database classes.
This reworking can insert 1,000,000 "users" in under a minute without any memory limits :)
public function create_daily_email($dealId)
{
$time_start = microtime(true);
set_time_limit(0);
$deal = $this->ci->deal->get($dealId);
if ($deal == false)
throw new exception('Unknown Deal Specified');
$message = $this->ci->load->view('emails/daily', array('name' => $deal->title, 'content' => $deal->snippet), true);
$start = 0;
$end = 50000;
$q = $this->db->select('uuid')->from('userRegionLink')->where('regionId', $deal->region)->limit($end, $start)->get();
$sendId = 0;
while ($q->num_rows() != 0) {
//do stuff
$uuids = array();
foreach ($q->result() as $u)
$uuids[] = $u->uuid;
$uuids = array_chunk($uuids, 1000);
foreach ($uuids as $batch) {
$count = count($batch);
$this->db->set('dealId', $dealId)->set('content', $message)->set('regionId', $deal->region)->set('recipients', $count)->set('created', 'NOW()', false)->set('status', 'Creating');
if ($sendId === 0) {
$this->db->insert('dealEmailParent');
$sendId = $this->db->insert_id();
$this->db->set('sendId', $sendId)->where('id', $sendId)->update('dealEmailParent');
$parentId = $sendId;
}
else {
$this->db->set('sendId', $sendId)->insert('dealEmailParent');
$parentId = $this->db->insert_id();
}
$insert = array();
foreach ($batch as $uuid) {
$insert[] = array(
'parentId' => $parentId,
'uuid' => $uuid
);
}
$this->db->insert_batch('dealEmailChild', $insert);
}
//stop stuff
unset($q);
unset($uuids);
unset($insert);
$start = $start + $end;
$q = $this->db->select('uuid')->from('userRegionLink')->where('regionId', $deal->region)->limit($end, $start)->get();
}
$this->db->set('status', 'Pending')->where('sendId', $sendId)->update('dealEmailParent');
$time_end = microtime(true);
$time = $time_end - $time_start;
die("Did nothing in $time seconds");
}