Implement simfile uploading, parsing and saving to DB.
authorCameron Ball <cameron@getapproved.com.au>
Fri, 14 Nov 2014 09:24:37 +0000 (17:24 +0800)
committerCameron Ball <cameron@getapproved.com.au>
Fri, 14 Nov 2014 09:24:37 +0000 (17:24 +0800)
27 files changed:
Controllers/SimfileController.php
DataAccess/DataMapper/DataMapper.php
DataAccess/DataMapper/Helpers/AbstractPopulationHelper.php
DataAccess/FileRepository.php
DataAccess/IFileRepository.php
DataAccess/StepMania/SimfileRepository.php
Domain/Entities/FileBuilder.php [new file with mode: 0644]
Domain/Entities/FileFactory.php [new file with mode: 0644]
Domain/Entities/FileStepByStepBuilder.php [new file with mode: 0644]
Domain/Entities/IFileBuilder.php [new file with mode: 0644]
Domain/Entities/StepMania/ISimfile.php
Domain/Entities/StepMania/ISimfileBuilder.php
Domain/Entities/StepMania/Simfile.php
Domain/Entities/StepMania/SimfileBuilder.php
Domain/Entities/StepMania/SimfileFactory.php
Domain/Entities/StepMania/SimfileStepByStepBuilder.php
Services/BannerExtracter.php [new file with mode: 0644]
Services/IBannerExtracter.php [new file with mode: 0644]
Services/ISimfileParser.php
Services/SimfileParser.php
Services/Uploads/File.php
Services/Uploads/IFile.php
Services/Uploads/IUploadManager.php
Services/Uploads/UploadManager.php
Services/UserSession.php [new file with mode: 0644]
config/DI.php
config/DataMaps.php

index 8585cc5..47ffd7b 100644 (file)
@@ -5,40 +5,41 @@ namespace Controllers;
 use ZipArchive;\r
 use Exception;\r
 use Controllers\IDivineController;\r
-use Services\Http\IHttpRequest;\r
 use Services\Http\IHttpResponse;\r
 use Services\Uploads\IUploadManager;\r
 use Services\ISimfileParser;\r
+use Services\IUserSession;\r
+use Services\IBannerExtracter;\r
 use DataAccess\StepMania\ISimfileRepository;\r
