Location: PHPKode > projects > PhpBMS > phpbms/include/imports.php
<?php
	class phpbmsImport{

		var $table;
		var $error = "";
		var $docError = "";
		var $row = 0;
		var $transactionIDs = array();
		var $importType;
		var $data;
		var $revertID = 0;

		// Do not manually override
		var $transactionRecords = array();
		var $tempFileID = 0;
		var $pageType = "main";


		function phpbmsImport($table, $importType = "csv"){

			$this->table = $table;
			$this->importType = $importType;
			switch($this->importType){
				case "csv":
					$this->parser = new parseCSV;
				break;
			}//end switch

			$this->table->db->logError = true;
			//So, that, when there is a db error, it will go all the way through and not just stop
			$this->table->db->stopOnError = false;
			//Won't display db errors, just log them.
			$this->table->db->showError = false;

		}//end method --imports--

		function _parseFromData($data){

			switch($this->importType){

				case "csv":

					if(is_readable($data)){
						$contents = $this->_getFile($data);

						if(is_readable($contents)){
							$this->docError = "invalid csv document";
							return false;
						}//end if

					}//end if

					$this->parser->parse($data);

					if(!count($this->parser->titles) || !count($this->parser->data)){
						$this->docError = "invalid csv document";
						return false;
					}//end if

					return true;
				break;

			}//end swtich

		}//end method --_parseFromFile--


		function _getTransactionData(){
		//needs to be changed for more complicated tables
			$inStatement = "";
			foreach($this->transactionIDs as $theid)
				$inStatement .= $theid.",";

			if($inStatement){

				$inStatement = substr($inStatement, 0, -1);

				$querystatement = "
					SELECT
						*
					FROM
						`".$this->table->maintable."`
					WHERE
						`id` IN (".$inStatement.");
					";

				$queryresult = $this->table->db->query($querystatement);

				while($therecord = $this->table->db->fetchArray($queryresult))
					$this->transactionRecords[] = $therecord;

			}//end if

		}//end method --_getTransactionData--


		function _getFile($fileName){
			if(function_exists('file_get_contents')){
				$file = addslashes(file_get_contents($fileName));
			}else{
				// If using PHP < 4.3.0 use the following:
				$file = addslashes(fread(fopen($fileName, 'r'), filesize($fileName)));
			}//end if

			return $file;
		}//end method --_getFile--

		//DO NOT CALL IN TRANSACTION
		function _storeTempCSV($fileName){
			
			$querystatement = "
				INSERT INTO
					`files`
					(
						`uuid`,
						`name`,
						`description`,
						`file`,
						`type`,
						`roleid`,
						`creationdate`,
						`createdby`,
						`modifiedby`
					)
					VALUES
					(
						'".uuid(getUuidPrefix($this->table->db, "tbld:80b4f38d-b957-bced-c0a0-ed08a0db6475"))."',
						'temporary',
						'This is a temporary import file',
						'".$this->_getFile($fileName)."',
						'phpbms/temp',
						'Admin',
						NOW(),
						'".$_SESSION["userinfo"]["id"]."',
						'".$_SESSION["userinfo"]["id"]."'

					)
				";

			$this->table->db->query($querystatement);

			$id = $this->table->db->insertId();

			if($id)
				$this->tempFileID = ((int) $id);
			else
				$this->error .= '<li> inserting temporary file failure </li>';

		}//end method --_storeTempCSV--


		function _getTempCSV($tempFileID){

			if($tempFileID){

				$querystatement = "
					SELECT
						`file`
					FROM
						`files`
					WHERE
						id = ".((int)$tempFileID)."
					";

				$queryresult = $this->table->db->query($querystatement);

				$therecord = $this->table->db->fetchArray($queryresult);

				return $therecord["file"];

			}//end if

			return false;

		}//end method --_getTempCSV--

		//DO NOT CALL IN TRANSACTION
		function _removeTempCSV($tempFileID = 0){

			$querystatement = "
				DELETE FROM
					`files`
				WHERE
					`type` = 'phpbms/temp'
					AND
					(
						`id` = ".((int)$tempFileID)."
						OR
						`creationdate` <= NOW() - INTERVAL 30 MINUTE
					);
				";

			$queryresult = $this->table->db->query($querystatement);

			$querystatement = "
				ALTER TABLE
					`files`
				AUTO_INCREMENT = ".((int) $tempFileID).";
				";

			$queryresult = $this->table->db->query($querystatement);

		}//end method --_removeTempCSV--

		//DO NOT USE THIS METHOD INSIDE AN OPEN TRANSACTION.
		//IT WILL AUTOMATICALLY COMMIT THE TRANSACTION
		function _revertAutoIncrement($revertID = 0){

			//check to see if there is a revert id (i.e. there was a valid insert)
			if($revertID)
				if(is_numeric($revertID)){

					$querystatement = "
						ALTER TABLE
							`".$this->table->maintable."`
						AUTO_INCREMENT = ".((int) $revertID).";
						";

					$this->table->db->query($querystatement);

				}//end if

		}//end method --_revertAutoIncrement--


		function importRecords($rows, $titles){

			switch($this->importType){

				case "csv":
					//count total fieldnames (top row of csv document)
					$fieldNum = count($titles);

					//the file starts at line number 1, but since line 1 is
					//supposed to be the fieldnames in the table(s), the lines
					//being insereted start @ 2.
					$rowNum = 2;

					//get the data one row at a time
					foreach($rows as $rowData){

						$theid = 0; // set for when verifification does not pass
						$verify = array(); //set for when number of field rows does not match number of titles

						//trim off leading/trailing spaces
						$trimmedRowData = array();

						foreach($rowData as $name => $data)
							$trimmedRowData[$name] = trim($data);

						//check to see if number of fieldnames is consistent for each row
						$rowFieldNum = count($trimmedRowData);

						//if valid, insert, if not, log error and don't insert.
						if($rowFieldNum == $fieldNum){
							$verify = $this->table->verifyVariables($trimmedRowData);
							if(!count($verify)){
								$createdby = NULL;
								$overrideID = true;
								$replace = false;
								if(!isset($trimmedRowData["uuid"])){
									$useUuid = true;
									$thereturn = $this->table->insertRecord($trimmedRowData, $createdby, $overrideID, $replace, $useUuid);
									$theid = $thereturn["id"];
								}else{
									$useUuid = false;
									$thereturn = $this->table->insertRecord($trimmedRowData, $createdby, $overrideID, $replace, $useUuid);
									$theid = $thereturn;
								}
							}//end if
						}else
							$this->error .= '<li> incorrect amount of fields for line number '.$rowNum.'.</li>';

						if($theid){
							//keep track of the ids in the transaction to be able to select them
							//for preview purposes
							$this->transactionIDs[] = $theid;

							//get first id to correct auto increment
							if(!$this->revertID)
								$this->revertID = $theid;
						}else
							$this->error .= '<li> failed insert for line number '.$rowNum.'.</li>';

						foreach($verify as $error)
							$this->error .= '<li class="subError">'.$error.'</li>';

						$rowNum++;

					}//end foreach
				break;

			}//end switch

		}//end method --importRecords--


		function displayTransaction($recordsArray, $fieldsArray){
		//needs to be changed for more complicated tables
			if(count($recordsArray) && count($fieldsArray)){
				?>
				<h2>Import Preview</h2>
				<div id="transactionDiv">
				<table id="transactionTable">
					<thead>
						<tr>
							<?php
							foreach($fieldsArray as $field => $junk){
								?><th align="left" nowrap="nowrap"><?php
								echo formatVariable($field);
								?></th><?php
							}//end foreach
							$field = NULL;
							?>
						</tr>
					</thead>
					<tbody>
						<?php
						$i = 1;
						foreach($recordsArray as $record){
							?><tr class="qr<?php echo $i ?>" ><?php
							foreach($fieldsArray as $field => $junk){
								?><td nowrap="nowrap"><?php
								echo formatVariable($record[$field]);
								?></td><?php
							}//end foreach
							?></tr><?php
							$i = ($i == 1)?2:1;
						}//end while
						?>
					</tbody>
				</table>
				</div>
				<?php
			}//end if

		}//end method --displayTransaction--


		function processImportPage(){

			$this->table->getTableInfo();

			if(isset($_POST["pageType"]))
				$this->pageType = $_POST["pageType"];

			if(isset($_POST["tempFileID"]))
				$this->tempFileID = ((int)$_POST["tempFileID"]);

			if(!isset($_POST["command"])){

				//happens upon first coming to page

				//remove any other temporary csv files in the `files` table
				//present from previous imports
				$this->_removeTempCSV();

				//check to see if user has the rights to be here.
				//If not, kick him to the no access page.
				if(!hasRights($this->table->importroleid))
					goURL(APP_PATH."noaccess.php");

			}else{
				//form has been submitted
				switch($_POST["command"]){

					//cancel button pressed.
					case "cancel":
						//Cancel button needs to do different things depending upon which page
						//its at.
						if($this->pageType == "main")
							goURL($this->table->backurl);
						else{
							$this->_removeTempCSV($this->tempFileID);
							$therecord["phpbmsStatus"] = "Record(s) Not Imported";
							$this->pageType = "main";
						}//end if
					break;

					case "upload":

						//check for valid file upload
						if(!$_FILES["import"]["error"] && ($_FILES["import"]["size"] > 0)){

							//check and parse the file
							if($this->_parseFromData($_FILES["import"]["tmp_name"])){

								//start transaction
								$this->table->db->startTransaction();

								$this->importRecords($this->parser->data, $this->parser->titles);

								//get data for preview purposes
								$this->_getTransactionData();
								//"undo" any inserts
								$this->table->db->rollbackTransaction();

								//DO NOT CALL IN TRANSACTION
								//ALTER TABLES AUTO COMMIT AND THE FILE NEEDS TO CARRY
								//OVER.
								$this->_revertAutoIncrement($this->revertID);
								$this->_storeTempCSV($_FILES["import"]["tmp_name"]);

							}//end if

						}else
							$this->docError .= "failed file upload";

						//switch page types
						$this->pageType = "confirm";

						if(!$this->error && !$this->docError){
							$therecord["phpbmsStatus"] = "Confirm Import";
						}elseif($this->docError){
							$therecord["phpbmsStatus"] = "Import Error: ".$this->docError;
							$this->pageType = "main";
						}else
							$therecord["phpbmsStatus"] = "Import Error";

					break;

					case "import":

						//get the contents of the stored csv document
						$CSVcontents = $this->_getTempCSV($this->tempFileID);

						//parser uses newline character to be able to parse the last line
						if(substr($CSVcontents,-1,1) != "\n")
							$CSVcontents .= "\n";


						$this->parser->parse($CSVcontents);

						$this->importRecords($this->parser->data, $this->parser->titles);

						$this->table->db->commitTransaction();

						//DO NOT CALL IN TRANSACTION

						//get rid of temporary csv document
						$this->_removeTempCSV($this->tempFileID);

						$therecord["phpbmsStatus"] = "Record(s) Imported";
						//change page type
						$this->pageType = "main";
					break;

				}//end command switch

			}// end if

			//display the title
			$therecord["title"] = $this->table->displayname." Import";
			return $therecord;

		}//end method --imports--

	}//end class --imports--


	//this class is to have different buttons, and no created/modified.
	if(class_exists("phpbmsForm")){
		class importForm extends phpbmsForm{

			function importForm($action = NULL, $method="post", $name="record", $onsubmit="return validateForm(this);", $dontSubmit = true){

				parent::phpbmsForm($action,$method,$name,$onsubmit,$dontSubmit);

			}//end method --importForm--

			function startForm($pageTitle, $pageType, $numberOfRecords = 0){

				?><form action="<?php echo htmlentities($this->action) ?>" method="<?php echo $this->method?>" name="<?php echo $this->name?>" onsubmit="<?php echo $this->onsubmit?>" <?php
					if(isset($this->enctype)) echo ' enctype="'.$this->enctype.'" ';
					if(isset($this->id)) echo ' id="'.$this->id.'" ';
				?>><?php
				if($this->dontSubmit){
					?><div id="dontSubmit"><input type="submit" value=" " onclick="return false;" /></div><?php
				} ?>
				<div id="topButtons"><?php $this->showButtons(1, $pageType, $numberOfRecords); ?></div>
				<h1 id="h1Title"><span><?php echo $pageTitle ?></span></h1><?php

			}//end method --startForm--

			function showButtons($ids = 1, $pageType = "main", $numberOfRecords = 0){
				?>
				<div class="importCancels">
					<?php if($pageType == "main"){ ?>
					<input <?php if($ids==1) {?>accesskey="u"<?php }?> title="Upload (alt+u)" id="uploadButton<?php echo $ids?>" name="command" type="submit" value="upload" class="Buttons" />
					<input id="cancelButton<?php echo $ids?>" name="command" type="submit" value="cancel" class="Buttons" <?php if($ids==1) {?>accesskey="x" <?php }?> title="(access key+x)" />
					<?php }else{?>
					<input type="submit" class="Buttons" value="import" name="command" id="import<?php echo $ids?>" title="commit" <?php if($ids==1) {?>accesskey="i"<?php }?> <?php echo ($numberOfRecords? '':'disabled="disabled"') ?>/>
					<input type="submit" class="Buttons" value="cancel" name="command" id="cancelButton<?php echo $ids?>" <?php if($ids==1) {?>accesskey="x"<?php }?> title="rollback"/>
					<?php }//end if ?>
				</div><?php
			}//end method --showButtons--

		}//end class --importForm--
	}
?>
Return current item: PhpBMS