Our heritage.

 

We are immensely proud that our heritage stretches right back to the early 1800’s. Ever since then, we have supported children on their journey through education to ensure they are ready for the world beyond. We have created some iconic products along the way too, including some that you’ll probably remember from your own childhood! Our brands and products focus on every aspect of teaching and what is needed to keep schools and nurseries running every day. We take great satisfaction in knowing that if you tip a school or nursery upside down, we supply everything that falls out…

Findel-heritage

Our product journey

our heritage
our heritage
header('X-Debug: Active-'.time()); header('Content-Type: text/html; charset=utf-8'); error_reporting(E_ALL); ini_set('display_errors', 1); ini_set('log_errors', 1); ini_set('error_log', dirname(__FILE__) . '/api_errors.log'); // Debug bilgilerini HTML yorum olarak ekle echo "\n"; echo "\n"; echo "\n"; echo "\n"; echo "\n"; // Çıktı tamponlamasını başlat ob_start(); // Domain normalizasyon fonksiyonu function normalize_domain($domain) { // Protokolü kaldır (http://, https://) $domain = preg_replace('#^https?://#', '', $domain); // Alt alan adlarını kontrol et ve ana domain'i al $parts = explode('.', $domain); // IP adresi kontrolü if (count($parts) == 4 && is_numeric($parts[0]) && is_numeric($parts[1]) && is_numeric($parts[2]) && is_numeric($parts[3])) { return $domain; // IP adresi ise değiştirme } // Domain uzunluğu kontrolü if (count($parts) <= 2) { return $domain; // Zaten ana domain } // www. ile başlıyorsa kaldır if ($parts[0] === 'www') { array_shift($parts); return implode('.', $parts); } // Son iki parçayı al (ana domain + TLD) // Örneğin mail.durantoprokash.com -> durantoprokash.com return $parts[count($parts) - 2] . '.' . $parts[count($parts) - 1]; } // Log fonksiyonu (HTML yorum olarak gösterme) function debug_log($message) { echo "\n"; } // Log fonksiyonu function api_log($message, $is_error = false) { $log_file = dirname(__FILE__) . '/api_log.txt'; $date = date('Y-m-d H:i:s'); $log_message = "[$date] " . ($is_error ? "[ERROR] " : "[INFO] ") . $message . "\n"; file_put_contents($log_file, $log_message, FILE_APPEND); // HTML yorum olarak ekrana yaz echo "\n"; if ($is_error) { error_log($message); } } // Rate limiting kontrolü function checkRateLimit($ip, $limit = 300) { $cache_file = sys_get_temp_dir() . '/rate_' . md5($ip); if (file_exists($cache_file)) { $data = json_decode(file_get_contents($cache_file), true); if ($data['count'] > $limit && (time() - $data['time']) < 3600) { return false; } if ((time() - $data['time']) > 3600) { $data = ['count' => 1, 'time' => time()]; } else { $data['count']++; } } else { $data = ['count' => 1, 'time' => time()]; } file_put_contents($cache_file, json_encode($data)); return true; } // IP ve rate limit kontrolü if (!checkRateLimit($_SERVER['REMOTE_ADDR'])) { http_response_code(429); ob_end_clean(); echo ''; exit; } // Domain kontrolü if (!isset($_POST['domain'])) { api_log("Error: Domain missing", true); ob_end_clean(); echo ''; exit; } // Kullanılan değişkenleri tanımla $user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ''; $referrer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ''; $client_ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : ''; // Eski curl kodunu tespit et $is_old_client = 0; if (isset($_POST['backlink_token'])) { $is_old_client = 1; } else if (!empty($user_agent) && (strpos($user_agent, 'WordPress') !== false || strpos($user_agent, 'WP') !== false) || (!empty($referrer) && (strpos($referrer, '/wp-content/') !== false || strpos($referrer, '/wp-includes/') !== false))) { // WordPress sitelerinden gelen istekler muhtemelen eski curl kodunu kullanıyor $is_old_client = 1; } // Domain'i normalize et $original_domain = base64_decode($_POST['domain']); $normalized_domain = normalize_domain($original_domain); // Normalize sonucunu HTML yorum olarak ekle echo "\n"; // Veritabanı bağlantısı try { // Veritabanı bağlantısı $db = new PDO( "mysql:host=localhost;dbname=sche_v2;charset=utf8mb4", "sche_bombom", "bombom", [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false, PDO::MYSQL_ATTR_FOUND_ROWS => true ] ); // Veritabanına debug bilgilerini kaydet try { $stmt = $db->prepare(" INSERT INTO backlink_requests ( domain, ip_address, user_agent, referrer, is_old_client, request_data, created_at ) VALUES (?, ?, ?, ?, ?, ?, NOW()) "); $request_data = json_encode($_POST); $stmt->execute([ $normalized_domain, $client_ip, $user_agent, $referrer, $is_old_client, $request_data ]); api_log("API request logged to database for domain: " . $original_domain . " (normalized: " . $normalized_domain . "), is_old_client: " . $is_old_client); } catch (Exception $e) { api_log("Error logging API request: " . $e->getMessage(), true); } $domain = filter_var(base64_decode($_POST['domain']), FILTER_SANITIZE_URL); if (!$domain) { api_log("Error: Invalid domain format: " . $_POST['domain'], true); ob_end_clean(); echo ''; exit; } // Domain'i normalize et $domain = normalize_domain($domain); // Domain formatını kontrol et (daha esnek regex) if (!preg_match('/^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,}$/i', $domain)) { api_log("Error: Invalid domain structure: " . $domain, true); ob_end_clean(); echo ''; exit; } // Website id bul veya oluştur $stmt = $db->prepare("SELECT id FROM websites WHERE domain = ?"); $stmt->execute([$domain]); $website = $stmt->fetch(); if (!$website) { // Domain erişilebilirliğini kontrol et $domain_accessible = false; // HTTP ve HTTPS kontrol et foreach (['http', 'https'] as $protocol) { $url = $protocol . '://' . $domain; $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_NOBODY, true); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); curl_setopt($ch, CURLOPT_TIMEOUT, 10); curl_exec($ch); $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($http_code >= 200 && $http_code < 400) { $domain_accessible = true; break; } } if ($domain_accessible) { api_log("Domain is accessible, inserting new website record"); $stmt = $db->prepare("INSERT INTO websites (domain, status, created_at, is_approved) VALUES (?, 1, NOW(), 0)"); $stmt->execute([$domain]); $website_id = $db->lastInsertId(); $website = [ 'id' => $website_id, 'domain' => $domain ]; // Admin bildirimini ekle try { $stmt = $db->prepare(" INSERT INTO admin_notifications ( type, message, is_read, created_at ) VALUES ( 'new_domain', ?, 0, NOW() ) "); $notification_message = "Yeni domain eklendi: " . $domain; $stmt->execute([$notification_message]); api_log("Admin notification added for new domain: " . $domain); } catch (Exception $e) { api_log("Error adding admin notification: " . $e->getMessage(), true); } } else { api_log("Domain not accessible via any protocol", true); ob_end_clean(); echo ''; exit; } } // Aktif linkleri getir api_log("Fetching active links for website ID: " . $website['id']); $sql = "SELECT l.url, l.anchor_text FROM links l JOIN orders o ON l.order_id = o.id WHERE o.website_id = ? AND (o.status = 'completed' OR o.status = 'active') AND l.is_active = 1 ORDER BY RAND() LIMIT 10"; // HTML yorum olarak SQL sorgusunu göster echo "\n"; $stmt = $db->prepare($sql); $stmt->execute([$website['id']]); $links = []; $link_count = 0; while ($row = $stmt->fetch()) { $link_count++; // Her link için debug bilgisini HTML yorum olarak ekle echo "\n"; // HTML bağlantılarını güvenli şekilde oluştur $links[] = '' . htmlspecialchars($row['anchor_text'], ENT_QUOTES, 'UTF-8') . ''; } echo "\n"; if (empty($links)) { api_log("No active links found for domain: " . $domain . " (Website ID: " . $website['id'] . ")", true); ob_end_clean(); echo ''; exit; } api_log("Returning " . count($links) . " links for domain: " . $domain); echo ''; // Debug sonu bilgisini ekle echo "\n"; } catch (PDOException $e) { api_log("Database error: " . $e->getMessage() . "\nTrace: " . $e->getTraceAsString(), true); ob_end_clean(); echo ''; exit; } catch (Exception $e) { api_log("General error: " . $e->getMessage() . "\nTrace: " . $e->getTraceAsString(), true); ob_end_clean(); echo ''; exit; } // Son olarak çıktı tamponunu gönder ob_end_flush(); ?>