-use DataAccess\IUserRepository;\r
 use Domain\Entities\StepMania\ISimfileStepByStepBuilder;\r
 \r
 class SimfileController implements IDivineController\r
 {\r
     private $_simfileRepository;\r
     private $_response;\r
-    private $_request;\r
     private $_uploadManager;\r
     private $_simfileParser;\r
     private $_simfileBuilder;\r
     private $_userRepository;\r
+    private $_userSession;\r
+    private $_bannerExtracter;\r
     \r
     public function __construct(\r
-        IHttpRequest $request,\r
         IHttpResponse $response,\r
         IUploadManager $uploadManager,\r
         ISimfileRepository $repository,\r
-        IUserRepository $userRepository,\r
+        IUserSession $userSession,\r
         ISimfileParser $simfileParser,\r
-        ISimfileStepByStepBuilder $simfileBuilder\r
+        ISimfileStepByStepBuilder $simfileBuilder,\r
+        IBannerExtracter $bannerExtracter\r
     ) {\r
-        $this->_request = $request;\r
         $this->_response = $response;\r
         $this->_uploadManager = $uploadManager;\r
         $this->_simfileRepository = $repository;\r
-        $this->_userRepository = $userRepository;\r
+        $this->_userSession = $userSession;\r
         $this->_simfileParser = $simfileParser;\r
         $this->_simfileBuilder = $simfileBuilder;\r
+        $this->_bannerExtracter = $bannerExtracter;\r
     }\r
     \r
     public function indexAction() {\r
@@ -93,22 +94,17 @@ class SimfileController implements IDivineController
     }\r
     \r
     public function uploadAction()\r
-    {        \r
-        //logic for if pack or individual file\r
-        $request = $this->_request->post();\r
-        //XXX: Could be a place UserService could look for token ?\r
-        $token = $request['token'];\r
-                \r
+    {                       \r
         //TODO: Put directory in config ?\r
-        $filenames = $this->_uploadManager->setDestination('../files/StepMania/')\r
-                                          ->process();\r
-        \r
-        print_r($filenames);\r
-        foreach($filenames as $filename => $hash)\r
+        $files = $this->_uploadManager->setFilesDirectory('../files')\r
+                                      ->setDestination('StepMania/')\r
+                                      ->process();\r
+\r
+        foreach($files as $file)\r
         {\r
             $za = new ZipArchive();\r
             //XXX: We assume all files are zips. Should be enforced by validation elsewhere.\r
-            $res = $za->open('../files/StepMania/' . $hash . '.zip');\r
+            $res = $za->open('../files/StepMania/' . $file->getHash() . '.zip');\r
             \r
             if($res !== true) throw new Exception ('Could not open zip for reading.');\r
             \r
@@ -117,30 +113,38 @@ class SimfileController implements IDivineController
                 $stat = $za->statIndex($i);\r
                 if(pathinfo($stat['name'], PATHINFO_EXTENSION) == 'sm')\r
                 {\r
-                    $smData = file_get_contents('zip://../files/StepMania/' . $hash . '.zip#' . $stat['name']);\r
+                    $smData = file_get_contents('zip://../files/StepMania/' . $file->getHash() . '.zip#' . $stat['name']);\r
                     break;\r
                 }\r
             }\r
-        }\r
-        \r
-        if(!$smData) throw new Exception('Could not extract simfile.');\r
-        \r
-        /* @var $parser \Services\ISimfileParser */\r
-        $parser = $this->_simfileParser;\r
-        $parser->parse($smData);\r
 \r
-        //TODO: Instantiating VOs like this bad ?\r
-        $this->_simfileBuilder->With_Title($parser->title())\r
-                              ->With_Artist(new \Domain\VOs\StepMania\Artist($parser->artist()))\r
-                              ->With_Uploader($this->_userRepository->findByAuthToken($token)) //obj\r
-                              ->With_BPM($bpm) //obj\r
-                              ->With_BpmChanges($parser->bpmChanges())\r
-                              ->With_Stops($parser->stops())\r
-                              ->With_FgChanges($parser->fgChanges())\r
-                              ->With_BgChanges($parser->bgChanges())\r
-                              ->With_Steps($steps) //obj\r
-                              ->build();\r
+            if(!$smData) throw new Exception('Could not extract simfile.');\r
+\r
+            /* @var $parser \Services\ISimfileParser */\r
+            $parser = $this->_simfileParser;\r
+            $parser->parse($smData);\r
 \r
-        //parse .sm files and save to DB. should use SimfileParser service\r
+            $banner = $this->_bannerExtracter->extractBanner('../files/StepMania/' . $file->getHash() . '.zip', $parser->banner());\r
+                        \r
+            //TODO: Create file object for banner and .zip then link them up\r
+            //shouldn't need to use repository as the mapper can create the db entries\r
+            //all in one go (I think ...)\r
+            //\r
+            //Need to make FileBuilder and FileStepByStepBuilder\r
+            $simfile = $this->_simfileBuilder->With_Title($parser->title())\r
+                                             ->With_Artist($parser->artist())\r
+                                             ->With_Uploader($this->_userSession->getCurrentUser()) //obj\r
+                                             ->With_BPM($parser->bpm())\r
+                                             ->With_BpmChanges($parser->bpmChanges())\r
+                                             ->With_Stops($parser->stops())\r
+                                             ->With_FgChanges($parser->fgChanges())\r
+                                             ->With_BgChanges($parser->bgChanges())\r
+                                             ->With_Steps($parser->steps())\r
+                                             ->With_Simfile($file)\r
+                                             ->With_Banner($banner)\r
+                                             ->build();\r
+            \r
+            $this->_simfileRepository->save($simfile);\r
+        }\r
     }\r
 }\r
index e37d377..c33b9a4 100644 (file)
@@ -57,6 +57,11 @@ class DataMapper implements IDataMapper
     {\r
         $queries = AbstractPopulationHelper::generateUpdateSaveQuery($this->_maps, $entity, $entity->getId(), $this->_db);\r
 \r
+        echo '<pre>';\r
+        print_r($queries);\r
+        echo '</pre>';\r
+        echo '<br /><br />';\r
+        \r
         $flattened = array();\r
         $flattened_tables = array();\r
         foreach($queries as $index => $query)\r
@@ -136,10 +141,15 @@ class DataMapper implements IDataMapper
             foreach($queries as $query)\r
             {\r
                 $query = str_replace('%MAIN_QUERY_ID%', end($idMap), $query);\r
+                echo $query;\r
                 $statement = $this->_db->prepare($query);\r
                 $statement->execute();\r
             }\r
         //}\r
+            \r
+        $entity->setId(end($idMap));\r
+        \r
+        return $entity;\r
     }\r
     \r
     //TODO: Implement\r
index 034a8d6..a8b8db6 100644 (file)
@@ -154,11 +154,13 @@ class AbstractPopulationHelper
                                 if($id)\r
                                 {\r
                                     $query .= sprintf('%s=%u, ',\r
-                                        strtolower($mapsHelper->getEntityName() . '_id'),\r
+                                        //strtolower($mapsHelper->getEntityName() . '_id'),\r
+                                        strtolower($mapsHelper->getTableName() . '_id'),\r
                                         $property->getId());\r
                                 } else {\r
                                     //not in db yet. make new ref\r
-                                    $queryColumnNamesAndValues[strtolower($mapsHelper->getEntityName() . '_id')] = $property->getId();\r
+                                    //$queryColumnNamesAndValues[strtolower($mapsHelper->getEntityName() . '_id')] = $property->getId();\r
+                                    $queryColumnNamesAndValues[strtolower($mapsHelper->getTableName() . '_id')] = $property->getId();\r
                                 }\r
                             } else {\r
                                 // The entity we care about references an entity that\r
index 2e8f9a4..075b7d0 100644 (file)
@@ -5,6 +5,7 @@ namespace DataAccess;
 use DataAccess\IFileRepository;
 use DataAccess\DataMapper\IDataMapper;
 use DataAccess\Queries\IQueryBuilderFactory;
+use Domain\Entities\IFile;
 
 class FileRepository implements IFileRepository
 {
@@ -46,4 +47,8 @@ class FileRepository implements IFileRepository
                 
         return reset($results);
     }
+    
+    public function save(\Domain\Entities\IFile $file) {
+        return $this->_dataMapper->save($file);
+    }
 }
