Welcome to the Prospectus Builder
MESSAGE;
}
public static function getEndUserSubject() {
return <<json_data = CacheHandler::CacheUpToDate($json);
// if the latest cache is not the latest version of the JSON
if($this->json_data == false) {
// read the original JSON file
$this->json_data = $this->returnStructure($json);
// Write the new structure to the Cache
CacheHandler::WriteNewerCache($this->json_data);
}
}
function returnStructure($json) {
//replace the last ',' from the file
$json = $this->str_lreplace(',', '', $json);
$json = json_decode($json);
if($json === null) {
die("JSON is invalid.");
}
// initialise structure array
$structure = array();
// foreach of the json prospectus keys
foreach($json->prospectus as $obj => &$data) {
// explode on the sectionParent and take second last element (this is the actual parent from the URL)
$data->sectionParent = explode('/', $data->sectionParent);
$data->sectionParent = $data->sectionParent[count($data->sectionParent) - 2];
if(!isset($structure[$data->sectionParent]['display_title']) || ($structure[$data->sectionParent]['display_title'] !== CONFIG::getFirstPage() && $structure[$data->sectionParent]['display_title'] !== CONFIG::getLastPage())) {
$data->sectionParent = strtolower($data->sectionParent);
$data->sectionParent = replaceCommasHyphens($data->sectionParent);
$data->sectionTitle = replaceCommasHyphens((string)$data->sectionTitle);
// if the sectionParent doesn't have a key in the structure array
if(!isset($structure[$data->sectionParent])) {
// set the array up with a total_ranges value of the current section ranges
$structure[$data->sectionParent] = array ('total_ranges' => $data->sectionRanges );
} else if($structure[$data->sectionParent]['total_ranges'] !== ''){
// else just append onto what already exists
$structure[$data->sectionParent]['total_ranges'] .= ',' . $data->sectionRanges;
} else {
// else set the total_ranges to the section_ranges value
$structure[$data->sectionParent]['total_ranges'] = $data->sectionRanges;
}
if($data->sectionParent !== $data->sectionTitle) {
$thisArray = array();
$thisArray[$data->sectionTitle] = $data->sectionRanges;
$structure[$data->sectionParent] = array_merge($structure[$data->sectionParent], $thisArray);
}
$structure[$data->sectionParent]['display_title'] = $data->sectionParentTitle;
}
}
$structure['md5_checksum'] = md5(file_get_contents(CONFIG::getJSON_FILE()));
return $structure;
}
function str_lreplace($search, $replace, $subject) {
$pos = strrpos($subject, $search);
if($pos !== false)
{
$subject = substr_replace($subject, $replace, $pos, strlen($search));
}
return $subject;
}
}
class CacheHandler {
public static function CacheUpToDate($json) {
if(CONFIG::getENABLE_CACHING() === false) {
return false;
}
$cached_file = CONFIG::getJSON_CACHED_FILE();
// if the cached file exists
if(file_exists($cached_file)) {
$json_cached = json_decode(file_get_contents($cached_file), true);
$md5_main_json = md5($json);
// if the MD5 strings are the same, return the cached version
if($json_cached['md5_checksum'] === $md5_main_json) {
return $json_cached;
} else {
// else return false
return false;
}
} else {
// else return false
return false;
}
}
public static function WriteNewerCache($structure) {
if(CONFIG::getENABLE_CACHING() === false) {
return false;
}
if(file_exists(CONFIG::getJSON_CACHED_FILE())) {
// we write the cached file
file_put_contents(CONFIG::getJSON_CACHED_FILE(), json_encode($structure));
} else {
// else we make the directory, then write the cached file
$dir_to_write_json = CONFIG::getPROSPECTUS_BUILDER_LOCATION() . '/' . CONFIG::getJSON_CACHED_FILE();
$dir_to_write_json = str_replace('\\', '/', $dir_to_write_json);
$dir_to_write_json = str_replace('/index.json', '', $dir_to_write_json);
// check if the directory exists
if(is_dir($dir_to_write_json)) {
// write the file
file_put_contents(CONFIG::getJSON_CACHED_FILE(), json_encode($structure));
} else {
if(mkdir($dir_to_write_json) === false) {
die("error creating directory");
} else {
// we write the file
file_put_contents(CONFIG::getJSON_CACHED_FILE(), json_encode($structure));
}
}
}
}
}
class send_emails {
private $email_add;
private $port;
private $from;
private $content;
function __construct($email_addr) {
ini_set('SMTP', CONFIG::getSMTP_HOST());
ini_set('smtp_port', CONFIG::getSMTP_PORT());
$this->sendEmailToEndUser($email_addr);
$selections = $this->getUserSelections($_POST['selections']);
$this->sendEmailToSite($selections, $email_addr);
}
private function getUserSelections($selections) {
$selections = str_replace('-=-', ' ', $selections);
$selections = ucwords($selections);
return $selections;
}
private function sendEmailToSite($selections, $email_addr)
{
$this->from = CONFIG::getEmail_Address_From();
$this->msg = $this->formatSiteEmailMessage($_POST['selections'], $email_addr);
$this->headers = "MIME-Version: 1.0" . "\r\n" .
"Content-type: text/html; charset=UTF-8" . "\r\n" .
"From: " . $this->from . "\r\n" .
"Reply-To: " . $this->from . "\r\n" .
'X-Mailer: PHP/' . phpversion();
$this->subject = "User downloaded a Prospectus";
$client_email_address = CONFIG::getEmail_Address_Site();
$sent = mail($client_email_address, $this->subject, $this->msg, $this->headers);
if($sent === false) {
die("false");
}
}
private function sendEmailToEndUser($email_addr)
{
$this->from = CONFIG::getEmail_Address_From();
$this->msg = $this->getEndUserEmailMessage();
$this->subject = $this->getEndUserEmailSubject();
$validEmail = filter_var($email_addr, FILTER_VALIDATE_EMAIL);
if($validEmail === false) {
die('Please enter a valid email address');
}
if($this->msg && $this->subject) {
$this->headers = "MIME-Version: 1.0" . "\r\n" .
"Content-type: text/html; charset=UTF-8" . "\r\n" .
"From: " . $this->from . "\r\n" .
"Reply-To: " . $this->from . "\r\n" .
'X-Mailer: PHP/' . phpversion();
$sent = mail($email_addr, $this->subject, $this->msg, $this->headers);
if($sent === false) {
die("Failed to attempt sending email");
}
}
}
function formatSiteEmailMessage($subs, $end_user_email) {
$msg = "A user downloaded a prospectus with an email address of " . $end_user_email;
$msg .= "
List of topics included in the Prospectus were: ";
//$selections = implode(' ', $subs );
$selections = '';
// add blank value to subs, in case only one value was selected.
$subs[] = '';
foreach($subs as &$selection) {
$selection = str_replace('-=-', ' -> ', $selection);
$selection = str_replace('_', ' ', $selection);
$selection = ucwords($selection);
$selections .= $selection . ' ';
}
$msg .= $selections;
return $msg;
}
function getEndUserEmailMessage() {
return CONFIG::getEndUserMessage();
}
function getEndUserEmailSubject() {
return CONFIG::getEndUserSubject();
}
}
class GeneratePDF {
public $ranges;
public $pdf;
function __construct($choices, $json_data) {
$this->json_data = $json_data;
$this->ranges = $this->getRanges($choices, $json_data);
$this->ranges = $this->formatRanges($this->ranges);
// check if the first and past page data is set, and if so, include it.
$this->ranges = $this->addFirstLastPage($this->ranges, $json_data);
$this->pdf = $this->returnPDF($this->ranges);
}
function getRanges($choices, $json_data) {
$ranges = '';
// add compulsory, if exists
if(isset($json_data->json_data[CONFIG::getCOMPULSORY_SECTION()])) {
$ranges .= $json_data->json_data[CONFIG::getCOMPULSORY_SECTION()]['total_ranges'] . ',';
}
// loop over the user selections
foreach($choices['selections'] as $index => $course_selections) {
// flag to append comma or not
$append_comma = true;
// if there is no hyphen, we are dealing with a main course
if(strpos($course_selections, '-=-') === false) {
$ranges .= $json_data->json_data[$course_selections]['total_ranges'];
} else {
// else we explode by the hyphen to get the main course and sub course name
$sections = explode('-=-', $course_selections);
$course = $sections[0];
$sub_section = $sections[1];
if(!in_array($course, $choices['selections'])) {
$ranges .= $json_data->json_data[$course][$sub_section];
// we also need to include the compulsory section, if it is set
if(CONFIG::getCOMPULSORY_SECTION() && isset($json_data->json_data[$course][CONFIG::getCOMPULSORY_SECTION()]) && strpos($ranges, $json_data->json_data[$course][CONFIG::getCOMPULSORY_SECTION()]) === false ) {
$ranges .= ',' . $json_data->json_data[$course][CONFIG::getCOMPULSORY_SECTION()];
}
} else {
$append_comma = false;
}
}
// if we are not on the last index of the choices, add a trailing comma
if($index !== count($choices['selections']) -1 && $append_comma == true) {
$ranges .= ',';
}
/*
// we also need to include the compulsory section, if it is set
if(CONFIG::getCOMPULSORY_SECTION() && isset($json_data->json_data[$course][CONFIG::getCOMPULSORY_SECTION()]) && strpos($ranges, $json_data->json_data[$course][CONFIG::getCOMPULSORY_SECTION()]) === false ) {
$ranges .= $json_data->json_data[$course][CONFIG::getCOMPULSORY_SECTION()] . ',';
}
*/
}
// return the ranges
return $ranges;
}
/**
* Format the $range so that it is a comma delimitted string and replace all ranges with singular values
* that are comma delimitted
**/
function formatRanges($ranges) {
$ranges_array = array();
$ranges_array = explode(',', $ranges);
$ranges_array = array_filter($ranges_array);
foreach($ranges_array as &$range) {
// if there is a range
if(strpos($range, '-') !== false) {
// Explode by the hyphen
$numbers = explode('-', $range);
// Ensure the data is numeric, there are only 2 numbers, and the number on the left is less than the right
if((is_numeric($numbers[0]) && is_numeric($numbers[1]) && count($numbers) == 2) && ($numbers[0] < $numbers[1])) {
$new_range = '';
// Create the new page numbers with comma delimmitted values
for($i = $numbers[0]; $i<= $numbers[1]; $i++) {
$new_range .= $i;
if($i != $numbers[1]) {
$new_range .= ',';
}
}
$range = $new_range;
} else {
// there was an error with the data
$this->throw_range_error();
}
}
}
// implode by comma
$ranges = implode(',', $ranges_array);
// explode again by comma
$ranges = explode(',', $ranges);
// make ranges unique (remove duplicates so that same pages dont appear twice)
$ranges = array_unique($ranges);
// sort ranges so pages appear in order
sort($ranges, SORT_NUMERIC );
// reimplode and return
$ranges = implode(',', $ranges);
return $ranges;
}
function addFirstLastPage($ranges, $json_data) {
if(CONFIG::getFirstPage() && CONFIG::getLastPage()) {
$first_page_name = CONFIG::getFirstPage();
$last_page_name = CONFIG::getLastPage();
$first_page_range = $json_data->json_data[$first_page_name]['total_ranges'];
$last_page_range = $json_data->json_data[$last_page_name]['total_ranges'];
$ranges = $first_page_range . ',' . $ranges . ',' . $last_page_range;
return $ranges;
} else {
return $ranges;
}
}
function returnPDF($ranges, $type = 'download') {
require_once(CONFIG::getPDF_PHP_LIBRARY_FILE());
$pdf = new PDFMerger;
try {
$pdf->addPDF(CONFIG::getMAIN_PDF_FILE(), $ranges)
->merge($type, CONFIG::getPDF_NAME());
} catch (Exception $e) {}
return $pdf;
}
function checkExists($string, $json_data) {
}
function formatChoices($choices) {
}
function throw_range_error() {
die("Data error.");
}
}
class GetHTML {
public $html;
private $json_data;
private $parent_class;
private $child_class;
function __construct($json_data) {
$this->parent_class = CONFIG::getHTML_PARENT_CLASS();
$this->child_class = CONFIG::getHTML_CHILD_CLASS();
$this->json_data = $json_data;
$this->html = $this->generateHTML($this->json_data);
echo $this->html;
}
function generateHTML($json_data) {
$html = '';
$html .= "";
$html .= '
Step into a legacy of excellence, leadership, and transformation. At Rhodes University, we don’t just educate—you become part of a powerful network of thinkers, creators, and changemakers rooted in the Eastern Cape and reaching across the world. Whether you're applying for undergraduate, postgraduate, or international study, this is where your future begins.
Your donation helps us empower the next generation of leaders, innovators, and change agents. At Rhodes University, every gift—big or small—makes a real impact: funding student bursaries, advancing cutting-edge research, and preserving the spirit of academic excellence in the heart of Makhanda. Together, we can transform lives and build a stronger future.