PageRenderTime 52ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/codeception/codeception/src/Codeception/Module/FTP.php

https://gitlab.com/jhonn/rest
PHP | 890 lines | 484 code | 44 blank | 362 comment | 36 complexity | 7fca9c32c9ceda30115da7f677e886e3 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. namespace Codeception\Module;
  3. /**
  4. *
  5. * Works with SFTP/FTP servers.
  6. *
  7. * In order to test the contents of a specific file stored on any remote FTP/SFTP system
  8. * this module downloads a temporary file to the local system. The temporary directory is
  9. * defined by default as ```tests/_data``` to specify a different directory set the tmp config
  10. * option to your chosen path.
  11. *
  12. * Don't forget to create the folder and ensure its writable.
  13. *
  14. * Supported and tested FTP types are:
  15. *
  16. * * FTP
  17. * * SFTP
  18. *
  19. * Connection uses php build in FTP client for FTP, connection to SFTP uses [phpseclib](http://phpseclib.sourceforge.net/) pulled in using composer.
  20. *
  21. * For SFTP, add [phpseclib](http://phpseclib.sourceforge.net/) to require list.
  22. * ```
  23. * "require": {
  24. * "phpseclib/phpseclib": "0.3.6"
  25. * }
  26. * ```
  27. *
  28. * ## Status
  29. *
  30. * * Maintainer: **nathanmac**
  31. * * Stability:
  32. * - FTP: **stable**
  33. * - SFTP: **stable**
  34. * * Contact: nathan.macnamara@outlook.com
  35. *
  36. * ## Config
  37. *
  38. * * type: ftp - type of connection ftp/sftp (defaults to ftp).
  39. * * host *required* - hostname/ip address of the ftp server.
  40. * * port: 21 - port number for the ftp server
  41. * * timeout: 90 - timeout settings for connecting the ftp server.
  42. * * user: anonymous - user to access ftp server, defaults to anonymous authentication.
  43. * * password - password, defaults to empty for anonymous.
  44. * * tmp - path to local directory for storing tmp files.
  45. * * passive: true - Turns on or off passive mode (FTP only)
  46. * * cleanup: true - remove tmp files from local directory on completion.
  47. *
  48. * ### Example
  49. * #### Example (FTP)
  50. *
  51. * modules:
  52. * enabled: [FTP]
  53. * config:
  54. * FTP:
  55. * type: ftp
  56. * host: '127.0.0.1'
  57. * port: 21
  58. * timeout: 120
  59. * user: 'root'
  60. * password: 'root'
  61. * tmp: 'tests/_data/ftp'
  62. * passive: true
  63. * cleanup: false
  64. *
  65. * #### Example (SFTP)
  66. *
  67. * modules:
  68. * enabled: [FTP]
  69. * config:
  70. * FTP:
  71. * type: sftp
  72. * host: '127.0.0.1'
  73. * port: 22
  74. * timeout: 120
  75. * user: 'root'
  76. * password: 'root'
  77. * tmp: 'tests/_data/ftp'
  78. * cleanup: false
  79. *
  80. *
  81. * This module extends the Filesystem module, file contents methods are inherited from this module.
  82. */
  83. class FTP extends \Codeception\Module\Filesystem
  84. {
  85. /**
  86. * FTP/SFTP connection handler
  87. *
  88. * @var null
  89. */
  90. protected $ftp = null;
  91. /**
  92. * Configuration options and default settings
  93. *
  94. * @var array
  95. */
  96. protected $config = array(
  97. 'type' => 'ftp',
  98. 'port' => 21,
  99. 'timeout' => 90,
  100. 'user' => 'anonymous',
  101. 'password' => '',
  102. 'tmp' => 'tests/_data',
  103. 'passive' => false,
  104. 'cleanup' => true);
  105. /**
  106. * Required configuration fields
  107. *
  108. * @var array
  109. */
  110. protected $requiredFields = array('host');
  111. // ----------- SETUP METHODS BELOW HERE -------------------------//
  112. /**
  113. * Setup connection and login with config settings
  114. *
  115. * @param \Codeception\TestCase $test
  116. */
  117. public function _before(\Codeception\TestCase $test)
  118. {
  119. // Login using config settings
  120. $this->loginAs($this->config['user'], $this->config['password']);
  121. }
  122. /**
  123. * Close the FTP connection & Clear up
  124. */
  125. public function _after()
  126. {
  127. $this->_closeConnection();
  128. // Clean up temp files
  129. if ($this->config['cleanup'])
  130. {
  131. if (file_exists($this->config['tmp'] . '/ftp_data_file.tmp'))
  132. unlink($this->config['tmp'] . '/ftp_data_file.tmp');
  133. }
  134. }
  135. /**
  136. * Change the logged in user mid-way through your test, this closes the
  137. * current connection to the server and initialises and new connection.
  138. *
  139. * On initiation of this modules you are automatically logged into
  140. * the server using the specified config options or defaulted
  141. * to anonymous user if not provided.
  142. *
  143. * ``` php
  144. * <?php
  145. * $I->loginAs('user','password');
  146. * ?>
  147. * ```
  148. *
  149. * @param String $user
  150. * @param String $password
  151. */
  152. public function loginAs($user = 'anonymous', $password = '')
  153. {
  154. $this->_openConnection($user, $password); // Create new connection and login.
  155. }
  156. /**
  157. * Enters a directory on the ftp system - FTP root directory is used by default
  158. *
  159. * @param $path
  160. */
  161. public function amInPath($path)
  162. {
  163. $this->_changeDirectory($this->path = $this->absolutizePath($path) . ($path == '/' ? '' : DIRECTORY_SEPARATOR));
  164. $this->debug('Moved to ' . $this->path);
  165. }
  166. /**
  167. * Resolve path
  168. *
  169. * @param $path
  170. * @return string
  171. */
  172. protected function absolutizePath($path)
  173. {
  174. if (strpos($path, '/') === 0) return $path;
  175. return $this->path . $path;
  176. }
  177. // ----------- SEARCH METHODS BELOW HERE ------------------------//
  178. /**
  179. * Checks if file exists in path on the remote FTP/SFTP system.
  180. * DOES NOT OPEN the file when it's exists
  181. *
  182. * ``` php
  183. * <?php
  184. * $I->seeFileFound('UserModel.php','app/models');
  185. * ?>
  186. * ```
  187. *
  188. * @param $filename
  189. * @param string $path
  190. */
  191. public function seeFileFound($filename, $path = '')
  192. {
  193. $files = $this->grabFileList($path);
  194. $this->debug("see file: {$filename}");
  195. \PHPUnit_Framework_Assert::assertContains($filename, $files, "file {$filename} not found in {$path}");
  196. }
  197. /**
  198. * Checks if file exists in path on the remote FTP/SFTP system, using regular expression as filename.
  199. * DOES NOT OPEN the file when it's exists
  200. *
  201. * ``` php
  202. * <?php
  203. * $I->seeFileFoundMatches('/^UserModel_([0-9]{6}).php$/','app/models');
  204. * ?>
  205. * ```
  206. *
  207. * @param $regex
  208. * @param string $path
  209. */
  210. public function seeFileFoundMatches($regex, $path = '')
  211. {
  212. foreach ($this->grabFileList($path) as $filename)
  213. {
  214. preg_match($regex, $filename, $matches);
  215. if (!empty($matches)) {
  216. $this->debug("file '{$filename}' matches '{$regex}'");
  217. return;
  218. }
  219. }
  220. \PHPUnit_Framework_Assert::fail("no file matches found for '{$regex}'");
  221. }
  222. /**
  223. * Checks if file does not exists in path on the remote FTP/SFTP system
  224. *
  225. * @param $filename
  226. * @param string $path
  227. */
  228. public function dontSeeFileFound($filename, $path = '')
  229. {
  230. $files = $this->grabFileList($path);
  231. $this->debug("don't see file: {$filename}");
  232. \PHPUnit_Framework_Assert::assertNotContains($filename, $files);
  233. }
  234. /**
  235. * Checks if file does not exists in path on the remote FTP/SFTP system, using regular expression as filename.
  236. * DOES NOT OPEN the file when it's exists
  237. *
  238. * @param $regex
  239. * @param string $path
  240. */
  241. public function dontSeeFileFoundMatches($regex, $path = '')
  242. {
  243. foreach ($this->grabFileList($path) as $filename)
  244. {
  245. preg_match($regex, $filename, $matches);
  246. if (!empty($matches)) {
  247. \PHPUnit_Framework_Assert::fail("file matches found for {$regex}");
  248. return;
  249. }
  250. }
  251. $this->debug("no files match '{$regex}'");
  252. }
  253. // ----------- UTILITY METHODS BELOW HERE -------------------------//
  254. /**
  255. * Opens a file (downloads from the remote FTP/SFTP system to a tmp directory for processing) and stores it's content.
  256. *
  257. * Usage:
  258. *
  259. * ``` php
  260. * <?php
  261. * $I->openFile('composer.json');
  262. * $I->seeInThisFile('codeception/codeception');
  263. * ?>
  264. * ```
  265. *
  266. * @param $filename
  267. */
  268. public function openFile($filename)
  269. {
  270. $this->_openFile($this->absolutizePath($filename));
  271. }
  272. /**
  273. * Saves contents to tmp file and uploads the FTP/SFTP system.
  274. * Overwrites current file on server if exists.
  275. *
  276. * ``` php
  277. * <?php
  278. * $I->writeToFile('composer.json', 'some data here');
  279. * ?>
  280. * ```
  281. *
  282. * @param $filename
  283. * @param $contents
  284. */
  285. public function writeToFile($filename, $contents)
  286. {
  287. $this->_writeToFile($this->absolutizePath($filename), $contents);
  288. }
  289. /**
  290. * Create a directory on the server
  291. *
  292. * ``` php
  293. * <?php
  294. * $I->makeDir('vendor');
  295. * ?>
  296. * ```
  297. *
  298. * @param $dirname
  299. */
  300. public function makeDir($dirname)
  301. {
  302. $this->_makeDirectory($this->absolutizePath($dirname));
  303. }
  304. /**
  305. * Currently not supported in this module, overwrite inherited method
  306. *
  307. * @param $src
  308. * @param $dst
  309. */
  310. public function copyDir($src, $dst) {
  311. \PHPUnit_Framework_Assert::fail('copyDir() currently unsupported by FTP module');
  312. }
  313. /**
  314. * Rename/Move file on the FTP/SFTP server
  315. *
  316. * ``` php
  317. * <?php
  318. * $I->renameFile('composer.lock', 'composer_old.lock');
  319. * ?>
  320. * ```
  321. *
  322. * @param $filename
  323. * @param $rename
  324. */
  325. public function renameFile($filename, $rename)
  326. {
  327. $this->_renameDirectory($this->absolutizePath($filename), $this->absolutizePath($rename));
  328. }
  329. /**
  330. * Rename/Move directory on the FTP/SFTP server
  331. *
  332. * ``` php
  333. * <?php
  334. * $I->renameDir('vendor', 'vendor_old');
  335. * ?>
  336. * ```
  337. *
  338. * @param $dirname
  339. * @param $rename
  340. */
  341. public function renameDir($dirname, $rename)
  342. {
  343. $this->_renameDirectory($this->absolutizePath($dirname), $this->absolutizePath($rename));
  344. }
  345. /**
  346. * Deletes a file on the remote FTP/SFTP system
  347. *
  348. * ``` php
  349. * <?php
  350. * $I->deleteFile('composer.lock');
  351. * ?>
  352. * ```
  353. *
  354. * @param $filename
  355. */
  356. public function deleteFile($filename)
  357. {
  358. $this->_deleteFile($this->absolutizePath($filename));
  359. }
  360. /**
  361. * Deletes directory with all subdirectories on the remote FTP/SFTP server
  362. *
  363. * ``` php
  364. * <?php
  365. * $I->deleteDir('vendor');
  366. * ?>
  367. * ```
  368. *
  369. * @param $dirname
  370. */
  371. public function deleteDir($dirname)
  372. {
  373. $this->_deleteDirectory($this->absolutizePath($dirname));
  374. }
  375. /**
  376. * Erases directory contents on the FTP/SFTP server
  377. *
  378. * ``` php
  379. * <?php
  380. * $I->cleanDir('logs');
  381. * ?>
  382. * ```
  383. *
  384. * @param $dirname
  385. */
  386. public function cleanDir($dirname)
  387. {
  388. $this->_clearDirectory($this->absolutizePath($dirname));
  389. }
  390. // ----------- GRABBER METHODS BELOW HERE -----------------------//
  391. /**
  392. * Grabber method for returning file/folders listing in an array
  393. *
  394. * ```php
  395. * <?php
  396. * $files = $I->grabFileList();
  397. * $count = $I->grabFileList('TEST', false); // Include . .. .thumbs.db
  398. * ?>
  399. * ```
  400. *
  401. * @param string $path
  402. * @param bool $ignore - suppress '.', '..' and '.thumbs.db'
  403. * @return array
  404. */
  405. public function grabFileList($path = '', $ignore = true)
  406. {
  407. $absolutize_path = $this->absolutizePath($path) . ($path != '' && substr($path, -1) != '/' ? DIRECTORY_SEPARATOR : '');
  408. $files = $this->_listFiles($absolutize_path);
  409. $display_files = array();
  410. if (is_array($files) && !empty($files)) {
  411. $this->debug('File List:');
  412. foreach ($files as &$file) {
  413. if (strtolower($file) != '.' &&
  414. strtolower($file) != '..' &&
  415. strtolower($file) != 'thumbs.db') { // Ignore '.', '..' and 'thumbs.db'
  416. $file = str_replace($absolutize_path, '', $file); // Replace full path from file listings if returned in listing
  417. $display_files[] = $file;
  418. $this->debug(' - ' . $file);
  419. }
  420. }
  421. return $ignore ? $display_files : $files;
  422. }
  423. $this->debug("File List: <empty>");
  424. return array();
  425. }
  426. /**
  427. * Grabber method for returning file/folders count in directory
  428. *
  429. * ```php
  430. * <?php
  431. * $count = $I->grabFileCount();
  432. * $count = $I->grabFileCount('TEST', false); // Include . .. .thumbs.db
  433. * ?>
  434. * ```
  435. *
  436. * @param string $path
  437. * @param bool $ignore - suppress '.', '..' and '.thumbs.db'
  438. * @return int
  439. */
  440. public function grabFileCount($path = '', $ignore = true)
  441. {
  442. $count = count($this->grabFileList($path, $ignore));
  443. $this->debug("File Count: {$count}");
  444. return $count;
  445. }
  446. /**
  447. * Grabber method to return file size
  448. *
  449. * ```php
  450. * <?php
  451. * $size = $I->grabFileSize('test.txt');
  452. * ?>
  453. * ```
  454. *
  455. * @param $filename
  456. * @return bool
  457. */
  458. public function grabFileSize($filename)
  459. {
  460. $filesize = $this->_size($filename);
  461. $this->debug("{$filename} has a file size of {$filesize}");
  462. return $filesize;
  463. }
  464. /**
  465. * Grabber method to return last modified timestamp
  466. *
  467. * ```php
  468. * <?php
  469. * $time = $I->grabFileModified('test.txt');
  470. * ?>
  471. * ```
  472. *
  473. * @param $filename
  474. * @return bool
  475. */
  476. public function grabFileModified($filename)
  477. {
  478. $time = $this->_modified($filename);
  479. $this->debug("{$filename} was last modified at {$time}");
  480. return $time;
  481. }
  482. /**
  483. * Grabber method to return current working directory
  484. *
  485. * ```php
  486. * <?php
  487. * $pwd = $I->grabDirectory();
  488. * ?>
  489. * ```
  490. *
  491. * @return string
  492. */
  493. public function grabDirectory()
  494. {
  495. $pwd = $this->_directory();
  496. $this->debug("PWD: {$pwd}");
  497. return $pwd;
  498. }
  499. // ----------- SERVER CONNECTION METHODS BELOW HERE -------------//
  500. /**
  501. * Open a new FTP/SFTP connection and authenticate user.
  502. *
  503. * @param string $user
  504. * @param string $password
  505. */
  506. private function _openConnection($user = 'anonymous', $password = '')
  507. {
  508. $this->_closeConnection(); // Close connection if already open
  509. switch(strtolower($this->config['type']))
  510. {
  511. case 'sftp':
  512. $this->ftp = new \Net_SFTP($this->config['host'], $this->config['port'], $this->config['timeout']);
  513. if ($this->ftp === false) {
  514. $this->ftp = null;
  515. \PHPUnit_Framework_Assert::fail('failed to connect to ftp server');
  516. }
  517. if (!$this->ftp->login($user, $password)) {
  518. \PHPUnit_Framework_Assert::fail('failed to authenticate user');
  519. }
  520. break;
  521. default:
  522. $this->ftp = ftp_connect($this->config['host'], $this->config['port'], $this->config['timeout']);
  523. if ($this->ftp === false) {
  524. $this->ftp = null;
  525. \PHPUnit_Framework_Assert::fail('failed to connect to ftp server');
  526. }
  527. // Set passive mode option (ftp only option)
  528. if (isset($this->config['passive']))
  529. {
  530. ftp_pasv($this->ftp, strtolower($this->config['passive']) == 'enabled');
  531. }
  532. // Login using given access details
  533. if (!@ftp_login($this->ftp, $user, $password))
  534. {
  535. \PHPUnit_Framework_Assert::fail('failed to authenticate user');
  536. }
  537. }
  538. $pwd = $this->grabDirectory();
  539. $this->path = $pwd . ($pwd == '/' ? '' : DIRECTORY_SEPARATOR);
  540. }
  541. /**
  542. * Close open FTP/SFTP connection
  543. */
  544. private function _closeConnection()
  545. {
  546. if (!is_null($this->ftp)) {
  547. switch(strtolower($this->config['type']))
  548. {
  549. case 'sftp':
  550. break;
  551. default:
  552. ftp_close($this->ftp);
  553. }
  554. }
  555. }
  556. /**
  557. * Get the file listing for FTP/SFTP connection
  558. *
  559. * @param String $path
  560. * @return array
  561. */
  562. private function _listFiles($path)
  563. {
  564. switch(strtolower($this->config['type']))
  565. {
  566. case 'sftp':
  567. $files = @$this->ftp->nlist($path);
  568. if ($files !== false)
  569. return $files;
  570. break;
  571. default:
  572. $files = @ftp_nlist($this->ftp, $path);
  573. if ($files !== false)
  574. return $files;
  575. }
  576. \PHPUnit_Framework_Assert::fail("couldn't list files");
  577. }
  578. /**
  579. * Get the current directory for the FTP/SFTP connection
  580. *
  581. * @return string
  582. */
  583. private function _directory()
  584. {
  585. switch(strtolower($this->config['type']))
  586. {
  587. case 'sftp':
  588. if ($pwd = @$this->ftp->pwd())
  589. return $pwd;// == DIRECTORY_SEPARATOR ? '' : $pwd;
  590. break;
  591. default:
  592. if ($pwd = @ftp_pwd($this->ftp))
  593. return $pwd;
  594. }
  595. \PHPUnit_Framework_Assert::fail("couldn't get current directory");
  596. }
  597. /**
  598. * Change the working directory on the FTP/SFTP server
  599. *
  600. * @param $path
  601. */
  602. private function _changeDirectory($path)
  603. {
  604. switch(strtolower($this->config['type']))
  605. {
  606. case 'sftp':
  607. if (@$this->ftp->chdir($path))
  608. return;
  609. break;
  610. default:
  611. if (@ftp_chdir($this->ftp, $path))
  612. return;
  613. }
  614. \PHPUnit_Framework_Assert::fail("couldn't change directory {$path}");
  615. }
  616. /**
  617. * Download remote file to local tmp directory and open contents.
  618. *
  619. * @param $filename
  620. */
  621. private function _openFile($filename)
  622. {
  623. // Check local tmp directory
  624. if (!is_dir($this->config['tmp']) || !is_writeable($this->config['tmp'])) {
  625. \PHPUnit_Framework_Assert::fail('tmp directory not found or is not writable');
  626. }
  627. // Download file to local tmp directory
  628. $tmp_file = $this->config['tmp'] . "/ftp_data_file.tmp";
  629. switch(strtolower($this->config['type']))
  630. {
  631. case 'sftp':
  632. if (!@$this->ftp->get($filename, $tmp_file))
  633. \PHPUnit_Framework_Assert::fail('failed to download file to tmp directory');
  634. break;
  635. default:
  636. if (!@ftp_get($this->ftp, $tmp_file, $filename, FTP_BINARY))
  637. \PHPUnit_Framework_Assert::fail('failed to download file to tmp directory');
  638. }
  639. // Open file content to variable
  640. if($this->file = file_get_contents($tmp_file)){
  641. $this->filepath = $filename;
  642. } else {
  643. \PHPUnit_Framework_Assert::fail('failed to open tmp file');
  644. }
  645. }
  646. /**
  647. * Write data to local tmp file and upload to server
  648. *
  649. * @param $filename
  650. * @param $contents
  651. */
  652. private function _writeToFile($filename, $contents)
  653. {
  654. // Check local tmp directory
  655. if (!is_dir($this->config['tmp']) || !is_writeable($this->config['tmp'])) {
  656. \PHPUnit_Framework_Assert::fail('tmp directory not found or is not writable');
  657. }
  658. // Build temp file
  659. $tmp_file = $this->config['tmp'] . "/ftp_data_file.tmp";
  660. file_put_contents($tmp_file, $contents);
  661. // Update variables
  662. $this->filepath = $tmp_file;
  663. $this->file = $contents;
  664. // Upload the file to server
  665. switch(strtolower($this->config['type']))
  666. {
  667. case 'sftp':
  668. if (!@$this->ftp->put($filename, $tmp_file, NET_SFTP_LOCAL_FILE))
  669. \PHPUnit_Framework_Assert::fail('failed to upload file to server');
  670. break;
  671. default:
  672. if (!ftp_put($this->ftp, $filename, $tmp_file, FTP_BINARY))
  673. \PHPUnit_Framework_Assert::fail('failed to upload file to server');
  674. }
  675. }
  676. /**
  677. * Make new directory on server
  678. *
  679. * @param $path
  680. */
  681. private function _makeDirectory($path)
  682. {
  683. switch(strtolower($this->config['type']))
  684. {
  685. case 'sftp':
  686. if (!@$this->ftp->mkdir($path, true))
  687. \PHPUnit_Framework_Assert::fail("couldn't make directory {$path}");
  688. break;
  689. default:
  690. if (!@ftp_mkdir($this->ftp, $path))
  691. \PHPUnit_Framework_Assert::fail("couldn't make directory {$path}");
  692. }
  693. $this->debug("Make directory: {$path}");
  694. }
  695. /**
  696. * Rename/Move directory/file on server
  697. *
  698. * @param $path
  699. * @param $rename
  700. */
  701. private function _renameDirectory($path, $rename)
  702. {
  703. switch(strtolower($this->config['type']))
  704. {
  705. case 'sftp':
  706. if (!@$this->ftp->rename($path, $rename))
  707. \PHPUnit_Framework_Assert::fail("couldn't rename directory {$path} to {$rename}");
  708. break;
  709. default:
  710. if (!@ftp_rename($this->ftp, $path, $rename))
  711. \PHPUnit_Framework_Assert::fail("couldn't rename directory {$path} to {$rename}");
  712. }
  713. $this->debug("Renamed directory: {$path} to {$rename}");
  714. }
  715. /**
  716. * Delete file on server
  717. *
  718. * @param $filename
  719. */
  720. private function _deleteFile($filename)
  721. {
  722. switch(strtolower($this->config['type']))
  723. {
  724. case 'sftp':
  725. if (!@$this->ftp->delete($filename))
  726. \PHPUnit_Framework_Assert::fail("couldn't delete {$filename}");
  727. break;
  728. default:
  729. if (!@ftp_delete($this->ftp, $filename))
  730. \PHPUnit_Framework_Assert::fail("couldn't delete {$filename}");
  731. }
  732. $this->debug("Deleted file: {$filename}");
  733. }
  734. /**
  735. * Delete directory on server
  736. *
  737. * @param $path
  738. */
  739. private function _deleteDirectory($path)
  740. {
  741. switch(strtolower($this->config['type']))
  742. {
  743. case 'sftp':
  744. if (!@$this->ftp->delete($path, true))
  745. \PHPUnit_Framework_Assert::fail("couldn't delete directory {$path}");
  746. break;
  747. default:
  748. if (!@$this->_ftp_delete($path))
  749. \PHPUnit_Framework_Assert::fail("couldn't delete directory {$path}");
  750. }
  751. $this->debug("Deleted directory: {$path}");
  752. }
  753. /**
  754. * Function to recursively delete folder, used for PHP FTP build in client.
  755. *
  756. * @param $directory
  757. * @return bool
  758. */
  759. private function _ftp_delete($directory)
  760. {
  761. # here we attempt to delete the file/directory
  762. if( !(@ftp_rmdir($this->ftp, $directory) || @ftp_delete($this->ftp, $directory)) )
  763. {
  764. # if the attempt to delete fails, get the file listing
  765. $filelist = @ftp_nlist($this->ftp, $directory);
  766. # loop through the file list and recursively delete the FILE in the list
  767. foreach($filelist as $file)
  768. {
  769. $this->_ftp_delete($file);
  770. }
  771. #if the file list is empty, delete the DIRECTORY we passed
  772. $this->_ftp_delete($directory);
  773. }
  774. return true;
  775. }
  776. /**
  777. * Clear directory on server of all content
  778. *
  779. * @param $path
  780. */
  781. private function _clearDirectory($path)
  782. {
  783. $this->debug("Clear directory: {$path}");
  784. $this->_deleteDirectory($path);
  785. $this->_makeDirectory($path);
  786. }
  787. /**
  788. * Return the size of a given file
  789. *
  790. * @param $filename
  791. * @return bool
  792. */
  793. private function _size($filename)
  794. {
  795. switch(strtolower($this->config['type']))
  796. {
  797. case 'sftp':
  798. if ($size = @$this->ftp->size($filename))
  799. return $size;
  800. break;
  801. default:
  802. if ($size = @ftp_size($this->ftp, $filename) > 0)
  803. return $size;
  804. }
  805. \PHPUnit_Framework_Assert::fail("couldn't get the file size for {$filename}");
  806. }
  807. /**
  808. * Return the last modified time of a given file
  809. *
  810. * @param $filename
  811. * @return bool
  812. */
  813. private function _modified($filename)
  814. {
  815. switch(strtolower($this->config['type']))
  816. {
  817. case 'sftp':
  818. if ($info = @$this->ftp->lstat($filename))
  819. return $info['mtime'];
  820. break;
  821. default:
  822. if ($time = @ftp_mdtm($this->ftp, $filename))
  823. return $time;
  824. }
  825. \PHPUnit_Framework_Assert::fail("couldn't get the file size for {$filename}");
  826. }
  827. }