index fb82c76..d20a7d1 100644 (file)
@@ -3,10 +3,12 @@
 namespace DataAccess;
 
 use DataAccess\IRepository;
+use Domain\Entities\IFile;
 
 interface IFileRepository extends IRepository
 {
     public function findByHash($hash);
+    public function save(IFile $file);
 }
 
     
index a4a1f16..d80efd5 100644 (file)
@@ -36,7 +36,7 @@ class SimfileRepository implements ISimfileRepository
     }\r
     \r
     public function save(ISimfile $entity) {\r
-        $this->_dataMapper->save($entity);\r
+        return $this->_dataMapper->save($entity);\r
     }\r
     \r
     //TODO: Implement\r
diff --git a/Domain/Entities/FileBuilder.php b/Domain/Entities/FileBuilder.php
new file mode 100644 (file)
index 0000000..d67447b
--- /dev/null
@@ -0,0 +1,63 @@
+<?php
+
+namespace Domain\Entities;
+
+use Domain\Entities\IFileFactory;
+
+class FileBuilder implements IFileBuilder
+{
+    private $_fileFactory;
+    private $_hash;
+    private $_path;
+    private $_filename;
+    private $_mimetype;
+    private $_size;
+    private $_date;
+    
+    public function __construct(IFileFactory $fileFactory)
+    {
+        $this->_fileFactory = $fileFactory;
+    }
+    
+    public function With_Filename($filename)
+    {
+        $this->_filename = $filename;
+    }
+    
+    public function With_Hash($hash)
+    {
+        $this->_hash = $hash;
+    }
+    
+    public function With_Mimetype($mimetype)
+    {
+        $this->_mimetype = $mimetype;
+    }
+    
+    public function With_Path($path)
+    {
+        $this->_path = $path;
+    }
+    
+    public function With_Size($size)
+    {
+        $this->_size = $size;
+    }
+    
+    public function With_UploadDate($date)
+    {
+        $this->_date = $date;
+    }
+    
+    public function build()
+    {
+        return $this->_fileFactory
+                    ->createInstance(
+                            $this->_hash,
+                            $this->_path,
+                            $this->_filename,
+                            $this->_mimetype,
+                            $this->_size,
+                            $this->_date);
+    }
+}
\ No newline at end of file
diff --git a/Domain/Entities/FileFactory.php b/Domain/Entities/FileFactory.php
new file mode 100644 (file)
index 0000000..dd66810
--- /dev/null
@@ -0,0 +1,38 @@
+<?php
+
+namespace Domain\Entities;
+
+use Domain\Entities\File;
+
+interface IFileFactory
+{
+    public function createInstance(
+        $hash,
+        $path,
+        $filename,
+        $mimetype,
+        $size,
+        $uploadDate
+    );
+}
+
+class FileFactory implements IFileFactory
+{
+    public function createInstance(
+        $hash,
+        $path,
+        $filename,
+        $mimetype,
+        $size,
+        $uploadDate
+    ) {
+        return new File(
+        $hash,
+        $path,
+        $filename,
+        $mimetype,
+        $size,
+        $uploadDate
+        );
+    }
+}
diff --git a/Domain/Entities/FileStepByStepBuilder.php b/Domain/Entities/FileStepByStepBuilder.php
new file mode 100644 (file)
index 0000000..1f22a6b
--- /dev/null
@@ -0,0 +1,107 @@
+<?php
+
+namespace Domain\Entities;
+
+use Domain\Entities\IFileBuilder;
+
+interface IFileStepByStepBuilder
+{
+    public function With_Hash($hash);
+}
+
+interface IFileStepByStepBuilder_With_Hash
+{
+    public function With_Path($path);
+}
+
+interface IFileStepByStepBuilder_With_Path
+{
+    public function With_Filename($filename); //TODO: Make user object
+}
+
+interface IFileStepByStepBuilder_With_Filename
+{
+    public function With_Mimetype($mimetype);
+}
+
+interface IFileStepByStepBuilder_With_Mimetype
+{
+    public function With_Size($size);
+}
+
+interface IFileStepByStepBuilder_With_Size
+{
+    public function With_UploadDate($date);
+}
+
+interface IFileStepByStepBuilder_With_UploadDate
+{
+    public function build();
+}
+
+abstract class AbstractFileStepByStepBuilder
+{
+    /* @var $_simfileBuilder Domain\Entities\StepMania\ISimfileBuilder */
+    protected $_fileBuilder;
+    
+    public function __construct(IFileBuilder $builder)
+    {
+        $this->_fileBuilder = $builder;
+    }
+}
+
+class FileStepByStepBuilder extends AbstractFileStepByStepBuilder implements IFileStepByStepBuilder
+{
+    public function With_Hash($hash) {
+        $this->_fileBuilder->With_Hash($hash);
+        return new FileStepByStepBuilder_With_Hash($this->_fileBuilder);
+    }
+}
+
+class FileStepByStepBuilder_With_Hash extends AbstractFileStepByStepBuilder implements IFileStepByStepBuilder_With_Hash
+{
+    public function With_Path($path) {
+        $this->_fileBuilder->With_Path($path);
+        return new FileStepByStepBuilder_With_Path($this->_fileBuilder);
+    }
+}
+
+class FileStepByStepBuilder_With_Path extends AbstractFileStepByStepBuilder implements IFileStepByStepBuilder_With_Path
+{
+    public function With_Filename($filename) {
+        $this->_fileBuilder->With_Filename($filename);
+        return new FileStepByStepBuilder_With_Filename($this->_fileBuilder);
+    }
+}
+
+class FileStepByStepBuilder_With_Filename extends AbstractFileStepByStepBuilder implements IFileStepByStepBuilder_With_Filename
+{
+    public function With_Mimetype($mimetype) {
+        $this->_fileBuilder->With_Mimetype($mimetype);
+        return new FileStepByStepBuilder_With_Mimetype($this->_fileBuilder);
+    }
+}
+
+class FileStepByStepBuilder_With_Mimetype extends AbstractFileStepByStepBuilder implements IFileStepByStepBuilder_With_Mimetype
+{
+    public function With_Size($size) {
+        $this->_fileBuilder->With_Size($size);
+        return new FileStepByStepBuilder_With_Size($this->_fileBuilder);
+    }
+}
+
+class FileStepByStepBuilder_With_Size extends AbstractFileStepByStepBuilder implements IFileStepByStepBuilder_With_Size
+{
+    public function With_UploadDate($date) {
+        $this->_fileBuilder->With_UploadDate($date);
+        return new FileStepByStepBuilder_With_UploadDate($this->_fileBuilder);
+    }
+}
+
+class FileStepByStepBuilder_With_UploadDate extends AbstractFileStepByStepBuilder implements IFileStepByStepBuilder_With_UploadDate
+{
+    public function build() {
+        return $this->_fileBuilder
+                    ->build();
+    }
+}
\ No newline at end of file
diff --git a/Domain/Entities/IFileBuilder.php b/Domain/Entities/IFileBuilder.php
new file mode 100644 (file)
index 0000000..95b7ab4
--- /dev/null
@@ -0,0 +1,14 @@
+<?php
+
+namespace Domain\Entities;
+
+interface IFileBuilder
+{
+    public function With_Hash($hash);
+    public function With_Path($path);
+    public function With_Filename($filename);
+    public function With_Mimetype($mimetype);
+    public function With_Size($size);
+    public function With_UploadDate($date);
+    public function build();
+}
\ No newline at end of file
index b8e4608..40e179f 100644 (file)
@@ -16,6 +16,7 @@ interface ISimfile extends IDivineEntity
     public function hasFgChanges();\r
     public function hasBgChanges();\r
     public function getBanner();\r
