createUniqueID -> generateUniqueId renamed, dataset criteria added, registration...
[shipsimu.git] / application / ship-simu / main / class_WorksContract.php
1 <?php
2 /**
3  * The work constract class which can be used for contract parties
4  *
5  * @author              Roland Haeder <webmaster@ship-simu.org>
6  * @version             0.0.0
7  * @copyright   Copyright(c) 2007, 2008 Roland Haeder, this is free software
8  * @license             GNU GPL 3.0 or any newer version
9  * @link                http://www.ship-simu.org
10  *
11  * This program is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation, either version 3 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program. If not, see <http://www.gnu.org/licenses/>.
23  */
24 class WorksContract extends BaseFrameworkSystem implements SignableContract {
25         // Zukuenftiger Schiffsname
26         private $shipName         = "";
27
28         // Instanz zum Schiffstypen
29         private $shipInstance     = null;
30
31         // Contract partner
32         private $contractPartner  = null;
33
34         // Other contract partner
35         private $contractParty    = null;
36
37         // Is the contract signed?
38         private $signed           = false;
39
40         // Merchant instance
41         private $merchantInstance = null;
42
43         // Konstruktor
44         protected function __construct () {
45                 // Call parent constructor
46                 parent::__construct(__CLASS__);
47
48                 // Set description
49                 $this->setObjectDescription("Bauvertrag");
50
51                 // Unique-ID generieren
52                 $this->generateUniqueId();
53
54                 // Clean up a little
55                 $this->removeSystemArray();
56         }
57
58         // Neuen Bauvertrag generieren
59         public final static function createWorksContract ($shipType, $shipName, ContractPartner $partnerInstance) {
60                 // Strings absichern
61                 $shipType = (string) $shipType;
62                 $shipName = (string) $shipName;
63
64                 // Is the other one a contract partner?
65                 if (is_null($partnerInstance)) {
66                         // Opps! Empty partner instance?
67                         throw new NullPointerException($partnerInstance, self::EXCEPTION_IS_NULL_POINTER);
68                 } elseif (!is_object($partnerInstance)) {
69                         // Not an object! ;-(
70                         throw new NoObjectException($partnerInstance, self::EXCEPTION_IS_NO_OBJECT);
71                 } elseif (!method_exists($partnerInstance, 'isContractPartner')) {
72                         // Does not have the required feature (method)
73                         throw new MissingMethodException(array($partnerInstance, 'isContractPartner'), self::EXCEPTION_MISSING_METHOD);
74                 }
75
76                 // Get new instance
77                 $contractInstance = new WorksContract();
78
79                 // Debug-Meldung ausgeben
80                 if ((defined('DEBUG_CONTRACT')) || (defined('DEBUG_ALL'))) $contractInstance->getDebugInstance()->output(sprintf("[%s:%d] Neuer Bauvertrag wird f&uuml;r das Schiff <strong>%s</strong> mit der <strong>%s</strong> <strong>%s</strong> erstellt.<br />\n",
81                         __CLASS__,
82                         __LINE__,
83                         $shipName,
84                         $partnerInstance->getObjectDescription(),
85                         $partnerInstance->getCompanyName()
86                 ));
87
88                 // Schiffsnamen setzen
89                 $contractInstance->setShipName($shipName);
90
91                 // Existiert die Klasse ueberhaupt?
92                 if (!class_exists($shipType)) {
93                         // Klasse nicht gefunden
94                         throw new ClassNotFoundException ($shipType, self::EXCEPTION_CLASS_NOT_FOUND);
95                 }
96
97                 // Schiff-Instanz temporaer erzeugen und in den Bauvertrag einfuegen
98                 $eval = sprintf("\$contractInstance->setShipInstance(%s::create%s(\"%s\"));",
99                         $shipType,
100                         $shipType,
101                         $shipName
102                 );
103
104                 // Debug message
105                 if ((defined('DEBUG_EVAL')) || (defined('DEBUG_ALL'))) $contractInstance->getDebugInstance()->output(sprintf("[%s:%d] Konstruierte PHP-Anweisung: <pre><em>%s</em></pre><br />\n",
106                         __CLASS__,
107                         __LINE__,
108                         htmlentities($eval)
109                 ));
110
111                 // Execute constructed command
112                 @eval($eval);
113
114                 // Set itself as contract partner
115                 $contractInstance->setContractPartner($partnerInstance);
116
117                 // Instanz zurueckgeben
118                 return $contractInstance;
119         }
120
121         // Setter for ship instance
122         private final function setShipInstance (ConstructableShip $shipInstance) {
123                 if ((defined('DEBUG_CONTRACT')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Das Schiff <strong>%s</strong> wird in den Bauvertrag aufgenommen.<br />\n",
124                         __CLASS__,
125                         __LINE__,
126                         $shipInstance->getShipName()
127                 ));
128                 $this->shipInstance = $shipInstance;
129         }
130
131         // Setter for ship name
132         private final function setShipName ($shipName) {
133                 if ((defined('DEBUG_CONTRACT')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Das neue Schiff wird <strong>%s</strong> heissen.<br />\n",
134                         __CLASS__,
135                         __LINE__,
136                         $shipName
137                 ));
138                 $this->shipName = (string) $shipName;
139         }
140
141         // Getter for ship name
142         public final function getShipName () {
143                 if ((defined('DEBUG_CONTRACT')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Schiffsname <strong>%s</strong> angefordert.<br />\n",
144                         __CLASS__,
145                         __LINE__,
146                         $this->shipName
147                 ));
148                 return $this->shipName;
149         }
150
151         // Getter for ship instance
152         public final function getShipInstance () {
153                 if ((defined('DEBUG_CONTRACT')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Schiff-Instanz angefordert.<br />\n",
154                         __CLASS__,
155                         __LINE__
156                 ));
157                 return $this->shipInstance;
158         }
159
160         // Add detail to the contract
161         public function addContractDetails ($shipPart, $parentPart, array $dataArray) {
162                 // Secure strings
163                 $shipPart   = (string) $shipPart;
164                 $parentPart = (string) $parentPart;
165
166                 // Debug message
167                 if ((defined('DEBUG_CONTRACT')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Das Schiffsteil <strong>%s</strong> wird zusammen mit dem Konstruktionsteil <strong>%s</strong> in den Bauvertrag aufgenommen.<br />\n",
168                         __CLASS__,
169                         __LINE__,
170                         $shipPart,
171                         $parentPart
172                 ));
173
174                 // Initialize the instance (shall not be done within dynamic part)
175                 $instance = null;
176
177                 // Prepare the big command for everthing
178                 $eval = "try {
179         \$instance = ".$shipPart."::create".$shipPart."(";
180                 foreach ($dataArray as $pIdx => $parts) {
181                         if (is_string($parts)) {
182                                 // String einbauen
183                                 $eval .= "\"".$parts."\", ";
184                         } elseif (is_array($parts)) {
185                                 // Ist ein weiteres Array!
186                                 $eval .= "array(";
187                                 foreach ($parts as $idx2 => $sub) {
188                                         $eval .= "'".$idx2."' => ";
189                                         if (is_string($sub)) {
190                                                 // Ist erneut ein String
191                                                 $eval .= "\"".$sub."\"";
192                                         } elseif (is_array($sub)) {
193                                                 // Wird nicht mehr unterstuetzt!
194                                                 ApplicationEntryPoint::app_die("No more arrays!");
195                                         } else {
196                                                 // Direkt anhaengen
197                                                 $eval .= $sub;
198                                         }
199                                         $eval .= ", ";
200                                 }
201
202                                 // Letztes Komma entfernen
203                                 $eval = substr($eval, 0, -2);
204                                 $eval .= "), ";
205                         } else {
206                                 // Etwas anderes direkt!
207                                 $eval .= $parts.", ";
208                         }
209                 }
210
211                 // Letztes Komma abhaengen
212                 $eval = substr($eval, 0, -2);
213                 $eval .= ");
214 } catch (DimNotFoundInArrayException \$e) {
215         \$this->getDebugInstance()->output(sprintf(\"[main:] Die <strong>%s</strong> konnte nicht vervollst&auml;ndigt werden. Grund: <strong>%s</strong><br />\\n\",
216                 \$this->getShipInstance()->getShipName(),
217                 \$e->getMessage()
218         ));
219         \$instance = null;
220 }";
221
222                 // Debug message
223                 if ((defined('DEBUG_EVAL')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[Ship:] Konstruierte PHP-Anweisung: <pre><em>%s</em></pre><br />\n",
224                         htmlentities($eval)
225                 ));
226
227                 // Code ausfuhren
228                 @eval($eval);
229
230                 // Try to add the ship part to the contract
231                 try {
232                         if ((defined('DEBUG_CONTRACT')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Versuche ein Schiffsteil in den Bauvertrag aufzunehmen.<br />\n",
233                                 __CLASS__,
234                                 __LINE__
235                         ));
236                         if (!$instance instanceof ConstructableShipPart) {
237                                 // Ship part not constructable!
238                                 throw new ShipPartNotConstructableException(array($shipPart), self::EXCEPTION_NOT_CONSTRUCTABLE);
239                         } elseif (!$this->getShipInstance()->createShipPart($instance, $parentPart)) {
240                                 // Schiff konnte nicht gebaut werden!
241                                 throw new ShipNotConstructedException(sprintf("Das Schiff <strong>%s</strong> konnte wegen eines Fehlers nicht gebaut werden. Siehe obere Meldungen.",
242                                         $this->getShipInstance()->getShipName()
243                                 ));
244                         }
245                 } catch (ClassNotFoundException $e) {
246                         // Throw it again...
247                         throw new ClassNotFoundException($e->getMessage(), $e->getCode());
248                 }
249
250                 // Get price for this item
251                 $price = $this->getMerchantInstance()->getPriceFromList($instance);
252
253                 // Final debug message
254                 if ((defined('DEBUG_CONTRACT')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] <strong>%s</strong> kostet <strong>%s</strong>.<br />\n",
255                         __CLASS__,
256                         __LINE__,
257                         $instance->getObjectDescription(),
258                         $this->getMerchantInstance()->formatCurrency($price)
259                 ));
260
261                 // Add price
262                 $instance->setPrice($price);
263
264                 // Final debug message
265                 if ((defined('DEBUG_CONTRACT')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] <strong>%s</strong> wurde in den Bauvertrag aufgenommen.<br />\n",
266                         __CLASS__,
267                         __LINE__,
268                         $instance->getObjectDescription()
269                 ));
270         }
271
272         // Setter for contract partner
273         public final function setContractPartner (ContractPartner $partnerInstance) {
274                 $this->contractPartner = $partnerInstance;
275         }
276
277         // Getter for contract partner
278         public final function getContractPartner () {
279                 return $this->contractPartner;
280         }
281
282         // Setter for contract party
283         public final function setContractParty (ContractPartner $partyInstance) {
284                 $this->contractParty = $partyInstance;
285         }
286
287         // Getter for contract party
288         public final function getContractParty () {
289                 return $this->contractParty;
290         }
291
292         // Setter for signature
293         public final function setSigned ($signed) {
294                 $this->signed = (boolean) $signed;
295         }
296
297         // Getter for signature
298         public function isSigned () {
299                 return $this->signed;
300         }
301
302         // Sign the contract
303         public function signContract (ContractPartner $partnerInstance, ContractPartner $partyInstance) {
304                 // Is this contract already signed?
305                 if ($this->isSigned()) {
306                         // Throw an exception
307                         throw new ContractAllreadySignedException(array($this, $this->getContractPartner(), $this->getContractParty()), self::EXCEPTION_CONTRACT_ALREADY_SIGNED);
308                 }
309
310                 // Is the first contract partner still the same?
311                 if ($partnerInstance->equals($this->getContractPartner())) {
312                         // Set contract party (other partner is already set)
313                         $this->setContractParty($partyInstance);
314
315                         // Finally sign it
316                         $this->setSigned(true);
317                 } else {
318                         // Throw an exception
319                         throw new ContractPartnerMismatchException(array($this, $this->getContractPartner(), $partyInstance), self::EXCEPTION_CONTRACT_PARTNER_MISMATCH);
320                 }
321
322                 // Debug message
323                 if ((defined('DEBUG_CONTRACT')) || (defined('DEBUG_ALL'))) {
324                         if ($partnerInstance->equals($partyInstance)) {
325                                 // With itself
326                                 $this->getDebugInstance()->output(sprintf("[%s:%d] Die <strong>%s</strong> <em><strong>%s</strong></em> stimmt einem Bauvertrag &uuml;ber das <strong>%s</strong> <em><strong>%s</strong></em> zu.<br />\n",
327                                         __CLASS__,
328                                         __LINE__,
329                                         $partnerInstance->getObjectDescription(),
330                                         $partnerInstance->getCompanyName(),
331                                         $this->getShipInstance()->getObjectDescription(),
332                                         $this->getShipInstance()->getShipName()
333                                 ));
334                         } else {
335                                 // Other contract party
336                                 $this->getDebugInstance()->output(sprintf("[%s:%d] Die <strong>%s</strong> <em><strong>%s</strong></em> geht mit der <strong>%s</strong> <em><strong>%s</strong></em> einen Bauvertrag &uuml;ber das <strong>%s</strong> <em><strong>%s</strong></em> ein.<br />\n",
337                                         __CLASS__,
338                                         __LINE__,
339                                         $partnerInstance->getObjectDescription(),
340                                         $partnerInstance->getCompanyName(),
341                                         $partyInstance->getObjectDescription(),
342                                         $partyInstance->getCompanyName(),
343                                         $this->getShipInstance()->getObjectDescription(),
344                                         $this->getShipInstance()->getShipName()
345                                 ));
346                         }
347                 }
348         }
349
350         // Setter for merchant instance
351         public final function setMerchantInstance (Merchant $merchantInstance) {
352                 $this->merchantInstance = $merchantInstance;
353         }
354
355         // Getter for merchant instance
356         public final function getMerchantInstance () {
357                 return $this->merchantInstance;
358         }
359
360         // Getter for total price
361         public final function getTotalPrice () {
362                 // Get ship instance
363                 $shipInstance = $this->getShipInstance();
364
365                 // Is this a ship?
366                 if (is_null($shipInstance)) {
367                         // Opps! Empty partner instance?
368                         throw new NullPointerException($shipInstance, self::EXCEPTION_IS_NULL_POINTER);
369                 } elseif (!is_object($shipInstance)) {
370                         // Not an object! ;-(
371                         throw new NoObjectException($shipInstance, self::EXCEPTION_IS_NO_OBJECT);
372                 } elseif (!$shipInstance instanceof ConstructableShip) {
373                         // Does not have the required feature (method)
374                         throw new ShipIsInvalidException(array($shipInstance), self::EXCEPTION_INVALID_SHIP_INSTANCE);
375                 }
376
377                 // Get the structure array
378                 $struct = $shipInstance->getStructuresArray();
379
380                 // Is this a ship?
381                 if (is_null($struct)) {
382                         // Opps! Empty partner instance?
383                         throw new EmptyStructuresListException($this, self::EXCEPTION_EMPTY_STRUCTURES_ARRAY);
384                 }
385
386                 // Init total price
387                 $totalPrice = 0;
388
389                 // Iterate through the list
390                 for ($iter = $struct->getIterator(); $iter->valid(); $iter->next()) {
391                         // Get item
392                         $item = $iter->current();
393
394                         // Is this a ship?
395                         if (is_null($item)) {
396                                 // Opps! Empty partner instance?
397                                 throw new NullPointerException($item, self::EXCEPTION_IS_NULL_POINTER);
398                         } elseif (!is_object($item)) {
399                                 // Not an object! ;-(
400                                 throw new NoObjectException($item, self::EXCEPTION_IS_NO_OBJECT);
401                         } elseif (!method_exists($item, 'getPartInstance')) {
402                                 // Does not have the required feature (method)
403                                 throw new MissingMethodException(array($item, 'getPartInstance'), self::EXCEPTION_MISSING_METHOD);
404                         }
405
406                         // Get part instance
407                         $part = $item->getPartInstance();
408
409                         // Is this a ship?
410                         if (is_null($part)) {
411                                 // Opps! Empty partner instance?
412                                 throw new NullPointerException($part, self::EXCEPTION_IS_NULL_POINTER);
413                         } elseif (!is_object($part)) {
414                                 // Not an object! ;-(
415                                 throw new NoObjectException($part, self::EXCEPTION_IS_NO_OBJECT);
416                         } elseif (!method_exists($part, 'getPrice')) {
417                                 // Does not have the required feature (method)
418                                 throw new MissingMethodException(array($part, 'getPrice'), self::EXCEPTION_MISSING_METHOD);
419                         }
420
421                         // Get price for one item
422                         $price = $part->getPrice();
423
424                         // Is there numCabin() available?
425                         if (method_exists($item, 'getNumCabin')) {
426                                 // Get total cabin and multiply it with the price
427                                 $price = $price * $item->getNumCabin();
428                         }
429
430                         // Add price to total price
431                         $totalPrice += $price;
432                 }
433
434                 // Total price calculated?
435                 if ($totalPrice === 0) {
436                         // Throw exception
437                         throw new TotalPriceNotCalculatedException($this, self::EXCEPTION_TOTAL_PRICE_NOT_CALCULATED);
438                 }
439
440                 // Return total price
441                 return $totalPrice;
442         }
443 }
444
445 // [EOF]
446 ?>