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
;
19 class ZipParser
implements IZipParser
22 private $_smFiles = array();
25 private $_packBuilder;
26 private $_bannerExtracter;
27 private $_userSession;
29 private $_statusReporter;
31 public function __construct(
32 ISimfileParser
$smParser,
33 ISimfileStepByStepBuilder
$smBuilder,
34 IPackStepByStepBuilder
$packBuilder,
35 IBannerExtracter
$bannerExtracter,
36 IUserSession
$userSession,
37 IStatusReporter
$statusReporter
39 $this->_smParser
= $smParser;
40 $this->_smBuilder
= $smBuilder;
41 $this->_packBuilder
= $packBuilder;
42 $this->_bannerExtracter
= $bannerExtracter;
43 $this->_userSession
= $userSession;
44 $this->_statusReporter
= $statusReporter;
47 public function parse(IFile
$file)
50 $this->_za
= new ZipArchive();
51 //XXX: We assume all files are zips. Should be enforced by validation elsewhere.
52 $res = $this->_za
->open('../files/StepMania/' . $file->getHash() . '.zip');
54 if($res !== true
) throw new Exception ('Could not open zip for reading.');
58 public function pack()
60 if(count($this->_smFiles
) > 1)
62 $packname = $this->packNameFromFiles();
63 $banner = $this->_bannerExtracter
->extractPackBanner('../files/StepMania/' . $this->_file
->getHash() . '.zip', $packname);
65 /* @var $builder \Domain\Entities\StepMania\PackStepByStepBuilder */
66 $builder = $this->_packBuilder
;
67 return $builder->With_Title($packname)
68 ->With_Uploader($this->_userSession
->getCurrentUser())
69 //->With_Simfiles($this->_smFiles)
70 ->With_Simfiles(array())
71 ->With_Banner($banner)
72 ->With_File($this->_file
)
77 public function simfiles()
79 return $this->_smFiles
;
82 public function isPack()
84 return count($this->_smFiles
) > 1;
87 public function isSingle()
89 return count($this->_smFiles
) == 1;
92 private function findSms()
94 for($i=0; $i<$this->_za
->numFiles
; $i++
)
96 $stat = $this->_za
->statIndex($i);
97 if(pathinfo($stat['name'], PATHINFO_EXTENSION
) == 'sm')
99 $path = realpath('../files/StepMania/' . $this->_file
->getHash() . '.zip');
100 $smData = file_get_contents('zip://' . $path . '#' . $stat['name']);
101 $this->_smFiles
[$stat['name']] = $smData;
105 //XXX: Hack. SmDataToSmClass needs to know whether we are dealing with a pack
106 //or single, but to do that we simply check the number of found sm files. To overcome this
107 //first populate the smFiles array with the raw sm data, then apply SmDataToSmClass on each
108 //array element. This way the check is accurate and the array gets populated as expected.
109 foreach($this->_smFiles
as $index => $data)
113 $this->_smFiles
[$index] = $this->SmDataToSmClass($data);
114 } catch(Exception
$e) {
115 //Exceptions we care about at this stage
116 if(!$e instanceof InvalidSmFileException
&&
117 !$e instanceof InvalidDanceModeException
&&
118 !$e instanceof InvalidDifficultyException
)
124 $this->_statusReporter
->addMessage($e->getMessage() . ' in ' . $index);
125 unset($this->_smFiles
[$index]);
128 //$this->_smFiles = array_map(array($this, 'SmDataToSmClass'), $this->_smFiles);
131 private function packNameFromFiles()
134 $smpaths = array_keys($this->_smFiles
);
135 foreach($smpaths as $path)
137 $pathComponents = explode('/', $path);
139 if(empty($packName)) $packName = $pathComponents[0];
141 if($packName != $pathComponents[0])
142 throw new Exception('Malformed zip. I found more than 1 sm file but the directory structure is not consistent with a pack.');
145 return utf8_encode($packName);
148 private function SmDataToSmClass($smData)
150 $parser = $this->_smParser
;
151 $parser->parse($smData);
152 $banner = $this->_bannerExtracter
->extractSongBanner(realpath('../files/StepMania/' . $this->_file
->getHash() . '.zip'), $parser->banner());
153 $file = $this->isPack() ? null
: $this->_file
;
155 return $this->_smBuilder
->With_Title($parser->title())
156 ->With_Artist($parser->artist())
157 ->With_Uploader($this->_userSession
->getCurrentUser()) //obj
158 ->With_BPM($parser->bpm())
159 ->With_BpmChanges($parser->bpmChanges())
160 ->With_Stops($parser->stops())
161 ->With_FgChanges($parser->fgChanges())
162 ->With_BgChanges($parser->bgChanges())
163 ->With_Steps($parser->steps())
164 ->With_Simfile($file)
165 ->With_Banner($banner)