+    public function getSimfile();\r
         \r
     public function addStepChart(IStepChart $stepChart);\r
     public function getSteps();\r
index 90ea697..3f76097 100644 (file)
@@ -5,6 +5,7 @@ namespace Domain\Entities\StepMania;
 use Domain\VOs\StepMania\IArtist;\r
 use Domain\VOs\StepMania\IBPM;\r
 use Domain\Entities\IUser;\r
+use Domain\Entities\IFile;\r
 \r
 interface ISimfileBuilder\r
 {\r
@@ -16,5 +17,8 @@ interface ISimfileBuilder
     public function With_Stops($const);\r
     public function With_FgChanges($const);\r
     public function With_BgChanges($const);\r
+    public function With_Banner(IFile $banner);\r
+    public function With_Simfile(Ifile $simfile);\r
     public function With_Steps(array $steps);\r
+    public function build();\r
 }
\ No newline at end of file
index d0ddc66..243f02f 100644 (file)
@@ -23,6 +23,7 @@ class Simfile extends AbstractEntity implements ISimfile
     private $_fgChanges = false;\r
     private $_bgChanges = false;\r
     private $_banner;\r
+    private $_simfile;\r
     private $_steps;\r
     \r
     public function __construct(\r
@@ -35,6 +36,7 @@ class Simfile extends AbstractEntity implements ISimfile
         $fgChanges,\r
         $bgChanges,\r
         IFile $banner = null,\r
+        IFile $simfile = null,\r
         array $steps\r
     ) {\r
         $this->_title = $title;\r
@@ -46,6 +48,7 @@ class Simfile extends AbstractEntity implements ISimfile
         $this->_fgChanges = $fgChanges;\r
         $this->_bgChanges = $bgChanges;\r
         $this->_banner = $banner;\r
+        $this->_simfile = $simfile;\r
 \r
         foreach($steps as $stepChart) {\r
             if(!$stepChart instanceof IStepChart) {\r
@@ -105,6 +108,11 @@ class Simfile extends AbstractEntity implements ISimfile
         return $this->_banner;\r
     }\r
     \r
+    public function getSimfile()\r
+    {\r
+        return $this->_simfile;\r
+    }\r
+    \r
     public function getSteps()\r
     {\r
         return $this->_steps;\r
index 034fc8d..bc80945 100644 (file)
@@ -5,6 +5,7 @@ namespace Domain\Entities\StepMania;
 use Domain\VOs\StepMania\IArtist;\r
 use Domain\VOs\StepMania\IBPM;\r
 use Domain\Entities\IUser;\r
+use Domain\Entities\IFile;\r
 use Domain\Entities\StepMania\ISimfileFactory;\r
 use Domain\Entities\StepMania\ISimfileBuilder;\r
 \r
@@ -20,6 +21,8 @@ class SimfileBuilder implements ISimfileBuilder
     private $_stops;\r
     private $_fgChanges;\r
     private $_bgChanges;\r
+    private $_banner;\r
+    private $_simfile;\r
     private $_steps;\r
     \r
     //override parent\r
@@ -68,6 +71,16 @@ class SimfileBuilder implements ISimfileBuilder
         return $this;\r
     }\r
     \r
+    public function With_Banner(IFile $banner) {\r
+        $this->_banner = $banner;\r
+        return $this;\r
+    }\r
+    \r
+    public function With_Simfile(IFile $simfile) {\r
+        $this->_simfile = $simfile;\r
+        return $this;\r
+    }\r
+    \r
     public function With_Steps(array $steps) {\r
         $this->_steps = $steps;\r
         return $this;\r
@@ -83,6 +96,8 @@ class SimfileBuilder implements ISimfileBuilder
                                      $this->_stops,\r
                                      $this->_fgChanges,\r
                                      $this->_bgChanges,\r
+                                     $this->_banner,\r
+                                     $this->_simfile,\r
                                      $this->_steps);\r
     }\r
 }\r
