7 use Services\ISimfileParser
;
8 use Services\IBannerExtracter
;
9 use Domain\Entities\IFile
;
10 use Domain\Entities\StepMania\ISimfileStepByStepBuilder
;
11 use Domain\Entities\StepMania\IPackStepByStepBuilder
;
12 use Services\IZipParser
;
13 use Services\IUserSession
;
15 class ZipParser
implements IZipParser
18 private $_smFiles = array();
21 private $_packBuilder;
22 private $_bannerExtracter;
23 private $_userSession;
26 public function __construct(
27 ISimfileParser
$smParser,
28 ISimfileStepByStepBuilder
$smBuilder,
29 IPackStepByStepBuilder
$packBuilder,
30 IBannerExtracter
$bannerExtracter,
31 IUserSession
$userSession
33 $this->_smParser
= $smParser;
34 $this->_smBuilder
= $smBuilder;
35 $this->_packBuilder
= $packBuilder;
36 $this->_bannerExtracter
= $bannerExtracter;
37 $this->_userSession
= $userSession;
40 public function parse(IFile
$file)
43 $this->_za
= new ZipArchive();
44 //XXX: We assume all files are zips. Should be enforced by validation elsewhere.
45 $res = $this->_za
->open('../files/StepMania/' . $file->getHash() . '.zip');
47 if($res !== true
) throw new Exception ('Could not open zip for reading.');
51 public function pack()
53 if(count($this->_smFiles
) > 1)
55 $packname = $this->packNameFromFiles();
56 $banner = $this->_bannerExtracter
->extractPackBanner('../files/StepMania/' . $this->_file
->getHash() . '.zip', $packname);
58 /* @var $builder \Domain\Entities\StepMania\PackStepByStepBuilder */
59 $builder = $this->_packBuilder
;
60 return $builder->With_Title($packname)
61 ->With_Uploader($this->_userSession
->getCurrentUser())
62 //->With_Simfiles($this->_smFiles)
63 ->With_Simfiles(array())
64 ->With_Banner($banner)
65 ->With_File($this->_file
)
70 public function simfiles()
72 return $this->_smFiles
;
75 public function isPack()
77 return count($this->_smFiles
) > 1;
80 public function isSingle()
82 return count($this->_smFiles
) == 1;
85 private function findSms()
87 for($i=0; $i<$this->_za
->numFiles
; $i++
)
89 $stat = $this->_za
->statIndex($i);
90 if(pathinfo($stat['name'], PATHINFO_EXTENSION
) == 'sm')
92 $smData = file_get_contents('zip://../files/StepMania/' . $this->_file
->getHash() . '.zip#' . $stat['name']);
93 $this->_smFiles
[$stat['name']] = $smData;
97 //XXX: Hack. SmDataToSmClass needs to know whether we are dealing with a pack
98 //or single, but to do that we simply check the number of found sm files. To overcome this
99 //first populate the smFiles array with the raw sm data, then apply SmDataToSmClass on each
100 //array element. This way the check is accurate and the array gets populated as expected.
101 $this->_smFiles
= array_map(array($this, 'SmDataToSmClass'), $this->_smFiles
);
104 private function packNameFromFiles()
107 $smpaths = array_keys($this->_smFiles
);
108 foreach($smpaths as $path)
110 $pathComponents = explode('/', $path);
112 if(empty($packName)) $packName = $pathComponents[0];
114 if($packName != $pathComponents[0])
115 throw new Exception('Malformed zip. I found more than 1 sm file but the directory structure is not consistent with a pack.');
121 private function SmDataToSmClass($smData)
123 $parser = $this->_smParser
;
124 $parser->parse($smData);
125 $banner = $this->_bannerExtracter
->extractSongBanner('../files/StepMania/' . $this->_file
->getHash() . '.zip', $parser->banner());
126 $file = $this->isPack() ? null
: $this->_file
;
128 return $this->_smBuilder
->With_Title($parser->title())
129 ->With_Artist($parser->artist())
130 ->With_Uploader($this->_userSession
->getCurrentUser()) //obj
131 ->With_BPM($parser->bpm())
132 ->With_BpmChanges($parser->bpmChanges())
133 ->With_Stops($parser->stops())
134 ->With_FgChanges($parser->fgChanges())
135 ->With_BgChanges($parser->bgChanges())
136 ->With_Steps($parser->steps())
137 ->With_Simfile($file)
138 ->With_Banner($banner)