125 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			125 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| namespace nur\b\io;
 | |
| 
 | |
| use nulib\file\FileReader;
 | |
| use nur\v\http;
 | |
| 
 | |
| /**
 | |
|  * Class TmpfileWriter: écriture dans un fichier temporaire
 | |
|  */
 | |
| class TmpfileWriter extends FileWriter {
 | |
|   /** @var string */
 | |
|   private $output;
 | |
| 
 | |
|   /** @var bool */
 | |
|   private $delete;
 | |
| 
 | |
|   /** @throws IOException */
 | |
|   function __construct(?string $destdir=null, string $mode="w+") {
 | |
|     if ($destdir === null) $destdir = sys_get_temp_dir();
 | |
|     if (is_dir($destdir)) {
 | |
|       # si on spécifie un répertoire, créer un fichier temporaire dedans
 | |
|       $output = tempnam($destdir, "tmp_nur-base_");
 | |
|       $this->delete = true;
 | |
|     } elseif (is_file($destdir)) {
 | |
|       # si on spécifie un fichier qui existe le prendre comme "fichier
 | |
|       # temporaire" mais ne pas le supprimer automatiquement
 | |
|       $output = $destdir;
 | |
|       $this->delete = false;
 | |
|     } else {
 | |
|       # un chemin qui n'existe pas: ne le sélectionner que si le répertoire
 | |
|       # existe. dans ce cas, le fichier sera créé automatiquement, mais pas
 | |
|       # supprimé
 | |
|       if (!is_dir(dirname($destdir))) {
 | |
|         throw new IOException("$destdir: no such file or directory");
 | |
|       }
 | |
|       $output = $destdir;
 | |
|       $this->delete = false;
 | |
|     }
 | |
|     $this->output = $output;
 | |
|     parent::__construct($output, $mode);
 | |
|   }
 | |
| 
 | |
|   function __destruct() {
 | |
|     $this->close();
 | |
|     if ($this->delete) $this->delete();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * obtenir une nouvelle instance de {@link FileReader} sur le fichier
 | |
|    *
 | |
|    * cette méthode est utile si le flux a été fermé, à condition que le fichier
 | |
|    * n'aie pas été supprimé ni renommé
 | |
|    *
 | |
|    * @throws IOException
 | |
|    */
 | |
|   function getReader(): FileReader {
 | |
|     return new FileReader($this->output);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * obtenir une nouvelle instance de FileWriter sur le fichier
 | |
|    *
 | |
|    * cette méthode est utile si le flux a été fermé, à condition que le fichier
 | |
|    * n'aie pas été supprimé ni renommé
 | |
|    *
 | |
|    * @throws IOException
 | |
|    */
 | |
|   function getWriter(): FileWriter {
 | |
|     return new FileWriter($this->output);
 | |
|   }
 | |
| 
 | |
|   /** supprimer le fichier. NB: le flux **n'est pas** fermé au préalable */
 | |
|   function delete(): self {
 | |
|     if (file_exists($this->output)) unlink($this->output);
 | |
|     return $this;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * renommer le fichier. le flux est fermé d'abord
 | |
|    *
 | |
|    * @param int|null $default_mode mode par défaut si le fichier destination
 | |
|    * n'existe pas. sinon, changer le mode du fichier temporaire à la valeur du
 | |
|    * fichier destination après renommage
 | |
|    * @param bool $set_owner si le propriétaire et/ou le groupe du fichier
 | |
|    * temporaire ne sont pas les mêmes que le fichier destination, tenter de
 | |
|    * changer le propriétaire et le groupe du fichier temporaire à la valeur
 | |
|    * du fichier destination après le renommage (nécessite les droits de root)
 | |
|    * @throws IOException
 | |
|    */
 | |
|   function rename(string $dest, ?int $default_mode=0644, bool $set_owner=true): void {
 | |
|     $this->close();
 | |
|     $output = $this->output;
 | |
|     if (file_exists($dest)) {
 | |
|       $mode = fileperms($dest);
 | |
|       if ($set_owner) {
 | |
|         $tmpowner = fileowner($output);
 | |
|         $owner = fileowner($dest);
 | |
|         $tmpgroup = filegroup($output);
 | |
|         $group = filegroup($dest);
 | |
|       } else {
 | |
|         $owner = $group = null;
 | |
|       }
 | |
|     } else {
 | |
|       $mode = $default_mode;
 | |
|       $owner = $group = null;
 | |
|     }
 | |
|     if (!rename($output, $dest)) {
 | |
|       throw new IOException("$output: unable to rename to $dest");
 | |
|     }
 | |
|     if ($mode !== null) chmod($dest, $mode);
 | |
|     if ($owner !== null) {
 | |
|       if ($owner !== $tmpowner) chown($dest, $owner);
 | |
|       if ($group !== $tmpgroup) chgrp($dest, $group);
 | |
|     }
 | |
|     if ($mode !== null || $owner !== null) clearstatcache();
 | |
|   }
 | |
| 
 | |
|   /** streamer le contenu du fichier en sortie */
 | |
|   function readfile(?string $content_type=null, ?string $charset=null, ?string $filename=null, string $disposition=null): bool {
 | |
|     if ($content_type !== null) http::content_type($content_type, $charset);
 | |
|     if ($filename !== null) http::download_as($filename, $disposition);
 | |
|     return readfile($this->output) !== false;
 | |
|   }
 | |
| }
 |