use Services\Uploads\IUploadManager;\r
use Services\IUserSession;\r
use Services\IZipParser;\r
+use Services\ISMOMatcher;\r
use DataAccess\StepMania\ISimfileRepository;\r
use DataAccess\StepMania\IPackRepository;\r
use DataAccess\IFileRepository;\r
use Domain\Entities\StepMania\ISimfile;\r
-use Domain\Entities\StepMania\IPack;\r
+use Domain\Entities\IFile;\r
+use Domain\VOs\IFileMirror;\r
\r
class SimfileController implements IDivineController\r
{\r
private $_uploadManager;\r
private $_userSession;\r
private $_zipParser;\r
+ private $_smoMatcher;\r
\r
public function __construct(\r
IHttpResponse $response,\r
IPackRepository $packRepository,\r
IFileRepository $fileRepository,\r
IUserSession $userSession,\r
- IZipParser $zipParser\r
+ IZipParser $zipParser,\r
+ ISMOMatcher $smoMatcher\r
) {\r
$this->_response = $response;\r
$this->_uploadManager = $uploadManager;\r
$this->_fileRepository = $fileRepository;\r
$this->_userSession = $userSession;\r
$this->_zipParser = $zipParser;\r
+ $this->_smoMatcher = $smoMatcher;\r
}\r
\r
public function indexAction() {\r
$packSimfiles[] = $this->simfileToArray($simfile);\r
}\r
\r
+ $packMirrors = array();\r
+ if($pack->getFile()->getMirrors())\r
+ {\r
+ foreach($pack->getFile()->getMirrors() as $mirror)\r
+ {\r
+ $packMirrors = $mirror->getUri();\r
+ }\r
+ }\r
+ \r
$packArray[] = array(\r
'title'=> $pack->getTitle(),\r
'contributors' => $pack->getContributors(),\r
'simfiles' => $packSimfiles,\r
- 'banner' => $pack->getBanner() ? 'files/banner/' . $pack->getBanner()->getHash() : 'files/banner/default'\r
+ 'banner' => $pack->getBanner() ? 'files/banner/' . $pack->getBanner()->getHash() : 'files/banner/default',\r
+ 'mirrors' => $packMirrors\r
);\r
}\r
\r
{\r
$zipParser = $this->_zipParser;\r
$zipParser->parse($file);\r
- \r
+ \r
//save the actual zip in the db\r
+ $this->findAndAddSmoMirror($file);\r
$this->_fileRepository->save($file); \r
\r
if($zipParser->isPack())\r
}\r
}\r
\r
+ private function findAndAddSmoMirror(IFile $file)\r
+ {\r
+ $basename = pathinfo($file->getFilename(), PATHINFO_FILENAME);\r
+ $match = $this->_smoMatcher->match($basename, $file->getSize());\r
+ \r
+ //XXX: Direct instantiation of FileMirror bad?\r
+ if($match && $match['confidence'] > 90)\r
+ {\r
+ $file->addMirror(new \Domain\VOs\FileMirror($match['href']));\r
+ }\r
+ }\r
+ \r
private function simfileToArray(ISimfile $simfile)\r
{\r
$singleSteps = array();\r
namespace Domain\Entities;
use Domain\Entities\AbstractEntity;
+use Domain\VOs\IFileMirror;
class File extends AbstractEntity implements IFile
{
private $_mimetype;
private $_size;
private $_uploadDate;
+ private $_mirrors;
public function __construct(
$hash,
$filename,
$mimetype,
$size,
- $uploadDate
+ $uploadDate,
+ array $mirrors = null
) {
$this->_hash = $hash;
$this->_path = $path;
$this->_mimetype = $mimetype;
$this->_size = $size;
$this->_uploadDate = $uploadDate;
+
+ if($mirrors)
+ {
+ foreach($mirrors as $mirror) {
+ if(!$mirror instanceof IFileMirror) {
+ throw new InvalidStepChartException(sprintf('Invalid FileMirror array. All array elements must be an instance of IFileMirror.'));
+ }
+ }
+
+ $this->_mirrors = $mirrors;
+ }
}
public function getFilename()
{
return $this->_uploadDate;
}
+
+ public function getMirrors()
+ {
+ return $this->_mirrors;
+ }
+
+ public function addMirror(IFileMirror $mirror)
+ {
+ $this->_mirrors[] = $mirror;
+ }
}
\ No newline at end of file
private $_mimetype;
private $_size;
private $_date;
+ private $_mirrors;
public function __construct(IFileFactory $fileFactory)
{
$this->_date = $date;
}
+ public function With_Mirrors(array $mirrors = null)
+ {
+ $this->_mirrors = $mirrors;
+ }
+
public function build()
{
return $this->_fileFactory
$this->_filename,
$this->_mimetype,
$this->_size,
- $this->_date);
+ $this->_date,
+ $this->_mirrors);
}
}
\ No newline at end of file
$filename,
$mimetype,
$size,
- $uploadDate
+ $uploadDate,
+ array $mirrors = null
);
}
$filename,
$mimetype,
$size,
- $uploadDate
+ $uploadDate,
+ array $mirrors = null
) {
return new File(
- $hash,
- $path,
- $filename,
- $mimetype,
- $size,
- $uploadDate
+ $hash,
+ $path,
+ $filename,
+ $mimetype,
+ $size,
+ $uploadDate,
+ $mirrors
);
}
}
interface IFileStepByStepBuilder_With_UploadDate
{
+ public function With_Mirrors(array $mirrors = null);
public function build();
}
class FileStepByStepBuilder_With_UploadDate extends AbstractFileStepByStepBuilder implements IFileStepByStepBuilder_With_UploadDate
{
+ public function With_Mirrors(array $mirrors = null) {
+ $this->_fileBuilder->With_Mirrors($mirrors);
+ return new FileStepByStepBuilder_With_UploadDate($this->_fileBuilder);
+ }
+
public function build() {
return $this->_fileBuilder
->build();
namespace Domain\Entities;
+use Domain\VOs\IFileMirror;
+
interface IFile extends IDivineEntity
{
public function getPath();
public function getMimetype();
public function getSize();
public function getUploadDate();
+ public function getMirrors();
+ public function addMirror(IFileMirror $mirror);
}
\ No newline at end of file
public function With_Mimetype($mimetype);
public function With_Size($size);
public function With_UploadDate($date);
+ public function With_Mirrors(array $mirrors = null);
public function build();
}
\ No newline at end of file
--- /dev/null
+<?php
+
+namespace Domain\VOs;
+
+use Domain\VOs\IFileMirror;
+
+class FileMirror implements IFileMirror
+{
+ private $_uri;
+
+ public function __construct($uri)
+ {
+ $this->_uri = $uri;
+ }
+
+ public function getUri()
+ {
+ return $this->_uri;
+ }
+}
+
--- /dev/null
+<?php
+
+namespace Domain\VOs;
+
+interface IFileMirror
+{
+ public function getUri();
+}
\ No newline at end of file
--- /dev/null
+<?php
+
+namespace Services;
+
+interface ISMOMatcher
+{
+ public function match($filename, $filesize);
+}
\ No newline at end of file
--- /dev/null
+<?php
+
+namespace Services;
+
+use Services\ISMOMatcher;
+use DOMDocument;
+use DOMXPath;
+use DOMNodeList;
+
+class SMOMatcher implements ISMOMatcher
+{
+ private $_records;
+
+ public function match($title, $filesize)
+ {
+ if(!$this->scrapeSmo()) return null;
+
+ $most_likely = array('confidence' => 0);
+ foreach($this->_records as $rowNum => $row) {
+ $cells = $row->getElementsByTagName('td');
+
+ if($rowNum > 0) {
+ $candidate = $this->cellToCandidateArray($cells);
+ $this->setCandidateSimilarty($title, $filesize, $candidate);
+ $most_likely = $candidate['confidence'] > $most_likely['confidence'] ? $candidate : $most_likely;
+ }
+ }
+
+ return $most_likely;
+ }
+
+ private function scrapeSmo()
+ {
+ if($this->_records) return true;
+
+ $c = curl_init('http://stepmaniaonline.net/index.php?page=downloads');
+ curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
+ //curl_setopt(... other options you want...)
+
+ $html = curl_exec($c);
+
+ if (curl_error($c)) return false;
+
+ // Get the status code
+ $status = curl_getinfo($c, CURLINFO_HTTP_CODE);
+
+ curl_close($c);
+ //$html = file_get_contents('smo.html');
+ $dom = new DOMDocument();
+ @$dom->loadHTML($html);
+ $xpath = new DOMXPath($dom);
+
+ $table = $xpath->query("/html/body/div[@class='container']/div[@class='mid']/div[@class='content']/div[3]/div[@class='blockcontent']/table")->item(0);
+ $this->_records = $table->getElementsByTagName("tr");
+
+ return true;
+ }
+
+ private function cellToCandidateArray(DOMNodeList $cells)
+ {
+ return array(
+ 'href' => $cells->item(0)->getElementsByTagName('a')->item(0)->getAttribute('href'),
+ 'title' => $cells->item(0)->nodeValue,
+ 'filesize' => strpos($cells->item(1)->nodeValue, 'Gb') === true ? ($cells->item(1)->nodeValue)*1024*1024*1024 : ($cells->item(1)->nodeValue)*1024*1024
+ );
+ }
+
+ private function setCandidateSimilarty($title, $filesize, array &$candidate)
+ {
+ similar_text($title, $candidate['title'], $percent);
+ $r = $candidate['filesize'] > $filesize ? $filesize/$candidate['filesize'] : $candidate['filesize']/$filesize;
+ $candidate['confidence'] = $percent*$r;
+ }
+}
\ No newline at end of file
'Services\ISimfileParser' => DI\object('Services\SimfileParser'),\r
'Services\IZipParser' => DI\object('Services\ZipParser'),\r
'Services\IBannerExtracter' => DI\object('Services\BannerExtracter'),\r
+ 'Services\ISMOMatcher' => DI\object('Services\SMOMatcher'),\r
\r
//DA\r
'DataAccess\StepMania\ISimfileRepository' => DI\object('DataAccess\StepMania\SimfileRepository'),\r
'filename' => DataAccess\Varchar('filename'),\r
'mimetype' => DataAccess\Varchar('mimetype'),\r
'size' => DataAccess\Int('size'),\r
- 'uploadDate' => DataAccess\Int('uploaded', 'getUploadDate')\r
+ 'uploadDate' => DataAccess\Int('uploaded', 'getUploadDate'),\r
+ 'mirrors' => DataAccess\VOArray('FileMirror', 'getMirrors')\r
+ ]\r
+ ],\r
+ \r
+ 'FileMirror' => [\r
+ 'class' => 'Domain\VOs\FileMirror',\r
+ 'table' => 'mirrors',\r
+ 'maps' => [\r
+ 'uri' => DataAccess\Varchar('uri')\r
]\r
]\r
];\r