Usamos cookies para medir audiência e melhorar sua experiência. Você pode aceitar ou recusar a qualquer momento. Veja sobre o iMasters.
Estou continuando meus estudos sobre oop e SOLID, e queria saber se minhas classes estão violando algum principio do SOLID.
Segue a tentativa:
Upload.class.php
<?php
class Upload {
private $fileName;
private $fileSize = 2.0;
private $fileType;
private $filePath;
private $token;
protected $userFile;
public function __construct(Token $token) {
$this->token= $token;
}
public function setFileSize($maxSize) {
$this->fileSize = (float)$maxSize * 1024 * 1024;
}
public function setFileType(Array $type) {
$this->fileType = $type;
}
public function setFilePath($path) {
$this->filePath = $path;
}
public function setUserFile($userFile) {
$this->userFile = $userFile;
}
public function getFileName() {
if (is_null($this->fileName))
$this->randomName();
return $this->fileName;
}
public function uploadFile() {
if (!in_array($this->getExtension(), $this->fileType))
throw new RuntimeException("Extensão de arquivo não permitido.");
else if ($this->fileSize < $_FILES[$this->userFile]['size'])
throw new RuntimeException("Tamanho de arquivo não permitido.");
else if (!move_uploaded_file($_FILES[$this->userFile]['tmp_name'], $this->filePath.$this->getFileName()))
throw new RuntimeException("Falha ao mover arquivo.");
}
private function randomName() {
$this->fileName = $this->token->generateToken().'.'.$this->getExtension();
}
private function getExtension() {
return pathinfo($_FILES[$this->userFile]['name'], PATHINFO_EXTENSION);
}
}
?>
Esses sets, seria ideal colocar tudo no construtor?
Token.php
<?php
interface Token {
public function generateToken();
}
?>
Bin2Hex.class.php
class Bin2Hex implements Token {
public function generateToken() {
return bin2hex(openssl_random_pseudo_bytes(32));
}
}
UploadImage.class.php
<?php
class UploadImage extends Upload {
private $height;
private $width;
public function setImageHeight($height) {
$this->height = $height;
}
public function setImageWidth($width) {
$this->width = $width;
}
public function uploadFile() {
list($height, $width) = getimagesize($_FILES[$this->userFile]['tmp_name']);
if ($this->height < $height) {
throw new RuntimeException("Altura da imagem não permitida.");
} else if ($this->width < $width) {
throw new RuntimeException("Largura da imagem não permitida.");
}
parent::uploadFile();
}
}
->A ideia aqui seria uma classe mais especifica para imagem...
E a maior dúvida é se nessa parte viola o LSP (herança).
index.php
$upload = new UploadImage(new Bin2Hex());
$upload->setUserFile('photo');
$upload->setFilePath('uploads/');
$upload->setFileType(array('jpg', 'png'));
$upload->setFileSize(1.0);
$upload->setImageHeight(800);
$upload->setImageWidth(600);
try {
$upload->uploadFile();
} catch (RuntimeException $e) {
echo $e->getMessage();
}Entendi.... Agora em relação em passar os set's pelo construtor não é melhor? pois o File::setUserFile($userfile) tem que ser setado primeiro, mas ai eu penso, se eu quiser fazer varios uploads, vou ter que criar varios objetos.
Outra dúvida, então a antiga classe UploadImage, eu criaria apenas classe Image que extenderia File? E Qual seria a melhor maneira de fazer as consistencia, seria mesmo na classe Upload utilizando exceptions?
Segue a tentativa:
FileInterface
interface FileInterface {
public function setFilePath($path);
public function setFileSize($size);
public function setFileType(Array $type);
public function setRandomName(Token $token);
public function getUserFile();
public function getFilePath();
public function getFileType();
public function getFileSize();
public function getFileName();
public function getExtension();
}
File
class File implements FileInterface {
private $fileName;
private $filePath;
private $fileType;
private $fileSize = 2;
protected $userFile;
public function __construct($userFile) {
$this->userFile = $userFile;
}
public function setFilePath($path) {
$this->filePath = $path;
}
public function setFileType(Array $type) {
$this->fileType = $type;
}
public function setFileSize($size) {
$this->fileSize = (float)$size * 1024 * 1024;
}
public function setRandomName(Token $token) {
$this->fileName = $token->generateToken().'.'.$this->getExtension();
}
public function getUserFile() {
return $this->userFile;
}
public function getFilePath() {
return $this->filePath;
}
public function getFileType() {
return $this->fileType;
}
public function getFileSize() {
return $this->fileSize;
}
public function getFileName() {
return $this->fileName;
}
public function getExtension() {
return pathinfo($_FILES[$this->userFile]['name'], PATHINFO_EXTENSION);
}
}
Upload
class Upload {
public function uploadFile(FileInterface $file) {
if (!in_array($file->getExtension(), $file->getFileType()))
throw new RuntimeException("Extensão de arquivo não permitido.");
else if ($file->getFileSize() < $_FILES[$file->getUserFile()]['size'])
throw new RuntimeException("Tamanho de arquivo não permitido.");
else if (!move_uploaded_file($_FILES[$file->getUserFile()]['tmp_name'], $file->getFilePath().$file->getFileName()))
throw new RuntimeException("Falha ao mover arquivo.");
}
}
testeUpload
<?php
require_once 'autoload.php';
require_once 'display_error.php';
if (isset($_POST['submit'])) {
$file = new File('file');
$file->setFilePath('uploads/');
$file->setFileType(array('jpg', 'png', 'gif'));
$file->setFileSize(1.0);
$file->setRandomName(new Bin2Hex());
echo 'Teste1: '.$file->getFileName().'<br>';
$upload = new Upload();
$upload->uploadFile($file);
echo 'Teste2: '.$file->getFileName().'<br>';
}
?>
<form action="testeUpload.php" method="post" enctype="multipart/form-data">
<h2>Upload File</h2>
<label for="fileSelect">Filename:</label>
<input type="file" name="file"><br>
<input type="submit" name="submit" value="Upload">
</form>
Uma coisa que eu faria seria separar a sua classe upload.
interface FileInterface{
... get e set dos atributos da $_FILE
}
class File implements FileInterface
{
... atributos da $_FILE
.. Metodos get e set
}
class Upload{