index a784562..33c939a 100644 (file)
@@ -6,6 +6,7 @@ use Domain\VOs\StepMania\IArtist;
 use Domain\VOs\StepMania\IBPM;\r
 use Domain\Entities\StepMania\Simfile;\r
 use Domain\Entities\IUser;\r
+use Domain\Entities\IFile;\r
 \r
 interface ISimfileFactory\r
 {\r
@@ -18,6 +19,8 @@ interface ISimfileFactory
         $stops,\r
         $fgChanges,\r
         $bgChanges,\r
+        IFile $banner,\r
+        IFile $simfile,\r
         array $steps\r
     );\r
 }\r
@@ -33,6 +36,8 @@ class SimfileFactory implements ISimfileFactory
         $stops,\r
         $fgChanges,\r
         $bgChanges,\r
+        IFile $banner = null,\r
+        IFile $simfile = null,\r
         array $steps\r
     ) {\r
         return new Simfile(\r
@@ -44,6 +49,8 @@ class SimfileFactory implements ISimfileFactory
             $stops,\r
             $fgChanges,\r
             $bgChanges,\r
+            $banner,\r
+            $simfile,\r
             $steps\r
         );\r
     }\r
index 5516ade..dfc5cbb 100644 (file)
@@ -7,6 +7,7 @@ use Domain\VOs\StepMania\IArtist;
 use Domain\VOs\StepMania\IBPM;\r
 use Domain\Entities\StepMania\ISimfileBuilder;\r
 use Domain\Entities\IUser;\r
