Commit 759ad22b by 杨树贤

完成合同后台页面

parent ac3c186e
Showing with 4294 additions and 187 deletions
......@@ -165,3 +165,5 @@ TAG_URL=http://192.168.1.17:32581
SKIP_SEND_EMAIL=true
IMAGE_SERVER_URL=http://image.liexindev.net
FILE_SERVER_URL=http://file.liexindev.net
......@@ -31,71 +31,51 @@ class SupplierContractApiController extends Controller
{
$data = $request->only([
'id',
'contract_no',
'contract_file',
'supplier_id',
'status',
'commission_rate',
'start_date',
'end_date',
'start_time',
'end_time',
'check_date',
]);
$validator = \Validator::make($data, [
'supplier_id' => 'required|integer',
'start_date' => 'required|integer|min:1',
'end_date' => 'required|integer|min:1',
'commission_rate' => 'required|numeric',
'check_date' => 'required|integer|min:1'
'start_time' => 'required|date',
'end_time' => 'required|date|after:start_time',
'commission_rate' => 'required|numeric|max:100|min:1',
'check_date' => 'required|integer|min:1|max:31'
], [
'supplier_id.required' => '供应商ID不能为空',
'supplier_id.integer' => '供应商ID必须为整数',
'start_date.required' => '合同开始时间不能为空',
'start_date.integer' => '合同开始时间必须为时间戳',
'start_date.min' => '合同开始时间必须为有效时间戳',
'end_date.required' => '合同结束时间不能为空',
'end_date.integer' => '合同结束时间必须为时间戳',
'end_date.min' => '合同结束时间必须为有效时间戳',
'start_time.required' => '合同开始时间不能为空',
'start_time.date' => '合同开始时间必须为日期格式',
'end_time.required' => '合同结束时间不能为空',
'end_time.date' => '合同结束时间必须为日期格式',
'end_time.after' => '合同结束时间必须大于合同开始时间',
'commission_rate.required' => '抽佣比率不能为空',
'commission_rate.numeric' => '抽佣比率必须为数字',
'commission_rate.max' => '抽佣比率不能大于100',
'commission_rate.min' => '抽佣比率不能小于1',
'check_date.required' => '对账日期不能为空',
'check_date.integer' => '对账日期必须为时间戳',
'check_date.min' => '对账日期必须为有效时间戳'
'check_date.integer' => '对账日期必须为整数',
'check_date.min' => '对账日期不能小于1',
'check_date.max' => '对账日期不能大于31',
]);
if ($validator->fails()) {
$this->response(-1, $validator->errors()->first());
}
$result = (new SupplierContractService())->saveSupplierContract($data);
if (is_string($result)) {
$this->response(-1, $result);
}
if (!$result) {
$this->response(-1, '新增失败,请练习管理员');
$this->response(-1, '合同生成失败,请联系管理员');
}
$this->response(0, '新增成功');
$this->response(0, '合同生成成功');
}
/*
CREATE TABLE `supplier_contract` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`contract_no` varchar(50) DEFAULT '' COMMENT '合同编号',
`contract_file` varchar(255) DEFAULT '' COMMENT '合同文件路径',
`supplier_id` int(11) NOT NULL DEFAULT '0' COMMENT '供应商ID',
`status` tinyint(4) DEFAULT '1' COMMENT '状态 1:已生效 -1:已失效',
`commission_rate` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '抽佣比率',
`start_date` int(10) NOT NULL DEFAULT '0' COMMENT '合同开始时间',
`end_date` int(10) NOT NULL DEFAULT '0' COMMENT '合同结束时间',
`check_date` int(10) NOT NULL DEFAULT '0' COMMENT '对账日期',
`create_time` int(10) NOT NULL DEFAULT '0' COMMENT '创建时间',
`create_uid` int(10) NOT NULL DEFAULT '0' COMMENT '创建人ID',
`create_name` varchar(50) NOT NULL DEFAULT '' COMMENT '创建人姓名',
`update_time` int(10) NOT NULL DEFAULT '0' COMMENT '更新时间',
`update_uid` int(10) NOT NULL DEFAULT '0' COMMENT '更新人ID',
`update_name` varchar(50) NOT NULL DEFAULT '' COMMENT '更新人姓名',
PRIMARY KEY (`id`),
KEY `idx_supplier_id` (`supplier_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='供应商合同表';
*/
//删除合同
public function deleteSupplierContract($request)
{
......@@ -123,6 +103,9 @@ class SupplierContractApiController extends Controller
{
$data = $request->only(['supplier_id', 'contract_id']);
$result = (new SupplierContractService())->getSupplierContractLogList($data);
foreach ($result as &$log) {
$log['add_time'] = $log['add_time'] ? date('Y-m-d H:i:s', $log['add_time']) : '';
}
$this->response(0, '获取成功', $result);
}
}
......@@ -12,12 +12,16 @@ class SupplierContractFilter
{
$map = $request->all();
$model = new SupplierContractModel();
$query = $model->where('create_uid', $request->user->userId)->orderBy('id', 'desc');
$query = $model->with('supplier')->where('create_uid', $request->user->userId)->orderBy('id', 'desc');
if (!empty($map['supplier_code'])) {
$supplierId = SupplierChannelModel::where('supplier_code', $map['supplier_code'])->value('supplier_id');
$query->where('supplier_id', $supplierId);
}
if (!empty($map['supplier_id'])) {
$query->where('supplier_id', $map['supplier_id']);
}
if (!empty($map['status'])) {
$query->where('status', $map['status']);
}
......
......@@ -53,10 +53,13 @@ class SupplierContractController extends Controller
public function SaveSupplierContract($request)
{
$id = $request->get('id');
$supplierList = SupplierService::getSupplierCodeListForXmSelect();
$supplierList = SupplierService::getSupplierIdListForXmSelect();
if (!empty($id)) {
$model = new SupplierContractModel();
$this->data['contract'] = $model->where('id', $id)->first()->toArray();
$contract = $model->with('supplier')->where('id', $id)->first()->toArray();
$contract['start_time'] = date('Y-m-d H:i:s', $contract['start_time']);
$contract['end_time'] = date('Y-m-d H:i:s', $contract['end_time']);
$this->data['contract'] = $contract;
}
$this->data['supplierList'] = $supplierList;
return $this->view('保存合同');
......@@ -65,7 +68,7 @@ class SupplierContractController extends Controller
public function SupplierContractList($request)
{
$supplierList = SupplierService::getSupplierCodeListForXmSelect();
$supplierList = SupplierService::getSupplierIdListForXmSelect();
$this->data['supplierList'] = $supplierList;
return $this->view('合同列表');
}
......
......@@ -3,10 +3,11 @@
namespace App\Http\Services;
use App\Model\LogModel;
use Barryvdh\DomPDF\PDF;
use App\Model\SupplierLogModel;
use App\Http\Services\LogService;
use App\Model\SupplierExtendModel;
use App\Model\SupplierContractModel;
use App\Http\Services\LogService;
use App\Http\Transformers\SupplierContractTransformer;
use App\Http\Controllers\Filter\SupplierContractFilter;
......@@ -17,7 +18,6 @@ class SupplierContractService
$limit = $request->get('limit', 10);
$filter = new SupplierContractFilter();
$query = $filter->listFilter($request);
$query->where('supplier_id', $request->input('supplier_id'));
$list = $query->paginate($limit)->toArray();
$transformer = new SupplierContractTransformer();
$list['data'] = $transformer->transformList($list['data']);
......@@ -29,44 +29,105 @@ class SupplierContractService
{
try {
\DB::connection('web')->beginTransaction();
$data['start_time'] = strtotime($data['start_time']);
$data['end_time'] = strtotime($data['end_time']);
// 检查是否已存在相同供应商的合同
if (empty($data['id'])) {
// 新增时检查
$existContract = SupplierContractModel::where('supplier_id', $data['supplier_id'])->first();
if ($existContract) {
return '该供应商已存在合同,不能重复添加';
}
} else {
// 修改时检查
$existContract = SupplierContractModel::where('supplier_id', $data['supplier_id'])
->where('id', '!=', $data['id'])
->first();
if ($existContract) {
return '该供应商已存在其他合同,不能重复添加';
}
}
//记录日志
if (!empty($data['id'])) {
//修改时需要比对差异
$oldData = SupplierContractModel::where('id', $data['id'])->first();
if ($oldData) {
$columnMap = [
'supplier_id' => '供应商',
'start_time' => '开始时间',
'end_time' => '结束时间',
'commission_rate' => '抽佣比率',
'check_date' => '对账日期',
];
$diffArr = [];
$oldData = $oldData->toArray();
foreach ($data as $key => $value) {
if (isset($oldData[$key]) && $oldData[$key] != $value) {
$diffArr[] = $key . '由' . $oldData[$key] . '改为' . $value;
if ($key == 'start_time' || $key == 'end_time') {
$value = date('Y-m-d H:i:s', $value);
$oldData[$key] = date('Y-m-d H:i:s', $oldData[$key]);
}
$diffArr[] = $columnMap[$key] . '由 ' . $oldData[$key] . ' 改为 ' . $value;
}
}
if (!empty($diffArr)) {
(new LogService())->addLog($data['supplier_id'], LogModel::UPDATE_OPERATE, '合同日志', '修改合同信息:' . implode(',', $diffArr));
(new LogService())->addLog($data['supplier_id'], LogModel::UPDATE_OPERATE, '合同日志', '修改合同信息 : ' . implode('; ', $diffArr));
}
}
} else {
//新增时记录一条日志
(new LogService())->addLog($data['supplier_id'], LogModel::ADD_OPERATE, '合同日志', '新增合同,合同编号:' . ($data['contract_no']), 1, request()->user->userId, request()->user->name);
(new LogService())->addLog($data['supplier_id'], LogModel::ADD_OPERATE, '合同日志', '新增合同');
}
if (empty($data['id'])) {
$data['create_time'] = time();
$data['create_uid'] = request()->user->userId;
$data['create_name'] = request()->user->name;
return SupplierContractModel::insert($data);
$result = SupplierContractModel::insertGetId($data);
$data['id'] = $result;
} else {
$data['update_time'] = time();
$data['update_uid'] = request()->user->userId;
$data['update_name'] = request()->user->name;
return SupplierContractModel::where('id', $data['id'])->update($data);
$result = SupplierContractModel::where('id', $data['id'])->update($data);
}
if ($result !== false) {
$fileData = $this->createSupplierContractPdf($data);
if ($fileData['code'] == 0) {
SupplierContractModel::where('id', $data['id'])->update([
'contract_file' => $fileData['data']['oss_file_url'],
'contract_no' => $this->generateContractNo($data['id'])
]);
}
}
\DB::connection('web')->commit();
return true;
} catch (\Exception $e) {
\DB::connection('web')->rollBack();
\Log::error(json_encode($e->getMessage()));
return false;
}
}
//生成合同pdf
public function createSupplierContractPdf($data)
{
$pdf = app('dompdf.wrapper');
$pdf->loadView('web.SaveSupplierContract', $data);
$fileName = 'contract_' . time() . '.pdf';
$content = $pdf->output();
$file = tmpfile();
fwrite($file, $content);
$path = stream_get_meta_data($file)['uri'];
$uploadFile = new \Illuminate\Http\UploadedFile($path, $fileName, 'application/pdf');
$result = (new UploadService())->uploadFile($uploadFile);
fclose($file);
return $result;
}
//更新合同状态
public function updateSupplierContractStatus($data)
{
......@@ -78,4 +139,13 @@ class SupplierContractService
{
return LogModel::where('supplier_id', $data['supplier_id'])->where('action', "合同日志")->orderBy('id', 'desc')->get();
}
//生成合同编码
public function generateContractNo($contractId)
{
$prefix = 'JSHT-';
$date = date('Ymd');
$sequence = $contractId;
return $prefix . $date . str_pad($sequence, 4, '0', STR_PAD_LEFT);
}
}
......@@ -106,10 +106,17 @@ class SupplierService
'return_phone'
]);
$shippingAddress = array_get($channel, 'shipping_address');
unset($channel['return_phone'], $channel['return_address'],
$channel['return_consignee']);
unset($channel['shipping_address'], $channel['cn_delivery_time_period'],
$channel['us_delivery_time_period'], $channel['attachment']);
unset(
$channel['return_phone'],
$channel['return_address'],
$channel['return_consignee']
);
unset(
$channel['shipping_address'],
$channel['cn_delivery_time_period'],
$channel['us_delivery_time_period'],
$channel['attachment']
);
//sku上传规则相关设置
$skuAuditRulerService = new SupplierSkuAuditRulerService();
......@@ -220,8 +227,6 @@ class SupplierService
//新增的时候也要去添加地址了
$supplierAddressService = new SupplierAddressService();
$supplierAddressService->saveShippingAddress($supplierId, $shippingAddress);
} else {
/**这里的是更新供应商的操作**/
$supplierId = $this->newSupplierId = $channel['supplier_id'];
......@@ -252,8 +257,10 @@ class SupplierService
}
}
//还有个逻辑就是,如果是临时供应商修改成正式供应商,就又要走一次复审
if ($channel['supplier_type'] == SupplierChannelModel::SUPPLIER_TYPE_OFFICIAL &&
$oldSupplier['supplier_type'] == SupplierChannelModel::SUPPLIER_TYPE_TEMPORARY) {
if (
$channel['supplier_type'] == SupplierChannelModel::SUPPLIER_TYPE_OFFICIAL &&
$oldSupplier['supplier_type'] == SupplierChannelModel::SUPPLIER_TYPE_TEMPORARY
) {
$channel['need_review'] = 1;
}
......@@ -280,11 +287,18 @@ class SupplierService
//保存标签到标签系统
$oldCustomerTags = array_get($oldSupplier, 'customer_tags');
$oldSystemTags = array_get($oldSupplier, 'system_tags');
$tagService->saveTags($supplierId, SupplierTagService::TAG_TYPE_SYSTEM, $channel['system_tags'],
$oldSystemTags);
$tagService->saveTags($supplierId, SupplierTagService::TAG_TYPE_CUSTOMER, $channel['customer_tags'],
$oldCustomerTags);
$tagService->saveTags(
$supplierId,
SupplierTagService::TAG_TYPE_SYSTEM,
$channel['system_tags'],
$oldSystemTags
);
$tagService->saveTags(
$supplierId,
SupplierTagService::TAG_TYPE_CUSTOMER,
$channel['customer_tags'],
$oldCustomerTags
);
}
//新增供应商的话,还要去初始化有效期
......@@ -317,7 +331,6 @@ class SupplierService
}
return $supplierId;
});
//保存日志
......@@ -545,7 +558,6 @@ class SupplierService
$logService = new LogService();
$content = "将渠道开发员由 [${prePurchaseUserName}] 改为 [${purchaseUserName}]";
$logService->AddIgnoreAuditCheckLog($supplierId, LogModel::UPDATE_OPERATE, '分配渠道开发员', $content);
}
});
......@@ -929,7 +941,7 @@ class SupplierService
//获取供应商编码给xm-select使用
public static function getSupplierCodeListForXmSelect()
{
$supplierList = SupplierChannelModel::where('status','!=', SupplierChannelModel::STATUS_DISABLE)
$supplierList = SupplierChannelModel::where('status', '!=', SupplierChannelModel::STATUS_DISABLE)
->select(['supplier_code', 'supplier_name', 'supplier_id'])->get()->toArray();
$data = [];
......@@ -942,4 +954,19 @@ class SupplierService
return $data;
}
//获取供应商id给xm-select使用
public static function getSupplierIdListForXmSelect()
{
$supplierList = SupplierChannelModel::where('status', '!=', SupplierChannelModel::STATUS_DISABLE)
->select(['supplier_id', 'supplier_name', 'supplier_code'])->get()->toArray();
$data = [];
foreach ($supplierList as $supplier) {
$data[] = [
'name' => "{$supplier['supplier_name']} ( {$supplier['supplier_code']} )",
'value' => $supplier['supplier_id'],
];
}
return $data;
}
}
<?php
namespace App\Http\Services;
use Illuminate\Support\Facades\Log;
class UploadService
{
public static function uploadFile($file)
{
try {
if (!$file) {
throw new \Exception('文件不能为空');
}
// 检查文件类型是否为PDF
$extension = $file->getClientOriginalExtension();
$fileName = $file->getClientOriginalName();
if (strtolower($extension) !== 'pdf') {
throw new \Exception('只允许上传PDF文件');
}
// 上传到图片服务器
$client = new \GuzzleHttp\Client();
$response = $client->request('POST', env('FILE_SERVER_URL') . '/uploadFile?sys_type=5&create_uid=' . request()->cookie('oa_user_id'), [
'multipart' => [
[
'name' => 'file',
'contents' => fopen($file->getRealPath(), 'r'),
'filename' => $fileName // 添加原始文件名,包含后缀
]
]
]);
if ($response->getStatusCode() != 200) {
throw new \Exception('上传网络错误');
}
$result = json_decode($response->getBody()->getContents(), true);
// dd($result);
if (!isset($result['code']) || $result['code'] != 0) {
Log::error("上传服务接口返回错误: " . json_encode($result));
throw new \Exception('上传服务接口返回错误: ' . json_encode($result));
}
return [
'code' => 0,
'msg' => '上传成功',
'data' => [
'oss_file_url' => $result['data']['oss_file_url']
]
];
} catch (\Exception $e) {
return [
'code' => 1,
'msg' => $e->getMessage()
];
}
}
}
......@@ -21,6 +21,7 @@ class SupplierContractTransformer
'Y-m-d H:i:s',
$contract['update_time']
) : '';
$contract['valid_date'] = date('Y-m-d H:i:s', $contract['start_time']) . ' 至 ' . date('Y-m-d H:i:s', $contract['end_time']);
}
unset($contract);
return $list;
......
......@@ -24,8 +24,11 @@ function curl($url, $params = false, $isPost = 0, $https = 0, $cookie = '', $tim
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_USERAGENT,
'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36');
curl_setopt(
$ch,
CURLOPT_USERAGENT,
'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36'
);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
......@@ -64,9 +67,13 @@ function curlJson($url, $data)
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
curl_setopt(
$ch,
CURLOPT_HTTPHEADER,
array(
'Content-Type: application/json',
'Content-Length: ' . strlen($data_string))
'Content-Length: ' . strlen($data_string)
)
);
$result = curl_exec($ch);
......@@ -80,7 +87,7 @@ function perm($userId, $perm1 = '')
$permArr = config('perm.perm');
$NotAuth = $permArr['notAuth'];
$AdminID = $permArr['adminGroup'];
if ((!in_array($perm1, $NotAuth)) && !in_array($userId, $AdminID)) {//过滤不用鉴权的方法与用户
if ((!in_array($perm1, $NotAuth)) && !in_array($userId, $AdminID)) { //过滤不用鉴权的方法与用户
$permID = $permArr['id'];
$url = $permArr['url'] . '/' . $userId . '/' . $permID . '?perms=' . $perm1;
$result = json_decode(curl($url, '', 0), true);
......@@ -156,7 +163,7 @@ function DeleteMenu($menu, $find)
}
if (!count($v['childs']) > 0 && $v['title'] != '首页') {
unset($menu[$k]);
}//为了删除没有下级的目录
} //为了删除没有下级的目录
}
}
return array_values($menu);
......@@ -197,6 +204,12 @@ function checkPerm($perm)
return in_array($perm, $perms);
}
//判断是否为管理员
function isAdmin()
{
return request()->user->userId == 1000;
}
//批量清楚前后空格
function BatchTrim($data)
{
......@@ -228,11 +241,40 @@ function checkArrayAllValueNull($array, $excludeField = [])
function generateMobile($count)
{
$arr = [
130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
144, 147,
150, 151, 152, 153, 155, 156, 157, 158, 159,
176, 177, 178,
180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
130,
131,
132,
133,
134,
135,
136,
137,
138,
139,
144,
147,
150,
151,
152,
153,
155,
156,
157,
158,
159,
176,
177,
178,
180,
181,
182,
183,
184,
185,
186,
187,
188,
189,
];
$phone = [];
for ($i = 0; $i < $count; $i++) {
......@@ -244,16 +286,50 @@ function generateMobile($count)
function makePassword($length)
{
// 密码字符集,可任意添加你需要的字符
// $str = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
// 'i', 'j', 'k', 'l','m', 'n', 'o', 'p', 'q', 'r', 's',
// 't', 'u', 'v', 'w', 'x', 'y','z', 'A', 'B', 'C', 'D',
// 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L','M', 'N', 'O',
// 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y','Z',
// '0', '1', '2', '3', '4', '5', '6', '7', '8', '9');
$str = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9');
// $str = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
// 'i', 'j', 'k', 'l','m', 'n', 'o', 'p', 'q', 'r', 's',
// 't', 'u', 'v', 'w', 'x', 'y','z', 'A', 'B', 'C', 'D',
// 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L','M', 'N', 'O',
// 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y','Z',
// '0', '1', '2', '3', '4', '5', '6', '7', '8', '9');
$str = array(
'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
'i',
'j',
'k',
'l',
'm',
'n',
'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
'y',
'z',
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9'
);
// 在 $str 中随机取 $length 个数组元素键名
$keys = array_rand($str, $length);
$password = '';
......
......@@ -16,7 +16,8 @@
"doctrine/inflector": "1.1.0",
"doctrine/instantiator": "1.0.2",
"phpdocumentor/reflection-docblock": "3.2.2",
"jenssegers/mongodb": "3.0.0"
"jenssegers/mongodb": "3.0.0",
"barryvdh/laravel-dompdf": "0.6.*"
},
"require-dev": {
"fzaninotto/faker": "~1.4",
......
......@@ -4,9 +4,67 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "bcb4747641cc489a902e43d8506a0e13",
"content-hash": "af10b466509f15394149cd23c6ff826d",
"packages": [
{
"name": "barryvdh/laravel-dompdf",
"version": "v0.6.1",
"source": {
"type": "git",
"url": "https://github.com/barryvdh/laravel-dompdf.git",
"reference": "b606788108833f7765801dca35455fb23ce9f869"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/b606788108833f7765801dca35455fb23ce9f869",
"reference": "b606788108833f7765801dca35455fb23ce9f869",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"dompdf/dompdf": "0.6.*",
"illuminate/support": "5.0.x|5.1.x|5.2.x",
"php": ">=5.4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "0.6-dev"
}
},
"autoload": {
"psr-4": {
"Barryvdh\\DomPDF\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Barry vd. Heuvel",
"email": "barryvdh@gmail.com"
}
],
"description": "A DOMPDF Wrapper for Laravel",
"keywords": [
"dompdf",
"laravel",
"pdf"
],
"support": {
"issues": "https://github.com/barryvdh/laravel-dompdf/issues",
"source": "https://github.com/barryvdh/laravel-dompdf/tree/master"
},
"time": "2015-12-21T19:51:22+00:00"
},
{
"name": "classpreloader/classpreloader",
"version": "3.2.1",
"source": {
......@@ -215,6 +273,57 @@
"time": "2014-08-25T15:09:25+00:00"
},
{
"name": "dompdf/dompdf",
"version": "v0.6.2",
"source": {
"type": "git",
"url": "https://github.com/dompdf/dompdf.git",
"reference": "cc06008f75262510ee135b8cbb14e333a309f651"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/dompdf/dompdf/zipball/cc06008f75262510ee135b8cbb14e333a309f651",
"reference": "cc06008f75262510ee135b8cbb14e333a309f651",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"phenx/php-font-lib": "0.2.*"
},
"type": "library",
"autoload": {
"classmap": [
"include/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL"
],
"authors": [
{
"name": "Fabien Ménager",
"email": "fabien.menager@gmail.com"
},
{
"name": "Brian Sweeney",
"email": "eclecticgeek@gmail.com"
}
],
"description": "DOMPDF is a CSS 2.1 compliant HTML to PDF converter",
"homepage": "https://github.com/dompdf/dompdf",
"support": {
"issues": "https://github.com/dompdf/dompdf/issues",
"source": "https://github.com/dompdf/dompdf/tree/master"
},
"time": "2015-12-07T04:07:13+00:00"
},
{
"name": "guzzlehttp/guzzle",
"version": "6.3.0",
"source": {
......@@ -1365,6 +1474,50 @@
"time": "2018-04-04T21:48:54+00:00"
},
{
"name": "phenx/php-font-lib",
"version": "0.2.2",
"source": {
"type": "git",
"url": "https://github.com/PhenX/php-font-lib.git",
"reference": "c30c7fc00a6b0d863e9bb4c5d5dd015298b2dc82"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PhenX/php-font-lib/zipball/c30c7fc00a6b0d863e9bb4c5d5dd015298b2dc82",
"reference": "c30c7fc00a6b0d863e9bb4c5d5dd015298b2dc82",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"type": "library",
"autoload": {
"classmap": [
"classes/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL"
],
"authors": [
{
"name": "Fabien Ménager",
"email": "fabien.menager@gmail.com"
}
],
"description": "A library to read, parse, export and make subsets of different types of font files.",
"homepage": "https://github.com/PhenX/php-font-lib",
"support": {
"issues": "https://github.com/PhenX/php-font-lib/issues",
"source": "https://github.com/PhenX/php-font-lib/tree/master"
},
"time": "2014-02-01T15:22:28+00:00"
},
{
"name": "php-amqplib/php-amqplib",
"version": "v2.6.3",
"source": {
......
......@@ -157,6 +157,7 @@ return [
App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class,
Maatwebsite\Excel\ExcelServiceProvider::class,
Barryvdh\DomPDF\ServiceProvider::class,
],
......
......@@ -115,7 +115,7 @@ function getLogDomain() {
function arrayColumn(arr, column) {
return arr.map(function(row) {
return arr.map(function (row) {
return row[column];
});
}
......@@ -135,9 +135,9 @@ function arrayUnique(arr) {
}
function multiArrayUnique(arr) {
return arr.filter(function(item, index) {
return arr.filter(function (item, index) {
const json = JSON.stringify(item);
return arr.findIndex(function(subItem) {
return arr.findIndex(function (subItem) {
return JSON.stringify(subItem) === json;
}) === index;
});
......@@ -150,3 +150,5 @@ function getFootstoneDomain() {
}
return defaultDomain;
}
<html>
<body>
<h1>供应商合同</h1>
<p>供应商名称:{{ $data['supplier_name'] }}</p>
<p>合同编号:{{ $data['contract_number'] }}</p>
<p>合同金额:{{ $data['contract_amount'] }}</p>
<p>合同开始时间:{{ $data['contract_start_time'] }}</p>
<p>合同结束时间:{{ $data['contract_end_time'] }}</p>
</body>
</html>
......@@ -30,30 +30,54 @@
pageSize: 30,
filterable: true,
height: "400px",
@if (!empty($contract))
initValue: [{
name: "{!! $contract['supplier']['supplier_name'] . '(' . $contract['supplier']['supplier_code'] . ')' !!}",
value: {!! $contract['supplier_id'] !!}
}],
disabled: true
@endif
});
form.on('submit(load)', function(data) {
let loadIndex = layer.load(1, {
shade: [0.1, '#fff'],
}); // 添加loading效果
let url = '/api/supplier_contract/SaveSupplierContract';
let res = ajax(url, data.field);
if (!res) {
layer.msg('网络错误,请重试', {
icon: 6
});
} else {
if (res.err_code === 0) {
layer.msg('保存成功', {
icon: 6
});
setTimeout(function() {
admin.closeThisDialog();
}, 1000);
} else {
layer.msg(res.err_msg, {
$.ajax({
url: url,
type: 'POST',
data: data.field,
success: function(res) {
res = JSON.parse(res);
if (res.err_code == 0) {
layer.msg(res.err_msg, {
icon: 6
});
setTimeout(function() {
admin.closeThisDialog();
}, 1000);
} else {
layer.msg(res.err_msg, {
icon: 5
});
}
},
error: function() {
layer.close(loadIndex);
layer.msg('网络错误,请重试', {
icon: 5
});
}
}
});
return false;
});
//cancel
form.on('submit(cancel)', function(data) {
admin.closeThisDialog();
return false;
});
});
</script>
......@@ -8,62 +8,14 @@
let admin = layui.admin;
let xmSelect = layui.xmSelect;
let laydate = layui.laydate;
let layer = layui.layer;
let initCondition = {
source_type: 'all'
};
let whereCondition = initCondition;
let type = 'all';
$(document).on("click", ".layui-table-body table.layui-table tbody tr", function() {
let index = $(this).attr('data-index');
let tableBox = $(this).parents('.layui-table-box');
let tableDiv = null;
if (tableBox.find(".layui-table-fixed.layui-table-fixed-l").length > 0) {
tableDiv = tableBox.find(".layui-table-fixed.layui-table-fixed-l");
} else {
tableDiv = tableBox.find(".layui-table-body.layui-table-main");
}
let checkCell = tableDiv.find("tr[data-index=" + index + "]").find(
"td div.laytable-cell-checkbox div.layui-form-checkbox I");
if (checkCell.length > 0) {
checkCell.click();
}
});
$(document).on("click", "td div.laytable-cell-checkbox div.layui-form-checkbox", function(e) {
e.stopPropagation();
});
//监听复选框事件,被选中的行高亮显示
table.on('checkbox(contractList)', function(obj) {
//拉黑就不用变色了
if (obj.checked === true && obj.type === 'all') {
//点击全选,拉黑的不用选上
$('.layui-table-body table.layui-table tbody tr:not(.block-class)').addClass(
'layui-table-click');
$('.layui-table-body table.layui-table tbody').find('.block-class').find(
'.layui-form-checkbox').remove();
$('.layui-table-body table.layui-table tbody tr .block-class').addClass(
'layui-table-click');
} else if (obj.checked === false && obj.type === 'all') {
//点击全不选
$('.layui-table-body table.layui-table tbody tr').removeClass('layui-table-click');
} else if (obj.checked === true && obj.type === 'one') {
//点击单行
if (obj.checked === true) {
obj.tr.addClass('layui-table-click');
} else {
obj.tr.removeClass('layui-table-click');
}
} else if (obj.checked === false && obj.type === 'one') {
//点击全选之后点击单行
if (obj.tr.hasClass('layui-table-click')) {
obj.tr.removeClass('layui-table-click');
}
}
});
let cols = [{
type: 'checkbox'
......@@ -97,19 +49,25 @@
field: 'supplier_code',
title: '供应商编码',
align: 'center',
width: 120
width: 120,
templet: function(d) {
return d.supplier ? d.supplier.supplier_code : '';
}
},
{
field: 'supplier_name',
title: '供应商名称',
align: 'center',
width: 200
width: 200,
templet: function(d) {
return d.supplier ? d.supplier.supplier_name : '';
}
},
{
field: 'status',
title: '状态',
align: 'center',
width: 100,
width: 80,
templet: function(d) {
let status = d.status;
let statusName = status == 1 ? '有效' : '失效';
......@@ -121,44 +79,45 @@
field: 'commission_rate',
title: '抽佣比例(%)',
align: 'center',
width: 120
width: 100
},
{
field: 'valid_date',
title: '合同有效期',
align: 'center',
width: 160
width: 280
},
{
field: 'check_date',
title: '对账日期',
align: 'center',
width: 120
width: 100
},
{
field: 'updated_at',
field: 'update_time',
title: '更新时间',
align: 'center',
width: 160
width: 150
},
{
field: 'creator',
field: 'create_name',
title: '创建人',
align: 'center',
width: 100
},
{
field: 'created_at',
field: 'create_time',
title: '创建时间',
align: 'center',
width: 160
width: 150
},
{
field: 'operate',
title: '操作',
align: 'center',
width: 150,
toolbar: '#operateBar'
toolbar: '#operateBar',
fixed: 'right'
}
];
let currentPage = 0;
......@@ -168,8 +127,6 @@
'supplier_id');
}
$('#three_days_button').remove();
table.render({
elem: '#contractList',
url: url,
......@@ -328,18 +285,19 @@
type: 1,
area: ['80%', '90%'],
title: '查看合同日志',
content: '<table class="layui-table" id="logList" lay-filter="logList"></table>',
content: '<div style="padding: 10px"><table class="layui-table" id="logList" lay-filter="logList"></table></div>',
success: function() {
table.render({
elem: '#logList',
url: '/api/supplier_contract/GetSupplierContractLogList',
url: '/api/supplier_contract/GetSupplierContractLogList?supplier_id=' +
data.supplier_id + '&contract_id=' + data.id,
where: {
supplier_id: data.supplier_id,
contract_id: data.id
},
cols: [
[{
field: 'create_time',
field: 'add_time',
title: '操作时间',
align: 'center',
width: 180
......
......@@ -18,8 +18,8 @@
<div class="layui-form-item">
<label class="layui-form-label"><span class="require">*</span>合同编号</label>
<div class="layui-input-block block-42">
<input type="text" name="contract_no" id="contract_no" placeholder="请输入合同编号"
class="layui-input layui-disabled" value="{{ $contract['contract_no'] or '系统自动生成' }}" readonly>
<input type="text" id="contract_no" placeholder="请输入合同编号" class="layui-input layui-disabled"
value="{{ $contract['contract_no'] or '系统自动生成' }}" readonly>
</div>
</div>
......@@ -34,12 +34,12 @@
<label class="layui-form-label"><span class="require">*</span>合同有效期</label>
<div class="layui-input-inline" style="width: 150px;">
<input type="text" name="start_time" id="start_time" lay-verify="required" placeholder="开始日期"
class="layui-input" autocomplete="off">
class="layui-input" autocomplete="off" value="{{ $contract['start_time'] or '' }}">
</div>
<div class="layui-form-mid">-</div>
<div class="layui-input-inline" style="width: 150px;">
<input type="text" name="end_time" id="end_time" lay-verify="required" placeholder="结束日期"
class="layui-input" autocomplete="off">
class="layui-input" autocomplete="off" value="{{ $contract['end_time'] or '' }}">
</div>
</div>
......@@ -63,7 +63,8 @@
<div class="layui-form-item">
<div align="center" style="margin-top: 20px">
<button type="button" class="layui-btn layui-btn-normal" lay-submit lay-filter="load">生成合同</button>
<button type="button" class="layui-btn layui-btn-primary" onclick="closeDialog()">取消</button>
<button type="button" class="layui-btn layui-btn-primary" lay-submit
lay-filter="cancel">取消</button>
</div>
</div>
</form>
......
......@@ -42,14 +42,15 @@
</div>
<div class="layui-inline">
<button class="layui-btn layui-btn-sm" lay-submit lay-filter="search">搜索</button>
<button type="reset" class="layui-btn layui-btn-sm layui-btn-primary">重置</button>
<button type="reset" class="layui-btn layui-btn-sm layui-btn-primary"
onclick="location.reload()">重置</button>
</div>
</div>
</form>
</div>
<div class="layui-btn-group demoTable" style="margin-top: 15px">
<button type="button" class="layui-btn layui-btn-sm" id="create_contract">生成寄售合同</button>
@if (checkPerm('EditContract'))
@if (checkPerm('EditContract') || isAdmin())
<button type="button" class="layui-btn layui-btn-sm" id="edit_contract">编辑</button>
@endif
</div>
......
/vendor
composer.phar
composer.lock
.DS_Store
/.idea
\ No newline at end of file
{
"name": "barryvdh/laravel-dompdf",
"description": "A DOMPDF Wrapper for Laravel",
"license": "MIT",
"keywords": ["laravel", "dompdf", "pdf"],
"authors": [
{
"name": "Barry vd. Heuvel",
"email": "barryvdh@gmail.com"
}
],
"require": {
"php": ">=5.4.0",
"illuminate/support": "5.0.x|5.1.x|5.2.x",
"dompdf/dompdf": "0.6.*"
},
"autoload": {
"psr-4": {
"Barryvdh\\DomPDF\\": "src"
}
},
"extra": {
"branch-alias": {
"dev-master": "0.6-dev"
}
}
}
## DOMPDF Wrapper for Laravel 5
### For Laravel 4.x, check the [0.4 branch](https://github.com/barryvdh/laravel-dompdf/tree/0.4)!
Require this package in your composer.json and update composer. This will download the package and the dompdf + fontlib libraries also.
"barryvdh/laravel-dompdf": "0.6.*"
## Installation
### Laravel 5.x:
After updating composer, add the ServiceProvider to the providers array in config/app.php
Barryvdh\DomPDF\ServiceProvider::class,
You can optionally use the facade for shorter code. Add this to your facades:
'PDF' => Barryvdh\DomPDF\Facade::class,
### Lumen:
After updating composer add the following lines to register provider in `bootstrap/app.php`
```
$app->register(\Barryvdh\DomPDF\ServiceProvider::class);
```
To change the configuration, copy the config file to your config folder and enable it in `bootstrap/app.php`:
```
$app->configure('dompdf');
```
## Using
You can create a new DOMPDF instance and load a HTML string, file or view name. You can save it to a file, or stream (show in browser) or download.
$pdf = App::make('dompdf.wrapper');
$pdf->loadHTML('<h1>Test</h1>');
return $pdf->stream();
Or use the facade:
$pdf = PDF::loadView('pdf.invoice', $data);
return $pdf->download('invoice.pdf');
You can chain the methods:
return PDF::loadFile(public_path().'/myfile.html')->save('/path-to/my_stored_file.pdf')->stream('download.pdf');
You can change the orientation and paper size, and hide or show errors (by default, errors are shown when debug is on)
PDF::loadHTML($html)->setPaper('a4')->setOrientation('landscape')->setWarnings(false)->save('myfile.pdf')
If you need the output as a string, you can get the rendered PDF with the output() function, so you can save/output it yourself.
Use `php artisan vendor:publish` to create a config file located at `config/dompdf.php` which will allow you to define local configurations to change some settings (default paper etc).
You can also use your ConfigProvider to set certain keys.
### Tip: UTF-8 support
In your templates, set the UTF-8 Metatag:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
### Tip: Page breaks
You can use the CSS `page-break-before`/`page-break-after` properties to create a new page.
<style>
.page-break {
page-break-after: always;
}
</style>
<h1>Page 1</h1>
<div class="page-break"></div>
<h1>Page 2</h1>
### License
This DOMPDF Wrapper for Laravel is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT)
<?php
namespace Barryvdh\DomPDF;
use Illuminate\Support\Facades\Facade as IlluminateFacade;
class Facade extends IlluminateFacade {
/**
* Get the registered name of the component.
*
* @return string
*/
protected static function getFacadeAccessor() { return 'dompdf.wrapper'; }
/**
* Resolve a new instance
*/
public static function __callStatic($method, $args)
{
$instance = static::$app->make(static::getFacadeAccessor());
switch (count($args))
{
case 0:
return $instance->$method();
case 1:
return $instance->$method($args[0]);
case 2:
return $instance->$method($args[0], $args[1]);
case 3:
return $instance->$method($args[0], $args[1], $args[2]);
case 4:
return $instance->$method($args[0], $args[1], $args[2], $args[3]);
default:
return call_user_func_array(array($instance, $method), $args);
}
}
}
<?php
namespace Barryvdh\DomPDF;
use DOMPDF;
use Exception;
use Illuminate\Filesystem\Filesystem;
use Illuminate\View\Factory as ViewFactory;
use Illuminate\Contracts\Config\Repository as ConfigRepository;
use Illuminate\Http\Response;
/**
* A Laravel wrapper for DOMPDF
*
* @package laravel-dompdf
* @author Barry vd. Heuvel
*/
class PDF{
/** @var \DOMPDF */
protected $dompdf;
/** @var \Illuminate\Contracts\Config\Repository */
protected $config;
/** @var \Illuminate\Filesystem\Filesystem */
protected $files;
/** @var \Illuminate\Contracts\View\Factory */
protected $view;
protected $rendered = false;
protected $orientation;
protected $paper;
protected $showWarnings;
protected $public_path;
/**
* @param \DOMPDF $dompdf
* @param \Illuminate\Contracts\Config\Repository $config
* @param \Illuminate\Filesystem\Filesystem $files
* @param \Illuminate\View\Factory $view
*/
public function __construct(DOMPDF $dompdf, ConfigRepository $config, Filesystem $files, ViewFactory $view){
$this->dompdf = $dompdf;
$this->config = $config;
$this->files = $files;
$this->view = $view;
$this->showWarnings = $this->config->get('dompdf.show_warnings', false);
//To prevent old configs from not working..
if($this->config->has('dompdf.paper')){
$this->paper = $this->config->get('dompdf.paper');
}else{
$this->paper = DOMPDF_DEFAULT_PAPER_SIZE;
}
$this->orientation = $this->config->get('dompdf.orientation') ?: 'portrait';
}
/**
* Get the DomPDF instance
*
* @return \DOMPDF
*/
public function getDomPDF(){
return $this->dompdf;
}
/**
* Set the paper size (default A4)
*
* @param string $paper
* @param string $orientation
* @return $this
*/
public function setPaper($paper, $orientation=null){
$this->paper = $paper;
if($orientation){
$this->orientation = $orientation;
}
return $this;
}
/**
* Set the orientation (default portrait)
*
* @param string $orientation
* @return static
*/
public function setOrientation($orientation){
$this->orientation = $orientation;
return $this;
}
/**
* Show or hide warnings
*
* @param bool $warnings
* @return $this
*/
public function setWarnings($warnings){
$this->showWarnings = $warnings;
return $this;
}
/**
* Load a HTML string
*
* @param string $string
* @param string $encoding Not used yet
* @return static
*/
public function loadHTML($string, $encoding = null){
$string = $this->convertEntities($string);
$this->dompdf->load_html($string, $encoding);
$this->rendered = false;
return $this;
}
/**
* Load a HTML file
*
* @param string $file
* @return static
*/
public function loadFile($file){
$this->dompdf->load_html_file($file);
$this->rendered = false;
return $this;
}
/**
* Load a View and convert to HTML
*
* @param string $view
* @param array $data
* @param array $mergeData
* @param string $encoding Not used yet
* @return static
*/
public function loadView($view, $data = array(), $mergeData = array(), $encoding = null){
$html = $this->view->make($view, $data, $mergeData)->render();
return $this->loadHTML($html, $encoding);
}
/**
* Output the PDF as a string.
*
* @return string The rendered PDF as string
*/
public function output(){
if(!$this->rendered){
$this->render();
}
return $this->dompdf->output();
}
/**
* Save the PDF to a file
*
* @param $filename
* @return static
*/
public function save($filename){
$this->files->put($filename, $this->output());
return $this;
}
/**
* Make the PDF downloadable by the user
*
* @param string $filename
* @return \Illuminate\Http\Response
*/
public function download($filename = 'document.pdf' ){
$output = $this->output();
return new Response($output, 200, array(
'Content-Type' => 'application/pdf',
'Content-Disposition' => 'attachment; filename="'.$filename.'"'
));
}
/**
* Return a response with the PDF to show in the browser
*
* @param string $filename
* @return \Illuminate\Http\Response
*/
public function stream($filename = 'document.pdf' ){
$output = $this->output();
return new Response($output, 200, array(
'Content-Type' => 'application/pdf',
'Content-Disposition' => 'inline; filename="'.$filename.'"',
));
}
/**
* Render the PDF
*/
protected function render(){
if(!$this->dompdf){
throw new Exception('DOMPDF not created yet');
}
$this->dompdf->set_paper($this->paper, $this->orientation);
$this->dompdf->render();
if ( $this->showWarnings ) {
global $_dompdf_warnings;
if(count($_dompdf_warnings)){
$warnings = '';
foreach ($_dompdf_warnings as $msg){
$warnings .= $msg . "\n";
}
// $warnings .= $this->dompdf->get_canvas()->get_cpdf()->messages;
if(!empty($warnings)){
throw new Exception($warnings);
}
}
}
$this->rendered = true;
}
protected function convertEntities($subject){
$entities = array(
'€' => '&#0128;',
);
foreach($entities as $search => $replace){
$subject = str_replace($search, $replace, $subject);
}
return $subject;
}
}
<?php
namespace Barryvdh\DomPDF;
use Exception;
use Illuminate\Support\ServiceProvider as IlluminateServiceProvider;
class ServiceProvider extends IlluminateServiceProvider
{
/**
* Indicates if loading of the provider is deferred.
*
* @var bool
*/
protected $defer = false;
/**
* Register the service provider.
*
* @throws \Exception
* @return void
*/
public function register()
{
$configPath = __DIR__.'/../config/dompdf.php';
$this->mergeConfigFrom($configPath, 'dompdf');
$this->app->bind('dompdf', function ($app) {
$dompdf = new \DOMPDF();
$dompdf->set_base_path(realpath(base_path('public')));
return $dompdf;
});
$this->app->alias('dompdf', 'DOMPDF');
$this->app->bind('dompdf.wrapper', function ($app) {
return new PDF($app['dompdf'], $app['config'], $app['files'], $app['view']);
});
}
/**
* Check if package is running under Lumen app
*
* @return bool
*/
protected function isLumen()
{
return str_contains($this->app->version(), 'Lumen') === true;
}
public function boot()
{
if (! $this->isLumen()) {
$configPath = __DIR__.'/../config/dompdf.php';
$this->publishes([$configPath => config_path('dompdf.php')], 'config');
}
$defines = $this->app['config']->get('dompdf.defines') ?: array();
foreach ($defines as $key => $value) {
$this->define($key, $value);
}
//Still load these values, in case config is not used.
$this->define("DOMPDF_ENABLE_REMOTE", true);
$this->define("DOMPDF_ENABLE_AUTOLOAD", false);
$this->define("DOMPDF_CHROOT", realpath(base_path()));
$this->define("DOMPDF_LOG_OUTPUT_FILE", storage_path('logs/dompdf.html'));
$config_file = $this->app['config']->get(
'dompdf.config_file'
) ?: base_path('vendor/dompdf/dompdf/dompdf_config.inc.php');
if (file_exists($config_file)) {
require_once $config_file;
} else {
throw new Exception(
"$config_file cannot be loaded, please configure correct config file (dompdf.config_file)"
);
}
}
/**
* Get the services provided by the provider.
*
* @return array
*/
public function provides()
{
return array('dompdf', 'dompdf.wrapper');
}
/**
* Define a value, if not already defined
*
* @param string $name
* @param string $value
*/
protected function define($name, $value)
{
if (! defined($name)) {
define($name, $value);
}
}
}
This diff could not be displayed because it is too large.
......@@ -47,6 +47,7 @@ return array(
'Dotenv\\' => array($vendorDir . '/vlucas/phpdotenv/src'),
'Cron\\' => array($vendorDir . '/mtdowling/cron-expression/src/Cron'),
'ClassPreloader\\' => array($vendorDir . '/classpreloader/classpreloader/src'),
'Barryvdh\\DomPDF\\' => array($vendorDir . '/barryvdh/laravel-dompdf/src'),
'App\\' => array($baseDir . '/app'),
'' => array($vendorDir . '/nesbot/carbon/src'),
);
This diff could not be displayed because it is too large.
{
"packages": [
{
"name": "barryvdh/laravel-dompdf",
"version": "v0.6.1",
"version_normalized": "0.6.1.0",
"source": {
"type": "git",
"url": "https://github.com/barryvdh/laravel-dompdf.git",
"reference": "b606788108833f7765801dca35455fb23ce9f869"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/b606788108833f7765801dca35455fb23ce9f869",
"reference": "b606788108833f7765801dca35455fb23ce9f869",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"dompdf/dompdf": "0.6.*",
"illuminate/support": "5.0.x|5.1.x|5.2.x",
"php": ">=5.4.0"
},
"time": "2015-12-21T19:51:22+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "0.6-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Barryvdh\\DomPDF\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Barry vd. Heuvel",
"email": "barryvdh@gmail.com"
}
],
"description": "A DOMPDF Wrapper for Laravel",
"keywords": [
"dompdf",
"laravel",
"pdf"
],
"support": {
"issues": "https://github.com/barryvdh/laravel-dompdf/issues",
"source": "https://github.com/barryvdh/laravel-dompdf/tree/master"
},
"install-path": "../barryvdh/laravel-dompdf"
},
{
"name": "classpreloader/classpreloader",
"version": "3.2.1",
"version_normalized": "3.2.1.0",
......@@ -221,6 +282,60 @@
"install-path": "../doctrine/instantiator"
},
{
"name": "dompdf/dompdf",
"version": "v0.6.2",
"version_normalized": "0.6.2.0",
"source": {
"type": "git",
"url": "https://github.com/dompdf/dompdf.git",
"reference": "cc06008f75262510ee135b8cbb14e333a309f651"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/dompdf/dompdf/zipball/cc06008f75262510ee135b8cbb14e333a309f651",
"reference": "cc06008f75262510ee135b8cbb14e333a309f651",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"phenx/php-font-lib": "0.2.*"
},
"time": "2015-12-07T04:07:13+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"classmap": [
"include/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL"
],
"authors": [
{
"name": "Fabien Ménager",
"email": "fabien.menager@gmail.com"
},
{
"name": "Brian Sweeney",
"email": "eclecticgeek@gmail.com"
}
],
"description": "DOMPDF is a CSS 2.1 compliant HTML to PDF converter",
"homepage": "https://github.com/dompdf/dompdf",
"support": {
"issues": "https://github.com/dompdf/dompdf/issues",
"source": "https://github.com/dompdf/dompdf/tree/master"
},
"install-path": "../dompdf/dompdf"
},
{
"name": "fzaninotto/faker",
"version": "v1.9.1",
"version_normalized": "1.9.1.0",
......@@ -1610,6 +1725,53 @@
"install-path": "../paragonie/random_compat"
},
{
"name": "phenx/php-font-lib",
"version": "0.2.2",
"version_normalized": "0.2.2.0",
"source": {
"type": "git",
"url": "https://github.com/PhenX/php-font-lib.git",
"reference": "c30c7fc00a6b0d863e9bb4c5d5dd015298b2dc82"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PhenX/php-font-lib/zipball/c30c7fc00a6b0d863e9bb4c5d5dd015298b2dc82",
"reference": "c30c7fc00a6b0d863e9bb4c5d5dd015298b2dc82",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"time": "2014-02-01T15:22:28+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"classmap": [
"classes/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL"
],
"authors": [
{
"name": "Fabien Ménager",
"email": "fabien.menager@gmail.com"
}
],
"description": "A library to read, parse, export and make subsets of different types of font files.",
"homepage": "https://github.com/PhenX/php-font-lib",
"support": {
"issues": "https://github.com/PhenX/php-font-lib/issues",
"source": "https://github.com/PhenX/php-font-lib/tree/master"
},
"install-path": "../phenx/php-font-lib"
},
{
"name": "php-amqplib/php-amqplib",
"version": "v2.6.3",
"version_normalized": "2.6.3.0",
......
......@@ -5,11 +5,20 @@
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'reference' => '263640a855b4a9af67344a2d8fd747fbb8b0a09e',
'reference' => 'ac3c186e8c6551b2459919cfcbb59eb7d15d4e07',
'name' => 'laravel/laravel',
'dev' => true,
),
'versions' => array(
'barryvdh/laravel-dompdf' => array(
'pretty_version' => 'v0.6.1',
'version' => '0.6.1.0',
'type' => 'library',
'install_path' => __DIR__ . '/../barryvdh/laravel-dompdf',
'aliases' => array(),
'reference' => 'b606788108833f7765801dca35455fb23ce9f869',
'dev_requirement' => false,
),
'classpreloader/classpreloader' => array(
'pretty_version' => '3.2.1',
'version' => '3.2.1.0',
......@@ -58,6 +67,15 @@
'reference' => '26404e0c90565b614ee76b988b9bc8790d77f590',
'dev_requirement' => false,
),
'dompdf/dompdf' => array(
'pretty_version' => 'v0.6.2',
'version' => '0.6.2.0',
'type' => 'library',
'install_path' => __DIR__ . '/../dompdf/dompdf',
'aliases' => array(),
'reference' => 'cc06008f75262510ee135b8cbb14e333a309f651',
'dev_requirement' => false,
),
'fzaninotto/faker' => array(
'pretty_version' => 'v1.9.1',
'version' => '1.9.1.0',
......@@ -337,7 +355,7 @@
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'reference' => '263640a855b4a9af67344a2d8fd747fbb8b0a09e',
'reference' => 'ac3c186e8c6551b2459919cfcbb59eb7d15d4e07',
'dev_requirement' => false,
),
'league/flysystem' => array(
......@@ -421,6 +439,15 @@
'reference' => '9b3899e3c3ddde89016f576edb8c489708ad64cd',
'dev_requirement' => false,
),
'phenx/php-font-lib' => array(
'pretty_version' => '0.2.2',
'version' => '0.2.2.0',
'type' => 'library',
'install_path' => __DIR__ . '/../phenx/php-font-lib',
'aliases' => array(),
'reference' => 'c30c7fc00a6b0d863e9bb4c5d5dd015298b2dc82',
'dev_requirement' => false,
),
'php-amqplib/php-amqplib' => array(
'pretty_version' => 'v2.6.3',
'version' => '2.6.3.0',
......
*.json text
*.xml text
*.php text
*.LGPL text
*.md text
*.skel text
*.css text
*.inc text
*.js text
*.html text
*.txt text
*.svg text
.DS_Store
composer.lock
vendor
.idea
.project
lib/fonts/*.afm.php
lib/fonts/*.ufm.php
lib/fonts/log.htm
[submodule "lib/php-font-lib"]
path = lib/php-font-lib
url = https://github.com/PhenX/php-font-lib.git
# How to contribute
- [Getting help](#getting-help)
- [Submitting bug reports](#submitting-bug-reports)
- [Contributing code](#contributing-code)
## Getting help
Community discussion, questions, and informal bug reporting is done on the
[dompdf Google group](http://groups.google.com/group/dompdf). You may also
seek help on
[StackOverflow](http://stackoverflow.com/questions/tagged/dompdf).
## Submitting bug reports
The preferred way to report bugs is to use the
[GitHub issue tracker](http://github.com/dompdf/dompdf/issues). Before
reporting a bug, read these pointers.
**Please search inside the bug tracker to see if the bug you found is not already reported.**
**Note:** The issue tracker is for *bugs* and *feature requests*, not requests for help.
Questions should be asked on the
[dompdf Google group](http://groups.google.com/group/dompdf) instead.
### Reporting bugs effectively
- dompdf is maintained by volunteers. They don't owe you anything, so be
polite. Reports with an indignant or belligerent tone tend to be moved to the
bottom of the pile.
- Include information about **the PHP version on which the problem occurred**. Even
if you tested several PHP version on different servers, and the problem occurred
in all of them, mention this fact in the bug report.
Also include the operating system it's installed on. PHP configuration can also help,
and server error logs (like Apache logs)
- Mention which release of dompdf you're using (the zip, the master branch, etc).
Preferably, try also with the current development snapshot, to ensure the
problem has not already been fixed.
- Mention very precisely what went wrong. "X is broken" is not a good bug
report. What did you expect to happen? What happened instead? Describe the
exact steps a maintainer has to take to make the problem occur. We can not
fix something that we can not observe.
- If the problem can not be reproduced in any of the demos included in the
dompdf distribution, please provide an HTML document that demonstrates
the problem. There are a few options to show us your code:
- [JS Fiddle](http://jsfiddle.net/)
- [dompdf debug helper](http://eclecticgeek.com/dompdf/debug.php) (provided by @bsweeney)
- Include the HTML/CSS inside the bug report, with
[code highlighting](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#wiki-code).
## Contributing code
- Make sure you have a [GitHub Account](https://github.com/signup/free)
- Fork [dompdf](https://github.com/dompdf/dompdf/)
([how to fork a repo](https://help.github.com/articles/fork-a-repo))
- *Make your changes on the dev branch* or the most appropriate feature branch. Please only patch
the master branch if you are attempting to address an urgent bug in the released code.
- Add a simple test file in `www/test/`, with a comprehensive name.
- Submit a pull request
([how to create a pull request](https://help.github.com/articles/fork-a-repo))
### Coding standards
- 2 spaces per indentation level, no tabs.
- spaces inside `if` like this:
```php
if ( $foo == "bar" ) {
//
}
```
- booleans in lowercase
- opening braces *always* on the same line
[![Latest Stable Version](https://poser.pugx.org/dompdf/dompdf/v/stable.png)](https://packagist.org/packages/dompdf/dompdf) [![Total Downloads](https://poser.pugx.org/dompdf/dompdf/downloads.png)](https://packagist.org/packages/dompdf/dompdf) [![Latest Unstable Version](https://poser.pugx.org/dompdf/dompdf/v/unstable.png)](https://packagist.org/packages/dompdf/dompdf) [![License](https://poser.pugx.org/dompdf/dompdf/license.png)](https://packagist.org/packages/dompdf/dompdf)
**dompdf is an HTML to PDF converter**.
At its heart, dompdf is (mostly) [CSS 2.1](http://www.w3.org/TR/CSS2/) compliant
HTML layout and rendering engine written in PHP. It is a style-driven renderer:
it will download and read external stylesheets, inline style tags, and the style
attributes of individual HTML elements. It also supports most presentational
HTML attributes.
----
**Check out the [Demo](http://pxd.me/dompdf/www/examples.php) and ask any
question on [StackOverflow](http://stackoverflow.com/questions/tagged/dompdf) or
on the [Google Groups](http://groups.google.com/group/dompdf)**
----
[![Follow us on Twitter](http://twitter-badges.s3.amazonaws.com/twitter-a.png)](http://www.twitter.com/dompdf)
[![Follow us on Google+](https://ssl.gstatic.com/images/icons/gplus-32.png)](https://plus.google.com/108710008521858993320?prsrc=3)
Features
========
* handles most CSS 2.1 and a few CSS3 properties, including @import, @media &
@page rules
* supports most presentational HTML 4.0 attributes
* supports external stylesheets, either local or through http/ftp (via
fopen-wrappers)
* supports complex tables, including row & column spans, separate & collapsed
border models, individual cell styling
* image support (gif, png (8, 24 and 32 bit with alpha channel), bmp & jpeg)
* no dependencies on external PDF libraries, thanks to the R&OS PDF class
* inline PHP support
Requirements
============
* PHP 5.0+ (5.3+ recommended)
* DOM extension
* GD extension
Recommendations
============
* MBString extension: provides internationalization support. This extension is
*not* enabled by default. dompdf has limited internationalization support
when this extension is not enabled.
* opcache (OPcache, XCache, APC, etc.): improves performance
About Fonts & Character Encoding
============
PDF documents internally support the following fonts: Helvetica, Times-Roman,
Courier, Zapf-Dingbats, & Symbol. These fonts only support Windows ANSI
encoding. In order for a PDF to display characters that are not available in
Windows ANSI you must supply an external font. dompdf will embed any referenced
font in the PDF so long as it has been pre-loaded or is accessible to dompdf and
reference in CSS @font-face rules. See the
[font overview](https://github.com/dompdf/dompdf/wiki/About-Fonts-and-Character-Encoding)
for more information on how to use fonts.
The [DejaVu TrueType fonts](http://dejavu-fonts.org) have been pre-installed to
give dompdf decent Unicode character coverage by default. To use the DejaVu
fonts reference the font in your stylesheet, e.g. `body { font-family: DejaVu
Sans; }` (for DejaVu Sans).
Easy Installation
============
Install with git
---
From the command line switch to the directory where dompdf will reside and run
the following commands:
```sh
git clone https://github.com/dompdf/dompdf.git .
git submodule init
git submodule update
```
Install with composer
---
To install with Composer, simply add the requirement to your `composer.json`
file:
```json
{
"require" : {
"dompdf/dompdf" : "0.6.*"
}
}
```
And run Composer to update your dependencies:
```bash
$ curl -sS http://getcomposer.org/installer | php
$ php composer.phar update
```
Before you can use the Composer installation of DOMPDF in your application you
must disable dompdf's default auto-loader, include the Composer autoloader, and
load the dompdf configuration file:
```php
// somewhere early in your project's loading, require the Composer autoloader
// see: http://getcomposer.org/doc/00-intro.md
require 'vendor/autoload.php';
// disable DOMPDF's internal autoloader if you are using Composer
define('DOMPDF_ENABLE_AUTOLOAD', false);
// include DOMPDF's default configuration
require_once '/path/to/vendor/dompdf/dompdf/dompdf_config.inc.php';
```
Download and install
---
Download an archive of dompdf and extract it into the directory where dompdf
will reside
* You can download stable copies of dompdf from
https://github.com/dompdf/dompdf/tags
* Or download a nightly (the latest, unreleased code) from
http://eclecticgeek.com/dompdf
Limitations (Known Issues)
==========================
* not particularly tolerant to poorly-formed HTML input. To avoid any
unexpected rendering issues you should either enable the built-in HTML5
parser (via the `DOMPDF_ENABLE_HTML5PARSER` configuration constant) or run
your HTML through a HTML validator/cleaner (such as Tidy).
* large files or large tables can take a while to render
* CSS float is not supported (but is in the works, enable it through the
`DOMPDF_ENABLE_CSS_FLOAT` configuration constant).
If you find this project useful, please consider making a donation.
(Any funds donated will be used to help further development on this project.)
[![Donate button](https://www.paypal.com/en_US/i/btn/btn_donate_SM.gif)](http://goo.gl/DSvWf)
{
"name": "dompdf/dompdf",
"type": "library",
"description": "DOMPDF is a CSS 2.1 compliant HTML to PDF converter",
"homepage": "https://github.com/dompdf/dompdf",
"license": "LGPL",
"authors": [
{
"name": "Fabien Ménager",
"email": "fabien.menager@gmail.com"
},
{
"name": "Brian Sweeney",
"email": "eclecticgeek@gmail.com"
}
],
"autoload": {
"classmap": ["include/"]
},
"require": {
"phenx/php-font-lib": "0.2.*"
}
}
<?php
/**
* Command line utility to use dompdf.
* Can also be used with HTTP GET parameters
*
* @package dompdf
* @link http://dompdf.github.com/
* @author Benj Carson <benjcarson@digitaljunkies.ca>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
/**
* Display command line usage
*/
function dompdf_usage() {
$default_paper_size = DOMPDF_DEFAULT_PAPER_SIZE;
echo <<<EOD
Usage: {$_SERVER["argv"][0]} [options] html_file
html_file can be a filename, a url if fopen_wrappers are enabled, or the '-' character to read from standard input.
Options:
-h Show this message
-l List available paper sizes
-p size Paper size; something like 'letter', 'A4', 'legal', etc.
The default is '$default_paper_size'
-o orientation Either 'portrait' or 'landscape'. Default is 'portrait'
-b path Set the 'document root' of the html_file.
Relative urls (for stylesheets) are resolved using this directory.
Default is the directory of html_file.
-f file The output filename. Default is the input [html_file].pdf
-v Verbose: display html parsing warnings and file not found errors.
-d Very verbose: display oodles of debugging output: every frame
in the tree printed to stdout.
-t Comma separated list of debugging types (page-break,reflow,split)
EOD;
exit;
}
/**
* Parses command line options
*
* @return array The command line options
*/
function getoptions() {
$opts = array();
if ( $_SERVER["argc"] == 1 )
return $opts;
$i = 1;
while ($i < $_SERVER["argc"]) {
switch ($_SERVER["argv"][$i]) {
case "--help":
case "-h":
$opts["h"] = true;
$i++;
break;
case "-l":
$opts["l"] = true;
$i++;
break;
case "-p":
if ( !isset($_SERVER["argv"][$i+1]) )
die("-p switch requires a size parameter\n");
$opts["p"] = $_SERVER["argv"][$i+1];
$i += 2;
break;
case "-o":
if ( !isset($_SERVER["argv"][$i+1]) )
die("-o switch requires an orientation parameter\n");
$opts["o"] = $_SERVER["argv"][$i+1];
$i += 2;
break;
case "-b":
if ( !isset($_SERVER["argv"][$i+1]) )
die("-b switch requires a path parameter\n");
$opts["b"] = $_SERVER["argv"][$i+1];
$i += 2;
break;
case "-f":
if ( !isset($_SERVER["argv"][$i+1]) )
die("-f switch requires a filename parameter\n");
$opts["f"] = $_SERVER["argv"][$i+1];
$i += 2;
break;
case "-v":
$opts["v"] = true;
$i++;
break;
case "-d":
$opts["d"] = true;
$i++;
break;
case "-t":
if ( !isset($_SERVER['argv'][$i + 1]) )
die("-t switch requires a comma separated list of types\n");
$opts["t"] = $_SERVER['argv'][$i+1];
$i += 2;
break;
default:
$opts["filename"] = $_SERVER["argv"][$i];
$i++;
break;
}
}
return $opts;
}
require_once("dompdf_config.inc.php");
global $_dompdf_show_warnings, $_dompdf_debug, $_DOMPDF_DEBUG_TYPES;
$sapi = php_sapi_name();
$options = array();
$dompdf = new DOMPDF();
switch ( $sapi ) {
case "cli":
$opts = getoptions();
if ( isset($opts["h"]) || (!isset($opts["filename"]) && !isset($opts["l"])) ) {
dompdf_usage();
exit;
}
if ( isset($opts["l"]) ) {
echo "\nUnderstood paper sizes:\n";
foreach (array_keys(CPDF_Adapter::$PAPER_SIZES) as $size)
echo " " . mb_strtoupper($size) . "\n";
exit;
}
$file = $opts["filename"];
if ( isset($opts["p"]) )
$paper = $opts["p"];
else
$paper = DOMPDF_DEFAULT_PAPER_SIZE;
if ( isset($opts["o"]) )
$orientation = $opts["o"];
else
$orientation = "portrait";
if ( isset($opts["b"]) )
$base_path = $opts["b"];
if ( isset($opts["f"]) )
$outfile = $opts["f"];
else {
if ( $file === "-" )
$outfile = "dompdf_out.pdf";
else
$outfile = str_ireplace(array(".html", ".htm"), "", $file) . ".pdf";
}
if ( isset($opts["v"]) )
$_dompdf_show_warnings = true;
if ( isset($opts["d"]) ) {
$_dompdf_show_warnings = true;
$_dompdf_debug = true;
}
if ( isset($opts['t']) ) {
$arr = split(',',$opts['t']);
$types = array();
foreach ($arr as $type)
$types[ trim($type) ] = 1;
$_DOMPDF_DEBUG_TYPES = $types;
}
$save_file = true;
break;
default:
$dompdf->set_option('enable_php', false);
if ( isset($_GET["input_file"]) )
$file = rawurldecode($_GET["input_file"]);
else
throw new DOMPDF_Exception("An input file is required (i.e. input_file _GET variable).");
if ( isset($_GET["paper"]) )
$paper = rawurldecode($_GET["paper"]);
else
$paper = DOMPDF_DEFAULT_PAPER_SIZE;
if ( isset($_GET["orientation"]) )
$orientation = rawurldecode($_GET["orientation"]);
else
$orientation = "portrait";
if ( isset($_GET["base_path"]) ) {
$base_path = rawurldecode($_GET["base_path"]);
$file = $base_path . $file; # Set the input file
}
if ( isset($_GET["options"]) ) {
$options = $_GET["options"];
}
$file_parts = explode_url($file);
$outfile = "dompdf_out.pdf"; # Don't allow them to set the output file
$save_file = false; # Don't save the file
break;
}
if ( $file === "-" ) {
$str = "";
while ( !feof(STDIN) )
$str .= fread(STDIN, 4096);
$dompdf->load_html($str);
} else
$dompdf->load_html_file($file);
if ( isset($base_path) ) {
$dompdf->set_base_path($base_path);
}
$dompdf->set_paper($paper, $orientation);
$dompdf->render();
if ( $_dompdf_show_warnings ) {
global $_dompdf_warnings;
foreach ($_dompdf_warnings as $msg)
echo $msg . "\n";
echo $dompdf->get_canvas()->get_cpdf()->messages;
flush();
}
if ( $save_file ) {
// if ( !is_writable($outfile) )
// throw new DOMPDF_Exception("'$outfile' is not writable.");
if ( strtolower(DOMPDF_PDF_BACKEND) === "gd" )
$outfile = str_replace(".pdf", ".png", $outfile);
list($proto, $host, $path, $file) = explode_url($outfile);
if ( $proto != "" ) // i.e. not file://
$outfile = $file; // just save it locally, FIXME? could save it like wget: ./host/basepath/file
$outfile = realpath(dirname($outfile)) . DIRECTORY_SEPARATOR . basename($outfile);
if ( strpos($outfile, DOMPDF_CHROOT) !== 0 )
throw new DOMPDF_Exception("Permission denied.");
file_put_contents($outfile, $dompdf->output( array("compress" => 0) ));
exit(0);
}
if ( !headers_sent() ) {
$dompdf->stream($outfile, $options);
}
<?php
// Please refer to dompdf_config.inc.php for details on each configuration option.
//define("DOMPDF_TEMP_DIR", "/tmp");
//define("DOMPDF_FONT_DIR", DOMPDF_DIR."/lib/fonts/");
//define("DOMPDF_FONT_CACHE", DOMPDF_DIR."/lib/fonts/");
//define("DOMPDF_UNICODE_ENABLED", true);
//define("DOMPDF_PDF_BACKEND", "PDFLib");
//define("DOMPDF_DEFAULT_MEDIA_TYPE", "print");
//define("DOMPDF_DEFAULT_PAPER_SIZE", "letter");
//define("DOMPDF_DEFAULT_FONT", "serif");
//define("DOMPDF_DPI", 72);
//define("DOMPDF_ENABLE_CSS_FLOAT", true);
//define("DOMPDF_ENABLE_JAVASCRIPT", false);
//define("DEBUGPNG", true);
//define("DEBUGKEEPTEMP", true);
//define("DEBUGCSS", true);
//define("DEBUG_LAYOUT", true);
//define("DEBUG_LAYOUT_LINES", false);
//define("DEBUG_LAYOUT_BLOCKS", false);
//define("DEBUG_LAYOUT_INLINE", false);
//define("DOMPDF_FONT_HEIGHT_RATIO", 1.0);
//define("DEBUG_LAYOUT_PADDINGBOX", false);
//define("DOMPDF_LOG_OUTPUT_FILE", DOMPDF_FONT_DIR."log.htm");
//define("DOMPDF_ENABLE_HTML5PARSER", true);
//define("DOMPDF_ENABLE_FONTSUBSETTING", true);
// Authentication for the dompdf/www
//define("DOMPDF_ADMIN_USERNAME", "user");
//define("DOMPDF_ADMIN_PASSWORD", "password");
/**
* Attention!
* The following settings may increase the risk of system exploit.
* Do not change these settings without understanding the consequences.
* Additional documentation is available on the dompdf wiki at:
* https://github.com/dompdf/dompdf/wiki
*/
//define("DOMPDF_CHROOT", DOMPDF_DIR);
//define("DOMPDF_ENABLE_PHP", false);
//define("DOMPDF_ENABLE_REMOTE", false);
<?php
/**
* @package dompdf
* @link http://dompdf.github.com/
* @author Benj Carson <benjcarson@digitaljunkies.ca>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
/**
* Positions absolutely positioned frames
*/
class Absolute_Positioner extends Positioner {
function __construct(Frame_Decorator $frame) { parent::__construct($frame); }
function position() {
$frame = $this->_frame;
$style = $frame->get_style();
$p = $frame->find_positionned_parent();
list($x, $y, $w, $h) = $frame->get_containing_block();
$top = $style->length_in_pt($style->top, $h);
$right = $style->length_in_pt($style->right, $w);
$bottom = $style->length_in_pt($style->bottom, $h);
$left = $style->length_in_pt($style->left, $w);
if ( $p && !($left === "auto" && $right === "auto") ) {
// Get the parent's padding box (see http://www.w3.org/TR/CSS21/visuren.html#propdef-top)
list($x, $y, $w, $h) = $p->get_padding_box();
}
list($width, $height) = array($frame->get_margin_width(), $frame->get_margin_height());
$orig_style = $this->_frame->get_original_style();
$orig_width = $orig_style->width;
$orig_height = $orig_style->height;
/****************************
Width auto:
____________| left=auto | left=fixed |
right=auto | A | B |
right=fixed | C | D |
Width fixed:
____________| left=auto | left=fixed |
right=auto | E | F |
right=fixed | G | H |
*****************************/
if ( $left === "auto" ) {
if ( $right === "auto" ) {
// A or E - Keep the frame at the same position
$x = $x + $frame->find_block_parent()->get_current_line_box()->w;
}
else {
if ( $orig_width === "auto" ) {
// C
$x += $w - $width - $right;
}
else {
// G
$x += $w - $width - $right;
}
}
}
else {
if ( $right === "auto" ) {
// B or F
$x += $left;
}
else {
if ( $orig_width === "auto" ) {
// D - TODO change width
$x += $left;
}
else {
// H - Everything is fixed: left + width win
$x += $left;
}
}
}
// The same vertically
if ( $top === "auto" ) {
if ( $bottom === "auto" ) {
// A or E - Keep the frame at the same position
$y = $frame->find_block_parent()->get_current_line_box()->y;
}
else {
if ( $orig_height === "auto" ) {
// C
$y += $h - $height - $bottom;
}
else {
// G
$y += $h - $height - $bottom;
}
}
}
else {
if ( $bottom === "auto" ) {
// B or F
$y += $top;
}
else {
if ( $orig_height === "auto" ) {
// D - TODO change height
$y += $top;
}
else {
// H - Everything is fixed: top + height win
$y += $top;
}
}
}
$frame->set_position($x, $y);
}
}
\ No newline at end of file
<?php
/**
* @package dompdf
* @link http://dompdf.github.com/
* @author Benj Carson <benjcarson@digitaljunkies.ca>
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
/**
* DOMPDF autoload function
*
* If you have an existing autoload function, add a call to this function
* from your existing __autoload() implementation.
*
* @param string $class
*/
function DOMPDF_autoload($class) {
$filename = DOMPDF_INC_DIR . "/" . mb_strtolower($class) . ".cls.php";
if ( is_file($filename) ) {
include_once $filename;
}
}
// If SPL autoload functions are available (PHP >= 5.1.2)
if ( function_exists("spl_autoload_register") ) {
$autoload = "DOMPDF_autoload";
$funcs = spl_autoload_functions();
// No functions currently in the stack.
if ( !DOMPDF_AUTOLOAD_PREPEND || $funcs === false ) {
spl_autoload_register($autoload);
}
// If PHP >= 5.3 the $prepend argument is available
else if ( PHP_VERSION_ID >= 50300 ) {
spl_autoload_register($autoload, true, true);
}
else {
// Unregister existing autoloaders...
$compat = (PHP_VERSION_ID <= 50102 && PHP_VERSION_ID >= 50100);
foreach ($funcs as $func) {
if (is_array($func)) {
// :TRICKY: There are some compatibility issues and some
// places where we need to error out
$reflector = new ReflectionMethod($func[0], $func[1]);
if (!$reflector->isStatic()) {
throw new Exception('This function is not compatible with non-static object methods due to PHP Bug #44144.');
}
// Suprisingly, spl_autoload_register supports the
// Class::staticMethod callback format, although call_user_func doesn't
if ($compat) $func = implode('::', $func);
}
spl_autoload_unregister($func);
}
// Register the new one, thus putting it at the front of the stack...
spl_autoload_register($autoload);
// Now, go back and re-register all of our old ones.
foreach ($funcs as $func) {
spl_autoload_register($func);
}
// Be polite and ensure that userland autoload gets retained
if ( function_exists("__autoload") ) {
spl_autoload_register("__autoload");
}
}
}
else if ( !function_exists("__autoload") ) {
/**
* Default __autoload() function
*
* @param string $class
*/
function __autoload($class) {
DOMPDF_autoload($class);
}
}
<?php
/**
* @package dompdf
* @link http://dompdf.github.com/
* @author Benj Carson <benjcarson@digitaljunkies.ca>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
/**
* Decorates frames for block layout
*
* @access private
* @package dompdf
*/
class Block_Frame_Decorator extends Frame_Decorator {
/**
* Current line index
*
* @var int
*/
protected $_cl;
/**
* The block's line boxes
*
* @var Line_Box[]
*/
protected $_line_boxes;
function __construct(Frame $frame, DOMPDF $dompdf) {
parent::__construct($frame, $dompdf);
$this->_line_boxes = array(new Line_Box($this));
$this->_cl = 0;
}
function reset() {
parent::reset();
$this->_line_boxes = array(new Line_Box($this));
$this->_cl = 0;
}
/**
* @return Line_Box
*/
function get_current_line_box() {
return $this->_line_boxes[$this->_cl];
}
/**
* @return integer
*/
function get_current_line_number() {
return $this->_cl;
}
/**
* @return Line_Box[]
*/
function get_line_boxes() {
return $this->_line_boxes;
}
/**
* @param integer $i
*/
function clear_line($i) {
if ( isset($this->_line_boxes[$i]) ) {
unset($this->_line_boxes[$i]);
}
}
/**
* @param Frame $frame
*/
function add_frame_to_line(Frame $frame) {
if ( !$frame->is_in_flow() ) {
return;
}
$style = $frame->get_style();
$frame->set_containing_line($this->_line_boxes[$this->_cl]);
/*
// Adds a new line after a block, only if certain conditions are met
if ((($frame instanceof Inline_Frame_Decorator && $frame->get_node()->nodeName !== "br") ||
$frame instanceof Text_Frame_Decorator && trim($frame->get_text())) &&
($frame->get_prev_sibling() && $frame->get_prev_sibling()->get_style()->display === "block" &&
$this->_line_boxes[$this->_cl]->w > 0 )) {
$this->maximize_line_height( $style->length_in_pt($style->line_height), $frame );
$this->add_line();
// Add each child of the inline frame to the line individually
foreach ($frame->get_children() as $child)
$this->add_frame_to_line( $child );
}
else*/
// Handle inline frames (which are effectively wrappers)
if ( $frame instanceof Inline_Frame_Decorator ) {
// Handle line breaks
if ( $frame->get_node()->nodeName === "br" ) {
$this->maximize_line_height( $style->length_in_pt($style->line_height), $frame );
$this->add_line(true);
}
return;
}
// Trim leading text if this is an empty line. Kinda a hack to put it here,
// but what can you do...
if ( $this->get_current_line_box()->w == 0 &&
$frame->is_text_node() &&
!$frame->is_pre() ) {
$frame->set_text( ltrim($frame->get_text()) );
$frame->recalculate_width();
}
$w = $frame->get_margin_width();
if ( $w == 0 ) {
return;
}
// Debugging code:
/*
pre_r("\n<h3>Adding frame to line:</h3>");
// pre_r("Me: " . $this->get_node()->nodeName . " (" . spl_object_hash($this->get_node()) . ")");
// pre_r("Node: " . $frame->get_node()->nodeName . " (" . spl_object_hash($frame->get_node()) . ")");
if ( $frame->is_text_node() )
pre_r('"'.$frame->get_node()->nodeValue.'"');
pre_r("Line width: " . $this->_line_boxes[$this->_cl]->w);
pre_r("Frame: " . get_class($frame));
pre_r("Frame width: " . $w);
pre_r("Frame height: " . $frame->get_margin_height());
pre_r("Containing block width: " . $this->get_containing_block("w"));
*/
// End debugging
$line = $this->_line_boxes[$this->_cl];
if ( $line->left + $line->w + $line->right + $w > $this->get_containing_block("w")) {
$this->add_line();
}
$frame->position();
$current_line = $this->_line_boxes[$this->_cl];
$current_line->add_frame($frame);
if ( $frame->is_text_node() ) {
$current_line->wc += count(preg_split("/\s+/", trim($frame->get_text())));
}
$this->increase_line_width($w);
$this->maximize_line_height($frame->get_margin_height(), $frame);
}
function remove_frames_from_line(Frame $frame) {
// Search backwards through the lines for $frame
$i = $this->_cl;
$j = null;
while ($i >= 0) {
if ( ($j = in_array($frame, $this->_line_boxes[$i]->get_frames(), true)) !== false ) {
break;
}
$i--;
}
if ( $j === false ) {
return;
}
// Remove $frame and all frames that follow
while ($j < count($this->_line_boxes[$i]->get_frames())) {
$frames = $this->_line_boxes[$i]->get_frames();
$f = $frames[$j];
$frames[$j] = null;
unset($frames[$j]);
$j++;
$this->_line_boxes[$i]->w -= $f->get_margin_width();
}
// Recalculate the height of the line
$h = 0;
foreach ($this->_line_boxes[$i]->get_frames() as $f) {
$h = max( $h, $f->get_margin_height() );
}
$this->_line_boxes[$i]->h = $h;
// Remove all lines that follow
while ($this->_cl > $i) {
$this->_line_boxes[ $this->_cl ] = null;
unset($this->_line_boxes[ $this->_cl ]);
$this->_cl--;
}
}
function increase_line_width($w) {
$this->_line_boxes[ $this->_cl ]->w += $w;
}
function maximize_line_height($val, Frame $frame) {
if ( $val > $this->_line_boxes[ $this->_cl ]->h ) {
$this->_line_boxes[ $this->_cl ]->tallest_frame = $frame;
$this->_line_boxes[ $this->_cl ]->h = $val;
}
}
function add_line($br = false) {
// if ( $this->_line_boxes[$this->_cl]["h"] == 0 ) //count($this->_line_boxes[$i]["frames"]) == 0 ||
// return;
$this->_line_boxes[$this->_cl]->br = $br;
$y = $this->_line_boxes[$this->_cl]->y + $this->_line_boxes[$this->_cl]->h;
$new_line = new Line_Box($this, $y);
$this->_line_boxes[ ++$this->_cl ] = $new_line;
}
//........................................................................
}
<?php
/**
* @package dompdf
* @link http://dompdf.github.com/
* @author Benj Carson <benjcarson@digitaljunkies.ca>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
/**
* Positions block frames
*
* @access private
* @package dompdf
*/
class Block_Positioner extends Positioner {
function __construct(Frame_Decorator $frame) { parent::__construct($frame); }
//........................................................................
function position() {
$frame = $this->_frame;
$style = $frame->get_style();
$cb = $frame->get_containing_block();
$p = $frame->find_block_parent();
if ( $p ) {
$float = $style->float;
$enable_css_float = $frame->get_dompdf()->get_option("enable_css_float");
if ( !$enable_css_float || !$float || $float === "none" ) {
$p->add_line(true);
}
$y = $p->get_current_line_box()->y;
}
else {
$y = $cb["y"];
}
$x = $cb["x"];
// Relative positionning
if ( $style->position === "relative" ) {
$top = $style->length_in_pt($style->top, $cb["h"]);
//$right = $style->length_in_pt($style->right, $cb["w"]);
//$bottom = $style->length_in_pt($style->bottom, $cb["h"]);
$left = $style->length_in_pt($style->left, $cb["w"]);
$x += $left;
$y += $top;
}
$frame->set_position($x, $y);
}
}
<?php
/**
* @package dompdf
* @link http://dompdf.github.com/
* @author Benj Carson <benjcarson@digitaljunkies.ca>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
/**
* Renders block frames
*
* @access private
* @package dompdf
*/
class Block_Renderer extends Abstract_Renderer {
//........................................................................
function render(Frame $frame) {
$style = $frame->get_style();
$node = $frame->get_node();
list($x, $y, $w, $h) = $frame->get_border_box();
$this->_set_opacity( $frame->get_opacity( $style->opacity ) );
if ( $node->nodeName === "body" ) {
$h = $frame->get_containing_block("h") - $style->length_in_pt(array(
$style->margin_top,
$style->border_top_width,
$style->border_bottom_width,
$style->margin_bottom),
$style->width);
}
// Handle anchors & links
if ( $node->nodeName === "a" && $href = $node->getAttribute("href") ) {
$this->_canvas->add_link($href, $x, $y, $w, $h);
}
// Draw our background, border and content
list($tl, $tr, $br, $bl) = $style->get_computed_border_radius($w, $h);
if ( $tl + $tr + $br + $bl > 0 ) {
$this->_canvas->clipping_roundrectangle( $x, $y, $w, $h, $tl, $tr, $br, $bl );
}
if ( ($bg = $style->background_color) !== "transparent" ) {
$this->_canvas->filled_rectangle( $x, $y, $w, $h, $bg );
}
if ( ($url = $style->background_image) && $url !== "none" ) {
$this->_background_image($url, $x, $y, $w, $h, $style);
}
if ( $tl + $tr + $br + $bl > 0 ) {
$this->_canvas->clipping_end();
}
$border_box = array($x, $y, $w, $h);
$this->_render_border($frame, $border_box);
$this->_render_outline($frame, $border_box);
if (DEBUG_LAYOUT && DEBUG_LAYOUT_BLOCKS) {
$this->_debug_layout($frame->get_border_box(), "red");
if (DEBUG_LAYOUT_PADDINGBOX) {
$this->_debug_layout($frame->get_padding_box(), "red", array(0.5, 0.5));
}
}
if (DEBUG_LAYOUT && DEBUG_LAYOUT_LINES && $frame->get_decorator()) {
foreach ($frame->get_decorator()->get_line_boxes() as $line) {
$frame->_debug_layout(array($line->x, $line->y, $line->w, $line->h), "orange");
}
}
}
protected function _render_border(Frame_Decorator $frame, $border_box = null, $corner_style = "bevel") {
$style = $frame->get_style();
$bp = $style->get_border_properties();
if ( empty($border_box) ) {
$border_box = $frame->get_border_box();
}
// find the radius
$radius = $style->get_computed_border_radius($border_box[2], $border_box[3]); // w, h
// Short-cut: If all the borders are "solid" with the same color and style, and no radius, we'd better draw a rectangle
if (
in_array($bp["top"]["style"], array("solid", "dashed", "dotted")) &&
$bp["top"] == $bp["right"] &&
$bp["right"] == $bp["bottom"] &&
$bp["bottom"] == $bp["left"] &&
array_sum($radius) == 0
) {
$props = $bp["top"];
if ( $props["color"] === "transparent" || $props["width"] <= 0 ) return;
list($x, $y, $w, $h) = $border_box;
$width = $style->length_in_pt($props["width"]);
$pattern = $this->_get_dash_pattern($props["style"], $width);
$this->_canvas->rectangle($x + $width / 2, $y + $width / 2, $w - $width, $h - $width, $props["color"], $width, $pattern);
return;
}
// Do it the long way
$widths = array($style->length_in_pt($bp["top"]["width"]),
$style->length_in_pt($bp["right"]["width"]),
$style->length_in_pt($bp["bottom"]["width"]),
$style->length_in_pt($bp["left"]["width"]));
foreach ($bp as $side => $props) {
list($x, $y, $w, $h) = $border_box;
$length = 0;
$r1 = 0;
$r2 = 0;
if ( !$props["style"] ||
$props["style"] === "none" ||
$props["width"] <= 0 ||
$props["color"] == "transparent" )
continue;
switch($side) {
case "top":
$length = $w;
$r1 = $radius["top-left"];
$r2 = $radius["top-right"];
break;
case "bottom":
$length = $w;
$y += $h;
$r1 = $radius["bottom-left"];
$r2 = $radius["bottom-right"];
break;
case "left":
$length = $h;
$r1 = $radius["top-left"];
$r2 = $radius["bottom-left"];
break;
case "right":
$length = $h;
$x += $w;
$r1 = $radius["top-right"];
$r2 = $radius["bottom-right"];
break;
default:
break;
}
$method = "_border_" . $props["style"];
// draw rounded corners
$this->$method($x, $y, $length, $props["color"], $widths, $side, $corner_style, $r1, $r2);
}
}
protected function _render_outline(Frame_Decorator $frame, $border_box = null, $corner_style = "bevel") {
$style = $frame->get_style();
$props = array(
"width" => $style->outline_width,
"style" => $style->outline_style,
"color" => $style->outline_color,
);
if ( !$props["style"] || $props["style"] === "none" || $props["width"] <= 0 )
return;
if ( empty($border_box) ) {
$border_box = $frame->get_border_box();
}
$offset = $style->length_in_pt($props["width"]);
$pattern = $this->_get_dash_pattern($props["style"], $offset);
// If the outline style is "solid" we'd better draw a rectangle
if ( in_array($props["style"], array("solid", "dashed", "dotted")) ) {
$border_box[0] -= $offset / 2;
$border_box[1] -= $offset / 2;
$border_box[2] += $offset;
$border_box[3] += $offset;
list($x, $y, $w, $h) = $border_box;
$this->_canvas->rectangle($x, $y, $w, $h, $props["color"], $offset, $pattern);
return;
}
$border_box[0] -= $offset;
$border_box[1] -= $offset;
$border_box[2] += $offset * 2;
$border_box[3] += $offset * 2;
$method = "_border_" . $props["style"];
$widths = array_fill(0, 4, $props["width"]);
$sides = array("top", "right", "left", "bottom");
$length = 0;
foreach ($sides as $side) {
list($x, $y, $w, $h) = $border_box;
switch($side) {
case "top":
$length = $w;
break;
case "bottom":
$length = $w;
$y += $h;
break;
case "left":
$length = $h;
break;
case "right":
$length = $h;
$x += $w;
break;
default:
break;
}
$this->$method($x, $y, $length, $props["color"], $widths, $side, $corner_style);
}
}
}
<?php
/**
* @package dompdf
* @link http://dompdf.github.com/
* @author Benj Carson <benjcarson@digitaljunkies.ca>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
/**
* Caching canvas implementation
*
* Each rendered page is serialized and stored in the {@link Page_Cache}.
* This is useful for static forms/pages that do not need to be re-rendered
* all the time.
*
* This class decorates normal CPDF_Adapters. It is currently completely
* experimental.
*
* @access private
* @package dompdf
*/
class Cached_PDF_Decorator extends CPDF_Adapter implements Canvas {
/**
* @var CPDF_Adapter
*/
protected $_pdf;
protected $_cache_id;
protected $_current_page_id;
protected $_fonts; // fonts used in this document
function __construct($paper = "letter", $orientation = "portrait", DOMPDF $dompdf) {
$this->_fonts = array();
}
/**
* Must be called after constructor
*
* @param int $cache_id
* @param CPDF_Adapter $pdf
*/
function init($cache_id, CPDF_Adapter $pdf) {
$this->_cache_id = $cache_id;
$this->_pdf = $pdf;
$this->_current_page_id = $this->_pdf->open_object();
}
//........................................................................
function get_cpdf() { return $this->_pdf->get_cpdf(); }
function open_object() { $this->_pdf->open_object(); }
function reopen_object($object) { $this->_pdf->reopen_object($object); }
function close_object() { $this->_pdf->close_object(); }
function add_object($object, $where = 'all') { $this->_pdf->add_object($object, $where); }
function serialize_object($id) { $this->_pdf->serialize_object($id); }
function reopen_serialized_object($obj) { $this->_pdf->reopen_serialized_object($obj); }
//........................................................................
function get_width() { return $this->_pdf->get_width(); }
function get_height() { return $this->_pdf->get_height(); }
function get_page_number() { return $this->_pdf->get_page_number(); }
function get_page_count() { return $this->_pdf->get_page_count(); }
function set_page_number($num) { $this->_pdf->set_page_number($num); }
function set_page_count($count) { $this->_pdf->set_page_count($count); }
function line($x1, $y1, $x2, $y2, $color, $width, $style = array()) {
$this->_pdf->line($x1, $y1, $x2, $y2, $color, $width, $style);
}
function rectangle($x1, $y1, $w, $h, $color, $width, $style = array()) {
$this->_pdf->rectangle($x1, $y1, $w, $h, $color, $width, $style);
}
function filled_rectangle($x1, $y1, $w, $h, $color) {
$this->_pdf->filled_rectangle($x1, $y1, $w, $h, $color);
}
function polygon($points, $color, $width = null, $style = array(), $fill = false) {
$this->_pdf->polygon($points, $color, $width, $style, $fill);
}
function circle($x, $y, $r1, $color, $width = null, $style = null, $fill = false) {
$this->_pdf->circle($x, $y, $r1, $color, $width, $style, $fill);
}
function image($img_url, $x, $y, $w, $h, $resolution = "normal") {
$this->_pdf->image($img_url, $x, $y, $w, $h, $resolution);
}
function text($x, $y, $text, $font, $size, $color = array(0,0,0), $word_space = 0.0, $char_space = 0.0, $angle = 0.0) {
$this->_fonts[$font] = true;
$this->_pdf->text($x, $y, $text, $font, $size, $color, $word_space, $char_space, $angle);
}
function page_text($x, $y, $text, $font, $size, $color = array(0,0,0), $word_space = 0.0, $char_space = 0.0, $angle = 0.0) {
// We want to remove this from cached pages since it may not be correct
$this->_pdf->close_object();
$this->_pdf->page_text($x, $y, $text, $font, $size, $color, $word_space, $char_space, $angle);
$this->_pdf->reopen_object($this->_current_page_id);
}
function page_script($script, $type = 'text/php') {
// We want to remove this from cached pages since it may not be correct
$this->_pdf->close_object();
$this->_pdf->page_script($script, $type);
$this->_pdf->reopen_object($this->_current_page_id);
}
function new_page() {
$this->_pdf->close_object();
// Add the object to the current page
$this->_pdf->add_object($this->_current_page_id, "add");
$this->_pdf->new_page();
Page_Cache::store_page($this->_cache_id,
$this->_pdf->get_page_number() - 1,
$this->_pdf->serialize_object($this->_current_page_id));
$this->_current_page_id = $this->_pdf->open_object();
return $this->_current_page_id;
}
function stream($filename, $options = null) {
// Store the last page in the page cache
if ( !is_null($this->_current_page_id) ) {
$this->_pdf->close_object();
$this->_pdf->add_object($this->_current_page_id, "add");
Page_Cache::store_page($this->_cache_id,
$this->_pdf->get_page_number(),
$this->_pdf->serialize_object($this->_current_page_id));
Page_Cache::store_fonts($this->_cache_id, $this->_fonts);
$this->_current_page_id = null;
}
$this->_pdf->stream($filename);
}
function output($options = null) {
// Store the last page in the page cache
if ( !is_null($this->_current_page_id) ) {
$this->_pdf->close_object();
$this->_pdf->add_object($this->_current_page_id, "add");
Page_Cache::store_page($this->_cache_id,
$this->_pdf->get_page_number(),
$this->_pdf->serialize_object($this->_current_page_id));
$this->_current_page_id = null;
}
return $this->_pdf->output();
}
function get_messages() { return $this->_pdf->get_messages(); }
}
<?php
/**
* @package dompdf
* @link http://dompdf.github.com/
* @author Benj Carson <benjcarson@digitaljunkies.ca>
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
/**
* Main rendering interface
*
* Currently {@link CPDF_Adapter}, {@link PDFLib_Adapter}, {@link TCPDF_Adapter}, and {@link GD_Adapter}
* implement this interface.
*
* Implementations should measure x and y increasing to the left and down,
* respectively, with the origin in the top left corner. Implementations
* are free to use a unit other than points for length, but I can't
* guarantee that the results will look any good.
*
* @package dompdf
*/
interface Canvas {
function __construct($paper = "letter", $orientation = "portrait", DOMPDF $dompdf);
/**
* @return DOMPDF
*/
function get_dompdf();
/**
* Returns the current page number
*
* @return int
*/
function get_page_number();
/**
* Returns the total number of pages
*
* @return int
*/
function get_page_count();
/**
* Sets the total number of pages
*
* @param int $count
*/
function set_page_count($count);
/**
* Draws a line from x1,y1 to x2,y2
*
* See {@link Style::munge_color()} for the format of the color array.
* See {@link Cpdf::setLineStyle()} for a description of the format of the
* $style parameter (aka dash).
*
* @param float $x1
* @param float $y1
* @param float $x2
* @param float $y2
* @param array $color
* @param float $width
* @param array $style
*/
function line($x1, $y1, $x2, $y2, $color, $width, $style = null);
/**
* Draws a rectangle at x1,y1 with width w and height h
*
* See {@link Style::munge_color()} for the format of the color array.
* See {@link Cpdf::setLineStyle()} for a description of the $style
* parameter (aka dash)
*
* @param float $x1
* @param float $y1
* @param float $w
* @param float $h
* @param array $color
* @param float $width
* @param array $style
*/
function rectangle($x1, $y1, $w, $h, $color, $width, $style = null);
/**
* Draws a filled rectangle at x1,y1 with width w and height h
*
* See {@link Style::munge_color()} for the format of the color array.
*
* @param float $x1
* @param float $y1
* @param float $w
* @param float $h
* @param array $color
*/
function filled_rectangle($x1, $y1, $w, $h, $color);
/**
* Starts a clipping rectangle at x1,y1 with width w and height h
*
* @param float $x1
* @param float $y1
* @param float $w
* @param float $h
*/
function clipping_rectangle($x1, $y1, $w, $h);
/**
* Starts a rounded clipping rectangle at x1,y1 with width w and height h
*
* @param float $x1
* @param float $y1
* @param float $w
* @param float $h
* @param float $tl
* @param float $tr
* @param float $br
* @param float $bl
*
* @return
*/
function clipping_roundrectangle($x1, $y1, $w, $h, $tl, $tr, $br, $bl);
/**
* Ends the last clipping shape
*/
function clipping_end();
/**
* Save current state
*/
function save();
/**
* Restore last state
*/
function restore();
/**
* Rotate
*/
function rotate($angle, $x, $y);
/**
* Skew
*/
function skew($angle_x, $angle_y, $x, $y);
/**
* Scale
*/
function scale($s_x, $s_y, $x, $y);
/**
* Translate
*/
function translate($t_x, $t_y);
/**
* Transform
*/
function transform($a, $b, $c, $d, $e, $f);
/**
* Draws a polygon
*
* The polygon is formed by joining all the points stored in the $points
* array. $points has the following structure:
* <code>
* array(0 => x1,
* 1 => y1,
* 2 => x2,
* 3 => y2,
* ...
* );
* </code>
*
* See {@link Style::munge_color()} for the format of the color array.
* See {@link Cpdf::setLineStyle()} for a description of the $style
* parameter (aka dash)
*
* @param array $points
* @param array $color
* @param float $width
* @param array $style
* @param bool $fill Fills the polygon if true
*/
function polygon($points, $color, $width = null, $style = null, $fill = false);
/**
* Draws a circle at $x,$y with radius $r
*
* See {@link Style::munge_color()} for the format of the color array.
* See {@link Cpdf::setLineStyle()} for a description of the $style
* parameter (aka dash)
*
* @param float $x
* @param float $y
* @param float $r
* @param array $color
* @param float $width
* @param array $style
* @param bool $fill Fills the circle if true
*/
function circle($x, $y, $r, $color, $width = null, $style = null, $fill = false);
/**
* Add an image to the pdf.
*
* The image is placed at the specified x and y coordinates with the
* given width and height.
*
* @param string $img_url the path to the image
* @param float $x x position
* @param float $y y position
* @param int $w width (in pixels)
* @param int $h height (in pixels)
* @param string $resolution The resolution of the image
*/
function image($img_url, $x, $y, $w, $h, $resolution = "normal");
/**
* Add an arc to the PDF
* See {@link Style::munge_color()} for the format of the color array.
*
* @param float $x X coordinate of the arc
* @param float $y Y coordinate of the arc
* @param float $r1 Radius 1
* @param float $r2 Radius 2
* @param float $astart Start angle in degrees
* @param float $aend End angle in degrees
* @param array $color Color
* @param float $width
* @param array $style
*
* @return void
*/
function arc($x, $y, $r1, $r2, $astart, $aend, $color, $width, $style = array());
/**
* Writes text at the specified x and y coordinates
* See {@link Style::munge_color()} for the format of the color array.
*
* @param float $x
* @param float $y
* @param string $text the text to write
* @param string $font the font file to use
* @param float $size the font size, in points
* @param array $color
* @param float $word_space word spacing adjustment
* @param float $char_space char spacing adjustment
* @param float $angle angle
*
* @return void
*/
function text($x, $y, $text, $font, $size, $color = array(0,0,0), $word_space = 0.0, $char_space = 0.0, $angle = 0.0);
/**
* Add a named destination (similar to <a name="foo">...</a> in html)
*
* @param string $anchorname The name of the named destination
*/
function add_named_dest($anchorname);
/**
* Add a link to the pdf
*
* @param string $url The url to link to
* @param float $x The x position of the link
* @param float $y The y position of the link
* @param float $width The width of the link
* @param float $height The height of the link
*
* @return void
*/
function add_link($url, $x, $y, $width, $height);
/**
* Add meta information to the pdf
*
* @param string $name Label of the value (Creator, Producer, etc.)
* @param string $value The text to set
*/
function add_info($name, $value);
/**
* Calculates text size, in points
*
* @param string $text the text to be sized
* @param string $font the desired font
* @param float $size the desired font size
* @param float $word_spacing word spacing, if any
* @param float $char_spacing
*
* @return float
*/
function get_text_width($text, $font, $size, $word_spacing = 0.0, $char_spacing = 0.0);
/**
* Calculates font height, in points
*
* @param string $font
* @param float $size
*
* @return float
*/
function get_font_height($font, $size);
/**
* Calculates font baseline, in points
*
* @param string $font
* @param float $size
*
* @return float
*/
function get_font_baseline($font, $size);
/**
* Returns the font x-height, in points
*
* @param string $font
* @param float $size
*
* @return float
*/
//function get_font_x_height($font, $size);
/**
* Sets the opacity
*
* @param float $opacity
* @param string $mode
*/
function set_opacity($opacity, $mode = "Normal");
/**
* Sets the default view
*
* @param string $view
* 'XYZ' left, top, zoom
* 'Fit'
* 'FitH' top
* 'FitV' left
* 'FitR' left,bottom,right
* 'FitB'
* 'FitBH' top
* 'FitBV' left
* @param array $options
*
* @return void
*/
function set_default_view($view, $options = array());
/**
* @param string $script
*
* @return void
*/
function javascript($script);
/**
* Starts a new page
*
* Subsequent drawing operations will appear on the new page.
*/
function new_page();
/**
* Streams the PDF directly to the browser
*
* @param string $filename the name of the PDF file
* @param array $options associative array, 'Attachment' => 0 or 1, 'compress' => 1 or 0
*/
function stream($filename, $options = null);
/**
* Returns the PDF as a string
*
* @param array $options associative array: 'compress' => 1 or 0
* @return string
*/
function output($options = null);
}
<?php
/**
* @package dompdf
* @link http://dompdf.github.com/
* @author Benj Carson <benjcarson@digitaljunkies.ca>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
/**
* Create canvas instances
*
* The canvas factory creates canvas instances based on the
* availability of rendering backends and config options.
*
* @package dompdf
*/
class Canvas_Factory {
/**
* Constructor is private: this is a static class
*/
private function __construct() { }
/**
* @param DOMPDF $dompdf
* @param string|array $paper
* @param string $orientation
* @param string $class
*
* @return Canvas
*/
static function get_instance(DOMPDF $dompdf, $paper = null, $orientation = null, $class = null) {
$backend = strtolower(DOMPDF_PDF_BACKEND);
if ( isset($class) && class_exists($class, false) ) {
$class .= "_Adapter";
}
else if ( (DOMPDF_PDF_BACKEND === "auto" || $backend === "pdflib" ) &&
class_exists("PDFLib", false) ) {
$class = "PDFLib_Adapter";
}
// FIXME The TCPDF adapter is not ready yet
//else if ( (DOMPDF_PDF_BACKEND === "auto" || $backend === "cpdf") )
// $class = "CPDF_Adapter";
else if ( $backend === "tcpdf" ) {
$class = "TCPDF_Adapter";
}
else if ( $backend === "gd" ) {
$class = "GD_Adapter";
}
else {
$class = "CPDF_Adapter";
}
return new $class($paper, $orientation, $dompdf);
}
}
<?php
/**
* @package dompdf
* @link http://dompdf.github.com/
* @author Benj Carson <benjcarson@digitaljunkies.ca>
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
class CSS_Color {
static $cssColorNames = array(
"aliceblue" => "F0F8FF",
"antiquewhite" => "FAEBD7",
"aqua" => "00FFFF",
"aquamarine" => "7FFFD4",
"azure" => "F0FFFF",
"beige" => "F5F5DC",
"bisque" => "FFE4C4",
"black" => "000000",
"blanchedalmond" => "FFEBCD",
"blue" => "0000FF",
"blueviolet" => "8A2BE2",
"brown" => "A52A2A",
"burlywood" => "DEB887",
"cadetblue" => "5F9EA0",
"chartreuse" => "7FFF00",
"chocolate" => "D2691E",
"coral" => "FF7F50",
"cornflowerblue" => "6495ED",
"cornsilk" => "FFF8DC",
"crimson" => "DC143C",
"cyan" => "00FFFF",
"darkblue" => "00008B",
"darkcyan" => "008B8B",
"darkgoldenrod" => "B8860B",
"darkgray" => "A9A9A9",
"darkgreen" => "006400",
"darkgrey" => "A9A9A9",
"darkkhaki" => "BDB76B",
"darkmagenta" => "8B008B",
"darkolivegreen" => "556B2F",
"darkorange" => "FF8C00",
"darkorchid" => "9932CC",
"darkred" => "8B0000",
"darksalmon" => "E9967A",
"darkseagreen" => "8FBC8F",
"darkslateblue" => "483D8B",
"darkslategray" => "2F4F4F",
"darkslategrey" => "2F4F4F",
"darkturquoise" => "00CED1",
"darkviolet" => "9400D3",
"deeppink" => "FF1493",
"deepskyblue" => "00BFFF",
"dimgray" => "696969",
"dimgrey" => "696969",
"dodgerblue" => "1E90FF",
"firebrick" => "B22222",
"floralwhite" => "FFFAF0",
"forestgreen" => "228B22",
"fuchsia" => "FF00FF",
"gainsboro" => "DCDCDC",
"ghostwhite" => "F8F8FF",
"gold" => "FFD700",
"goldenrod" => "DAA520",
"gray" => "808080",
"green" => "008000",
"greenyellow" => "ADFF2F",
"grey" => "808080",
"honeydew" => "F0FFF0",
"hotpink" => "FF69B4",
"indianred" => "CD5C5C",
"indigo" => "4B0082",
"ivory" => "FFFFF0",
"khaki" => "F0E68C",
"lavender" => "E6E6FA",
"lavenderblush" => "FFF0F5",
"lawngreen" => "7CFC00",
"lemonchiffon" => "FFFACD",
"lightblue" => "ADD8E6",
"lightcoral" => "F08080",
"lightcyan" => "E0FFFF",
"lightgoldenrodyellow" => "FAFAD2",
"lightgray" => "D3D3D3",
"lightgreen" => "90EE90",
"lightgrey" => "D3D3D3",
"lightpink" => "FFB6C1",
"lightsalmon" => "FFA07A",
"lightseagreen" => "20B2AA",
"lightskyblue" => "87CEFA",
"lightslategray" => "778899",
"lightslategrey" => "778899",
"lightsteelblue" => "B0C4DE",
"lightyellow" => "FFFFE0",
"lime" => "00FF00",
"limegreen" => "32CD32",
"linen" => "FAF0E6",
"magenta" => "FF00FF",
"maroon" => "800000",
"mediumaquamarine" => "66CDAA",
"mediumblue" => "0000CD",
"mediumorchid" => "BA55D3",
"mediumpurple" => "9370DB",
"mediumseagreen" => "3CB371",
"mediumslateblue" => "7B68EE",
"mediumspringgreen" => "00FA9A",
"mediumturquoise" => "48D1CC",
"mediumvioletred" => "C71585",
"midnightblue" => "191970",
"mintcream" => "F5FFFA",
"mistyrose" => "FFE4E1",
"moccasin" => "FFE4B5",
"navajowhite" => "FFDEAD",
"navy" => "000080",
"oldlace" => "FDF5E6",
"olive" => "808000",
"olivedrab" => "6B8E23",
"orange" => "FFA500",
"orangered" => "FF4500",
"orchid" => "DA70D6",
"palegoldenrod" => "EEE8AA",
"palegreen" => "98FB98",
"paleturquoise" => "AFEEEE",
"palevioletred" => "DB7093",
"papayawhip" => "FFEFD5",
"peachpuff" => "FFDAB9",
"peru" => "CD853F",
"pink" => "FFC0CB",
"plum" => "DDA0DD",
"powderblue" => "B0E0E6",
"purple" => "800080",
"red" => "FF0000",
"rosybrown" => "BC8F8F",
"royalblue" => "4169E1",
"saddlebrown" => "8B4513",
"salmon" => "FA8072",
"sandybrown" => "F4A460",
"seagreen" => "2E8B57",
"seashell" => "FFF5EE",
"sienna" => "A0522D",
"silver" => "C0C0C0",
"skyblue" => "87CEEB",
"slateblue" => "6A5ACD",
"slategray" => "708090",
"slategrey" => "708090",
"snow" => "FFFAFA",
"springgreen" => "00FF7F",
"steelblue" => "4682B4",
"tan" => "D2B48C",
"teal" => "008080",
"thistle" => "D8BFD8",
"tomato" => "FF6347",
"turquoise" => "40E0D0",
"violet" => "EE82EE",
"wheat" => "F5DEB3",
"white" => "FFFFFF",
"whitesmoke" => "F5F5F5",
"yellow" => "FFFF00",
"yellowgreen" => "9ACD32",
);
static function parse($color) {
if ( is_array($color) ) {
// Assume the array has the right format...
// FIXME: should/could verify this.
return $color;
}
static $cache = array();
$color = strtolower($color);
if ( isset($cache[$color]) ) {
return $cache[$color];
}
if ( in_array($color, array("transparent", "inherit")) ) {
return $cache[$color] = $color;
}
if ( isset(self::$cssColorNames[$color]) ) {
return $cache[$color] = self::getArray(self::$cssColorNames[$color]);
}
$length = mb_strlen($color);
// #rgb format
if ( $length == 4 && $color[0] === "#" ) {
return $cache[$color] = self::getArray($color[1].$color[1].$color[2].$color[2].$color[3].$color[3]);
}
// #rrggbb format
else if ( $length == 7 && $color[0] === "#" ) {
return $cache[$color] = self::getArray(mb_substr($color, 1, 6));
}
// rgb( r,g,b ) / rgbaa( r,g,b,α ) format
else if ( mb_strpos($color, "rgb") !== false ) {
$i = mb_strpos($color, "(");
$j = mb_strpos($color, ")");
// Bad color value
if ( $i === false || $j === false ) {
return null;
}
$triplet = explode(",", mb_substr($color, $i+1, $j-$i-1));
// alpha transparency
// FIXME: not currently using transparency
$alpha = 1;
if ( count( $triplet ) == 4 ) {
$alpha = (float) ( trim( array_pop( $triplet ) ) );
// bad value, set to fully opaque
if ( $alpha > 1 || $alpha < 0 ) {
$alpha = 1;
}
}
if ( count($triplet) != 3 ) {
return null;
}
foreach (array_keys($triplet) as $c) {
$triplet[$c] = trim($triplet[$c]);
if ( $triplet[$c][mb_strlen($triplet[$c]) - 1] === "%" ) {
$triplet[$c] = round($triplet[$c] * 2.55);
}
}
return $cache[$color] = self::getArray(vsprintf("%02X%02X%02X", $triplet));
}
// cmyk( c,m,y,k ) format
// http://www.w3.org/TR/css3-gcpm/#cmyk-colors
else if ( mb_strpos($color, "cmyk") !== false ) {
$i = mb_strpos($color, "(");
$j = mb_strpos($color, ")");
// Bad color value
if ( $i === false || $j === false ) {
return null;
}
$values = explode(",", mb_substr($color, $i+1, $j-$i-1));
if ( count($values) != 4 ) {
return null;
}
foreach ($values as &$c) {
$c = floatval(trim($c));
if ($c > 1.0) $c = 1.0;
if ($c < 0.0) $c = 0.0;
}
return $cache[$color] = self::getArray($values);
}
return null;
}
static function getArray($color) {
$c = array(null, null, null, null, "hex" => null);
if (is_array($color)) {
$c = $color;
$c["c"] = $c[0];
$c["m"] = $c[1];
$c["y"] = $c[2];
$c["k"] = $c[3];
$c["hex"] = "cmyk($c[0],$c[1],$c[2],$c[3])";
}
else {
$c[0] = hexdec(mb_substr($color, 0, 2)) / 0xff;
$c[1] = hexdec(mb_substr($color, 2, 2)) / 0xff;
$c[2] = hexdec(mb_substr($color, 4, 2)) / 0xff;
$c["r"] = $c[0];
$c["g"] = $c[1];
$c["b"] = $c[2];
$c["hex"] = "#$color";
}
return $c;
}
}
<?php
/**
* @package dompdf
* @link http://dompdf.github.com/
* @author Benj Carson <benjcarson@digitaljunkies.ca>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
/**
* Standard exception thrown by DOMPDF classes
*
* @package dompdf
*/
class DOMPDF_Exception extends Exception {
/**
* Class constructor
*
* @param string $message Error message
* @param int $code Error code
*/
function __construct($message = null, $code = 0) {
parent::__construct($message, $code);
}
}
<?php
/**
* @package dompdf
* @link http://dompdf.github.com/
* @author Benj Carson <benjcarson@digitaljunkies.ca>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
/**
* Image exception thrown by DOMPDF
*
* @package dompdf
*/
class DOMPDF_Image_Exception extends DOMPDF_Exception {
/**
* Class constructor
*
* @param string $message Error message
* @param int $code Error code
*/
function __construct($message = null, $code = 0) {
parent::__construct($message, $code);
}
}
<?php
/**
* @package dompdf
* @link http://dompdf.github.com/
* @author Benj Carson <benjcarson@digitaljunkies.ca>
* @author ...
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
<?php
/**
* @package dompdf
* @link http://dompdf.github.com/
* @author Benj Carson <benjcarson@digitaljunkies.ca>
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
/**
* Positions fixely positioned frames
*/
class Fixed_Positioner extends Positioner {
function __construct(Frame_Decorator $frame) { parent::__construct($frame); }
function position() {
$frame = $this->_frame;
$style = $frame->get_original_style();
$root = $frame->get_root();
$initialcb = $root->get_containing_block();
$initialcb_style = $root->get_style();
$p = $frame->find_block_parent();
if ( $p ) {
$p->add_line();
}
// Compute the margins of the @page style
$margin_top = $initialcb_style->length_in_pt($initialcb_style->margin_top, $initialcb["h"]);
$margin_right = $initialcb_style->length_in_pt($initialcb_style->margin_right, $initialcb["w"]);
$margin_bottom = $initialcb_style->length_in_pt($initialcb_style->margin_bottom, $initialcb["h"]);
$margin_left = $initialcb_style->length_in_pt($initialcb_style->margin_left, $initialcb["w"]);
// The needed computed style of the element
$height = $style->length_in_pt($style->height, $initialcb["h"]);
$width = $style->length_in_pt($style->width, $initialcb["w"]);
$top = $style->length_in_pt($style->top, $initialcb["h"]);
$right = $style->length_in_pt($style->right, $initialcb["w"]);
$bottom = $style->length_in_pt($style->bottom, $initialcb["h"]);
$left = $style->length_in_pt($style->left, $initialcb["w"]);
$y = $margin_top;
if ( isset($top) ) {
$y = $top + $margin_top;
if ( $top === "auto" ) {
$y = $margin_top;
if ( isset($bottom) && $bottom !== "auto" ) {
$y = $initialcb["h"] - $bottom - $margin_bottom;
$margin_height = $this->_frame->get_margin_height();
if ( $margin_height !== "auto" ) {
$y -= $margin_height;
}
else {
$y -= $height;
}
}
}
}
$x = $margin_left;
if ( isset($left) ) {
$x = $left + $margin_left;
if ( $left === "auto" ) {
$x = $margin_left;
if ( isset($right) && $right !== "auto" ) {
$x = $initialcb["w"] - $right - $margin_right;
$margin_width = $this->_frame->get_margin_width();
if ( $margin_width !== "auto" ) {
$x -= $margin_width;
}
else {
$x -= $width;
}
}
}
}
$frame->set_position($x, $y);
$children = $frame->get_children();
foreach($children as $child) {
$child->set_position($x, $y);
}
}
}
\ No newline at end of file
<?php
/**
* @package dompdf
* @link http://dompdf.github.com/
* @author Benj Carson <benjcarson@digitaljunkies.ca>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
/**
* Contains frame decorating logic
*
* This class is responsible for assigning the correct {@link Frame_Decorator},
* {@link Positioner}, and {@link Frame_Reflower} objects to {@link Frame}
* objects. This is determined primarily by the Frame's display type, but
* also by the Frame's node's type (e.g. DomElement vs. #text)
*
* @access private
* @package dompdf
*/
class Frame_Factory {
/**
* Decorate the root Frame
*
* @param $root Frame The frame to decorate
* @param $dompdf DOMPDF The dompdf instance
* @return Page_Frame_Decorator
*/
static function decorate_root(Frame $root, DOMPDF $dompdf) {
$frame = new Page_Frame_Decorator($root, $dompdf);
$frame->set_reflower( new Page_Frame_Reflower($frame) );
$root->set_decorator($frame);
return $frame;
}
/**
* Decorate a Frame
*
* @param Frame $frame The frame to decorate
* @param DOMPDF $dompdf The dompdf instance
* @param Frame $root The frame to decorate
*
* @throws DOMPDF_Exception
* @return Frame_Decorator
* FIXME: this is admittedly a little smelly...
*/
static function decorate_frame(Frame $frame, DOMPDF $dompdf, Frame $root = null) {
if ( is_null($dompdf) ) {
throw new DOMPDF_Exception("The DOMPDF argument is required");
}
$style = $frame->get_style();
// Floating (and more generally out-of-flow) elements are blocks
// http://coding.smashingmagazine.com/2007/05/01/css-float-theory-things-you-should-know/
if ( !$frame->is_in_flow() && in_array($style->display, Style::$INLINE_TYPES)) {
$style->display = "block";
}
$display = $style->display;
switch ($display) {
case "block":
$positioner = "Block";
$decorator = "Block";
$reflower = "Block";
break;
case "inline-block":
$positioner = "Inline";
$decorator = "Block";
$reflower = "Block";
break;
case "inline":
$positioner = "Inline";
if ( $frame->is_text_node() ) {
$decorator = "Text";
$reflower = "Text";
}
else {
$enable_css_float = $dompdf->get_option("enable_css_float");
if ( $enable_css_float && $style->float !== "none" ) {
$decorator = "Block";
$reflower = "Block";
}
else {
$decorator = "Inline";
$reflower = "Inline";
}
}
break;
case "table":
$positioner = "Block";
$decorator = "Table";
$reflower = "Table";
break;
case "inline-table":
$positioner = "Inline";
$decorator = "Table";
$reflower = "Table";
break;
case "table-row-group":
case "table-header-group":
case "table-footer-group":
$positioner = "Null";
$decorator = "Table_Row_Group";
$reflower = "Table_Row_Group";
break;
case "table-row":
$positioner = "Null";
$decorator = "Table_Row";
$reflower = "Table_Row";
break;
case "table-cell":
$positioner = "Table_Cell";
$decorator = "Table_Cell";
$reflower = "Table_Cell";
break;
case "list-item":
$positioner = "Block";
$decorator = "Block";
$reflower = "Block";
break;
case "-dompdf-list-bullet":
if ( $style->list_style_position === "inside" ) {
$positioner = "Inline";
}
else {
$positioner = "List_Bullet";
}
if ( $style->list_style_image !== "none" ) {
$decorator = "List_Bullet_Image";
}
else {
$decorator = "List_Bullet";
}
$reflower = "List_Bullet";
break;
case "-dompdf-image":
$positioner = "Inline";
$decorator = "Image";
$reflower = "Image";
break;
case "-dompdf-br":
$positioner = "Inline";
$decorator = "Inline";
$reflower = "Inline";
break;
default:
// FIXME: should throw some sort of warning or something?
case "none":
if ( $style->_dompdf_keep !== "yes" ) {
// Remove the node and the frame
$frame->get_parent()->remove_child($frame);
return;
}
$positioner = "Null";
$decorator = "Null";
$reflower = "Null";
break;
}
// Handle CSS position
$position = $style->position;
if ( $position === "absolute" ) {
$positioner = "Absolute";
}
else if ( $position === "fixed" ) {
$positioner = "Fixed";
}
$node = $frame->get_node();
// Handle nodeName
if ( $node->nodeName === "img" ) {
$style->display = "-dompdf-image";
$decorator = "Image";
$reflower = "Image";
}
$positioner .= "_Positioner";
$decorator .= "_Frame_Decorator";
$reflower .= "_Frame_Reflower";
$deco = new $decorator($frame, $dompdf);
$deco->set_positioner( new $positioner($deco) );
$deco->set_reflower( new $reflower($deco) );
if ( $root ) {
$deco->set_root($root);
}
if ( $display === "list-item" ) {
// Insert a list-bullet frame
$xml = $dompdf->get_dom();
$bullet_node = $xml->createElement("bullet"); // arbitrary choice
$b_f = new Frame($bullet_node);
$node = $frame->get_node();
$parent_node = $node->parentNode;
if ( $parent_node ) {
if ( !$parent_node->hasAttribute("dompdf-children-count") ) {
$xpath = new DOMXPath($xml);
$count = $xpath->query("li", $parent_node)->length;
$parent_node->setAttribute("dompdf-children-count", $count);
}
if ( is_numeric($node->getAttribute("value")) ) {
$index = intval($node->getAttribute("value"));
}
else {
if ( !$parent_node->hasAttribute("dompdf-counter") ) {
$index = ($parent_node->hasAttribute("start") ? $parent_node->getAttribute("start") : 1);
}
else {
$index = $parent_node->getAttribute("dompdf-counter")+1;
}
}
$parent_node->setAttribute("dompdf-counter", $index);
$bullet_node->setAttribute("dompdf-counter", $index);
}
$new_style = $dompdf->get_css()->create_style();
$new_style->display = "-dompdf-list-bullet";
$new_style->inherit($style);
$b_f->set_style($new_style);
$deco->prepend_child( Frame_Factory::decorate_frame($b_f, $dompdf, $root) );
}
return $deco;
}
}
<?php
/**
* @package dompdf
* @link http://dompdf.github.com/
* @author Benj Carson <benjcarson@digitaljunkies.ca>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
/**
* Represents an entire document as a tree of frames
*
* The Frame_Tree consists of {@link Frame} objects each tied to specific
* DOMNode objects in a specific DomDocument. The Frame_Tree has the same
* structure as the DomDocument, but adds additional capabalities for
* styling and layout.
*
* @package dompdf
* @access protected
*/
class Frame_Tree {
/**
* Tags to ignore while parsing the tree
*
* @var array
*/
static protected $_HIDDEN_TAGS = array("area", "base", "basefont", "head", "style",
"meta", "title", "colgroup",
"noembed", "noscript", "param", "#comment");
/**
* The main DomDocument
*
* @see http://ca2.php.net/manual/en/ref.dom.php
* @var DomDocument
*/
protected $_dom;
/**
* The root node of the FrameTree.
*
* @var Frame
*/
protected $_root;
/**
* Subtrees of absolutely positioned elements
*
* @var array of Frames
*/
protected $_absolute_frames;
/**
* A mapping of {@link Frame} objects to DOMNode objects
*
* @var array
*/
protected $_registry;
/**
* Class constructor
*
* @param DomDocument $dom the main DomDocument object representing the current html document
*/
function __construct(DomDocument $dom) {
$this->_dom = $dom;
$this->_root = null;
$this->_registry = array();
}
function __destruct() {
clear_object($this);
}
/**
* Returns the DomDocument object representing the curent html document
*
* @return DOMDocument
*/
function get_dom() {
return $this->_dom;
}
/**
* Returns the root frame of the tree
*
* @return Page_Frame_Decorator
*/
function get_root() {
return $this->_root;
}
/**
* Returns a specific frame given its id
*
* @param string $id
* @return Frame
*/
function get_frame($id) {
return isset($this->_registry[$id]) ? $this->_registry[$id] : null;
}
/**
* Returns a post-order iterator for all frames in the tree
*
* @return FrameTreeList|Frame[]
*/
function get_frames() {
return new FrameTreeList($this->_root);
}
/**
* Builds the tree
*/
function build_tree() {
$html = $this->_dom->getElementsByTagName("html")->item(0);
if ( is_null($html) ) {
$html = $this->_dom->firstChild;
}
if ( is_null($html) ) {
throw new DOMPDF_Exception("Requested HTML document contains no data.");
}
$this->fix_tables();
$this->_root = $this->_build_tree_r($html);
}
/**
* Adds missing TBODYs around TR
*/
protected function fix_tables(){
$xp = new DOMXPath($this->_dom);
// Move table caption before the table
// FIXME find a better way to deal with it...
$captions = $xp->query("//table/caption");
foreach($captions as $caption) {
$table = $caption->parentNode;
$table->parentNode->insertBefore($caption, $table);
}
$rows = $xp->query("//table/tr");
foreach($rows as $row) {
$tbody = $this->_dom->createElement("tbody");
$tbody = $row->parentNode->insertBefore($tbody, $row);
$tbody->appendChild($row);
}
}
/**
* Recursively adds {@link Frame} objects to the tree
*
* Recursively build a tree of Frame objects based on a dom tree.
* No layout information is calculated at this time, although the
* tree may be adjusted (i.e. nodes and frames for generated content
* and images may be created).
*
* @param DOMNode $node the current DOMNode being considered
* @return Frame
*/
protected function _build_tree_r(DOMNode $node) {
$frame = new Frame($node);
$id = $frame->get_id();
$this->_registry[ $id ] = $frame;
if ( !$node->hasChildNodes() ) {
return $frame;
}
// Fixes 'cannot access undefined property for object with
// overloaded access', fix by Stefan radulian
// <stefan.radulian@symbion.at>
//foreach ($node->childNodes as $child) {
// Store the children in an array so that the tree can be modified
$children = array();
for ($i = 0; $i < $node->childNodes->length; $i++) {
$children[] = $node->childNodes->item($i);
}
foreach ($children as $child) {
$node_name = mb_strtolower($child->nodeName);
// Skip non-displaying nodes
if ( in_array($node_name, self::$_HIDDEN_TAGS) ) {
if ( $node_name !== "head" && $node_name !== "style" ) {
$child->parentNode->removeChild($child);
}
continue;
}
// Skip empty text nodes
if ( $node_name === "#text" && $child->nodeValue == "" ) {
$child->parentNode->removeChild($child);
continue;
}
// Skip empty image nodes
if ( $node_name === "img" && $child->getAttribute("src") == "" ) {
$child->parentNode->removeChild($child);
continue;
}
$frame->append_child($this->_build_tree_r($child), false);
}
return $frame;
}
public function insert_node(DOMNode $node, DOMNode $new_node, $pos) {
if ( $pos === "after" || !$node->firstChild ) {
$node->appendChild($new_node);
}
else {
$node->insertBefore($new_node, $node->firstChild);
}
$this->_build_tree_r($new_node);
$frame_id = $new_node->getAttribute("frame_id");
$frame = $this->get_frame($frame_id);
$parent_id = $node->getAttribute("frame_id");
$parent = $this->get_frame($parent_id);
if ( $parent ) {
if ( $pos === "before" ) {
$parent->prepend_child($frame, false);
}
else {
$parent->append_child($frame, false);
}
}
return $frame_id;
}
}
<?php
/**
* @package dompdf
* @link http://dompdf.github.com/
* @author Benj Carson <benjcarson@digitaljunkies.ca>
* @author Helmut Tischer <htischer@weihenstephan.org>
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
/**
* Static class that resolves image urls and downloads and caches
* remote images if required.
*
* @access private
* @package dompdf
*/
class Image_Cache {
/**
* Array of downloaded images. Cached so that identical images are
* not needlessly downloaded.
*
* @var array
*/
static protected $_cache = array();
/**
* The url to the "broken image" used when images can't be loade
*
* @var string
*/
public static $broken_image;
/**
* Resolve and fetch an image for use.
*
* @param string $url The url of the image
* @param string $protocol Default protocol if none specified in $url
* @param string $host Default host if none specified in $url
* @param string $base_path Default path if none specified in $url
* @param DOMPDF $dompdf The DOMPDF instance
*
* @throws DOMPDF_Image_Exception
* @return array An array with two elements: The local path to the image and the image extension
*/
static function resolve_url($url, $protocol, $host, $base_path, DOMPDF $dompdf) {
$protocol = mb_strtolower($protocol);
$parsed_url = explode_url($url);
$message = null;
$remote = ($protocol && $protocol !== "file://") || ($parsed_url['protocol'] != "");
$data_uri = strpos($parsed_url['protocol'], "data:") === 0;
$full_url = null;
$enable_remote = $dompdf->get_option("enable_remote");
try {
// Remote not allowed and is not DataURI
if ( !$enable_remote && $remote && !$data_uri ) {
throw new DOMPDF_Image_Exception("DOMPDF_ENABLE_REMOTE is set to FALSE");
}
// Remote allowed or DataURI
else if ( $enable_remote && $remote || $data_uri ) {
// Download remote files to a temporary directory
$full_url = build_url($protocol, $host, $base_path, $url);
// From cache
if ( isset(self::$_cache[$full_url]) ) {
$resolved_url = self::$_cache[$full_url];
}
// From remote
else {
$tmp_dir = $dompdf->get_option("temp_dir");
$resolved_url = tempnam($tmp_dir, "ca_dompdf_img_");
$image = "";
if ($data_uri) {
if ($parsed_data_uri = parse_data_uri($url)) {
$image = $parsed_data_uri['data'];
}
}
else {
set_error_handler("record_warnings");
$image = file_get_contents($full_url, null, $dompdf->get_http_context());
restore_error_handler();
}
// Image not found or invalid
if ( strlen($image) == 0 ) {
$msg = ($data_uri ? "Data-URI could not be parsed" : "Image not found");
throw new DOMPDF_Image_Exception($msg);
}
// Image found, put in cache and process
else {
//e.g. fetch.php?media=url.jpg&cache=1
//- Image file name might be one of the dynamic parts of the url, don't strip off!
//- a remote url does not need to have a file extension at all
//- local cached file does not have a matching file extension
//Therefore get image type from the content
file_put_contents($resolved_url, $image);
}
}
}
// Not remote, local image
else {
$resolved_url = build_url($protocol, $host, $base_path, $url);
}
// Check if the local file is readable
if ( !is_readable($resolved_url) || !filesize($resolved_url) ) {
throw new DOMPDF_Image_Exception("Image not readable or empty");
}
// Check is the file is an image
else {
list($width, $height, $type) = dompdf_getimagesize($resolved_url, $dompdf->get_http_context());
// Known image type
if ( $width && $height && in_array($type, array(IMAGETYPE_GIF, IMAGETYPE_PNG, IMAGETYPE_JPEG, IMAGETYPE_BMP)) ) {
//Don't put replacement image into cache - otherwise it will be deleted on cache cleanup.
//Only execute on successful caching of remote image.
if ( $enable_remote && $remote || $data_uri ) {
self::$_cache[$full_url] = $resolved_url;
}
}
// Unknown image type
else {
throw new DOMPDF_Image_Exception("Image type unknown");
}
}
}
catch(DOMPDF_Image_Exception $e) {
$resolved_url = self::$broken_image;
$type = IMAGETYPE_PNG;
$message = "Image not found or type unknown";
$_dompdf_warnings[] = $e->getMessage()." :: $url";
}
return array($resolved_url, $type, $message);
}
/**
* Unlink all cached images (i.e. temporary images either downloaded
* or converted)
*/
static function clear() {
if ( empty(self::$_cache) || DEBUGKEEPTEMP ) return;
foreach ( self::$_cache as $file ) {
if (DEBUGPNG) print "[clear unlink $file]";
unlink($file);
}
self::$_cache = array();
}
static function detect_type($file, $context = null) {
list(, , $type) = dompdf_getimagesize($file, $context);
return $type;
}
static function type_to_ext($type) {
$image_types = array(
IMAGETYPE_GIF => "gif",
IMAGETYPE_PNG => "png",
IMAGETYPE_JPEG => "jpeg",
IMAGETYPE_BMP => "bmp",
);
return (isset($image_types[$type]) ? $image_types[$type] : null);
}
static function is_broken($url) {
return $url === self::$broken_image;
}
}
Image_Cache::$broken_image = DOMPDF_LIB_DIR . "/res/broken_image.png";
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
No preview for this file type
No preview for this file type
This diff could not be displayed because it is too large.
No preview for this file type
No preview for this file type
No preview for this file type
This diff could not be displayed because it is too large.
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 sign in to comment