\r
namespace Controllers;\r
\r
+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 DataAccess\StepMania\ISimfileRepository;\r
+use DataAccess\IUserRepository;\r
+use Domain\Entities\StepMania\ISimfileStepByStepBuilder;\r
\r
class SimfileController implements IDivineController\r
{\r
private $_response;\r
private $_request;\r
private $_uploadManager;\r
+ private $_simfileParser;\r
+ private $_simfileBuilder;\r
+ private $_userRepository;\r
\r
public function __construct(\r
IHttpRequest $request,\r
IHttpResponse $response,\r
IUploadManager $uploadManager,\r
- ISimfileRepository $repository\r
+ ISimfileRepository $repository,\r
+ IUserRepository $userRepository,\r
+ ISimfileParser $simfileParser,\r
+ ISimfileStepByStepBuilder $simfileBuilder\r
) {\r
$this->_request = $request;\r
$this->_response = $response;\r
$this->_uploadManager = $uploadManager;\r
$this->_simfileRepository = $repository;\r
+ $this->_userRepository = $userRepository;\r
+ $this->_simfileParser = $simfileParser;\r
+ $this->_simfileBuilder = $simfileBuilder;\r
}\r
\r
public function indexAction() {\r
public function uploadAction()\r
{ \r
//logic for if pack or individual file\r
- \r
+ $request = $this->_request->post();\r
+ //XXX: Could be a place UserService could look for token ?\r
+ $token = $request['token'];\r
+ \r
//TODO: Put directory in config ?\r
$filenames = $this->_uploadManager->setDestination('../files/StepMania/')\r
->process();\r
\r
- //parse .sm files and save to DB. should use SimfileParser service\r
- \r
- echo '<pre>';\r
print_r($filenames);\r
- echo '</pre>';\r
- }\r
- \r
- public function testAction($testArg)\r
- {\r
- $this->_response->setHeader('Content-Type', 'application/json')\r
- ->setBody(json_encode(array('testArg' => $testArg)))\r
- ->sendResponse();\r
+ foreach($filenames as $filename => $hash)\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
+ \r
+ if($res !== true) throw new Exception ('Could not open zip for reading.');\r
+ \r
+ for($i=0; $i<$za->numFiles; $i++)\r
+ {\r
+ $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
+ 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
+\r
+ //parse .sm files and save to DB. should use SimfileParser service\r
}\r
}\r
use Domain\Entities\IUser;
use DataAccess\Queries\IQueryBuilderFactory;
use Services\IFacebookSessionFactory;
+use Facebook\FacebookRequest;
+use Facebook\GraphUser;
//TODO: Implement some sort of caching. Probably OK for now not to worry.
class UserRepository implements IUserRepository
public function findByAuthToken($token) {
$facebookSession = $this->_facebookSessionFactory->createInstance($token);
- $id = $facebookSession->getGraphObject(GraphUser::className())->getId();
+ $facebookRequest = (new FacebookRequest($facebookSession, 'GET', '/me?fields=hometown,first_name,last_name'))->execute();
+
+ $id = $facebookRequest->getGraphObject(GraphUser::className())->getId();
return $this->findByFacebookId($id);
}
interface ISimfileParser
{
+ public function parse($smFileData);
public function title();
public function subtitle();
+ public function artist();
public function bpmChanges();
public function stops();
public function bgChanges();
--- /dev/null
+<?php
+
+namespace Services;
+
+interface IUserSession
+{
+ public function getCurrentUser();
+}
+
private $_smFileLines;
- public function __construct($simfileData)
+ public function parse($simfileData)
{
//XXX: Should I explode on ';' instead? That seems like it might be a more reliable delimiter
- $this->_smFileLines = explode("\n", $simfileData);
+ $this->_smFileLines = explode(";", $simfileData);
}
public function title()
{
$title = $this->extractKey('TITLE');
- if(!$title) throw new Exception ('Invalid SM file. Title missing');
+ if(!$title) throw new Exception ('Invalid SM file. TITLE missing');
return $title;
}
+ public function artist()
+ {
+ $artist = $this->extractKey('ARTIST');
+ if(!$artist) throw new Exception ('Invalid SM file. ARTIST missing');
+
+ return $artist;
+ }
+
public function stops()
{
- return $this->extractKey('STOPS') ? 'Yes' : 'No';
+ $stops = $this->extractKey('STOPS') ? 'Yes' : 'No';
+ if(!$stops) throw new Exception ('Invalid SM file. STOPS missing');
+
+ return $stops;
}
- public function steps($mode, $difficulty)
+ public function fgChanges()
{
- $steps = array();
+ $fgChanges = $this->extractKey('FGCHANGES') ? 'Yes' : 'No';
+ if(!$fgChanges) throw new Exception ('Invalid SM file. FGCHANGES missing');
+
+ return $fgChanges;
+ }
+
+ public function bgChanges()
+ {
+ $bgChanges = $this->extractKey('BGCHANGES') ? 'Yes' : 'No';
+ if(!$bgChanges) throw new Exception ('Invalid SM file. BGCHANGES missing');
+
+ return $bgChanges;
+ }
+
+ public function bpmChanges()
+ {
+ $bmpChanges = $this->extractKey('BPMS') ? 'Yes' : 'No';
+ if(!$bpmChanges) throw new Exception ('Invalid SM file. BPMS missing');
+
+ return $bpmChanges;
+ }
+
+ public function subtitle()
+ {
+ $subtitle = $this->extractKey('SUBTITLE');
+ if(!$subtitle) throw new Exception ('Invalid SM file. SUBTITLE missing');
- foreach ($this->_smFileLines as $index => $line) {
- if (strpos($line, '#NOTES') !== false) {
- $mode = substr(trim($lines[$index + 1]), 0, -1) == 'dance-single' ? 'single' : null;
- $notes[$mode][] = array(
- 'artist' => substr(trim($lines[$index + 2]), 0, -1),
- 'difficulty' => substr(trim($lines[$index + 3]), 0, -1),
- 'rating' => substr(trim($lines[$index + 4]), 0, -1)
- );
+ return $subtitle;
+ }
+
+ function steps()
+ {
+ if(empty($this->_smFileLines)) throw new Exception('SM file data not set.');
+ $allSteps = array();
+
+ foreach ($this->_smFileLines as $line)
+ {
+ $pos = strpos($line, '#NOTES:');
+ if ($pos !== false)
+ {
+ $noteData = trim(substr($line, $pos + 9));
+ $allSteps = array_merge($allSteps, $this->stepsArrayFromNoteData($noteData));
}
}
+ if(empty($allSteps)) throw new Exception('Invalid Sm file. NOTES missing');
+ return $allSteps;
+ }
+
+ private function stepsArrayFromNoteData($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 $steps;
}
- private function extractKey($key) {
- foreach ($lines as $line) {
+ private function extractKey($key)
+ {
+ if(empty($this->_smFileLines)) throw new Exception('SM file data not set.');
+
+ foreach ($this->_smFileLines as $line)
+ {
$pos = strpos($line, '#' . $key . ':');
- if($pos !== false) return substr(trim($line), strlen($key) + 2, -1);
+ if ($pos !== false) return trim(substr($line, $pos + strlen($key) + 2));
}
}
-
}
--- /dev/null
+<?php
+
+namespace Services;
+
+use Services\IUserSession;
+use Services\Http\IHttpRequest;
+use DataAccess\IUserRepository;
+
+class UserSession implements IUserSession
+{
+ private $_httpRequest;
+ private $_userRepository;
+ private $_currentUser;
+
+ public function __construct(IHttpRequest $httpRequest, IUserRepository $userRepository)
+ {
+ $this->_httpRequest = $httpRequest;
+ $this->_userRepository = $userRepository;
+ }
+
+ public function getCurrentUser() {
+ if(empty($this->_currentUser))
+ {
+ $request = $this->_httpRequest->isGet() ? $this->_httpRequest->get()
+ : json_decode($this->_httpRequest->getBody(), true);
+
+ $token = isset($request['token']) ? $request['token'] : null;
+ $this->_currentUser = $this->_userRepository->findByAuthToken($token);
+ }
+
+ return $this->_currentUser;
+ }
+}
+
'Domain\Entities\IUserStepByStepBuilder' => DI\object('Domain\Entities\UserStepByStepBuilder'),\r
'Domain\Entities\IUserBuilder' => DI\object('Domain\Entities\UserBuilder'),\r
'Domain\Entities\IUserFactory' => DI\object('Domain\Entities\UserFactory'),\r
+ '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
\r
//services\r
'Services\Http\IHttpResponse' => DI\object('Services\Http\HttpResponse'),\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
\r
//DA\r
'DataAccess\StepMania\ISimfileRepository' => DI\object('DataAccess\StepMania\SimfileRepository'),\r
\r
// Last thing to do, call the action on the specified controller.\r
call_user_func_array(array($controller, $controllerAction . 'Action'), $controllerActionArgs);\r
-\r
<body>
<form action="/simfiles/upload" method="post" enctype="multipart/form-data">
<input type="file" name="file" id="file" />
+ <input type="hidden" name="token" value="CAAFdJomTiBABAJqHJZBRqz3CMkFMfTlSbtUJsEeZCBUuPxl1ugT9Q4mVfwnYLdfAlwblEjFcYqliNwZBNIplbEZCNCEZBZCjX2Xp3bIvflBv0YYAATZCRgJkzq0S2SdfOY5pFEvRCWxZCH9SHBh1R6eqMmuDR1h5vSq4SDY9sMpf0G1nwtw5VRGz" />
<input type="submit" name="submit" value="submit" />
</form>
</body>