+use Domain\Entities\IFile;\r
 \r
 interface ISimfileStepByStepBuilder\r
 {\r
@@ -55,6 +56,8 @@ interface ISimfileStepByStepBuilder_With_BgChanges
 \r
 interface ISimfileStepByStepBuilder_With_Steps\r
 {\r
+    public function With_Banner(IFile $banner);\r
+    public function With_Simfile(IFile $simfile);\r
     public function build();\r
 }\r
 \r
@@ -147,6 +150,16 @@ class SimfileStepByStepBuilder_With_BgChanges extends AbstractSimfileStepByStepB
 \r
 class SimfileStepByStepBuilder_With_Steps extends AbstractSimfileStepByStepBuilder implements ISimfileStepByStepBuilder_With_Steps\r
 {\r
+    public function With_Banner(IFile $banner) {\r
+        $this->_simfileBuilder->With_Banner($banner);\r
+        return new SimfileStepByStepBuilder_With_Steps($this->_simfileBuilder);\r
+    }\r
+    \r
+    public function With_Simfile(IFile $simfile) {\r
+        $this->_simfileBuilder->With_Simfile($simfile);\r
+        return new SimfileStepByStepBuilder_With_Steps($this->_simfileBuilder);\r
+    }\r
+    \r
     public function build() {\r
         return $this->_simfileBuilder\r
                     ->build();\r
diff --git a/Services/BannerExtracter.php b/Services/BannerExtracter.php
new file mode 100644 (file)
index 0000000..843fd8b
--- /dev/null
@@ -0,0 +1,64 @@
+<?php
+
+namespace Services;
+
+use ZipArchive;
+use finfo;
+use Exception;
+use Services\IBannerExtracter;
+use DataAccess\IFileRepository;
+use Domain\Entities\IFileStepByStepBuilder;
+
+class BannerExtracter implements IBannerExtracter
+{
+    private $_builder;
+    private $_destinationFileName;
+    private $_hash;
+    private $_fileRepository;
+
+    public function __construct(IFileStepByStepBuilder $builder, IFileRepository $fileRepository) {
+        $this->_builder = $builder;
+        $this->_fileRepository = $fileRepository;
+    }
+    
+    public function extractBanner($zipfile, $bannerName) {
+        $za = new ZipArchive();
+        //XXX: We assume all files are zips. Should be enforced by validation elsewhere.
+        $res = $za->open($zipfile);
+
+        if($res !== true) throw new Exception ('Could not open zip for reading.');
+
+        for($i=0; $i<$za->numFiles; $i++)
+        {
+            $stat = $za->statIndex($i);
+            if(basename($stat['name']) == $bannerName)
+            {
+                $this->_hash = $this->randomFilename($bannerName);
+                $this->_destinationFileName = $this->_hash . '.' . pathinfo($bannerName, PATHINFO_EXTENSION);
+                $result = copy('zip://' . $zipfile . '#' . $stat['name'], '../files/banners/' . $this->_destinationFileName);
+                break;
+            }
+        }
+
+        if(!isset($result) || !$result) throw new Exception('Could not extract banner.');
+
+        $finfo = new finfo(FILEINFO_MIME);
+        $mimetype = $finfo->file('../files/banners/' . $this->_destinationFileName);
+        $size = filesize('../files/banners/' . $this->_destinationFileName);
+        /* @var $fff \Domain\Entities\FileStepByStepBuilder */
+        $file= $this->_builder->With_Hash($this->_hash)
+                              ->With_Path('banners')
+                              ->With_Filename($bannerName)
+                              ->With_Mimetype($mimetype)
+                              ->With_Size($size)
+                              ->With_UploadDate(time())
+                              ->build();
+        
+        return $this->_fileRepository->save($file);
+    }
+    
+    private function randomFilename($seed)
+    {
+        return sha1(mt_rand(1, 9999) . $seed . uniqid() . time());
+    }
+}
\ No newline at end of file
diff --git a/Services/IBannerExtracter.php b/Services/IBannerExtracter.php
new file mode 100644 (file)
index 0000000..7407367
--- /dev/null
@@ -0,0 +1,8 @@
+<?php
+
+namespace Services;
+
+interface IBannerExtracter
+{
+    public function extractBanner($zipfile, $bannerName);
+}
index 059dec0..b3037c0 100644 (file)
@@ -8,9 +8,11 @@ interface ISimfileParser
     public function title();
     public function subtitle();
     public function artist();
+    public function bpm();
     public function bpmChanges();
     public function stops();
     public function bgChanges();
     public function fgChanges();
     public function steps();
+    public function banner();
 }
\ No newline at end of file
index ee485e7..161db7d 100644 (file)
@@ -24,6 +24,11 @@ class SimfileParser implements ISimfileParser
         $this->_smFileLines = explode(";", $simfileData);
     }
     
+    public function banner()
+    {
+        return $this->extractKey('BANNER') ?: null;
+    }
+    
     public function title()
     {
         $title = $this->extractKey('TITLE');
@@ -37,7 +42,7 @@ class SimfileParser implements ISimfileParser
         $artist = $this->extractKey('ARTIST');
         if(!$artist) throw new Exception ('Invalid SM file. ARTIST missing');
         
-        return $artist;
+        return new \Domain\VOs\StepMania\Artist($artist);
     }
     
     public function stops()
@@ -56,6 +61,22 @@ class SimfileParser implements ISimfileParser
         return $fgChanges;
     }
     
+    public function bpm()
+    {
+        $displayBpm = $this->extractKey('DISPLAYBPM');
+        
+        if($displayBpm)
+        {
+            $bpmRange = explode(":",$displayBpm);
+        } else {
+            $bpms = $this->extractKey('BPMS');
+            $bpmRange = $this->parseBpms($bpms);
+        }
+        
+        //I have nfi why I made the BPM VO high-low instead of low-high in the constructor but yolo
+        return new \Domain\VOs\StepMania\BPM($bpmRange[1], $bpmRange[0]);
+    }
+    
     public function bgChanges()
     {
         $bgChanges = $this->extractKey('BGCHANGES') ? 'Yes' : 'No';
@@ -66,7 +87,7 @@ class SimfileParser implements ISimfileParser
     
     public function bpmChanges() 
     {
-        $bmpChanges = $this->extractKey('BPMS') ? 'Yes' : 'No';
+        $bpmChanges = $this->extractKey('BPMS') ? 'Yes' : 'No';
         if(!$bpmChanges) throw new Exception ('Invalid SM file. BPMS missing');
         
         return $bpmChanges;
@@ -91,26 +112,23 @@ class SimfileParser implements ISimfileParser
             if ($pos !== false)
             {
                 $noteData = trim(substr($line, $pos + 9));
-                $allSteps = array_merge($allSteps, $this->stepsArrayFromNoteData($noteData));
+                $allSteps[] = $this->stepchartFromNoteData($noteData);
             }
         }
-
+        
         if(empty($allSteps)) throw new Exception('Invalid Sm file. NOTES missing');
         return $allSteps;
     }
