1
0
Fork 0
mirror of https://github.com/YunoHost-Apps/limesurvey_ynh.git synced 2024-09-03 19:36:32 +02:00
limesurvey_ynh/sources/application/libraries/admin/quexmlpdf.php

3425 lines
107 KiB
PHP
Raw Normal View History

<?php
/*
* LimeSurvey
* Copyright (C) 2007-2011 The LimeSurvey Project Team / Carsten Schmitz
* All rights reserved.
* License: GNU/GPL License v2 or later, see LICENSE.php
* LimeSurvey is free software. This version may have been modified pursuant
* to the GNU General Public License, and as distributed it includes or
* is derivative of works licensed under the GNU General Public License or
* other free or open source software licenses.
* See COPYRIGHT.php for copyright notices and details.
*
* $Id$
*/
/**
* Modify these two lines to point to your TCPDF installation
* Tested with TCPDF 5.8.008 - see http://www.tcpdf.org/
*/
require('pdf.php');
require_once($tcpdf['base_directory'].'/tcpdf.php');
require_once($tcpdf['base_directory'].'/config/lang/eng.php');
/**
* A TCPDF based class to produce queXF compatible questionnaire PDF files and banding description XML from queXML
*
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @copyright (c) 2010 Australian Consortium for Social and Political Research Incorporated (ACSPRI)
* @since 2010-09-02
* @link http://www.acspri.org.au/software
* @link http://quexml.sourceforge.net
* @link http://quexf.sourceforge.net
*/
class quexmlpdf extends pdf {
/**
* Define an inch in MM
*
* @const float Defaults to 25.4
*/
const INCH_IN_MM = 25.4;
/**
* Language for translation
*/
protected $language = "en";
/**
* Pixels per inch of exported document
*
* @var int Defaults to 300.
*/
protected $ppi = 300;
/**
* Whether a page break has occured
* Should be a private var but crash occurs on PHP 5.1.6, see Limesurvey Bug 5824
* @var bool
*/
protected $pageBreakOccured;
/**
* Corner border (the number of mm between the edge of the page and the start of the document)
*
* @var int Defaults to 15.
* @since 2010-09-02
*/
protected $cornerBorder = 14;
/**
* The length in MM of a corner line
*
* @var mixed Defaults to 20.
* @since 2010-09-20
*/
protected $cornerLength = 20;
/**
* The width in MM of a corner line
*
* @var mixed Defaults to 0.5.
* @since 2010-09-20
*/
protected $cornerWidth = 0.5;
/**
* The TCPDF barcode type
*
* @var bool Defaults to 'I25'.
* @since 2010-09-20
* @see write1DBarcode
*/
protected $barcodeType = 'I25';
/**
* The x position in MM of the barcode
*
* @var bool Defaults to 138.
* @since 2010-09-20
* @deprecated
* @see $barcodeMarginX
*/
//protected $barcodeX = 138;
/**
* The distance between the right hand page border and
* the end of the barcode in MM
*
* @var bool Defaults to 23.
* @since 2011-10-25
*/
protected $barcodeMarginX = 23;
/**
* Y position of barcode in mm
*
* @var bool Defaults to 6.
* @since 2010-09-20
*/
protected $barcodeY = 6;
/**
* Width of the barcode in mm
*
* @var bool Defaults to 49.
* @since 2010-09-20
*/
protected $barcodeW = 49;
/**
* Height of the barcode in mm
*
* @var bool Defaults to 6.
* @since 2010-09-20
*/
protected $barcodeH = 6;
/**
* The questionnaire ID of this form
*
* @var mixed Defaults to 1.
* @since 2010-09-20
*/
protected $questionnaireId = 1;
/**
* The length of a the id portion barcode
*
* @var int Defaults to 6.
* @since 2010-09-20
* @see $pageLength
*/
protected $idLength = 6;
/**
* The length of the page portion of the barcode
*
* @var mixed Defaults to 2.
* @since 2010-09-20
* @see $idLength
*/
protected $pageLength = 2;
/**
* width of the question title column in MM
*
* @var mixed Defaults to 14.
* @since 2010-09-20
*/
protected $questionTitleWidth = 14;
/**
* The suffix of the question title. i.e. A15. (the . is the suffix)
*
* @var mixed Defaults to ".".
* @since 2012-01-31
*/
protected $questionTitleSuffix = ".";
/**
* Width of question text in MM
*
* @var mixed Defaults to 120.
* @since 2010-09-20
* @deprecated
*/
//protected $questionTextWidth = 120;
/**
* Right margin of question text in MM
*
* @var mixed Defaults to 40.
* @since 2012-01-11
* @see $questionTextWidth
*/
protected $questionTextRightMargin = 40;
/**
* Height of the border between questions in MM
*
* @var mixed Defaults to 1.
* @since 2010-09-20
*/
protected $questionBorderBottom = 1;
/**
* Border after a help before directive
*
* @var mixed Defaults to 3.
* @since 2012-01-31
*/
protected $helpBeforeBorderBottom = 3;
/**
* Border before a help before directive
*
* @var mixed Defaults to 3.
* @since 2012-01-31
*/
protected $helpBeforeBorderTop = 3;
/**
* Width of the skip column area (where skip text is written)
*
* @var string Defaults to 20.
* @since 2010-09-20
*/
protected $skipColumnWidth = 20;
/**
* The default style for the text of the questionnaire
*
* @var string Defaults to "<style>td.questionHelp {text-align:right; font-style:italic; font-size: 8pt;} td.responseText {text-align:right; margin-right:1mm;} td.responseAboveText {text-align:left;} td.responseLabel {text-align:center; font-size:8pt;} span.sectionTitle {font-size: 18pt} span.sectionDescription {font-size: 14pt}</style>".
* @since 2010-09-16
*/
protected $style = "<style>
td.questionTitle {font-weight:bold; font-size:12pt;}
td.questionTitleSkipTo {font-weight:bold; font-size:16pt;}
td.questionText {font-weight:bold; font-size:12pt;}
td.questionSpecifier {font-weight:normal; font-size:12pt;}
td.vasLabel {font-weight:bold; font-size:10pt; text-align:center;}
td.questionHelp {font-weight:normal; text-align:right; font-style:italic; font-size:8pt;}
td.questionHelpAfter {text-align:center; font-weight:bold; font-size:10pt;}
td.questionHelpBefore {text-align:center; font-weight:bold; font-size:12pt;}
td.responseAboveText {font-weight:normal; font-style:normal; text-align:left; font-size:12pt;}
td.matrixResponseGroupLabel {font-weight:normal; font-style:normal; text-align:left; font-size:12pt;}
span.sectionTitle {font-size:18pt; font-weight:bold;}
span.sectionDescription {font-size:14pt; font-weight:bold;}
div.sectionInfo {font-style:normal; font-size:10pt; text-align:left; font-weight:normal;}
td.questionnaireInfo {font-size:14pt; text-align:center; font-weight:bold;}
</style>";
/**
* Width of the area of each single response
*
* @var string Defaults to 10.
* @since 2010-09-20
* Height of the area of a single response where displayed horizontally
*
* @var string Defaults to 10.5.
* @since 2011-12-20
*/
protected $singleResponseHorizontalHeight = 10.5;
/**
* The maximum number of lines of text to display
* in a horizontal single response before adding additional space
*
* @var string Defaults to 2.
* @since 2013-05-02
* @see $singleResponseHorizontalHeight
*/
protected $singleResponseHorizontalMaxLines = 2;
/**
* Height of the are of each single response (includes guiding lines)
*
* @var string Defaults to 9.
* @since 2010-09-20
*/
protected $singleResponseAreaHeight = 9;
/**
* Width of a single response box
*
* @var string Defaults to 5.
* @since 2010-09-20
*/
protected $singleResponseBoxWidth = 5;
/**
* Height of a single response box
*
* @var string Defaults to 5.
* @since 2010-09-20
*/
protected $singleResponseBoxHeight = 5;
/**
* Width of a response boxes border
*
* @var string Defaults to 0.1.
* @since 2010-09-20
*/
protected $singleResponseBoxBorder = 0.15;
/**
* Length of the "eye guide" for a vertical response box
*
* @var string Defaults to 1.
* @since 2010-09-20
*/
protected $singleResponseBoxLineLength = 1;
/**
* Vertical area taken up by a response box
*
* @var string Defaults to 15.
* @since 2010-09-20
*/
protected $singleResponseVerticalAreaWidth = 13;
/**
* Vertical area taken up by a "small" vertical response area
*
* @var string Defaults to 9.
* @since 2010-09-20
*/
protected $singleResponseVerticalAreaWidthSmall = 9;
/**
* Maximum number of horizontal boxes to display normally before shrinking horizontal area width
*
* @var int Defaults to 10.
* @since 2010-09-08
*/
protected $singleResponseHorizontalMax = 10;
/**
* Allows all single choice horizontal arrays to be split over multiple pages/columns
* Can override with "split" attribute on "response" in queXML
*
* @var bool Defaults to false.
* @since 2012-08-10
*/
protected $allowSplittingSingleChoiceHorizontal = true;
/**
* Allows all single choice vertical arrays to be split over multiple pages/columns
* Can override with "split" attribute on "response" in queXML
*
* @var bool Defaults to false.
* @since 2013-10-24
*/
protected $allowSplittingSingleChoiceVertical = true;
/**
* If splitting is allowed for single choice vertical, only split if there is at
* least these many categories
*
* @var int Defaults to 5.
* @since 2013-12-13
*/
protected $minSplittingSingleChoiceVertical = 25;
/**
* Allows multiple responses to the same question to be split over multiple pages/columns
* Can override with "split" attribute on "question" in queXML
*
* @var bool Defaults to false.
* @since 2013-10-25
*/
protected $allowSplittingResponses = true;
/**
* Allows vertical matrix texts to be split over multiple pages/columns
* Can override with "split" attribute on "response" in queXML
*
* @var bool Defaults to false.
* @since 2013-10-25
*/
protected $allowSplittingMatrixText = true;
/**
* Allows matrix VAS items to be split over multiple pages/columns
* Can override with "split" attribute on "response" in queXML
*
* @var bool Defaults to false.
* @since 2013-10-25
*/
protected $allowSplittingVas = false;
/**
* The height of an arrow
*
* @var array Defaults to 3.
* @since 2010-09-20
*/
protected $arrowHeight = 3;
/**
* The width of a text response box
*
* @var mixed Defaults to 6.
* @since 2010-09-20
*/
protected $textResponseWidth = 6;
/**
* The border width of a text response box
*
* @var mixed Defaults to 0.15. Any less than this may produce printing problems
* @since 2010-09-20
*/
protected $textResponseBorder = 0.15;
/**
* The height of a text response box
*
* @var mixed Defaults to 8.
* @since 2010-09-20
*/
protected $textResponseHeight = 8;
/**
* The height of a pre-filled response barcode
*
* @var bool Defaults to 6.
* @since 2012-06-22
*/
protected $barcodeResponseHeight = 6;
/**
* The maximum number of text responses per line
*
* @var mixed Defaults to 24.
* @since 2010-09-20
* @deprecated
* @see $textResponseMarginX
*/
//protected $textResponsesPerLine = 24;
/**
* The left hand margin of text responses to auto calculate responses
* per line (mm)
*
* @var mixed Defaults to 13.
* @since 2011-10-25
*/
protected $textResponseMarginX = 13;
/**
* Maximum number of text responses boxes where the label should appear on the same line
*
* @var mixed Defaults to 16.
* @since 2010-09-20
* @deprecated
* @see $labelTextResponsesSameLineMarginX
*/
//protected $labelTextResponsesSameLine = 16;
/**
* The left hand margin of text responses to auto calculated responses
* per line where the label should appear on the same line (mm)
*
* @var mixed Defaults to 62.
* @since 2011-10-25
*/
protected $labelTextResponsesSameLineMarginX = 62;
/**
* The gap between multi line text responses
*
* @var mixed Defaults to 1.
* @since 2010-09-20
*/
protected $textResponseLineSpacing = 1;
/**
* The vertical gap between subquestions in mm
*
* @var string Defaults to 2.
* @since 2010-09-02
*/
protected $subQuestionLineSpacing = 2;
/**
* The multiplier from long text response width specified to the height in mm
*
* @var mixed Defaults to 1.
* @since 2010-09-20
*/
protected $longTextResponseHeightMultiplier = 1;
/**
* Width of a long text response box
*
* @var mixed Defaults to 145.
* @since 2010-09-20
* @deprecated
* @see drawLongText() for the new calculation of long text box width
*/
//protected $longTextResponseWidth = 145;
/**
* Default number of characters to store in a long text field
*
* @var int Default is 1024;
* @since 2010-09-02
*/
protected $longTextStorageWidth = 1024;
/**
* The number of columns to display the sections/questions in on each page
*
* @var int Defaults to 1.
* @since 2012-05-30
*/
protected $columns = 1;
/**
* The width of the border between columns
*
* @var int Defaults to 1.
* @since 2012-05-31
*/
protected $columnBorder = 1;
/**
* The layout of the form for importing in to queXF
*
* @var array Defaults to empty array
* @link http://quexf.sourceforge.net/
*/
protected $layout = array();
/**
* Array to store section information for layout
*
* @var array Defaults to empty array
* @since 2010-09-02
*/
protected $section = array();
/**
* An array of key: skip target, value: last originating question
* that skips to the target
*
* @var string Defaults to array().
* @since 2012-01-31
*/
protected $skipToRegistry = array();
/**
* Page counter pointer (links to barcode id of page)
*
* @var mixed Defaults to "".
* @since 2010-09-02
*/
protected $layoutCP = "";
/**
* Section counter pointer
*
* @var string Defaults to 0.
* @since 2010-09-02
*/
protected $sectionCP = 0;
/**
* Box group counter pointer
*
* @var bool Defaults to 0.
* @since 2010-09-02
*/
protected $boxGroupCP = 0;
/**
* Box counter pointer
*
* @var int Defaults to 0.
*/
protected $boxCP = 0;
/**
* Column counter pointer (current column)
*
* @var mixed Defaults to 0.
* @since 2012-05-30
*/
protected $columnCP = 0;
/**
* Background colour of a question
*
* @var bool Defaults to array(220,220,220).
* @since 2010-09-15
*/
protected $backgroundColourQuestion = array(241);
/**
* The bacground colour of a section
*
* @var bool Defaults to array(200,200,200).
* @since 2010-09-20
*/
protected $backgroundColourSection = array(221);
/**
* Empty background colour
*
* @var bool Defaults to array(255,255,255).
* @since 2010-09-20
*/
protected $backgroundColourEmpty = array(255);
/**
* The colour of a line/fill
*
* @var mixed Defaults to array(0,0,0).
* @since 2010-09-20
*/
protected $lineColour = array(0);
/**
* Text colour in grayscale
*
* @var mixed Defaults to 0.
* @since 2012-04-16
*/
protected $textColour = 0;
/**
* The text to display before a skip
*
* @var string Defaults to "Skip to ".
* @since 2010-09-16
*/
protected $skipToText = "Skip to ";
/**
* Should fonts be embedded in the document?
*
* @var mixed Defaults to true.
* @since 2010-09-20
*/
protected $embedFonts = true;
/**
* Height in MM of a VAS response
*
* @var mixed Defaults to 8.
* @since 2010-09-20
*/
protected $vasAreaHeight = 8;
/**
* Width of a VAS line
*
* @var mixed Defaults to 0.5.
* @since 2010-09-20
*/
protected $vasLineWidth = 0.5;
/**
* The width of a line for the default value
*
* @var double Defaults to 0.5.
* @since 2012-06-14
*/
protected $defaultValueLineWidth = 0.5;
/**
* Height of the VAS ending lines in mm
*
* @var mixed Defaults to 4.
* @since 2010-09-20
*/
protected $vasHeight = 4;
/**
* Length of the vas line itself
*
* @var mixed Defaults to 100.
* @since 2010-09-20
*/
protected $vasLength = 100;
/**
* The number of increments stored on a vas line
*
* @var mixed Defaults to 100.
* @since 2010-09-20
*/
protected $vasIncrements = 100;
/**
* The text to separate parent text and subquestion text
*
* @var string Defaults to " : ".
* @since 2010-09-22
*/
protected $subQuestionTextSeparator = " : ";
/**
* The top margin for questionnaireInfo section
*
* @var mixed Defaults to 5.
* @since 2010-10-29
*/
protected $questionnaireInfoMargin = 5;
/**
* Height of a response label
*
* @var resource Defaults to 10.
* @since 2010-11-05
*/
protected $responseLabelHeight = 10;
/**
* Font size for response label
*
* @var resource Defaults to 8.
* @since 2010-11-05
*/
protected $responseLabelFontSize = 7.5;
/**
* A smaller font size for response labels where otherwise will break the line
*
* @var resource Defaults to 6.
* @since 2012-03-30
*/
protected $responseLabelFontSizeSmall = 6.5;
/**
* Reduce the font size of a response label if any words are longer than this
*
* @var resource Defaults to 7.
* @since 2012-03-30
*/
protected $responseLabelSmallWordLength = 7;
/**
* Font size for response text
*
* @var resource Defaults to 10.
* @since 2010-11-05
*/
protected $responseTextFontSize = 10;
/**
* Font size of the skip to text
*
* @var string Defaults to 8.
* @since 2010-11-05
*/
protected $skipToTextFontSize = 8;
/**
* Default font
*
* @var string Defaults to 'freeserif'.
* @since 2010-11-05
*/
protected $defaultFont = 'freeserif';
/**
* Height of a section break in mm
*
* @var string Defaults to 18.
* @since 2010-11-05
*/
protected $sectionHeight = 18;
public function setLanguage($language)
{
if (!empty($language))
$this->language = $language;
}
/**
* Return the length of the longest word
*
* @param mixed $txt
*
* @return int Length of longest word
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2012-03-30
*/
protected function wordLength($txt)
{
$words = explode(' ', $txt);
$length = 0;
foreach($words as $v)
{
if(strlen($v) > $length)
$length = strlen($v);
}
return $length;
}
/**
* Add a box group to the page layout system
*
* VALUES(0, 'Temporary');
* VALUES(1, 'Single choice');
* VALUES(2, 'Multiple choice');
* VALUES(3, 'Text');
* VALUES(4, 'Number');
* VALUES(5, 'Barcode');
* VALUES(6, 'Long text');
*
* @param int $type The type of box group for verification purposes
* @param string $varname The variable name
* @param string $label The label for the box group Optional, defaults to "".
* @param int $width The width of this group Optional, defaults to 1.
*
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2010-09-02
*/
protected function addBoxGroup($type,$varname,$label = "", $width = 1)
{
$this->boxGroupCP++;
$this->layout[$this->layoutCP]['boxgroup'][$this->boxGroupCP] =
array( 'type' => $type,
'width' => $width,
'varname' => $varname,
'sortorder' => $this->boxGroupCP,
'label' => $label,
'groupsection' => $this->sectionCP,
'box' => array());
}
/**
* Add a new box group which is a copy of the previous one (if exists)
*
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2012-03-26
*/
protected function addBoxGroupCopyPrevious()
{
if (isset($this->layout[$this->layoutCP]['boxgroup'][$this->boxGroupCP]))
{
$a = $this->layout[$this->layoutCP]['boxgroup'][$this->boxGroupCP];
$this->addBoxGroup($a['type'],$a['varname'],$a['label']);
}
}
/**
* Add a box to the page layout system
*
* @param int $tlx Top left X
* @param int $tly Top left Y
* @param int $brx Bottom right X
* @param int $bry Bottom right Y
* @param string $value Optional, defaults to "".
* @param string $label Optional, defaults to "".
*
*/
protected function addBox($tlx,$tly,$brx,$bry,$value = "",$label = "")
{
$this->boxCP++;
$this->layout[$this->layoutCP]['boxgroup'][$this->boxGroupCP]['box'][] =
array( 'tlx' => $this->mm2px($tlx),
'tly' => $this->mm2px($tly),
'brx' => $this->mm2px($brx),
'bry' => $this->mm2px($bry),
'value' => $value,
'label'=> $label,
);
//Update the width of the parent boxgroup given its type and this additional box
$type = $this->layout[$this->layoutCP]['boxgroup'][$this->boxGroupCP]['type'];
$count = count($this->layout[$this->layoutCP]['boxgroup'][$this->boxGroupCP]['box']);
$width = $this->layout[$this->layoutCP]['boxgroup'][$this->boxGroupCP]['width'];
switch($type){
case 1: //Single choice
case 2: //Multiple choice
if (strlen($value) > $width) $width = strlen($value);
if (strlen($count) > $width) $width = strlen($count);
break;
case 3: //Text
case 4: //Numbers
$width = $count;
break;
case 6: //Longtext
$width = $this->longTextStorageWidth;
}
$this->layout[$this->layoutCP]['boxgroup'][$this->boxGroupCP]['width'] = $width;
}
/**
* Set allow splitting
*
* @param bool $allow Whether to allow or not (default true)
*
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2013-10-25
*/
public function setAllowSplittingSingleChoiceVertical($allow = true)
{
if ($allow)
$this->allowSplittingSingleChoiceVertical = true;
else
$this->allowSplittingSingleChoiceVertical = false;
}
/**
* Get allow splitting
*
* @return bool Whether to allow or not
*
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2013-10-25
*/
public function getAllowSplittingSingleChoiceVertical()
{
return $this->allowSplittingSingleChoiceVertical;
}
/**
* Set allow splitting
*
* @param bool $allow Whether to allow or not (default true)
*
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2013-10-25
*/
public function setAllowSplittingSingleChoiceHorizontal($allow = true)
{
if ($allow)
$this->allowSplittingSingleChoiceHorizontal = true;
else
$this->allowSplittingSingleChoiceHorizontal = false;
}
/**
* Get allow splitting
*
* @return bool Whether to allow or not
*
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2013-10-25
*/
public function getAllowSplittingSingleChoiceHorizontal()
{
return $this->allowSplittingSingleChoiceHorizontal;
}
/**
* Set allow splitting
*
* @param bool $allow Whether to allow or not (default true)
*
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2013-10-25
*/
public function setAllowSplittingVas($allow = true)
{
if ($allow)
$this->allowSplittingVas = true;
else
$this->allowSplittingVas = false;
}
/**
* Get allow splitting
*
* @return bool Whether to allow or not
*
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2013-10-25
*/
public function getAllowSplittingVas()
{
return $this->allowSplittingVas;
}
/**
* Set allow splitting
*
* @param bool $allow Whether to allow or not (default true)
*
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2013-10-25
*/
public function setAllowSplittingMatrixText($allow = true)
{
if ($allow)
$this->allowSplittingMatrixText = true;
else
$this->allowSplittingMatrixText = false;
}
/**
* Get allow splitting
*
* @return bool Whether to allow or not
*
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2013-10-25
*/
public function getAllowSplittingMatrixText()
{
return $this->allowSplittingMatrixText;
}
/**
* Set allow splitting
*
* @param bool $allow Whether to allow or not (default true)
*
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2013-10-25
*/
public function setAllowSplittingResponses($allow = true)
{
if ($allow)
$this->allowSplittingResponses = true;
else
$this->allowSplittingResponses = false;
}
/**
* Get allow splitting
*
* @return bool Whether to allow or not
*
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2013-10-25
*/
public function getAllowSplittingResponses()
{
return $this->allowSplittingResponses;
}
/**
* Set the minimum section height
*
* @param int $height The minimum height of a section
*
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2013-07-30
*/
public function setSectionHeight($height)
{
$height = intval($height);
if ($height < 0) $height = 1;
$this->sectionHeight = $height;
}
/**
* Get the section height
*
* @return The section height
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2013-07-30
*/
public function getSectionHeight()
{
return $this->sectionHeight;
}
/**
* Get the response label font sizes (normal and small)
*
* @return array containing the normal font size as the first element and small as second
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2013-04-10
*/
public function getResponseLabelFontSize()
{
return array($this->responseLabelFontSize,$this->responseLabelFontSizeSmall);
}
/**
* Set the response label font sizes
*
* @param array $sizes normal font size first then small
*
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2013-04-10
*/
public function setResponseLabelFontSize($sizes)
{
$this->responseLabelFontSize = intval($sizes[0]);
$this->responseLabelFontSizeSmall = intval($sizes[1]);
}
/**
* Get the response text font size
*
* @return int The response text font size
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2013-04-10
*/
public function getResponseTextFontSize()
{
return $this->responseTextFontSize;
}
/**
* Set the response text font size
*
* @param int $size
*
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2013-04-10
*/
public function setResponseTextFontSize($size)
{
$this->responseTextFontSize = intval($size);
}
/**
* Get the style without any HTML/etc formatting
*
* @return string The style without HTML or tabs
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2013-04-10
*/
public function getStyle()
{
return strip_tags(str_replace("\t","",$this->style));
}
/**
* Set the CSS styling of some questionnaire elements
*
* @param string $style The CSS styling of some questionnire elements
*
* @return none
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2013-04-10
*/
public function setStyle($style)
{
$this->style = "<style>" . $style . "</style>";
}
/**
* Export the layout as an XML file
*
* @return string The XML layout in queXF Banding XML format
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2010-09-20
*/
public function getLayout()
{
$doc = new DomDocument('1.0');
$root = $doc->createElement('queXF');
$q = $doc->createElement('questionnaire');
$id = $doc->createElement('id');
$value = $doc->createTextNode($this->questionnaireId);
$id->appendChild($value);
$q->appendChild($id);
foreach($this->section as $key => $val)
{
$s = $doc->createElement('section');
$s->setAttribute('id',$key);
foreach ($val as $sk => $sv)
{
$tmpe = $doc->createElement($sk);
$tmpv = $doc->createTextNode($sv);
$tmpe->appendChild($tmpv);
$s->appendChild($tmpe);
}
$q->appendChild($s);
}
foreach($this->layout as $key => $val)
{
$p = $doc->createElement('page');
foreach ($val as $pk => $pv)
{
if ($pk != 'boxgroup')
{
$tmpe = $doc->createElement($pk);
$tmpv = $doc->createTextNode($pv);
$tmpe->appendChild($tmpv);
$p->appendChild($tmpe);
}
}
foreach ($val['boxgroup'] as $bg)
{
$bgE = $doc->createElement('boxgroup');
foreach ($bg as $pk => $pv)
{
if ($pk == 'groupsection')
{
$gs = $doc->createElement('groupsection');
$gs->setAttribute('idref',$pv);
$bgE->appendChild($gs);
}
else if ($pk != 'box')
{
$tmpe = $doc->createElement($pk);
$tmpv = $doc->createTextNode($pv);
$tmpe->appendChild($tmpv);
$bgE->appendChild($tmpe);
}
}
foreach($bg['box'] as $b)
{
$bE = $doc->createElement('box');
foreach($b as $bk => $bv)
{
$tmpe = $doc->createElement($bk);
$tmpv = $doc->createTextNode($bv);
$tmpe->appendChild($tmpv);
$bE->appendChild($tmpe);
}
$bgE->appendChild($bE);
}
$p->appendChild($bgE);
}
$q->appendChild($p);
}
$root->appendChild($q);
$doc->appendChild($root);
$doc->formatOutput = true; //make it look nice
return $doc->saveXML();
}
/**
* Set font size and style
*
* @param string $size Optional, defaults to 12
* @param string $style Optional, defaults to ''.
*
* @return TODO
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2010-11-05
*/
protected function setDefaultFont($size = 12,$style = '')
{
$alternatepdffontfile=Yii::app()->getConfig('alternatepdffontfile');
if(array_key_exists($this->language,$alternatepdffontfile))
{
$this->SetFont($alternatepdffontfile[$this->language],$style);
}
else
{
$this->SetFont($this->defaultFont,$style);
}
$this->SetFontSize($size);
}
/**
* Initialise TCPDF width some default values and embedded fonts
*
* @return TODO
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2010-09-20
*/
protected function init()
{
if ($this->embedFonts)
{
$this->setFontSubsetting(false); //we want full subsetting
$this->AddFont('freesans','');
$this->AddFont('freesans','B');
$this->AddFont('freesans','I');
$this->AddFont('freesans','BI');
$this->AddFont('freeserif','');
$this->AddFont('freeserif','B');
$this->AddFont('freeserif','I');
$this->AddFont('freeserif','BI');
$this->setDefaultFont();
}
// set document information
$this->SetCreator('queXMLPDF (http://quexml.sourceforge.net)');
$this->SetAuthor('Adam Zammit <adam.zammit@acspri.org.au>');
$this->SetTitle('queXML Document');
$this->SetSubject('queXML');
$this->SetKeywords('queXML queXF');
//set text colour
$this->SetTextColor($this->textColour);
//set column pointer
$this->columnCP = -1;
}
/**
* Override of TCPDF Header function to blank
*
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2010-09-20
*/
public function Header(){
}
/**
* Override of TCPDF Footer function to blank
*
* @author Adam Zammit <adam.zammit@acspri.org.au>
*/
public function Footer(){
}
/**
* Set the background wash of the page
*
* @param mixed $type Optional, defaults to 'empty'.
*
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2010-09-02
*/
protected function setBackground($type = 'empty')
{
switch ($type) {
case 'question':
$this->SetFillColor($this->backgroundColourQuestion[0]);
break;
case 'section':
$this->SetFillColor($this->backgroundColourSection[0]);
break;
case 'empty':
$this->SetFillColor($this->backgroundColourEmpty[0]);
break;
}
}
/*
* The X coordinate of the start of the page proper
*
* @return int The X coordinate of the start of the page
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2010-09-02
*/
public function getMainPageX()
{
return ($this->cornerBorder + $this->cornerWidth);
}
/**
* The X coordinate of the start of the column
*
* @return int The X coordinate of the start of the current column
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2012-05-30
*/
public function getColumnX()
{
$border = 0;
if ($this->columnCP > 0)
$border = $this->columnBorder;
return $this->getMainPageX() + ($this->columnCP * ($this->getColumnWidth() + $border)) + $border;
}
/**
* The width of the writeable page
*
* @return int The width of the writeable page
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2010-09-02
*/
public function getMainPageWidth()
{
return ($this->getPageWidth() - (($this->cornerBorder * 2.0) + ($this->cornerWidth * 2.0)));
}
/**
* The width of the writable column
*
* @return int The width of the current column
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2012-05-30
*/
public function getColumnWidth()
{
$border = 0;
if ($this->columnCP > 0)
$border = $this->columnBorder;
return ((1 / $this->columns) * $this->getMainPageWidth()) - $border;
}
/**
* Draw a horizontal response box with possible eye guides and arrows
*
* @param int $x The x position of the box area (top left)
* @param int $y The y position of the box area (top left)
* @param string $position What position the box is in for the eye guides
* @param bool $downarrow Draw a down arrow?
* @param bool $rightarrow Draw an arrow to the right?
* @param bool $smallwidth Whether or not to use the small width
* @param bool $filled Whether or not to have the box pre-filled
*
*/
protected function drawHorizontalResponseBox($x,$y,$position = 'only',$downarrow = false, $rightarrow = false, $smallwidth = false, $filled =false)
{
$this->SetDrawColor($this->lineColour[0]);
$this->SetLineWidth($this->singleResponseBoxBorder);
//centre for the line
$boxmid = ($y + ($this->singleResponseHorizontalHeight / 2.0));
//centre on y
$y = $y + (($this->singleResponseHorizontalHeight - $this->singleResponseBoxHeight) / 2.0);
if ($smallwidth)
$areawidth = $this->singleResponseVerticalAreaWidthSmall;
else
$areawidth = $this->singleResponseVerticalAreaWidth;
$linelength = (($areawidth - $this->singleResponseBoxWidth) / 2.0);
$this->SetLineStyle(array('dash' => '1'));
if ($position == 'last' || $position == 'middle')
{
$this->Line($x, $boxmid, $x + $linelength,$boxmid);
}
if ($position == 'first' || $position == 'middle')
{
$this->Line($x + $linelength + $this->singleResponseBoxWidth, $boxmid, $x + ($linelength * 2) + $this->singleResponseBoxWidth,$boxmid);
}
$this->SetLineStyle(array('dash' => '0'));
$this->Rect($x + $linelength,$y,$this->singleResponseBoxWidth,$this->singleResponseBoxHeight,'DF',array(),$this->backgroundColourEmpty);
if ($downarrow)
{
$boxmiddle = ($x + ($this->singleResponseBoxWidth / 2.0)) + $linelength;
$this->SetFillColor($this->lineColour[0]);
$this->Polygon(array($x + $linelength, $y + $this->singleResponseBoxHeight, $boxmiddle, $y + $this->singleResponseBoxHeight + $this->arrowHeight, $x + $linelength + $this->singleResponseBoxWidth, $y + $this->singleResponseBoxHeight),'DF',array(),$this->lineColour);
$this->setBackground('empty');
}
if ($filled)
{
//draw a cross
$this->SetLineWidth($this->defaultValueLineWidth);
$this->Line($x + $linelength, $y, $x + $linelength + $this->singleResponseBoxWidth, $y + $this->singleResponseBoxHeight);
$this->Line($x + $linelength + $this->singleResponseBoxWidth, $y, $x + $linelength, $y + $this->singleResponseBoxHeight);
}
$this->setBackground('question');
return array($x + $linelength,$y,$x + $linelength + $this->singleResponseBoxWidth, $y + $this->singleResponseBoxHeight); //return the posistion for banding
}
/**
* Draw a vertical response box with possible eye guides and arrows
*
* @param int $x The x position of the box area (top left)
* @param int $y The y position of the box area (top left)
* @param string $position What position the box is in for the eye guides
* @param bool $downarrow Draw a down arrow?
* @param bool $rightarrow Draw an arrow to the right?
* @param bool $filled Whether or not to have the box pre-filled
*
*/
protected function drawVerticalResponseBox($x,$y,$position = 'only',$downarrow = false, $rightarrow = false, $filled = false)
{
$this->SetDrawColor($this->lineColour[0]);
$this->SetLineWidth($this->singleResponseBoxBorder);
if (!$downarrow)
{
$y = $y + (($this->singleResponseAreaHeight - $this->singleResponseBoxHeight) / 2.0);
}
$boxmid = ($x + ($this->singleResponseBoxWidth / 2.0));
if ($position == 'first' || $position == 'middle')
{
$this->Line($boxmid, ($y + $this->singleResponseBoxHeight), $boxmid, ($y + $this->singleResponseBoxHeight + $this->singleResponseBoxLineLength));
}
if ($position == 'last' || $position == 'middle')
{
$this->Line($boxmid, $y, $boxmid, ($y - $this->singleResponseBoxLineLength));
}
if ($downarrow)
{
$this->SetFillColor($this->lineColour[0]);
$this->Polygon(array($x, $y + $this->singleResponseBoxHeight, $boxmid, $y + $this->singleResponseBoxHeight + $this->arrowHeight, $x + $this->singleResponseBoxWidth, $y + $this->singleResponseBoxHeight),'DF',array(),$this->lineColour);
$this->setBackground('empty');
}
if ($rightarrow !== false)
{
//Draw skipto
$boxymid = ($y + ($this->singleResponseBoxHeight / 2.0));
$this->SetFillColor($this->lineColour[0]);
$this->Polygon(array($x + $this->singleResponseBoxWidth, $y, $x + $this->singleResponseBoxWidth + $this->arrowHeight, $boxymid, $x + $this->singleResponseBoxWidth, $y + $this->singleResponseBoxHeight),'DF',array(),$this->lineColour);
$this->setBackground('empty');
//Now draw the text
//Start at $x + singleResponseboxWidth + arrowHeight, $y - siongleresponseboxlinelength and go to $skipcolumnwidth wide and singleresponseareHeight high
$this->setBackground('question');
$text = $this->skipToText . $rightarrow;
$ypos = $this->GetY();
$this->setDefaultFont($this->skipToTextFontSize,'B');
$this->MultiCell($this->skipColumnWidth,$this->singleResponseBoxHeight,$text,0,'L',false,0,(($this->getColumnWidth() + $this->getColumnX()) - $this->skipColumnWidth),$y,true,0,false,true,$this->singleResponseBoxHeight,'M',true);
//Reset to non bold as causing problems with TCPDF HTML CSS conversion
$this->setDefaultFont($this->skipToTextFontSize,'');
//$this->writeHTMLCell($this->skipColumnWidth, 0, $this->getPageWidth() - $this->getMainPageX() - $this->skipColumnWidth ,$y, $this->style . $html,0,0,true,true,'C',true);
$this->SetY($ypos,false);
}
$this->Rect($x,$y,$this->singleResponseBoxWidth,$this->singleResponseBoxHeight,'DF',array(),$this->backgroundColourEmpty);
if ($filled)
{
//draw a cross
$this->SetLineWidth($this->defaultValueLineWidth);
$this->Line($x, $y, $x + $this->singleResponseBoxWidth, $y + $this->singleResponseBoxHeight);
$this->Line($x + $this->singleResponseBoxWidth, $y, $x, $y + $this->singleResponseBoxHeight);
}
$this->setBackground('question');
return array($x,$y,$x + $this->singleResponseBoxWidth, $y + $this->singleResponseBoxHeight); //return the posistion for banding
}
/**
* Return capital letter(s) corresponding to the given number
*
* @param integer $number
*
* @return string Letter(s) corresponding to the number
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2010-09-08
*/
public function numberToLetter($number)
{
if ($number < 1) $number = 1;
if ($number > 26)
return chr((($number - 1) / 26) + 64) . chr((($number - 1) % 26) + 65);
else
return chr($number + 64);
}
/**
* Get the questionnaire id
*
* @return int The questionnaire Id
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2010-09-23
*/
public function getQuestionnaireId()
{
return $this->questionnaireId;
}
/**
* Converts a queXML file to the array format required for the create function
*
* @param string $quexml The queXML file
*
* @return array An array readable by create
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2010-09-08
* @see create
*/
public function createqueXML($quexml)
{
$clang = new limesurvey_lang($this->language);
$xml = new SimpleXMLElement($quexml);
$q = array();
$scount = 1;
$sl = "";
$q['id'] = $xml['id'];
foreach ($xml->questionnaireInfo as $qitmp)
{
if ($qitmp->position == 'after')
{
if (!isset($q['infoafter']))
$q['infoafter'] = "";
$q['infoafter'] .= $qitmp->text . "<br/><br/>";
}
else if ($qitmp->position == 'before')
{
if (!isset($q['infobefore']))
$q['infobefore'] = "";
$q['infobefore'] .= $qitmp->text . "<br/><br/>";
}
}
foreach($xml->section as $s)
{
$stmp = array();
$sl = $this->numberToLetter($scount);
$stmp['title'] = $clang->gT("Section") . " " . $sl;
$stmp['info'] = "";
$stmp['text'] = "";
$bfc = 0;
foreach ($s->sectionInfo as $sitmp)
{
if ($sitmp->position == 'title')
{
$stmp['text'] .= $sitmp->text;
}
if ($sitmp->position == 'before' || $sitmp->position == 'during')
{
$stmp['info'] .= $sitmp->text;
if ($bfc > 0)
$stmp['info'] .= "<br/>";
$bfc++;
}
}
$qcount = 1;
foreach ($s->question as $qu)
{
$qtmp = array();
$rstmp = array();
$qtmp['split'] = 'notset';
if (isset($qu['split']))
{
if (current($qu['split']) == "true")
$qtmp['split'] = true;
else
$qtmp['split'] = false;
}
$qtmp['title'] = $sl . $qcount . $this->questionTitleSuffix;
if (isset($qu['hidetitle']) && $qu['hidetitle'] == "true")
$qtmp['hidetitle'] = "true";
$qtmp['text'] = "";
foreach ($qu->text as $ttmp)
{
//Add a new line if we aren't at the end
if ($ttmp != end($qu->text)){ $qtmp['text'] .= "<br/>"; }
$qtmp['text'] .= $ttmp;
}
foreach ($qu->specifier as $ttmp)
{
if (!isset($qtmp['specifier']))
$qtmp['specifier'] = "";
$qtmp['specifier'] .= $ttmp;
}
foreach ($qu->directive as $ttmp)
{
if ($ttmp->administration == 'self' && $ttmp->position == 'during')
{
if (!isset($qtmp['helptext']))
$qtmp['helptext'] = "";
$qtmp['helptext'] .= $ttmp->text;
}
if ($ttmp->administration == 'self' && $ttmp->position == 'after')
{
if (!isset($qtmp['helptextafter']))
$qtmp['helptextafter'] = "";
$qtmp['helptextafter'] .= $ttmp->text;
}
if ($ttmp->administration == 'self' && $ttmp->position == 'before')
{
if (!isset($qtmp['helptextbefore']))
$qtmp['helptextbefore'] = "";
$qtmp['helptextbefore'] .= $ttmp->text;
}
}
foreach ($qu->subQuestion as $sq)
{
$sqtmp = array();
$sqtmp['text'] = "";
foreach ($sq->text as $ttmp)
{
$sqtmp['text'] .= $ttmp;
}
$sqtmp['varname'] = $sq['varName'];
if (isset($sq['defaultValue']))
$sqtmp['defaultvalue'] = $sq['defaultValue'];
if (isset($sq->contingentQuestion))
{
//Need to handle contingent questions
$oarr = array();
$oarr['width'] = current($sq->contingentQuestion->length);
$oarr['text'] = current($sq->contingentQuestion->text);
$oarr['format'] = 'text';
if (isset($sq->contingentQuestion->format))
$oarr['format'] = current($sq->contingentQuestion->format);
if (isset($sq->contingentQuestion['defaultValue']))
$oarr['defaultvalue'] = $sq->contingentQuestion['defaultValue'];
$oarr['varname'] = $sq->contingentQuestion['varName'];
$sqtmp['other'] = $oarr;
}
$rstmp['subquestions'][] = $sqtmp;
}
foreach ($qu->response as $r)
{
$rtmp = array();
$rstmp['varname'] = $r['varName'];
$rtmp['split'] = 'notset';
if (isset($r['split']))
{
if (current($r['split']) == "true")
$rtmp['split'] = true;
else
$rtmp['split'] = false;
}
if (isset($r['defaultValue']))
$rstmp['defaultvalue'] = $r['defaultValue'];
if (isset($r->fixed))
{
$rtmp['type'] = 'fixed';
$rtmp['width'] = count($r->fixed->category);
if ($r->fixed['rotate'] == "true")
$rtmp['rotate'] = "true";
if ($r->fixed['separate'] == "true")
$rtmp['separate'] = "true";
$ctmp = array();
foreach ($r->fixed->category as $c)
{
$cat = array();
$cat['text'] = current($c->label);
$cat['value'] = current($c->value);
if (isset($c->skipTo))
{
$cat['skipto'] = current($c->skipTo);
//save a skip
$this->skipToRegistry[current($c->skipTo) . $this->questionTitleSuffix] = $qtmp['title'];
}
if (isset($c->contingentQuestion))
{
//Need to handle contingent questions
$oarr = array();
$oarr['width'] = current($c->contingentQuestion->length);
$oarr['text'] = current($c->contingentQuestion->text);
$oarr['format'] = 'text';
if (isset($c->contingentQuestion->format))
$oarr['format'] = current($c->contingentQuestion->format);
if (isset($c->contingentQuestion['defaultValue']))
$oarr['defaultvalue'] = $c->contingentQuestion['defaultValue'];
$oarr['varname'] = $c->contingentQuestion['varName'];
$cat['other'] = $oarr;
}
$ctmp[] = $cat;
}
$rtmp['categories'] = $ctmp;
}
else if (isset($r->free))
{
$format = strtolower(trim(current($r->free->format)));
if ($format == 'longtext')
$rtmp['type'] = 'longtext';
else if ($format == 'number' || $format == 'numeric' || $format == 'integer')
$rtmp['type'] = 'number';
else if ($format == 'i25')
$rtmp['type'] = 'i25';
else if ($format == 'codabar')
$rtmp['type'] = 'codabar';
else
$rtmp['type'] = 'text';
$rtmp['width'] = current($r->free->length);
$rtmp['text'] = current($r->free->label);
}
else if (isset($r->vas))
{
$rtmp['type'] = 'vas';
$rtmp['width'] = 100;
$rtmp['labelleft'] = current($r->vas->labelleft);
$rtmp['labelright'] = current($r->vas->labelright);
}
$rstmp['response'] = $rtmp;
$qtmp['responses'][] = $rstmp;
}
$stmp['questions'][] = $qtmp;
$qcount++;
}
$q['sections'][] = $stmp;
$scount++;
}
return $q;
}
/**
* Create a queXML PDF document based on an array
* that is structured like a queXML document
*
* sections (title, text, info)
* questions (title, text, varname, helptext, helptextafter)
* responses (varname)
* subquestion (text, varname)
* response (type, width, text, rotate)
* categories (text, value)
*
* @param array $questionnaire The questionnaire in the array format above
*/
public function create($questionnaire)
{
$this->init();
$this->questionnaireId = intval($questionnaire['id']);
$this->newPage(true); //first page
//Draw questionnaireInfo before if exists
if (isset($questionnaire['infobefore']))
{
$this->drawInfo($questionnaire['infobefore']);
}
foreach($questionnaire['sections'] as $sk => $sv)
{
//link the section title with the first question for pagination purposes
if (isset($sv['questions']))
{
$questions = count($sv['questions']);
}
else $questions=0;
$this->startTransaction();
$this->addSection($sv['text'],$sv['title'],$sv['info']);
if ($questions != 0) $this->createQuestion($sv['questions'][0]);
if ($this->pageBreakOccured)
{
$this->pageBreakOccured = false;
$this->rollBackTransaction(true);
$this->SetAutoPageBreak(false); //Temporarily set so we don't trigger a page break
$this->fillPageBackground();
$this->newPage();
$this->addSection($sv['text'],$sv['title'],$sv['info']);
if ($questions != 0) $this->createQuestion($sv['questions'][0]);
}
else
$this->commitTransaction();
//start from the second question as first is linked to the section (if there is a question in this section)
if ($questions != 0)
{
foreach(array_slice($sv['questions'], 1) as $qk => $qv)
{
$this->startTransaction();
//add question here
$this->createQuestion($qv);
if ($this->pageBreakOccured)
{
$this->pageBreakOccured = false;
$this->rollBackTransaction(true);
$this->SetAutoPageBreak(false); //Temporarily set so we don't trigger a page break
//now draw a background to the bottom of the page
$this->fillPageBackground();
$this->newPage();
//retry question here
$this->createQuestion($qv);
}
else
$this->commitTransaction();
}
}
}
//Draw questionnaireInfo after if exists
if (isset($questionnaire['infoafter']))
{
$this->startTransaction();
$this->drawInfo($questionnaire['infoafter']);
if ($this->pageBreakOccured)
{
$this->pageBreakOccured = false;
$this->rollBackTransaction(true);
$this->SetAutoPageBreak(false); //Temporarily set so we don't trigger a page break
//now draw a background to the bottom of the page
$this->fillPageBackground();
$this->newPage();
//retry question here
$this->drawInfo($questionnaire['infoafter']);
}
else
$this->commitTransaction();
}
//fill to the end of the last page
$this->fillLastPageBackground();
}
/**
* Draw the questionnaire info specified
*
* @param string $text The text to draw in info style
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2011-12-21
*/
protected function drawInfo($info)
{
$this->setBackground('question');
$this->writeHTMLCell($this->getColumnWidth(), $this->questionnaireInfoMargin, $this->getColumnX(), $this->GetY() - $this->questionBorderBottom, "<div></div>",0,1,true,true);
$html = "<table><tr><td width=\"" . $this->getColumnWidth() . "mm\" class=\"questionnaireInfo\">{$info}</td><td></td></tr></table>";
$this->writeHTMLCell($this->getColumnWidth(), 1, $this->getColumnX(), $this->GetY(), $this->style . $html,0,1,true,true);
}
/**
* Create a question that may have multiple response groups
*
* questions (title, text, specifier, helptext, helptextafter)
* responses (varname)
* subquestions
* subquestion(text, varname)
* response (type, width, text, rotate)
* categories
* category(text, value, skipto, other)
*
* @param array $question The questions portion of the array
* @see create
*/
protected function createQuestion($question)
{
$help = false;
$specifier = false;
if (isset($question['helptext'])) $help = $question['helptext'];
if (isset($question['specifier'])) $specifier = $question['specifier'];
//If there is some help text for before the question
if (isset($question['helptextbefore']))
{
//Leave a border at the top of the Help Before text
if ($this->helpBeforeBorderTop > 0) //question border
$this->SetY($this->GetY() + $this->helpBeforeBorderTop,false); //new line
$this->setBackground('question');
$html = "<table><tr><td width=\"" . $this->getColumnWidth() . "mm\" class=\"questionHelpBefore\">{$question['helptextbefore']}</td><td></td></tr></table>";
$this->writeHTMLCell($this->getColumnWidth(), 1, $this->getColumnX(), $this->GetY(), $this->style . $html,0,1,true,true);
//Leave a border at the bottom of the Help Before text
if ($this->helpBeforeBorderBottom > 0) //question border
$this->SetY($this->GetY() + $this->helpBeforeBorderBottom,false); //new line
}
//Question header
$helph = $help;
//don't display help if separate questions are involved
if (isset($question['responses'][0]['response']['separate'])) $helph = false;
//hide if requested
$qtitle = $question['title'];
if (isset($question['hidetitle']))
$qtitle = "";
$this->drawQuestionHead($qtitle, $question['text'],$helph,$specifier);
$text = "";
if (isset($question['text'])) $text = $question['text'];
$split = $question['split'];
if ($split === 'notset')
$split = $this->allowSplittingResponses;
//Loop over response groups and produce questions of various types
if (isset($question['responses']))
{
//the number of response scales is needed later on to decide on labelling scales in fixed response questions
$iCountResponseScales=count($question['responses']);
if ($this->pageBreakOccured) //don't continue if page break already
return;
for ($rcount = 0; $rcount < count($question['responses']); $rcount++)
{
$r = $question['responses'][$rcount];
//only split after one response
if ($split && $rcount == 1)
{
if ($this->pageBreakOccured)
return;
$this->startTransaction();
}
$varname = $r['varname'];
if (isset($r['subquestions']))
{
$response = $r['response'];
$subquestions = $r['subquestions'];
$type = $response['type'];
$bgtype = 3; //box group type temp set to 3 (text)
// question with > 1 responses and >1 subquestions --> matrix question --> need to come up with unique variable names
if (count($question['responses'])>1)
{
foreach ($subquestions as $index=>$sv)
{
$subquestions[$index]['varname']=$subquestions[$index]['varname'].'_'.$varname;
}
}
switch ($type)
{
case 'fixed':
$categories = $response['categories'];
if (isset($response['rotate']))
$this->drawSingleChoiceVertical($categories,$subquestions,$text,$response['split']);
else
{
if (isset($response['separate']))
{
$this->drawSingleChoiceVerticalSeparate($categories,$subquestions,$text,$help,$response['split']);
}
else
{
// if there is more than one response scale, add a label to scales in the pdf
$vn = false;
if ($iCountResponseScales > 1)
$vn = $varname;
$this->drawSingleChoiceHorizontal($categories,$subquestions,$text,$vn,$response['split']);
}
}
break;
case 'number':
$bgtype = 4;
case 'currency':
case 'text':
if (isset($response['rotate']))
$this->drawMatrixTextHorizontal($subquestions,$response['width'],$text,$bgtype,$response['text']);
else
$this->drawMatrixTextVertical($subquestions,$response['width'],$text,$bgtype,$response['text'],$response['split']);
break;
case 'vas':
$this->drawMatrixVas($subquestions,$text,$response['labelleft'],$response['labelright'],$response['split']);
break;
case 'i25':
$this->drawMatrixBarcode($subquestions, 'I25');
break;
case 'codabar':
$this->drawMatrixBarcode($subquestions, 'CODABAR');
break;
}
}
else
{
$response = $r['response'];
$type = $response['type'];
$defaultvalue = false;
if (isset($r['defaultvalue']))
$defaultvalue = $r['defaultvalue'];
if (isset($response['text']) && !empty($response['text']))
$rtext = $text . $this->subQuestionTextSeparator . $response['text'];
else
$rtext = $text;
$bgtype = 3; //box group type temp set to 3 (text)
switch ($type)
{
case 'fixed':
if (isset($response['rotate']))
$this->drawSingleChoiceHorizontal($response['categories'],array(array('text' => '', 'varname' => $varname, 'defaultvalue' => $defaultvalue)),$rtext,false,$response['split']);
else
$this->drawSingleChoiceVertical($response['categories'],array(array('text' => '', 'varname' => $varname, 'defaultvalue' => $defaultvalue)),$rtext,$response['split']);
break;
case 'longtext':
$this->addBoxGroup(6,$varname,$rtext);
$this->drawLongText($response['width'],$defaultvalue);
break;
case 'number':
$bgtype = 4;
case 'currency':
case 'text':
$this->addBoxGroup($bgtype,$varname,$rtext,$response['width']);
$this->drawText($response['text'],$response['width'],$defaultvalue);
//Insert a gap here
$this->Rect($this->getColumnX(),$this->GetY(),$this->getColumnWidth(),$this->subQuestionLineSpacing,'F',array(),$this->backgroundColourQuestion);
$this->SetY($this->GetY() + $this->subQuestionLineSpacing,false);
break;
case 'vas':
$this->addBoxGroup(1,$varname,$rtext,strlen($this->vasIncrements));
$this->drawVas("",$response['labelleft'],$response['labelright']);
break;
case 'i25':
$this->drawMatrixBarcode(array(array('text' => $rtext, 'varname' => $varname, 'defaultvalue' => $defaultvalue)),'I25');
break;
case 'codabar':
$this->drawMatrixBarcode(array(array('text' => $rtext, 'varname' => $varname, 'defaultvalue' => $defaultvalue)),'CODABAR');
break;
}
}
//only allow a page break if defined and we have more than one item already on this page
if ($split && $this->pageBreakOccured && $rcount > 0)
{
$this->pageBreakOccured = false;
$this->rollBackTransaction(true);
$this->SetAutoPageBreak(false); //Temporarily set so we don't trigger a page break
$this->fillPageBackground();
$this->newPage();
//go back to last response
$rcount = $rcount - 1;
}
else
{
if ($split && $rcount > 0)
{
$this->commitTransaction();
$this->startTransaction(); //start a transaction to allow for splitting over pages if necessary
}
}
}}
//If there is some help text for after the question
if (isset($question['helptextafter']))
{
$this->setBackground('question');
$html = "<table><tr><td width=\"" . $this->getColumnWidth() . "mm\" class=\"questionHelpAfter\">{$question['helptextafter']}</td><td></td></tr></table>";
$this->writeHTMLCell($this->getColumnWidth(), 1, $this->getColumnX(), $this->GetY(), $this->style . $html,0,1,true,true);
}
//Leave a border at the bottom of the question
if ($this->questionBorderBottom > 0) //question border
$this->SetY($this->GetY() + $this->questionBorderBottom,false); //new line
}
/**
* Draw text responses line by line
*
* @param array $subquestions The subquestions containing text and varname
* @param int $width The width of the text element
* @param string|bool $parenttext The question text of the parent or false if not specified
* @param int $bgtype The box group type (default is 3 - text)
* @param string|bool $responsegrouplabel The label for this response group or false if not specified
* @param string|bool $split Allow splitting this over multiple pages. 'notset' means leave default. Otherwise force setting
*
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2010-09-02
*/
protected function drawMatrixTextVertical($subquestions,$width,$parenttext = false,$bgtype = 3, $responsegrouplabel = false, $split = 'notset')
{
if ($split === 'notset')
$split = $this->allowSplittingMatrixText;
$c = count($subquestions);
//draw second axis label
if ($responsegrouplabel)
{
$this->setBackground('question');
$html = "<table><tr><td width=\"{$this->questionTitleWidth}mm\"></td><td width=\"" . ($this->getColumnWidth() - $this->skipColumnWidth - $this->questionTitleWidth) . "mm\" class=\"matrixResponseGroupLabel\">$responsegrouplabel:</td><td></td></tr></table>";
$this->writeHTMLCell($this->getColumnWidth(), 1, $this->getColumnX(), $this->GetY(), $this->style . $html,0,1,true,true);
}
//don't proceed if breaking the page already
if ($this->pageBreakOccured)
return;
for($i = 0; $i < $c; $i++)
{
if ($split && $i == 1)
{
//don't proceed if breaking the page already
if ($this->pageBreakOccured)
return;
$this->startTransaction(); //start a transaction when one line drawn
}
$s = $subquestions[$i];
if ($parenttext == false)
$this->addBoxGroup($bgtype,$s['varname'],$s['text'],$width);
else
$this->addBoxGroup($bgtype,$s['varname'],$parenttext . $this->subQuestionTextSeparator . $s['text'],$width);
$defaultvalue = false;
if (isset($s['defaultvalue']))
$defaultvalue = $s['defaultvalue'];
$this->drawText($s['text'],$width,$defaultvalue);
$currentY = $this->GetY();
//Insert a gap here
$this->Rect($this->getColumnX(),$this->GetY(),$this->getColumnWidth(),$this->subQuestionLineSpacing,'F',array(),$this->backgroundColourQuestion);
$this->SetY($currentY + $this->subQuestionLineSpacing,false);
//only allow a page break if defined and we have more than one item already on this page
if ($split && $this->pageBreakOccured && $i > 0)
{
$this->pageBreakOccured = false;
$this->rollBackTransaction(true);
$this->SetAutoPageBreak(false); //Temporarily set so we don't trigger a page break
$this->fillPageBackground();
$this->newPage();
//fill page background at top
$html = "<div></div>";
$this->setBackground('question');
$this->writeHTMLCell($this->getColumnWidth(), $this->subQuestionLineSpacing, $this->getColumnX(), $this->GetY(), $this->style . $html,0,1,true,true);
//move from top of page
$currentY = $this->GetY();
$i = $i - 1; //go back and draw subquestions on the new page
}
else
{
if ($split && $i > 0)
{
$this->commitTransaction();
$this->startTransaction(); //start a transaction to allow for splitting over pages if necessary
}
}
}
}
/**
* Draw a barcode as a "question"
*
* @param string $subquestions
* @param mixed $type
*
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2012-06-22
*/
protected function drawMatrixBarcode($subquestions, $type)
{
$c = count($subquestions);
for ($i = 0; $i < $c; $i++)
{
$s = $subquestions[$i];
$this->addBoxGroup(5,$s['varname'],$s['text'],strlen($s['defaultvalue']));
$x = $this->getColumnX();
$y = $this->GetY();
$html = "<div></div>";
$this->setBackground('question');
$this->writeHTMLCell($this->getColumnWidth(), $this->barcodeResponseHeight, $this->getColumnX(), $this->GetY() , $this->style . $html,0,1,true,false);
//draw the barcode
$barcodeStyle = array('align' => 'R', 'border' => false, 'padding' => '0', 'bgcolor' => $this->backgroundColourQuestion, 'text' => false, 'stretch' => false);
$this->write1DBarcode($s['defaultvalue'], $type, $x, $y, $this->getColumnWidth() - $this->skipColumnWidth,$this->barcodeResponseHeight,'', $barcodeStyle, 'B');
//pointer should now be at the bottom right - but make the box the width of the whole column for better reading
$this->addBox($x,$y,$this->GetX(),$this->getColumnWidth() + $this->getColumnX());
$currentY = $this->GetY();
//Insert a gap here
$this->Rect($this->getColumnX(),$this->GetY(),$this->getColumnWidth(),$this->subQuestionLineSpacing,'F',array(),$this->backgroundColourQuestion);
$this->SetY($currentY + $this->subQuestionLineSpacing,false);
}
}
/**
* Draw multiple VAS items
*
* @param array $subquestions The subquestions containing text and varname
* @param string|bool $parenttext The question text of the parent or false if not specified
* @param string $labelleft The left hand side label
* @param string $labelright The right hand side label
* @param string|bool $split Allow splitting this over multiple pages. 'notset' means leave default. Otherwise force setting
*
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2010-09-20
*/
protected function drawMatrixVas($subquestions,$parenttext = false,$labelleft,$labelright,$split = 'notset')
{
if ($split === 'notset')
$split = $this->allowSplittingVas;
$c = count($subquestions);
$width = strlen($this->vasIncrements);
$heading = true;
for ($i = 0; $i < $c; $i++)
{
if ($split && $i == 1)
{
//don't proceed if breaking the page already
if ($this->pageBreakOccured)
return;
$this->startTransaction(); //start a transaction when one line drawn
}
$s = $subquestions[$i];
if ($parenttext == false)
$this->addBoxGroup(1,$s['varname'],$s['text'],$width);
else
$this->addBoxGroup(1,$s['varname'],$parenttext . $this->subQuestionTextSeparator . $s['text'],$width);
$this->drawVas($s['text'],$labelleft,$labelright,$heading);
$currentY = $this->GetY();
//Insert a gap here
$this->Rect($this->getColumnX(),$this->GetY(),$this->getColumnWidth(),$this->subQuestionLineSpacing,'F',array(),$this->backgroundColourQuestion);
$this->SetY($currentY + $this->subQuestionLineSpacing,false);
$heading = false;
//only allow a page break if defined and we have more than one item already on this page
if ($split && $this->pageBreakOccured && $i > 0)
{
$this->pageBreakOccured = false;
$this->rollBackTransaction(true);
$this->SetAutoPageBreak(false); //Temporarily set so we don't trigger a page break
$this->fillPageBackground();
$this->newPage();
//fill page background at top
$html = "<div></div>";
$this->setBackground('question');
$this->writeHTMLCell($this->getColumnWidth(), $this->subQuestionLineSpacing, $this->getColumnX(), $this->GetY(), $this->style . $html,0,1,true,true);
//move from top of page
$currentY = $this->GetY();
$i = $i - 1; //go back and draw subquestions on the new page
//draw heading again
$heading = true;
}
else
{
if ($split && $i > 0)
{
$this->commitTransaction();
$this->startTransaction(); //start a transaction to allow for splitting over pages if necessary
}
}
}
}
/**
* Draw a large empty box for writing in text
*
* @param mixed $width The "width" of the box. This relates to the number of "lines" high
* @param bool|string $defaultvalue The default text to print in the box (if any)
* @param bool|string $text The text to display above the box (if any)
*
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2010-09-02
*/
protected function drawLongText($width,$defaultvalue = false,$text =false)
{
//Calculate long text box width as the width of the available column minus the skip column and question title area
$rwidth = $this->getColumnWidth() - $this->skipColumnWidth - $this->questionTitleWidth;
if ($text !== false && !empty($text))
{
$this->setBackground('question');
$html = "<table><tr><td width=\"{$this->questionTitleWidth}mm\"></td><td width=\"" . ($this->getColumnWidth() - $this->skipColumnWidth - $this->questionTitleWidth) . "mm\" class=\"responseAboveText\">$text</td><td></td></tr></table>";
$this->writeHTMLCell($this->getColumnWidth(), 1, $this->getColumnX(), $this->GetY(), $this->style . $html,0,1,true,true);
}
$currentY = $this->GetY();
$height = $width * $this->longTextResponseHeightMultiplier;
$html = "<div></div>";
$this->setBackground('question');
$this->writeHTMLCell($this->getColumnWidth(), $height, $this->getColumnX(), $this->GetY(), $this->style . $html,0,1,true,true);
$this->SetY($currentY,false);
$this->setBackground('empty');
$border = array('LTRB' => array('width' => $this->textResponseBorder, 'dash' => 0));
//Align to skip column on right
$this->SetX((($this->getColumnWidth() + $this->getColumnX()) - $this->skipColumnWidth - $rwidth),false);
//Add to pay layout
$this->addBox($this->GetX(),$this->GetY(),$this->GetX() + $rwidth, $this->GetY() + $height);
$this->SetDrawColor($this->lineColour[0]);
$text = "";
if ($defaultvalue !== false)
$text = $defaultvalue;
$this->Cell($rwidth,$height,$text,$border,0,'',true,'',0,false,'T','T');
$currentY = $currentY + $height;
$this->SetY($currentY,false);
}
/**
* Draw a VAS
*
* @param string $text The text of this item
* @param string $labelleft The left hand side label
* @param string $labelright The right hand side label
* @param bool $heading Whether to draw a heading or not
*
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2010-09-20
*/
protected function drawVas($text, $labelleft,$labelright,$heading = true)
{
$textwidth = $this->getColumnWidth() - $this->skipColumnWidth - ($this->vasLength + ($this->vasLineWidth * 2.0)) - 2;
$this->setBackground('question');
if ($heading)
{
//draw heading
$lwidth = 20;
$slwidth = $textwidth - ($lwidth / 2);
$gapwidth = ($this->vasLength + ($this->vasLineWidth * 2.0)) - $lwidth;
$html = "<table><tr><td width=\"{$slwidth}mm\"></td><td width=\"{$lwidth}mm\" class=\"vasLabel\">$labelleft</td><td width=\"{$gapwidth}mm\"></td><td width=\"{$lwidth}mm\" class=\"vasLabel\">$labelright</td></tr></table>";
$this->writeHTMLCell($this->getColumnWidth(), 0, $this->getColumnX(), $this->GetY(), $this->style . $html,0,1,true,false);
}
$currentY = $this->GetY();
$html = "<table><tr><td width=\"{$textwidth}mm\" class=\"responseText\">$text</td><td></td></tr></table>";
$textwidth += 2;
$this->writeHTMLCell($this->getColumnWidth(), $this->vasAreaHeight, $this->getColumnX(), $this->GetY(), $this->style . $html,0,1,true,false);
$ncurrentY = $this->GetY();
$this->SetY($currentY,false);
$this->SetX($textwidth + $this->getColumnX(),false);
$this->SetLineWidth($this->vasLineWidth);
$this->SetDrawColor($this->lineColour[0]);
//Draw the VAS left vert line
$ly = (($this->vasAreaHeight - $this->vasHeight) / 2.0) + $currentY;
$lx = $textwidth + $this->getColumnX();
$this->Line($lx,$ly,$lx,$ly + $this->vasHeight);
//Right vert line
$lx = $textwidth + $this->getColumnX() + $this->vasLength + $this->vasLineWidth;
$this->Line($lx,$ly,$lx,$ly + $this->vasHeight);
//Line itself
$ly = ($this->vasAreaHeight / 2.0) + $currentY;
$lx = $textwidth + $this->getColumnX() + ($this->vasLineWidth / 2.0);
$this->Line($lx,$ly,$lx + $this->vasLength,$ly);
//Add to layout system
$bw = ($this->vasLength / $this->vasIncrements);
$ly = (($this->vasAreaHeight - $this->vasHeight) / 2.0) + $currentY;
for ($i = 0; $i < $this->vasIncrements; $i++)
{
$this->addBox($lx,$ly,$lx + $bw,$ly + $this->vasHeight, $i + 1, $i + 1);
$lx += $bw;
}
//Go back to the right Y position
$this->SetY($ncurrentY,false);
}
/**
* Draw a text response
*
* @param string $text The text label if any (can be HTML)
* @param int $width The number of boxes to draw
* @param bool|string $defaultvalue The default text to include or false if none
*/
protected function drawText($text,$width,$defaultvalue = false)
{
$this->SetDrawColor($this->lineColour[0]);
//calculate text responses per line
$textResponsesPerLine = round(($this->getColumnWidth() - $this->skipColumnWidth - $this->textResponseMarginX) / ($this->textResponseWidth + $this->textResponseBorder));
$labelTextResponsesSameLine = round(($this->getColumnWidth() - $this->skipColumnWidth - $this->labelTextResponsesSameLineMarginX) / ($this->textResponseWidth + $this->textResponseBorder));
//draw boxes - can draw up to $textResponsesPerLine for each line
$lines = ceil($width / $textResponsesPerLine);
//draw the text label on the top of this box
if ($width > $labelTextResponsesSameLine && !empty($text))
{
$this->setBackground('question');
$html = "<table><tr><td width=\"{$this->questionTitleWidth}mm\"></td><td width=\"" . ($this->getColumnWidth() - $this->skipColumnWidth - $this->questionTitleWidth) . "mm\" class=\"responseAboveText\">$text</td><td></td></tr></table>";
$this->writeHTMLCell($this->getColumnWidth(), 1, $this->getColumnX(), $this->GetY(), $this->style . $html,0,1,true,true);
}
$currentY = $this->GetY();
$startstring = 0;
for ($i = 0; $i < $lines; $i++)
{
if ($lines == 1) $cells = $width; //one line only
else if (($i + 1 == $lines)) $cells = ($width - ($textResponsesPerLine * $i)); //last line
else $cells = $textResponsesPerLine; //middle line
//add another box group if moving on to another line
if ($i >= 1)
$this->addBoxGroupCopyPrevious();
$textwidth = ($this->getColumnWidth() - $this->skipColumnWidth) - (($this->textResponseWidth + $this->textResponseBorder ) * $cells);
//print "textwidth: $textwidth cells: $cells mainpagex: " . $this->getMainPageX() . "<br/>";
//First draw a background of height $this->responseLabelHeight
$html = "<div></div>";
$this->setBackground('question');
$this->writeHTMLCell($this->getColumnWidth(), $this->textResponseHeight, $this->getColumnX(), $this->GetY() , $this->style . $html,0,1,true,false);
if ($lines == 1 && $cells <= $labelTextResponsesSameLine && !empty($text))
{
$this->setDefaultFont($this->responseTextFontSize);
$this->MultiCell($textwidth,$this->textResponseHeight,$text,0,'R',false,1,$this->getColumnX(),$currentY,true,0,false,true,$this->textResponseHeight,'M',true);
//$html = "<table><tr><td width=\"{$textwidth}mm\" class=\"responseText\">$text</td><td></td></tr></table>";
}
$ncurrentY = $this->GetY();
$this->SetY($currentY,false);
$this->SetX($textwidth + $this->getColumnX() + 2,false); //set the X position to the first cell
$string = false;
if ($defaultvalue !== false)
$string = substr($defaultvalue,$startstring,$cells);
$this->drawCells($cells,$string);
$startstring += $cells;
$currentY = $ncurrentY;
//New line
$this->SetY($currentY,false); //new line
if (!(($i + 1) == $lines) && $this->textResponseLineSpacing > 0) //if there should be a gap between text responses and not the last
{
$this->SetX($this->getColumnX(),false);
$this->setBackground('question');
$this->Cell($this->getColumnWidth(),$this->textResponseLineSpacing,'','',0,'',true,'',0,false,'T','C');
$currentY += $this->textResponseLineSpacing;
$this->SetY($currentY,false); //new line
}
}
}
/**
* Draw X number of cells at the current X Y position
*
* @param int $cells The number of text cells to draw
* @param string $string A string to draw if set
*
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2010-09-08
*/
protected function drawCells($cells, $string)
{
$this->setBackground('empty');
$this->SetDrawColor($this->lineColour[0]);
for ($j = 0; $j < $cells; $j++)
{
//draw text cells
if ($cells == 1) //only
$border = array('LTR' => array('width' => $this->textResponseBorder, 'dash' => 0), 'B' => array('width' => ($this->textResponseBorder * 2), 'dash' => 0));
else if ($j == 0) //first
$border = array('LT' => array('width' => $this->textResponseBorder, 'dash' => 0), 'R' => array('width' => $this->textResponseBorder, 'dash' => 1), 'B' => array('width' => ($this->textResponseBorder * 2), 'dash' => 0));
else if (($j + 1) == $cells) //last
{
$border = array('TR' => array('width' => $this->textResponseBorder, 'dash' => 0), 'B' => array('width' => ($this->textResponseBorder * 2), 'dash' => 0));
//add a border gap
$this->SetX($this->GetX() + ($this->textResponseBorder),false);
}
else //middle
{
$border = array('T' => array('width' => $this->textResponseBorder, 'dash' => 0), 'R' => array('width' => $this->textResponseBorder, 'dash' => 1), 'B' => array('width' => ($this->textResponseBorder * 2), 'dash' => 0));
//add a border gap
$this->SetX($this->GetX() + ($this->textResponseBorder),false);
}
//Add the box to the layout scheme
$this->addBox($this->GetX(),$this->GetY(),$this->GetX() + $this->textResponseWidth,$this->GetY() + $this->textResponseHeight);
$text = '';
if (isset($string[$j]))
$text = $string[$j];
//Draw the box
$this->Cell($this->textResponseWidth,$this->textResponseHeight,$text,$border,0,'',true,'',0,false,'T','C');
}
//add some spacing for the bottom border
//$this->SetY(($this->GetY() + ($this->textResponseBorder * 2)),false);
}
/**
* Draw a horizontal table of text boxes
*
* @param array $subquestions The subquestions
* @param int $width The width
* @param string|bool $parenttext The question text of the parent or false if not specified
* @param int $bgtype The type of the box group (defaults to 3 - text)
* @param string|bool $responsegrouplabel The label for this response group or false if not specified
*
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2010-09-08
*/
protected function drawMatrixTextHorizontal($subquestions,$width,$parenttext = false,$bgtype = 3, $responsegrouplabel = false)
{
$total = count($subquestions);
$currentY = $this->GetY();
$rwidth = ($width * ($this->textResponseWidth + $this->textResponseBorder + $this->textResponseLineSpacing));
$textwidth = ($this->getColumnWidth() - $this->skipColumnWidth) - ($rwidth * $total);
$html = "<table><tr><td width=\"{$textwidth}mm\" class=\"responseText\"></td>";
foreach ($subquestions as $r)
{
$html .= "<td class=\"responseLabel\" width=\"{$rwidth}mm\">{$r['text']}</td>";
}
$html .= "<td></td></tr></table>";
$this->writeHTMLCell($this->getColumnWidth(), $this->singleResponseAreaHeight, $this->getColumnX(), $this->GetY(), $this->style . $html,0,1,true,true);
$currentY = $this->GetY();
//label "vertical axis"
$html = "<table><tr><td width=\"{$textwidth}mm\" class=\"matrixResponseGroupLabel\">$responsegrouplabel</td><td></td></tr></table>";
$this->writeHTMLCell($this->getColumnWidth(), $this->singleResponseAreaHeight, $this->getColumnX(), $this->GetY(), $this->style . $html,0,1,true,true);
$ncurrentY = $this->GetY();
$this->SetY($currentY,false);
//Set X position
$this->SetX($this->getColumnX() + $textwidth,false);
foreach ($subquestions as $s)
{
//Add box group to current layout
if ($parenttext == false)
$this->addBoxGroup($bgtype,$s['varname'],$s['text']);
else
$this->addBoxGroup($bgtype,$s['varname'],$parenttext . $this->subQuestionTextSeparator . $s['text']);
$string = false;
if (isset($s['defaultvalue']))
$string = substr($defaultvalue,0,$width);
//Draw the cells
$this->drawCells($width,$string);
//Move X for a gap
$this->SetX($this->GetX() + $this->textResponseLineSpacing,false);
$this->SetY($currentY,false);
}
//Move cursor back to the right spot
$this->SetY($ncurrentY,false);
}
/**
* Draw the head of a single choice horizontal table of responses
*
* @param array $categories The response categories
* @param string|bool $responsegrouplabel The label for this response group or false if not specified
*
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2012-06-05
*/
protected function drawSingleChoiceHorizontalHead($categories, $responsegrouplabel=false)
{
$total = count($categories);
$currentY = $this->GetY();
if ($total > $this->singleResponseHorizontalMax) //change if too many cats
$rwidth = $this->singleResponseVerticalAreaWidthSmall;
else
$rwidth = $this->singleResponseVerticalAreaWidth;
$textwidth = ($this->getColumnWidth() - $this->skipColumnWidth) - ($rwidth * $total);
//Draw a label for a group of Questions/Responses (e.g. useful for dual scale matrix questions)
if ($responsegrouplabel!=false)
{
$this->setBackground('question');
$this->setDefaultFont();
$this->MultiCell($textwidth,$this->responseLabelHeight,$responsegrouplabel.':',0,'L',false,0,$this->getColumnX()+$this->questionTitleWidth,$this->GetY(),true,0,false,true,$this->responseLabelHeight,'B',true);
}
//First draw a background of height $this->responseLabelHeight
$html = "<div></div>";
$this->setBackground('question');
$this->writeHTMLCell($this->getColumnWidth(), $this->responseLabelHeight, $this->getColumnX(), $currentY , $this->style . $html,0,1,true,true);
$this->setDefaultFont($this->responseLabelFontSize);
$count = 0;
//Draw a Cell for each rwidth from $textwidth + $this->getColumnX(),currentY
foreach ($categories as $r)
{
$y = $currentY;
$x = ($textwidth + $this->getColumnX() + ($rwidth * $count));
// Going to break the line because of long word
if ($this->wordLength($r['text']) > $this->responseLabelSmallWordLength)
$this->setDefaultFont($this->responseLabelFontSizeSmall);
$this->MultiCell($rwidth,$this->responseLabelHeight,$r['text'],0,'C',false,0,$x,$y,true,0,false,true,$this->responseLabelHeight,'B',true);
//reset font
if ($this->wordLength($r['text']) > $this->responseLabelSmallWordLength)
$this->setDefaultFont($this->responseLabelFontSize);
$count++;
}
}
/**
* Draw a horizontal table of respones including "eye guides"
*
* @param array $categories The response categories
* @param array $subquestions The subquestions if any
* @param string|bool $parenttext The question text of the parent or false if not specified
* @param string|bool $responsegrouplabel The label for this response group or false if not specified
* @param string|bool $split Allow splitting this over multiple pages. 'notset' means leave default. Otherwise force setting
*
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2010-09-08
*/
protected function drawSingleChoiceHorizontal($categories, $subquestions = array(array('text' => '')),$parenttext = false, $responsegrouplabel=false, $split = "notset")
{
if ($split === "notset")
$split = $this->allowSplittingSingleChoiceHorizontal;
$total = count($categories);
$currentY = $this->GetY();
if ($total > $this->singleResponseHorizontalMax) //change if too many cats
$rwidth = $this->singleResponseVerticalAreaWidthSmall;
else
$rwidth = $this->singleResponseVerticalAreaWidth;
$textwidth = ($this->getColumnWidth() - $this->skipColumnWidth) - ($rwidth * $total);
//draw the header
$this->drawSingleChoiceHorizontalHead($categories, $responsegrouplabel);
$currentY += $this->responseLabelHeight;
//don't continue if page break already
if ($this->pageBreakOccured)
return;
for ($i = 0; $i < count($subquestions); $i++)
{
if ($split && $i == 1)
{
//don't proceed if breaking the page already
if ($this->pageBreakOccured)
return;
$this->startTransaction(); //start a transaction when one line drawn
}
$s = $subquestions[$i];
//Add box group to current layout
if ($parenttext == false)
$this->addBoxGroup(1,$s['varname'],$s['text']);
else
$this->addBoxGroup(1,$s['varname'],$parenttext . $this->subQuestionTextSeparator . $s['text']);
//Draw background
$html = "<div></div>";
$this->setBackground('question');
$this->writeHTMLCell($this->getColumnWidth(), $this->singleResponseHorizontalHeight, $this->getColumnX(), $currentY, $this->style . $html,0,1,true,true);
$this->setDefaultFont($this->responseTextFontSize);
$newlineheight = $this->singleResponseHorizontalHeight;
$heightadjust = 0;
$testcells = $this->getNumLines($s['text'],$textwidth);
if ($testcells > $this->singleResponseHorizontalMaxLines)
{
//more than two lines so need to increase the space between these questions
$heightadjust = (($this->singleResponseHorizontalHeight / $this->singleResponseHorizontalMaxLines) * ($testcells - $this->singleResponseHorizontalMaxLines));
$newlineheight = $newlineheight + $heightadjust;
$this->setBackground('question');
$this->writeHTMLCell($this->getColumnWidth(), $newlineheight, $this->getColumnX(), $currentY, $this->style . $html,0,1,true,false);
$this->setDefaultFont($this->responseTextFontSize);
$this->MultiCell($textwidth,$newlineheight,$s['text'],0,'R',false,0,$this->getColumnX(),$currentY,true,0,false,true,$newlineheight,'M',false);
}
else
{
$this->MultiCell($textwidth,$this->singleResponseHorizontalHeight,$s['text'],0,'R',false,0,$this->getColumnX(),$currentY,true,0,false,true,$this->singleResponseHorizontalHeight,'M',false);
}
$other = false;
if (isset($s['other']))
$other = true;
//Draw the categories horizontally
$rnum = 1;
foreach ($categories as $r)
{
if ($total == 1) $num = 'only';
else if ($rnum == 1) $num = 'first';
else if ($rnum < $total) $num = 'middle';
else if ($rnum == $total) $num = 'last';
$bfilled = false;
if (isset($s['defaultvalue']) && $s['defaultvalue'] !== false && $s['defaultvalue'] == $r['value'])
$bfilled = true;
$position = $this->drawHorizontalResponseBox(($this->getColumnX() + $textwidth + (($rnum - 1) * $rwidth)),$currentY + ($heightadjust/2), $num,$other,false,($total > $this->singleResponseHorizontalMax),$bfilled);
//Add box to the current layout
$this->addBox($position[0],$position[1],$position[2],$position[3],$r['value'],$r['text']);
$rnum++;
}
if (($this->GetY() - $currentY) > $newlineheight)
$currentY = $this->GetY();
else
$currentY = $currentY + $newlineheight;
$this->SetY($currentY,false);
if ($other)
$this->drawOther($s['other']);
//only allow a page break if defined and we have more than one item already on this page
if ($split && $this->pageBreakOccured && $i > 0)
{
$this->pageBreakOccured = false;
$this->rollBackTransaction(true);
$this->SetAutoPageBreak(false); //Temporarily set so we don't trigger a page break
$this->fillPageBackground();
$this->newPage();
$this->drawSingleChoiceHorizontalHead($categories, $responsegrouplabel);
//reset currentY
$currentY = $this->GetY() + $this->responseLabelHeight;
$i = $i - 1; //go back and draw subquestions on the new page
}
else
{
if ($split && $i > 0)
{
$this->commitTransaction();
$this->startTransaction(); //start a transaction to allow for splitting over pages if necessary
}
}
}
}
/**
* Draw vertical questions separately instead of in a matrix
*
* @param array $categories An array containing the category text, value, skipto and other
* @param array $subquestions An array containing the subquestions if any
* @param string|bool $parenttext The question text of the parent or false if not specified
* @param string|bool $help Help text if any for the responses
* @param string|bool $split Allow splitting this over multiple pages. 'notset' means leave default. Otherwise force setting
*
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2013-07-30
*/
protected function drawSingleChoiceVerticalSeparate($categories,$subquestions,$parenttext,$help,$split='notset')
{
for ($sc = 0; $sc < count($subquestions); $sc++)
{
$s = $subquestions[$sc];
$this->drawQuestionHead("",$this->numberToLetter($sc + 1) . ". " . $s['text'],$help);
//Don't send it twice
unset($s['text']);
$this->drawSingleChoiceVertical($categories,array(array($s)),$this->subQuestionTextSeparator . $s['text']);
}
}
/**
* Draw the head of a single choice vertical table of responses
*
* @param array $subquestions The subquestions
*
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2013-10-24
*/
protected function drawSingleChoiceVerticalHead($subquestions)
{
$currentY = $this->GetY();
$total = count($subquestions);
$rwidth = $this->singleResponseVerticalAreaWidth;
$textwidth = ($this->getColumnWidth() - $this->skipColumnWidth) - ($rwidth * $total);
$isempty = true;
$count = 0;
//First draw a background of height $this->responseLabelHeight
$html = "<div></div>";
$this->setBackground('question');
$this->writeHTMLCell($this->getColumnWidth(), $this->responseLabelHeight, $this->getColumnX(), $currentY , $this->style . $html,0,1,true,true);
$this->setDefaultFont($this->responseLabelFontSize);
//Draw a Cell for each rwidth from $textwidth + $this->getColumnX(),currentY
foreach ($subquestions as $r)
{
$y = $currentY;
$x = ($textwidth + $this->getColumnX() + ($rwidth * $count));
// Going to break the line because of long word
if ($this->wordLength($r['text']) > $this->responseLabelSmallWordLength)
$this->setDefaultFont($this->responseLabelFontSizeSmall);
$this->MultiCell($rwidth,$this->responseLabelHeight,$r['text'],0,'C',false,0,$x,$y,true,0,false,true,$this->responseLabelHeight,'B',true);
if ($this->wordLength($r['text']) > $this->responseLabelSmallWordLength)
$this->setDefaultFont($this->responseLabelFontSize);
if (!empty($r['text']))
$isempty = false;
$count++;
}
if ($isempty)
$this->SetY($currentY,false);
else
$this->SetY($currentY+$this->responseLabelHeight);
}
/**
* Draw a vertical table of single choice responses including "eye guides"
*
* @param array $categories An array containing the category text, value, skipto and other
* @param array $subquestions An array containing the subquestions if any
* @param string|bool $parenttext The question text of the parent or false if not specified
* @param string|bool $split Allow splitting this over multiple pages. 'notset' means leave default. Otherwise force setting
*
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2010-09-02
*/
protected function drawSingleChoiceVertical($categories, $subquestions = array(array('text' => '')),$parenttext = false,$split = 'notset')
{
//draw subquestions if more than one category (otherwise probably a multiple choice question)
if (count($categories) > 1)
$this->drawSingleChoiceVerticalHead($subquestions);
$total = count($subquestions);
$rwidth = $this->singleResponseVerticalAreaWidth;
$textwidth = ($this->getColumnWidth() - $this->skipColumnWidth) - ($rwidth * $total);
$currentY = $this->GetY();
$total = count($categories);
$boxcp = array();
//restrict splitting to minSplittingSingleChoiceVertical where not explicitly set in queXML
if ($split === 'notset')
$split = $this->allowSplittingSingleChoiceVertical && ($total >= $this->minSplittingSingleChoiceVertical);
for ($i = 0; $i < count($categories); $i++)
{
//don't continue if page break already (start on new page)
if ($i == 1 && $split)
{
if ($this->pageBreakOccured)
return;
$this->startTransaction(); //allow for splitting
}
$rnum = $i + 1;
$r = $categories[$i];
if ($total == 1) $num = 'only';
else if ($rnum == 1) $num = 'first';
else if ($rnum < $total) $num = 'middle';
else if ($rnum == $total) $num = 'last';
//Draw background
$html = "<div></div>";
$this->setBackground('question');
$this->writeHTMLCell($this->getColumnWidth(), $this->singleResponseAreaHeight, $this->getColumnX(), $this->GetY(), $this->style . $html,0,1,true,true);
$this->setDefaultFont($this->responseTextFontSize);
//draw text
$this->MultiCell($textwidth,$this->singleResponseAreaHeight,$r['text'],0,'R',false,0,$this->getColumnX(),$currentY,true,0,false,true,$this->singleResponseAreaHeight,'M',true);
$skipto = false;
$other = false;
if (isset($r['skipto'])) $skipto = $r['skipto'];
if (isset($r['other']) && $rnum == $total) $other = $r['other']; //only set for last in set
//draw the response boxes
for ($j = 0; $j < count($subquestions); $j++)
{
$s = $subquestions[$j];
if ($i == 0) // only need to do this once
{
if ($parenttext == false)
$this->addBoxGroup(1,$s['varname'],$s['text']);
else
$this->addBoxGroup(1,$s['varname'],$parenttext . $this->subQuestionTextSeparator . $s['text']);
//save the box group for this subquestion
$boxcp[$j] = $this->boxGroupCP;
}
else
{
//reset box group pointer to be for the correct subquestion
$this->boxGroupCP = $boxcp[$j];
}
$bfilled = false;
if (isset($s['defaultvalue']) && $s['defaultvalue'] !== false && $s['defaultvalue'] == $r['value'])
$bfilled = true;
$x = $this->getColumnX() + $textwidth + ($rwidth * $j) + ((($rwidth - $this->singleResponseBoxWidth) / 2.0 ));
//Draw the box over the top
$position = $this->drawVerticalResponseBox($x,$currentY, $num, $other, $skipto, $bfilled);
//Add box to the current layout
$this->addBox($position[0],$position[1],$position[2],$position[3],$r['value'],$r['text']);
}
if (($this->GetY() - $currentY) > $this->singleResponseAreaHeight)
$currentY = $this->GetY();
else
$currentY = $currentY + $this->singleResponseAreaHeight;
$this->SetY($currentY,false);
if ($other !== false)
{
//Display the "other" variable
$this->drawOther($other);
}
//only allow a page break if defined and we have more than one item already on this page
if ($split && $this->pageBreakOccured && $i > 0)
{
$this->pageBreakOccured = false;
$this->rollBackTransaction(true);
$this->SetAutoPageBreak(false); //Temporarily set so we don't trigger a page break
$this->fillPageBackground();
//draw an arrow indicating that this was split and will be on the next page
$boxmiddle = ($x + ($this->singleResponseBoxWidth / 2.0));
$this->SetFillColor($this->lineColour[0]);
//set the bottom of the box to be the bottom of the page
$y = $this->getPageHeight() - $this->cornerBorder - $this->arrowHeight;
$this->Polygon(array($x, $y, $boxmiddle, $y + $this->arrowHeight, $x + $this->singleResponseBoxWidth, $y),'DF',array(),$this->lineColour);
$this->setBackground('empty');
$this->newPage();
if (count($categories) > 1)
$this->drawSingleChoiceVerticalHead($subquestions);
//reset currentY
$currentY = $this->GetY();
$i = $i - 1; //go back and draw categories on the new page
//create a new box group as we are on a new page
$sbgc = 0;
foreach ($subquestions as $sbg)
{
if ($parenttext == false)
$this->addBoxGroup(1,$sbg['varname'],$sbg['text']);
else
$this->addBoxGroup(1,$sbg['varname'],$parenttext . $this->subQuestionTextSeparator . $sbg['text']);
//save the box group for this subquestion
$boxcp[$sbgc] = $this->boxGroupCP;
$sbgc++;
}
}
else
{
if ($split && $i > 0)
{
$this->commitTransaction();
$this->startTransaction(); //start a transaction to allow for splitting over pages if necessary
}
}
}
}
/**
* Draw an "other" box
*
* @param array $other An array continaing varname,text,width,defaultvalue
*
* @return TODO
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2013-05-01
*/
protected function drawOther($other)
{
$btid = 3;
if ($other['format'] == 'longtext')
$btid = 6;
$this->addBoxGroup($btid,$other['varname'],$other['text'],$other['width']);
$defaultvalue = false;
if (isset($other['defaultvalue']) && $other['defaultvalue'] !== false)
$defaultvalue = $other['defaultvalue'];
if ($btid == 3)
$this->drawText($other['text'],$other['width'],$defaultvalue);
else
$this->drawLongText($other['width'],$defaultValue,$other['text']);
//Insert a gap here
$this->Rect($this->getColumnX(),$this->GetY(),$this->getColumnWidth(),$this->subQuestionLineSpacing,'F',array(),$this->backgroundColourQuestion);
$this->SetY($this->GetY() + $this->subQuestionLineSpacing,false);
}
/**
* Draw the header of a question (question title, text and help text if any)
*
* @param string $title The question title (number)
* @param string $text The question text (can be HTML)
* @param string|bool $help The question help text or false if none (can be HTML)
* @param string|bool $specifier The question specifier text or false if none (can be HTML)
*/
protected function drawQuestionHead($title,$text,$help = false,$specifier = false)
{
$this->setBackground('question');
//Cell for question number (title) and text including a white border at the bottom
$class = "questionTitle";
//If there is a skip to this question, make the question title bigger
if (isset($this->skipToRegistry[$title]))
$class = "questionTitleSkipTo";
$html = "<table><tr><td class=\"$class\" width=\"" . $this->questionTitleWidth . "mm\">$title</td><td class=\"questionText\" width=\"" . ($this->getColumnWidth() - $this->questionTextRightMargin - $this->questionTitleWidth) . "mm\">$text</td><td></td></tr>";
if ($specifier !== false)
{
$html .= "<tr><td></td><td></td><td></td></tr><tr><td class=\"$class\" width=\"" . $this->questionTitleWidth . "mm\">&nbsp;</td><td class=\"questionSpecifier\" width=\"" . ($this->getColumnWidth() - $this->questionTextRightMargin - $this->questionTitleWidth) . "mm\">$specifier</td><td></td></tr>";
}
$html .= "</table>";
$this->writeHTMLCell($this->getColumnWidth(), 1, $this->getColumnX(), $this->GetY(), $this->style . $html,0,1,true,true);
if ($help != false)
{
$html = "<table><tr><td width=\"" . ($this->getColumnWidth() - $this->skipColumnWidth) . "mm\" class=\"questionHelp\">$help</td><td></td></tr></table>";
$this->writeHTMLCell($this->getColumnWidth(), 1, $this->getColumnX(), $this->GetY(), $this->style . $html,0,1,true,true);
}
}
/**
* Add a new section to the page
*
* @param string $text The text of the section
* @param string $desc The description of this section
* @param string $info Information for this section
*/
protected function addSection($desc = 'queXMLPDF Section',$title = false,$info = false)
{
$this->sectionCP++;
if ($title === false)
$title = $this->sectionCP;
$this->section[$this->sectionCP] = array('label' => $desc, 'title' => $title);
$html = "<span class=\"sectionTitle\">$title:</span>&nbsp;<span class=\"sectionDescription\">$desc</span>";
if ($info && !empty($info))
$html .= "<div class=\"sectionInfo\">$info</div>";
$this->setBackground('section');
$this->writeHTMLCell($this->getColumnWidth(),$this->sectionHeight,$this->getColumnX(),$this->getY(),$this->style . $html,array('B' => array('width' => 1, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => $this->backgroundColourEmpty)),1,true,true,'');
$this->setBackground('empty');
}
/**
* Convert mm to pixels based on the set ppi (dpi)
*
* @param float $mm Measurement in millimetres
* @return int Pixel value as an integer
*/
public function mm2px($mm)
{
return round($mm * ($this->ppi / self::INCH_IN_MM));
}
/**
* Make sure to fill the remaining columns on the last page
*
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2012-05-31
*/
protected function fillLastPageBackground()
{
while ($this->columnCP < $this->columns)
{
$this->fillPageBackground();
$this->SetXY($this->getColumnX(),($this->cornerBorder + $this->cornerWidth));
$this->columnCP++;
}
}
/**
* Draw the background from the current Y position to the bottom of the page
*
* @author Adam Zammit <adam.zammit@acspri.org.au>
* @since 2010-09-15
*/
protected function fillPageBackground()
{
$height = $this->getPageHeight() - $this->cornerBorder - $this->GetY() + $this->questionBorderBottom;
$html = "<div></div>";
$this->setBackground('question');
$this->writeHTMLCell($this->getColumnWidth(), $height, $this->getColumnX(), $this->GetY() - $this->questionBorderBottom, $this->style . $html,0,1,true,true);
}
/**
* Create a new queXML PDF page
*
* Draw the barcode and page corners
*
*/
protected function newPage($init = false)
{
$this->columnCP++; //increment the column pointer
if ($init || ($this->columnCP >= $this->columns)) // if it is time for a new page
{
$this->AddPage();
//Set Auto page break to false
$this->SetAutoPageBreak(false);
$this->SetMargins(0,0,0);
$this->SetHeaderMargin(0);
$this->SetFooterMargin(0);
//Shortcuts to make the code (a bit) nicer
$width = $this->getPageWidth();
$height = $this->getPageHeight();
$cb = $this->cornerBorder;
$cl = $this->cornerLength;
$this->SetDrawColor($this->lineColour[0]);
$barcodeStyle = array('border' => false, 'padding' => '0', 'bgcolor' => false, 'text' => false, 'stretch' => true);
$lineStyle = array('width' => $this->cornerWidth, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0));
//Top left
$this->Line($cb,$cb,$cb + $cl,$cb,$lineStyle);
$this->Line($cb,$cb,$cb,$cb + $cl,$lineStyle);
//Top right
$this->Line($width - $cb,$cb,$width - $cb - $cl,$cb,$lineStyle);
$this->Line($width - $cb,$cb,$width - $cb,$cb + $cl,$lineStyle);
//Bottom left
$this->Line($cb,$height - $cb,$cb + $cl,$height - $cb,$lineStyle);
$this->Line($cb,$height - $cb,$cb,$height - ($cb + $cl),$lineStyle);
//Bottom right
$this->Line($width - $cb,$height - $cb,$width - $cb - $cl,$height - $cb,$lineStyle);
$this->Line($width - $cb,$height - $cb,$width - $cb,$height - ($cb + $cl),$lineStyle);
$barcodeValue = substr(str_pad($this->questionnaireId,$this->idLength,"0",STR_PAD_LEFT),0,$this->idLength) . substr(str_pad($this->getPage(),$this->pageLength,"0",STR_PAD_LEFT),0,$this->pageLength);
//Calc X position of barcode from page width
$barcodeX = $width - ($this->barcodeMarginX + $this->barcodeW);
$this->write1DBarcode($barcodeValue, $this->barcodeType, $barcodeX, $this->barcodeY, $this->barcodeW, $this->barcodeH,'', $barcodeStyle, 'N');
//Add this page to the layout system
$b = $this->cornerBorder + ($this->cornerWidth / 2.0); //temp calc for middle of line
$this->layout[$barcodeValue] = array( 'id' => $barcodeValue,
'tlx' => $this->mm2px($b),
'tly' => $this->mm2px($b),
'trx' => $this->mm2px($width - $b),
'try' => $this->mm2px($b),
'brx' => $this->mm2px($width - $b),
'bry' => $this->mm2px($height - $b),
'blx' => $this->mm2px($b),
'bly' => $this->mm2px($height - $b),
'rotation' => 0,
'boxgroup' => array()
);
$this->layoutCP = $barcodeValue;
$this->SetXY($cb + $this->cornerWidth, $cb + $this->cornerWidth);
$this->setBackground('empty');
$this->columnCP = 0; //reset column pointer
}
else // move to a new column
{
$this->SetXY($this->getColumnX(),($this->cornerBorder + $this->cornerWidth));
}
$this->SetAutoPageBreak(true,$this->getMainPageX());
//after a new page was begun....page should not have already ended
$this->pageBreakOccured = false;
}
/**
* Override of the acceptPageBreak function
*
* Allow our page handling function to know that a page break has occured
*
* $return bool Returns false so no page break is automatically issued
*/
public function AcceptPageBreak()
{
$this->pageBreakOccured = true;
return FALSE;
}
}