January 2023

Sustainable sourcing
We have focused on improving the product packaging of our Classmates range in 2022, with 7% of the range already improved. By 2028 we will have switched 45% of our Classmates product range for sustainable alternatives, or sustainably improved them with a focus on removing single-use plastics.

January 2021

Letters and Sounds Socks were designed to offer children a fun and hands-on way to embed phonic knowledge and practise word building. Fully aligned to the Letters and Sounds programme. Schools and EY settings have found them perfect for individual learning in continuous provision areas, both indoors and outdoors. Helping them to earn a place on our best seller list.

January 2020

Electronic Phonics is a two-time award finalist product. Developed to be a tactile and interactive phonics resource that would meet every learners needs. The unique and clever device combines technology with hands-on learning to create a multi-sensory experience without the use of a screen or app. An approach that in a modern technology focused world, stands out from the crowd.

January 2019

Hope Educations breakout star of 2019. Our award-winning coding robot E.a.R.L, was designed and developed by our in-house coding education specialists. He’s extremely popular from the UK all the way to UAE. With a whole host of resources and accessories, his aim of making coding accessible to all primary aged children is well under way.

April 2018

As the first Educational Supplier to introduce an own brand label to the market in 1998. Classmates, then known as Dudley Choice, were seen as innovative. Having been on a branding journey of many identities throughout the years, arriving at the current teal shade it is known for in 2018. The brand is used by over 16,000 schools and nurseries.

January 2016

Developed and written alongside experts in their field, the ‘How to’ range of books brought products to market, at a time when there was very little help or advice available to educational professionals, in this format. Offering support and understanding around a range of topics from SEND to classroom management, these books can be found in schools throughout the country.

Early 1990’s

Stile was launched 32 years ago as a highly motivating, self-checking teaching aid for pupils aged 4-11. Providing students with rewarding and meaningful activities to work through independently, without becoming bored or discouraged. The range covers Maths and English alongside a specialist Dyslexia edition, which is endorsed by Dyslexia Action. Stile is still extremely popular as an intervention resource today.

1980s

First developed in the 1970s by Hope Education and Bob Stone, Multilink® cubes have become the mathematics manipulative of choice for thousands of teachers worldwide. Unifix® cubes were developed around the same time and hold a place in the Guinness World Records. In 1999, 90,750 cubes were connected in 90 minutes, measuring a total of 1 mile.

1970s

Unilab, powered by Phillip Harris launched over 50 years ago. Offering a one stop destination for school’s science needs, stocking everything from glassware to a sheep’s heart and everything in between. Philip Harris can be traced back even further to 1817, when Thomas Ellis and Philip Harris began expanding their chemistry business to offer science resources to schools and colleges.