//: "used" in the shop's language. */ function usedkit_seo_base($locale) { $bases = array('fi' => 'kaytetty', 'sv' => 'begagnad', 'de' => 'gebraucht', 'fr' => 'occasion', 'es' => 'segunda-mano', 'it' => 'usato', 'pl' => 'uzywane', 'nl' => 'tweedehands', 'pt' => 'usado'); return $bases[substr((string) $locale, 0, 2)] ?? 'used'; } /** A model's address part, from its name: ASCII, lowercase, hyphens. */ function usedkit_model_slug($label) { $s = preg_replace('/[^a-z0-9]+/', '-', usedkit_fold($label)); return trim($s, '-'); } /** * A model gets a page when there is something to show and a reason to come back: two * items or more, for sale now or sold in the last year. One item alone is its own page. */ function usedkit_model_eligible($in_stock, $sold_recently) { return $in_stock + $sold_recently >= 2; } /** * What a sold item's page does: "keep" (an ordinary page), "noindex" (stays, but out of * search results and sitemaps), or "redirect" (to its model page, else its category). * Nothing changes until the item has been sold `days` days: a page that is fresh in * search results still brings people, and the notify form and in-stock items catch them. */ function usedkit_sold_fate($sold_at, $now, $days, $mode) { if (!$sold_at || !in_array($mode, array('noindex', 'redirect'), true) || $now - $sold_at < $days * 86400) { return 'keep'; } return $mode; } /** * The model's name for its page: the service's name where it knows the model (it reads * "Alpha 7 III body" as Sony A7 III), else the shortest of the items' titles, which has * the fewest extras ("Sony RX100 III" over "Sony RX100 III + extra battery"). */ function usedkit_model_label($key, $service_label, $titles) { if ($service_label !== '' && strpos($key, 'plain:') !== 0) { return $service_label; } $titles = array_values(array_filter(array_map('trim', $titles), 'strlen')); if (!$titles) { return $service_label; } usort($titles, function ($a, $b) { return strlen($a) <=> strlen($b) ?: strcmp($a, $b); }); return $titles[0]; } /** A text cut to `max` characters at a word, with an ellipsis when cut. */ function usedkit_clip($text, $max = 155) { $text = trim(preg_replace('/\s+/', ' ', (string) $text)); if (mb_strlen($text) <= $max) { return $text; } $cut = mb_substr($text, 0, $max - 1); $space = mb_strrpos($cut, ' '); return rtrim($space > $max * 0.6 ? mb_substr($cut, 0, $space) : $cut, " ,.;:-") . '…'; } /** * An item's description for search results, when it has none of its own: its condition, * the shop's note on it, what is included. Sentences in the order a buyer asks. * $parts: ['grade' => "Used, good condition.", 'note' => ..., 'included' => "Included: ..."] */ function usedkit_seo_description($parts) { $out = array(); foreach (array('grade', 'note', 'included') as $k) { $t = trim((string) ($parts[$k] ?? '')); if ($t !== '') { $out[] = preg_match('/[.!?…]$/u', $t) ? $t : $t . '.'; } } return usedkit_clip(implode(' ', $out)); }