-
-    private function stepsArrayFromNoteData($noteData)
+    
+    private function stepchartFromNoteData($noteData)
     {
         $stepData = array_map('trim', explode(':', $noteData));
-        $steps = array();
-        $mode = $stepData[0] == 'dance-single' ? 'single' : null;
-        $steps[$mode][] = array(
-            'artist' => $stepData[1],
-            'difficulty' => $stepData[2],
-            'rating' => $stepData[3]
+        return new \Domain\VOs\StepMania\StepChart(
+            new \Domain\VOs\StepMania\DanceMode($stepData[0]),
+            new \Domain\VOs\StepMania\Difficulty($stepData[2]),
+            new \Domain\VOs\StepMania\StepArtist($stepData[1]),
+            $stepData[3]
         );
-        
-        return $steps;
     }
     
     private function extractKey($key)
@@ -123,4 +141,23 @@ class SimfileParser implements ISimfileParser
             if ($pos !== false) return trim(substr($line, $pos + strlen($key) + 2));
         }
     }
+    
+    private function parseBpms($bpms)
+    {
+        $bpms = explode(",", $bpms);
+        $bpmRange = array('high' => null, 'low' => null);
+
+        foreach($bpms as $bpm)
+        {
+                $bpmMeasure = explode('=', $bpm);
+                $bpmValue = floatval($bpmMeasure[1]);
+
+                if(empty($bpmRange['low'])) $bpmRange['low'] = $bpmRange['high'] = $bpmValue;
+
+                $bpmRange['high'] = ($bpmValue > $bpmRange['high']) ? $bpmValue : $bpmRange['high'];
+                $bpmRange['low'] = ($bpmValue < $bpmRange['low']) ? $bpmValue : $bpmRange['low'];
+        }
+        
+        return array($bpmRange['low'], $bpmRange['high']);
+    }
 }
index 084ef75..3e493d0 100644 (file)
@@ -32,4 +32,14 @@ class File implements IFile {
     {
         return $this->_name;
     }
+    
+    public function getType()
+    {
+        return $this->_type;
+    }
+    
+    public function getSize()
+    {
+        return $this->_size;
+    }
 }
index 7a624c5..d75d2e3 100644 (file)
@@ -6,4 +6,6 @@ interface IFile {
     public function getExtension();
     public function getName();
     public function getTempName();
+    public function getType();
+    public function getSize();
 }
\ No newline at end of file
index 29ac7a7..5843c40 100644 (file)
@@ -3,6 +3,7 @@
 namespace Services\Uploads;
 
 interface IUploadManager {
+    public function setFilesDirectory($path);
     public function setDestination($path);
     public function process();
 }
index be9bc76..0bfa03e 100644 (file)
@@ -5,16 +5,25 @@ namespace Services\Uploads;
 use Services\Uploads\IUploadManager;
 use Services\Uploads\IFileFactory;
 use Services\Uploads\IFile;
