PageRenderTime 51ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/extensions/jlextdfbnetplayerimport/admin/helpers/helper.php

https://gitlab.com/julienv/joomleague
PHP | 771 lines | 443 code | 78 blank | 250 comment | 206 complexity | 8cb832d1ad9932f52d4edf2bd6c85275 MD5 | raw file
  1. <?php
  2. class parseCSV {
  3. /*
  4. Class: parseCSV v0.4.3 beta
  5. http://code.google.com/p/parsecsv-for-php/
  6. Fully conforms to the specifications lined out on wikipedia:
  7. - http://en.wikipedia.org/wiki/Comma-separated_values
  8. Based on the concept of Ming Hong Ng's CsvFileParser class:
  9. - http://minghong.blogspot.com/2006/07/csv-parser-for-php.html
  10. Copyright (c) 2007 Jim Myhrberg (jim@zydev.info).
  11. Permission is hereby granted, free of charge, to any person obtaining a copy
  12. of this software and associated documentation files (the "Software"), to deal
  13. in the Software without restriction, including without limitation the rights
  14. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  15. copies of the Software, and to permit persons to whom the Software is
  16. furnished to do so, subject to the following conditions:
  17. The above copyright notice and this permission notice shall be included in
  18. all copies or substantial portions of the Software.
  19. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25. THE SOFTWARE.
  26. Code Examples
  27. ----------------
  28. # general usage
  29. $csv = new parseCSV('data.csv');
  30. print_r($csv->data);
  31. ----------------
  32. # tab delimited, and encoding conversion
  33. $csv = new parseCSV();
  34. $csv->encoding('UTF-16', 'UTF-8');
  35. $csv->delimiter = "\t";
  36. $csv->parse('data.tsv');
  37. print_r($csv->data);
  38. ----------------
  39. # auto-detect delimiter character
  40. $csv = new parseCSV();
  41. $csv->auto('data.csv');
  42. print_r($csv->data);
  43. ----------------
  44. # modify data in a csv file
  45. $csv = new parseCSV();
  46. $csv->sort_by = 'id';
  47. $csv->parse('data.csv');
  48. # "4" is the value of the "id" column of the CSV row
  49. $csv->data[4] = array('firstname' => 'John', 'lastname' => 'Doe', 'email' => 'john@doe.com');
  50. $csv->save();
  51. ----------------
  52. # add row/entry to end of CSV file
  53. # - only recommended when you know the extact sctructure of the file
  54. $csv = new parseCSV();
  55. $csv->save('data.csv', array('1986', 'Home', 'Nowhere', ''), true);
  56. ----------------
  57. # convert 2D array to csv data and send headers
  58. # to browser to treat output as a file and download it
  59. $csv = new parseCSV();
  60. $csv->output (true, 'movies.csv', $array);
  61. ----------------
  62. */
  63. /**
  64. * Configuration
  65. * - set these options with $object->var_name = 'value';
  66. */
  67. # use first line/entry as field names
  68. var $heading = true;
  69. # override field names
  70. var $fields = array();
  71. # sort entries by this field
  72. var $sort_by = null;
  73. var $sort_reverse = false;
  74. # sort behavior passed to ksort/krsort functions
  75. # regular = SORT_REGULAR
  76. # numeric = SORT_NUMERIC
  77. # string = SORT_STRING
  78. var $sort_type = null;
  79. # delimiter (comma) and enclosure (double quote)
  80. var $delimiter = ',';
  81. var $enclosure = '"';
  82. # basic SQL-like conditions for row matching
  83. var $conditions = null;
  84. # number of rows to ignore from beginning of data
  85. var $offset = null;
  86. # limits the number of returned rows to specified amount
  87. var $limit = null;
  88. # number of rows to analyze when attempting to auto-detect delimiter
  89. var $auto_depth = 15;
  90. # characters to ignore when attempting to auto-detect delimiter
  91. var $auto_non_chars = "a-zA-Z0-9\n\r";
  92. # preferred delimiter characters, only used when all filtering method
  93. # returns multiple possible delimiters (happens very rarely)
  94. var $auto_preferred = ",;\t.:|";
  95. # character encoding options
  96. var $convert_encoding = false;
  97. var $input_encoding = 'ISO-8859-1';
  98. var $output_encoding = 'ISO-8859-1';
  99. # used by unparse(), save(), and output() functions
  100. var $linefeed = "\r\n";
  101. # only used by output() function
  102. var $output_delimiter = ',';
  103. var $output_filename = 'data.csv';
  104. # keep raw file data in memory after successful parsing (useful for debugging)
  105. var $keep_file_data = false;
  106. /**
  107. * Internal variables
  108. */
  109. # current file
  110. var $file;
  111. # loaded file contents
  112. var $file_data;
  113. # error while parsing input data
  114. # 0 = No errors found. Everything should be fine :)
  115. # 1 = Hopefully correctable syntax error was found.
  116. # 2 = Enclosure character (double quote by default)
  117. # was found in non-enclosed field. This means
  118. # the file is either corrupt, or does not
  119. # standard CSV formatting. Please validate
  120. # the parsed data yourself.
  121. var $error = 0;
  122. # detailed error info
  123. var $error_info = array();
  124. # array of field values in data parsed
  125. var $titles = array();
  126. # two dimentional array of CSV data
  127. var $data = array();
  128. /**
  129. * Constructor
  130. * @param input CSV file or string
  131. * @return nothing
  132. */
  133. function parseCSV ($input = null, $offset = null, $limit = null, $conditions = null) {
  134. if ( $offset !== null ) $this->offset = $offset;
  135. if ( $limit !== null ) $this->limit = $limit;
  136. if ( count($conditions) > 0 ) $this->conditions = $conditions;
  137. if ( !empty($input) ) $this->parse($input);
  138. }
  139. // ==============================================
  140. // ----- [ Main Functions ] ---------------------
  141. // ==============================================
  142. /**
  143. * Parse CSV file or string
  144. * @param input CSV file or string
  145. * @return nothing
  146. */
  147. function parse ($input = null, $offset = null, $limit = null, $conditions = null) {
  148. if ( $input === null ) $input = $this->file;
  149. if ( !empty($input) ) {
  150. if ( $offset !== null ) $this->offset = $offset;
  151. if ( $limit !== null ) $this->limit = $limit;
  152. if ( count($conditions) > 0 ) $this->conditions = $conditions;
  153. if ( is_readable($input) ) {
  154. $this->data = $this->parse_file($input);
  155. } else {
  156. $this->file_data = &$input;
  157. $this->data = $this->parse_string();
  158. }
  159. if ( $this->data === false ) return false;
  160. }
  161. return true;
  162. }
  163. /**
  164. * Save changes, or new file and/or data
  165. * @param file file to save to
  166. * @param data 2D array with data
  167. * @param append append current data to end of target CSV if exists
  168. * @param fields field names
  169. * @return true or false
  170. */
  171. function save ($file = null, $data = array(), $append = false, $fields = array()) {
  172. if ( empty($file) ) $file = &$this->file;
  173. $mode = ( $append ) ? 'at' : 'wt' ;
  174. $is_php = ( preg_match('/\.php$/i', $file) ) ? true : false ;
  175. return $this->_wfile($file, $this->unparse($data, $fields, $append, $is_php), $mode);
  176. }
  177. /**
  178. * Generate CSV based string for output
  179. * @param filename if specified, headers and data will be output directly to browser as a downloable file
  180. * @param data 2D array with data
  181. * @param fields field names
  182. * @param delimiter delimiter used to separate data
  183. * @return CSV data using delimiter of choice, or default
  184. */
  185. function output ($filename = null, $data = array(), $fields = array(), $delimiter = null) {
  186. if ( empty($filename) ) $filename = $this->output_filename;
  187. if ( $delimiter === null ) $delimiter = $this->output_delimiter;
  188. $data = $this->unparse($data, $fields, null, null, $delimiter);
  189. if ( $filename !== null ) {
  190. header('Content-type: application/csv');
  191. header('Content-Disposition: attachment; filename="'.$filename.'"');
  192. echo $data;
  193. }
  194. return $data;
  195. }
  196. /**
  197. * Convert character encoding
  198. * @param input input character encoding, uses default if left blank
  199. * @param output output character encoding, uses default if left blank
  200. * @return nothing
  201. */
  202. function encoding ($input = null, $output = null) {
  203. $this->convert_encoding = true;
  204. if ( $input !== null ) $this->input_encoding = $input;
  205. if ( $output !== null ) $this->output_encoding = $output;
  206. }
  207. /**
  208. * Auto-Detect Delimiter: Find delimiter by analyzing a specific number of
  209. * rows to determine most probable delimiter character
  210. * @param file local CSV file
  211. * @param parse true/false parse file directly
  212. * @param search_depth number of rows to analyze
  213. * @param preferred preferred delimiter characters
  214. * @param enclosure enclosure character, default is double quote (").
  215. * @return delimiter character
  216. */
  217. function auto ($file = null, $parse = true, $search_depth = null, $preferred = null, $enclosure = null) {
  218. if ( $file === null ) $file = $this->file;
  219. if ( empty($search_depth) ) $search_depth = $this->auto_depth;
  220. if ( $enclosure === null ) $enclosure = $this->enclosure;
  221. if ( $preferred === null ) $preferred = $this->auto_preferred;
  222. if ( empty($this->file_data) ) {
  223. if ( $this->_check_data($file) ) {
  224. $data = &$this->file_data;
  225. } else return false;
  226. } else {
  227. $data = &$this->file_data;
  228. }
  229. $chars = array();
  230. $strlen = strlen($data);
  231. $enclosed = false;
  232. $n = 1;
  233. $to_end = true;
  234. // walk specific depth finding posssible delimiter characters
  235. for ( $i=0; $i < $strlen; $i++ ) {
  236. $ch = $data{$i};
  237. $nch = ( isset($data{$i+1}) ) ? $data{$i+1} : false ;
  238. $pch = ( isset($data{$i-1}) ) ? $data{$i-1} : false ;
  239. // open and closing quotes
  240. if ( $ch == $enclosure ) {
  241. if ( !$enclosed || $nch != $enclosure ) {
  242. $enclosed = ( $enclosed ) ? false : true ;
  243. } elseif ( $enclosed ) {
  244. $i++;
  245. }
  246. // end of row
  247. } elseif ( ($ch == "\n" && $pch != "\r" || $ch == "\r") && !$enclosed ) {
  248. if ( $n >= $search_depth ) {
  249. $strlen = 0;
  250. $to_end = false;
  251. } else {
  252. $n++;
  253. }
  254. // count character
  255. } elseif (!$enclosed) {
  256. if ( !preg_match('/['.preg_quote($this->auto_non_chars, '/').']/i', $ch) ) {
  257. if ( !isset($chars[$ch][$n]) ) {
  258. $chars[$ch][$n] = 1;
  259. } else {
  260. $chars[$ch][$n]++;
  261. }
  262. }
  263. }
  264. }
  265. // filtering
  266. $depth = ( $to_end ) ? $n-1 : $n ;
  267. $filtered = array();
  268. foreach( $chars as $char => $value ) {
  269. if ( $match = $this->_check_count($char, $value, $depth, $preferred) ) {
  270. $filtered[$match] = $char;
  271. }
  272. }
  273. // capture most probable delimiter
  274. ksort($filtered);
  275. $this->delimiter = reset($filtered);
  276. // parse data
  277. if ( $parse ) $this->data = $this->parse_string();
  278. return $this->delimiter;
  279. }
  280. // ==============================================
  281. // ----- [ Core Functions ] ---------------------
  282. // ==============================================
  283. /**
  284. * Read file to string and call parse_string()
  285. * @param file local CSV file
  286. * @return 2D array with CSV data, or false on failure
  287. */
  288. function parse_file ($file = null) {
  289. if ( $file === null ) $file = $this->file;
  290. if ( empty($this->file_data) ) $this->load_data($file);
  291. return ( !empty($this->file_data) ) ? $this->parse_string() : false ;
  292. }
  293. /**
  294. * Parse CSV strings to arrays
  295. * @param data CSV string
  296. * @return 2D array with CSV data, or false on failure
  297. */
  298. function parse_string ($data = null) {
  299. if ( empty($data) ) {
  300. if ( $this->_check_data() ) {
  301. $data = &$this->file_data;
  302. } else return false;
  303. }
  304. $white_spaces = str_replace($this->delimiter, '', " \t\x0B\0");
  305. $rows = array();
  306. $row = array();
  307. $row_count = 0;
  308. $current = '';
  309. $head = ( !empty($this->fields) ) ? $this->fields : array() ;
  310. $col = 0;
  311. $enclosed = false;
  312. $was_enclosed = false;
  313. $strlen = strlen($data);
  314. // walk through each character
  315. for ( $i=0; $i < $strlen; $i++ ) {
  316. $ch = $data{$i};
  317. $nch = ( isset($data{$i+1}) ) ? $data{$i+1} : false ;
  318. $pch = ( isset($data{$i-1}) ) ? $data{$i-1} : false ;
  319. // open/close quotes, and inline quotes
  320. if ( $ch == $this->enclosure ) {
  321. if ( !$enclosed ) {
  322. if ( ltrim($current, $white_spaces) == '' ) {
  323. $enclosed = true;
  324. $was_enclosed = true;
  325. } else {
  326. $this->error = 2;
  327. $error_row = count($rows) + 1;
  328. $error_col = $col + 1;
  329. if ( !isset($this->error_info[$error_row.'-'.$error_col]) ) {
  330. $this->error_info[$error_row.'-'.$error_col] = array(
  331. 'type' => 2,
  332. 'info' => 'Syntax error found on row '.$error_row.'. Non-enclosed fields can not contain double-quotes.',
  333. 'row' => $error_row,
  334. 'field' => $error_col,
  335. 'field_name' => (!empty($head[$col])) ? $head[$col] : null,
  336. );
  337. }
  338. $current .= $ch;
  339. }
  340. } elseif ($nch == $this->enclosure) {
  341. $current .= $ch;
  342. $i++;
  343. } elseif ( $nch != $this->delimiter && $nch != "\r" && $nch != "\n" ) {
  344. for ( $x=($i+1); isset($data{$x}) && ltrim($data{$x}, $white_spaces) == ''; $x++ ) {}
  345. if ( $data{$x} == $this->delimiter ) {
  346. $enclosed = false;
  347. $i = $x;
  348. } else {
  349. if ( $this->error < 1 ) {
  350. $this->error = 1;
  351. }
  352. $error_row = count($rows) + 1;
  353. $error_col = $col + 1;
  354. if ( !isset($this->error_info[$error_row.'-'.$error_col]) ) {
  355. $this->error_info[$error_row.'-'.$error_col] = array(
  356. 'type' => 1,
  357. 'info' =>
  358. 'Syntax error found on row '.(count($rows) + 1).'. '.
  359. 'A single double-quote was found within an enclosed string. '.
  360. 'Enclosed double-quotes must be escaped with a second double-quote.',
  361. 'row' => count($rows) + 1,
  362. 'field' => $col + 1,
  363. 'field_name' => (!empty($head[$col])) ? $head[$col] : null,
  364. );
  365. }
  366. $current .= $ch;
  367. $enclosed = false;
  368. }
  369. } else {
  370. $enclosed = false;
  371. }
  372. // end of field/row
  373. } elseif ( ($ch == $this->delimiter || $ch == "\n" || $ch == "\r") && !$enclosed ) {
  374. $key = ( !empty($head[$col]) ) ? $head[$col] : $col ;
  375. $row[$key] = ( $was_enclosed ) ? $current : trim($current) ;
  376. $current = '';
  377. $was_enclosed = false;
  378. $col++;
  379. // end of row
  380. if ( $ch == "\n" || $ch == "\r" ) {
  381. if ( $this->_validate_offset($row_count) && $this->_validate_row_conditions($row, $this->conditions) ) {
  382. if ( $this->heading && empty($head) ) {
  383. $head = $row;
  384. } elseif ( empty($this->fields) || (!empty($this->fields) && (($this->heading && $row_count > 0) || !$this->heading)) ) {
  385. if ( !empty($this->sort_by) && !empty($row[$this->sort_by]) ) {
  386. if ( isset($rows[$row[$this->sort_by]]) ) {
  387. $rows[$row[$this->sort_by].'_0'] = &$rows[$row[$this->sort_by]];
  388. unset($rows[$row[$this->sort_by]]);
  389. for ( $sn=1; isset($rows[$row[$this->sort_by].'_'.$sn]); $sn++ ) {}
  390. $rows[$row[$this->sort_by].'_'.$sn] = $row;
  391. } else $rows[$row[$this->sort_by]] = $row;
  392. } else $rows[] = $row;
  393. }
  394. }
  395. $row = array();
  396. $col = 0;
  397. $row_count++;
  398. if ( $this->sort_by === null && $this->limit !== null && count($rows) == $this->limit ) {
  399. $i = $strlen;
  400. }
  401. if ( $ch == "\r" && $nch == "\n" ) $i++;
  402. }
  403. // append character to current field
  404. } else {
  405. $current .= $ch;
  406. }
  407. }
  408. $this->titles = $head;
  409. if ( !empty($this->sort_by) ) {
  410. $sort_type = SORT_REGULAR;
  411. if ( $this->sort_type == 'numeric' ) {
  412. $sort_type = SORT_NUMERIC;
  413. } elseif ( $this->sort_type == 'string' ) {
  414. $sort_type = SORT_STRING;
  415. }
  416. ( $this->sort_reverse ) ? krsort($rows, $sort_type) : ksort($rows, $sort_type) ;
  417. if ( $this->offset !== null || $this->limit !== null ) {
  418. $rows = array_slice($rows, ($this->offset === null ? 0 : $this->offset) , $this->limit, true);
  419. }
  420. }
  421. if ( !$this->keep_file_data ) {
  422. $this->file_data = null;
  423. }
  424. return $rows;
  425. }
  426. /**
  427. * Create CSV data from array
  428. * @param data 2D array with data
  429. * @param fields field names
  430. * @param append if true, field names will not be output
  431. * @param is_php if a php die() call should be put on the first
  432. * line of the file, this is later ignored when read.
  433. * @param delimiter field delimiter to use
  434. * @return CSV data (text string)
  435. */
  436. function unparse ( $data = array(), $fields = array(), $append = false , $is_php = false, $delimiter = null) {
  437. if ( !is_array($data) || empty($data) ) $data = &$this->data;
  438. if ( !is_array($fields) || empty($fields) ) $fields = &$this->titles;
  439. if ( $delimiter === null ) $delimiter = $this->delimiter;
  440. $string = ( $is_php ) ? "<?php header('Status: 403'); die(' '); ?>".$this->linefeed : '' ;
  441. $entry = array();
  442. // create heading
  443. if ( $this->heading && !$append && !empty($fields) ) {
  444. foreach( $fields as $key => $value ) {
  445. $entry[] = $this->_enclose_value($value);
  446. }
  447. $string .= implode($delimiter, $entry).$this->linefeed;
  448. $entry = array();
  449. }
  450. // create data
  451. foreach( $data as $key => $row ) {
  452. foreach( $row as $field => $value ) {
  453. $entry[] = $this->_enclose_value($value);
  454. }
  455. $string .= implode($delimiter, $entry).$this->linefeed;
  456. $entry = array();
  457. }
  458. return $string;
  459. }
  460. /**
  461. * Load local file or string
  462. * @param input local CSV file
  463. * @return true or false
  464. */
  465. function load_data ($input = null) {
  466. $data = null;
  467. $file = null;
  468. if ( $input === null ) {
  469. $file = $this->file;
  470. } elseif ( file_exists($input) ) {
  471. $file = $input;
  472. } else {
  473. $data = $input;
  474. }
  475. if ( !empty($data) || $data = $this->_rfile($file) ) {
  476. if ( $this->file != $file ) $this->file = $file;
  477. if ( preg_match('/\.php$/i', $file) && preg_match('/<\?.*?\?>(.*)/ims', $data, $strip) ) {
  478. $data = ltrim($strip[1]);
  479. }
  480. if ( $this->convert_encoding ) $data = iconv($this->input_encoding, $this->output_encoding, $data);
  481. if ( substr($data, -1) != "\n" ) $data .= "\n";
  482. $this->file_data = &$data;
  483. return true;
  484. }
  485. return false;
  486. }
  487. // ==============================================
  488. // ----- [ Internal Functions ] -----------------
  489. // ==============================================
  490. /**
  491. * Validate a row against specified conditions
  492. * @param row array with values from a row
  493. * @param conditions specified conditions that the row must match
  494. * @return true of false
  495. */
  496. function _validate_row_conditions ($row = array(), $conditions = null) {
  497. if ( !empty($row) ) {
  498. if ( !empty($conditions) ) {
  499. $conditions = (strpos($conditions, ' OR ') !== false) ? explode(' OR ', $conditions) : array($conditions) ;
  500. $or = '';
  501. foreach( $conditions as $key => $value ) {
  502. if ( strpos($value, ' AND ') !== false ) {
  503. $value = explode(' AND ', $value);
  504. $and = '';
  505. foreach( $value as $k => $v ) {
  506. $and .= $this->_validate_row_condition($row, $v);
  507. }
  508. $or .= (strpos($and, '0') !== false) ? '0' : '1' ;
  509. } else {
  510. $or .= $this->_validate_row_condition($row, $value);
  511. }
  512. }
  513. return (strpos($or, '1') !== false) ? true : false ;
  514. }
  515. return true;
  516. }
  517. return false;
  518. }
  519. /**
  520. * Validate a row against a single condition
  521. * @param row array with values from a row
  522. * @param condition specified condition that the row must match
  523. * @return true of false
  524. */
  525. function _validate_row_condition ($row, $condition) {
  526. $operators = array(
  527. '=', 'equals', 'is',
  528. '!=', 'is not',
  529. '<', 'is less than',
  530. '>', 'is greater than',
  531. '<=', 'is less than or equals',
  532. '>=', 'is greater than or equals',
  533. 'contains',
  534. 'does not contain',
  535. );
  536. $operators_regex = array();
  537. foreach( $operators as $value ) {
  538. $operators_regex[] = preg_quote($value, '/');
  539. }
  540. $operators_regex = implode('|', $operators_regex);
  541. if ( preg_match('/^(.+) ('.$operators_regex.') (.+)$/i', trim($condition), $capture) ) {
  542. $field = $capture[1];
  543. $op = $capture[2];
  544. $value = $capture[3];
  545. if ( preg_match('/^([\'\"]{1})(.*)([\'\"]{1})$/i', $value, $capture) ) {
  546. if ( $capture[1] == $capture[3] ) {
  547. $value = $capture[2];
  548. $value = str_replace("\\n", "\n", $value);
  549. $value = str_replace("\\r", "\r", $value);
  550. $value = str_replace("\\t", "\t", $value);
  551. $value = stripslashes($value);
  552. }
  553. }
  554. if ( array_key_exists($field, $row) ) {
  555. if ( ($op == '=' || $op == 'equals' || $op == 'is') && $row[$field] == $value ) {
  556. return '1';
  557. } elseif ( ($op == '!=' || $op == 'is not') && $row[$field] != $value ) {
  558. return '1';
  559. } elseif ( ($op == '<' || $op == 'is less than' ) && $row[$field] < $value ) {
  560. return '1';
  561. } elseif ( ($op == '>' || $op == 'is greater than') && $row[$field] > $value ) {
  562. return '1';
  563. } elseif ( ($op == '<=' || $op == 'is less than or equals' ) && $row[$field] <= $value ) {
  564. return '1';
  565. } elseif ( ($op == '>=' || $op == 'is greater than or equals') && $row[$field] >= $value ) {
  566. return '1';
  567. } elseif ( $op == 'contains' && preg_match('/'.preg_quote($value, '/').'/i', $row[$field]) ) {
  568. return '1';
  569. } elseif ( $op == 'does not contain' && !preg_match('/'.preg_quote($value, '/').'/i', $row[$field]) ) {
  570. return '1';
  571. } else {
  572. return '0';
  573. }
  574. }
  575. }
  576. return '1';
  577. }
  578. /**
  579. * Validates if the row is within the offset or not if sorting is disabled
  580. * @param current_row the current row number being processed
  581. * @return true of false
  582. */
  583. function _validate_offset ($current_row) {
  584. if ( $this->sort_by === null && $this->offset !== null && $current_row < $this->offset ) return false;
  585. return true;
  586. }
  587. /**
  588. * Enclose values if needed
  589. * - only used by unparse()
  590. * @param value string to process
  591. * @return Processed value
  592. */
  593. function _enclose_value ($value = null) {
  594. if ( $value !== null && $value != '' ) {
  595. $delimiter = preg_quote($this->delimiter, '/');
  596. $enclosure = preg_quote($this->enclosure, '/');
  597. if ( preg_match("/".$delimiter."|".$enclosure."|\n|\r/i", $value) || ($value{0} == ' ' || substr($value, -1) == ' ') ) {
  598. $value = str_replace($this->enclosure, $this->enclosure.$this->enclosure, $value);
  599. $value = $this->enclosure.$value.$this->enclosure;
  600. }
  601. }
  602. return $value;
  603. }
  604. /**
  605. * Check file data
  606. * @param file local filename
  607. * @return true or false
  608. */
  609. function _check_data ($file = null) {
  610. if ( empty($this->file_data) ) {
  611. if ( $file === null ) $file = $this->file;
  612. return $this->load_data($file);
  613. }
  614. return true;
  615. }
  616. /**
  617. * Check if passed info might be delimiter
  618. * - only used by find_delimiter()
  619. * @return special string used for delimiter selection, or false
  620. */
  621. function _check_count ($char, $array, $depth, $preferred) {
  622. if ( $depth == count($array) ) {
  623. $first = null;
  624. $equal = null;
  625. $almost = false;
  626. foreach( $array as $key => $value ) {
  627. if ( $first == null ) {
  628. $first = $value;
  629. } elseif ( $value == $first && $equal !== false) {
  630. $equal = true;
  631. } elseif ( $value == $first+1 && $equal !== false ) {
  632. $equal = true;
  633. $almost = true;
  634. } else {
  635. $equal = false;
  636. }
  637. }
  638. if ( $equal ) {
  639. $match = ( $almost ) ? 2 : 1 ;
  640. $pref = strpos($preferred, $char);
  641. $pref = ( $pref !== false ) ? str_pad($pref, 3, '0', STR_PAD_LEFT) : '999' ;
  642. return $pref.$match.'.'.(99999 - str_pad($first, 5, '0', STR_PAD_LEFT));
  643. } else return false;
  644. }
  645. }
  646. /**
  647. * Read local file
  648. * @param file local filename
  649. * @return Data from file, or false on failure
  650. */
  651. function _rfile ($file = null) {
  652. if ( is_readable($file) ) {
  653. if ( !($fh = fopen($file, 'r')) ) return false;
  654. $data = fread($fh, filesize($file));
  655. fclose($fh);
  656. return $data;
  657. }
  658. return false;
  659. }
  660. /**
  661. * Write to local file
  662. * @param file local filename
  663. * @param string data to write to file
  664. * @param mode fopen() mode
  665. * @param lock flock() mode
  666. * @return true or false
  667. */
  668. function _wfile ($file, $string = '', $mode = 'wb', $lock = 2) {
  669. if ( $fp = fopen($file, $mode) ) {
  670. flock($fp, $lock);
  671. $re = fwrite($fp, $string);
  672. $re2 = fclose($fp);
  673. if ( $re != false && $re2 != false ) return true;
  674. }
  675. return false;
  676. }
  677. }
  678. ?>