0) {
$attachment_url = wp_get_attachment_url($attachment_id);
if ($attachment_url) {
$file_url = esc_url_raw($attachment_url);
}
}
$extracted_fields = array();
if (isset($record['extracted_fields']) && is_array($record['extracted_fields'])) {
foreach ($record['extracted_fields'] as $field_key => $field_value) {
$field_key = sanitize_key((string) $field_key);
if ('' === $field_key || !is_scalar($field_value)) {
continue;
}
$extracted_fields[$field_key] = sanitize_textarea_field((string) $field_value);
}
}
return array(
'setup_pack_id' => $pack_id,
'attachment_id' => $attachment_id,
'file_name' => isset($record['file_name']) ? sanitize_file_name((string) $record['file_name']) : '',
'file_url' => $file_url,
'file_type' => 'application/pdf',
'uploaded_at' => isset($record['uploaded_at']) ? absint($record['uploaded_at']) : 0,
'uploaded_by' => isset($record['uploaded_by']) ? absint($record['uploaded_by']) : 0,
'extracted_at' => isset($record['extracted_at']) ? absint($record['extracted_at']) : 0,
'extracted_field_count' => isset($record['extracted_field_count']) ? absint($record['extracted_field_count']) : 0,
'extracted_fields' => $extracted_fields,
);
}
}
if (!function_exists('matewa_agency_client_pdf_get_records')) {
function matewa_agency_client_pdf_get_records() {
$records = get_option(MATEWA_AGENCY_CLIENT_PDF_UPLOADS_OPTION, array());
$records = is_array($records) ? $records : array();
$safe = array();
foreach ($records as $pack_id => $record) {
$clean = matewa_agency_client_pdf_clean_record($record, $pack_id);
if (!empty($clean['setup_pack_id']) && !empty($clean['attachment_id'])) {
$safe[$clean['setup_pack_id']] = $clean;
}
}
return $safe;
}
}
if (!function_exists('matewa_agency_client_pdf_store_records')) {
function matewa_agency_client_pdf_store_records($records) {
$records = is_array($records) ? $records : array();
$safe = array();
foreach ($records as $pack_id => $record) {
$clean = matewa_agency_client_pdf_clean_record($record, $pack_id);
if (!empty($clean['setup_pack_id']) && !empty($clean['attachment_id'])) {
$safe[$clean['setup_pack_id']] = $clean;
}
}
update_option(MATEWA_AGENCY_CLIENT_PDF_UPLOADS_OPTION, $safe, false);
return true;
}
}
if (!function_exists('matewa_agency_client_pdf_get_record_for_pack')) {
function matewa_agency_client_pdf_get_record_for_pack($pack_id) {
$pack_id = sanitize_key((string) $pack_id);
if ('' === $pack_id) {
return array();
}
$records = matewa_agency_client_pdf_get_records();
return isset($records[$pack_id]) ? $records[$pack_id] : array();
}
}
if (!function_exists('matewa_agency_client_pdf_pack_exists')) {
function matewa_agency_client_pdf_pack_exists($pack_id) {
$pack_id = sanitize_key((string) $pack_id);
if ('' === $pack_id || !function_exists('matewa_agency_client_pack_get_records')) {
return false;
}
foreach (matewa_agency_client_pack_get_records() as $record) {
$record_id = isset($record['setup_pack_id']) ? sanitize_key((string) $record['setup_pack_id']) : '';
if ('' !== $record_id && hash_equals($record_id, $pack_id)) {
return true;
}
}
return false;
}
}
if (!function_exists('matewa_agency_client_pdf_has_available_bundle_seat')) {
function matewa_agency_client_pdf_has_available_bundle_seat() {
if (!function_exists('matewa_agency_bundle_get_records') || !function_exists('matewa_agency_client_pack_find_available_bundle_index')) {
return false;
}
$bundle_records = matewa_agency_bundle_get_records();
return matewa_agency_client_pack_find_available_bundle_index($bundle_records) >= 0;
}
}
if (!function_exists('matewa_agency_client_pdf_draft_name_from_file')) {
function matewa_agency_client_pdf_draft_name_from_file($file_name) {
$file_name = sanitize_file_name((string) $file_name);
$base = preg_replace('/\.pdf$/i', '', $file_name);
$base = preg_replace('/[\-_]+/', ' ', (string) $base);
$base = preg_replace('/\b(247chatmate|client|setup|form|completed|complete|pdf|review|copy|final)\b/i', ' ', (string) $base);
$base = preg_replace('/\s+/', ' ', (string) $base);
$base = trim((string) $base, " \t\n\r\0\x0B-_");
if ('' === $base) {
return 'PDF Review - ' . date_i18n('j M Y H:i');
}
$base = sanitize_text_field($base);
if (function_exists('mb_substr')) {
$base = mb_substr($base, 0, 72);
} else {
$base = substr($base, 0, 72);
}
return trim($base);
}
}
if (!function_exists('matewa_agency_client_pdf_decode_pdf_string_value')) {
function matewa_agency_client_pdf_decode_pdf_string_value($raw) {
$raw = (string) $raw;
$out = '';
$length = strlen($raw);
for ($i = 0; $i < $length; $i++) {
$char = $raw[$i];
if ('\\' !== $char) {
$out .= $char;
continue;
}
$i++;
if ($i >= $length) {
break;
}
$next = $raw[$i];
if (preg_match('/[0-7]/', $next)) {
$octal = $next;
for ($j = 0; $j < 2 && ($i + 1) < $length && preg_match('/[0-7]/', $raw[$i + 1]); $j++) {
$i++;
$octal .= $raw[$i];
}
$out .= chr(octdec($octal));
continue;
}
switch ($next) {
case 'n':
$out .= "\n";
break;
case 'r':
$out .= "\r";
break;
case 't':
$out .= "\t";
break;
case 'b':
$out .= "\x08";
break;
case 'f':
$out .= "\x0c";
break;
case '(':
case ')':
case '\\':
$out .= $next;
break;
case "\r":
if (($i + 1) < $length && "\n" === $raw[$i + 1]) {
$i++;
}
break;
case "\n":
break;
default:
$out .= $next;
break;
}
}
if (strlen($out) >= 2 && "\xfe\xff" === substr($out, 0, 2) && function_exists('mb_convert_encoding')) {
$converted = @mb_convert_encoding(substr($out, 2), 'UTF-8', 'UTF-16BE');
if (is_string($converted) && '' !== $converted) {
$out = $converted;
}
}
$out = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F]+/', ' ', (string) $out);
$out = preg_replace('/[ \t]+/', ' ', (string) $out);
$out = preg_replace('/\s*\n\s*/', "\n", (string) $out);
return trim((string) $out);
}
}
if (!function_exists('matewa_agency_client_pdf_decode_pdf_hex_string')) {
function matewa_agency_client_pdf_decode_pdf_hex_string($raw) {
$hex = preg_replace('/[^0-9a-f]/i', '', (string) $raw);
if ('' === $hex) {
return '';
}
if (1 === (strlen($hex) % 2)) {
$hex .= '0';
}
$bytes = @hex2bin($hex);
if (!is_string($bytes)) {
return '';
}
return matewa_agency_client_pdf_decode_pdf_string_value($bytes);
}
}
if (!function_exists('matewa_agency_client_pdf_decode_pdf_name_token')) {
function matewa_agency_client_pdf_decode_pdf_name_token($raw) {
$raw = (string) $raw;
$raw = preg_replace_callback('/#([0-9A-Fa-f]{2})/', function ($matches) {
return chr(hexdec($matches[1]));
}, $raw);
$raw = str_replace(array(' ', '-'), '_', $raw);
return $raw;
}
}
if (!function_exists('matewa_agency_client_pdf_parse_objects')) {
function matewa_agency_client_pdf_parse_objects($content) {
$content = (string) $content;
$objects = array();
if (!preg_match_all('/(\d+)\s+(\d+)\s+obj\b(.*?)endobj/s', $content, $matches, PREG_SET_ORDER)) {
return $objects;
}
foreach ($matches as $match) {
$object_id = isset($match[1]) ? absint($match[1]) : 0;
if ($object_id <= 0) {
continue;
}
$objects[$object_id] = isset($match[3]) ? (string) $match[3] : '';
}
/*
* Some PDF editors save form widgets inside compressed PDF object streams
* (/Type /ObjStm). The first PDF import pass only inspected normal top-level
* objects, so valid AcroForm fields such as business_name and business_type
* could be missed even though the PDF still contained proper fillable fields.
* Expand object streams into the same object map before field extraction.
*/
$object_streams = $objects;
foreach ($object_streams as $stream_object) {
if (false === strpos($stream_object, '/ObjStm') || false === strpos($stream_object, 'stream')) {
continue;
}
$first = null;
$count = null;
if (preg_match('/\/First\s+(\d+)/', $stream_object, $first_match)) {
$first = isset($first_match[1]) ? absint($first_match[1]) : null;
}
if (preg_match('/\/N\s+(\d+)/', $stream_object, $count_match)) {
$count = isset($count_match[1]) ? absint($count_match[1]) : null;
}
if (null === $first || null === $count || $first <= 0 || $count <= 0 || $count > 300) {
continue;
}
$decoded = function_exists('matewa_agency_client_pdf_decode_stream_data') ? matewa_agency_client_pdf_decode_stream_data($stream_object) : '';
if (!is_string($decoded) || '' === $decoded || strlen($decoded) <= $first) {
continue;
}
$header = substr($decoded, 0, $first);
$body = substr($decoded, $first);
$tokens = preg_split('/\s+/', trim((string) $header));
$tokens = is_array($tokens) ? array_values(array_filter($tokens, 'strlen')) : array();
if (count($tokens) < ($count * 2)) {
continue;
}
$pairs = array();
for ($i = 0; $i < ($count * 2); $i += 2) {
if (!isset($tokens[$i], $tokens[$i + 1]) || !is_numeric($tokens[$i]) || !is_numeric($tokens[$i + 1])) {
continue 2;
}
$pairs[] = array(absint($tokens[$i]), absint($tokens[$i + 1]));
}
$body_length = strlen($body);
foreach ($pairs as $index => $pair) {
$embedded_object_id = isset($pair[0]) ? absint($pair[0]) : 0;
$offset = isset($pair[1]) ? absint($pair[1]) : 0;
if ($embedded_object_id <= 0 || $offset < 0 || $offset >= $body_length) {
continue;
}
$next_offset = $body_length;
if (isset($pairs[$index + 1][1])) {
$next_offset = absint($pairs[$index + 1][1]);
}
if ($next_offset <= $offset || $next_offset > $body_length) {
$next_offset = $body_length;
}
$embedded_object = trim((string) substr($body, $offset, $next_offset - $offset));
if ('' === $embedded_object) {
continue;
}
$objects[$embedded_object_id] = $embedded_object;
}
}
ksort($objects, SORT_NUMERIC);
return $objects;
}
}
if (!function_exists('matewa_agency_client_pdf_read_token_after_key')) {
function matewa_agency_client_pdf_read_token_after_key($source, $key) {
$source = (string) $source;
$key = (string) $key;
$pattern = '/' . preg_quote($key, '/') . '(?![A-Za-z0-9_#])/';
if (!preg_match($pattern, $source, $key_match, PREG_OFFSET_CAPTURE)) {
return null;
}
$pos = isset($key_match[0][1]) ? (int) $key_match[0][1] : -1;
if ($pos < 0) {
return null;
}
$i = $pos + strlen($key);
$length = strlen($source);
while ($i < $length && preg_match('/\s/', $source[$i])) {
$i++;
}
if ($i >= $length) {
return null;
}
$char = $source[$i];
if ('(' === $char) {
$i++;
$depth = 1;
$raw = '';
while ($i < $length && $depth > 0) {
$c = $source[$i];
if ('\\' === $c) {
$raw .= $c;
$i++;
if ($i < $length) {
$raw .= $source[$i];
if (preg_match('/[0-7]/', $source[$i])) {
for ($j = 0; $j < 2 && ($i + 1) < $length && preg_match('/[0-7]/', $source[$i + 1]); $j++) {
$i++;
$raw .= $source[$i];
}
}
}
$i++;
continue;
}
if ('(' === $c) {
$depth++;
$raw .= $c;
$i++;
continue;
}
if (')' === $c) {
$depth--;
if ($depth > 0) {
$raw .= $c;
}
$i++;
continue;
}
$raw .= $c;
$i++;
}
return matewa_agency_client_pdf_decode_pdf_string_value($raw);
}
if ('<' === $char && (($i + 1) >= $length || '<' !== $source[$i + 1])) {
$end = strpos($source, '>', $i + 1);
if (false === $end) {
return null;
}
return matewa_agency_client_pdf_decode_pdf_hex_string(substr($source, $i + 1, $end - $i - 1));
}
if ('/' === $char) {
$i++;
$raw = '';
while ($i < $length && !preg_match('/[\s<>\[\]\(\)\/]/', $source[$i])) {
$raw .= $source[$i];
$i++;
}
return sanitize_key(matewa_agency_client_pdf_decode_pdf_name_token($raw));
}
$raw = '';
while ($i < $length && !preg_match('/\s/', $source[$i])) {
$raw .= $source[$i];
$i++;
}
return trim($raw);
}
}
if (!function_exists('matewa_agency_client_pdf_ascii85_decode')) {
function matewa_agency_client_pdf_ascii85_decode($data) {
$data = preg_replace('/\s+/', '', (string) $data);
$data = str_replace(array('<~', '~>'), '', $data);
$out = '';
$group = array();
$length = strlen($data);
for ($i = 0; $i < $length; $i++) {
$ch = $data[$i];
if ('z' === $ch && empty($group)) {
$out .= "\0\0\0\0";
continue;
}
$ord = ord($ch);
if ($ord < 33 || $ord > 117) {
continue;
}
$group[] = $ord - 33;
if (5 === count($group)) {
$value = 0;
foreach ($group as $digit) {
$value = ($value * 85) + $digit;
}
$out .= chr(($value >> 24) & 255) . chr(($value >> 16) & 255) . chr(($value >> 8) & 255) . chr($value & 255);
$group = array();
}
}
if (!empty($group)) {
$count = count($group);
while (count($group) < 5) {
$group[] = 84;
}
$value = 0;
foreach ($group as $digit) {
$value = ($value * 85) + $digit;
}
$bytes = chr(($value >> 24) & 255) . chr(($value >> 16) & 255) . chr(($value >> 8) & 255) . chr($value & 255);
$out .= substr($bytes, 0, max(0, $count - 1));
}
return $out;
}
}
if (!function_exists('matewa_agency_client_pdf_decode_stream_data')) {
function matewa_agency_client_pdf_decode_stream_data($object) {
$object = (string) $object;
if (!preg_match('/stream\r?\n(.*?)\r?\nendstream/s', $object, $stream_match)) {
if (!preg_match('/stream\r(.*?)\rendstream/s', $object, $stream_match)) {
return '';
}
}
$data = isset($stream_match[1]) ? (string) $stream_match[1] : '';
if ('' === $data) {
return '';
}
$filters = array();
if (preg_match('/\/Filter\s*\[([^\]]+)\]/s', $object, $filter_match)) {
if (preg_match_all('/\/([A-Za-z0-9]+)/', $filter_match[1], $filter_names)) {
$filters = $filter_names[1];
}
} elseif (preg_match('/\/Filter\s*\/([A-Za-z0-9]+)/', $object, $filter_match)) {
$filters = array($filter_match[1]);
}
foreach ($filters as $filter) {
$filter = (string) $filter;
if ('ASCII85Decode' === $filter || 'A85' === $filter) {
$data = matewa_agency_client_pdf_ascii85_decode($data);
} elseif ('FlateDecode' === $filter || 'Fl' === $filter) {
$decoded = @gzuncompress($data);
if (!is_string($decoded)) {
$decoded = @gzinflate($data);
}
if (!is_string($decoded)) {
$decoded = @gzdecode($data);
}
if (is_string($decoded) && '' !== $decoded) {
$data = $decoded;
}
}
}
return is_string($data) ? $data : '';
}
}
if (!function_exists('matewa_agency_client_pdf_extract_text_chunks_from_stream')) {
function matewa_agency_client_pdf_extract_text_chunks_from_stream($stream) {
$stream = (string) $stream;
if ('' === $stream) {
return array();
}
$chunks = array();
if (preg_match_all('/\(((?:\\.|[^\\()])*)\)\s*Tj\b/s', $stream, $matches)) {
foreach ($matches[1] as $raw) {
$text = matewa_agency_client_pdf_decode_pdf_string_value($raw);
$text = trim(preg_replace('/\s+/', ' ', (string) $text));
if ('' !== $text) {
$chunks[] = $text;
}
}
}
if (preg_match_all('/<([0-9A-Fa-f\s]+)>\s*Tj\b/s', $stream, $matches)) {
foreach ($matches[1] as $raw) {
$text = matewa_agency_client_pdf_decode_pdf_hex_string($raw);
$text = trim(preg_replace('/\s+/', ' ', (string) $text));
if ('' !== $text) {
$chunks[] = $text;
}
}
}
if (preg_match_all('/\[(.*?)\]\s*TJ\b/s', $stream, $matches)) {
foreach ($matches[1] as $array_source) {
$parts = array();
if (preg_match_all('/\(((?:\\.|[^\\()])*)\)|<([0-9A-Fa-f\s]+)>/s', $array_source, $part_matches, PREG_SET_ORDER)) {
foreach ($part_matches as $part) {
if (isset($part[1]) && '' !== $part[1]) {
$parts[] = matewa_agency_client_pdf_decode_pdf_string_value($part[1]);
} elseif (isset($part[2]) && '' !== $part[2]) {
$parts[] = matewa_agency_client_pdf_decode_pdf_hex_string($part[2]);
}
}
}
$text = trim(preg_replace('/\s+/', ' ', implode('', $parts)));
if ('' !== $text) {
$chunks[] = $text;
}
}
}
$out = array();
foreach ($chunks as $chunk) {
$chunk = trim(wp_strip_all_tags((string) $chunk));
if ('' === $chunk) {
continue;
}
$out[] = $chunk;
}
return array_values(array_unique($out));
}
}
if (!function_exists('matewa_agency_client_pdf_first_safe_appearance_text')) {
function matewa_agency_client_pdf_first_safe_appearance_text($texts) {
$texts = is_array($texts) ? $texts : array();
foreach ($texts as $text) {
$text = trim((string) $text);
if ('' === $text) {
continue;
}
$normal = strtolower($text);
if (in_array($normal, array('off', 'yes', 'on', 'true', 'false'), true)) {
continue;
}
if (strlen($text) > 500) {
$text = substr($text, 0, 500);
}
return $text;
}
return '';
}
}
if (!function_exists('matewa_agency_client_pdf_extract_fillable_fields_from_file')) {
function matewa_agency_client_pdf_extract_fillable_fields_from_file($file_path) {
$file_path = (string) $file_path;
if ('' === $file_path || !is_readable($file_path)) {
return array();
}
$size = @filesize($file_path);
if (false !== $size && $size > 12 * 1024 * 1024) {
return array();
}
$content = @file_get_contents($file_path);
if (!is_string($content) || '' === $content) {
return array();
}
$wanted = array(
'business_name' => true,
'website_domain' => true,
'client_contact_name' => true,
'main_admin_email' => true,
'leads_email' => true,
'whatsapp_mobile' => true,
'business_type' => true,
'country_language' => true,
'placement_homepage' => true,
'placement_all_pages' => true,
'placement_specific_pages' => true,
'visitor_button_notes' => true,
'google_business_profile' => true,
'instagram_link' => true,
'facebook_link' => true,
'review_link' => true,
'additional_notes' => true,
'confirm_correct' => true,
'confirmed_by' => true,
'confirmed_date' => true,
);
for ($i = 1; $i <= 8; $i++) {
$wanted['page_' . $i] = true;
}
$fields = array();
$objects = matewa_agency_client_pdf_parse_objects($content);
$parsed_objects = array();
foreach ($objects as $object_id => $object) {
if (false === strpos($object, '/T') && false === strpos($object, '/V') && false === strpos($object, '/Parent') && false === strpos($object, 'stream')) {
continue;
}
$name = matewa_agency_client_pdf_read_token_after_key($object, '/T');
$name = is_scalar($name) ? sanitize_key((string) $name) : '';
$value = matewa_agency_client_pdf_read_token_after_key($object, '/V');
$has_value = null !== $value;
$parent_id = 0;
if (preg_match('/\/Parent\s+(\d+)\s+\d+\s+R\b/', $object, $parent_match)) {
$parent_id = isset($parent_match[1]) ? absint($parent_match[1]) : 0;
}
$appearance_id = 0;
if (preg_match('/\/AP\s*<<.*?\/N\s+(\d+)\s+\d+\s+R.*?>>/s', $object, $appearance_match)) {
$appearance_id = isset($appearance_match[1]) ? absint($appearance_match[1]) : 0;
}
$stream_texts = array();
if (function_exists('matewa_agency_client_pdf_decode_stream_data') && function_exists('matewa_agency_client_pdf_extract_text_chunks_from_stream')) {
$stream_texts = matewa_agency_client_pdf_extract_text_chunks_from_stream(matewa_agency_client_pdf_decode_stream_data($object));
}
$parsed_objects[$object_id] = array(
'name' => $name,
'value' => $has_value && is_scalar($value) ? trim((string) $value) : '',
'has_value' => $has_value,
'parent_id' => $parent_id,
'appearance_id' => $appearance_id,
'stream_texts' => $stream_texts,
);
}
/* First pass: standard AcroForm fields where /T and /V live in the same object. */
foreach ($parsed_objects as $parsed) {
$name = isset($parsed['name']) ? sanitize_key((string) $parsed['name']) : '';
if ('' === $name || !isset($wanted[$name]) || empty($parsed['has_value'])) {
continue;
}
$value = isset($parsed['value']) && is_scalar($parsed['value']) ? trim((string) $parsed['value']) : '';
if (!isset($fields[$name]) || '' === $fields[$name] || '' !== $value) {
$fields[$name] = $value;
}
}
/* Second pass: some PDF editors save /V on a child widget and keep /T on the parent field. */
foreach ($parsed_objects as $parsed) {
if (empty($parsed['has_value'])) {
continue;
}
$name = isset($parsed['name']) ? sanitize_key((string) $parsed['name']) : '';
if ('' === $name && !empty($parsed['parent_id']) && isset($parsed_objects[$parsed['parent_id']]['name'])) {
$name = sanitize_key((string) $parsed_objects[$parsed['parent_id']]['name']);
}
if ('' === $name || !isset($wanted[$name])) {
continue;
}
$value = isset($parsed['value']) && is_scalar($parsed['value']) ? trim((string) $parsed['value']) : '';
if (!isset($fields[$name]) || '' === $fields[$name] || '' !== $value) {
$fields[$name] = $value;
}
}
/* Third pass: if a parent has a value but a child provided the display name, keep the non-empty value. */
foreach ($parsed_objects as $object_id => $parsed) {
if (!empty($parsed['has_value']) || empty($parsed['name'])) {
continue;
}
$name = sanitize_key((string) $parsed['name']);
if ('' === $name || !isset($wanted[$name])) {
continue;
}
foreach ($parsed_objects as $child) {
$child_parent = isset($child['parent_id']) ? absint($child['parent_id']) : 0;
if ($child_parent !== absint($object_id) || empty($child['has_value'])) {
continue;
}
$value = isset($child['value']) && is_scalar($child['value']) ? trim((string) $child['value']) : '';
if (!isset($fields[$name]) || '' === $fields[$name] || '' !== $value) {
$fields[$name] = $value;
}
}
}
/* Fourth pass: recover values from PDF appearance streams when a PDF editor draws text but does not save /V cleanly. */
foreach ($parsed_objects as $object_id => $parsed) {
$name = isset($parsed['name']) ? sanitize_key((string) $parsed['name']) : '';
if ('' === $name || !isset($wanted[$name])) {
continue;
}
if (isset($fields[$name]) && '' !== trim((string) $fields[$name]) && 'off' !== sanitize_key((string) $fields[$name])) {
continue;
}
$appearance_text = '';
if (!empty($parsed['stream_texts']) && function_exists('matewa_agency_client_pdf_first_safe_appearance_text')) {
$appearance_text = matewa_agency_client_pdf_first_safe_appearance_text($parsed['stream_texts']);
}
$appearance_id = isset($parsed['appearance_id']) ? absint($parsed['appearance_id']) : 0;
if ('' === $appearance_text && $appearance_id > 0 && isset($parsed_objects[$appearance_id]['stream_texts']) && function_exists('matewa_agency_client_pdf_first_safe_appearance_text')) {
$appearance_text = matewa_agency_client_pdf_first_safe_appearance_text($parsed_objects[$appearance_id]['stream_texts']);
}
if ('' === $appearance_text) {
$next_id = absint($object_id) + 1;
if (isset($parsed_objects[$next_id]['stream_texts']) && function_exists('matewa_agency_client_pdf_first_safe_appearance_text')) {
$appearance_text = matewa_agency_client_pdf_first_safe_appearance_text($parsed_objects[$next_id]['stream_texts']);
}
}
if ('' !== $appearance_text) {
$fields[$name] = $appearance_text;
}
}
foreach ($wanted as $wanted_name => $_enabled) {
if (!isset($fields[$wanted_name])) {
$fields[$wanted_name] = '';
}
}
foreach ($fields as $field_name => $value) {
if (0 === strpos($field_name, 'placement_') || in_array($field_name, array('confirm_correct'), true)) {
$value = sanitize_key((string) $value);
$fields[$field_name] = in_array($value, array('yes', 'on', 'true', '1'), true) ? 'yes' : 'off';
} else {
$value = wp_strip_all_tags((string) $value);
$value = str_replace(array("\r\n", "\r"), "\n", $value);
$value = preg_replace('/[ \t]+/', ' ', $value);
$fields[$field_name] = trim((string) $value);
}
}
return $fields;
}
}
if (!function_exists('matewa_agency_client_pdf_field_value')) {
function matewa_agency_client_pdf_field_value($fields, $key) {
$fields = is_array($fields) ? $fields : array();
$key = sanitize_key((string) $key);
return isset($fields[$key]) && is_scalar($fields[$key]) ? trim((string) $fields[$key]) : '';
}
}
if (!function_exists('matewa_agency_client_pdf_checkbox_is_on')) {
function matewa_agency_client_pdf_checkbox_is_on($fields, $key) {
$value = sanitize_key(matewa_agency_client_pdf_field_value($fields, $key));
return in_array($value, array('yes', 'on', 'true', '1'), true);
}
}
if (!function_exists('matewa_agency_client_pdf_build_page_items_from_fields')) {
function matewa_agency_client_pdf_build_page_items_from_fields($fields, $client_domain = '') {
$fields = is_array($fields) ? $fields : array();
$client_domain = function_exists('matewa_agency_client_pack_normalise_domain') ? matewa_agency_client_pack_normalise_domain($client_domain) : sanitize_text_field((string) $client_domain);
$pages = array();
for ($i = 1; $i <= 8; $i++) {
$raw = matewa_agency_client_pdf_field_value($fields, 'page_' . $i);
if ('' === $raw) {
continue;
}
$raw = trim($raw);
if ('' !== $client_domain && 0 === strpos($raw, '/')) {
$raw = 'https://' . $client_domain . '/' . ltrim($raw, '/');
} elseif ('' !== $client_domain && !preg_match('#^https?://#i', $raw) && false === strpos($raw, '.')) {
$raw = 'https://' . $client_domain . '/' . ltrim($raw, '/');
}
$url = function_exists('matewa_agency_client_pack_clean_page_url') ? matewa_agency_client_pack_clean_page_url($raw, $client_domain) : esc_url_raw($raw);
if ('' === $url) {
continue;
}
$path = wp_parse_url($url, PHP_URL_PATH);
$path = trim((string) $path, '/');
$title = '' === $path ? 'Homepage' : ucwords(str_replace(array('-', '_', '/'), ' ', $path));
$pages[] = array(
'url' => $url,
'title' => $title,
'source' => 'pdf',
);
}
return function_exists('matewa_agency_client_pack_clean_page_list') ? matewa_agency_client_pack_clean_page_list($pages, $client_domain, 8) : $pages;
}
}
if (!function_exists('matewa_agency_client_pdf_build_import_data_from_fields')) {
function matewa_agency_client_pdf_build_import_data_from_fields($fields, $file_name = '', $business_type_hint = '') {
$fields = is_array($fields) ? $fields : array();
$client_business = sanitize_text_field(matewa_agency_client_pdf_field_value($fields, 'business_name'));
$client_domain = function_exists('matewa_agency_client_pack_normalise_domain') ? matewa_agency_client_pack_normalise_domain(matewa_agency_client_pdf_field_value($fields, 'website_domain')) : sanitize_text_field(matewa_agency_client_pdf_field_value($fields, 'website_domain'));
$client_admin_email = sanitize_email(matewa_agency_client_pdf_field_value($fields, 'main_admin_email'));
$leads_email = sanitize_email(matewa_agency_client_pdf_field_value($fields, 'leads_email'));
$whatsapp_number = function_exists('matewa_agency_client_pack_clean_phone') ? matewa_agency_client_pack_clean_phone(matewa_agency_client_pdf_field_value($fields, 'whatsapp_mobile')) : sanitize_text_field(matewa_agency_client_pdf_field_value($fields, 'whatsapp_mobile'));
$business_type_text = sanitize_text_field(matewa_agency_client_pdf_field_value($fields, 'business_type'));
$selected_pages = matewa_agency_client_pdf_build_page_items_from_fields($fields, $client_domain);
if (!empty($selected_pages) || matewa_agency_client_pdf_checkbox_is_on($fields, 'placement_specific_pages')) {
$page_mode = 'specific_pages';
} elseif (matewa_agency_client_pdf_checkbox_is_on($fields, 'placement_homepage')) {
$page_mode = 'homepage';
} else {
$page_mode = 'all_pages';
}
$raw_summary = array();
foreach (array(
'business_name', 'website_domain', 'main_admin_email', 'leads_email', 'whatsapp_mobile', 'business_type', 'country_language',
'visitor_button_notes', 'google_business_profile', 'instagram_link', 'facebook_link', 'review_link', 'additional_notes', 'confirmed_by', 'confirmed_date'
) as $field_key) {
$value = matewa_agency_client_pdf_field_value($fields, $field_key);
if ('' !== $value) {
$raw_summary[$field_key] = sanitize_textarea_field($value);
}
}
$found = 0;
foreach ($fields as $value) {
if (is_scalar($value) && '' !== trim((string) $value) && 'off' !== sanitize_key((string) $value)) {
$found++;
}
}
return array(
'client_business' => $client_business,
'client_domain' => $client_domain,
'client_admin_email' => $client_admin_email,
'leads_email' => $leads_email,
'whatsapp_number' => $whatsapp_number,
'business_type_text' => $business_type_text,
'country_language' => sanitize_text_field(matewa_agency_client_pdf_field_value($fields, 'country_language')),
'page_mode' => $page_mode,
'detected_pages' => $selected_pages,
'selected_pages' => $selected_pages,
'extracted_fields' => $raw_summary,
'extracted_field_count' => absint($found),
'has_extracted_fields' => $found > 0,
);
}
}
if (!function_exists('matewa_agency_client_pdf_match_normalise_text')) {
function matewa_agency_client_pdf_match_normalise_text($value) {
$value = is_scalar($value) ? (string) $value : '';
$value = html_entity_decode(wp_strip_all_tags($value), ENT_QUOTES, 'UTF-8');
$value = strtolower($value);
$value = str_replace(array('&', '+'), ' and ', $value);
$value = preg_replace('/[^a-z0-9]+/i', ' ', (string) $value);
$value = preg_replace('/\s+/', ' ', (string) $value);
return trim((string) $value);
}
}
if (!function_exists('matewa_agency_client_pdf_match_text_contains_phrase')) {
function matewa_agency_client_pdf_match_text_contains_phrase($haystack, $phrase) {
$haystack = ' ' . matewa_agency_client_pdf_match_normalise_text($haystack) . ' ';
$phrase = matewa_agency_client_pdf_match_normalise_text($phrase);
if ('' === $phrase) {
return false;
}
if (false !== strpos($haystack, ' ' . $phrase . ' ')) {
return true;
}
$words = preg_split('/\s+/', $phrase);
if (!is_array($words) || empty($words)) {
return false;
}
$last_index = count($words) - 1;
if (isset($words[$last_index]) && strlen((string) $words[$last_index]) > 3 && 's' !== substr((string) $words[$last_index], -1)) {
$words[$last_index] .= 's';
return false !== strpos($haystack, ' ' . implode(' ', $words) . ' ');
}
return false;
}
}
if (!function_exists('matewa_agency_client_pdf_business_type_synonyms')) {
function matewa_agency_client_pdf_business_type_synonyms() {
return array(
'aerial_installer' => array('aerial installer', 'tv aerial', 'satellite installer', 'antenna installer'),
'appliance_repair' => array('appliance repair', 'appliance repairs', 'washing machine repair', 'oven repair', 'dishwasher repair'),
'bathroom_fitter' => array('bathroom fitter', 'bathroom fitters', 'bathroom installer', 'bathroom installation'),
'builder' => array('builder', 'builders', 'building contractor', 'building work'),
'car_dealer' => array('car dealer', 'car dealers', 'used cars', 'used car', 'car sales', 'vehicle sales', 'motors', 'cars'),
'car_detailing' => array('car detailing', 'detailing', 'car valeting', 'valeting'),
'car_repair' => array('car repair', 'car repairs', 'mechanic', 'mechanics', 'garage', 'vehicle repair', 'vehicle repairs', 'auto repair'),
'carpenter_joiner' => array('carpenter', 'carpenters', 'joiner', 'joiners', 'joinery', 'carpentry'),
'cleaner' => array('cleaner', 'cleaners', 'cleaning company', 'domestic cleaning', 'commercial cleaning'),
'decorator' => array('decorator', 'decorators', 'painter', 'painters', 'painting', 'decorating', 'painter decorator'),
'painter_decorator' => array('decorator', 'decorators', 'painter', 'painters', 'painting', 'decorating', 'painter decorator'),
'drainage' => array('drainage', 'drains', 'blocked drain', 'blocked drains', 'drain unblocking'),
'electric_gates' => array('electric gates', 'gate automation', 'automated gates'),
'electrician' => array('electrician', 'electricians', 'electrical', 'electrical contractor', 'sparky'),
'fencer' => array('fencer', 'fencing', 'fence installer', 'fence installation'),
'flooring_installer' => array('flooring installer', 'floor fitter', 'flooring', 'carpet fitter', 'laminate floor'),
'gardener' => array('gardener', 'gardeners', 'gardening', 'garden maintenance'),
'glazier' => array('glazier', 'glazing', 'glass repair', 'window glass'),
'guttering_fascias_soffits'=> array('guttering', 'gutters', 'fascias', 'soffits', 'fascia soffit'),
'handyman' => array('handyman', 'handy man', 'property maintenance'),
'home_networking' => array('home networking', 'wifi installer', 'network installer', 'home wifi'),
'hvac' => array('hvac', 'air conditioning', 'air con', 'heating ventilation'),
'it_services' => array('it services', 'it support', 'computer support', 'managed it'),
'landscaper' => array('landscaper', 'landscapers', 'landscaping', 'garden design'),
'locksmith' => array('locksmith', 'locksmiths', 'locks', 'lock repair'),
'mobile_mechanic' => array('mobile mechanic', 'mobile mechanics', 'mobile car repair', 'mobile vehicle repair'),
'mot_garage' => array('mot garage', 'mot test', 'mot testing', 'mot'),
'plasterer' => array('plasterer', 'plasterers', 'plastering', 'renderer', 'rendering'),
'plumber' => array('plumber', 'plumbers', 'plumbing', 'boiler', 'boilers', 'gas engineer', 'heating engineer', 'central heating'),
'roofer' => array('roofer', 'roofers', 'roofing', 'roof repair', 'roof repairs', 'leaking roof'),
'tiler' => array('tiler', 'tilers', 'tiling', 'wall tiling', 'floor tiling'),
'tree_surgeon' => array('tree surgeon', 'tree surgeons', 'tree surgery', 'arborist'),
'tyre_fitting' => array('tyre fitting', 'tyres', 'tyre', 'tire', 'tires'),
'window_cleaner' => array('window cleaner', 'window cleaners', 'window cleaning'),
'window_door_installer' => array('window installer', 'door installer', 'windows and doors', 'double glazing'),
);
}
}
if (!function_exists('matewa_agency_client_pdf_trade_match_groups')) {
function matewa_agency_client_pdf_trade_match_groups() {
return array(
'plumber' => array(
'source' => array('plumber', 'plumbers', 'plumbing', 'boiler', 'boilers', 'gas engineer', 'gas engineers', 'heating engineer', 'heating engineers', 'central heating'),
'candidate' => array('plumber', 'plumbers', 'plumbing', 'boiler', 'boilers', 'gas', 'heating', 'central heating'),
),
'electrician' => array(
'source' => array('electrician', 'electricians', 'electrical', 'electrical contractor', 'sparky'),
'candidate' => array('electrician', 'electricians', 'electrical', 'electric'),
),
'roofer' => array(
'source' => array('roofer', 'roofers', 'roofing', 'roof repair', 'leaking roof'),
'candidate' => array('roofer', 'roofers', 'roofing', 'roof'),
),
'car_dealer' => array(
'source' => array('car dealer', 'used cars', 'used car', 'car sales', 'vehicle sales', 'jims cars', 'cars'),
'candidate' => array('car dealer', 'used cars', 'used car', 'car sales', 'vehicle sales', 'dealer', 'dealership', 'motors'),
),
'car_repair' => array(
'source' => array('car repair', 'car repairs', 'mechanic', 'mechanics', 'garage', 'vehicle repair', 'auto repair'),
'candidate' => array('car repair', 'vehicle repair', 'mechanic', 'garage', 'auto repair'),
),
'mobile_mechanic' => array(
'source' => array('mobile mechanic', 'mobile mechanics', 'mobile car repair', 'mobile vehicle repair'),
'candidate' => array('mobile mechanic', 'mobile mechanics', 'mobile car repair', 'mobile vehicle repair'),
),
'cleaner' => array(
'source' => array('cleaner', 'cleaners', 'cleaning', 'domestic cleaning', 'commercial cleaning'),
'candidate' => array('cleaner', 'cleaners', 'cleaning'),
),
'gardener' => array(
'source' => array('gardener', 'gardeners', 'gardening', 'garden maintenance'),
'candidate' => array('gardener', 'gardeners', 'gardening', 'garden maintenance'),
),
'locksmith' => array(
'source' => array('locksmith', 'locksmiths', 'locks'),
'candidate' => array('locksmith', 'locksmiths', 'locks'),
),
'carpenter_joiner' => array(
'source' => array('carpenter', 'carpenters', 'joiner', 'joiners', 'joinery', 'carpentry'),
'candidate' => array('carpenter', 'carpenters', 'joiner', 'joiners', 'joinery', 'carpentry'),
),
'builder' => array(
'source' => array('builder', 'builders', 'building contractor', 'building work'),
'candidate' => array('builder', 'builders', 'building contractor', 'building'),
),
);
}
}
if (!function_exists('matewa_agency_client_pdf_text_has_any_phrase')) {
function matewa_agency_client_pdf_text_has_any_phrase($text, $phrases) {
$phrases = is_array($phrases) ? $phrases : array();
foreach ($phrases as $phrase) {
if (matewa_agency_client_pdf_match_text_contains_phrase($text, $phrase)) {
return true;
}
}
return false;
}
}
if (!function_exists('matewa_agency_client_pdf_match_business_type_from_text')) {
function matewa_agency_client_pdf_match_business_type_from_text($source_text) {
$source_text = matewa_agency_client_pdf_match_normalise_text($source_text);
if ('' === $source_text || !function_exists('matewa_agency_client_pack_get_selector_data')) {
return array();
}
$selector = matewa_agency_client_pack_get_selector_data();
$categories = isset($selector['categories']) && is_array($selector['categories']) ? $selector['categories'] : array();
$synonyms = matewa_agency_client_pdf_business_type_synonyms();
$stop_words = array('and' => true, 'the' => true, 'for' => true, 'with' => true, 'setup' => true, 'pdf' => true, 'review' => true, 'test' => true, 'client' => true, 'business' => true, 'company' => true, 'limited' => true, 'ltd' => true, 'uk' => true, 'service' => true, 'services' => true);
$best = array();
$best_score = 0;
foreach ($categories as $category_key => $category_data) {
$category_key = sanitize_key((string) $category_key);
$options = isset($category_data['options']) && is_array($category_data['options']) ? $category_data['options'] : array();
foreach ($options as $vertical_key => $vertical_data) {
$vertical_key = sanitize_key((string) $vertical_key);
if ('' === $vertical_key || 'general' === $vertical_key) {
continue;
}
$label = isset($vertical_data['display_label']) ? sanitize_text_field((string) $vertical_data['display_label']) : ucwords(str_replace('_', ' ', $vertical_key));
$phrases = array($vertical_key, str_replace('_', ' ', $vertical_key), $label);
if (isset($synonyms[$vertical_key]) && is_array($synonyms[$vertical_key])) {
$phrases = array_merge($phrases, $synonyms[$vertical_key]);
}
$score = 0;
$unique_phrases = array_unique(array_filter($phrases));
foreach ($unique_phrases as $phrase) {
$normalised_phrase = matewa_agency_client_pdf_match_normalise_text($phrase);
if ('' !== $normalised_phrase && $source_text === $normalised_phrase) {
$exact_score = 240 + strlen($normalised_phrase);
if ($vertical_key === sanitize_key(str_replace(' ', '_', $normalised_phrase))) {
$exact_score += 30;
}
if (isset($synonyms[$vertical_key]) && in_array($phrase, $synonyms[$vertical_key], true)) {
$exact_score += 20;
}
$score = max($score, $exact_score);
}
}
foreach ($unique_phrases as $phrase) {
if (matewa_agency_client_pdf_match_text_contains_phrase($source_text, $phrase)) {
$phrase_score = 80 + strlen(matewa_agency_client_pdf_match_normalise_text($phrase));
if (isset($synonyms[$vertical_key]) && in_array($phrase, $synonyms[$vertical_key], true)) {
$phrase_score += 30;
}
$score = max($score, $phrase_score);
}
}
if ($score < 70) {
$tokens = preg_split('/\s+/', matewa_agency_client_pdf_match_normalise_text($label . ' ' . str_replace('_', ' ', $vertical_key)));
$tokens = is_array($tokens) ? array_values(array_unique(array_filter($tokens))) : array();
$meaningful = array();
foreach ($tokens as $token) {
$token = trim((string) $token);
if (strlen($token) < 4 || isset($stop_words[$token])) {
continue;
}
$meaningful[] = $token;
}
$hits = 0;
foreach ($meaningful as $token) {
if (matewa_agency_client_pdf_match_text_contains_phrase($source_text, $token)) {
$hits++;
}
}
if (!empty($meaningful) && $hits === count($meaningful)) {
$score = max($score, 70 + ($hits * 8));
} elseif ($hits >= 2) {
$score = max($score, 64 + ($hits * 6));
}
}
if ($score < 95 && function_exists('matewa_agency_client_pdf_trade_match_groups')) {
$candidate_text = $label . ' ' . str_replace('_', ' ', $vertical_key);
foreach (matewa_agency_client_pdf_trade_match_groups() as $trade_group) {
if (!is_array($trade_group)) {
continue;
}
$source_phrases = isset($trade_group['source']) && is_array($trade_group['source']) ? $trade_group['source'] : array();
$candidate_phrases = isset($trade_group['candidate']) && is_array($trade_group['candidate']) ? $trade_group['candidate'] : array();
if (matewa_agency_client_pdf_text_has_any_phrase($source_text, $source_phrases) && matewa_agency_client_pdf_text_has_any_phrase($candidate_text, $candidate_phrases)) {
$score = max($score, 118);
break;
}
}
}
if ($score > $best_score) {
$best_score = $score;
$best = array(
'category_key' => $category_key,
'vertical_key' => $vertical_key,
'vertical_label' => $label,
'score' => $score,
);
}
}
}
return $best_score >= 80 ? $best : array();
}
}
if (!function_exists('matewa_agency_client_pdf_resolve_vertical_selection')) {
function matewa_agency_client_pdf_resolve_vertical_selection($file_name, $business_type_hint = '', $pdf_business_type = '', $pdf_client_business = '') {
$business_type_hint = sanitize_text_field((string) $business_type_hint);
$pdf_business_type = sanitize_text_field((string) $pdf_business_type);
$file_name = sanitize_file_name((string) $file_name);
$sources = array();
if ('' !== trim($pdf_business_type)) {
$sources['pdf_field'] = $pdf_business_type;
}
if ('' !== trim($business_type_hint)) {
$sources['hint'] = $business_type_hint;
}
if ('' !== trim($file_name)) {
$sources['filename'] = preg_replace('/\.pdf$/i', '', $file_name);
}
foreach ($sources as $source => $text) {
$match = matewa_agency_client_pdf_match_business_type_from_text($text);
if (!empty($match['vertical_key']) && function_exists('matewa_agency_client_pack_resolve_vertical_selection')) {
$selection = matewa_agency_client_pack_resolve_vertical_selection($match['category_key'], $match['vertical_key']);
$selection['pdf_trade_match_source'] = $source;
$selection['pdf_trade_match_score'] = isset($match['score']) ? absint($match['score']) : 0;
return $selection;
}
}
$selection = function_exists('matewa_agency_client_pack_resolve_vertical_selection')
? matewa_agency_client_pack_resolve_vertical_selection('', '')
: array(
'category_key' => 'general',
'category_label' => 'General',
'vertical_key' => 'general',
'vertical_label' => 'General',
'chips' => array('Get a quote', 'Pricing', 'Availability', 'Ask a question', 'Book a job', 'Something else'),
);
$selection['pdf_trade_match_source'] = '';
$selection['pdf_trade_match_score'] = 0;
return $selection;
}
}
if (!function_exists('matewa_agency_client_pdf_create_pending_pack')) {
function matewa_agency_client_pdf_create_pending_pack($file_name, $business_type_hint = '', $pdf_import_data = array()) {
if (!function_exists('matewa_agency_client_pack_get_records') || !function_exists('matewa_agency_client_pack_store_records') || !function_exists('matewa_agency_client_pack_find_available_bundle_index')) {
return new WP_Error('pdf_new_pack_unavailable', 'Client setup pack storage is not available.');
}
if (!function_exists('matewa_agency_bundle_get_records') || !function_exists('matewa_agency_bundle_store_records')) {
return new WP_Error('pdf_new_pack_unavailable', 'Agency bundle storage is not available.');
}
$bundle_records = matewa_agency_bundle_get_records();
$bundle_index = matewa_agency_client_pack_find_available_bundle_index($bundle_records);
if ($bundle_index < 0 || empty($bundle_records[$bundle_index]) || !is_array($bundle_records[$bundle_index])) {
return new WP_Error('pdf_no_seats', 'No active client seats are available.');
}
$bundle = $bundle_records[$bundle_index];
$bundle_id = isset($bundle['bundle_id']) ? sanitize_key((string) $bundle['bundle_id']) : '';
$bundle_used = isset($bundle['used_seats']) ? absint($bundle['used_seats']) : 0;
$bundle_seats = isset($bundle['seats']) ? absint($bundle['seats']) : 0;
$now = time();
$agency_summary = function_exists('matewa_agency_entitlement_get_summary') ? matewa_agency_entitlement_get_summary() : array();
$agency_summary = is_array($agency_summary) ? $agency_summary : array();
$agency_id = isset($agency_summary['agency_id']) ? sanitize_key((string) $agency_summary['agency_id']) : '';
$pdf_import_data = is_array($pdf_import_data) ? $pdf_import_data : array();
$pdf_business_type_text = isset($pdf_import_data['business_type_text']) ? sanitize_text_field((string) $pdf_import_data['business_type_text']) : '';
$pdf_client_business = isset($pdf_import_data['client_business']) ? sanitize_text_field((string) $pdf_import_data['client_business']) : '';
$vertical_selection = matewa_agency_client_pdf_resolve_vertical_selection($file_name, $business_type_hint, $pdf_business_type_text, $pdf_client_business);
$existing_packs = matewa_agency_client_pack_get_records();
$existing_ids = array();
foreach ($existing_packs as $existing_pack) {
if (is_array($existing_pack) && !empty($existing_pack['setup_pack_id'])) {
$existing_ids[sanitize_key((string) $existing_pack['setup_pack_id'])] = true;
}
}
$seed = $agency_id . '|pdf|' . sanitize_file_name((string) $file_name) . '|' . (string) $now . '|' . (string) wp_rand(10000, 999999);
$pack_id = 'pack_' . substr(matewa_agency_client_pack_hash_value($seed), 0, 12);
$guard = 0;
while (isset($existing_ids[$pack_id]) && $guard < 10) {
$seed .= '|' . (string) wp_rand(10000, 999999);
$pack_id = 'pack_' . substr(matewa_agency_client_pack_hash_value($seed), 0, 12);
$guard++;
}
if (isset($existing_ids[$pack_id])) {
return new WP_Error('pdf_new_pack_unavailable', 'A unique setup pack ID could not be generated.');
}
$pdf_client_domain = isset($pdf_import_data['client_domain']) && function_exists('matewa_agency_client_pack_normalise_domain') ? matewa_agency_client_pack_normalise_domain((string) $pdf_import_data['client_domain']) : '';
$pdf_client_admin_email = isset($pdf_import_data['client_admin_email']) ? sanitize_email((string) $pdf_import_data['client_admin_email']) : '';
$pdf_whatsapp_number = isset($pdf_import_data['whatsapp_number']) && function_exists('matewa_agency_client_pack_clean_phone') ? matewa_agency_client_pack_clean_phone((string) $pdf_import_data['whatsapp_number']) : '';
$pdf_leads_email = isset($pdf_import_data['leads_email']) ? sanitize_email((string) $pdf_import_data['leads_email']) : '';
$pdf_page_mode = isset($pdf_import_data['page_mode']) && function_exists('matewa_agency_client_pack_allowed_page_mode') ? matewa_agency_client_pack_allowed_page_mode((string) $pdf_import_data['page_mode']) : 'all_pages';
$pdf_detected_pages = isset($pdf_import_data['detected_pages']) && is_array($pdf_import_data['detected_pages']) && function_exists('matewa_agency_client_pack_clean_page_list') ? matewa_agency_client_pack_clean_page_list($pdf_import_data['detected_pages'], $pdf_client_domain, 8) : array();
$pdf_selected_pages = isset($pdf_import_data['selected_pages']) && is_array($pdf_import_data['selected_pages']) && function_exists('matewa_agency_client_pack_clean_page_list') ? matewa_agency_client_pack_clean_page_list($pdf_import_data['selected_pages'], $pdf_client_domain, 8) : array();
$data = array(
'client_business' => '' !== $pdf_client_business ? $pdf_client_business : matewa_agency_client_pdf_draft_name_from_file($file_name),
'client_domain' => $pdf_client_domain,
'client_admin_email' => $pdf_client_admin_email,
'whatsapp_number' => $pdf_whatsapp_number,
'leads_email' => $pdf_leads_email,
'industry' => isset($vertical_selection['category_label']) ? sanitize_text_field((string) $vertical_selection['category_label']) : 'General',
'business_category' => isset($vertical_selection['category_label']) ? sanitize_text_field((string) $vertical_selection['category_label']) : 'General',
'business_category_key' => isset($vertical_selection['category_key']) ? sanitize_key((string) $vertical_selection['category_key']) : 'general',
'business_type' => isset($vertical_selection['vertical_label']) ? sanitize_text_field((string) $vertical_selection['vertical_label']) : 'General',
'business_type_key' => isset($vertical_selection['vertical_key']) ? sanitize_key((string) $vertical_selection['vertical_key']) : 'general',
'page_mode' => $pdf_page_mode,
'detected_pages' => $pdf_detected_pages,
'selected_pages' => $pdf_selected_pages,
'chip_mode' => 'defaults',
'visitor_buttons' => isset($vertical_selection['chips']) && is_array($vertical_selection['chips']) ? array_values($vertical_selection['chips']) : array(),
'pdf_trade_match_source'=> isset($vertical_selection['pdf_trade_match_source']) ? sanitize_key((string) $vertical_selection['pdf_trade_match_source']) : '',
'pdf_trade_match_score' => isset($vertical_selection['pdf_trade_match_score']) ? absint($vertical_selection['pdf_trade_match_score']) : 0,
);
$record = array_merge(array(
'setup_pack_id' => $pack_id,
'agency_id' => $agency_id,
'assigned_bundle_id' => $bundle_id,
'seat_status' => 'assigned',
'licence_status' => 'draft',
'expires_at' => isset($bundle['expires_at']) ? sanitize_text_field((string) $bundle['expires_at']) : '',
'renews_at' => isset($bundle['renews_at']) ? sanitize_text_field((string) $bundle['renews_at']) : '',
'status' => 'pdf_uploaded_review',
'created_at' => $now,
'updated_at' => $now,
), $data);
$existing_packs[] = $record;
matewa_agency_client_pack_store_records($existing_packs);
$bundle_records[$bundle_index]['used_seats'] = min($bundle_seats, $bundle_used + 1);
$bundle_records[$bundle_index]['available_seats'] = max(0, $bundle_seats - absint($bundle_records[$bundle_index]['used_seats']));
$bundle_records[$bundle_index]['updated_at'] = $now;
matewa_agency_bundle_store_records($bundle_records);
if (function_exists('matewa_agency_client_pack_reconcile_bundle_seats')) {
matewa_agency_client_pack_reconcile_bundle_seats($existing_packs);
}
return $record;
}
}
if (!function_exists('matewa_agency_client_pdf_notice_message')) {
function matewa_agency_client_pdf_notice_message($code = '') {
$code = sanitize_key((string) $code);
$messages = array(
'pdf_uploaded' => 'Client setup PDF uploaded successfully.',
'pdf_uploaded_new_pack'=> 'Client setup PDF uploaded and opened for review. Check the prefilled boxes, choose the right business type if needed, then save the setup pack.',
'pdf_uploaded_new_pack_no_fields' => 'Client setup PDF uploaded and opened for review, but no fillable PDF fields were read. Fill the boxes manually or re-save the original fillable PDF and upload again.',
'pdf_removed' => 'Client setup PDF removed.',
'pdf_missing_pack' => 'Choose a saved client setup pack before uploading a PDF.',
'pdf_pack_not_found' => 'Client setup pack could not be found.',
'pdf_missing_file' => 'Choose a client setup PDF file before uploading.',
'pdf_upload_failed' => 'Client setup PDF could not be uploaded. Please try again.',
'pdf_invalid_type' => 'Please upload a PDF file only.',
'pdf_agency_required' => 'Agency Hub access is required before uploading client setup PDFs.',
'pdf_removed_missing' => 'No uploaded PDF was found for that setup pack.',
'pdf_no_seats' => 'No active client seats are available. Add or enable an agency bundle before starting a setup pack from PDF.',
'pdf_new_pack_failed' => 'Client setup PDF uploaded, but the new setup pack could not be started.',
'pdf_new_pack_unavailable' => 'Client setup pack storage is not available right now.',
);
return isset($messages[$code]) ? $messages[$code] : ('' !== $code ? 'Client setup PDF status: ' . str_replace('_', ' ', $code) . '.' : '');
}
}
if (!function_exists('matewa_agency_client_pdf_redirect')) {
function matewa_agency_client_pdf_redirect($notice_code, $pack_id = '', $target = 'pdf_panel') {
$args = array(
'page' => '247chatmate',
'matewa_saved_section' => 'agency',
'matewa_agency_client_pdf_notice' => sanitize_key((string) $notice_code),
);
$pack_id = sanitize_key((string) $pack_id);
if ('' !== $pack_id) {
$args['matewa_agency_pdf_pack'] = $pack_id;
}
$target = sanitize_key((string) $target);
$anchor = '#matewa-agency-client-pdf-upload-panel';
if ('edit_pack' === $target && '' !== $pack_id) {
$args['matewa_agency_edit_pack'] = $pack_id;
$anchor = '#matewa-agency-client-pack-editor';
} elseif ('client_packs' === $target) {
$anchor = '#matewa-agency-client-packs';
} elseif ('pdf_list' === $target) {
$anchor = '#matewa-agency-client-pdf-list';
}
wp_safe_redirect(add_query_arg($args, admin_url('admin.php')) . $anchor);
exit;
}
}
if (!function_exists('matewa_agency_client_pdf_handle_upload')) {
function matewa_agency_client_pdf_handle_upload() {
if (!current_user_can('manage_options')) {
wp_die(esc_html__('You do not have permission to upload client setup PDFs.', '247chatmate'));
}
check_admin_referer('matewa_agency_client_pdf_upload', 'matewa_agency_client_pdf_nonce');
$upload_mode = isset($_POST['matewa_agency_client_pdf_upload_mode']) ? sanitize_key(wp_unslash($_POST['matewa_agency_client_pdf_upload_mode'])) : 'existing_pack';
$create_new_pack = 'new_pack' === $upload_mode;
$pack_id = isset($_POST['matewa_agency_client_pdf_pack_id']) ? sanitize_key(wp_unslash($_POST['matewa_agency_client_pdf_pack_id'])) : '';
$business_type_hint = isset($_POST['matewa_agency_client_pdf_business_type_hint']) && is_scalar($_POST['matewa_agency_client_pdf_business_type_hint']) ? sanitize_text_field(wp_unslash($_POST['matewa_agency_client_pdf_business_type_hint'])) : '';
if (!function_exists('matewa_agency_hub_is_active') || !matewa_agency_hub_is_active()) {
matewa_agency_client_pdf_redirect('pdf_agency_required', $pack_id);
}
if ($create_new_pack) {
if (!matewa_agency_client_pdf_has_available_bundle_seat()) {
matewa_agency_client_pdf_redirect('pdf_no_seats');
}
} else {
if ('' === $pack_id) {
matewa_agency_client_pdf_redirect('pdf_missing_pack');
}
if (!matewa_agency_client_pdf_pack_exists($pack_id)) {
matewa_agency_client_pdf_redirect('pdf_pack_not_found', $pack_id);
}
}
if (empty($_FILES['matewa_agency_client_pdf_file']) || !is_array($_FILES['matewa_agency_client_pdf_file'])) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- File arrays are validated by the WordPress upload handler below.
matewa_agency_client_pdf_redirect('pdf_missing_file', $pack_id);
}
$file = $_FILES['matewa_agency_client_pdf_file']; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- File arrays are validated by the WordPress upload handler below.
$upload_error = isset($file['error']) ? absint($file['error']) : UPLOAD_ERR_NO_FILE;
if (UPLOAD_ERR_OK !== $upload_error) {
matewa_agency_client_pdf_redirect(UPLOAD_ERR_NO_FILE === $upload_error ? 'pdf_missing_file' : 'pdf_upload_failed', $pack_id);
}
$file_name = isset($file['name']) ? sanitize_file_name((string) $file['name']) : '';
$tmp_name = isset($file['tmp_name']) ? (string) $file['tmp_name'] : '';
if ('' === $file_name || '' === $tmp_name || !is_uploaded_file($tmp_name)) {
matewa_agency_client_pdf_redirect('pdf_missing_file', $pack_id);
}
$allowed_mimes = array('pdf' => 'application/pdf');
$checked = wp_check_filetype_and_ext($tmp_name, $file_name, $allowed_mimes);
$checked_ext = isset($checked['ext']) ? strtolower((string) $checked['ext']) : '';
$checked_type = isset($checked['type']) ? strtolower((string) $checked['type']) : '';
if ('pdf' !== $checked_ext || 'application/pdf' !== $checked_type) {
matewa_agency_client_pdf_redirect('pdf_invalid_type', $pack_id);
}
$pdf_raw_fields = function_exists('matewa_agency_client_pdf_extract_fillable_fields_from_file')
? matewa_agency_client_pdf_extract_fillable_fields_from_file($tmp_name)
: array();
$pdf_import_data = function_exists('matewa_agency_client_pdf_build_import_data_from_fields')
? matewa_agency_client_pdf_build_import_data_from_fields($pdf_raw_fields, $file_name, $business_type_hint)
: array();
$pdf_extracted_field_count = isset($pdf_import_data['extracted_field_count']) ? absint($pdf_import_data['extracted_field_count']) : 0;
$pdf_extracted_fields = isset($pdf_import_data['extracted_fields']) && is_array($pdf_import_data['extracted_fields']) ? $pdf_import_data['extracted_fields'] : array();
require_once ABSPATH . 'wp-admin/includes/file.php';
require_once ABSPATH . 'wp-admin/includes/media.php';
require_once ABSPATH . 'wp-admin/includes/image.php';
$attachment_id = media_handle_upload(
'matewa_agency_client_pdf_file',
0,
array(
'post_title' => preg_replace('/\.pdf$/i', '', $file_name),
'post_content' => '247ChatMate Agency Hub client setup PDF.',
'post_status' => 'private',
),
array(
'test_form' => false,
'mimes' => $allowed_mimes,
)
);
if (is_wp_error($attachment_id) || empty($attachment_id)) {
matewa_agency_client_pdf_redirect('pdf_upload_failed', $pack_id);
}
$notice_code = 'pdf_uploaded';
$previous_attachment_id = 0;
if ($create_new_pack) {
$created_pack = matewa_agency_client_pdf_create_pending_pack($file_name, $business_type_hint, $pdf_import_data);
if (is_wp_error($created_pack) || !is_array($created_pack) || empty($created_pack['setup_pack_id'])) {
wp_delete_attachment(absint($attachment_id), true);
$error_code = is_wp_error($created_pack) ? sanitize_key($created_pack->get_error_code()) : 'pdf_new_pack_failed';
matewa_agency_client_pdf_redirect($error_code ?: 'pdf_new_pack_failed');
}
$pack_id = sanitize_key((string) $created_pack['setup_pack_id']);
$notice_code = $pdf_extracted_field_count > 0 ? 'pdf_uploaded_new_pack' : 'pdf_uploaded_new_pack_no_fields';
}
$records = matewa_agency_client_pdf_get_records();
if (!$create_new_pack) {
$previous_attachment_id = isset($records[$pack_id]['attachment_id']) ? absint($records[$pack_id]['attachment_id']) : 0;
}
$records[$pack_id] = array(
'setup_pack_id' => $pack_id,
'attachment_id' => absint($attachment_id),
'file_name' => $file_name,
'file_url' => wp_get_attachment_url($attachment_id),
'file_type' => 'application/pdf',
'uploaded_at' => time(),
'uploaded_by' => get_current_user_id(),
'extracted_at' => $pdf_extracted_field_count > 0 ? time() : 0,
'extracted_field_count' => $pdf_extracted_field_count,
'extracted_fields' => $pdf_extracted_fields,
);
matewa_agency_client_pdf_store_records($records);
if ($previous_attachment_id > 0 && $previous_attachment_id !== absint($attachment_id)) {
wp_delete_attachment($previous_attachment_id, true);
}
matewa_agency_client_pdf_redirect($notice_code, $pack_id, $create_new_pack ? 'edit_pack' : 'pdf_panel');
}
}
add_action('admin_post_matewa_agency_upload_client_pdf', 'matewa_agency_client_pdf_handle_upload');
if (!function_exists('matewa_agency_client_pdf_handle_remove')) {
function matewa_agency_client_pdf_handle_remove() {
if (!current_user_can('manage_options')) {
wp_die(esc_html__('You do not have permission to remove client setup PDFs.', '247chatmate'));
}
check_admin_referer('matewa_agency_client_pdf_remove', 'matewa_agency_client_pdf_remove_nonce');
$pack_id = isset($_POST['matewa_agency_client_pdf_remove_pack_id']) ? sanitize_key(wp_unslash($_POST['matewa_agency_client_pdf_remove_pack_id'])) : '';
if (!function_exists('matewa_agency_hub_is_active') || !matewa_agency_hub_is_active()) {
matewa_agency_client_pdf_redirect('pdf_agency_required', $pack_id);
}
if ('' === $pack_id) {
matewa_agency_client_pdf_redirect('pdf_missing_pack');
}
$records = matewa_agency_client_pdf_get_records();
if (empty($records[$pack_id])) {
matewa_agency_client_pdf_redirect('pdf_removed_missing', $pack_id);
}
$attachment_id = isset($records[$pack_id]['attachment_id']) ? absint($records[$pack_id]['attachment_id']) : 0;
unset($records[$pack_id]);
matewa_agency_client_pdf_store_records($records);
if ($attachment_id > 0) {
wp_delete_attachment($attachment_id, true);
}
matewa_agency_client_pdf_redirect('pdf_removed', $pack_id, 'pdf_list');
}
}
add_action('admin_post_matewa_agency_remove_client_pdf', 'matewa_agency_client_pdf_handle_remove');
if (!function_exists('matewa_agency_client_pdf_render_panel')) {
function matewa_agency_client_pdf_render_panel($client_pack_records = null) {
$client_pack_records = null === $client_pack_records && function_exists('matewa_agency_client_pack_get_records')
? matewa_agency_client_pack_get_records()
: (is_array($client_pack_records) ? array_values($client_pack_records) : array());
$pdf_records = matewa_agency_client_pdf_get_records();
$notice_code = isset($_GET['matewa_agency_client_pdf_notice']) && is_scalar($_GET['matewa_agency_client_pdf_notice'])
? sanitize_key(wp_unslash($_GET['matewa_agency_client_pdf_notice']))
: '';
$selected_pack_id = isset($_GET['matewa_agency_pdf_pack']) && is_scalar($_GET['matewa_agency_pdf_pack'])
? sanitize_key(wp_unslash($_GET['matewa_agency_pdf_pack']))
: '';
if ('' === $selected_pack_id && !empty($client_pack_records[0]['setup_pack_id'])) {
$selected_pack_id = sanitize_key((string) $client_pack_records[0]['setup_pack_id']);
}
$valid_pack_ids = array();
foreach ($client_pack_records as $pack) {
if (is_array($pack) && !empty($pack['setup_pack_id'])) {
$valid_pack_ids[] = sanitize_key((string) $pack['setup_pack_id']);
}
}
$valid_pack_ids = array_values(array_unique(array_filter($valid_pack_ids)));
$visible_pdf_records = array_intersect_key($pdf_records, array_flip($valid_pack_ids));
$notice_message = '' !== $notice_code ? matewa_agency_client_pdf_notice_message($notice_code) : '';
$notice_type = in_array($notice_code, array('pdf_uploaded', 'pdf_uploaded_new_pack', 'pdf_removed'), true) ? 'success' : 'warning';
$has_packs = !empty($client_pack_records);
$has_available_seat = matewa_agency_client_pdf_has_available_bundle_seat();
$panel_open = '' !== $notice_code || !empty($visible_pdf_records);
?>
No client setup PDFs uploaded yet.
Client Setup PDF Upload
Upload Client Setup PDF