0504fa59a5d470c94f3e63cef8adbc742ca63c5b
[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         private function __construct () {
45                 // Call parent constructor
46                 parent::constructor(__CLASS__);
47
48                 // Debug message
49                 if (((defined('DEBUG_CONTRACT')) || (defined('DEBUG_ALL'))) && (defined('DEBUG_CONSTRUCT'))) {
50                         $this->getDebugInstance()->output(sprintf("[%s:%d] Konstruktor erreicht.<br />\n",
51                                 __CLASS__,
52                                 __LINE__
53                         ));
54                 }
55
56                 // Set description
57                 $this->setPartDescr("Bauvertrag");
58
59                 // Unique-ID generieren
60                 $this->createUniqueID();
61
62                 // Clean up a little
63                 $this->removeSystemArray();
64         }
65
66         // Neuen Bauvertrag generieren
67         public static function createWorksContract ($shipType, $shipName, ContractPartner $partnerInstance) {
68                 // Strings absichern
69                 $shipType = (string) $shipType;
70                 $shipName = (string) $shipName;
71
72                 // Is the other one a contract partner?
73                 if (is_null($partnerInstance)) {
74                         // Opps! Empty partner instance?
75                         throw new NullPointerException($partnerInstance, self::EXCEPTION_IS_NULL_POINTER);
76                 } elseif (!is_object($partnerInstance)) {
77                         // Not an object! ;-(
78                         throw new NoObjectException($partnerInstance, self::EXCEPTION_IS_NO_OBJECT);
79                 } elseif (!method_exists($partnerInstance, 'isContractPartner')) {
80                         // Does not have the required feature (method)
81                         throw new MissingMethodException(array($partnerInstance, 'isContractPartner'), self::EXCEPTION_MISSING_METHOD);
82                 }
83
84                 // Get new instance
85                 $contractInstance = new WorksContract();
86
87                 // Debug-Meldung ausgeben
88                 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",
89                         __CLASS__,
90                         __LINE__,
91                         $shipName,
92                         $partnerInstance->getPartDescr(),
93                         $partnerInstance->getCompanyName()
94                 ));
95
96                 // Schiffsnamen setzen
97                 $contractInstance->setShipName($shipName);
98
99                 // Existiert die Klasse ueberhaupt?
100                 if (!class_exists($shipType)) {
101                         // Klasse nicht gefunden
102                         throw new ClassNotFoundException ($shipType, 0);
103                 }
104
105                 // Schiff-Instanz temporaer erzeugen und in den Bauvertrag einfuegen
106                 $eval = sprintf("\$contractInstance->setShipInstance(%s::create%s(\"%s\"));",
107                         $shipType,
108                         $shipType,
109                         $shipName
110                 );
111
112                 // Debug message
113                 if ((defined('DEBUG_EVAL')) || (defined('DEBUG_ALL'))) $contractInstance->getDebugInstance()->output(sprintf("[%s:%d] Konstruierte PHP-Anweisung: <pre><em>%s</em></pre><br />\n",
114                         __CLASS__,
115                         __LINE__,
116                         htmlentities($eval)
117                 ));
118
119                 // Execute constructed command
120                 @eval($eval);
121
122                 // Set itself as contract partner
123                 $contractInstance->setContractPartner($partnerInstance);
124
125                 // Instanz zurueckgeben
126                 return $contractInstance;
127         }
128
129         // Setter for ship instance
130         private function setShipInstance (ConstructableShip $shipInstance) {
131                 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",
132                         __CLASS__,
133                         __LINE__,
134                         $shipInstance->getShipName()
135                 ));
136                 $this->shipInstance = $shipInstance;
137         }
138
139         // Setter for ship name
140         private function setShipName ($shipName) {
141                 if ((defined('DEBUG_CONTRACT')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Das neue Schiff wird <strong>%s</strong> heissen.<br />\n",
142                         __CLASS__,
143                         __LINE__,
144                         $shipName
145                 ));
146                 $this->shipName = (string) $shipName;
147         }
148
149         // Getter for ship name
150         public final function getShipName () {
151                 if ((defined('DEBUG_CONTRACT')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Schiffsname <strong>%s</strong> angefordert.<br />\n",
152                         __CLASS__,
153                         __LINE__,
154                         $this->shipName
155                 ));
156                 return $this->shipName;
157         }
158
159         // Getter for ship instance
160         public final function getShipInstance () {
161                 if ((defined('DEBUG_CONTRACT')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Schiff-Instanz angefordert.<br />\n",
162                         __CLASS__,
163                         __LINE__
164                 ));
165                 return $this->shipInstance;
166         }
167
168         // Add detail to the contract
169         public function addContractDetails ($shipPart, $parentPart, array $dataArray) {
170                 // Secure strings
171                 $shipPart   = (string) $shipPart;
172                 $parentPart = (string) $parentPart;
173
174                 // Debug message
175                 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",
176                         __CLASS__,
177                         __LINE__,
178                         $shipPart,
179                         $parentPart
180                 ));
181
182                 // Initialize the instance (shall not be done within dynamic part)
183                 $instance = null;
184
185                 // Prepare the big command for everthing
186                 $eval = "try {
187         \$instance = ".$shipPart."::create".$shipPart."(";
188                 foreach ($dataArray as $pIdx => $parts) {
189                         if (is_string($parts)) {
190                                 // String einbauen
191                                 $eval .= "\"".$parts."\", ";
192                         } elseif (is_array($parts)) {
193                                 // Ist ein weiteres Array!
194                                 $eval .= "array(";
195                                 foreach ($parts as $idx2 => $sub) {
196                                         $eval .= "'".$idx2."' => ";
197                                         if (is_string($sub)) {
198                                                 // Ist erneut ein String
199                                                 $eval .= "\"".$sub."\"";
200                                         } elseif (is_array($sub)) {
201                                                 // Wird nicht mehr unterstuetzt!
202                                                 ApplicationEntryPoint::app_die("No more arrays!");
203                                         } else {
204                                                 // Direkt anhaengen
205                                                 $eval .= $sub;
206                                         }
207                                         $eval .= ", ";
208                                 }
209
210                                 // Letztes Komma entfernen
211                                 $eval = substr($eval, 0, -2);
212                                 $eval .= "), ";
213                         } else {
214                                 // Etwas anderes direkt!
215                                 $eval .= $parts.", ";
216                         }
217                 }
218
219                 // Letztes Komma abhaengen
220                 $eval = substr($eval, 0, -2);
221                 $eval .= ");
222 } catch (DimNotFoundInArrayException \$e) {
223         \$this->getDebugInstance()->output(sprintf(\"[main:] Die <strong>%s</strong> konnte nicht vervollst&auml;ndigt werden. Grund: <strong>%s</strong><br />\\n\",
224                 \$this->getShipInstance()->getShipName(),
225                 \$e->getMessage()
226         ));
227         \$instance = null;
228 }";
229
230                 // Debug message
231                 if ((defined('DEBUG_EVAL')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[Ship:] Konstruierte PHP-Anweisung: <pre><em>%s</em></pre><br />\n",
232                         htmlentities($eval)
233                 ));
234
235                 // Code ausfuhren
236                 @eval($eval);
237
238                 // Try to add the ship part to the contract
239                 try {
240                         if ((defined('DEBUG_CONTRACT')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Versuche ein Schiffsteil in den Bauvertrag aufzunehmen.<br />\n",
241                                 __CLASS__,
242                                 __LINE__
243                         ));
244                         if (!$instance instanceof ConstructableShipPart) {
245                                 // Ship part not constructable!
246                                 throw new ShipPartNotConstructableException(array($shipPart), self::EXCEPTION_NOT_CONSTRUCTABLE);
247                         } elseif (!$this->getShipInstance()->createShipPart($instance, $parentPart)) {
248                                 // Schiff konnte nicht gebaut werden!
249                                 throw new ShipNotConstructedException(sprintf("Das Schiff <strong>%s</strong> konnte wegen eines Fehlers nicht gebaut werden. Siehe obere Meldungen.",
250                                         $this->getShipInstance()->getShipName()
251                                 ));
252                         }
253                 } catch(ClassNotFoundException $e) {
254                         // Throw it again...
255                         throw new ClassNotFoundException($e->getMessage(), $e->getCode());
256                 }
257
258                 // Get price for this item
259                 $price = $this->getMerchantInstance()->getPriceFromList($instance);
260
261                 // Final debug message
262                 if ((defined('DEBUG_CONTRACT')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] <strong>%s</strong> kostet <strong>%s</strong>.<br />\n",
263                         __CLASS__,
264                         __LINE__,
265                         $instance->getPartDescr(),
266                         $this->getMerchantInstance()->formatCurrency($price)
267                 ));
268
269                 // Add price
270                 $instance->setPrice($price);
271
272                 // Final debug message
273                 if ((defined('DEBUG_CONTRACT')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] <strong>%s</strong> wurde in den Bauvertrag aufgenommen.<br />\n",
274                         __CLASS__,
275                         __LINE__,
276                         $instance->getPartDescr()
277                 ));
278         }
279
280         // Setter for contract partner
281         public final function setContractPartner (ContractPartner $partnerInstance) {
282                 $this->contractPartner = $partnerInstance;
283         }
284
285         // Getter for contract partner
286         public final function getContractPartner () {
287                 return $this->contractPartner;
288         }
289
290         // Setter for contract party
291         public final function setContractParty (ContractPartner $partyInstance) {
292                 $this->contractParty = $partyInstance;
293         }
294
295         // Getter for contract party
296         public final function getContractParty () {
297                 return $this->contractParty;
298         }
299
300         // Setter for signature
301         public final function setSigned ($signed) {
302                 $this->signed = (boolean) $signed;
303         }
304
305         // Getter for signature
306         public function isSigned () {
307                 return $this->signed;
308         }
309
310         // Sign the contract
311         public function signContract (ContractPartner $partnerInstance, ContractPartner $partyInstance) {
312                 // Is this contract already signed?
313                 if ($this->isSigned()) {
314                         // Throw an exception
315                         throw new ContractAllreadySignedException(array($this, $this->getContractPartner(), $this->getContractParty()), self::EXCEPTION_CONTRACT_ALREADY_SIGNED);
316                 }
317
318                 // Is the first contract partner still the same?
319                 if ($partnerInstance->equals($this->getContractPartner())) {
320                         // Set contract party (other partner is already set)
321                         $this->setContractParty($partyInstance);
322
323                         // Finally sign it
324                         $this->setSigned(true);
325                 } else {
326                         // Throw an exception
327                         throw new ContractPartnerMismatchException(array($this, $this->getContractPartner(), $partyInstance), self::EXCEPTION_CONTRACT_PARTNER_MISMATCH);
328                 }
329
330                 // Debug message
331                 if ((defined('DEBUG_CONTRACT')) || (defined('DEBUG_ALL'))) {
332                         if ($partnerInstance->equals($partyInstance)) {
333                                 // With itself
334                                 $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",
335                                         __CLASS__,
336                                         __LINE__,
337                                         $partnerInstance->getPartDescr(),
338                                         $partnerInstance->getCompanyName(),
339                                         $this->getShipInstance()->getPartDescr(),
340                                         $this->getShipInstance()->getShipName()
341                                 ));
342                         } else {
343                                 // Other contract party
344                                 $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",
345                                         __CLASS__,
346                                         __LINE__,
347                                         $partnerInstance->getPartDescr(),
348                                         $partnerInstance->getCompanyName(),
349                                         $partyInstance->getPartDescr(),
350                                         $partyInstance->getCompanyName(),
351                                         $this->getShipInstance()->getPartDescr(),
352                                         $this->getShipInstance()->getShipName()
353                                 ));
354                         }
355                 }
356         }
357
358         // Setter for merchant instance
359         public final function setMerchantInstance (Merchant $merchantInstance) {
360                 $this->merchantInstance = $merchantInstance;
361         }
362
363         // Getter for merchant instance
364         public final function getMerchantInstance () {
365                 return $this->merchantInstance;
366         }
367
368         // Getter for total price
369         public final function getTotalPrice () {
370                 // Get ship instance
371                 $shipInstance = $this->getShipInstance();
372
373                 // Is this a ship?
374                 if (is_null($shipInstance)) {
375                         // Opps! Empty partner instance?
376                         throw new NullPointerException($shipInstance, self::EXCEPTION_IS_NULL_POINTER);
377                 } elseif (!is_object($shipInstance)) {
378                         // Not an object! ;-(
379                         throw new NoObjectException($shipInstance, self::EXCEPTION_IS_NO_OBJECT);
380                 } elseif (!$shipInstance instanceof ConstructableShip) {
381                         // Does not have the required feature (method)
382                         throw new ShipIsInvalidException(array($shipInstance), self::EXCEPTION_INVALID_SHIP_INSTANCE);
383                 }
384
385                 // Get the structure array
386                 $struct = $shipInstance->getStructuresArray();
387
388                 // Is this a ship?
389                 if (is_null($struct)) {
390                         // Opps! Empty partner instance?
391                         throw new EmptyStructuresListException($this, self::EXCEPTION_EMPTY_STRUCTURES_ARRAY);
392                 }
393
394                 // Init total price
395                 $totalPrice = 0;
396
397                 // Iterate through the list
398                 for ($iter = $struct->getIterator(); $iter->valid(); $iter->next()) {
399                         // Get item
400                         $item = $iter->current();
401
402                         // Is this a ship?
403                         if (is_null($item)) {
404                                 // Opps! Empty partner instance?
405                                 throw new NullPointerException($item, self::EXCEPTION_IS_NULL_POINTER);
406                         } elseif (!is_object($item)) {
407                                 // Not an object! ;-(
408                                 throw new NoObjectException($item, self::EXCEPTION_IS_NO_OBJECT);
409                         } elseif (!method_exists($item, 'getPartInstance')) {
410                                 // Does not have the required feature (method)
411                                 throw new MissingMethodException(array($item, 'getPartInstance'), self::EXCEPTION_MISSING_METHOD);
412                         }
413
414                         // Get part instance
415                         $part = $item->getPartInstance();
416
417                         // Is this a ship?
418                         if (is_null($part)) {
419                                 // Opps! Empty partner instance?
420                                 throw new NullPointerException($part, self::EXCEPTION_IS_NULL_POINTER);
421                         } elseif (!is_object($part)) {
422                                 // Not an object! ;-(
423                                 throw new NoObjectException($part, self::EXCEPTION_IS_NO_OBJECT);
424                         } elseif (!method_exists($part, 'getPrice')) {
425                                 // Does not have the required feature (method)
426                                 throw new MissingMethodException(array($part, 'getPrice'), self::EXCEPTION_MISSING_METHOD);
427                         }
428
429                         // Get price for one item
430                         $price = $part->getPrice();
431
432                         // Is there numCabin() available?
433                         if (method_exists($item, 'getNumCabin')) {
434                                 // Get total cabin and multiply it with the price
435                                 $price = $price * $item->getNumCabin();
436                         }
437
438                         // Add price to total price
439                         $totalPrice += $price;
440                 }
441
442                 // Total price calculated?
443                 if ($totalPrice === 0) {
444                         // Throw exception
445                         throw new TotalPriceNotCalculatedException($this, self::EXCEPTION_TOTAL_PRICE_NOT_CALCULATED);
446                 }
447
448                 // Return total price
449                 return $totalPrice;
450         }
451
452         /**
453          * Stub!
454          */
455         public function saveObjectToDatabase () {
456                 $this->getDebugInstance()->output(sprintf("[%s:] Stub <strong>%s</strong> erreicht.",
457                         $this->__toString(),
458                         __FUNCTION__
459                 ));
460         }
461 }
462
463 // [EOF]
464 ?>