Commit 60a5f42a authored by Karamel's avatar Karamel
Browse files

Add some docblocks.

parent faa2c59b
......@@ -20,8 +20,15 @@
namespace Pasteque\Server\API;
interface API {
/** @param $app The AppContext. */
/** Interface for all Pastèque APIs. */
interface API
{
/**
* Create the API from the application context.
* @param \Pasteque\Server\AppContext $app The AppContext to read the
* parameters of the constructor from.
* @return \Pasteque\Server\API The created API.
*/
public static function fromApp($app);
}
\ No newline at end of file
}
......@@ -37,8 +37,11 @@ class TicketAPI extends APIHelper implements API
const MODEL_NAME = 'Pasteque\Server\Model\Ticket';
const DEFAULT_ORDER = '-number';
/** Check for duplicated ticket in database. This is required because
* Doctrine will crash everything if a DB exception is thrown. */
/**
* Check for duplicated ticket in database. This is required because
* Doctrine will crash everything if a DB exception is thrown.
* @param \Pasteque\Server\Model\Ticket $tkt
*/
private function canInsert($tkt) {
$search = $this->dao->search(static::MODEL_NAME,
[new DAOCondition('cashRegister', '=', $tkt->getCashRegister()),
......@@ -220,8 +223,12 @@ class TicketAPI extends APIHelper implements API
return $ticket;
}
/** Update the signature of the end-of-sequence FiscalTicket with
* the last ticket inserted. Does not commit. */
/**
* Update the signature of the end-of-sequence FiscalTicket with
* the last ticket inserted. Does not commit.
* @param \Pasteque\Server\Model\FiscalTicket $lastFTicket The last ticket
* of the sequence.
*/
protected function updateEOSTicket($lastFTicket) {
if ($lastFTicket === null) {
// TODO: warning
......@@ -243,7 +250,11 @@ class TicketAPI extends APIHelper implements API
$this->dao->write($eosTicket);
}
/** Delete is disabled. Does nothing and return null. */
/**
* Delete is disabled. Does nothing and return null.
* @param $id unused.
* @return null.
*/
public function delete($id) { return null; }
}
......@@ -28,6 +28,14 @@ use \Pasteque\Server\System\Login;
/** Utility class to call API methods. */
class APICaller {
/**
* Escape and format the API name to be safely called and match the API
* filename convention.
* '..' are removed, first letter is uppercased while the other are
* lowercased. The 'API' suffix is added/uppercased if required.
* @param string $apiName The name of the API.
* @return string The formated name of the API to match it's class name.
*/
public static function formatAPIName($apiName) {
$name = strtolower($apiName);
$name = str_replace('..', '', $name);
......@@ -40,6 +48,14 @@ class APICaller {
/**
* Run an API method and wrap the response in an APIResult.
* @param \Pasteque\Server\AppContext $app The application context.
* @param string $apiName The name of the API to call. It is formated with
* formatAPIName().
* @param string $methodName The name of the method to call within the API.
* @param array $args The arguments to pass to the method.
* @return \Pasteque\Server\System\API\APIResult An APIResult holding the
* result of the method. The content is the result of the method for
* successful calls, or an exception for rejected calls or errors.
*/
public static function run($app, $apiName, $methodName, $args = array()) {
if ($args === null) { $args = array(); }
......
......@@ -23,21 +23,27 @@ namespace Pasteque\Server\System\API;
/** Utility class for APICaller to format things. */
class APIMethodParser {
/** @var \Pasteque\Server\API\API */
private $api;
/** @var \ReflectionMethod */
private $method;
/** Build a parser.
* @param $api Instance of the API class.
* @param $method ReflexionMethod requested to call.
* to pass to the method. */
/**
* Build a parser.
* @param \Pasteque\Server\API\API $api Instance of the API class.
* @param \ReflectionMethod $method Method requested to call.
* to pass to the method.
*/
public function __construct($api, $method) {
$this->api = $api;
$this->method = $method;
}
/** Check that the number of arguments is suitable for the method.
* @param $args Flat or associative array of arguments.
* @return True if the size or $args is suitable for the targeted method. */
/**
* Check that the number of arguments is suitable for the method.
* @param array $args Flat or associative array of arguments.
* @return True if the size or $args is suitable for the targeted method.
*/
public function checkArgc($args) {
$reqParamCount = $this->method->getNumberOfRequiredParameters();
$allParamCount = $this->method->getNumberOfParameters();
......@@ -53,13 +59,15 @@ class APIMethodParser {
return true;
}
/** Get an array of arguments to pass to call the method.
/**
* Get an array of arguments to pass to call the method.
* Arguments are considered passing the $this->checkArgc() test.
* @param $args Associative of flat array
* @param array $args Associative of flat array
* to conform to the targeted method signature
* @return A flat array to use to call the method.
* @return array A flat array to use to call the method.
* @throws \BadMethodCallException if some named arguments
* are found but not all. */
* are found but not all.
*/
public function buildArgsArray($args) {
if ($this->isFlatArray($args)) { return $args; }
// Args is an associative array, look for named arguments
......@@ -84,9 +92,11 @@ class APIMethodParser {
public function getAPI() { return $this->api; }
public function getMethod() { return $this->method; }
/** @return int The number of required parameters. */
public function getMinArgc() {
return $this->method->getNumberOfRequiredParameters();
}
/** @return int The number of parameters including optional ones. */
public function getMaxArgc() {
return $this->method->getNumberOfParameters();
}
......
......@@ -25,11 +25,12 @@ class APIResult {
/** Call went well until the end, content is the result of the code. */
const STATUS_CALL_OK = 'ok';
/** Call is invalid (client-side error), content is an APIError. */
/** Call is invalid (client-side error), content is generally an Exception. */
const STATUS_CALL_REJECTED = 'rej';
/** Call encountered a server-side error, content is an APIError. */
/** Call encountered a server-side error, content is generally an Exception. */
const STATUS_CALL_ERROR = 'err';
/** See class constants. */
private $status;
private $content;
......@@ -38,19 +39,47 @@ class APIResult {
$this->content = $content;
}
/**
* Create a sucessful result.
* @param mixed $result The result of the method call.
* @return APIResult The result with status STATUS_CALL_OK and $result
* in the content.
*/
public static function success($result) {
return new APIResult(APIResult::STATUS_CALL_OK, $result);
}
/**
* @deprecated
* @see APIResult::reject()
*/
public static function badRequest() {
return new APIResult(APIResult::STATUS_CALL_REJECTED, 'Bad request');
}
/**
* @deprecated
* @see APIResult::reject()
*/
public static function forbidden() {
return new APIResult(APIResult::STATUS_CALL_REJECTED, 'Forbidden');
}
/**
* Create a reject result.
* @param \Pasteque\Server\Exception\PastequeException $reason The reason
* of rejection.
* @return APIResult The result with status STATUS_CALL_REJECTED and
* $result in the content.
*/
public static function reject($reason) {
return new APIResult(APIResult::STATUS_CALL_REJECTED, $reason);
}
/**
* Create an error result.
* @param \Exception $err_code The reason of the error.
* @return APIResult The result with status STATUS_CALL_ERROR and
* $err_code in the content.
*/
public static function error($err_code) {
return new APIResult(APIResult::STATUS_CALL_ERROR, $err_code);
}
......
......@@ -29,11 +29,14 @@ class DAOCondition
private $operator;
private $value;
/** Create a search condition.
* @param $fieldName Property name of the model to filter on.
* @param $operator Either '=', '!=' , '>', '>=', '<' or '<='.
/**
* Create a search condition.
* @param string $fieldName Property name of the model to filter on.
* This is not the database field name.
* @param string $operator Either '=', '!=' , '>', '>=', '<' or '<='.
* <field> '=' null is a valid condition as well as '!=' null.
* @param $value The value to use with the operator. */
* @param mixed $value The value to use with the operator.
*/
public function __construct($fieldName, $operator, $value) {
$this->fieldName = $fieldName;
$this->operator = $operator;
......@@ -43,4 +46,4 @@ class DAOCondition
public function getFieldName() { return $this->fieldName; }
public function getOperator() { return $this->operator; }
public function getValue() { return $this->value; }
}
\ No newline at end of file
}
......@@ -23,13 +23,16 @@ namespace Pasteque\Server\System\DAO;
/** Utility class to setup DAO. */
class DAOFactory
{
/** Get a DAO object.
/**
* Get a DAO object.
* @param $dbInfo Database connexion info from a DBModule
* @param $options Additionnal options in an associative array
* for the DAO. Allowed options are 'debug' (true/false). */
* for the DAO. Allowed options are 'debug' (true/false).
* @return DoctrineDAO The DAO according to the configuration.
*/
public static function getDAO($dbInfo, $options) {
// This prevents spreading references to DoctrineDAO everywhere in API
return new DoctrineDAO($dbInfo, $options);
}
}
\ No newline at end of file
}
......@@ -26,6 +26,7 @@ use \Doctrine\Common\Collections\Criteria;
use \Doctrine\ORM\EntityManager;
use \Doctrine\ORM\Tools\Setup;
/** DAO using Doctrine. */
class DoctrineDAO implements DAO
{
protected $em;
......@@ -47,8 +48,11 @@ class DoctrineDAO implements DAO
}
}
/** Get a DoctrineDAO. It does not try to connect to the database directly.
* @throw DBException if the type is unknown or unsupported. */
/**
* Get a DoctrineDAO.
* It does not try to connect to the database directly.
* @throw DBException if the type is unknown or unsupported.
*/
public function __construct($dbInfo, $options = array()) {
$path = [__DIR__ . '/../../Model'];
$isDevMode = (isset($options['debug'])) ? $options['debug'] : false;
......@@ -89,14 +93,22 @@ class DoctrineDAO implements DAO
else { return null; }
}
/** Start a transaction. It should be a private method automatically called
* through write/delete calls, but it may be required for hacky tricks.
* Do not use it unless starting updates from a dql request. */
/**
* Start a transaction.
* It should be a private method and is automatically called through
* write/delete calls, but it may be required for hacky tricks.
* Do not use it unless starting updates from a dql request.
*/
public function startTransaction() {
$this->em->beginTransaction();
$this->inTransaction = true;
}
/**
* End the transaction and commit changes.
* In case of error, rollback is done.
* @throws \Exception When something bad happens. Automatically rollbacks.
*/
public function commit() {
if (!$this->inTransaction) { return; }
try {
......@@ -115,16 +127,40 @@ class DoctrineDAO implements DAO
}
}
/**
* Append the model to the transaction.
* A transaction is automatically created if none is running.
* End the transaction with commit().
* @param DoctrineModel $model
*/
public function write($model) {
if (!$this->inTransaction) { $this->startTransaction(); }
$this->em->persist($model);
}
/**
* Read from database. May use caching.
* @param string $modelName The class name of the model. See MODEL_NAME
* in API classes.
* @param mixed $id The database id. It may be a single value or an
* associative array for composite keys.
* @return DoctrineModel|null
*/
public function read($modelName, $id) {
if ($id === null) { return null; }
return $this->em->find($modelName, $id);
}
/**
* Force reading from database.
* It skips reference caching and return the record as present in the
* database, while read may return a modified entity from it's cache.
* @param string $modelName The class name of the model. See MODEL_NAME
* in API classes.
* @param mixed $id The database id. It may be a single value or an
* associative array for composite keys.
* @return DoctrineModel|null
*/
public function readSnapshot($modelName, $id) {
if ($id === null) { return null; }
$entity = $this->roEm->find($modelName, $id);
......@@ -219,6 +255,21 @@ class DoctrineDAO implements DAO
}
}
/**
* Search records from the database.
* @param string $modelName The class name of the model. See MODEL_NAME
* in API classes.
* @param DAOCondition|DAOCondition[] A single or array of DAOConditions.
* When null, all records are returned.
* @param int|null $count The maximum number of records to return. Use null
* to disable the limit.
* @param int|null $offset The starting offset for pagination. Use null
* to disable it.
* @param string|array $order The field names for ordering. Prefix the name
* with '-' for a descending order, nothing or '+' for ascending order. Use
* null for undefined ordering.
* @return DoctrineModel[]
*/
public function search($modelName, $conditions = null,
$count = null, $offset = null, $order = null) {
$optimizePagination = false;
......@@ -260,6 +311,13 @@ class DoctrineDAO implements DAO
}
/**
* Count the number of records matching a search.
* @param string $modelName The class name of the model. See MODEL_NAME in
* API classes.
* @param DAOCondition|DAOCondition[] $conditions The search criterias.
* @return int The number of matching records.
*/
public function count($modelName, $conditions = array()) {
$qb = $this->em->createQueryBuilder();
$qb->select('count(model)')->from($modelName, 'model');
......@@ -282,8 +340,10 @@ class DoctrineDAO implements DAO
$this->roEm->getConnection()->close();
}
/** Access to low-level implementation.
* Should be used only for unit testing purposes. */
/**
* Access to low-level implementation.
* Should be used only for unit testing purposes.
*/
public function getEntityManager() {
return $this->em;
}
......
......@@ -24,7 +24,10 @@ namespace Pasteque\Server\System\DAO;
use \Pasteque\Server\Exception\InvalidFieldException;
use \Pasteque\Server\Exception\RecordNotFoundException;
/** Parent class of embedded models to use with Doctrine. */
/**
* Parent class of embedded models to use with Doctrine.
* Embedded models cannot be retreived outside their parent.
*/
abstract class DoctrineEmbeddedModel extends DoctrineModel
{
/**
......
......@@ -23,7 +23,10 @@ namespace Pasteque\Server\System\DAO;
use \Pasteque\Server\Exception\RecordNotFoundException;
/** Parent class of all main models (non-embedded) to use with Doctrine. */
/**
* Parent class of all main models (non-embedded) to use with Doctrine.
* Main models have meaning from themselves and can be retreived independently.
*/
abstract class DoctrineMainModel extends DoctrineModel
{
/**
......@@ -53,10 +56,12 @@ abstract class DoctrineMainModel extends DoctrineModel
}
}
/** @deprecated Use load instead. Id will be strictly internal
* @deprecated in future version of the API. But it is still used
* @deprecated for exported records.
/**
* Get an instance from it's internal id.
* Id will be strictly internal in future version of the API. But it is
* still used for exported records and some model does not have a
* reference-like property.
* @deprecated Use load instead when possible.
* @return A record linked to the DAO, or a new instance.
*/
public static function loadFromId($id, $dao) {
......
......@@ -26,11 +26,16 @@ use \Pasteque\Server\Exception\RecordNotFoundException;
/** Parent class of all models to use with Doctrine. */
abstract class DoctrineModel
{
/** List primitive typed field names of the model in an array, excluding id. */
/**
* Get the list of primitive typed field names of the model in an array,
* excluding id.
* @return string[]
*/
protected abstract static function getDirectFieldNames();
/**
* List reference field of the model in an array. A field is an associative
* List reference field of the model in an array.
* A field is an associative
* array with the following keys:
* name: The field name (declared in code)
* class: The full class name of the reference.
......@@ -64,6 +69,12 @@ abstract class DoctrineModel
}
}
/**
* Extract the value of a field in a suitable format.
* 'resource' typed values are converted to base64.
* @param string $field The name of the field (property) to extract.
* @return The value of that field.
*/
protected function directFieldToStruct($field) {
$value = call_user_func(array($this, 'get' . ucfirst($field)));
switch (gettype($value)) {
......@@ -74,6 +85,16 @@ abstract class DoctrineModel
}
}
/**
* Extract the value of an association field in a suitable format.
* Non embedded values are converted to their id, embedded values
* are converted to struct.
* @param string $field The definition of the field (property) to extract,
* as retreived from getAssociationFields.
* @return mixed The id (primitive type, associative array of primitive
* types) for non-embedded models, the complete associative array of
* primitive types for embedded models.
*/
protected function associationFieldToStruct($field) {
$value = call_user_func([$this, 'get' . ucfirst($field['name'])]);
// Association field
......
......@@ -26,11 +26,13 @@ namespace Pasteque\Server\System;
class DateUtils
{
/** Check if two dates are equals in seconds.
/**
* Check if two dates are equals in seconds.
* @param mixed $a Something representing a date (passed to readDate).
* @param maxed $b Something represinting a date (passed to readDate).
* @param mixed $b Something represinting a date (passed to readDate).
* @return True if the dates are equals. False if one is not a date
* or if they are different. Null and null are equals. */
* or if they are different. Null and null are equals.
*/
public static function equals($a, $b) {
$dateA = static::readDate($a);
$dateB = static::readDate($b);
......@@ -42,9 +44,10 @@ class DateUtils
return $dateA->getTimestamp() == $dateB->getTimestamp();
}
/** Convert a DateTime to timestamp in seconds.
* @param DateTime|null $date The date to convert.
* @return Null if $date is null or invalid,
/**
* Convert a DateTime to timestamp in seconds.
* @param \DateTime|null $date The date to convert.
* @return int|null Null if $date is null or invalid,
* timestamp if already a timestamp or a DateTime. */
public static function toTimestamp($date) {
if ($date === null) { return null; }
......@@ -55,10 +58,11 @@ class DateUtils
return null;
}
/** Convert a timestamp in second to a DateTime.
/**
* Convert a timestamp in second to a DateTime.
* Use DateUtils::readDate instead not to bother with the input format.
* @param int $timestamp The timestamp.
* @return DateTime|false DateTime on success, false if not a timestamp. */
* @return DateTime|bool DateTime on success, false if not a timestamp. */
public static function readTimestamp($timestamp) {
if (!is_int($timestamp)) {
return false;
......@@ -68,12 +72,14 @@ class DateUtils
return $date;
}
/** Convert a date string to a DateTime.
/**
* Convert a date string to a DateTime.
* Use DateUtils::readDate instead not to bother with the input format.
* @param string $string The date. Valid format are YYYY-MM-DD
* and YYYY-MM-DD HH:mm.
* @return DateTime|false DateTime on success, false if not a valid
* date string. */
* @return DateTime|bool DateTime on success, false if not a valid
* date string.
*/
public static function readString($string) {
$date = \DateTime::createFromFormat('!Y-m-d', $string);
if ($date === false) {
......@@ -82,7 +88,11 @@ class DateUtils
return $date;
}
/** Automatically detect date format and get a DateTime. */
/**
* Automatically detect date format and get a DateTime.
* @param int|string|\DateTime $input Something representing a date.
* @return \DateTime|bool The date as a \DateTime, false if invalid.
*/
public static function readDate($input) {
if ($input === null) { return null; }
if (is_int($input)) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment