adding biometric device
This commit is contained in:
parent
79a5056e8e
commit
040f45e79d
87
api/iclock/cdata
Normal file
87
api/iclock/cdata
Normal file
@ -0,0 +1,87 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../../db/config.php';
|
||||
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
|
||||
if ($method === 'GET') {
|
||||
$sn = $_GET['SN'] ?? '';
|
||||
if (empty($sn)) {
|
||||
http_response_code(400);
|
||||
exit('Error: SN missing');
|
||||
}
|
||||
|
||||
// Respond to device init
|
||||
echo "GET OPTION FROM: {$sn}\n";
|
||||
echo "Stamp=9999\n";
|
||||
echo "OpStamp=9999\n";
|
||||
echo "ErrorDelay=60\n";
|
||||
echo "Delay=30\n";
|
||||
echo "TransTimes=00:00;14:00\n";
|
||||
echo "TransInterval=1\n";
|
||||
echo "TransFlag=1111000000\n";
|
||||
echo "TimeZone=74\n"; // local timezone config
|
||||
echo "Realtime=1\n";
|
||||
echo "Encrypt=0\n";
|
||||
exit;
|
||||
} elseif ($method === 'POST') {
|
||||
$sn = $_GET['SN'] ?? '';
|
||||
$table = $_GET['table'] ?? '';
|
||||
|
||||
if ($table === 'ATTLOG') {
|
||||
$body = file_get_contents('php://input');
|
||||
$lines = explode("\n", trim($body));
|
||||
|
||||
$empStmt = db()->query("SELECT id, zkteco_uid FROM hr_employees WHERE zkteco_uid IS NOT NULL AND zkteco_uid != '' AND status = 'active'");
|
||||
$empMap = [];
|
||||
while ($emp = $empStmt->fetch()) {
|
||||
$empMap[(string)$emp['zkteco_uid']] = $emp['id'];
|
||||
}
|
||||
|
||||
$insertedCount = 0;
|
||||
foreach ($lines as $line) {
|
||||
$line = trim($line);
|
||||
if (empty($line)) continue;
|
||||
|
||||
$parts = explode("\t", $line);
|
||||
if (count($parts) >= 2) {
|
||||
$uid = trim($parts[0]);
|
||||
$datetime = trim($parts[1]);
|
||||
|
||||
if (strlen($datetime) >= 19 && isset($empMap[$uid])) {
|
||||
$emp_id = $empMap[$uid];
|
||||
$date = substr($datetime, 0, 10);
|
||||
$time = substr($datetime, 11, 8);
|
||||
|
||||
$chkStmt = db()->prepare("SELECT id, check_in, check_out FROM hr_attendance WHERE employee_id = ? AND date = ?");
|
||||
$chkStmt->execute([$emp_id, $date]);
|
||||
$existing = $chkStmt->fetch();
|
||||
|
||||
if ($existing) {
|
||||
$upd_in = $existing['check_in'];
|
||||
$upd_out = $existing['check_out'];
|
||||
$changed = false;
|
||||
|
||||
if (empty($upd_in) || $time < $upd_in) { $upd_in = $time; $changed = true; }
|
||||
if ($time > $upd_in && (empty($upd_out) || $time > $upd_out)) { $upd_out = $time; $changed = true; }
|
||||
|
||||
if ($changed) {
|
||||
$uStmt = db()->prepare("UPDATE hr_attendance SET check_in = ?, check_out = ?, status = 'present' WHERE id = ?");
|
||||
$uStmt->execute([$upd_in, $upd_out, $existing['id']]);
|
||||
}
|
||||
} else {
|
||||
$iStmt = db()->prepare("INSERT INTO hr_attendance (employee_id, date, check_in, status) VALUES (?, ?, ?, 'present')");
|
||||
$iStmt->execute([$emp_id, $date, $time]);
|
||||
}
|
||||
$insertedCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo "OK: " . $insertedCount;
|
||||
exit;
|
||||
} else {
|
||||
// Acknowledge OPERLOG or other tables to keep device happy
|
||||
echo "OK";
|
||||
exit;
|
||||
}
|
||||
}
|
||||
4
api/iclock/devicecmd
Normal file
4
api/iclock/devicecmd
Normal file
@ -0,0 +1,4 @@
|
||||
<?php
|
||||
// ZKTeco devices return the result of executing commands here.
|
||||
// We just acknowledge.
|
||||
echo "OK";
|
||||
4
api/iclock/getrequest
Normal file
4
api/iclock/getrequest
Normal file
@ -0,0 +1,4 @@
|
||||
<?php
|
||||
// ZKTeco devices call this to ask the server if there are any pending commands.
|
||||
// We just return OK so it doesn't get stuck.
|
||||
echo "OK";
|
||||
1788
composer-setup.php
Normal file
1788
composer-setup.php
Normal file
File diff suppressed because it is too large
Load Diff
5
composer.json
Normal file
5
composer.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"require": {
|
||||
"rats/zkteco": "^002.0"
|
||||
}
|
||||
}
|
||||
56
composer.lock
generated
Normal file
56
composer.lock
generated
Normal file
@ -0,0 +1,56 @@
|
||||
{
|
||||
"_readme": [
|
||||
"This file locks the dependencies of your project to a known state",
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "b0f94fedb2e61e4b370f9be3a60b2340",
|
||||
"packages": [
|
||||
{
|
||||
"name": "rats/zkteco",
|
||||
"version": "V002",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/raihanafroz/zkteco.git",
|
||||
"reference": "6e17024370ec56c89d87c85a54a1c55079304834"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/raihanafroz/zkteco/zipball/6e17024370ec56c89d87c85a54a1c55079304834",
|
||||
"reference": "6e17024370ec56c89d87c85a54a1c55079304834",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Rats\\Zkteco\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Raihan Afroz",
|
||||
"email": "raihanafroz9@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "ZKTeco Laravel Library",
|
||||
"support": {
|
||||
"issues": "https://github.com/raihanafroz/zkteco/issues",
|
||||
"source": "https://github.com/raihanafroz/zkteco/tree/V002"
|
||||
},
|
||||
"time": "2021-11-21T17:53:28+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": {},
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": {},
|
||||
"platform-dev": {},
|
||||
"plugin-api-version": "2.9.0"
|
||||
}
|
||||
BIN
composer.phar
Executable file
BIN
composer.phar
Executable file
Binary file not shown.
12
db/migrations/029_add_zkteco_integration.sql
Normal file
12
db/migrations/029_add_zkteco_integration.sql
Normal file
@ -0,0 +1,12 @@
|
||||
CREATE TABLE IF NOT EXISTS hr_zkteco_settings (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
ip_address VARCHAR(100) NOT NULL,
|
||||
port INT DEFAULT 4370,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
INSERT INTO hr_zkteco_settings (ip_address, port)
|
||||
SELECT '192.168.1.201', 4370
|
||||
WHERE NOT EXISTS (SELECT 1 FROM hr_zkteco_settings);
|
||||
|
||||
ALTER TABLE hr_employees ADD COLUMN zkteco_uid VARCHAR(50) NULL DEFAULT NULL AFTER id;
|
||||
@ -71,7 +71,7 @@ $records = $stmt->fetchAll();
|
||||
?>
|
||||
|
||||
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
|
||||
<h1 class="h2">سجل الحضور والانصراف</h1>
|
||||
<h1 class="h2">سجل الحضور والانصراف <a href="hr_zkteco.php" class="btn btn-sm btn-outline-info ms-3"><i class="fas fa-fingerprint me-1"></i> ربط البصمة ZKTeco</a></h1>
|
||||
<div class="btn-toolbar mb-2 mb-md-0">
|
||||
<form class="d-flex gap-2 align-items-center" method="get">
|
||||
<label class="col-form-label">التاريخ:</label>
|
||||
|
||||
@ -19,7 +19,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$error = "لا تملك صلاحية التعديل.";
|
||||
} else {
|
||||
$id = !empty($_POST['id']) ? $_POST['id'] : null;
|
||||
$first_name = trim($_POST['first_name']);
|
||||
$first_name = trim($_POST["first_name"]);
|
||||
$zkteco_uid = !empty($_POST["zkteco_uid"]) ? trim($_POST["zkteco_uid"]) : null;
|
||||
$last_name = trim($_POST['last_name']);
|
||||
$email = trim($_POST['email']);
|
||||
$phone = trim($_POST['phone']);
|
||||
@ -37,13 +38,13 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
try {
|
||||
if ($id) {
|
||||
// Update
|
||||
$stmt = db()->prepare("UPDATE hr_employees SET first_name=?, last_name=?, email=?, phone=?, department_id=?, job_title=?, basic_salary=?, join_date=?, status=?, gender=?, birth_date=? WHERE id=?");
|
||||
$stmt->execute([$first_name, $last_name, $email, $phone, $department_id, $job_title, $basic_salary, $join_date, $status, $gender, $birth_date, $id]);
|
||||
$stmt = db()->prepare("UPDATE hr_employees SET first_name=?, last_name=?, email=?, phone=?, department_id=?, job_title=?, basic_salary=?, join_date=?, status=?, gender=?, birth_date=?, zkteco_uid=? WHERE id=?");
|
||||
$stmt->execute([$first_name, $last_name, $email, $phone, $department_id, $job_title, $basic_salary, $join_date, $status, $gender, $birth_date, $zkteco_uid, $id]);
|
||||
$success = "تم تحديث بيانات الموظف بنجاح.";
|
||||
} else {
|
||||
// Insert
|
||||
$stmt = db()->prepare("INSERT INTO hr_employees (first_name, last_name, email, phone, department_id, job_title, basic_salary, join_date, status, gender, birth_date) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
||||
$stmt->execute([$first_name, $last_name, $email, $phone, $department_id, $job_title, $basic_salary, $join_date, $status, $gender, $birth_date]);
|
||||
$stmt = db()->prepare("INSERT INTO hr_employees (first_name, last_name, email, phone, department_id, job_title, basic_salary, join_date, status, gender, birth_date, zkteco_uid) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
||||
$stmt->execute([$first_name, $last_name, $email, $phone, $department_id, $job_title, $basic_salary, $join_date, $status, $gender, $birth_date, $zkteco_uid]);
|
||||
$success = "تم إضافة الموظف بنجاح.";
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
@ -207,7 +208,10 @@ $pagination = getPagination($page, $totalEmployees, $perPage);
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">الراتب الأساسي</label>
|
||||
<input type="number" step="0.01" name="basic_salary" id="empSalary" class="form-control">
|
||||
<input type="number" step="0.01" name="basic_salary" id="empSalary" class="form-control"></div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">ZKTeco UID</label>
|
||||
<input type="text" name="zkteco_uid" id="empZktecoUid" class="form-control">
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
@ -242,6 +246,7 @@ $pagination = getPagination($page, $totalEmployees, $perPage);
|
||||
<th>المسمى الوظيفي</th>
|
||||
<th>تاريخ التعيين</th>
|
||||
<th>الحالة</th>
|
||||
<th>بصمة (UID)</th>
|
||||
<th>الإجراءات</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -286,6 +291,7 @@ $pagination = getPagination($page, $totalEmployees, $perPage);
|
||||
?>
|
||||
<span class="badge bg-<?= $status_cls ?>"><?= htmlspecialchars($row['status']) ?></span>
|
||||
</td>
|
||||
<td><span class="badge bg-light text-dark border"><?= htmlspecialchars($row['zkteco_uid'] ?: '-') ?></span></td>
|
||||
<td>
|
||||
<div class="btn-group">
|
||||
<?php if (canEdit('hr_employees')): ?>
|
||||
@ -346,7 +352,8 @@ $pagination = getPagination($page, $totalEmployees, $perPage);
|
||||
document.getElementById('empDept').value = btn.dataset.dept;
|
||||
document.getElementById('empJobTitle').value = btn.dataset.job;
|
||||
document.getElementById('empJoinDate').value = btn.dataset.join;
|
||||
document.getElementById('empSalary').value = btn.dataset.salary;
|
||||
document.getElementById("empSalary").value = btn.dataset.salary;
|
||||
document.getElementById("empZktecoUid").value = btn.dataset.zkteco;
|
||||
document.getElementById('empStatus').value = btn.dataset.status;
|
||||
}
|
||||
</script>
|
||||
|
||||
283
hr_zkteco.php
Normal file
283
hr_zkteco.php
Normal file
@ -0,0 +1,283 @@
|
||||
<?php
|
||||
require_once 'includes/header.php';
|
||||
require 'vendor/autoload.php';
|
||||
|
||||
use Rats\Zkteco\Lib\ZKTeco;
|
||||
|
||||
if (!isAdmin()) {
|
||||
echo "<div class='alert alert-danger'>ليس لديك صلاحية للوصول إلى هذه الصفحة.</div>";
|
||||
require_once 'includes/footer.php';
|
||||
exit;
|
||||
}
|
||||
|
||||
$error = '';
|
||||
$success = '';
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if (isset($_POST['save_settings'])) {
|
||||
$ip = trim($_POST['ip_address']);
|
||||
$port = (int)$_POST['port'];
|
||||
if ($ip && $port) {
|
||||
$stmt = db()->prepare("UPDATE hr_zkteco_settings SET ip_address = ?, port = ? WHERE id = 1");
|
||||
$stmt->execute([$ip, $port]);
|
||||
$success = "تم حفظ الإعدادات بنجاح.";
|
||||
} else {
|
||||
$error = "يرجى تعبئة الحقول المطلوبة.";
|
||||
}
|
||||
}
|
||||
|
||||
$stmt = db()->query("SELECT * FROM hr_zkteco_settings LIMIT 1");
|
||||
$settings = $stmt->fetch();
|
||||
$ip = $settings['ip_address'] ?? '192.168.1.201';
|
||||
$port = $settings['port'] ?? 4370;
|
||||
|
||||
if (isset($_POST['test_connection'])) {
|
||||
try {
|
||||
$zk = new ZKTeco($ip, $port);
|
||||
if ($zk->connect()) {
|
||||
$success = "تم الاتصال بالجهاز بنجاح (الإصدار: " . htmlspecialchars($zk->version() ?? 'غير معروف') . ")";
|
||||
$zk->disconnect();
|
||||
} else {
|
||||
$error = "فشل الاتصال بالجهاز. يرجى التأكد من أن الجهاز على نفس الشبكة والمنفذ مفتوح (عادة 4370).";
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$error = "خطأ أثناء الاتصال: " . $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_POST['sync_logs'])) {
|
||||
try {
|
||||
$zk = new ZKTeco($ip, $port);
|
||||
if ($zk->connect()) {
|
||||
$attendance = $zk->getAttendance();
|
||||
|
||||
$empStmt = db()->query("SELECT id, zkteco_uid FROM hr_employees WHERE zkteco_uid IS NOT NULL AND zkteco_uid != '' AND status = 'active'");
|
||||
$empMap = [];
|
||||
while ($emp = $empStmt->fetch()) {
|
||||
$empMap[(string)$emp['zkteco_uid']] = $emp['id'];
|
||||
}
|
||||
|
||||
$syncedCount = 0;
|
||||
if (is_array($attendance)) {
|
||||
$attData = [];
|
||||
foreach ($attendance as $att) {
|
||||
$uid = (string)$att['id'];
|
||||
if (isset($empMap[$uid])) {
|
||||
$emp_id = $empMap[$uid];
|
||||
$timeStr = $att['timestamp'];
|
||||
$date = date('Y-m-d', strtotime($timeStr));
|
||||
$time = date('H:i:s', strtotime($timeStr));
|
||||
|
||||
if (!isset($attData[$emp_id][$date])) {
|
||||
$attData[$emp_id][$date] = ['min' => $time, 'max' => $time];
|
||||
} else {
|
||||
if ($time < $attData[$emp_id][$date]['min']) $attData[$emp_id][$date]['min'] = $time;
|
||||
if ($time > $attData[$emp_id][$date]['max']) $attData[$emp_id][$date]['max'] = $time;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($attData as $emp_id => $dates) {
|
||||
foreach ($dates as $date => $times) {
|
||||
$check_in = $times['min'];
|
||||
$check_out = ($times['max'] != $times['min']) ? $times['max'] : null;
|
||||
|
||||
$chkStmt = db()->prepare("SELECT id, check_in, check_out FROM hr_attendance WHERE employee_id = ? AND date = ?");
|
||||
$chkStmt->execute([$emp_id, $date]);
|
||||
$existing = $chkStmt->fetch();
|
||||
|
||||
if ($existing) {
|
||||
$upd_in = $existing['check_in'];
|
||||
$upd_out = $existing['check_out'];
|
||||
$changed = false;
|
||||
|
||||
if (empty($upd_in) || $check_in < $upd_in) { $upd_in = $check_in; $changed = true; }
|
||||
if ($check_out && (empty($upd_out) || $check_out > $upd_out)) { $upd_out = $check_out; $changed = true; }
|
||||
|
||||
if ($changed) {
|
||||
$uStmt = db()->prepare("UPDATE hr_attendance SET check_in = ?, check_out = ?, status = 'present' WHERE id = ?");
|
||||
$uStmt->execute([$upd_in, $upd_out, $existing['id']]);
|
||||
$syncedCount++;
|
||||
}
|
||||
} else {
|
||||
$iStmt = db()->prepare("INSERT INTO hr_attendance (employee_id, date, check_in, check_out, status) VALUES (?, ?, ?, ?, 'present')");
|
||||
$iStmt->execute([$emp_id, $date, $check_in, $check_out]);
|
||||
$syncedCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$zk->disconnect();
|
||||
if ($syncedCount > 0) {
|
||||
$success = "تم مزامنة $syncedCount سجل حضور (تحديث / إنشاء) بنجاح.";
|
||||
} else {
|
||||
$success = "تم الاتصال بنجاح ولكن لم يتم العثور على سجلات جديدة للموظفين المعرفين.";
|
||||
}
|
||||
|
||||
} else {
|
||||
$error = "فشل الاتصال بالجهاز.";
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$error = "حدث خطأ أثناء المزامنة: " . $e->getMessage();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$stmt = db()->query("SELECT * FROM hr_zkteco_settings LIMIT 1");
|
||||
$settings = $stmt->fetch();
|
||||
$ip = $settings['ip_address'] ?? '192.168.1.201';
|
||||
$port = $settings['port'] ?? 4370;
|
||||
}
|
||||
?>
|
||||
|
||||
<div class="container-fluid py-4">
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-8">
|
||||
<h2 class="h3 mb-0 text-gray-800">ربط جهاز البصمة ZKTeco</h2>
|
||||
<p class="text-muted">اختر طريقة الربط المناسبة للشبكة الخاصة بك لسحب سجلات الحضور.</p>
|
||||
</div>
|
||||
<div class="col-md-4 text-end">
|
||||
<a href="hr_attendance.php" class="btn btn-secondary"><i class="fas fa-arrow-left"></i> العودة لسجل الحضور</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if ($error): ?>
|
||||
<div class="alert alert-danger shadow-sm border-0 border-start border-danger border-4 alert-dismissible fade show" role="alert">
|
||||
<i class="fas fa-exclamation-circle me-2"></i> <?= htmlspecialchars($error) ?>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($success): ?>
|
||||
<div class="alert alert-success shadow-sm border-0 border-start border-success border-4 alert-dismissible fade show" role="alert">
|
||||
<i class="fas fa-check-circle me-2"></i> <?= htmlspecialchars($success) ?>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Nav tabs -->
|
||||
<ul class="nav nav-tabs mb-4" id="zktecoTabs" role="tablist">
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link active fw-bold text-dark" id="pull-tab" data-bs-toggle="tab" data-bs-target="#pull" type="button" role="tab" aria-controls="pull" aria-selected="true">
|
||||
<i class="fas fa-network-wired me-1 text-primary"></i> الطريقة 1: الاتصال المباشر (TCP Pull)
|
||||
</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link fw-bold text-dark" id="push-tab" data-bs-toggle="tab" data-bs-target="#push" type="button" role="tab" aria-controls="push" aria-selected="false">
|
||||
<i class="fas fa-cloud-upload-alt me-1 text-success"></i> الطريقة 2: الدفع التلقائي (ADMS Push)
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- Tab panes -->
|
||||
<div class="tab-content" id="zktecoTabsContent">
|
||||
<!-- Tab 1: TCP Pull -->
|
||||
<div class="tab-pane fade show active" id="pull" role="tabpanel" aria-labelledby="pull-tab">
|
||||
<div class="alert alert-info border-0 border-start border-info border-4">
|
||||
<i class="fas fa-info-circle me-2"></i> هذه الطريقة تتطلب أن يكون الخادم (السيرفر) قادراً على الوصول إلى عنوان IP الخاص بالجهاز. إذا كان الجهاز في شبكة محلية مختلفة ولا يوجد IP ثابت، استخدم <strong>الطريقة 2</strong>.
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xl-6 col-lg-6 mb-4">
|
||||
<div class="card shadow-sm border-0 h-100">
|
||||
<div class="card-header bg-white pb-0 border-bottom-0">
|
||||
<h6 class="m-0 font-weight-bold text-primary"><i class="fas fa-cog me-2"></i> إعدادات الاتصال المباشر</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form method="POST" action="">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">IP Address (عنوان الجهاز)</label>
|
||||
<input type="text" class="form-control" name="ip_address" value="<?= htmlspecialchars($ip) ?>" required placeholder="مثال: 192.168.1.201">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Port (المنفذ)</label>
|
||||
<input type="number" class="form-control" name="port" value="<?= htmlspecialchars($port) ?>" required placeholder="الافتراضي: 4370">
|
||||
</div>
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-start">
|
||||
<button type="submit" name="save_settings" class="btn btn-primary"><i class="fas fa-save me-1"></i> حفظ الإعدادات</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-xl-6 col-lg-6 mb-4">
|
||||
<div class="card shadow-sm border-0 h-100">
|
||||
<div class="card-header bg-white pb-0 border-bottom-0">
|
||||
<h6 class="m-0 font-weight-bold text-info"><i class="fas fa-sync-alt me-2"></i> العمليات</h6>
|
||||
</div>
|
||||
<div class="card-body text-center py-5">
|
||||
<p class="text-muted mb-4">اختبر الاتصال أو ابدأ بسحب البيانات الان.</p>
|
||||
<form method="POST" action="">
|
||||
<div class="d-grid gap-3 col-8 mx-auto">
|
||||
<button type="submit" name="test_connection" class="btn btn-outline-info btn-lg shadow-sm">
|
||||
<i class="fas fa-wifi me-2"></i> اختبار الاتصال
|
||||
</button>
|
||||
<button type="submit" name="sync_logs" class="btn btn-success btn-lg shadow-sm">
|
||||
<i class="fas fa-download me-2"></i> مزامنة الحضور والانصراف
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tab 2: ADMS Push -->
|
||||
<div class="tab-pane fade" id="push" role="tabpanel" aria-labelledby="push-tab">
|
||||
<div class="card shadow-sm border-0 mb-4">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title text-success mb-3"><i class="fas fa-check-circle me-2"></i> النظام جاهز لاستقبال البصمات تلقائياً (ADMS/WDMS)</h5>
|
||||
<p class="card-text text-muted mb-4">من خلال هذه الطريقة، يقوم جهاز البصمة بإرسال سجلات الحضور تلقائياً إلى هذا النظام عبر الإنترنت. <strong>هذه الطريقة مثالية إذا كان جهاز البصمة في شبكة محلية بدون IP ثابت (Public IP).</strong></p>
|
||||
|
||||
<h6 class="font-weight-bold text-dark mb-3"><i class="fas fa-desktop me-2"></i> خطوات الإعداد على جهاز البصمة ZKTeco:</h6>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<ul class="list-group list-group-flush mb-4 shadow-sm rounded border">
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center py-3">
|
||||
<div class="ms-2 me-auto">
|
||||
<div class="fw-bold text-primary mb-1">1. إعدادات الشبكة (Comm.)</div>
|
||||
افتح القائمة الرئيسية للجهاز واذهب إلى <kbd>COMM.</kbd> ثم <kbd>Cloud Server Setting</kbd> أو <kbd>ADMS</kbd>.
|
||||
</div>
|
||||
<span class="badge bg-primary rounded-pill"><i class="fas fa-arrow-left"></i></span>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center py-3">
|
||||
<div class="ms-2 me-auto">
|
||||
<div class="fw-bold text-primary mb-1">2. عنوان السيرفر (Server Address)</div>
|
||||
أدخل عنوان هذا النظام أو الـ IP الخاص به.
|
||||
<br><small class="text-muted">مثال: إذا كان عنوان التطبيق <code>http://your-app.com</code> أدخل فقط <code>your-app.com</code></small>
|
||||
</div>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center py-3">
|
||||
<div class="ms-2 me-auto">
|
||||
<div class="fw-bold text-primary mb-1">3. منفذ السيرفر (Server Port)</div>
|
||||
أدخل المنفذ: <kbd>80</kbd> للاتصال العادي (أو 443 إذا كنت تستخدم HTTPS مدعوم).
|
||||
</div>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center py-3">
|
||||
<div class="ms-2 me-auto">
|
||||
<div class="fw-bold text-primary mb-1">4. تفعيل المزامنة</div>
|
||||
بمجرد الحفظ، سيبدأ الجهاز بإرسال بيانات الحضور تلقائياً إلى السيرفر. ستظهر السجلات في صفحة "سجل الحضور".
|
||||
</div>
|
||||
<span class="badge bg-success rounded-pill"><i class="fas fa-check"></i></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="alert alert-warning border-0 border-start border-warning border-4 h-100 d-flex flex-column justify-content-center">
|
||||
<div>
|
||||
<h6 class="alert-heading font-weight-bold"><i class="fas fa-exclamation-triangle me-2"></i> خطوة هامة لربط الموظفين</h6>
|
||||
<p class="mb-0 small">لكي يتم احتساب البصمات للموظف الصحيح، تأكد من الذهاب إلى <a href="hr_employees.php" class="alert-link fw-bold">قائمة الموظفين</a> وتعديل بيانات كل موظف وإضافة <strong>ZKTeco UID</strong> (رقم الموظف في جهاز البصمة).</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php require_once 'includes/footer.php'; ?>
|
||||
1
iclock.php
Normal file
1
iclock.php
Normal file
@ -0,0 +1 @@
|
||||
<?php echo $_SERVER['PATH_INFO']; ?>
|
||||
1
iclock/cdata.php
Normal file
1
iclock/cdata.php
Normal file
@ -0,0 +1 @@
|
||||
<?php echo 'cdata works'; ?>
|
||||
1
iclock/cdata/index.php
Normal file
1
iclock/cdata/index.php
Normal file
@ -0,0 +1 @@
|
||||
<?php echo 'cdata works'; ?>
|
||||
22
vendor/autoload.php
vendored
Normal file
22
vendor/autoload.php
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
// autoload.php @generated by Composer
|
||||
|
||||
if (PHP_VERSION_ID < 50600) {
|
||||
if (!headers_sent()) {
|
||||
header('HTTP/1.1 500 Internal Server Error');
|
||||
}
|
||||
$err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
|
||||
if (!ini_get('display_errors')) {
|
||||
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
||||
fwrite(STDERR, $err);
|
||||
} elseif (!headers_sent()) {
|
||||
echo $err;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException($err);
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInit6910b6f5ff1d98cde5c3ed7e3c06c3dd::getLoader();
|
||||
579
vendor/composer/ClassLoader.php
vendored
Normal file
579
vendor/composer/ClassLoader.php
vendored
Normal file
@ -0,0 +1,579 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
/**
|
||||
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
|
||||
*
|
||||
* $loader = new \Composer\Autoload\ClassLoader();
|
||||
*
|
||||
* // register classes with namespaces
|
||||
* $loader->add('Symfony\Component', __DIR__.'/component');
|
||||
* $loader->add('Symfony', __DIR__.'/framework');
|
||||
*
|
||||
* // activate the autoloader
|
||||
* $loader->register();
|
||||
*
|
||||
* // to enable searching the include path (eg. for PEAR packages)
|
||||
* $loader->setUseIncludePath(true);
|
||||
*
|
||||
* In this example, if you try to use a class in the Symfony\Component
|
||||
* namespace or one of its children (Symfony\Component\Console for instance),
|
||||
* the autoloader will first look for the class under the component/
|
||||
* directory, and it will then fallback to the framework/ directory if not
|
||||
* found before giving up.
|
||||
*
|
||||
* This class is loosely based on the Symfony UniversalClassLoader.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
* @see https://www.php-fig.org/psr/psr-0/
|
||||
* @see https://www.php-fig.org/psr/psr-4/
|
||||
*/
|
||||
class ClassLoader
|
||||
{
|
||||
/** @var \Closure(string):void */
|
||||
private static $includeFile;
|
||||
|
||||
/** @var string|null */
|
||||
private $vendorDir;
|
||||
|
||||
// PSR-4
|
||||
/**
|
||||
* @var array<string, array<string, int>>
|
||||
*/
|
||||
private $prefixLengthsPsr4 = array();
|
||||
/**
|
||||
* @var array<string, list<string>>
|
||||
*/
|
||||
private $prefixDirsPsr4 = array();
|
||||
/**
|
||||
* @var list<string>
|
||||
*/
|
||||
private $fallbackDirsPsr4 = array();
|
||||
|
||||
// PSR-0
|
||||
/**
|
||||
* List of PSR-0 prefixes
|
||||
*
|
||||
* Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
|
||||
*
|
||||
* @var array<string, array<string, list<string>>>
|
||||
*/
|
||||
private $prefixesPsr0 = array();
|
||||
/**
|
||||
* @var list<string>
|
||||
*/
|
||||
private $fallbackDirsPsr0 = array();
|
||||
|
||||
/** @var bool */
|
||||
private $useIncludePath = false;
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
private $classMap = array();
|
||||
|
||||
/** @var bool */
|
||||
private $classMapAuthoritative = false;
|
||||
|
||||
/**
|
||||
* @var array<string, bool>
|
||||
*/
|
||||
private $missingClasses = array();
|
||||
|
||||
/** @var string|null */
|
||||
private $apcuPrefix;
|
||||
|
||||
/**
|
||||
* @var array<string, self>
|
||||
*/
|
||||
private static $registeredLoaders = array();
|
||||
|
||||
/**
|
||||
* @param string|null $vendorDir
|
||||
*/
|
||||
public function __construct($vendorDir = null)
|
||||
{
|
||||
$this->vendorDir = $vendorDir;
|
||||
self::initializeIncludeClosure();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, list<string>>
|
||||
*/
|
||||
public function getPrefixes()
|
||||
{
|
||||
if (!empty($this->prefixesPsr0)) {
|
||||
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, list<string>>
|
||||
*/
|
||||
public function getPrefixesPsr4()
|
||||
{
|
||||
return $this->prefixDirsPsr4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<string>
|
||||
*/
|
||||
public function getFallbackDirs()
|
||||
{
|
||||
return $this->fallbackDirsPsr0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<string>
|
||||
*/
|
||||
public function getFallbackDirsPsr4()
|
||||
{
|
||||
return $this->fallbackDirsPsr4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, string> Array of classname => path
|
||||
*/
|
||||
public function getClassMap()
|
||||
{
|
||||
return $this->classMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, string> $classMap Class to filename map
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addClassMap(array $classMap)
|
||||
{
|
||||
if ($this->classMap) {
|
||||
$this->classMap = array_merge($this->classMap, $classMap);
|
||||
} else {
|
||||
$this->classMap = $classMap;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-0 directories for a given prefix, either
|
||||
* appending or prepending to the ones previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param list<string>|string $paths The PSR-0 root directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add($prefix, $paths, $prepend = false)
|
||||
{
|
||||
$paths = (array) $paths;
|
||||
if (!$prefix) {
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
$paths,
|
||||
$this->fallbackDirsPsr0
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
$this->fallbackDirsPsr0,
|
||||
$paths
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$first = $prefix[0];
|
||||
if (!isset($this->prefixesPsr0[$first][$prefix])) {
|
||||
$this->prefixesPsr0[$first][$prefix] = $paths;
|
||||
|
||||
return;
|
||||
}
|
||||
if ($prepend) {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
$paths,
|
||||
$this->prefixesPsr0[$first][$prefix]
|
||||
);
|
||||
} else {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
$this->prefixesPsr0[$first][$prefix],
|
||||
$paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-4 directories for a given namespace, either
|
||||
* appending or prepending to the ones previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param list<string>|string $paths The PSR-4 base directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addPsr4($prefix, $paths, $prepend = false)
|
||||
{
|
||||
$paths = (array) $paths;
|
||||
if (!$prefix) {
|
||||
// Register directories for the root namespace.
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
$paths,
|
||||
$this->fallbackDirsPsr4
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
$this->fallbackDirsPsr4,
|
||||
$paths
|
||||
);
|
||||
}
|
||||
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
|
||||
// Register directories for a new namespace.
|
||||
$length = strlen($prefix);
|
||||
if ('\\' !== $prefix[$length - 1]) {
|
||||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||
}
|
||||
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||
$this->prefixDirsPsr4[$prefix] = $paths;
|
||||
} elseif ($prepend) {
|
||||
// Prepend directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
$paths,
|
||||
$this->prefixDirsPsr4[$prefix]
|
||||
);
|
||||
} else {
|
||||
// Append directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
$this->prefixDirsPsr4[$prefix],
|
||||
$paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-0 directories for a given prefix,
|
||||
* replacing any others previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param list<string>|string $paths The PSR-0 base directories
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set($prefix, $paths)
|
||||
{
|
||||
if (!$prefix) {
|
||||
$this->fallbackDirsPsr0 = (array) $paths;
|
||||
} else {
|
||||
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-4 directories for a given namespace,
|
||||
* replacing any others previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param list<string>|string $paths The PSR-4 base directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setPsr4($prefix, $paths)
|
||||
{
|
||||
if (!$prefix) {
|
||||
$this->fallbackDirsPsr4 = (array) $paths;
|
||||
} else {
|
||||
$length = strlen($prefix);
|
||||
if ('\\' !== $prefix[$length - 1]) {
|
||||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||
}
|
||||
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns on searching the include path for class files.
|
||||
*
|
||||
* @param bool $useIncludePath
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUseIncludePath($useIncludePath)
|
||||
{
|
||||
$this->useIncludePath = $useIncludePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can be used to check if the autoloader uses the include path to check
|
||||
* for classes.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getUseIncludePath()
|
||||
{
|
||||
return $this->useIncludePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns off searching the prefix and fallback directories for classes
|
||||
* that have not been registered with the class map.
|
||||
*
|
||||
* @param bool $classMapAuthoritative
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setClassMapAuthoritative($classMapAuthoritative)
|
||||
{
|
||||
$this->classMapAuthoritative = $classMapAuthoritative;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should class lookup fail if not found in the current class map?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isClassMapAuthoritative()
|
||||
{
|
||||
return $this->classMapAuthoritative;
|
||||
}
|
||||
|
||||
/**
|
||||
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
||||
*
|
||||
* @param string|null $apcuPrefix
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setApcuPrefix($apcuPrefix)
|
||||
{
|
||||
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The APCu prefix in use, or null if APCu caching is not enabled.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getApcuPrefix()
|
||||
{
|
||||
return $this->apcuPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers this instance as an autoloader.
|
||||
*
|
||||
* @param bool $prepend Whether to prepend the autoloader or not
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register($prepend = false)
|
||||
{
|
||||
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
||||
|
||||
if (null === $this->vendorDir) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($prepend) {
|
||||
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
|
||||
} else {
|
||||
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||
self::$registeredLoaders[$this->vendorDir] = $this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters this instance as an autoloader.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unregister()
|
||||
{
|
||||
spl_autoload_unregister(array($this, 'loadClass'));
|
||||
|
||||
if (null !== $this->vendorDir) {
|
||||
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the given class or interface.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
* @return true|null True if loaded, null otherwise
|
||||
*/
|
||||
public function loadClass($class)
|
||||
{
|
||||
if ($file = $this->findFile($class)) {
|
||||
$includeFile = self::$includeFile;
|
||||
$includeFile($file);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the path to the file where the class is defined.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
*
|
||||
* @return string|false The path if found, false otherwise
|
||||
*/
|
||||
public function findFile($class)
|
||||
{
|
||||
// class map lookup
|
||||
if (isset($this->classMap[$class])) {
|
||||
return $this->classMap[$class];
|
||||
}
|
||||
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
|
||||
return false;
|
||||
}
|
||||
if (null !== $this->apcuPrefix) {
|
||||
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
|
||||
if ($hit) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
$file = $this->findFileWithExtension($class, '.php');
|
||||
|
||||
// Search for Hack files if we are running on HHVM
|
||||
if (false === $file && defined('HHVM_VERSION')) {
|
||||
$file = $this->findFileWithExtension($class, '.hh');
|
||||
}
|
||||
|
||||
if (null !== $this->apcuPrefix) {
|
||||
apcu_add($this->apcuPrefix.$class, $file);
|
||||
}
|
||||
|
||||
if (false === $file) {
|
||||
// Remember that this class does not exist.
|
||||
$this->missingClasses[$class] = true;
|
||||
}
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently registered loaders keyed by their corresponding vendor directories.
|
||||
*
|
||||
* @return array<string, self>
|
||||
*/
|
||||
public static function getRegisteredLoaders()
|
||||
{
|
||||
return self::$registeredLoaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @param string $ext
|
||||
* @return string|false
|
||||
*/
|
||||
private function findFileWithExtension($class, $ext)
|
||||
{
|
||||
// PSR-4 lookup
|
||||
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
|
||||
|
||||
$first = $class[0];
|
||||
if (isset($this->prefixLengthsPsr4[$first])) {
|
||||
$subPath = $class;
|
||||
while (false !== $lastPos = strrpos($subPath, '\\')) {
|
||||
$subPath = substr($subPath, 0, $lastPos);
|
||||
$search = $subPath . '\\';
|
||||
if (isset($this->prefixDirsPsr4[$search])) {
|
||||
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
|
||||
foreach ($this->prefixDirsPsr4[$search] as $dir) {
|
||||
if (file_exists($file = $dir . $pathEnd)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-4 fallback dirs
|
||||
foreach ($this->fallbackDirsPsr4 as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 lookup
|
||||
if (false !== $pos = strrpos($class, '\\')) {
|
||||
// namespaced class name
|
||||
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
|
||||
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
|
||||
} else {
|
||||
// PEAR-like class name
|
||||
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
|
||||
}
|
||||
|
||||
if (isset($this->prefixesPsr0[$first])) {
|
||||
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
|
||||
if (0 === strpos($class, $prefix)) {
|
||||
foreach ($dirs as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 fallback dirs
|
||||
foreach ($this->fallbackDirsPsr0 as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 include paths.
|
||||
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
private static function initializeIncludeClosure()
|
||||
{
|
||||
if (self::$includeFile !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope isolated include.
|
||||
*
|
||||
* Prevents access to $this/self from included files.
|
||||
*
|
||||
* @param string $file
|
||||
* @return void
|
||||
*/
|
||||
self::$includeFile = \Closure::bind(static function($file) {
|
||||
include $file;
|
||||
}, null, null);
|
||||
}
|
||||
}
|
||||
396
vendor/composer/InstalledVersions.php
vendored
Normal file
396
vendor/composer/InstalledVersions.php
vendored
Normal file
@ -0,0 +1,396 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer;
|
||||
|
||||
use Composer\Autoload\ClassLoader;
|
||||
use Composer\Semver\VersionParser;
|
||||
|
||||
/**
|
||||
* This class is copied in every Composer installed project and available to all
|
||||
*
|
||||
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
|
||||
*
|
||||
* To require its presence, you can require `composer-runtime-api ^2.0`
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class InstalledVersions
|
||||
{
|
||||
/**
|
||||
* @var string|null if set (by reflection by Composer), this should be set to the path where this class is being copied to
|
||||
* @internal
|
||||
*/
|
||||
private static $selfDir = null;
|
||||
|
||||
/**
|
||||
* @var mixed[]|null
|
||||
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
|
||||
*/
|
||||
private static $installed;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private static $installedIsLocalDir;
|
||||
|
||||
/**
|
||||
* @var bool|null
|
||||
*/
|
||||
private static $canGetVendors;
|
||||
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||
*/
|
||||
private static $installedByVendor = array();
|
||||
|
||||
/**
|
||||
* Returns a list of all package names which are present, either by being installed, replaced or provided
|
||||
*
|
||||
* @return string[]
|
||||
* @psalm-return list<string>
|
||||
*/
|
||||
public static function getInstalledPackages()
|
||||
{
|
||||
$packages = array();
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
$packages[] = array_keys($installed['versions']);
|
||||
}
|
||||
|
||||
if (1 === \count($packages)) {
|
||||
return $packages[0];
|
||||
}
|
||||
|
||||
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all package names with a specific type e.g. 'library'
|
||||
*
|
||||
* @param string $type
|
||||
* @return string[]
|
||||
* @psalm-return list<string>
|
||||
*/
|
||||
public static function getInstalledPackagesByType($type)
|
||||
{
|
||||
$packagesByType = array();
|
||||
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
foreach ($installed['versions'] as $name => $package) {
|
||||
if (isset($package['type']) && $package['type'] === $type) {
|
||||
$packagesByType[] = $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $packagesByType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given package is installed
|
||||
*
|
||||
* This also returns true if the package name is provided or replaced by another package
|
||||
*
|
||||
* @param string $packageName
|
||||
* @param bool $includeDevRequirements
|
||||
* @return bool
|
||||
*/
|
||||
public static function isInstalled($packageName, $includeDevRequirements = true)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (isset($installed['versions'][$packageName])) {
|
||||
return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given package satisfies a version constraint
|
||||
*
|
||||
* e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
|
||||
*
|
||||
* Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
|
||||
*
|
||||
* @param VersionParser $parser Install composer/semver to have access to this class and functionality
|
||||
* @param string $packageName
|
||||
* @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
|
||||
* @return bool
|
||||
*/
|
||||
public static function satisfies(VersionParser $parser, $packageName, $constraint)
|
||||
{
|
||||
$constraint = $parser->parseConstraints((string) $constraint);
|
||||
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
|
||||
|
||||
return $provided->matches($constraint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a version constraint representing all the range(s) which are installed for a given package
|
||||
*
|
||||
* It is easier to use this via isInstalled() with the $constraint argument if you need to check
|
||||
* whether a given version of a package is installed, and not just whether it exists
|
||||
*
|
||||
* @param string $packageName
|
||||
* @return string Version constraint usable with composer/semver
|
||||
*/
|
||||
public static function getVersionRanges($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$ranges = array();
|
||||
if (isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
|
||||
}
|
||||
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
|
||||
}
|
||||
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
|
||||
}
|
||||
if (array_key_exists('provided', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
|
||||
}
|
||||
|
||||
return implode(' || ', $ranges);
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||
*/
|
||||
public static function getVersion($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($installed['versions'][$packageName]['version'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $installed['versions'][$packageName]['version'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||
*/
|
||||
public static function getPrettyVersion($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $installed['versions'][$packageName]['pretty_version'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
|
||||
*/
|
||||
public static function getReference($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($installed['versions'][$packageName]['reference'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $installed['versions'][$packageName]['reference'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
|
||||
*/
|
||||
public static function getInstallPath($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
|
||||
*/
|
||||
public static function getRootPackage()
|
||||
{
|
||||
$installed = self::getInstalled();
|
||||
|
||||
return $installed[0]['root'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw installed.php data for custom implementations
|
||||
*
|
||||
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
|
||||
* @return array[]
|
||||
* @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
|
||||
*/
|
||||
public static function getRawData()
|
||||
{
|
||||
@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
|
||||
|
||||
if (null === self::$installed) {
|
||||
// only require the installed.php file if this file is loaded from its dumped location,
|
||||
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||
self::$installed = include __DIR__ . '/installed.php';
|
||||
} else {
|
||||
self::$installed = array();
|
||||
}
|
||||
}
|
||||
|
||||
return self::$installed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw data of all installed.php which are currently loaded for custom implementations
|
||||
*
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||
*/
|
||||
public static function getAllRawData()
|
||||
{
|
||||
return self::getInstalled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Lets you reload the static array from another file
|
||||
*
|
||||
* This is only useful for complex integrations in which a project needs to use
|
||||
* this class but then also needs to execute another project's autoloader in process,
|
||||
* and wants to ensure both projects have access to their version of installed.php.
|
||||
*
|
||||
* A typical case would be PHPUnit, where it would need to make sure it reads all
|
||||
* the data it needs from this class, then call reload() with
|
||||
* `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
|
||||
* the project in which it runs can then also use this class safely, without
|
||||
* interference between PHPUnit's dependencies and the project's dependencies.
|
||||
*
|
||||
* @param array[] $data A vendor/composer/installed.php data set
|
||||
* @return void
|
||||
*
|
||||
* @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
|
||||
*/
|
||||
public static function reload($data)
|
||||
{
|
||||
self::$installed = $data;
|
||||
self::$installedByVendor = array();
|
||||
|
||||
// when using reload, we disable the duplicate protection to ensure that self::$installed data is
|
||||
// always returned, but we cannot know whether it comes from the installed.php in __DIR__ or not,
|
||||
// so we have to assume it does not, and that may result in duplicate data being returned when listing
|
||||
// all installed packages for example
|
||||
self::$installedIsLocalDir = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private static function getSelfDir()
|
||||
{
|
||||
if (self::$selfDir === null) {
|
||||
self::$selfDir = strtr(__DIR__, '\\', '/');
|
||||
}
|
||||
|
||||
return self::$selfDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||
*/
|
||||
private static function getInstalled()
|
||||
{
|
||||
if (null === self::$canGetVendors) {
|
||||
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
|
||||
}
|
||||
|
||||
$installed = array();
|
||||
$copiedLocalDir = false;
|
||||
|
||||
if (self::$canGetVendors) {
|
||||
$selfDir = self::getSelfDir();
|
||||
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
|
||||
$vendorDir = strtr($vendorDir, '\\', '/');
|
||||
if (isset(self::$installedByVendor[$vendorDir])) {
|
||||
$installed[] = self::$installedByVendor[$vendorDir];
|
||||
} elseif (is_file($vendorDir.'/composer/installed.php')) {
|
||||
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
|
||||
$required = require $vendorDir.'/composer/installed.php';
|
||||
self::$installedByVendor[$vendorDir] = $required;
|
||||
$installed[] = $required;
|
||||
if (self::$installed === null && $vendorDir.'/composer' === $selfDir) {
|
||||
self::$installed = $required;
|
||||
self::$installedIsLocalDir = true;
|
||||
}
|
||||
}
|
||||
if (self::$installedIsLocalDir && $vendorDir.'/composer' === $selfDir) {
|
||||
$copiedLocalDir = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null === self::$installed) {
|
||||
// only require the installed.php file if this file is loaded from its dumped location,
|
||||
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
|
||||
$required = require __DIR__ . '/installed.php';
|
||||
self::$installed = $required;
|
||||
} else {
|
||||
self::$installed = array();
|
||||
}
|
||||
}
|
||||
|
||||
if (self::$installed !== array() && !$copiedLocalDir) {
|
||||
$installed[] = self::$installed;
|
||||
}
|
||||
|
||||
return $installed;
|
||||
}
|
||||
}
|
||||
21
vendor/composer/LICENSE
vendored
Normal file
21
vendor/composer/LICENSE
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
|
||||
Copyright (c) Nils Adermann, Jordi Boggiano
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
10
vendor/composer/autoload_classmap.php
vendored
Normal file
10
vendor/composer/autoload_classmap.php
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
// autoload_classmap.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
|
||||
);
|
||||
9
vendor/composer/autoload_namespaces.php
vendored
Normal file
9
vendor/composer/autoload_namespaces.php
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
// autoload_namespaces.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
);
|
||||
10
vendor/composer/autoload_psr4.php
vendored
Normal file
10
vendor/composer/autoload_psr4.php
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
// autoload_psr4.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'Rats\\Zkteco\\' => array($vendorDir . '/rats/zkteco/src'),
|
||||
);
|
||||
36
vendor/composer/autoload_real.php
vendored
Normal file
36
vendor/composer/autoload_real.php
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
// autoload_real.php @generated by Composer
|
||||
|
||||
class ComposerAutoloaderInit6910b6f5ff1d98cde5c3ed7e3c06c3dd
|
||||
{
|
||||
private static $loader;
|
||||
|
||||
public static function loadClassLoader($class)
|
||||
{
|
||||
if ('Composer\Autoload\ClassLoader' === $class) {
|
||||
require __DIR__ . '/ClassLoader.php';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Composer\Autoload\ClassLoader
|
||||
*/
|
||||
public static function getLoader()
|
||||
{
|
||||
if (null !== self::$loader) {
|
||||
return self::$loader;
|
||||
}
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInit6910b6f5ff1d98cde5c3ed7e3c06c3dd', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInit6910b6f5ff1d98cde5c3ed7e3c06c3dd', 'loadClassLoader'));
|
||||
|
||||
require __DIR__ . '/autoload_static.php';
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInit6910b6f5ff1d98cde5c3ed7e3c06c3dd::getInitializer($loader));
|
||||
|
||||
$loader->register(true);
|
||||
|
||||
return $loader;
|
||||
}
|
||||
}
|
||||
36
vendor/composer/autoload_static.php
vendored
Normal file
36
vendor/composer/autoload_static.php
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
// autoload_static.php @generated by Composer
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
class ComposerStaticInit6910b6f5ff1d98cde5c3ed7e3c06c3dd
|
||||
{
|
||||
public static $prefixLengthsPsr4 = array (
|
||||
'R' =>
|
||||
array (
|
||||
'Rats\\Zkteco\\' => 12,
|
||||
),
|
||||
);
|
||||
|
||||
public static $prefixDirsPsr4 = array (
|
||||
'Rats\\Zkteco\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/rats/zkteco/src',
|
||||
),
|
||||
);
|
||||
|
||||
public static $classMap = array (
|
||||
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
|
||||
);
|
||||
|
||||
public static function getInitializer(ClassLoader $loader)
|
||||
{
|
||||
return \Closure::bind(function () use ($loader) {
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInit6910b6f5ff1d98cde5c3ed7e3c06c3dd::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInit6910b6f5ff1d98cde5c3ed7e3c06c3dd::$prefixDirsPsr4;
|
||||
$loader->classMap = ComposerStaticInit6910b6f5ff1d98cde5c3ed7e3c06c3dd::$classMap;
|
||||
|
||||
}, null, ClassLoader::class);
|
||||
}
|
||||
}
|
||||
46
vendor/composer/installed.json
vendored
Normal file
46
vendor/composer/installed.json
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
{
|
||||
"packages": [
|
||||
{
|
||||
"name": "rats/zkteco",
|
||||
"version": "V002",
|
||||
"version_normalized": "002.0.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/raihanafroz/zkteco.git",
|
||||
"reference": "6e17024370ec56c89d87c85a54a1c55079304834"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/raihanafroz/zkteco/zipball/6e17024370ec56c89d87c85a54a1c55079304834",
|
||||
"reference": "6e17024370ec56c89d87c85a54a1c55079304834",
|
||||
"shasum": ""
|
||||
},
|
||||
"time": "2021-11-21T17:53:28+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Rats\\Zkteco\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Raihan Afroz",
|
||||
"email": "raihanafroz9@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "ZKTeco Laravel Library",
|
||||
"support": {
|
||||
"issues": "https://github.com/raihanafroz/zkteco/issues",
|
||||
"source": "https://github.com/raihanafroz/zkteco/tree/V002"
|
||||
},
|
||||
"install-path": "../rats/zkteco"
|
||||
}
|
||||
],
|
||||
"dev": true,
|
||||
"dev-package-names": []
|
||||
}
|
||||
32
vendor/composer/installed.php
vendored
Normal file
32
vendor/composer/installed.php
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
<?php return array(
|
||||
'root' => array(
|
||||
'name' => '__root__',
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'reference' => '79a5056e8ec090b0861aa5c8dc1189870f3fe8eb',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'dev' => true,
|
||||
),
|
||||
'versions' => array(
|
||||
'__root__' => array(
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'reference' => '79a5056e8ec090b0861aa5c8dc1189870f3fe8eb',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'rats/zkteco' => array(
|
||||
'pretty_version' => 'V002',
|
||||
'version' => '002.0.0.0',
|
||||
'reference' => '6e17024370ec56c89d87c85a54a1c55079304834',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../rats/zkteco',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
),
|
||||
);
|
||||
0
vendor/rats/zkteco/CHANGELOG.md
vendored
Normal file
0
vendor/rats/zkteco/CHANGELOG.md
vendored
Normal file
292
vendor/rats/zkteco/README.md
vendored
Normal file
292
vendor/rats/zkteco/README.md
vendored
Normal file
@ -0,0 +1,292 @@
|
||||
# ZKTeco - Laravel Library #
|
||||
|
||||
[](https://github.com/raihanafroz/zkteco/issues)
|
||||
[](https://github.com/raihanafroz/zkteco/network/members)
|
||||
[](https://github.com/raihanafroz/zkteco/stargazers)
|
||||
[](https://packagist.org/packages/rats/zkteco)
|
||||
[](https://packagist.org/packages/rats/zkteco)
|
||||
|
||||
|
||||
The `rats/zkteco` package provides easy to use functions to ZKTeco Device activities.
|
||||
|
||||
__Requires:__ **Laravel** >= **6.0**
|
||||
|
||||
__License:__ MIT or later
|
||||
|
||||
## Installation:
|
||||
You can install the package via composer:
|
||||
|
||||
``` bash
|
||||
composer require rats/zkteco
|
||||
```
|
||||
The package will automatically register itself.
|
||||
|
||||
You have to enable your php socket if it is not enable.
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
1. Create a object of ZKTeco class.
|
||||
|
||||
```php
|
||||
use Rats\Zkteco\Lib\ZKTeco;
|
||||
|
||||
// 1 s't parameter is string $ip Device IP Address
|
||||
// 2 nd parameter is integer $port Default: 4370
|
||||
|
||||
$zk = new ZKTeco('192.168.1.201');
|
||||
|
||||
// or you can use with port
|
||||
// $zk = new ZKTeco('192.168.1.201', 8080);
|
||||
|
||||
```
|
||||
|
||||
2. Call ZKTeco methods
|
||||
|
||||
* __Connect__
|
||||
```php
|
||||
// connect
|
||||
// this return bool
|
||||
$zk->connect();
|
||||
```
|
||||
|
||||
* __Disconnect__
|
||||
```php
|
||||
// disconnect
|
||||
// this return bool
|
||||
|
||||
$zk->disconnect();
|
||||
```
|
||||
|
||||
* __Enable Device__
|
||||
```php
|
||||
// enable
|
||||
// this return bool/mixed
|
||||
|
||||
$zk->enableDevice();
|
||||
```
|
||||
> **NOTE**: You have to call after read/write any info of Device.
|
||||
|
||||
* __Disable Device__
|
||||
```php
|
||||
// disable
|
||||
// this return bool/mixed
|
||||
|
||||
$zk->disableDevice();
|
||||
```
|
||||
> **NOTE**: You have to call before read/write any info of Device.
|
||||
|
||||
|
||||
* __Device Version__
|
||||
```php
|
||||
// get device version
|
||||
// this return bool/mixed
|
||||
|
||||
$zk->version();
|
||||
```
|
||||
|
||||
|
||||
* __Device Os Version__
|
||||
```php
|
||||
// get device os version
|
||||
// this return bool/mixed
|
||||
|
||||
$zk->osVersion();
|
||||
```
|
||||
|
||||
* __Power Off__
|
||||
```php
|
||||
// turn off the device
|
||||
// this return bool/mixed
|
||||
|
||||
$zk->shutdown();
|
||||
```
|
||||
|
||||
* __Restart__
|
||||
```php
|
||||
// restart the device
|
||||
// this return bool/mixed
|
||||
|
||||
$zk->restart();
|
||||
```
|
||||
|
||||
* __Sleep__
|
||||
```php
|
||||
// sleep the device
|
||||
// this return bool/mixed
|
||||
|
||||
$zk->sleep();
|
||||
```
|
||||
|
||||
* __Resume__
|
||||
```php
|
||||
// resume the device from sleep
|
||||
// this return bool/mixed
|
||||
|
||||
$zk->resume();
|
||||
```
|
||||
|
||||
* __Voice Test__
|
||||
```php
|
||||
// voice test of the device "Thank you"
|
||||
// this return bool/mixed
|
||||
|
||||
$zk->testVoice();
|
||||
```
|
||||
|
||||
* __Platform__
|
||||
```php
|
||||
// get platform
|
||||
// this return bool/mixed
|
||||
|
||||
$zk->platform();
|
||||
```
|
||||
|
||||
* __Firmware Version__
|
||||
```php
|
||||
// get firmware version
|
||||
// this return bool/mixed
|
||||
|
||||
$zk->fmVersion();
|
||||
```
|
||||
|
||||
* __Work Code__
|
||||
```php
|
||||
// get work code
|
||||
// this return bool/mixed
|
||||
|
||||
$zk->workCode();
|
||||
```
|
||||
|
||||
* __SSR__
|
||||
```php
|
||||
// get SSR
|
||||
// this return bool/mixed
|
||||
|
||||
$zk->ssr();
|
||||
```
|
||||
|
||||
* __Pin Width__
|
||||
```php
|
||||
// get Pin Width
|
||||
// this return bool/mixed
|
||||
|
||||
$zk->pinWidth();
|
||||
```
|
||||
|
||||
* __Serial Number__
|
||||
```php
|
||||
// get device serial number
|
||||
// this return bool/mixed
|
||||
|
||||
$zk->serialNumber();
|
||||
```
|
||||
|
||||
* __Device Name__
|
||||
```php
|
||||
// get device name
|
||||
// this return bool/mixed
|
||||
|
||||
$zk->deviceName();
|
||||
```
|
||||
|
||||
* __Get Device Time__
|
||||
```php
|
||||
// get device time
|
||||
|
||||
// return bool/mixed bool|mixed Format: "Y-m-d H:i:s"
|
||||
|
||||
$zk->getTime();
|
||||
```
|
||||
|
||||
* __Set Device Time__
|
||||
```php
|
||||
// set device time
|
||||
// parameter string $t Format: "Y-m-d H:i:s"
|
||||
// return bool/mixed
|
||||
|
||||
$zk->setTime();
|
||||
```
|
||||
|
||||
* __Get Users__
|
||||
```php
|
||||
// get User
|
||||
// this return array[]
|
||||
|
||||
$zk->getUser();
|
||||
```
|
||||
|
||||
* __Set Users__
|
||||
```php
|
||||
// set user
|
||||
|
||||
// 1 s't parameter int $uid Unique ID (max 65535)
|
||||
// 2 nd parameter int|string $userid ID in DB (same like $uid, max length = 9, only numbers - depends device setting)
|
||||
// 3 rd parameter string $name (max length = 24)
|
||||
// 4 th parameter int|string $password (max length = 8, only numbers - depends device setting)
|
||||
// 5 th parameter int $role Default Util::LEVEL_USER
|
||||
// 6 th parameter int $cardno Default 0 (max length = 10, only numbers
|
||||
|
||||
// return bool|mixed
|
||||
|
||||
$zk->setUser();
|
||||
```
|
||||
|
||||
* __Clear All Admin__
|
||||
```php
|
||||
// remove all admin
|
||||
// return bool|mixed
|
||||
|
||||
$zk->clearAdmin();
|
||||
```
|
||||
|
||||
* __Clear All Users__
|
||||
```php
|
||||
// remove all users
|
||||
// return bool|mixed
|
||||
|
||||
$zk->clearAdmin();
|
||||
```
|
||||
|
||||
* __Remove A User__
|
||||
```php
|
||||
// remove a user by $uid
|
||||
// parameter integer $uid
|
||||
// return bool|mixed
|
||||
|
||||
$zk->removeUser();
|
||||
```
|
||||
|
||||
* __Get Attendance Log__
|
||||
```php
|
||||
// get attendance log
|
||||
|
||||
// return array[]
|
||||
|
||||
// like as 0 => array:5 [▼
|
||||
// "uid" => 1 /* serial number of the attendance */
|
||||
// "id" => "1" /* user id of the application */
|
||||
// "state" => 1 /* the authentication type, 1 for Fingerprint, 4 for RF Card etc */
|
||||
// "timestamp" => "2020-05-27 21:21:06" /* time of attendance */
|
||||
// "type" => 255 /* attendance type, like check-in, check-out, overtime-in, overtime-out, break-in & break-out etc. if attendance type is none of them, it gives 255. */
|
||||
// ]
|
||||
|
||||
$zk->getAttendance();
|
||||
```
|
||||
|
||||
* __Clear Attendance Log__
|
||||
```php
|
||||
// clear attendance log
|
||||
|
||||
// return bool/mixed
|
||||
|
||||
$zk->clearAttendance();
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# end
|
||||
19
vendor/rats/zkteco/composer.json
vendored
Normal file
19
vendor/rats/zkteco/composer.json
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "rats/zkteco",
|
||||
"description": "ZKTeco Laravel Library",
|
||||
"type": "library",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Raihan Afroz",
|
||||
"email": "raihanafroz9@gmail.com"
|
||||
}
|
||||
],
|
||||
"autoload": {
|
||||
"psr-4":{
|
||||
"Rats\\Zkteco\\": "src"
|
||||
}
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"require": {}
|
||||
}
|
||||
72
vendor/rats/zkteco/src/Lib/Helper/Attendance.php
vendored
Normal file
72
vendor/rats/zkteco/src/Lib/Helper/Attendance.php
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace Rats\Zkteco\Lib\Helper;
|
||||
|
||||
use Rats\Zkteco\Lib\ZKTeco;
|
||||
|
||||
class Attendance
|
||||
{
|
||||
/**
|
||||
* @param ZKTeco $self
|
||||
* @return array [uid, id, state, timestamp]
|
||||
*/
|
||||
static public function get(ZKTeco $self)
|
||||
{
|
||||
$self->_section = __METHOD__;
|
||||
|
||||
$command = Util::CMD_ATT_LOG_RRQ;
|
||||
$command_string = '';
|
||||
|
||||
$session = $self->_command($command, $command_string, Util::COMMAND_TYPE_DATA);
|
||||
if ($session === false) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$attData = Util::recData($self);
|
||||
|
||||
$attendance = [];
|
||||
if (!empty($attData)) {
|
||||
$attData = substr($attData, 10);
|
||||
|
||||
while (strlen($attData) > 40) {
|
||||
$u = unpack('H78', substr($attData, 0, 39));
|
||||
|
||||
$u1 = hexdec(substr($u[1], 4, 2));
|
||||
$u2 = hexdec(substr($u[1], 6, 2));
|
||||
$uid = $u1 + ($u2 * 256);
|
||||
$id = hex2bin(substr($u[1], 8, 18));
|
||||
$id = str_replace(chr(0), '', $id);
|
||||
$state = hexdec(substr($u[1], 56, 2));
|
||||
$timestamp = Util::decodeTime(hexdec(Util::reverseHex(substr($u[1], 58, 8))));
|
||||
$type = hexdec(Util::reverseHex(substr($u[1], 66, 2 )));
|
||||
|
||||
$attendance[] = [
|
||||
'uid' => $uid,
|
||||
'id' => $id,
|
||||
'state' => $state,
|
||||
'timestamp' => $timestamp,
|
||||
'type' => $type
|
||||
];
|
||||
|
||||
$attData = substr($attData, 40);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $attendance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ZKTeco $self
|
||||
* @return bool|mixed
|
||||
*/
|
||||
static public function clear(ZKTeco $self)
|
||||
{
|
||||
$self->_section = __METHOD__;
|
||||
|
||||
$command = Util::CMD_CLEAR_ATT_LOG;
|
||||
$command_string = '';
|
||||
|
||||
return $self->_command($command, $command_string);
|
||||
}
|
||||
}
|
||||
83
vendor/rats/zkteco/src/Lib/Helper/Connect.php
vendored
Normal file
83
vendor/rats/zkteco/src/Lib/Helper/Connect.php
vendored
Normal file
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace Rats\Zkteco\Lib\Helper;
|
||||
|
||||
use Rats\Zkteco\Lib\Helper\Util;
|
||||
use Rats\Zkteco\Lib\ZKTeco;
|
||||
use ErrorException;
|
||||
use Exception;
|
||||
|
||||
class Connect
|
||||
{
|
||||
/**
|
||||
* @param ZKTeco $self
|
||||
* @return bool
|
||||
*/
|
||||
static public function connect(ZKTeco $self)
|
||||
{
|
||||
$self->_section = __METHOD__;
|
||||
|
||||
$command = Util::CMD_CONNECT;
|
||||
$command_string = '';
|
||||
$chksum = 0;
|
||||
$session_id = 0;
|
||||
$reply_id = -1 + Util::USHRT_MAX;
|
||||
|
||||
$buf = Util::createHeader($command, $chksum, $session_id, $reply_id, $command_string);
|
||||
|
||||
socket_sendto($self->_zkclient, $buf, strlen($buf), 0, $self->_ip, $self->_port);
|
||||
|
||||
try {
|
||||
@socket_recvfrom($self->_zkclient, $self->_data_recv, 1024, 0, $self->_ip, $self->_port);
|
||||
if (strlen($self->_data_recv) > 0) {
|
||||
$u = unpack('H2h1/H2h2/H2h3/H2h4/H2h5/H2h6', substr($self->_data_recv, 0, 8));
|
||||
|
||||
$session = hexdec($u['h6'] . $u['h5']);
|
||||
if (empty($session)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$self->_session_id = $session;
|
||||
return Util::checkValid($self->_data_recv);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} catch (ErrorException $e) {
|
||||
return false;
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ZKTeco $self
|
||||
* @return bool
|
||||
*/
|
||||
static public function disconnect(ZKTeco $self)
|
||||
{
|
||||
$self->_section = __METHOD__;
|
||||
|
||||
$command = Util::CMD_EXIT;
|
||||
$command_string = '';
|
||||
$chksum = 0;
|
||||
$session_id = $self->_session_id;
|
||||
|
||||
$u = unpack('H2h1/H2h2/H2h3/H2h4/H2h5/H2h6/H2h7/H2h8', substr($self->_data_recv, 0, 8));
|
||||
$reply_id = hexdec($u['h8'] . $u['h7']);
|
||||
|
||||
$buf = Util::createHeader($command, $chksum, $session_id, $reply_id, $command_string);
|
||||
|
||||
|
||||
socket_sendto($self->_zkclient, $buf, strlen($buf), 0, $self->_ip, $self->_port);
|
||||
try {
|
||||
@socket_recvfrom($self->_zkclient, $self->_data_recv, 1024, 0, $self->_ip, $self->_port);
|
||||
|
||||
$self->_session_id = 0;
|
||||
return Util::checkValid($self->_data_recv);
|
||||
} catch (ErrorException $e) {
|
||||
return false;
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
151
vendor/rats/zkteco/src/Lib/Helper/Device.php
vendored
Normal file
151
vendor/rats/zkteco/src/Lib/Helper/Device.php
vendored
Normal file
@ -0,0 +1,151 @@
|
||||
<?php
|
||||
|
||||
namespace Rats\Zkteco\Lib\Helper;
|
||||
|
||||
use Rats\Zkteco\Lib\ZKTeco;
|
||||
|
||||
class Device
|
||||
{
|
||||
/**
|
||||
* @param ZKTeco $self
|
||||
* @return bool|mixed
|
||||
*/
|
||||
static public function name(ZKTeco $self)
|
||||
{
|
||||
$self->_section = __METHOD__;
|
||||
|
||||
$command = Util::CMD_DEVICE;
|
||||
$command_string = '~DeviceName';
|
||||
|
||||
return $self->_command($command, $command_string);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ZKTeco $self
|
||||
* @return bool|mixed
|
||||
*/
|
||||
static public function enable(ZKTeco $self)
|
||||
{
|
||||
$self->_section = __METHOD__;
|
||||
|
||||
$command = Util::CMD_ENABLE_DEVICE;
|
||||
$command_string = '';
|
||||
|
||||
return $self->_command($command, $command_string);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ZKTeco $self
|
||||
* @return bool|mixed
|
||||
*/
|
||||
static public function disable(ZKTeco $self)
|
||||
{
|
||||
$self->_section = __METHOD__;
|
||||
|
||||
$command = Util::CMD_DISABLE_DEVICE;
|
||||
$command_string = chr(0) . chr(0);
|
||||
|
||||
return $self->_command($command, $command_string);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ZKTeco $self
|
||||
* @return bool|mixed *** this will turn off the device
|
||||
*/
|
||||
public static function powerOff(ZKTeco $self)
|
||||
{
|
||||
$self->_section = __METHOD__;
|
||||
|
||||
$command = Util::CMD_POWEROFF;
|
||||
$command_string = chr(0) . chr(0);
|
||||
return $self->_command($command, $command_string);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param ZKTeco $self
|
||||
* @return bool|mixed *** this will restart the device
|
||||
*/
|
||||
public static function restart(ZKTeco $self)
|
||||
{
|
||||
$self->_section = __METHOD__;
|
||||
|
||||
$command = Util::CMD_RESTART;
|
||||
$command_string = chr(0) . chr(0);
|
||||
return $self->_command($command, $command_string);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param ZKTeco $self
|
||||
* @return bool|mixed *** this will sleep the device
|
||||
*/
|
||||
public static function sleep(ZKTeco $self)
|
||||
{
|
||||
$self->_section = __METHOD__;
|
||||
|
||||
$command = Util::CMD_SLEEP;
|
||||
$command_string = chr(0) . chr(0);
|
||||
return $self->_command($command, $command_string);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param ZKTeco $self
|
||||
* @return bool|mixed *** this will resume the device from sleep
|
||||
*/
|
||||
public static function resume(ZKTeco $self)
|
||||
{
|
||||
$self->_section = __METHOD__;
|
||||
|
||||
$command = Util::CMD_RESUME;
|
||||
$command_string = chr(0) . chr(0);
|
||||
return $self->_command($command, $command_string);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param ZKTeco $self
|
||||
* @return bool|mixed *** this will play voice "Thank you"
|
||||
*/
|
||||
public static function testVoice(ZKTeco $self)
|
||||
{
|
||||
$self->_section = __METHOD__;
|
||||
|
||||
$command = Util::CMD_TESTVOICE;
|
||||
$command_string = chr(0) . chr(0);
|
||||
return $self->_command($command, $command_string);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param ZKTeco $self
|
||||
* @return bool|mixed *** this will clear the LCD screen
|
||||
*/
|
||||
public static function clearLCD(ZKTeco $self)
|
||||
{
|
||||
$self->_section = __METHOD__;
|
||||
|
||||
$command = Util::CMD_CLEAR_LCD;
|
||||
return $self->_command($command, '');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param ZKTeco $self
|
||||
* @param $rank *** Line number of text
|
||||
* @param $text *** Text which will display in the LCD screen
|
||||
* @return bool|mixed *** this will write text into the LCD
|
||||
*/
|
||||
public static function writeLCD(ZKTeco $self, $rank, $text)
|
||||
{
|
||||
$self->_section = __METHOD__;
|
||||
|
||||
$command = Util::CMD_WRITE_LCD;
|
||||
$byte1 = chr((int)($rank % 256));
|
||||
$byte2 = chr((int)($rank >> 8));
|
||||
$byte3 = chr(0);
|
||||
$command_string = $byte1.$byte2.$byte3.' '.$text;
|
||||
return $self->_command($command, $command_string);
|
||||
}
|
||||
}
|
||||
23
vendor/rats/zkteco/src/Lib/Helper/Face.php
vendored
Normal file
23
vendor/rats/zkteco/src/Lib/Helper/Face.php
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Rats\Zkteco\Lib\Helper;
|
||||
|
||||
use Rats\Zkteco\Lib\ZKTeco;
|
||||
|
||||
class Face
|
||||
{
|
||||
/**
|
||||
* @param ZKTeco $self
|
||||
* @return bool|mixed
|
||||
*/
|
||||
static public function on(ZKTeco $self)
|
||||
{
|
||||
$self->_section = __METHOD__;
|
||||
|
||||
$command = Util::CMD_DEVICE;
|
||||
$command_string = 'FaceFunOn';
|
||||
|
||||
return $self->_command($command, $command_string);
|
||||
}
|
||||
}
|
||||
|
||||
166
vendor/rats/zkteco/src/Lib/Helper/Fingerprint.php
vendored
Normal file
166
vendor/rats/zkteco/src/Lib/Helper/Fingerprint.php
vendored
Normal file
@ -0,0 +1,166 @@
|
||||
<?php
|
||||
|
||||
namespace Rats\Zkteco\Lib\Helper;
|
||||
|
||||
use Rats\Zkteco\Lib\ZKTeco;
|
||||
|
||||
class Fingerprint
|
||||
{
|
||||
/**
|
||||
* TODO: Can get data, but don't know how to parse the data. Need more documentation about it...
|
||||
*
|
||||
* @param ZKTeco $self
|
||||
* @param integer $uid Unique Employee ID in ZK device
|
||||
* @return array Binary fingerprint data array (where key is finger ID (0-9))
|
||||
*/
|
||||
static public function get(ZKTeco $self, $uid)
|
||||
{
|
||||
$self->_section = __METHOD__;
|
||||
|
||||
$data = [];
|
||||
//fingers of the hands
|
||||
for ($i = 0; $i <= 9; $i++) {
|
||||
$finger = new Fingerprint();
|
||||
$tmp = $finger->_getFinger($self, $uid, $i);
|
||||
if ($tmp['size'] > 0) {
|
||||
$data[$i] = $tmp['tpl'];
|
||||
}
|
||||
unset($tmp);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param ZKTeco $self
|
||||
* @param integer $uid Unique Employee ID in ZK device
|
||||
* @param integer $finger Finger ID (0-9)
|
||||
* @return array
|
||||
*/
|
||||
private function _getFinger(ZKTeco $self, $uid, $finger)
|
||||
{
|
||||
$command = Util::CMD_USER_TEMP_RRQ;
|
||||
$byte1 = chr((int)($uid % 256));
|
||||
$byte2 = chr((int)($uid >> 8));
|
||||
$command_string = $byte1 . $byte2 . chr($finger);
|
||||
|
||||
$ret = [
|
||||
'size' => 0,
|
||||
'tpl' => ''
|
||||
];
|
||||
|
||||
$session = $self->_command($command, $command_string, Util::COMMAND_TYPE_DATA);
|
||||
if ($session === false) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$data = Util::recData($self, 10, false);
|
||||
|
||||
if (!empty($data)) {
|
||||
$templateSize = strlen($data);
|
||||
$prefix = chr($templateSize % 256) . chr(round($templateSize / 256)) . $byte1 . $byte2 . chr($finger) . chr(1);
|
||||
$data = $prefix . $data;
|
||||
if (strlen($templateSize) > 0) {
|
||||
$ret['size'] = $templateSize;
|
||||
$ret['tpl'] = $data;
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Still can not set fingerprint. Need more documentation about it...
|
||||
*
|
||||
* @param ZKTeco $self
|
||||
* @param int $uid Unique Employee ID in ZK device
|
||||
* @param array $data Binary fingerprint data array (where key is finger ID (0-9) same like returned array from 'get' method)
|
||||
* @return int Count of added fingerprints
|
||||
*/
|
||||
static public function set(ZKTeco $self, $uid, array $data)
|
||||
{
|
||||
$self->_section = __METHOD__;
|
||||
|
||||
|
||||
$count = 0;
|
||||
foreach ($data as $finger => $item) {
|
||||
$allowSet = true;
|
||||
$fingerPrint = new Fingerprint();
|
||||
if ($fingerPrint->_checkFinger($self, $uid, $finger) === true) {
|
||||
$allowSet = $fingerPrint->_removeFinger($self, $uid, $finger);
|
||||
}
|
||||
if ($allowSet === true && $fingerPrint->_setFinger($self, $item) === true) {
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ZKTeco $self
|
||||
* @param string $data Binary fingerprint data item
|
||||
* @return bool|mixed
|
||||
*/
|
||||
private function _setFinger(ZKTeco $self, $data)
|
||||
{
|
||||
$command = Util::CMD_USER_TEMP_WRQ;
|
||||
$command_string = $data;
|
||||
|
||||
return $self->_command($command, $command_string);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ZKTeco $self
|
||||
* @param int $uid Unique Employee ID in ZK device
|
||||
* @param array $data Fingers ID array (0-9)
|
||||
* @return int Count of deleted fingerprints
|
||||
*/
|
||||
static public function remove(ZKTeco $self, $uid, array $data)
|
||||
{
|
||||
$self->_section = __METHOD__;
|
||||
|
||||
$count = 0;
|
||||
foreach ($data as $finger) {
|
||||
$fingerPrint = new Fingerprint();
|
||||
if ($fingerPrint->_checkFinger($self, $uid, $finger) === true) {
|
||||
if ($fingerPrint->_removeFinger($self, $uid, $finger) === true) {
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ZKTeco $self
|
||||
* @param int $uid Unique Employee ID in ZK device
|
||||
* @param int $finger Finger ID (0-9)
|
||||
* @return bool
|
||||
*/
|
||||
private function _removeFinger(ZKTeco $self, $uid, $finger)
|
||||
{
|
||||
$command = Util::CMD_DELETE_USER_TEMP;
|
||||
$byte1 = chr((int)($uid % 256));
|
||||
$byte2 = chr((int)($uid >> 8));
|
||||
$command_string = ($byte1 . $byte2) . chr($finger);
|
||||
|
||||
$self->_command($command, $command_string);
|
||||
$fingerPrint = new Fingerprint();
|
||||
return !($fingerPrint->_checkFinger($self, $uid, $finger));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ZKTeco $self
|
||||
* @param int $uid Unique Employee ID in ZK device
|
||||
* @param int $finger Finger ID (0-9)
|
||||
* @return bool Returned true if exist
|
||||
*/
|
||||
private function _checkFinger(ZKTeco $self, $uid, $finger)
|
||||
{
|
||||
$fingerPrint = new Fingerprint();
|
||||
$res = $fingerPrint->_getFinger($self, $uid, $finger);
|
||||
return (bool)($res['size'] > 0);
|
||||
}
|
||||
}
|
||||
22
vendor/rats/zkteco/src/Lib/Helper/Os.php
vendored
Normal file
22
vendor/rats/zkteco/src/Lib/Helper/Os.php
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Rats\Zkteco\Lib\Helper;
|
||||
|
||||
use Rats\Zkteco\Lib\ZKTeco;
|
||||
|
||||
class Os
|
||||
{
|
||||
/**
|
||||
* @param ZKTeco $self
|
||||
* @return bool|mixed
|
||||
*/
|
||||
static public function get(ZKTeco $self)
|
||||
{
|
||||
$self->_section = __METHOD__;
|
||||
|
||||
$command = Util::CMD_DEVICE;
|
||||
$command_string = '~OS';
|
||||
|
||||
return $self->_command($command, $command_string);
|
||||
}
|
||||
}
|
||||
22
vendor/rats/zkteco/src/Lib/Helper/Pin.php
vendored
Normal file
22
vendor/rats/zkteco/src/Lib/Helper/Pin.php
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Rats\Zkteco\Lib\Helper;
|
||||
|
||||
use Rats\Zkteco\Lib\ZKTeco;
|
||||
|
||||
class Pin
|
||||
{
|
||||
/**
|
||||
* @param ZKTeco $self
|
||||
* @return bool|mixed
|
||||
*/
|
||||
static public function width(ZKTeco $self)
|
||||
{
|
||||
$self->_section = __METHOD__;
|
||||
|
||||
$command = Util::CMD_DEVICE;
|
||||
$command_string = '~PIN2Width';
|
||||
|
||||
return $self->_command($command, $command_string);
|
||||
}
|
||||
}
|
||||
36
vendor/rats/zkteco/src/Lib/Helper/Platform.php
vendored
Normal file
36
vendor/rats/zkteco/src/Lib/Helper/Platform.php
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Rats\Zkteco\Lib\Helper;
|
||||
|
||||
use Rats\Zkteco\Lib\ZKTeco;
|
||||
|
||||
class Platform
|
||||
{
|
||||
/**
|
||||
* @param ZKTeco $self
|
||||
* @return bool|mixed
|
||||
*/
|
||||
static public function get(ZKTeco $self)
|
||||
{
|
||||
$self->_section = __METHOD__;
|
||||
|
||||
$command = Util::CMD_DEVICE;
|
||||
$command_string = '~Platform';
|
||||
|
||||
return $self->_command($command, $command_string);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ZKTeco $self
|
||||
* @return bool|mixed
|
||||
*/
|
||||
static public function getVersion(ZKTeco $self)
|
||||
{
|
||||
$self->_section = __METHOD__;
|
||||
|
||||
$command = Util::CMD_DEVICE;
|
||||
$command_string = '~ZKFPVersion';
|
||||
|
||||
return $self->_command($command, $command_string);
|
||||
}
|
||||
}
|
||||
22
vendor/rats/zkteco/src/Lib/Helper/SerialNumber.php
vendored
Normal file
22
vendor/rats/zkteco/src/Lib/Helper/SerialNumber.php
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Rats\Zkteco\Lib\Helper;
|
||||
|
||||
use Rats\Zkteco\Lib\ZKTeco;
|
||||
|
||||
class SerialNumber
|
||||
{
|
||||
/**
|
||||
* @param ZKTeco $self
|
||||
* @return bool|mixed
|
||||
*/
|
||||
static public function get(ZKTeco $self)
|
||||
{
|
||||
$self->_section = __METHOD__;
|
||||
|
||||
$command = Util::CMD_DEVICE;
|
||||
$command_string = '~SerialNumber';
|
||||
|
||||
return $self->_command($command, $command_string);
|
||||
}
|
||||
}
|
||||
22
vendor/rats/zkteco/src/Lib/Helper/Ssr.php
vendored
Normal file
22
vendor/rats/zkteco/src/Lib/Helper/Ssr.php
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Rats\Zkteco\Lib\Helper;
|
||||
|
||||
use Rats\Zkteco\Lib\ZKTeco;
|
||||
|
||||
class Ssr
|
||||
{
|
||||
/**
|
||||
* @param ZKTeco $self
|
||||
* @return bool|mixed
|
||||
*/
|
||||
static public function get(ZKTeco $self)
|
||||
{
|
||||
$self->_section = __METHOD__;
|
||||
|
||||
$command = Util::CMD_DEVICE;
|
||||
$command_string = '~SSR';
|
||||
|
||||
return $self->_command($command, $command_string);
|
||||
}
|
||||
}
|
||||
44
vendor/rats/zkteco/src/Lib/Helper/Time.php
vendored
Normal file
44
vendor/rats/zkteco/src/Lib/Helper/Time.php
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Rats\Zkteco\Lib\Helper;
|
||||
|
||||
use Rats\Zkteco\Lib\ZKTeco;
|
||||
|
||||
class Time
|
||||
{
|
||||
/**
|
||||
* @param ZKTeco $self
|
||||
* @param string $t Format: "Y-m-d H:i:s"
|
||||
* @return bool|mixed
|
||||
*/
|
||||
static public function set(ZKTeco $self, $t)
|
||||
{
|
||||
die($t);
|
||||
$self->_section = __METHOD__;
|
||||
|
||||
$command = Util::CMD_SET_TIME;
|
||||
$command_string = pack('I', Util::encodeTime($t));
|
||||
|
||||
return $self->_command($command, $command_string);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ZKTeco $self
|
||||
* @return bool|mixed
|
||||
*/
|
||||
static public function get(ZKTeco $self)
|
||||
{
|
||||
$self->_section = __METHOD__;
|
||||
|
||||
$command = Util::CMD_GET_TIME;
|
||||
$command_string = '';
|
||||
|
||||
$ret = $self->_command($command, $command_string);
|
||||
|
||||
if ($ret) {
|
||||
return Util::decodeTime(hexdec(Util::reverseHex(bin2hex($ret))));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
161
vendor/rats/zkteco/src/Lib/Helper/User.php
vendored
Normal file
161
vendor/rats/zkteco/src/Lib/Helper/User.php
vendored
Normal file
@ -0,0 +1,161 @@
|
||||
<?php
|
||||
|
||||
namespace Rats\Zkteco\Lib\Helper;
|
||||
|
||||
use Rats\Zkteco\Lib\ZKTeco;
|
||||
|
||||
class User
|
||||
{
|
||||
/**
|
||||
* @param ZKTeco $self
|
||||
* @param int $uid Unique ID (max 65535)
|
||||
* @param int|string $userid (max length = 9, only numbers - depends device setting)
|
||||
* @param string $name (max length = 24)
|
||||
* @param int|string $password (max length = 8, only numbers - depends device setting)
|
||||
* @param int $role Default Util::LEVEL_USER
|
||||
* @param int $cardno Default 0 (max length = 10, only numbers)
|
||||
* @return bool|mixed
|
||||
*/
|
||||
static public function set(ZKTeco $self, $uid, $userid, $name, $password, $role = Util::LEVEL_USER, $cardno = 0)
|
||||
{
|
||||
$self->_section = __METHOD__;
|
||||
|
||||
if (
|
||||
(int)$uid === 0 ||
|
||||
(int)$uid > Util::USHRT_MAX ||
|
||||
strlen($userid) > 9 ||
|
||||
strlen($name) > 24 ||
|
||||
strlen($password) > 8 ||
|
||||
strlen($cardno) > 10
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$command = Util::CMD_SET_USER;
|
||||
$byte1 = chr((int)($uid % 256));
|
||||
$byte2 = chr((int)($uid >> 8));
|
||||
$cardno = hex2bin(Util::reverseHex(dechex($cardno)));
|
||||
|
||||
$command_string = implode('', [
|
||||
$byte1,
|
||||
$byte2,
|
||||
chr($role),
|
||||
str_pad($password, 8, chr(0)),
|
||||
str_pad($name, 24, chr(0)),
|
||||
str_pad($cardno, 4, chr(0)),
|
||||
str_pad(chr(1), 9, chr(0)),
|
||||
str_pad($userid, 9, chr(0)),
|
||||
str_repeat(chr(0), 15)
|
||||
]);
|
||||
// die($command_string);
|
||||
return $self->_command($command, $command_string);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ZKTeco $self
|
||||
* @return array [userid, name, cardno, uid, role, password]
|
||||
*/
|
||||
static public function get(ZKTeco $self)
|
||||
{
|
||||
$self->_section = __METHOD__;
|
||||
|
||||
$command = Util::CMD_USER_TEMP_RRQ;
|
||||
$command_string = chr(Util::FCT_USER);
|
||||
|
||||
$session = $self->_command($command, $command_string, Util::COMMAND_TYPE_DATA);
|
||||
if ($session === false) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$userData = Util::recData($self);
|
||||
|
||||
$users = [];
|
||||
if (!empty($userData)) {
|
||||
$userData = substr($userData, 11);
|
||||
|
||||
while (strlen($userData) > 72) {
|
||||
$u = unpack('H144', substr($userData, 0, 72));
|
||||
|
||||
$u1 = hexdec(substr($u[1], 2, 2));
|
||||
$u2 = hexdec(substr($u[1], 4, 2));
|
||||
$uid = $u1 + ($u2 * 256);
|
||||
$cardno = hexdec(substr($u[1], 78, 2) . substr($u[1], 76, 2) . substr($u[1], 74, 2) . substr($u[1], 72, 2)) . ' ';
|
||||
$role = hexdec(substr($u[1], 6, 2)) . ' ';
|
||||
$password = hex2bin(substr($u[1], 8, 16)) . ' ';
|
||||
$name = hex2bin(substr($u[1], 24, 74)) . ' ';
|
||||
$userid = hex2bin(substr($u[1], 98, 72)) . ' ';
|
||||
|
||||
//Clean up some messy characters from the user name
|
||||
$password = explode(chr(0), $password, 2);
|
||||
$password = $password[0];
|
||||
$userid = explode(chr(0), $userid, 2);
|
||||
$userid = $userid[0];
|
||||
$name = explode(chr(0), $name, 3);
|
||||
$name = utf8_encode($name[0]);
|
||||
$cardno = str_pad($cardno, 11, '0', STR_PAD_LEFT);
|
||||
|
||||
if ($name == '') {
|
||||
$name = $userid;
|
||||
}
|
||||
|
||||
$users[$userid] = [
|
||||
'uid' => $uid,
|
||||
'userid' => $userid,
|
||||
'name' => $name,
|
||||
'role' => intval($role),
|
||||
'password' => $password,
|
||||
'cardno' => $cardno,
|
||||
];
|
||||
|
||||
$userData = substr($userData, 72);
|
||||
}
|
||||
}
|
||||
|
||||
return $users;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ZKTeco $self
|
||||
* @return bool|mixed
|
||||
*/
|
||||
static public function clear(ZKTeco $self)
|
||||
{
|
||||
$self->_section = __METHOD__;
|
||||
|
||||
$command = Util::CMD_CLEAR_DATA;
|
||||
$command_string = '';
|
||||
|
||||
return $self->_command($command, $command_string);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ZKTeco $self
|
||||
* @return bool|mixed
|
||||
*/
|
||||
static public function clearAdmin(ZKTeco $self)
|
||||
{
|
||||
$self->_section = __METHOD__;
|
||||
|
||||
$command = Util::CMD_CLEAR_ADMIN;
|
||||
$command_string = '';
|
||||
|
||||
return $self->_command($command, $command_string);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ZKTeco $self
|
||||
* @param integer $uid
|
||||
* @return bool|mixed
|
||||
*/
|
||||
static public function remove(ZKTeco $self, $uid)
|
||||
{
|
||||
$self->_section = __METHOD__;
|
||||
|
||||
$command = Util::CMD_DELETE_USER;
|
||||
$byte1 = chr((int)($uid % 256));
|
||||
$byte2 = chr((int)($uid >> 8));
|
||||
$command_string = ($byte1 . $byte2);
|
||||
|
||||
return $self->_command($command, $command_string);
|
||||
}
|
||||
}
|
||||
427
vendor/rats/zkteco/src/Lib/Helper/Util.php
vendored
Normal file
427
vendor/rats/zkteco/src/Lib/Helper/Util.php
vendored
Normal file
@ -0,0 +1,427 @@
|
||||
<?php
|
||||
|
||||
namespace Rats\Zkteco\Lib\Helper;
|
||||
|
||||
use Rats\Zkteco\Lib\ZKTeco;
|
||||
|
||||
class Util
|
||||
{
|
||||
const USHRT_MAX = 65535;
|
||||
|
||||
const CMD_CONNECT = 1000; # Connections requests
|
||||
const CMD_EXIT = 1001; # Disconnection requests
|
||||
const CMD_ENABLE_DEVICE = 1002; # Ensure the machine to be at the normal work condition
|
||||
const CMD_DISABLE_DEVICE = 1003; # Make the machine to be at the shut-down condition, generally demonstrates ‘in the work ...’on LCD
|
||||
|
||||
const CMD_RESTART = 1004; # Restart the machine
|
||||
const CMD_POWEROFF = 1005; # Turn Off the machine
|
||||
const CMD_SLEEP = 1006; # Sleep the machine
|
||||
const CMD_RESUME = 1007; # Resume the machine from Sleep
|
||||
const CMD_TEST_TEMP = 1011;
|
||||
const CMD_TESTVOICE = 1017; # Voice test to the device
|
||||
const CMD_CHANGE_SPEED = 1101;
|
||||
|
||||
|
||||
const CMD_WRITE_LCD = 66; # Write in LCD
|
||||
const CMD_CLEAR_LCD = 67; # Clear LCD
|
||||
|
||||
const CMD_ACK_OK = 2000; # Return value for order perform successfully
|
||||
const CMD_ACK_ERROR = 2001; # Return value for order perform failed
|
||||
const CMD_ACK_DATA = 2002; # Return data
|
||||
const CMD_ACK_UNAUTH = 2005; # Connection unauthorized
|
||||
|
||||
const CMD_PREPARE_DATA = 1500; # Prepares to transmit the data
|
||||
const CMD_DATA = 1501; # Transmit a data packet
|
||||
const CMD_FREE_DATA = 1502; # Clear machines open buffer
|
||||
|
||||
const CMD_USER_TEMP_RRQ = 9; # Read some fingerprint template or some kind of data entirely
|
||||
const CMD_ATT_LOG_RRQ = 13; # Read all attendance record
|
||||
const CMD_CLEAR_DATA = 14; # Clear Data
|
||||
const CMD_CLEAR_ATT_LOG = 15; # Clear attendance records
|
||||
|
||||
const CMD_GET_TIME = 201; # Obtain the machine time
|
||||
const CMD_SET_TIME = 202; # Set machines time
|
||||
|
||||
const CMD_VERSION = 1100; # Obtain the firmware edition
|
||||
const CMD_DEVICE = 11; # Read in the machine some configuration parameter
|
||||
|
||||
const CMD_SET_USER = 8; # Upload the user information (from PC to terminal).
|
||||
const CMD_USER_TEMP_WRQ = 10; # Upload some fingerprint template
|
||||
const CMD_DELETE_USER = 18; # Delete some user
|
||||
const CMD_DELETE_USER_TEMP = 19; # Delete some fingerprint template
|
||||
const CMD_CLEAR_ADMIN = 20; # Cancel the manager
|
||||
|
||||
const LEVEL_USER = 0; # User level as User
|
||||
const LEVEL_ADMIN = 14; # User level as Admin
|
||||
|
||||
const FCT_ATTLOG = 1;
|
||||
const FCT_WORKCODE = 8;
|
||||
const FCT_FINGERTMP = 2;
|
||||
const FCT_OPLOG = 4;
|
||||
const FCT_USER = 5;
|
||||
const FCT_SMS = 6;
|
||||
const FCT_UDATA = 7;
|
||||
|
||||
const COMMAND_TYPE_GENERAL = 'general';
|
||||
const COMMAND_TYPE_DATA = 'data';
|
||||
|
||||
const ATT_STATE_FINGERPRINT = 1;
|
||||
const ATT_STATE_PASSWORD = 0;
|
||||
const ATT_STATE_CARD = 2;
|
||||
|
||||
const ATT_TYPE_CHECK_IN = 0;
|
||||
const ATT_TYPE_CHECK_OUT = 1;
|
||||
const ATT_TYPE_OVERTIME_IN = 4;
|
||||
const ATT_TYPE_OVERTIME_OUT = 5;
|
||||
|
||||
/**
|
||||
* Encode a timestamp send at the timeclock
|
||||
* copied from zkemsdk.c - EncodeTime
|
||||
*
|
||||
* @param string $t Format: "Y-m-d H:i:s"
|
||||
* @return int
|
||||
*/
|
||||
static public function encodeTime($t)
|
||||
{
|
||||
$timestamp = strtotime($t);
|
||||
$t = (object)[
|
||||
'year' => (int)date('Y', $timestamp),
|
||||
'month' => (int)date('m', $timestamp),
|
||||
'day' => (int)date('d', $timestamp),
|
||||
'hour' => (int)date('H', $timestamp),
|
||||
'minute' => (int)date('i', $timestamp),
|
||||
'second' => (int)date('s', $timestamp),
|
||||
];
|
||||
|
||||
$d = (($t->year % 100) * 12 * 31 + (($t->month - 1) * 31) + $t->day - 1) *
|
||||
(24 * 60 * 60) + ($t->hour * 60 + $t->minute) * 60 + $t->second;
|
||||
|
||||
return $d;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a timestamp retrieved from the timeclock
|
||||
* copied from zkemsdk.c - DecodeTime
|
||||
*
|
||||
* @param int|string $t
|
||||
* @return false|string Format: "Y-m-d H:i:s"
|
||||
*/
|
||||
static public function decodeTime($t)
|
||||
{
|
||||
$second = $t % 60;
|
||||
$t = $t / 60;
|
||||
|
||||
$minute = $t % 60;
|
||||
$t = $t / 60;
|
||||
|
||||
$hour = $t % 24;
|
||||
$t = $t / 24;
|
||||
|
||||
$day = $t % 31 + 1;
|
||||
$t = $t / 31;
|
||||
|
||||
$month = $t % 12 + 1;
|
||||
$t = $t / 12;
|
||||
|
||||
$year = floor($t + 2000);
|
||||
|
||||
$d = date('Y-m-d H:i:s', strtotime(
|
||||
$year . '-' . $month . '-' . $day . ' ' . $hour . ':' . $minute . ':' . $second
|
||||
));
|
||||
|
||||
return $d;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $hex
|
||||
* @return string
|
||||
*/
|
||||
static public function reverseHex($hex)
|
||||
{
|
||||
$tmp = '';
|
||||
|
||||
for ($i = strlen($hex); $i >= 0; $i--) {
|
||||
$tmp .= substr($hex, $i, 2);
|
||||
$i--;
|
||||
}
|
||||
|
||||
return $tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks a returned packet to see if it returned self::CMD_PREPARE_DATA,
|
||||
* indicating that data packets are to be sent
|
||||
* Returns the amount of bytes that are going to be sent
|
||||
*
|
||||
* @param ZKTeco $self
|
||||
* @return bool|number
|
||||
*/
|
||||
static public function getSize(ZKTeco $self)
|
||||
{
|
||||
$u = unpack('H2h1/H2h2/H2h3/H2h4/H2h5/H2h6/H2h7/H2h8', substr($self->_data_recv, 0, 8));
|
||||
$command = hexdec($u['h2'] . $u['h1']);
|
||||
|
||||
if ($command == self::CMD_PREPARE_DATA) {
|
||||
$u = unpack('H2h1/H2h2/H2h3/H2h4', substr($self->_data_recv, 8, 4));
|
||||
$size = hexdec($u['h4'] . $u['h3'] . $u['h2'] . $u['h1']);
|
||||
return $size;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function calculates the chksum of the packet to be sent to the
|
||||
* time clock
|
||||
* Copied from zkemsdk.c
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
static public function createChkSum($p)
|
||||
{
|
||||
$l = count($p);
|
||||
$chksum = 0;
|
||||
$i = $l;
|
||||
$j = 1;
|
||||
while ($i > 1) {
|
||||
$u = unpack('S', pack('C2', $p['c' . $j], $p['c' . ($j + 1)]));
|
||||
|
||||
$chksum += $u[1];
|
||||
|
||||
if ($chksum > self::USHRT_MAX) {
|
||||
$chksum -= self::USHRT_MAX;
|
||||
}
|
||||
$i -= 2;
|
||||
$j += 2;
|
||||
}
|
||||
|
||||
if ($i) {
|
||||
$chksum = $chksum + $p['c' . strval(count($p))];
|
||||
}
|
||||
|
||||
while ($chksum > self::USHRT_MAX) {
|
||||
$chksum -= self::USHRT_MAX;
|
||||
}
|
||||
|
||||
if ($chksum > 0) {
|
||||
$chksum = -($chksum);
|
||||
} else {
|
||||
$chksum = abs($chksum);
|
||||
}
|
||||
|
||||
$chksum -= 1;
|
||||
while ($chksum < 0) {
|
||||
$chksum += self::USHRT_MAX;
|
||||
}
|
||||
|
||||
return pack('S', $chksum);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function puts a the parts that make up a packet together and
|
||||
* packs them into a byte string
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
static public function createHeader($command, $chksum, $session_id, $reply_id, $command_string)
|
||||
{
|
||||
$buf = pack('SSSS', $command, $chksum, $session_id, $reply_id) . $command_string;
|
||||
|
||||
$buf = unpack('C' . (8 + strlen($command_string)) . 'c', $buf);
|
||||
|
||||
$u = unpack('S', self::createChkSum($buf));
|
||||
|
||||
if (is_array($u)) {
|
||||
$u = reset($u);
|
||||
}
|
||||
$chksum = $u;
|
||||
|
||||
$reply_id += 1;
|
||||
|
||||
if ($reply_id >= self::USHRT_MAX) {
|
||||
$reply_id -= self::USHRT_MAX;
|
||||
}
|
||||
|
||||
$buf = pack('SSSS', $command, $chksum, $session_id, $reply_id);
|
||||
|
||||
return $buf . $command_string;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks a returned packet to see if it returned Util::CMD_ACK_OK,
|
||||
* indicating success
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
static public function checkValid($reply)
|
||||
{
|
||||
$u = unpack('H2h1/H2h2', substr($reply, 0, 8));
|
||||
|
||||
$command = hexdec($u['h2'] . $u['h1']);
|
||||
/** TODO: Some device can return 'Connection unauthorized' then should check also */
|
||||
if ($command == self::CMD_ACK_OK || $command == self::CMD_ACK_UNAUTH) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get User Role string
|
||||
* @param integer $role
|
||||
* @return string
|
||||
*/
|
||||
static public function getUserRole($role)
|
||||
{
|
||||
switch ($role) {
|
||||
case self::LEVEL_USER:
|
||||
$ret = 'User';
|
||||
break;
|
||||
case self::LEVEL_ADMIN:
|
||||
$ret = 'Admin';
|
||||
break;
|
||||
default:
|
||||
$ret = 'Unknown';
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Attendance State string
|
||||
* @param integer $state
|
||||
* @return string
|
||||
*/
|
||||
static public function getAttState($state)
|
||||
{
|
||||
switch ($state) {
|
||||
case self::ATT_STATE_FINGERPRINT:
|
||||
$ret = 'Fingerprint';
|
||||
break;
|
||||
case self::ATT_STATE_PASSWORD:
|
||||
$ret = 'Password';
|
||||
break;
|
||||
case self::ATT_STATE_CARD:
|
||||
$ret = 'Card';
|
||||
break;
|
||||
default:
|
||||
$ret = 'Unknown';
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Attendance Type string
|
||||
* @param integer $type
|
||||
* @return string
|
||||
*/
|
||||
static public function getAttType($type)
|
||||
{
|
||||
switch ($type) {
|
||||
case self::ATT_TYPE_CHECK_IN:
|
||||
$ret = 'Check-in';
|
||||
break;
|
||||
case self::ATT_TYPE_CHECK_OUT:
|
||||
$ret = 'Check-out';
|
||||
break;
|
||||
case self::ATT_TYPE_OVERTIME_IN:
|
||||
$ret = 'Overtime-in';
|
||||
break;
|
||||
case self::ATT_TYPE_OVERTIME_OUT:
|
||||
$ret = 'Overtime-out';
|
||||
break;
|
||||
default:
|
||||
$ret = 'Undefined';
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive data from device
|
||||
* @param ZKTeco $self
|
||||
* @param int $maxErrors
|
||||
* @param bool $first if 'true' don't remove first 4 bytes for first row
|
||||
* @return string
|
||||
*/
|
||||
static public function recData(ZKTeco $self, $maxErrors = 10, $first = true)
|
||||
{
|
||||
$data = '';
|
||||
$bytes = self::getSize($self);
|
||||
|
||||
if ($bytes) {
|
||||
$received = 0;
|
||||
$errors = 0;
|
||||
|
||||
while ($bytes > $received) {
|
||||
$ret = @socket_recvfrom($self->_zkclient, $dataRec, 1032, 0, $self->_ip, $self->_port);
|
||||
|
||||
if ($ret === false) {
|
||||
if ($errors < $maxErrors) {
|
||||
//try again if false
|
||||
$errors++;
|
||||
sleep(1);
|
||||
continue;
|
||||
} else {
|
||||
//return empty if has maximum count of errors
|
||||
self::logReceived($self, $received, $bytes);
|
||||
unset($data);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
if ($first === false) {
|
||||
//The first 4 bytes don't seem to be related to the user
|
||||
$dataRec = substr($dataRec, 8);
|
||||
}
|
||||
|
||||
$data .= $dataRec;
|
||||
$received += strlen($dataRec);
|
||||
|
||||
unset($dataRec);
|
||||
$first = false;
|
||||
}
|
||||
|
||||
//flush socket
|
||||
@socket_recvfrom($self->_zkclient, $dataRec, 1024, 0, $self->_ip, $self->_port);
|
||||
unset($dataRec);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ZKTeco $self
|
||||
* @param int $received
|
||||
* @param int $bytes
|
||||
*/
|
||||
static private function logReceived(ZKTeco $self, $received, $bytes)
|
||||
{
|
||||
self::logger($self, 'Received: ' . $received . ' of ' . $bytes . ' bytes');
|
||||
}
|
||||
|
||||
/**
|
||||
* Write log
|
||||
* @param ZKTeco $self
|
||||
* @param string $str
|
||||
*/
|
||||
static private function logger(ZKTeco $self, $str)
|
||||
{
|
||||
if (defined('ZK_LIB_LOG')) {
|
||||
//use constant if defined
|
||||
$log = ZK_LIB_LOG;
|
||||
} else {
|
||||
$dir = dirname(dirname(__FILE__));
|
||||
$log = $dir . '/logs/error.log';
|
||||
}
|
||||
|
||||
$row = '<' . $self->_ip . '> [' . date('d.m.Y H:i:s') . '] ';
|
||||
$row .= (empty($self->_section) ? '' : '(' . $self->_section . ') ');
|
||||
$row .= $str;
|
||||
$row .= PHP_EOL;
|
||||
|
||||
file_put_contents($log, $row, FILE_APPEND);
|
||||
}
|
||||
}
|
||||
23
vendor/rats/zkteco/src/Lib/Helper/Version.php
vendored
Normal file
23
vendor/rats/zkteco/src/Lib/Helper/Version.php
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Rats\Zkteco\Lib\Helper;;
|
||||
|
||||
use Rats\Zkteco\Lib\Helper\Util;
|
||||
use Rats\Zkteco\Lib\ZKTeco;
|
||||
|
||||
class Version
|
||||
{
|
||||
/**
|
||||
* @param ZKTeco $self
|
||||
* @return bool|mixed
|
||||
*/
|
||||
static public function get(ZKTeco $self)
|
||||
{
|
||||
$self->_section = __METHOD__;
|
||||
|
||||
$command = Util::CMD_VERSION;
|
||||
$command_string = '';
|
||||
|
||||
return $self->_command($command, $command_string);
|
||||
}
|
||||
}
|
||||
22
vendor/rats/zkteco/src/Lib/Helper/WorkCode.php
vendored
Normal file
22
vendor/rats/zkteco/src/Lib/Helper/WorkCode.php
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Rats\Zkteco\Lib\Helper;
|
||||
|
||||
use Rats\Zkteco\Lib\ZKTeco;
|
||||
|
||||
class WorkCode
|
||||
{
|
||||
/**
|
||||
* @param ZKTeco $self
|
||||
* @return bool|mixed
|
||||
*/
|
||||
static public function get(ZKTeco $self)
|
||||
{
|
||||
$self->_section = __METHOD__;
|
||||
|
||||
$command = Util::CMD_DEVICE;
|
||||
$command_string = 'WorkCode';
|
||||
|
||||
return $self->_command($command, $command_string);
|
||||
}
|
||||
}
|
||||
435
vendor/rats/zkteco/src/Lib/ZKTeco.php
vendored
Normal file
435
vendor/rats/zkteco/src/Lib/ZKTeco.php
vendored
Normal file
@ -0,0 +1,435 @@
|
||||
<?php
|
||||
|
||||
namespace Rats\Zkteco\Lib;
|
||||
|
||||
use ErrorException;
|
||||
use Exception;
|
||||
use Rats\Zkteco\Lib\Helper\Attendance;
|
||||
use Rats\Zkteco\Lib\Helper\Device;
|
||||
use Rats\Zkteco\Lib\Helper\Face;
|
||||
use Rats\Zkteco\Lib\Helper\Fingerprint;
|
||||
use Rats\Zkteco\Lib\Helper\Os;
|
||||
use Rats\Zkteco\Lib\Helper\Pin;
|
||||
use Rats\Zkteco\Lib\Helper\Platform;
|
||||
use Rats\Zkteco\Lib\Helper\SerialNumber;
|
||||
use Rats\Zkteco\Lib\Helper\Ssr;
|
||||
use Rats\Zkteco\Lib\Helper\Time;
|
||||
use Rats\Zkteco\Lib\Helper\User;
|
||||
use Rats\Zkteco\Lib\Helper\Util;
|
||||
use Rats\Zkteco\Lib\Helper\Connect;
|
||||
use Rats\Zkteco\Lib\Helper\Version;
|
||||
use Rats\Zkteco\Lib\Helper\WorkCode;
|
||||
|
||||
|
||||
class ZKTeco{
|
||||
public $_ip;
|
||||
public $_port;
|
||||
public $_zkclient;
|
||||
|
||||
public $_data_recv = '';
|
||||
public $_session_id = 0;
|
||||
public $_section = '';
|
||||
|
||||
/**
|
||||
* ZKLib constructor.
|
||||
* @param string $ip Device IP
|
||||
* @param integer $port Default: 4370
|
||||
*/
|
||||
public function __construct($ip, $port = 4370)
|
||||
{
|
||||
$this->_ip = $ip;
|
||||
$this->_port = $port;
|
||||
|
||||
$this->_zkclient = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
|
||||
|
||||
$timeout = array('sec' => 60, 'usec' => 500000);
|
||||
socket_set_option($this->_zkclient, SOL_SOCKET, SO_RCVTIMEO, $timeout);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and send command to device
|
||||
*
|
||||
* @param string $command
|
||||
* @param string $command_string
|
||||
* @param string $type
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function _command($command, $command_string, $type = Util::COMMAND_TYPE_GENERAL)
|
||||
{
|
||||
$chksum = 0;
|
||||
$session_id = $this->_session_id;
|
||||
|
||||
$u = unpack('H2h1/H2h2/H2h3/H2h4/H2h5/H2h6/H2h7/H2h8', substr($this->_data_recv, 0, 8));
|
||||
$reply_id = hexdec($u['h8'] . $u['h7']);
|
||||
|
||||
$buf = Util::createHeader($command, $chksum, $session_id, $reply_id, $command_string);
|
||||
|
||||
socket_sendto($this->_zkclient, $buf, strlen($buf), 0, $this->_ip, $this->_port);
|
||||
|
||||
try {
|
||||
@socket_recvfrom($this->_zkclient, $this->_data_recv, 1024, 0, $this->_ip, $this->_port);
|
||||
|
||||
$u = unpack('H2h1/H2h2/H2h3/H2h4/H2h5/H2h6', substr($this->_data_recv, 0, 8));
|
||||
|
||||
$ret = false;
|
||||
$session = hexdec($u['h6'] . $u['h5']);
|
||||
|
||||
if ($type === Util::COMMAND_TYPE_GENERAL && $session_id === $session) {
|
||||
$ret = substr($this->_data_recv, 8);
|
||||
} else if ($type === Util::COMMAND_TYPE_DATA && !empty($session)) {
|
||||
$ret = $session;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
} catch (ErrorException $e) {
|
||||
return false;
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to device
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function connect()
|
||||
{
|
||||
return Connect::connect($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect from device
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function disconnect()
|
||||
{
|
||||
return Connect::disconnect($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get device version
|
||||
*
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function version()
|
||||
{
|
||||
return Version::get($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get OS version
|
||||
*
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function osVersion()
|
||||
{
|
||||
return Os::get($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get platform
|
||||
*
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function platform()
|
||||
{
|
||||
return Platform::get($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get firmware version
|
||||
*
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function fmVersion()
|
||||
{
|
||||
return Platform::getVersion($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get work code
|
||||
*
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function workCode()
|
||||
{
|
||||
return WorkCode::get($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get SSR
|
||||
*
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function ssr()
|
||||
{
|
||||
return Ssr::get($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get pin width
|
||||
*
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function pinWidth()
|
||||
{
|
||||
return Pin::width($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function faceFunctionOn()
|
||||
{
|
||||
return Face::on($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get device serial number
|
||||
*
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function serialNumber()
|
||||
{
|
||||
return SerialNumber::get($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get device name
|
||||
*
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function deviceName()
|
||||
{
|
||||
return Device::name($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable device
|
||||
*
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function disableDevice()
|
||||
{
|
||||
return Device::disable($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable device
|
||||
*
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function enableDevice()
|
||||
{
|
||||
return Device::enable($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get users data
|
||||
*
|
||||
* @return array [userid, name, cardno, uid, role, password]
|
||||
*/
|
||||
public function getUser()
|
||||
{
|
||||
return User::get($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set user data
|
||||
*
|
||||
* @param int $uid Unique ID (max 65535)
|
||||
* @param int|string $userid ID in DB (same like $uid, max length = 9, only numbers - depends device setting)
|
||||
* @param string $name (max length = 24)
|
||||
* @param int|string $password (max length = 8, only numbers - depends device setting)
|
||||
* @param int $role Default Util::LEVEL_USER
|
||||
* @param int $cardno Default 0 (max length = 10, only numbers)
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function setUser($uid, $userid, $name, $password, $role = Util::LEVEL_USER, $cardno = 0)
|
||||
{
|
||||
return User::set($this, $uid, $userid, $name, $password, $role, $cardno);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Remove All users
|
||||
*
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function clearUsers()
|
||||
{
|
||||
return User::clear($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove admin
|
||||
*
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function clearAdmin()
|
||||
{
|
||||
return User::clearAdmin($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove user by UID
|
||||
*
|
||||
* @param integer $uid
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function removeUser($uid)
|
||||
{
|
||||
return User::remove($this, $uid);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get fingerprint data array by UID
|
||||
* TODO: Can get data, but don't know how to parse the data. Need more documentation about it...
|
||||
*
|
||||
* @param integer $uid Unique ID (max 65535)
|
||||
* @return array Binary fingerprint data array (where key is finger ID (0-9))
|
||||
*/
|
||||
public function getFingerprint($uid)
|
||||
{
|
||||
return Fingerprint::get($this, $uid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set fingerprint data array
|
||||
* TODO: Still can not set fingerprint. Need more documentation about it...
|
||||
*
|
||||
* @param integer $uid Unique ID (max 65535)
|
||||
* @param array $data Binary fingerprint data array (where key is finger ID (0-9) same like returned array from 'getFingerprint' method)
|
||||
* @return int Count of added fingerprints
|
||||
*/
|
||||
public function setFingerprint($uid, array $data)
|
||||
{
|
||||
return Fingerprint::set($this, $uid, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove fingerprint by UID and fingers ID array
|
||||
*
|
||||
* @param integer $uid Unique ID (max 65535)
|
||||
* @param array $data Fingers ID array (0-9)
|
||||
* @return int Count of deleted fingerprints
|
||||
*/
|
||||
public function removeFingerprint($uid, array $data)
|
||||
{
|
||||
return Fingerprint::remove($this, $uid, $data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get attendance log
|
||||
*
|
||||
* @return array [uid, id, state, timestamp]
|
||||
*/
|
||||
public function getAttendance()
|
||||
{
|
||||
return Attendance::get($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear attendance log
|
||||
*
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function clearAttendance()
|
||||
{
|
||||
return Attendance::clear($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set device time
|
||||
*
|
||||
* @param string $t Format: "Y-m-d H:i:s"
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function setTime($t)
|
||||
{
|
||||
return Time::set($this, $t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get device time
|
||||
*
|
||||
* @return bool|mixed Format: "Y-m-d H:i:s"
|
||||
*/
|
||||
public function getTime()
|
||||
{
|
||||
return Time::get($this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* turn off the device
|
||||
*
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function shutdown()
|
||||
{
|
||||
return Device::powerOff($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* restart the device
|
||||
*
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function restart()
|
||||
{
|
||||
return Device::restart($this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* make sleep mood the device
|
||||
*
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function sleep()
|
||||
{
|
||||
return Device::sleep($this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* resume the device from sleep
|
||||
*
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function resume()
|
||||
{
|
||||
return Device::resume($this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* voice test Sound will "Thank you"
|
||||
*
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function testVoice()
|
||||
{
|
||||
return Device::testVoice($this);
|
||||
}
|
||||
|
||||
|
||||
public function clearLCD()
|
||||
{
|
||||
return Device::clearLCD($this);
|
||||
}
|
||||
|
||||
|
||||
public function writeLCD()
|
||||
{
|
||||
return Device::writeLCD($this, 2, "RAIHAN Afroz Topu");
|
||||
}
|
||||
}
|
||||
16
vendor/rats/zkteco/src/Providers/ZktecoServiceProvider.php
vendored
Normal file
16
vendor/rats/zkteco/src/Providers/ZktecoServiceProvider.php
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Rats\Zkteco\Providers;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class ZktecoServiceProvider extends ServiceProvider {
|
||||
|
||||
public function boot(){
|
||||
// dd("Zkteco is running");
|
||||
}
|
||||
|
||||
public function register(){
|
||||
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user