Jump to content

All Activity

This stream auto-updates

  1. Past hour
  2. Oh, SOAP is terrible. Hate it. REST is so much easier to work with. And yeah, XHTML... I miss that. When it was still a thing, and for a while after, that was what I was using for all my stuff. Then they took all the weirdness of HTML 4 and doubled-down on it with 5. Sigh.
  3. Today
  4. It sounds like what you are describing is a custom work flow engine. Just editorially, a well known product that a lot of people know of in the software world is Jira. Most people think of Jira as an issue tracker, but it's actually a workflow engine with issue tracking workflows pre-configured. You can create any sort of workflow with it. I set up some fairly elaborate internal workflows for companies I worked for in the past. The level of complexity available, can make it very difficult to change a workflow once you started using it, which is one of the things that can be surprising about Jira. At any rate, there's a large list of workflow related products and software libraries you might take a look at. Unfortunately, like jira itself, a lot of Business Process Modelling (BPM) and workflow engines are written in Java, however I did note in the list, that there are libraries for both Laravel and Symfony frameworks that I would take a look at, even if it's just to see how someone else has solved the problem.
  5. Maybe it's because the method is expectOutputString, not expectedOutputString.
  6. I fought a few xml wars in my day, most involving soap. Every now and then, some of this comes in handy. A lot of people working in web development don't realize it wasn't all that long ago that people were arguing over html4 vs xhtml.
  7. https://docs.phpunit.de/en/11.1/writing-tests-for-phpunit.html#writing-tests-for-phpunit-output-examples-outputtest-php But it gives me an error //PHPUnit 11.1.3 by Sebastian Bergmann and contributors. //Runtime: PHP 8.3.6 //this->expectedOutputString() Error: Call to undefined method OutputTest::expectedOutputString() //parent::expectedOutputString() Error: Call to undefined method PHPUnit\Framework\TestCase::expectedOutputString() Why?
  8. Yesterday
  9. I actually use XSLT for some stuff at home: got a lot of data, I manage most it in XML with some in JSON because a real NoSQL database would be awkward to hand-edit like I need, and want to render it into a viewable form. Add XSLT and throw in PHP's function bindings and you can do just about anything. Downside: super inefficient, so complicated processing takes a while. Early 2000s, give or take, I even experimented with a XML-based website - as in the server responded with XML, not HTML. It worked very well. In fact, after getting back into it for the above project stuff, I'll very likely do it again for a couple smaller projects. Because the simplicity of editing data in XML lets me do whatever I want without having to run a database server or make table schema changes or build CRUD tools.
  10. I have about 10 pounds of old xml books in my office covering all this type of arcana. Fortunately (or not depending on how you look at it) we have people like Requinix and Barand on this forum, who have the memories of elephants -- quite appropriate given that the elePHant is the official mascot of the PHP project.
  11. One thing of concern is that your site is leaking error information. Unless you changed this just for the purposes of debugging, you should have display_errors = Off, and be logging the errors instead to a log file. In terms of session timeout parameters, people are often given the impression that overriding the defaults with different runtime parameters is a solution, but the reality is, that the default handling will delete your session file, should garbage collection be run somewhere else on your site. The only way the timestamp on the session file will be updated, is if something in the session is updated. This is partially based on the default session setting for session.lazy_write which defaults to true. One way to handle this extension would be to update some session variable each time your refresh runs. However, given that this is a personal system for you, the best solution in my opinion would be to implement a "remember me" feature, which is a fairly standard addition to many website systems. The way you would handle remember me, is to add a security feature where your code (for you as the admin) sets a cookie in the future. Practically speaking, this cookie can now only be set a year in advance, and for security reasons, these types of limits are subject to change depending on what the browser developers decide. From what I've seen, Chrome for example, will only allow a cookie to set with an expiration a bit more than a year now. But you would do something like this: // Get these things from your user table: //$userId //$userName //$userCreatedDate (user account was created) // Generate the hash $rememberMeHash = sha1(uniqid($userName, true) . $userCreatedDate . $userId); // Now store this value (it's a 40 character hex string) in the row of your user table, for your personal/admin user. setcookie( "someCookieName", $rememberMeHash, time() + (365 * 24 * 60 * 60) ); After implementing this into your admin login, you then need to change your authentication to take this cookie into account. If authentication failed, check for your "remember me" cookie. If that value exists, see if there is a user who has that hash value in their user record. If found, handle this the same way you would if the user had authenticated with username/password and set the session up accordingly. In essence this will keep your login available for a year at a time, just so long as this remember me cookie exists.
  12. I should have checked the is_int manual page, and should have seen that it checks PHP's internal type. Thanks to Psycho and mac_gyver we got you there, but just to be complete, is_numeric will pass many numbers through that are not integers. To really do the job well, this is what I should have offered up from the beginning (and also takes advantage of the typecasting I wrote about. if (!isset($_GET['t']) || !is_numeric($_GET['t']) || !is_int((int)$_GET['t'] || $_GET['t'] < 0) { header('Location: http://www.baltimorebeach.com'); exit; } It is always very important that location redirects are followed by an exit, because redirection is a function of the browser. The server is basically saying: "you go here", but it is up to the browser to actually follow that instruction. Bots and artificial clients may not play by the rules. So the script should at that point exit, so that no additional code is run, or access restriction bypassed.
  13. I have no idea how your chart software works but if you provide five data values (8, 19, 11, 3, 49) for one type and three data values (1, 3, 7) for the other, how is it supposed to know which months those values are for? You have a very weird x-axis for that chart (the month sequence is 6-5-4-3-2-1-12-11-10-9-8-7). The norm is to put them in chronological order.
  14. Bit of a breakthrough I've altered the PHP to if(!empty($data['legend'])) { foreach($data['legend'] as $r1) { if(isset($r1->Name)) { $sales = $this->_query->get_sales_count($r1->IdService); if(!empty($sales)) { foreach($sales as $r2) { $count[$r1->Name][] = $r2->Sales; } $legend[] = array('label' => $r1->Name, 'backgroundColor' => $r1->GraphColor, 'data' => implode(',',$count[$r1->Name])); } } } } and that has given me [{"label":"Installation","backgroundColor":"#2bca2d","data":"8,19,11,3,49"},{"label":"Repair","backgroundColor":"#cfca3a","data":"1,3,7"}] which looks ok until its placed in the char then it adds everything to the wrong month and only 1 item per month
  15. Barand

    CBT Exam

    Another option, maybe Create question in MSWord Save page as html doc Display it in an <iframe> on your page
  16. Olumide

    CBT Exam

    I keep getting this error Warning: DOMDocument::loadXML(): Namespace prefix m on oMath is not defined in Entity, line: 1 in C:\wamp64\www\cbt\cbt_exam\vendor\phpoffice\math\src\Math\Reader\OfficeMathML.php on line 39 Call Stack #TimeMemoryFunctionLocation 10.0005449024{main}( )...\upload.php:0 20.0080581080convertDocxToHtml( $filename = 'uploads/Question_me2.docx' )...\upload.php:30 30.0087581080PhpOffice\PhpWord\IOFactory::load( $filename = 'uploads/Question_me2.docx', $readerName = ??? )...\upload.php:120 40.0100581872PhpOffice\PhpWord\Reader\Word2007->load( $docFile = 'uploads/Question_me2.docx' )...\IOFactory.php:89 50.0479598432PhpOffice\PhpWord\Reader\Word2007->readPart( $phpWord = class PhpOffice\PhpWord\PhpWord { private $sections = [0 => class PhpOffice\PhpWord\Element\Section { ... }]; private $collections = ['Bookmarks' => class PhpOffice\PhpWord\Collection\Bookmarks { ... }, 'Titles' => class PhpOffice\PhpWord\Collection\Titles { ... }, 'Footnotes' => class PhpOffice\PhpWord\Collection\Footnotes { ... }, 'Endnotes' => class PhpOffice\PhpWord\Collection\Endnotes { ... }, 'Charts' => class PhpOffice\PhpWord\Collection\Charts { ... }, 'Comments' => class PhpOffice\PhpWord\Collection\Comments { ... }]; private $metadata = ['DocInfo' => class PhpOffice\PhpWord\Metadata\DocInfo { ... }, 'Settings' => class PhpOffice\PhpWord\Metadata\Settings { ... }, 'Compatibility' => class PhpOffice\PhpWord\Metadata\Compatibility { ... }] }, $relationships = ['main' => ['rId1' => [...], 'rId2' => [...], 'rId3' => [...]], 'document' => ['rId1' => [...], 'rId2' => [...], 'rId3' => [...], 'rId4' => [...], 'rId5' => [...], 'rId6' => [...]]], $commentRefs = [], $partName = 'Document', $docFile = 'uploads/Question_me2.docx', $xmlFile = 'word/document.xml' )...\Word2007.php:89 and here is the OfficeMathML.php <?php namespace PhpOffice\Math\Reader; use DOMDocument; use DOMNode; use DOMXPath; use PhpOffice\Math\Element; use PhpOffice\Math\Exception\InvalidInputException; use PhpOffice\Math\Exception\NotImplementedException; use PhpOffice\Math\Math; class OfficeMathML implements ReaderInterface { /** @var DOMDocument */ protected $dom; /** @var Math */ protected $math; /** @var DOMXpath */ protected $xpath; /** @var string[] */ protected $operators = ['+', '-', '/', '∗']; public function read(string $content): ?Math { $nsMath = 'xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math"'; $nsWord = 'xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"'; $content = str_replace( $nsMath, $nsMath . ' ' . $nsWord, $content ); $this->dom = new DOMDocument(); $this->dom->loadXML($content); $this->math = new Math(); $this->parseNode(null, $this->math); return $this->math; } /** * @see https://devblogs.microsoft.com/math-in-office/officemath/ * @see https://learn.microsoft.com/fr-fr/archive/blogs/murrays/mathml-and-ecma-math-omml * * @param Math|Element\AbstractGroupElement $parent */ protected function parseNode(?DOMNode $nodeRowElement, $parent): void { $this->xpath = new DOMXpath($this->dom); foreach ($this->xpath->query('*', $nodeRowElement) ?: [] as $nodeElement) { $element = $this->getElement($nodeElement); $parent->add($element); if ($element instanceof Element\AbstractGroupElement) { $this->parseNode($nodeElement, $element); } } } protected function getElement(DOMNode $nodeElement): Element\AbstractElement { switch ($nodeElement->nodeName) { case 'm:f': // Numerator $nodeNumerator = $this->xpath->query('m:num/m:r/m:t', $nodeElement); if ($nodeNumerator && $nodeNumerator->length == 1) { $value = $nodeNumerator->item(0)->nodeValue; if (is_numeric($value)) { $numerator = new Element\Numeric(floatval($value)); } else { $numerator = new Element\Identifier($value); } } else { throw new InvalidInputException(sprintf( '%s : The tag `%s` has no numerator defined', __METHOD__, $nodeElement->nodeName )); } // Denominator $nodeDenominator = $this->xpath->query('m:den/m:r/m:t', $nodeElement); if ($nodeDenominator && $nodeDenominator->length == 1) { $value = $nodeDenominator->item(0)->nodeValue; if (is_numeric($value)) { $denominator = new Element\Numeric(floatval($value)); } else { $denominator = new Element\Identifier($value); } } else { throw new InvalidInputException(sprintf( '%s : The tag `%s` has no denominator defined', __METHOD__, $nodeElement->nodeName )); } return new Element\Fraction($numerator, $denominator); case 'm:r': $nodeText = $this->xpath->query('m:t', $nodeElement); if ($nodeText && $nodeText->length == 1) { $value = trim($nodeText->item(0)->nodeValue); if (in_array($value, $this->operators)) { return new Element\Operator($value); } if (is_numeric($value)) { return new Element\Numeric(floatval($value)); } return new Element\Identifier($value); } throw new InvalidInputException(sprintf( '%s : The tag `%s` has no tag `m:t` defined', __METHOD__, $nodeElement->nodeName )); case 'm:oMath': return new Element\Row(); default: throw new NotImplementedException(sprintf( '%s : The tag `%s` is not implemented', __METHOD__, $nodeElement->nodeName )); } } } And here is my upload.php <?php session_start(); if ($_SESSION['role'] !== 'teacher') { header("Location: login.php"); exit(); } require 'db.php'; require 'vendor/autoload.php'; // Load the PHPWord library use PhpOffice\PhpWord\IOFactory; use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\Shared\Html; $database = new Database(); $db = $database->getConnection(); if ($_SERVER['REQUEST_METHOD'] == 'POST') { $class_id = $_POST['class_id']; $subject_id = $_POST['subject_id']; $file = $_FILES['file']; if ($file['type'] == 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') { $upload_dir = 'uploads/'; $file_path = $upload_dir . basename($file['name']); if (move_uploaded_file($file['tmp_name'], $file_path)) { try { // Convert .docx file to HTML $htmlFilePath = convertDocxToHtml($file_path); if ($htmlFilePath) { echo "File converted to HTML successfully.<br>"; } else { echo "Failed to convert file to HTML.<br>"; exit(); } // Parse the HTML file $htmlContent = file_get_contents($htmlFilePath); $questions = parseHtmlToQuestions($htmlContent); foreach ($questions as $question) { $stmt = $db->prepare("INSERT INTO questions (question_text, question_type, option_a, option_b, option_c, option_d, correct_option, subject_id) VALUES (?, 'Multiple Choice', ?, ?, ?, ?, ?, ?)"); if ($stmt->execute([ $question['question_text'], $question['options']['a'] ?? '', $question['options']['b'] ?? '', $question['options']['c'] ?? '', $question['options']['d'] ?? '', $question['correct_option'], $subject_id ])) { echo "Question inserted successfully: " . htmlspecialchars($question['question_text']) . "<br>"; } else { echo "Failed to insert question: " . htmlspecialchars($question['question_text']) . "<br>"; print_r($stmt->errorInfo()); } } echo "File uploaded and questions added successfully."; } catch (Exception $e) { echo "Error processing file: " . htmlspecialchars($e->getMessage()); } } else { echo "Failed to upload file."; } } else { echo "Invalid file type. Please upload a .docx file."; } } else { $classes = $db->query("SELECT * FROM classes")->fetchAll(PDO::FETCH_ASSOC); ?> <!DOCTYPE html> <html> <head> <title>Upload Questions</title> </head> <body> <h1>Upload Questions</h1> <form action="upload.php" method="post" enctype="multipart/form-data"> <label for="class">Class:</label> <select name="class_id" id="class" onchange="fetchSubjects(this.value)"> <option value="">Select Class</option> <?php foreach ($classes as $class): ?> <option value="<?= htmlspecialchars($class['class_id']) ?>"><?= htmlspecialchars($class['class_name']) ?></option> <?php endforeach; ?> </select> <label for="subject">Subject:</label> <select name="subject_id" id="subject"> <option value="">Select Subject</option> <!-- Subjects will be populated based on selected class --> </select> <label for="file">Choose a file:</label> <input type="file" name="file" id="file" accept=".docx"> <button type="submit">Upload</button> </form> <script> function fetchSubjects(classId) { fetch(`fetch_subjects.php?class_id=${classId}`) .then(response => response.json()) .then(data => { const subjectSelect = document.getElementById('subject'); subjectSelect.innerHTML = '<option value="">Select Subject</option>'; data.forEach(subject => { const option = document.createElement('option'); option.value = subject.subject_id; option.textContent = subject.subject_name; subjectSelect.appendChild(option); }); }); } </script> </body> </html> <?php } function convertDocxToHtml($filename) { $phpWord = IOFactory::load($filename); $htmlWriter = IOFactory::createWriter($phpWord, 'HTML'); $htmlFilePath = str_replace('.docx', '.html', $filename); $htmlWriter->save($htmlFilePath); return $htmlFilePath; } function parseHtmlToQuestions($htmlContent) { $questions = []; $currentQuestion = null; $dom = new DOMDocument; @$dom->loadHTML($htmlContent); $paragraphs = $dom->getElementsByTagName('p'); $currentPassage = ''; foreach ($paragraphs as $paragraph) { $text = trim($paragraph->textContent); $nodeContent = ''; foreach ($paragraph->childNodes as $node) { if ($node->nodeName === 'b' || $node->nodeName === 'strong') { $nodeContent .= '<b>' . $node->textContent . '</b>'; } elseif ($node->nodeName === 'i' || $node->nodeName === 'em') { $nodeContent .= '<i>' . $node->textContent . '</i>'; } elseif ($node->nodeName === 'img') { $src = $node->getAttribute('src'); $nodeContent .= '<img src="' . $src . '">'; } else { $nodeContent .= $node->textContent; } } // Handle equations (assuming they are marked with a specific tag or format) if (strpos($text, 'Equation:') === 0) { $equation = substr($text, 9); $currentQuestion['equation'] = $equation; // Store equations separately } if (strpos($text, 'Passage:') === 0) { if ($currentPassage) { $questions[] = ['passage' => $currentPassage, 'questions' => []]; } $currentPassage = substr($text, 8); } elseif (strpos($text, 'Question:') === 0) { if ($currentQuestion) { $questions[] = $currentQuestion; } $currentQuestion = [ 'question_text' => $nodeContent, 'options' => [], 'correct_option' => '', 'equation' => '', 'images' => [] ]; } elseif (preg_match('/^[A-D]\)/', $text)) { if ($currentQuestion) { $optionKey = strtolower($text[0]); $currentQuestion['options'][$optionKey] = substr($text, 3); } } elseif (strpos($text, 'Answer:') === 0) { if ($currentQuestion) { $currentQuestion['correct_option'] = trim(substr($text, 7)); } } } if ($currentQuestion) { $questions[] = $currentQuestion; } return $questions; } ?>
  17. I tried that but still gives the same results
  18. Why don't you group by job type, month
  19. I have had to go about it a totally different way because I need figures for each job type so have got this "SELECT ".PREFIX."tservices.IdService, ".PREFIX."tservices.Name, ".PREFIX."tservices.GraphColor, ".PREFIX."tprojects.Service, COUNT(".PREFIX."tprojects.IdProject) as Sales, ".PREFIX."tprojects.Finish FROM ".PREFIX."tservices LEFT JOIN ".PREFIX."tprojects ON ".PREFIX."tservices.IdService = ".PREFIX."tprojects.Service WHERE ".PREFIX."tservices.InGraph = '1' GROUP BY MONTH(".PREFIX."tprojects.Finish), YEAR(".PREFIX."tprojects.Finish) ORDER BY ".PREFIX."tprojects.Finish DESC LIMIT 0, 12" Then the PHP is if(!empty($data['legend'])) { foreach($data['legend'] as $r1) { if(isset($r1->Name)) { $sales = $this->_query->get_sales_count($r1->IdService); if(!empty($sales)) { foreach($sales as $r2) { $count[] = $r2->Sales; } $legend[] = array('label' => $r1->Name, 'backgroundColor' => $r1->GraphColor, 'data' => implode(',',$count)); } } } } But the json its outputting [{"label":"Installation","backgroundColor":"#2bca2d","data":"8,19,11,3,49"},{"label":"Repair","backgroundColor":"#cfca3a","data":"8,19,11,3,49,1,3,7"}] instead of [{"label":"Installation","backgroundColor":"#2bca2d","data":"8,19,11,3,49"},{"label":"Repair","backgroundColor":"#cfca3a","data":"1,3,7"}] Does anyone have any idea how to solve this? Thanks in advance
  20. Not that anyone has been using it this decade - or century, even - but there's a technology that exists which is designed for transforming XML into HTML as you just did. It's called XSLT. You can do it fully within PHP, but here's a demo without. kjv.xml <?xml version="1.0"?> <?xml-stylesheet href="kjv.xslt" type="text/xsl"?> <root> <book num="I don't know"> <chapter num="17"> <verse num="1">And after six days Jesus taketh Peter, James, and John his brother, and bringeth them up into an high mountain apart,</verse> <verse num="2">And was transfigured before them: and his face did shine as the sun, and his raiment was white as the light.</verse> <verse num="3">And, behold, there appeared unto them Moses and Elias talking with him.</verse> <verse num="4">Then answered Peter, and said unto Jesus, Lord, it is good for us to be here: if thou wilt, let us make here three tabernacles; one for thee, and one for Moses, and one for Elias.</verse> <verse num="5">While he yet spake, behold, a bright cloud overshadowed them: and behold a voice out of the cloud, which said, This is my beloved Son, in whom I am well pleased; hear ye him.</verse> <verse num="6">And when the disciples heard <i>it,</i> they fell on their face, and were sore afraid.</verse> <verse num="7">And Jesus came and touched them, and said, <span class="j">Arise, and be not afraid. </span></verse> <verse num="8">And when they had lifted up their eyes, they saw no man, save Jesus only.</verse> <verse num="9">And as they came down from the mountain, Jesus charged them, saying, <span class="j">Tell the vision to no man, until the Son of man be risen again from the dead. </span></verse> <verse num="10">And his disciples asked him, saying, Why then say the scribes that Elias must first come?</verse> <verse num="11">And Jesus answered and said unto them, <span class="j">Elias truly shall first come, and restore all things. </span></verse> <verse num="12"><span class="j">But I say unto you, That Elias is come already, and they knew him not, but have done unto him whatsoever they listed. Likewise shall also the Son of man suffer of them. </span></verse> <verse num="13">Then the disciples understood that he spake unto them of John the Baptist.</verse> <verse num="14">And when they were come to the multitude, there came to him a <i>certain</i> man, kneeling down to him, and saying,</verse> <verse num="15">Lord, have mercy on my son: for he is lunatick, and sore vexed: for ofttimes he falleth into the fire, and oft into the water.</verse> <verse num="16">And I brought him to thy disciples, and they could not cure him.</verse> <verse num="17">Then Jesus answered and said, <span class="j">O faithless and perverse generation, how long shall I be with you? how long shall I suffer you? bring him hither to me. </span></verse> </chapter> </book> </root> kjv.xslt <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" /> <xsl:template match="/"> <html> <body> <xsl:apply-templates select="/root/book" /> </body> </html> </xsl:template> <xsl:template match="book"> <h1>Book <xsl:value-of select="@num" /></h1> <xsl:apply-templates select="chapter" /> </xsl:template> <xsl:template match="chapter"> <h2>Chapter <xsl:value-of select="@num" /></h2> <ol start="{verse[1]/@num}"> <xsl:apply-templates select="verse" /> </ol> </xsl:template> <xsl:template match="verse"> <li><xsl:apply-templates /></li> </xsl:template> <xsl:template match="b | i | span"> <xsl:copy-of select="." /> </xsl:template> </xsl:stylesheet> In a browser, which you might have to run through a webserver depending on your browser security settings, (you can see the italics in verses 6 and 14; the spans are invisible but they are present)
  21. Thank you very much for your time. I will look through your solution and try to figure it out. In case it does not work, I will get rid of the Ajax processing, then use pure php to process my form.
  22. Last week
  23. Thank you.... xpath didn't really do what I wanted because of the fact I need to have other attributes above the verse (this is going into a database).... BUT ....asXML() did the trick when combined with my existing code. For anyone who may find this helpful, or struggle with the same general thing I did... here is my whole code for parsing this. The KJV.xml file can be found online pretty easily. <?php $fileName = $_SERVER['DOCUMENT_ROOT'].'/assets/php/kjv.xml'; if (file_exists($fileName)) { $xml = simplexml_load_file($fileName); foreach($xml->book as $book) { $bookName = $book['num']; foreach($book->chapter as $ch ){ $verseNum = 1; $chapterNum = $ch['num']; foreach($ch->verse as $verse){ echo $bookName.' '.$chapterNum.' '.$verseNum++.' '. $verse->asXML().'<br>'; } } } } ?> Thank you for your help in this. It is precisely what I needed.
  24. this checks the datatype of the variable, not what's in the variable. get, post, cookies are by definition strings, regardless of what value they hold. change this to is_numeric().
  25. Yeah I saw that - fixed that myself - still getting the same error Will try again... Nope! That didn't work. No error but still sends me back to home page.
  26. Olumide

    CBT Exam

    You are very intelligent sir. I saved the document as an html file and it created a folder as you have said. But my problem is, how do extract them? Here is my upload.php which extract text directly from Microsoft word but not extracting images or equation. <?php session_start(); if ($_SESSION['role'] !== 'teacher') { header("Location: login.php"); exit(); } require 'db.php'; require 'vendor/autoload.php'; // Load the PHPWord library use PhpOffice\PhpWord\IOFactory; $database = new Database(); $db = $database->getConnection(); if ($_SERVER['REQUEST_METHOD'] == 'POST') { $class_id = $_POST['class_id']; $subject_id = $_POST['subject_id']; $file = $_FILES['file']; if ($file['type'] == 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') { $upload_dir = 'uploads/'; $file_path = $upload_dir . basename($file['name']); if (move_uploaded_file($file['tmp_name'], $file_path)) { $phpWord = IOFactory::load($file_path, 'Word2007'); if ($phpWord) { echo "File loaded successfully.<br>"; } else { echo "Failed to load file.<br>"; exit(); } $questions = []; $currentQuestion = null; foreach ($phpWord->getSections() as $section) { foreach ($section->getElements() as $element) { if (method_exists($element, 'getText')) { $text = trim($element->getText()); // Convert bold text $text = preg_replace('/\*\*(.*?)\*\*/', '<strong>$1</strong>', $text); // Convert italicized text $text = preg_replace('/__(.*?)__/', '<em>$1</em>', $text); // Convert quoted text to blockquote $text = preg_replace('/\"(.*?)\"/', '<blockquote>$1</blockquote>', $text); // Convert subscript text $text = preg_replace('/~(.*?)~/', '<sub>$1</sub>', $text); // Convert superscript text $text = preg_replace('/\^(.*?)\^/', '<sup>$1</sup>', $text); if (strpos($text, 'Question:') === 0) { if ($currentQuestion) { $questions[] = $currentQuestion; } $currentQuestion = [ 'question_text' => substr($text, 10), 'options' => [], 'correct_option' => '' ]; } elseif (strpos($text, 'A)') === 0 || strpos($text, 'B)') === 0 || strpos($text, 'C)') === 0 || strpos($text, 'D)') === 0) { if ($currentQuestion) { $optionKey = strtolower($text[0]); $currentQuestion['options'][$optionKey] = substr($text, 3); } } elseif (strpos($text, 'Answer:') === 0) { if ($currentQuestion) { $currentQuestion['correct_option'] = trim(substr($text, 7)); } } } elseif (method_exists($element, 'getDrawing')) { // Handle image extraction $drawing = $element->getDrawing(); $imagePath = $drawing->getPath(); $imageName = basename($imagePath); $newImagePath = $upload_dir . $imageName; copy($imagePath, $newImagePath); // Here you can store $newImagePath in the database for the question } } } if ($currentQuestion) { $questions[] = $currentQuestion; } foreach ($questions as $question) { $stmt = $db->prepare("INSERT INTO questions (question_text, question_type, option_a, option_b, option_c, option_d, correct_option, subject_id) VALUES (?, 'Multiple Choice', ?, ?, ?, ?, ?, ?)"); if ($stmt->execute([ $question['question_text'], $question['options']['a'] ?? '', $question['options']['b'] ?? '', $question['options']['c'] ?? '', $question['options']['d'] ?? '', $question['correct_option'], $subject_id ])) { echo "Question inserted successfully: " . $question['question_text'] . "<br>"; } else { echo "Failed to insert question: " . $question['question_text'] . "<br>"; print_r($stmt->errorInfo()); } } echo "File uploaded and questions added successfully."; } else { echo "Failed to upload file."; } } else { echo "Invalid file type. Please upload a .docx file."; } } else { $classes = $db->query("SELECT * FROM classes")->fetchAll(PDO::FETCH_ASSOC); ?> <!DOCTYPE html> <html> <head> <title>Upload Questions</title> </head> <body> <h1>Upload Questions</h1> <form action="upload.php" method="post" enctype="multipart/form-data"> <label for="class">Class:</label> <select name="class_id" id="class" onchange="fetchSubjects(this.value)"> <option value="">Select Class</option> <?php foreach ($classes as $class): ?> <option value="<?= $class['class_id'] ?>"><?= $class['class_name'] ?></option> <?php endforeach; ?> </select> <label for="subject">Subject:</label> <select name="subject_id" id="subject"> <option value="">Select Subject</option> <!-- Subjects will be populated based on selected class --> </select> <label for="file">Choose a file:</label> <input type="file" name="file" id="file" accept=".docx"> <button type="submit">Upload</button> </form> <script> function fetchSubjects(classId) { fetch(`fetch_subjects.php?class_id=${classId}`) .then(response => response.json()) .then(data => { const subjectSelect = document.getElementById('subject'); subjectSelect.innerHTML = '<option value="">Select Subject</option>'; data.forEach(subject => { const option = document.createElement('option'); option.value = subject.subject_id; option.textContent = subject.subject_name; subjectSelect.appendChild(option); }); }); } </script> </body> </html> <?php } ?>
  27. Barand

    CBT Exam

    If you save "X.doc", which contains an equation, as "X.html" into a "documents" folder it creates as subfolder "X_files" containing the equation as an image documents | +- X.html +- X_files | +- image1.jpg
  28. Olumide

    CBT Exam

    Thank you sir. Can you please explain this further. In my previous and abandoned work, I do upload images inside the Microsoft word but and also wrote a script to identify that, but it doesn't work. It only captured the text documents.
  1. Load more activity
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.