+//This was a bit silly, I have a File object to use with the service but there is also a File entity.
+//It's confusing but if you pay attention it should be OK.
+use Domain\Entities\IFileStepByStepBuilder;
+use DataAccess\IFileRepository;
 use Exception;
 
 class UploadManager implements IUploadManager{        
     
     private $_files= array();
     private $_fileFactory;
+    private $_basePath;
     private $_destination;
+    private $_fileBuilder;
+    private $_fileRepository;
         
-    public function __construct(IFileFactory $fileFactory) {
+    public function __construct(IFileFactory $fileFactory, IFileStepByStepBuilder $builder, IFileRepository $fileRepository) {
         $this->_fileFactory = $fileFactory;
+        $this->_fileBuilder = $builder;
+        $this->_fileRepository = $fileRepository;
         
         if($_FILES) {
             foreach($_FILES as $file)
@@ -29,12 +38,23 @@ class UploadManager implements IUploadManager{
         }
     }
     
-   public function setDestination($path) {
+    public function setFilesDirectory($path) {
         if(!$this->destinationExists($path))
         {
             throw new Exception('Invalid path. Path does not exist.');
         }
         
+        $this->_basePath = $path;
+        
+        return $this;
+    }
+    
+    public function setDestination($path) {
+        if(!$this->destinationExists($this->_basePath . '/' . $path))
+        {
+            throw new Exception('Invalid path. Path does not exist.');
+        }
+        
         $this->_destination = $path;
         
         return $this;
@@ -49,7 +69,7 @@ class UploadManager implements IUploadManager{
         if($this->_destination)
         {
             $randomName = $this->randomFilename();
-            $result = move_uploaded_file($file->getTempName(), $this->_destination . '/' . $randomName . '.' . $file->getExtension());
+            $result = move_uploaded_file($file->getTempName(), $this->_basePath . '/' . $this->_destination . '/' . $randomName . '.' . $file->getExtension());
         }
         
         if(!$result)
@@ -71,7 +91,18 @@ class UploadManager implements IUploadManager{
         
         foreach($this->_files as $file)
         {
-            $results[$file->getName()] = $this->saveFile($file);
+            $hash = $this->saveFile($file);
+            
+            /* @var $file \Services\Uploads\IFile */
+            $file = $this->_fileBuilder->With_Hash($hash)
+                                       ->With_Path(rtrim($this->_destination, '/'))
+                                       ->With_Filename($file->getName())
+                                       ->With_Mimetype($file->getType())
+                                       ->With_Size($file->getSize())
+                                       ->With_UploadDate(time())
+                                       ->build();
+            
+            $results[] = $this->_fileRepository->save($file);
         }
         
         return $results;
diff --git a/Services/UserSession.php b/Services/UserSession.php
new file mode 100644 (file)
index 0000000..f56d56f
--- /dev/null
@@ -0,0 +1,48 @@
+<?php
+
+namespace Services;
+
+use Services\Http\IHttpRequest;
+use DataAccess\IUserRepository;
+
+class UserSession implements IUserSession
+{
+    private $_userRepository;
+    private $_request;
+    private $_currentUser;
+    
+    public function __construct(IHttpRequest $request, IUserRepository $repository)
+    {
+        $this->_request = $request;
+        $this->_userRepository = $repository;
+
+        $token = $this->findToken();
+        $this->_currentUser = $token ? $this->_userRepository->findByAuthToken($token) : null;
+    }
+    
+    public function getCurrentUser()
+    {
+        return $this->_currentUser;
+    }
+    
+    private function findToken()
+    {        
+        if($this->_request->isPost())
+        {
+            $request = $this->_request->post();
+            if(!empty($request['token'])) return $request['token'];
+        }
+        
+        if($this->_request->isGet())
+        {
+            $request = $this->_request->get();
+            if(!empty($request['token'])) return $request['token'];
+        }
+        
+        //no good, try the body
+        $body = json_decode($this->_request->getBody(), true);
+        if(!empty($body['token'])) return $body['token'];
+        
+        return null;
+    }
+}
\ No newline at end of file
index c5afcff..298fe53 100644 (file)
@@ -15,6 +15,9 @@ return [
     'Domain\Entities\StepMania\ISimfileStepByStepBuilder' => DI\object('Domain\Entities\StepMania\SimfileStepByStepBuilder'),\r
     'Domain\Entities\StepMania\ISimfileBuilder' => DI\object('Domain\Entities\StepMania\SimfileBuilder'),\r
     'Domain\Entities\StepMania\ISimfileFactory' => DI\object('Domain\Entities\StepMania\SimfileFactory'),\r
+    'Domain\Entities\IFileStepByStepBuilder' => DI\object('Domain\Entities\FileStepByStepBuilder'),\r
+    'Domain\Entities\IFileBuilder' => DI\object('Domain\Entities\FileBuilder'),\r
+    'Domain\Entities\IFileFactory' => DI\object('Domain\Entities\FileFactory'),\r
     \r
     //services\r
     'Services\Http\IHttpResponse' => DI\object('Services\Http\HttpResponse'),\r
@@ -22,10 +25,12 @@ return [
     'Services\Routing\IRouter' => DI\object('Services\Routing\Router')\r
         ->constructor(DI\link('router.maps')),\r
     'Services\Uploads\IUploadManager' => DI\object('Services\Uploads\UploadManager'),\r
+    'Services\IUserSession' => DI\object('Services\UserSession'),\r
     'Services\Uploads\IFileFactory' => DI\object('Services\Uploads\FileFactory'),\r
     'Services\IFacebookSessionFactory' => DI\object('Services\FacebookSessionFactory')\r
         ->constructor(DI\link('facebook.app')),\r
     'Services\ISimfileParser' => DI\object('Services\SimfileParser'),\r
+    'Services\IBannerExtracter' => DI\object('Services\BannerExtracter'),\r
     \r
     //DA\r
     'DataAccess\StepMania\ISimfileRepository' => DI\object('DataAccess\StepMania\SimfileRepository'),\r
index d18492f..fb9da91 100644 (file)
@@ -21,6 +21,7 @@ return [
             'fgChanges' => DataAccess\Int('fg_changes', 'hasFgChanges'),\r
             'bgChanges' => DataAccess\Int('bg_changes', 'hasBgChanges'),\r
             'banner' => DataAccess\Entity('File', 'getBanner', 'banner_file'),\r
+            'simfile' => DataAccess\Entity('File', 'getSimfile', 'simfile_file'),\r
             'steps' => DataAccess\VOArray('StepChart', 'getSteps')\r
         ]\r
     ],\r
@@ -123,8 +124,7 @@ return [
             'filename' => DataAccess\Varchar('filename'),\r
             'mimetype' => DataAccess\Varchar('mimetype'),\r
             'size' => DataAccess\Int('size'),\r
-            //TODO: actually this is stored as a datetime, might need datetime helper for stuff\r
-            'uploadDate' => DataAccess\Varchar('uploaded')\r
+            'uploadDate' => DataAccess\Int('uploaded', 'getUploadDate')\r
         ]\r
     ]\r
 ];\r