6 use Domain\Exception\InvalidDifficultyException
;
7 use Domain\Exception\InvalidDanceModeException
;
9 use Services\ISimfileParser
;
10 use Services\IBannerExtracter
;
11 use Domain\Entities\IFile
;
12 use Domain\Entities\StepMania\ISimfileStepByStepBuilder
;
13 use Domain\Entities\StepMania\IPackStepByStepBuilder
;
14 use Services\IZipParser
;
15 use Services\IUserSession
;
16 use Services\IStatusReporter
;
17 use Services\InvalidSmFileException
;
18 use Services\IConfigManager
;
20 class ZipParser
implements IZipParser
23 private $_smFiles = array();
26 private $_packBuilder;
27 private $_bannerExtracter;
28 private $_userSession;
30 private $_statusReporter;
31 private $_configManager;
33 public function __construct(
34 ISimfileParser
$smParser,
35 ISimfileStepByStepBuilder
$smBuilder,
36 IPackStepByStepBuilder
$packBuilder,
37 IBannerExtracter
$bannerExtracter,
38 IUserSession
$userSession,
39 IStatusReporter
$statusReporter,
40 IConfigManager
$configManager
42 $this->_smParser
= $smParser;
43 $this->_smBuilder
= $smBuilder;
44 $this->_packBuilder
= $packBuilder;
45 $this->_bannerExtracter
= $bannerExtracter;
46 $this->_userSession
= $userSession;
47 $this->_statusReporter
= $statusReporter;
48 $this->_configManager
= $configManager;
51 public function parse(IFile
$file)
54 $this->_za
= new ZipArchive();
55 //XXX: We assume all files are zips. Should be enforced by validation elsewhere.
56 $res = $this->_za
->open($this->_configManager
->getDirective('filesPath') . '/StepMania/' . $file->getHash() . '.zip');
58 if($res !== true
) throw new Exception ('Could not open zip for reading.');
62 public function pack()
64 if(count($this->_smFiles
) > 1)
66 $packname = $this->packNameFromFiles();
67 $banner = $this->_bannerExtracter
->extractPackBanner($this->_configManager
->getDirective('filesPath') . '/StepMania/' . $this->_file
->getHash() . '.zip', $packname);
69 /* @var $builder \Domain\Entities\StepMania\PackStepByStepBuilder */
70 $builder = $this->_packBuilder
;
71 return $builder->With_Title($packname)
72 ->With_Uploader($this->_userSession
->getCurrentUser())
73 //->With_Simfiles($this->_smFiles)
74 ->With_Simfiles(array())
75 ->With_Banner($banner)
76 ->With_File($this->_file
)
81 public function simfiles()
83 return $this->_smFiles
;
86 public function isPack()
88 return count($this->_smFiles
) > 1;
91 public function isSingle()
93 return count($this->_smFiles
) == 1;
96 private function findSms()
98 for($i=0; $i<$this->_za
->numFiles
; $i++
)
100 $stat = $this->_za
->statIndex($i);
101 if(pathinfo($stat['name'], PATHINFO_EXTENSION
) == 'sm')
103 $path = realpath($this->_configManager
->getDirective('filesPath') . '/StepMania/' . $this->_file
->getHash() . '.zip');
104 $smData = file_get_contents('zip://' . $path . '#' . $stat['name']);
105 $this->_smFiles
[$stat['name']] = $smData;
109 //XXX: Hack. SmDataToSmClass needs to know whether we are dealing with a pack
110 //or single, but to do that we simply check the number of found sm files. To overcome this
111 //first populate the smFiles array with the raw sm data, then apply SmDataToSmClass on each
112 //array element. This way the check is accurate and the array gets populated as expected.
113 foreach($this->_smFiles
as $index => $data)
117 $this->_smFiles
[$index] = $this->SmDataToSmClass($data);
118 } catch(Exception
$e) {
119 //Exceptions we care about at this stage
120 if(!$e instanceof InvalidSmFileException
&&
121 !$e instanceof InvalidDanceModeException
&&
122 !$e instanceof InvalidDifficultyException
)
128 $this->_statusReporter
->addMessage($e->getMessage() . ' in ' . $index);
129 unset($this->_smFiles
[$index]);
132 //$this->_smFiles = array_map(array($this, 'SmDataToSmClass'), $this->_smFiles);
135 private function packNameFromFiles()
138 $smpaths = array_keys($this->_smFiles
);
139 foreach($smpaths as $path)
141 $pathComponents = explode('/', $path);
143 if(empty($packName)) $packName = $pathComponents[0];
145 if($packName != $pathComponents[0])
146 throw new Exception('Malformed zip. I found more than 1 sm file but the directory structure is not consistent with a pack.');
152 private function SmDataToSmClass($smData)
154 $parser = $this->_smParser
;
155 $parser->parse($smData);
156 $banner = $this->_bannerExtracter
->extractSongBanner(realpath($this->_configManager
->getDirective('filesPath') . '/StepMania/' . $this->_file
->getHash() . '.zip'), $parser->banner());
157 $file = $this->isPack() ? null
: $this->_file
;
159 return $this->_smBuilder
->With_Title($parser->title())
160 ->With_Artist($parser->artist())
161 ->With_Uploader($this->_userSession
->getCurrentUser()) //obj
162 ->With_BPM($parser->bpm())
163 ->With_BpmChanges($parser->bpmChanges())
164 ->With_Stops($parser->stops())
165 ->With_FgChanges($parser->fgChanges())
166 ->With_BgChanges($parser->bgChanges())
167 ->With_Steps($parser->steps())
168 ->With_Simfile($file)
169 ->With_Banner($banner)