89 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			89 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
namespace nur\sery\os\file;
 | 
						|
 | 
						|
use nur\sery\os\IOException;
 | 
						|
use nur\sery\web\http;
 | 
						|
 | 
						|
class TmpfileWriter extends FileWriter {
 | 
						|
  const DEFAULT_MODE = "w+b";
 | 
						|
 | 
						|
  function __construct(?string $destdir=null, ?string $mode=null, bool $throwOnError=true, ?bool $allowLocking=null) {
 | 
						|
    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
 | 
						|
      $file = tempnam($destdir, "tmp_nulib_");
 | 
						|
      $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
 | 
						|
      $file = $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");
 | 
						|
      }
 | 
						|
      $file = $destdir;
 | 
						|
      $this->delete = false;
 | 
						|
    }
 | 
						|
    parent::__construct($file, $mode, $throwOnError, $allowLocking);
 | 
						|
  }
 | 
						|
 | 
						|
  /** @var bool */
 | 
						|
  protected $delete;
 | 
						|
 | 
						|
  function __destruct() {
 | 
						|
    $this->close();
 | 
						|
    if ($this->delete) $this->delete();
 | 
						|
  }
 | 
						|
 | 
						|
  /** supprimer le fichier. NB: le flux **n'est pas** fermé au préalable */
 | 
						|
  function delete(): self {
 | 
						|
    if (file_exists($this->file)) unlink($this->file);
 | 
						|
    return $this;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * renommer le fichier. le flux est fermé d'abord
 | 
						|
   *
 | 
						|
   * @param int|null $defaultMode 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 $setOwner 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 $defaultMode=0644, bool $setOwner=true): void {
 | 
						|
    $this->close();
 | 
						|
    $file = $this->file;
 | 
						|
    if (file_exists($dest)) {
 | 
						|
      $mode = fileperms($dest);
 | 
						|
      if ($setOwner) {
 | 
						|
        $tmpowner = fileowner($file);
 | 
						|
        $owner = fileowner($dest);
 | 
						|
        $tmpgroup = filegroup($file);
 | 
						|
        $group = filegroup($dest);
 | 
						|
      } else {
 | 
						|
        $owner = $group = null;
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      $mode = $defaultMode;
 | 
						|
      $owner = $group = null;
 | 
						|
    }
 | 
						|
    if (!rename($file, $dest)) {
 | 
						|
      throw new IOException("$file: unable to rename to $dest");
 | 
						|
    }
 | 
						|
    $this->file = $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(true, $file);
 | 
						|
  }
 | 
						|
}
 |