diff --git a/composer.json b/composer.json
index 4ac274a..9ee3c91 100644
--- a/composer.json
+++ b/composer.json
@@ -21,10 +21,8 @@
"pluf/user" : "^2.1.0"
},
"require-dev" : {
- "phpunit/phpunit" : "^5.7.14",
- "phpunit/php-invoker" : "^1.1",
- "phpunit/dbunit" : "^2.0",
- "phpunit/phpunit-story" : "^1.0"
+ "pluf/test" : "^2.1.0",
+ "pluf/collection" : "^2.1.0"
},
"include-path" : [
"src/"
diff --git a/doc/Data-Model.uxf b/doc/Data-Model.uxf
new file mode 100644
index 0000000..b6e2dc0
--- /dev/null
+++ b/doc/Data-Model.uxf
@@ -0,0 +1,212 @@
+
+
+ 10
+
+ UMLClass
+
+ 690
+ 50
+ 210
+ 150
+
+ Tenant::Ticket
+--
++id: long
++type: string
++subject: string
++description: string
++status: string
++creation_dtime: datetime
++modif_dtime: datetime
+
+
+
+ UMLClass
+
+ 110
+ 50
+ 210
+ 160
+
+ Core::Tenant
+--
++id: long
++title: string
++description: string
++domain: string
++subdomain: string
++validate: boolean
++creation_dtime: datetime
++modif_dtime: datetime
+
+
+
+ UMLClass
+
+ 80
+ 590
+ 120
+ 30
+
+ Bank::Payment
+
+
+
+ UMLClass
+
+ 220
+ 590
+ 160
+ 30
+
+ Discount::Discount
+
+
+
+ UMLClass
+
+ 110
+ 310
+ 210
+ 170
+
+ Tenant::Invoice
+--
++id: long
++title: string
++description: string
++amount: integer
++due_date: date
++discount_code: string
++status: string
++creation_dtime: datetime
++modif_dtime: datetime
+
+
+
+ Relation
+
+ 140
+ 470
+ 80
+ 140
+
+ lt=-
+m1=1
+m2=1
+payment
+ 10.0;120.0;10.0;10.0
+
+
+ Relation
+
+ 280
+ 470
+ 80
+ 140
+
+ lt=-
+m1=1
+m2=1
+discount
+ 10.0;120.0;10.0;10.0
+
+
+ UMLClass
+
+ 460
+ 400
+ 100
+ 30
+
+ User::User
+
+
+
+ Relation
+
+ 500
+ 160
+ 210
+ 260
+
+ lt=-
+m1=1
+m2=*
+requester
+ 10.0;240.0;10.0;10.0;190.0;10.0
+
+
+ UMLClass
+
+ 690
+ 350
+ 210
+ 120
+
+ Tenant::Comment
+--
++id: long
++title: string
++description: string
++creation_dtime: datetime
++modif_dtime: datetime
+
+
+
+ Relation
+
+ 550
+ 390
+ 160
+ 50
+
+ lt=-
+m1=*
+m2=1
+author
+ 140.0;20.0;10.0;20.0
+
+
+ Relation
+
+ 780
+ 190
+ 90
+ 180
+
+ lt=-
+m1=*
+m2=1
+comments
+ 10.0;160.0;10.0;10.0
+
+
+ Relation
+
+ 310
+ 100
+ 400
+ 50
+
+ lt=-
+m1=*
+m2=1
+tickets
+ 380.0;20.0;10.0;20.0
+
+
+ Relation
+
+ 200
+ 200
+ 80
+ 130
+
+ lt=-
+m1=*
+m2=1
+invoices
+ 10.0;110.0;10.0;10.0
+
+
diff --git a/src/Tenant/Comment.php b/src/Tenant/Comment.php
new file mode 100755
index 0000000..b993b31
--- /dev/null
+++ b/src/Tenant/Comment.php
@@ -0,0 +1,106 @@
+_a['table'] = 'tenant_comment';
+ $this->_a['verbose'] = 'Tenant Comment';
+ $this->_a['cols'] = array(
+ 'id' => array(
+ 'type' => 'Pluf_DB_Field_Sequence',
+ 'blank' => false,
+ 'editable' => false,
+ 'readable' => true
+ ),
+ 'title' => array(
+ 'type' => 'Pluf_DB_Field_Varchar',
+ 'blank' => false,
+ 'is_null' => false,
+ 'size' => 256
+ ),
+ 'description' => array(
+ 'type' => 'Pluf_DB_Field_Varchar',
+ 'blank' => true,
+ 'is_null' => true,
+ 'size' => 2048
+ ),
+ 'creation_dtime' => array(
+ 'type' => 'Pluf_DB_Field_Datetime',
+ 'blank' => true,
+ 'is_null' => true,
+ 'editable' => false,
+ 'readable' => true
+ ),
+ 'modif_dtime' => array(
+ 'type' => 'Pluf_DB_Field_Datetime',
+ 'blank' => true,
+ 'is_null' => true,
+ 'editable' => false,
+ 'readable' => true
+ ),
+ // relations
+ 'author' => array(
+ 'type' => 'Pluf_DB_Field_Foreignkey',
+ 'model' => 'Pluf_User',
+ 'blank' => false,
+ 'is_null' => false,
+ 'editable' => false,
+ 'readable' => true,
+ 'relate_name' => 'author'
+ ),
+ 'ticket' => array(
+ 'type' => 'Pluf_DB_Field_Foreignkey',
+ 'model' => 'Tenant_Ticket',
+ 'blank' => false,
+ 'is_null' => false,
+ 'editable' => false,
+ 'readable' => true,
+ 'relate_name' => 'ticket'
+ )
+ );
+
+ // $this->_a['idx'] = array(
+ // 'comment_tenant_idx' => array(
+ // 'col' => 'secure_comment',
+ // 'type' => 'unique', // normal, unique, fulltext, spatial
+ // 'index_type' => '', // hash, btree
+ // 'index_option' => '',
+ // 'algorithm_option' => '',
+ // 'lock_option' => ''
+ // )
+ // );
+ }
+
+ /**
+ * \brief پیش ذخیره را انجام میدهد
+ *
+ * @param boolean $create
+ * حالت
+ * ساخت یا به روز رسانی را تعیین میکند
+ */
+ function preSave($create = false)
+ {
+ if ($this->id == '') {
+ $this->creation_dtime = gmdate('Y-m-d H:i:s');
+ }
+ $this->modif_dtime = gmdate('Y-m-d H:i:s');
+ }
+
+ /**
+ * حالت کار ایجاد شده را به روز میکند
+ *
+ * @see Pluf_Model::postSave()
+ */
+ function postSave($create = false)
+ {
+ //
+ }
+
+}
\ No newline at end of file
diff --git a/src/Tenant/Invoice.php b/src/Tenant/Invoice.php
new file mode 100755
index 0000000..ce63940
--- /dev/null
+++ b/src/Tenant/Invoice.php
@@ -0,0 +1,146 @@
+_a['table'] = 'tenant_invoice';
+ $this->_a['verbose'] = 'Tenant Invoice';
+ $this->_a['cols'] = array(
+ 'id' => array(
+ 'type' => 'Pluf_DB_Field_Sequence',
+ 'blank' => false,
+ 'editable' => false,
+ 'readable' => true
+ ),
+ 'title' => array(
+ 'type' => 'Pluf_DB_Field_Varchar',
+ 'blank' => true,
+ 'is_null' => true,
+ 'size' => 256
+ ),
+ 'description' => array(
+ 'type' => 'Pluf_DB_Field_Varchar',
+ 'blank' => true,
+ 'is_null' => true,
+ 'size' => 500
+ ),
+ 'amount' => array(
+ 'type' => 'Pluf_DB_Field_Integer',
+ 'blank' => false,
+ 'is_null' => false
+ ),
+ 'due_dtiem' => array(
+ 'type' => 'Pluf_DB_Field_Date',
+ 'blank' => false,
+ 'is_null' => false
+ ),
+ 'status' => array(
+ 'type' => 'Pluf_DB_Field_Varchar',
+ 'blank' => false,
+ 'is_null' => false,
+ 'size' => 50,
+ 'editable' => false,
+ 'readable' => true
+ ),
+ 'discount_code' => array(
+ 'type' => 'Pluf_DB_Field_Varchar',
+ 'blank' => true,
+ 'is_null' => true,
+ 'size' => 50,
+ 'editable' => false,
+ 'readable' => true
+ ),
+ 'creation_dtime' => array(
+ 'type' => 'Pluf_DB_Field_Datetime',
+ 'blank' => true,
+ 'is_null' => true,
+ 'editable' => false,
+ 'readable' => true
+ ),
+ 'modif_dtime' => array(
+ 'type' => 'Pluf_DB_Field_Datetime',
+ 'blank' => true,
+ 'is_null' => true,
+ 'editable' => false,
+ 'readable' => true
+ ),
+ // relations
+ 'payment' => array(
+ 'type' => 'Pluf_DB_Field_Foreignkey',
+ 'model' => 'Bank_Receipt',
+ 'blank' => false,
+ 'editable' => false,
+ 'readable' => true,
+ 'relate_name' => 'payment'
+ )
+ );
+
+ // $this->_a['idx'] = array(
+ // 'invoice_tenant_idx' => array(
+ // 'col' => 'secure_invoice',
+ // 'type' => 'unique', // normal, unique, fulltext, spatial
+ // 'index_type' => '', // hash, btree
+ // 'index_option' => '',
+ // 'algorithm_option' => '',
+ // 'lock_option' => ''
+ // )
+ // );
+ }
+
+ /**
+ * \brief پیش ذخیره را انجام میدهد
+ *
+ * @param boolean $create
+ * حالت
+ * ساخت یا به روز رسانی را تعیین میکند
+ */
+ function preSave($create = false)
+ {
+ if ($this->id == '') {
+ $this->creation_dtime = gmdate('Y-m-d H:i:s');
+ }
+ $this->modif_dtime = gmdate('Y-m-d H:i:s');
+ }
+
+ /**
+ * حالت کار ایجاد شده را به روز میکند
+ *
+ * @see Pluf_Model::postSave()
+ */
+ function postSave($create = false)
+ {
+ //
+ }
+
+ /**
+ * Returns status of this invoice
+ *
+ * @return string
+ */
+ function getStatus()
+ {
+ return $this->status;
+ }
+
+ function setStatus($status)
+ {
+ // if ($this->status === 'payed') {
+ // return;
+ // }
+ // // It is first time to activate invoice
+ // // Note: Hadi - 1396-04: time is base on day
+ // $day = Setting_Service::get(Tenant_Constants::SETTING_KEY_LINK_VALID_DAY, '30');
+ // $expiryDay = ' +' . $day . ' day';
+ // $this->expiry = date('Y-m-d H:i:s', strtotime($expiryDay));
+ // $this->active = true;
+ $this->status = $status;
+ $this->update();
+ }
+}
\ No newline at end of file
diff --git a/src/Tenant/Ticket.php b/src/Tenant/Ticket.php
new file mode 100755
index 0000000..5c22b01
--- /dev/null
+++ b/src/Tenant/Ticket.php
@@ -0,0 +1,125 @@
+_a['table'] = 'tenant_ticket';
+ $this->_a['verbose'] = 'Tenant Ticket';
+ $this->_a['cols'] = array(
+ 'id' => array(
+ 'type' => 'Pluf_DB_Field_Sequence',
+ 'blank' => false,
+ 'editable' => false,
+ 'readable' => true
+ ),
+ 'type' => array(
+ 'type' => 'Pluf_DB_Field_Varchar',
+ 'blank' => true,
+ 'is_null' => true,
+ 'size' => 256
+ ),
+ 'subject' => array(
+ 'type' => 'Pluf_DB_Field_Varchar',
+ 'blank' => false,
+ 'is_null' => false,
+ 'size' => 256
+ ),
+ 'description' => array(
+ 'type' => 'Pluf_DB_Field_Varchar',
+ 'blank' => true,
+ 'is_null' => true,
+ 'size' => 2048
+ ),
+ 'status' => array(
+ 'type' => 'Pluf_DB_Field_Varchar',
+ 'blank' => false,
+ 'is_null' => false,
+ 'size' => 50,
+ 'editable' => false,
+ 'readable' => true
+ ),
+ 'creation_dtime' => array(
+ 'type' => 'Pluf_DB_Field_Datetime',
+ 'blank' => true,
+ 'is_null' => true,
+ 'editable' => false,
+ 'readable' => true
+ ),
+ 'modif_dtime' => array(
+ 'type' => 'Pluf_DB_Field_Datetime',
+ 'blank' => true,
+ 'is_null' => true,
+ 'editable' => false,
+ 'readable' => true
+ ),
+ // relations
+ 'requester' => array(
+ 'type' => 'Pluf_DB_Field_Foreignkey',
+ 'model' => 'Pluf_User',
+ 'blank' => false,
+ 'editable' => false,
+ 'readable' => true,
+ 'relate_name' => 'requester'
+ )
+ );
+
+ // $this->_a['idx'] = array(
+ // 'ticket_tenant_idx' => array(
+ // 'col' => 'secure_ticket',
+ // 'type' => 'unique', // normal, unique, fulltext, spatial
+ // 'index_type' => '', // hash, btree
+ // 'index_option' => '',
+ // 'algorithm_option' => '',
+ // 'lock_option' => ''
+ // )
+ // );
+ }
+
+ /**
+ * \brief پیش ذخیره را انجام میدهد
+ *
+ * @param boolean $create
+ * حالت
+ * ساخت یا به روز رسانی را تعیین میکند
+ */
+ function preSave($create = false)
+ {
+ if ($this->id == '') {
+ $this->creation_dtime = gmdate('Y-m-d H:i:s');
+ }
+ $this->modif_dtime = gmdate('Y-m-d H:i:s');
+ }
+
+ /**
+ * حالت کار ایجاد شده را به روز میکند
+ *
+ * @see Pluf_Model::postSave()
+ */
+ function postSave($create = false)
+ {
+ //
+ }
+
+ /**
+ * Returns status of this ticket
+ *
+ * @return string
+ */
+ function getStatus()
+ {
+ return $this->status;
+ }
+
+ function setStatus($status)
+ {
+ $this->status = $status;
+ $this->update();
+ }
+}
\ No newline at end of file
diff --git a/src/Tenant/Views.php b/src/Tenant/Views.php
index 9089ba7..27bb3e7 100644
--- a/src/Tenant/Views.php
+++ b/src/Tenant/Views.php
@@ -30,8 +30,8 @@ class Tenant_Views extends Pluf_Views
/**
*
- * @param unknown_type $request
- * @param unknown_type $match
+ * @param Pluf_HTTP_Request $request
+ * @param array $match
*/
public static function current ($request, $match)
{
@@ -40,8 +40,8 @@ public static function current ($request, $match)
/**
*
- * @param unknown_type $request
- * @param unknown_type $match
+ * @param Pluf_HTTP_Request $request
+ * @param array $match
*/
public static function update ($request, $match)
{
@@ -53,8 +53,8 @@ public static function update ($request, $match)
/**
*
- * @param unknown_type $request
- * @param unknown_type $match
+ * @param Pluf_HTTP_Request $request
+ * @param array $match
*/
public static function get ($request, $match)
{
@@ -63,8 +63,8 @@ public static function get ($request, $match)
/**
*
- * @param unknown_type $request
- * @param unknown_type $match
+ * @param Pluf_HTTP_Request $request
+ * @param array $match
*/
public function delete ($request, $match)
{
diff --git a/src/Tenant/Views/Invoices.php b/src/Tenant/Views/Invoices.php
new file mode 100644
index 0000000..607ae79
--- /dev/null
+++ b/src/Tenant/Views/Invoices.php
@@ -0,0 +1,29 @@
+.
+ */
+
+/**
+ * Invoices view
+ *
+ * @author maso
+ */
+class Tenant_Views_Invoices
+{
+ // TODO: maso, 2017: adding payment
+}
\ No newline at end of file
diff --git a/src/Tenant/module.json b/src/Tenant/module.json
index 2165173..9830844 100644
--- a/src/Tenant/module.json
+++ b/src/Tenant/module.json
@@ -2,6 +2,11 @@
"name": "Tenant",
"version": "2.1.9",
"title": "Tenant Management",
+ "model": [
+ "Tenant_Invoice",
+ "Tenant_Ticket",
+ "Tenant_Comment"
+ ],
"permisson": [],
"monitor":[{
"bean": "tenant",
diff --git a/src/Tenant/relations.php b/src/Tenant/relations.php
index 0170fc3..a7a7ac9 100644
--- a/src/Tenant/relations.php
+++ b/src/Tenant/relations.php
@@ -16,4 +16,23 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-return array ();
\ No newline at end of file
+return array(
+ 'Tenant_Invoice' => array(
+ 'relate_to' => array(
+ 'Bank_Receipt'
+ )
+ ),
+ 'Tenant_Ticket' => array(
+ 'relate_to' => array(
+ 'Pluf_User'
+ ),
+ 'relate_to_many' => array(
+ 'Tenant_Comment'
+ )
+ ),
+ 'Tenant_Comment' => array(
+ 'relate_to' => array(
+ 'Pluf_User'
+ )
+ )
+);
\ No newline at end of file
diff --git a/src/Tenant/urls.php b/src/Tenant/urls.php
index 9b23ada..19edc8f 100644
--- a/src/Tenant/urls.php
+++ b/src/Tenant/urls.php
@@ -17,15 +17,18 @@
* along with this program. If not, see .
*/
return array(
+ /*
+ * Tenant
+ */
array(
- 'regex' => '#^$#',
+ 'regex' => '#^/tenant/current$#',
'model' => 'Tenant_Views',
'method' => 'current',
'http-method' => 'GET',
'precond' => array()
),
array(
- 'regex' => '#^$#',
+ 'regex' => '#^/tenant/current$#',
'model' => 'Tenant_Views',
'method' => 'update',
'http-method' => 'POST',
@@ -34,57 +37,239 @@
)
),
array(
- 'regex' => '#^$#',
+ 'regex' => '#^/tenant/current$#',
'model' => 'Tenant_Views',
'method' => 'delete',
'http-method' => 'DELETE',
'precond' => array(
'Pluf_Precondition::ownerRequired'
)
+ ),
+ /*
+ * Ticket
+ */
+ array(
+ 'regex' => '#^/ticket/find$#',
+ 'model' => 'Pluf_Views',
+ 'method' => 'findObject',
+ 'http-method' => 'GET',
+ 'precond' => array(
+ 'Pluf_Precondition::ownerRequired'
+ ),
+ 'params' => array(
+ 'model' => 'Tenant_Ticket',
+ 'listFilters' => array(
+ 'status',
+ 'type',
+ 'requester'
+ ),
+ 'listDisplay' => array(),
+ 'searchFields' => array(
+ 'subject',
+ 'description'
+ ),
+ 'sortFields' => array(
+ 'id',
+ 'status',
+ 'type',
+ 'modif_dtime',
+ 'creation_dtime'
+ ),
+ 'sortOrder' => array(
+ 'id',
+ 'DESC'
+ )
+ )
+ ),
+ array(
+ 'regex' => '#^/ticket/new$#',
+ 'model' => 'Pluf_Views',
+ 'method' => 'createObject',
+ 'http-method' => 'POST',
+ 'precond' => array(
+ 'Pluf_Precondition::ownerRequired'
+ ),
+ 'params' => array(
+ 'model' => 'Tenant_Ticket'
+ )
+ ),
+ array(
+ 'regex' => '#^/ticket/(?P\d+)$#',
+ 'model' => 'Pluf_Views',
+ 'method' => 'getObject',
+ 'http-method' => 'GET',
+ 'precond' => array(
+ 'Pluf_Precondition::ownerRequired'
+ ),
+ 'params' => array(
+ 'model' => 'Tenant_Ticket'
+ )
+ ),
+ array(
+ 'regex' => '#^/ticket/(?P\d+)$#',
+ 'model' => 'Pluf_Views',
+ 'method' => 'updateObject',
+ 'http-method' => 'POST',
+ 'precond' => array(
+ 'Pluf_Precondition::ownerRequired'
+ ),
+ 'params' => array(
+ 'model' => 'Tenant_Ticket'
+ )
+ ),
+ array(
+ 'regex' => '#^/ticket/(?P\d+)$#',
+ 'model' => 'Pluf_Views',
+ 'method' => 'deleteObject',
+ 'http-method' => 'DELETE',
+ 'precond' => array(
+ 'Pluf_Precondition::ownerRequired'
+ ),
+ 'params' => array(
+ 'model' => 'Tenant_Ticket'
+ )
+ ),
+ /*
+ * Comments of ticket
+ */
+ array(
+ 'regex' => '#^/ticket/(?P\d+)/comment/find$#',
+ 'model' => 'Pluf_Views',
+ 'method' => 'findManyToOne',
+ 'http-method' => 'GET',
+ 'precond' => array(
+ 'Pluf_Precondition::ownerRequired'
+ ),
+ 'params' => array(
+ 'model' => 'Tenant_Comment',
+ 'parent' => 'Tenant_Ticket',
+ 'parentKey' => 'ticket',
+ 'listFilters' => array(
+ 'status',
+ 'type',
+ 'requester'
+ ),
+ 'listDisplay' => array(),
+ 'searchFields' => array(
+ 'subject',
+ 'description'
+ ),
+ 'sortFields' => array(
+ 'id',
+ 'status',
+ 'type',
+ 'modif_dtime',
+ 'creation_dtime'
+ ),
+ 'sortOrder' => array(
+ 'id',
+ 'DESC'
+ )
+ )
+ ),
+ array(
+ 'regex' => '#^/ticket/(?P\d+)/comment/new$#',
+ 'model' => 'Pluf_Views',
+ 'method' => 'createManyToOne',
+ 'http-method' => 'POST',
+ 'precond' => array(
+ 'Pluf_Precondition::ownerRequired'
+ ),
+ 'params' => array(
+ 'model' => 'Tenant_Comment',
+ 'parent' => 'Tenant_Ticket',
+ 'parentKey' => 'ticket'
+ )
+ ),
+ array(
+ 'regex' => '#^/ticket/(?P\d+)/comment/(?P\d+)$#',
+ 'model' => 'Pluf_Views',
+ 'method' => 'getManyToOne',
+ 'http-method' => 'GET',
+ 'precond' => array(
+ 'Pluf_Precondition::ownerRequired'
+ ),
+ 'params' => array(
+ 'model' => 'Tenant_Comment',
+ 'parent' => 'Tenant_Ticket',
+ 'parentKey' => 'ticket'
+ )
+ ),
+ array(
+ 'regex' => '#^/ticket/(?P\d+)/comment/(?P\d+)$#',
+ 'model' => 'Pluf_Views',
+ 'method' => 'updateManyToOne',
+ 'http-method' => 'POST',
+ 'precond' => array(
+ 'Pluf_Precondition::ownerRequired'
+ ),
+ 'params' => array(
+ 'model' => 'Tenant_Comment',
+ 'parent' => 'Tenant_Ticket',
+ 'parentKey' => 'ticket'
+ )
+ ),
+ array(
+ 'regex' => '#^/ticket/(?P\d+)/comment/(?P\d+)$#',
+ 'model' => 'Pluf_Views',
+ 'method' => 'deleteManyToOne',
+ 'http-method' => 'DELETE',
+ 'precond' => array(
+ 'Pluf_Precondition::ownerRequired'
+ ),
+ 'params' => array(
+ 'model' => 'Tenant_Comment',
+ 'parent' => 'Tenant_Ticket',
+ 'parentKey' => 'ticket'
+ )
+ ),
+
+ /*
+ * invoices
+ */
+ array(
+ 'regex' => '#^/invoice/find$#',
+ 'model' => 'Pluf_Views',
+ 'method' => 'findObject',
+ 'http-method' => 'GET',
+ 'precond' => array(
+ 'Pluf_Precondition::ownerRequired'
+ ),
+ 'params' => array(
+ 'model' => 'Tenant_Invoice',
+ 'listFilters' => array(
+ 'id',
+ 'status'
+ ),
+ 'listDisplay' => array(),
+ 'searchFields' => array(
+ 'title',
+ 'description'
+ ),
+ 'sortFields' => array(
+ 'id',
+ 'status',
+ 'amount',
+ 'due_dtiem',
+ 'modif_dtime',
+ 'creation_dtime'
+ ),
+ 'sortOrder' => array(
+ 'id',
+ 'DESC'
+ )
+ )
+ ),
+ array(
+ 'regex' => '#^/invoice/(?P\d+)$#',
+ 'model' => 'Pluf_Views',
+ 'method' => 'getObject',
+ 'http-method' => 'GET',
+ 'precond' => array(
+ 'Pluf_Precondition::ownerRequired'
+ ),
+ 'params' => array(
+ 'model' => 'Tenant_Invoice'
+ )
)
-// array(
-// 'regex' => '#^/find$#',
-// 'model' => 'Tenant_Views',
-// 'method' => 'find',
-// 'http-method' => 'GET',
-// 'precond' => array(
-// 'Pluf_Precondition::loginRequired'
-// )
-// ),
-// array(
-// 'regex' => '#^/new$#',
-// 'model' => 'Tenant_Views',
-// 'method' => 'create',
-// 'http-method' => 'POST',
-// 'precond' => array(
-// 'Pluf_Precondition::loginRequired'
-// )
-// ),
-// array(
-// 'regex' => '#^/(?P.+)$#',
-// 'model' => 'Tenant_Views',
-// 'method' => 'get',
-// 'http-method' => 'GET',
-// 'precond' => array(
-// 'Pluf_Precondition::loginRequired'
-// )
-// ),
-// array(
-// 'regex' => '#^/(?P.+)$#',
-// 'model' => 'Tenant_Views',
-// 'method' => 'update',
-// 'http-method' => 'POST',
-// 'precond' => array(
-// 'Pluf_Precondition::loginRequired'
-// )
-// ),
-// array(
-// 'regex' => '#^/(?P.+)$#',
-// 'model' => 'Tenant_Views',
-// 'method' => 'delete',
-// 'http-method' => 'DELETE',
-// 'precond' => array(
-// 'Pluf_Precondition::loginRequired'
-// )
-// )
);
diff --git a/tests/Pluf_Tenant_REST/PlufTenantSingleEmptyTest.php b/tests/Pluf_Tenant_REST/PlufTenantSingleEmptyTest.php
new file mode 100644
index 0000000..565739c
--- /dev/null
+++ b/tests/Pluf_Tenant_REST/PlufTenantSingleEmptyTest.php
@@ -0,0 +1,76 @@
+.
+ */
+use PHPUnit\Framework\TestCase;
+use PHPUnit\Framework\IncompleteTestError;
+require_once 'Pluf.php';
+
+
+/**
+ * @backupGlobals disabled
+ * @backupStaticAttributes disabled
+ */
+class PlufTenantSingleEmptyTest extends TestCase
+{
+
+ /**
+ * @before
+ */
+ protected function setUp ()
+ {
+ Pluf::start(dirname(__FILE__) . '/../conf/config.singleEmptyTenant.php');
+ }
+
+ /**
+ * @test
+ */
+ public function testDefaultTenant ()
+ {
+ $tenant = Pluf_Tenant::current();
+ $this->assertNotNull($tenant);
+
+ // check id
+ $id = $tenant->id;
+ $this->assertNotNull($id);
+
+ // check title
+ $title = $tenant->title;
+ $this->assertNotNull($title);
+
+ // check description
+ $desc = $tenant->description;
+ $this->assertNotNull($desc);
+ }
+
+
+ /**
+ * @test
+ */
+ public function testStoragePath()
+ {
+ $tenant = Pluf_Tenant::current();
+ $this->assertNotNull($tenant);
+
+ $storage = $tenant->storagePath();
+ $this->assertNotNull($storage);
+ $this->assertEquals(Pluf::f('upload_path'), $storage);
+ }
+
+}
+
+
diff --git a/tests/Pluf_Tenant_REST/PlufTenantSingleTest.php b/tests/Pluf_Tenant_REST/PlufTenantSingleTest.php
new file mode 100755
index 0000000..5bcee08
--- /dev/null
+++ b/tests/Pluf_Tenant_REST/PlufTenantSingleTest.php
@@ -0,0 +1,73 @@
+.
+ */
+use PHPUnit\Framework\TestCase;
+use PHPUnit\Framework\IncompleteTestError;
+require_once 'Pluf.php';
+
+/**
+ * @backupGlobals disabled
+ * @backupStaticAttributes disabled
+ */
+class PlufTenantSingleTest extends TestCase
+{
+
+ /**
+ * @before
+ */
+ protected function setUp ()
+ {
+ Pluf::start(dirname(__FILE__) . '/../conf/config.singleTenant.php');
+ }
+
+ /**
+ * @test
+ */
+ public function testDefaultTenant ()
+ {
+ $tenant = Pluf_Tenant::current();
+ $this->assertNotNull($tenant);
+
+ // check id
+ $id = $tenant->id;
+ $this->assertNotNull($id);
+
+ // check title
+ $title = $tenant->title;
+ $this->assertNotNull($title);
+
+ // check description
+ $desc = $tenant->description;
+ $this->assertNotNull($desc);
+ }
+
+
+ /**
+ * @test
+ */
+ public function testStoragePath()
+ {
+ $tenant = Pluf_Tenant::current();
+ $this->assertNotNull($tenant);
+
+ $storage = $tenant->storagePath();
+ $this->assertNotNull($storage);
+ $this->assertEquals(Pluf::f('upload_path'), $storage);
+ }
+}
+
diff --git a/tests/Tenant_REST/InvoicesTest.php b/tests/Tenant_REST/InvoicesTest.php
new file mode 100644
index 0000000..127fe4d
--- /dev/null
+++ b/tests/Tenant_REST/InvoicesTest.php
@@ -0,0 +1,215 @@
+.
+ */
+use PHPUnit\Framework\TestCase;
+require_once 'Pluf.php';
+
+/**
+ * @backupGlobals disabled
+ * @backupStaticAttributes disabled
+ */
+class Tenant_REST_InvoicesTest extends TestCase
+{
+
+ /**
+ * @beforeClass
+ */
+ public static function installApps()
+ {
+ Pluf::start(dirname(__FILE__) . '/../conf/config-01.php');
+ $m = new Pluf_Migration(array(
+ 'Pluf',
+ 'Tenant'
+ ));
+ $m->install();
+ // Test user
+ $user = new Pluf_User();
+ $user->login = 'test';
+ $user->first_name = 'test';
+ $user->last_name = 'test';
+ $user->email = 'toto@example.com';
+ $user->setPassword('test');
+ $user->active = true;
+ $user->administrator = true;
+ if (true !== $user->create()) {
+ throw new Exception();
+ }
+
+ // Test tenant
+ $tenant = new Pluf_Tenant();
+ $tenant->domain = 'localhost';
+ $tenant->subdomain = 'test';
+ $tenant->validate = true;
+ if (true !== $tenant->create()) {
+ throw new Pluf_Exception('Faile to create new tenant');
+ }
+
+ $client = new Test_Client(array());
+ $GLOBALS['_PX_request']->tenant = $tenant;
+
+ $per = new Pluf_RowPermission();
+ $per->version = 1;
+ $per->model_id = $tenant->id;
+ $per->model_class = 'Pluf_Tenant';
+ $per->owner_id = $user->id;
+ $per->owner_class = 'Pluf_User';
+ $per->create();
+ }
+
+ /**
+ * @afterClass
+ */
+ public static function uninstallApps()
+ {
+ $m = new Pluf_Migration(array(
+ 'Pluf',
+ 'Tenant'
+ ));
+ $m->unInstall();
+ }
+
+ /**
+ * Getting invoice list
+ *
+ * @test
+ */
+ public function testFindInvoices()
+ {
+ $client = new Test_Client(array(
+ array(
+ 'app' => 'Tenant',
+ 'regex' => '#^/api/tenant#',
+ 'base' => '',
+ 'sub' => include 'Tenant/urls.php'
+ ),
+ array(
+ 'app' => 'User',
+ 'regex' => '#^/api/user#',
+ 'base' => '',
+ 'sub' => include 'User/urls.php'
+ )
+ ));
+ // login
+ $response = $client->post('/api/user/login', array(
+ 'login' => 'test',
+ 'password' => 'test'
+ ));
+ Test_Assert::assertResponseStatusCode($response, 200, 'Fail to login');
+
+ // find
+ $response = $client->get('/api/tenant/invoice/find');
+ Test_Assert::assertResponseNotNull($response, 'Find result is empty');
+ Test_Assert::assertResponseStatusCode($response, 200, 'Find status code is not 200');
+ Test_Assert::assertResponsePaginateList($response, 'Find result is not JSON paginated list');
+ }
+
+ /**
+ * Getting invoice list
+ *
+ * Check non-empty list
+ *
+ * @test
+ */
+ public function testFindInvoicesNonEmpty()
+ {
+ $client = new Test_Client(array(
+ array(
+ 'app' => 'Tenant',
+ 'regex' => '#^/api/tenant#',
+ 'base' => '',
+ 'sub' => include 'Tenant/urls.php'
+ ),
+ array(
+ 'app' => 'User',
+ 'regex' => '#^/api/user#',
+ 'base' => '',
+ 'sub' => include 'User/urls.php'
+ )
+ ));
+ // login
+ $response = $client->post('/api/user/login', array(
+ 'login' => 'test',
+ 'password' => 'test'
+ ));
+ Test_Assert::assertResponseStatusCode($response, 200, 'Fail to login');
+
+ $i = new Tenant_Invoice();
+ $i->title = 'test';
+ $i->descscription = 'test';
+ $i->amount = 1000;
+ $i->due_dtiem = gmdate('Y-m-d H:i:s');
+ $i->create();
+
+ // find
+ $response = $client->get('/api/tenant/invoice/find');
+ Test_Assert::assertResponseNotNull($response, 'Find result is empty');
+ Test_Assert::assertResponseStatusCode($response, 200, 'Find status code is not 200');
+ Test_Assert::assertResponsePaginateList($response, 'Find result is not JSON paginated list');
+ Test_Assert::assertResponseNonEmptyPaginateList($response, 'No object is in list');
+
+ // delete
+ $i->delete();
+ }
+
+
+ /**
+ * Getting invoice
+ *
+ * @test
+ */
+ public function testGetInvoice()
+ {
+ $client = new Test_Client(array(
+ array(
+ 'app' => 'Tenant',
+ 'regex' => '#^/api/tenant#',
+ 'base' => '',
+ 'sub' => include 'Tenant/urls.php'
+ ),
+ array(
+ 'app' => 'User',
+ 'regex' => '#^/api/user#',
+ 'base' => '',
+ 'sub' => include 'User/urls.php'
+ )
+ ));
+ // login
+ $response = $client->post('/api/user/login', array(
+ 'login' => 'test',
+ 'password' => 'test'
+ ));
+ Test_Assert::assertResponseStatusCode($response, 200, 'Fail to login');
+
+ $i = new Tenant_Invoice();
+ $i->title = 'test';
+ $i->descscription = 'test';
+ $i->amount = 1000;
+ $i->due_dtiem = gmdate('Y-m-d H:i:s');
+ $i->create();
+
+ // find
+ $response = $client->get('/api/tenant/invoice/'. $i->id);
+ Test_Assert::assertResponseNotNull($response);
+ Test_Assert::assertResponseStatusCode($response, 200);
+ Test_Assert::assertResponseNotAnonymousModel($response, 'Invoice not foudn');
+
+ // delete
+ $i->delete();
+ }
+}
+
diff --git a/tests/Tenant_REST/TenantTest.php b/tests/Tenant_REST/TenantTest.php
new file mode 100755
index 0000000..3a0c902
--- /dev/null
+++ b/tests/Tenant_REST/TenantTest.php
@@ -0,0 +1,108 @@
+.
+ */
+use PHPUnit\Framework\TestCase;
+require_once 'Pluf.php';
+
+/**
+ * @backupGlobals disabled
+ * @backupStaticAttributes disabled
+ */
+class Tenant_REST_TenantTest extends TestCase
+{
+
+ /**
+ * @beforeClass
+ */
+ public static function installApps()
+ {
+ Pluf::start(dirname(__FILE__) . '/../conf/config-01.php');
+ $m = new Pluf_Migration(array(
+ 'Pluf',
+ 'Tenant'
+ ));
+ $m->install();
+ // Test user
+ $user = new Pluf_User();
+ $user->login = 'test';
+ $user->first_name = 'test';
+ $user->last_name = 'test';
+ $user->email = 'toto@example.com';
+ $user->setPassword('test');
+ $user->active = true;
+ $user->administrator = true;
+ if (true !== $user->create()) {
+ throw new Exception();
+ }
+
+ // Test tenant
+ $tenant = new Pluf_Tenant();
+ $tenant->domain = 'localhost';
+ $tenant->subdomain = 'test';
+ $tenant->validate = true;
+ if (true !== $tenant->create()) {
+ throw new Pluf_Exception('Faile to create new tenant');
+ }
+
+ $client = new Test_Client(array());
+ $GLOBALS['_PX_request']->tenant = $tenant;
+
+ $per = new Pluf_RowPermission();
+ $per->version = 1;
+ $per->model_id = $tenant->id;
+ $per->model_class = 'Pluf_Tenant';
+ $per->owner_id = $user->id;
+ $per->owner_class = 'Pluf_User';
+ $per->create();
+ }
+
+ /**
+ * @afterClass
+ */
+ public static function uninstallApps()
+ {
+ $m = new Pluf_Migration(array(
+ 'Pluf',
+ 'Tenant'
+ ));
+ $m->unInstall();
+ }
+
+ /**
+ * Getting tenant info
+ *
+ * Call tenant to get current tenant information.
+ *
+ * @test
+ */
+ public function testDefaultTenant()
+ {
+ $client = new Test_Client(array(
+ array(
+ 'app' => 'Tenant',
+ 'regex' => '#^/api/tenant#',
+ 'base' => '',
+ 'sub' => include 'Tenant/urls.php'
+ )
+ ));
+ $response = $client->get('/api/tenant/tenant/current');
+ $this->assertNotNull($response);
+ $this->assertEquals($response->status_code, 200);
+ }
+}
+
diff --git a/tests/Tenant_REST/TicketCommentTest.php b/tests/Tenant_REST/TicketCommentTest.php
new file mode 100644
index 0000000..bc932b5
--- /dev/null
+++ b/tests/Tenant_REST/TicketCommentTest.php
@@ -0,0 +1,448 @@
+.
+ */
+use PHPUnit\Framework\TestCase;
+require_once 'Pluf.php';
+
+/**
+ * @backupGlobals disabled
+ * @backupStaticAttributes disabled
+ */
+class Tenant_REST_TicketCommentsTest extends TestCase
+{
+
+ /**
+ * @beforeClass
+ */
+ public static function installApps()
+ {
+ Pluf::start(dirname(__FILE__) . '/../conf/config-01.php');
+ $m = new Pluf_Migration(array(
+ 'Pluf',
+ 'Tenant'
+ ));
+ $m->install();
+ // Test user
+ $user = new Pluf_User();
+ $user->login = 'test';
+ $user->first_name = 'test';
+ $user->last_name = 'test';
+ $user->email = 'toto@example.com';
+ $user->setPassword('test');
+ $user->active = true;
+ $user->administrator = true;
+ if (true !== $user->create()) {
+ throw new Exception();
+ }
+
+ // Test tenant
+ $tenant = new Pluf_Tenant();
+ $tenant->domain = 'localhost';
+ $tenant->subdomain = 'test';
+ $tenant->validate = true;
+ if (true !== $tenant->create()) {
+ throw new Pluf_Exception('Faile to create new tenant');
+ }
+
+ $client = new Test_Client(array());
+ $GLOBALS['_PX_request']->tenant = $tenant;
+
+ $per = new Pluf_RowPermission();
+ $per->version = 1;
+ $per->model_id = $tenant->id;
+ $per->model_class = 'Pluf_Tenant';
+ $per->owner_id = $user->id;
+ $per->owner_class = 'Pluf_User';
+ $per->create();
+ }
+
+ /**
+ * @afterClass
+ */
+ public static function uninstallApps()
+ {
+ $m = new Pluf_Migration(array(
+ 'Pluf',
+ 'Tenant'
+ ));
+ $m->unInstall();
+ }
+
+ /**
+ * Getting tenant tickets
+ *
+ * Call tenant to get list of tickets
+ *
+ * @test
+ */
+ public function testFindTikcetComments()
+ {
+ $client = new Test_Client(array(
+ array(
+ 'app' => 'Tenant',
+ 'regex' => '#^/api/tenant#',
+ 'base' => '',
+ 'sub' => include 'Tenant/urls.php'
+ ),
+ array(
+ 'app' => 'User',
+ 'regex' => '#^/api/user#',
+ 'base' => '',
+ 'sub' => include 'User/urls.php'
+ )
+ ));
+ // login
+ $response = $client->post('/api/user/login', array(
+ 'login' => 'test',
+ 'password' => 'test'
+ ));
+ Test_Assert::assertResponseStatusCode($response, 200, 'Fail to login');
+
+ // Create ticket
+ $user = new Pluf_User();
+ $user = $user->getUser('test');
+
+ $t = new Tenant_Ticket();
+ $t->subject = 'test';
+ $t->description = 'test';
+ $t->type = 'bug';
+ $t->status = 'new';
+ $t->requester = $user;
+ $t->create();
+
+ // find comments
+ $response = $client->get('/api/tenant/ticket/' . $t->id . '/comment/find');
+ Test_Assert::assertResponseNotNull($response, 'Find result is empty');
+ Test_Assert::assertResponseStatusCode($response, 200, 'Find status code is not 200');
+ Test_Assert::assertResponsePaginateList($response, 'Find result is not JSON paginated list');
+
+ // delete
+ $t->delete();
+ }
+
+ /**
+ * Getting not empety comments
+ *
+ * @test
+ */
+ public function testFindTikcetCommentSNotEmpty()
+ {
+ $client = new Test_Client(array(
+ array(
+ 'app' => 'Tenant',
+ 'regex' => '#^/api/tenant#',
+ 'base' => '',
+ 'sub' => include 'Tenant/urls.php'
+ ),
+ array(
+ 'app' => 'User',
+ 'regex' => '#^/api/user#',
+ 'base' => '',
+ 'sub' => include 'User/urls.php'
+ )
+ ));
+ // login
+ $response = $client->post('/api/user/login', array(
+ 'login' => 'test',
+ 'password' => 'test'
+ ));
+ Test_Assert::assertResponseStatusCode($response, 200, 'Fail to login');
+
+ // Create ticket
+ $user = new Pluf_User();
+ $user = $user->getUser('test');
+
+ $t = new Tenant_Ticket();
+ $t->subject = 'test';
+ $t->description = 'test';
+ $t->type = 'bug';
+ $t->status = 'new';
+ $t->requester = $user;
+ $t->create();
+
+ $c = new Tenant_Comment();
+ $c->title = 'test';
+ $c->description = 'test';
+ $c->author = $user;
+ $c->ticket = $t;
+ $c->create();
+
+ // find comments
+ $response = $client->get('/api/tenant/ticket/' . $t->id . '/comment/find');
+ Test_Assert::assertResponseNotNull($response, 'Find result is empty');
+ Test_Assert::assertResponseStatusCode($response, 200, 'Find status code is not 200');
+ Test_Assert::assertResponsePaginateList($response);
+ Test_Assert::assertResponseNonEmptyPaginateList($response);
+
+ // delete
+ $c->delete();
+ $t->delete();
+ }
+
+ /**
+ * Getting comment
+ *
+ * @test
+ */
+ public function testGetTikcetComment()
+ {
+ $client = new Test_Client(array(
+ array(
+ 'app' => 'Tenant',
+ 'regex' => '#^/api/tenant#',
+ 'base' => '',
+ 'sub' => include 'Tenant/urls.php'
+ ),
+ array(
+ 'app' => 'User',
+ 'regex' => '#^/api/user#',
+ 'base' => '',
+ 'sub' => include 'User/urls.php'
+ )
+ ));
+ // login
+ $response = $client->post('/api/user/login', array(
+ 'login' => 'test',
+ 'password' => 'test'
+ ));
+ Test_Assert::assertResponseStatusCode($response, 200, 'Fail to login');
+
+ // Create ticket
+ $user = new Pluf_User();
+ $user = $user->getUser('test');
+
+ $t = new Tenant_Ticket();
+ $t->subject = 'test';
+ $t->description = 'test';
+ $t->type = 'bug';
+ $t->status = 'new';
+ $t->requester = $user;
+ $t->create();
+
+ $c = new Tenant_Comment();
+ $c->title = 'test';
+ $c->description = 'test';
+ $c->author = $user;
+ $c->ticket = $t;
+ $c->create();
+
+ // find comments
+ $response = $client->get('/api/tenant/ticket/' . $t->id . '/comment/' . $c->id);
+ Test_Assert::assertResponseNotNull($response, 'Find result is empty');
+ Test_Assert::assertResponseStatusCode($response, 200, 'Find status code is not 200');
+ Test_Assert::assertResponseAsModel($response);
+ Test_Assert::assertResponseNotAnonymousModel($response);
+
+ // delete
+ $c->delete();
+ $t->delete();
+ }
+
+ /**
+ * Creating comment
+ *
+ * @test
+ */
+ public function testCreateTikcetComment()
+ {
+ $client = new Test_Client(array(
+ array(
+ 'app' => 'Tenant',
+ 'regex' => '#^/api/tenant#',
+ 'base' => '',
+ 'sub' => include 'Tenant/urls.php'
+ ),
+ array(
+ 'app' => 'User',
+ 'regex' => '#^/api/user#',
+ 'base' => '',
+ 'sub' => include 'User/urls.php'
+ )
+ ));
+ // login
+ $response = $client->post('/api/user/login', array(
+ 'login' => 'test',
+ 'password' => 'test'
+ ));
+ Test_Assert::assertResponseStatusCode($response, 200, 'Fail to login');
+
+ // Create ticket
+ $user = new Pluf_User();
+ $user = $user->getUser('test');
+
+ $t = new Tenant_Ticket();
+ $t->subject = 'test';
+ $t->description = 'test';
+ $t->type = 'bug';
+ $t->status = 'new';
+ $t->requester = $user;
+ $t->create();
+
+ // find comments
+ $response = $client->post('/api/tenant/ticket/' . $t->id . '/comment/new', array(
+ 'title' => 'test',
+ 'description' => 'test'
+ ));
+ Test_Assert::assertResponseStatusCode($response, 200);
+ $tc = json_decode($response->content, true);
+
+ // find comments
+ $response = $client->get('/api/tenant/ticket/' . $t->id . '/comment/find');
+ Test_Assert::assertResponseNotNull($response, 'Find result is empty');
+ Test_Assert::assertResponseStatusCode($response, 200, 'Find status code is not 200');
+ Test_Assert::assertResponsePaginateList($response);
+ Test_Assert::assertResponseNonEmptyPaginateList($response);
+
+ // delete
+ $c = new Tenant_Comment($tc['id']);
+ $c->delete();
+ $t->delete();
+ }
+
+ /**
+ * Creating comment
+ *
+ * @test
+ */
+ public function testUpdateTikcetComment()
+ {
+ $client = new Test_Client(array(
+ array(
+ 'app' => 'Tenant',
+ 'regex' => '#^/api/tenant#',
+ 'base' => '',
+ 'sub' => include 'Tenant/urls.php'
+ ),
+ array(
+ 'app' => 'User',
+ 'regex' => '#^/api/user#',
+ 'base' => '',
+ 'sub' => include 'User/urls.php'
+ )
+ ));
+ // login
+ $response = $client->post('/api/user/login', array(
+ 'login' => 'test',
+ 'password' => 'test'
+ ));
+ Test_Assert::assertResponseStatusCode($response, 200, 'Fail to login');
+
+ // Create ticket
+ $user = new Pluf_User();
+ $user = $user->getUser('test');
+
+ $t = new Tenant_Ticket();
+ $t->subject = 'test';
+ $t->description = 'test';
+ $t->type = 'bug';
+ $t->status = 'new';
+ $t->requester = $user;
+ $t->create();
+
+ // find comments
+ $response = $client->post('/api/tenant/ticket/' . $t->id . '/comment/new', array(
+ 'title' => 'test',
+ 'description' => 'test'
+ ));
+ Test_Assert::assertResponseStatusCode($response, 200);
+ $tc = json_decode($response->content, true);
+
+ // update
+ $response = $client->post('/api/tenant/ticket/' . $t->id . '/comment/' . $tc['id'], array(
+ 'title' => 'test new title',
+ 'description' => 'test'
+ ));
+ Test_Assert::assertResponseStatusCode($response, 200);
+
+ // find comments
+ $response = $client->get('/api/tenant/ticket/' . $t->id . '/comment/find');
+ Test_Assert::assertResponseNotNull($response, 'Find result is empty');
+ Test_Assert::assertResponseStatusCode($response, 200, 'Find status code is not 200');
+ Test_Assert::assertResponsePaginateList($response);
+ Test_Assert::assertResponseNonEmptyPaginateList($response);
+
+ // delete
+ $c = new Tenant_Comment($tc['id']);
+ $c->delete();
+ $t->delete();
+ }
+
+ /**
+ * Creating comment
+ *
+ * @test
+ */
+ public function testDeleteTikcetComment()
+ {
+ $client = new Test_Client(array(
+ array(
+ 'app' => 'Tenant',
+ 'regex' => '#^/api/tenant#',
+ 'base' => '',
+ 'sub' => include 'Tenant/urls.php'
+ ),
+ array(
+ 'app' => 'User',
+ 'regex' => '#^/api/user#',
+ 'base' => '',
+ 'sub' => include 'User/urls.php'
+ )
+ ));
+ // login
+ $response = $client->post('/api/user/login', array(
+ 'login' => 'test',
+ 'password' => 'test'
+ ));
+ Test_Assert::assertResponseStatusCode($response, 200, 'Fail to login');
+
+ // Create ticket
+ $user = new Pluf_User();
+ $user = $user->getUser('test');
+
+ $t = new Tenant_Ticket();
+ $t->subject = 'test';
+ $t->description = 'test';
+ $t->type = 'bug';
+ $t->status = 'new';
+ $t->requester = $user;
+ $t->create();
+
+ // find comments
+ $response = $client->post('/api/tenant/ticket/' . $t->id . '/comment/new', array(
+ 'title' => 'test',
+ 'description' => 'test'
+ ));
+ Test_Assert::assertResponseStatusCode($response, 200);
+ $tc = json_decode($response->content, true);
+
+ // update
+ $response = $client->delete('/api/tenant/ticket/' . $t->id . '/comment/' . $tc['id']);
+ Test_Assert::assertResponseStatusCode($response, 200);
+
+ // find comments
+ $response = $client->get('/api/tenant/ticket/' . $t->id . '/comment/find');
+ Test_Assert::assertResponseNotNull($response, 'Find result is empty');
+ Test_Assert::assertResponseStatusCode($response, 200, 'Find status code is not 200');
+ Test_Assert::assertResponsePaginateList($response);
+ Test_Assert::assertResponseEmptyPaginateList($response);
+
+ // delete
+ $t->delete();
+ }
+}
+
diff --git a/tests/Tenant_REST/TicketTest.php b/tests/Tenant_REST/TicketTest.php
new file mode 100644
index 0000000..2ee8fc4
--- /dev/null
+++ b/tests/Tenant_REST/TicketTest.php
@@ -0,0 +1,269 @@
+.
+ */
+use PHPUnit\Framework\TestCase;
+require_once 'Pluf.php';
+
+/**
+ * @backupGlobals disabled
+ * @backupStaticAttributes disabled
+ */
+class Tenant_REST_TicketsTest extends TestCase
+{
+
+ /**
+ * @beforeClass
+ */
+ public static function installApps()
+ {
+ Pluf::start(dirname(__FILE__) . '/../conf/config-01.php');
+ $m = new Pluf_Migration(array(
+ 'Pluf',
+ 'Tenant'
+ ));
+ $m->install();
+ // Test user
+ $user = new Pluf_User();
+ $user->login = 'test';
+ $user->first_name = 'test';
+ $user->last_name = 'test';
+ $user->email = 'toto@example.com';
+ $user->setPassword('test');
+ $user->active = true;
+ $user->administrator = true;
+ if (true !== $user->create()) {
+ throw new Exception();
+ }
+
+ // Test tenant
+ $tenant = new Pluf_Tenant();
+ $tenant->domain = 'localhost';
+ $tenant->subdomain = 'test';
+ $tenant->validate = true;
+ if (true !== $tenant->create()) {
+ throw new Pluf_Exception('Faile to create new tenant');
+ }
+
+ $client = new Test_Client(array());
+ $GLOBALS['_PX_request']->tenant = $tenant;
+
+ $per = new Pluf_RowPermission();
+ $per->version = 1;
+ $per->model_id = $tenant->id;
+ $per->model_class = 'Pluf_Tenant';
+ $per->owner_id = $user->id;
+ $per->owner_class = 'Pluf_User';
+ $per->create();
+ }
+
+ /**
+ * @afterClass
+ */
+ public static function uninstallApps()
+ {
+ $m = new Pluf_Migration(array(
+ 'Pluf',
+ 'Tenant'
+ ));
+ $m->unInstall();
+ }
+
+ /**
+ * Getting tenant tickets
+ *
+ * Call tenant to get list of tickets
+ *
+ * @test
+ */
+ public function testFindTikcets()
+ {
+ $client = new Test_Client(array(
+ array(
+ 'app' => 'Tenant',
+ 'regex' => '#^/api/tenant#',
+ 'base' => '',
+ 'sub' => include 'Tenant/urls.php'
+ ),
+ array(
+ 'app' => 'User',
+ 'regex' => '#^/api/user#',
+ 'base' => '',
+ 'sub' => include 'User/urls.php'
+ )
+ ));
+ // login
+ $response = $client->post('/api/user/login', array(
+ 'login' => 'test',
+ 'password' => 'test'
+ ));
+ Test_Assert::assertResponseStatusCode($response, 200, 'Fail to login');
+
+ // find teckets
+ $response = $client->get('/api/tenant/ticket/find');
+ Test_Assert::assertResponseNotNull($response, 'Find result is empty');
+ Test_Assert::assertResponseStatusCode($response, 200, 'Find status code is not 200');
+ Test_Assert::assertResponsePaginateList($response, 'Find result is not JSON paginated list');
+ }
+
+ /**
+ * Create a ticket
+ *
+ * @test
+ */
+ public function testFindTikcetsNotEmpty()
+ {
+ $client = new Test_Client(array(
+ array(
+ 'app' => 'Tenant',
+ 'regex' => '#^/api/tenant#',
+ 'base' => '',
+ 'sub' => include 'Tenant/urls.php'
+ ),
+ array(
+ 'app' => 'User',
+ 'regex' => '#^/api/user#',
+ 'base' => '',
+ 'sub' => include 'User/urls.php'
+ )
+ ));
+ // login
+ $response = $client->post('/api/user/login', array(
+ 'login' => 'test',
+ 'password' => 'test'
+ ));
+ Test_Assert::assertResponseStatusCode($response, 200, 'Fail to login');
+
+ // create tecket
+ $response = $client->post('/api/tenant/ticket/new', array(
+ 'type' => 'bug',
+ 'subject' => 'test ticket',
+ 'description' => 'it is not possible to test',
+ ));
+ Test_Assert::assertResponseNotNull($response, 'Find result is empty');
+ Test_Assert::assertResponseStatusCode($response, 200, 'Find status code is not 200');
+ Test_Assert::assertResponseNotAnonymousModel($response, 'Ticket is not created');
+ $t = json_decode($response->content, true);
+
+ // find teckets
+ $response = $client->get('/api/tenant/ticket/find');
+ Test_Assert::assertResponseNotNull($response, 'Find result is empty');
+ Test_Assert::assertResponseStatusCode($response, 200, 'Find status code is not 200');
+ Test_Assert::assertResponsePaginateList($response, 'Find result is not JSON paginated list');
+ Test_Assert::assertResponseNonEmptyPaginateList($response, 'No ticket is created');
+
+ // delete ticket
+ $response = $client->delete('/api/tenant/ticket/' . $t['id']);
+ Test_Assert::assertResponseStatusCode($response, 200, 'Ticket is removed');
+ }
+
+ /**
+ * Create a ticket
+ *
+ * @test
+ */
+ public function testCreateTikcet()
+ {
+ $client = new Test_Client(array(
+ array(
+ 'app' => 'Tenant',
+ 'regex' => '#^/api/tenant#',
+ 'base' => '',
+ 'sub' => include 'Tenant/urls.php'
+ ),
+ array(
+ 'app' => 'User',
+ 'regex' => '#^/api/user#',
+ 'base' => '',
+ 'sub' => include 'User/urls.php'
+ )
+ ));
+ // login
+ $response = $client->post('/api/user/login', array(
+ 'login' => 'test',
+ 'password' => 'test'
+ ));
+ Test_Assert::assertResponseStatusCode($response, 200, 'Fail to login');
+
+ // create tecket
+ $response = $client->post('/api/tenant/ticket/new', array(
+ 'type' => 'bug',
+ 'subject' => 'test ticket',
+ 'description' => 'it is not possible to test',
+ ));
+ Test_Assert::assertResponseNotNull($response, 'Find result is empty');
+ Test_Assert::assertResponseStatusCode($response, 200, 'Find status code is not 200');
+ Test_Assert::assertResponseNotAnonymousModel($response, 'Ticket is not created');
+ $t = json_decode($response->content, true);
+
+ // delete ticket
+ $response = $client->delete('/api/tenant/ticket/' . $t['id']);
+ Test_Assert::assertResponseStatusCode($response, 200, 'Ticket is removed');
+ }
+
+
+
+ /**
+ * Get a ticket
+ *
+ * @test
+ */
+ public function testGetTikcet()
+ {
+ $client = new Test_Client(array(
+ array(
+ 'app' => 'Tenant',
+ 'regex' => '#^/api/tenant#',
+ 'base' => '',
+ 'sub' => include 'Tenant/urls.php'
+ ),
+ array(
+ 'app' => 'User',
+ 'regex' => '#^/api/user#',
+ 'base' => '',
+ 'sub' => include 'User/urls.php'
+ )
+ ));
+ // login
+ $response = $client->post('/api/user/login', array(
+ 'login' => 'test',
+ 'password' => 'test'
+ ));
+ Test_Assert::assertResponseStatusCode($response, 200, 'Fail to login');
+
+ // create tecket
+ $response = $client->post('/api/tenant/ticket/new', array(
+ 'type' => 'bug',
+ 'subject' => 'test ticket',
+ 'description' => 'it is not possible to test',
+ ));
+ Test_Assert::assertResponseNotNull($response, 'Find result is empty');
+ Test_Assert::assertResponseStatusCode($response, 200, 'Find status code is not 200');
+ Test_Assert::assertResponseNotAnonymousModel($response, 'Ticket is not created');
+
+ // Get tecket
+ $t = json_decode($response->content, true);
+ $response = $client->get('/api/tenant/ticket/' . $t['id']);
+ Test_Assert::assertResponseNotAnonymousModel($response, 'Ticket is not find');
+
+ // delete ticket
+ $response = $client->delete('/api/tenant/ticket/' . $t['id']);
+ Test_Assert::assertResponseStatusCode($response, 200, 'Ticket is removed');
+ }
+
+}
+
diff --git a/tests/conf/config-01.php b/tests/conf/config-01.php
new file mode 100644
index 0000000..083e97c
--- /dev/null
+++ b/tests/conf/config-01.php
@@ -0,0 +1,57 @@
+ 'pluf.ir',
+ 'general_admin_email' => array(
+ 'info@pluf.ir'
+ ),
+ 'general_from_email' => 'info@pluf.ir',
+ 'general_new_request_mail_title' => 'Pluf Request',
+
+ 'installed_apps' => array(
+ 'Pluf',
+ 'Tenant',
+ 'User'
+ ),
+ 'middleware_classes' => array(
+ 'Pluf_Middleware_Session',
+ 'Pluf_Middleware_TenantFromDomain',
+ ),
+ 'debug' => true,
+
+ 'languages' => array(
+ 'fa',
+ 'en'
+ ),
+ 'tmp_folder' => dirname(__FILE__) . '/../tmp',
+ 'template_folders' => array(
+ // Templates
+ ),
+ 'template_tags' => array(
+ // Tags
+ ),
+ 'upload_path' => dirname(__FILE__) . '/../tmp',
+ 'upload_max_size' => 52428800,
+ 'time_zone' => 'Asia/Tehran',
+ 'encoding' => 'UTF-8',
+
+ 'secret_key' => '5a8d7e0f2aad8bdab8f6eef725412850',
+ 'auth_backends' => array(
+ 'Pluf_Auth_ModelBackend'
+ ),
+ 'pluf_use_rowpermission' => true,
+
+ 'db_engine' => 'MySQL',
+ 'db_version' => '5.5.33',
+
+ 'db_login' => 'root',
+ 'db_password' => '',
+ 'db_server' => 'localhost',
+ 'db_database' => 'test',
+ 'db_table_prefix' => 'tenant_unit_test_',
+
+ 'tenant_default' => 'test',
+ 'multitenant' => true,
+ 'migrate_allow_web' => true,
+);
+
diff --git a/tests/conf/config.common.php b/tests/conf/config.common.php
new file mode 100644
index 0000000..4678ba5
--- /dev/null
+++ b/tests/conf/config.common.php
@@ -0,0 +1,55 @@
+ 'Pluf_Template_Tag_Mytag',
+);
+
+// Must be shared by all the installed_apps and the core framework.
+// That way you can have several installations of the core framework.
+$cfg['db_table_prefix'] = 'pluf_unit_tests_';
+
+// Starting version 4.1 of MySQL the utf-8 support is "correct".
+// The reason of the db_version for MySQL is only for that.
+$cfg['db_version'] = '5.0';
+$cfg['db_engine'] = 'SQLite';
+
+
diff --git a/tests/conf/config.singleEmptyTenant.php b/tests/conf/config.singleEmptyTenant.php
new file mode 100644
index 0000000..7ad787e
--- /dev/null
+++ b/tests/conf/config.singleEmptyTenant.php
@@ -0,0 +1,5 @@
+ 10,
+ 'title' => 'Tenant title',
+ 'description' => 'Default tenant in single mode',
+ 'domain' => 'mydomain.com',
+ 'subdomain' => 'www',
+ 'validate' => 1
+);
+
+return $cfg;
+
diff --git a/tests/phpunit.xml b/tests/phpunit.xml
index 34b6750..e6cc256 100644
--- a/tests/phpunit.xml
+++ b/tests/phpunit.xml
@@ -1,8 +1,18 @@
-
- ./Tenant_Api/
+
+ ./Pluf_Tenant_REST/
+ ./Tenant_REST/
+
+
+
+ ../src
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/templates/User/Mail/mail-token.html b/tests/templates/User/Mail/mail-token.html
new file mode 100644
index 0000000..d4efe49
--- /dev/null
+++ b/tests/templates/User/Mail/mail-token.html
@@ -0,0 +1,4 @@
+subject: {$subject}
+token: {$token->token}
+user: {$user->id}
+callback: {$callback}
\ No newline at end of file
diff --git a/tests/templates/User/Mail/pass-token.html b/tests/templates/User/Mail/pass-token.html
new file mode 100644
index 0000000..d4efe49
--- /dev/null
+++ b/tests/templates/User/Mail/pass-token.html
@@ -0,0 +1,4 @@
+subject: {$subject}
+token: {$token->token}
+user: {$user->id}
+callback: {$callback}
\ No newline at end of file
diff --git a/tests/tmp/.gitignore b/tests/tmp/.gitignore
new file mode 100644
index 0000000..f6a1c90
--- /dev/null
+++ b/tests/tmp/.gitignore
@@ -0,0 +1,3 @@
+/*.db
+/*.php
+/*.png