/** * Launches a new request. This would be the main entry for a Phlite * framework handled request. */ function __invoke() { Signal::connect('php.fatal', array($this, '__onShutdown')); Signal::connect('php.exception', array($this, '__onUnhandledException')); $this->loadMiddleware(); Signal::send('request.start', $this); try { $request = $this->getRequest(); $response = $this->getResponse($request); $response = $this->processResponse($request, $response); } catch (UnicodeException $ex) { $response = new HttpResponseBadRequest(); } catch (HttpException $ex) { $response = $ex->getResponse($request); } catch (\Exception $ex) { // TODO: Handle unhandled exception here return $this->middleware->reverse()->processException($request, $ex); } if ($response) { $response->setHandler($this); return $response->output($request); } }
function save($refetch = false) { if ($this->__deleted__) { throw new OrmException('Trying to update a deleted object'); } $pk = static::getMeta('pk'); $wasnew = $this->__new__; // First, if any foreign properties of this object are connected to // another *new* object, then save those objects first and set the // local foreign key field values foreach (static::getMeta('joins') as $prop => $j) { if (isset($this->ht[$prop]) && ($foreign = $this->ht[$prop]) && $foreign instanceof VerySimpleModel && !in_array($j['local'], $pk) && null === $this->get($j['local'])) { if ($foreign->__new__ && !$foreign->save()) { return false; } $this->set($j['local'], $foreign->get($j['fkey'][1])); } } // If there's nothing in the model to be saved, then we're done if (count($this->__dirty__) === 0) { return true; } $ex = Manager::save($this); try { $ex->execute(); if ($ex->affected_rows() != 1) { // This doesn't really signify an error. It just means that // the database believes that the row did not change. For // inserts though, it's a deal breaker if ($this->__new__) { return false; } else { // No need to reload the record if requested — the // database didn't update anything $refetch = false; } } } catch (Exception\OrmError $e) { return false; } if ($wasnew) { // XXX: Ensure AUTO_INCREMENT is set for the field if (count($pk) == 1 && !$refetch) { $key = $pk[0]; $id = $ex->insert_id(); if (!isset($this->{$key}) && $id) { $this->__ht__[$key] = $id; } } $this->__new__ = false; Signal::send('model.created', $this); } else { $data = array('dirty' => $this->__dirty__); Signal::send('model.updated', $this, $data); } # Refetch row from database if ($refetch) { // Preserve non database information such as list relationships // across the refetch $this->__ht__ = static::objects()->filter($this->getPk())->values()->one() + $this->__ht__; // TODO: Cache $this object } if ($wasnew) { // Attempt to update foreign, unsaved objects with the PK of // this newly created object foreach (static::getMeta('joins') as $prop => $j) { if (isset($this->ht[$prop]) && ($foreign = $this->ht[$prop]) && in_array($j['local'], $pk)) { if ($foreign instanceof VerySimpleModel && null === $foreign->get($j['fkey'][1])) { $foreign->set($j['fkey'][1], $this->get($j['local'])); } elseif ($foreign instanceof InstrumentedList) { foreach ($foreign as $item) { if (null === $item->get($j['fkey'][1])) { $item->set($j['fkey'][1], $this->get($j['local'])); } } } } } $this->__onsave(); } $this->__dirty__ = array(); return true; }