2019-07-16 15:00:53 +02:00

375 lines
12 KiB
PHP

<?php
class Product {
private $id = 0;
private $brand = '';
private $name = '';
private $invoice = '';
private $serial = '';
private $createtime = null;
private $discardtime = null;
private $info = array();
private $tags = array();
public static function create_product(
$brand,
$name,
$invoice,
$serial,
$info = array(),
$tags = array()
) {
$now = time();
begin_trans();
try {
$stmt = 'insert into
`product`(`brand`, `name`, `invoice`, `serial`, `createtime`)
values (?, ?, ?, ?, ?)';
$ins_prod = prepare($stmt);
bind($ins_prod, 'ssssi', $brand, $name, $invoice, $serial, $now);
execute($ins_prod);
$product = new Product($serial, 'serial');
foreach($info as $field => $value) {
$product->set_info($field, $value);
}
foreach($tags as $tag) {
$product->add_tag($tag);
}
commit_trans();
return $product;
} catch(Exception $e) {
revert_trans();
throw $e;
}
}
public function __construct($clue, $type = 'id') {
$search = null;
switch($type) {
case 'id':
$search = prepare('select `id` from `product`
where `id`=?');
bind($search, 'i', $clue);
break;
case 'serial':
$search = prepare('select `id` from `product`
where `serial`=?');
bind($search, 's', $clue);
break;
default:
throw new Exception('Invalid type.');
}
execute($search);
$result = result_single($search);
if($result === null) {
throw new Exception('Product does not exist.');
}
$this->id = $result['id'];
$this->update_fields();
$this->update_info();
$this->update_tags();
}
private function update_fields() {
$get = prepare('select * from `product` where `id`=?');
bind($get, 'i', $this->id);
execute($get);
$product = result_single($get);
$this->brand = $product['brand'];
$this->name = $product['name'];
$this->invoice = $product['invoice'];
$this->serial = $product['serial'];
$this->createtime = $product['createtime'];
$this->discardtime = $product['discardtime'];
return true;
}
private function update_info() {
$get = prepare('select * from `product_info`
where `product`=? order by `field`');
bind($get, 'i', $this->id);
execute($get);
foreach(result_list($get) as $row) {
$field = $row['field'];
$data = $row['data'];
$this->info[$field] = $data;
}
return true;
}
private function update_tags() {
$get = prepare('select * from `product_tag`
where `product`=? order by `tag`');
bind($get, 'i', $this->id);
execute($get);
$newtags = array();
foreach(result_list($get) as $row) {
$newtags[] = $row['tag'];
}
$this->tags = $newtags;
return true;
}
public function matches($terms) {
foreach($terms as $field => $values) {
$matchvalues = array();
if(property_exists($this, $field)) {
$matchvalues[] = $this->$field;
} else if(array_key_exists($field, $this->get_info())) {
$matchvalues[] = $this->get_info()[$field];
} else {
switch($field) {
case 'tag':
$matchvalues = $this->get_tags();
case 'status':
$matchvalues[] = $this->get_status();
case 'fritext':
$matchvalues[] = $this->brand;
$matchvalues[] = $this->name;
$matchvalues[] = $this->serial;
$matchvalues[] = $this->invoice;
$matchvalues = array_merge($matchvalues,
$this->get_tags(),
array_values(
$this->get_info()));
}
}
if(!match($values, $matchvalues)) {
return false;
}
}
return true;
}
public function get_id() {
return $this->id;
}
public function get_createtime() {
return $this->createtime;
}
public function get_discardtime($format = true) {
if($this->discardtime && $format) {
return gmdate('Y-m-d', $this->discardtime);
}
return $this->discardtime;
}
public function discard() {
if($this->get_status() != 'available') {
return false;
}
$now = time();
$update = prepare('update `product` set `discardtime`=? where `id`=?');
bind($update, 'ii', $now, $this->id);
execute($update);
$this->discardtime = $now;
return true;
}
public function toggle_service() {
$status = $this->get_status();
$now = time();
$update = '';
if($status == 'service') {
return $this->get_active_service()->end();
} else if($status == 'available') {
Service::create_service($this);
return true;
}
$id = $this->get_id();
throw new Exception("The state ($status) of this product (id $id) "
."does not allow servicing.");
}
public function get_active_service() {
$find = prepare('select `id` from `service`'
.'where `returntime` is null and product=?');
bind($find, 'i', $this->id);
execute($find);
$result = result_single($find);
if($result === null) {
return null;
}
return new Service($result['id']);
}
public function get_brand() {
return $this->brand;
}
public function set_brand($newbrand) {
$update = prepare('update `product` set `brand`=? where `id`=?');
bind($update, 'si', $newbrand, $this->id);
execute($update);
$this->brand = $newbrand;
return true;
}
public function get_name() {
return $this->name;
}
public function set_name($newname) {
$update = prepare('update `product` set `name`=? where `id`=?');
bind($update, 'si', $newname, $this->id);
execute($update);
$this->name = $newname;
return true;
}
public function get_invoice() {
return $this->invoice;
}
public function set_invoice($newinvoice) {
$update = prepare('update `product` set `invoice`=? where `id`=?');
bind($update, 'si', $newinvoice, $this->id);
execute($update);
$this->invoice = $newinvoice;
return true;
}
public function get_serial() {
return $this->serial;
}
public function set_serial($newserial) {
$update = prepare('update `product` set `serial`=? where `id`=?');
bind($update, 'si', $newserial, $this->id);
execute($update);
$this->serial = $newserial;
return true;
}
public function get_info() {
return $this->info;
}
public function set_info($field, $value) {
if(!$value) {
return true;
}
$find = prepare('select * from `product_info`
where `product`=? and `field`=?');
bind($find, 'is', $this->id, $field);
execute($find);
if(result_single($find) === null) {
$update = prepare('insert into
`product_info`(`data`, `product`, `field`)
values (?, ?, ?)');
} else {
$update = prepare('update `product_info` set `data`=?
where `product`=? and `field`=?');
}
bind($update, 'sis', $value, $this->id, $field);
execute($update);
$this->update_info();
return true;
}
public function remove_info($field) {
$find = prepare('select * from `product_info`
where `product`=? and `field`=?');
bind($find, 'is', $this->id, $field);
execute($find);
if(result_single($find) === null) {
return true;
}
$update = prepare('delete from `product_info`
where `field`=? and `product`=?');
bind($update, 'si', $field, $this->id);
execute($update);
$this->update_info();
return true;
}
public function get_tags() {
return $this->tags;
}
public function add_tag($tag) {
if(!$tag) {
return true;
}
$find = prepare('select * from `product_tag`
where `product`=? and `tag`=?');
bind($find, 'is', $this->id, $tag);
execute($find);
if(result_single($find) === null) {
$update = prepare('insert into `product_tag`(`tag`, `product`)
values (?, ?)');
bind($update, 'si', $tag, $this->id);
execute($update);
$this->update_tags();
}
return true;
}
public function remove_tag($tag) {
$find = prepare('select * from `product_tag`
where `product`=? and `tag`=?');
bind($find, 'is', $this->id, $tag);
execute($find);
if(result_single($find) === null) {
return true;
}
$update = prepare('delete from `product_tag`
where `tag`=? and `product`=?');
bind($update, 'si', $tag, $this->id);
execute($update);
$this->update_tags();
return true;
}
public function get_status() {
if($this->get_discardtime(false)) {
return 'discarded';
}
if($this->get_active_service()) {
return 'service';
}
$loan = $this->get_active_loan();
if(!$loan) {
return 'available';
}
if($loan->is_overdue()) {
return 'overdue';
}
return 'on_loan';
}
public function get_active_loan() {
$find = prepare('select `id` from `loan`
where `returntime` is null and product=?');
bind($find, 'i', $this->id);
execute($find);
$result = result_single($find);
if($result === null) {
return null;
}
return new Loan($result['id']);
}
public function get_history() {
$out = array();
foreach(array('loan' => function($id) { return new Loan($id);},
'service' => function($id) { return new Service($id);})
as $type => $func) {
$find = prepare("select `id` from `$type`"
.'where `product`=? order by `starttime` desc');
bind($find, 'i', $this->id);
execute($find);
$items = result_list($find);
foreach($items as $item) {
$out[] = $func($item['id']);
}
}
usort($out, function($a, $b) {
return $a->get_duration()['start'] < $b->get_duration()['start'];
});
return $out;
}
}
?>