From: Alexander Sadleir Date: Tue, 15 Nov 2011 07:50:54 +0000 Subject: Merge branch 'master' of ssh://apples.lambdacomplex.org/git/contractdashboard X-Git-Url: https://maxious.lambdacomplex.org/git/?p=contractdashboard.git&a=commitdiff&h=e7a65556b17654f82887e0597999a58bbde3588d --- Merge branch 'master' of ssh://apples.lambdacomplex.org/git/contractdashboard --- --- a/admin/import.php +++ b/admin/import.php @@ -261,10 +261,10 @@ } // run post import data processing // cn -//include ("linkAmendments.php"); +include ("linkAmendments.php"); include ("updateUNSPSC.php"); // agency -include ("setAgencyStatus.php"); -include ("setAgencyURLABN.php"); +//include ("setAgencyStatus.php"); +//include ("setAgencyURLABN.php"); ?> --- /dev/null +++ b/admin/neo4jimporter/.classpath @@ -1,1 +1,11 @@ + + + + + + + + + + --- /dev/null +++ b/admin/neo4jimporter/.project @@ -1,1 +1,24 @@ + + + neo4jimporter + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + --- /dev/null +++ b/admin/neo4jimporter/.settings/org.eclipse.jdt.core.prefs @@ -1,1 +1,7 @@ +#Sun Aug 07 18:15:32 EST 2011 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.source=1.5 --- /dev/null +++ b/admin/neo4jimporter/.settings/org.eclipse.m2e.core.prefs @@ -1,1 +1,6 @@ +#Sun Aug 07 18:14:30 EST 2011 +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 --- /dev/null +++ b/admin/neo4jimporter/nbactions.xml @@ -1,1 +1,53 @@ + + + + run + + process-classes + org.codehaus.mojo:exec-maven-plugin:1.2:exec + + + runtime + -Xmx4048M -server -classpath %classpath ${packageClassName} + java + + + + debug + + process-classes + org.codehaus.mojo:exec-maven-plugin:1.2:exec + + + runtime + -Xdebug -Xrunjdwp:transport=dt_socket,server=n,address=${jpda.address} -Xmx4048M -server -classpath %classpath ${packageClassName} + true + java + + + + profile + + process-classes + org.codehaus.mojo:exec-maven-plugin:1.1.1:exec + + + ${profiler.args} -Xmx4048M -server -classpath %classpath ${packageClassName} + profile + ${profiler.java} + + + + run + + process-classes + org.codehaus.mojo:exec-maven-plugin:1.2:exec + + + runtime + -classpath %classpath Importer + java + + + --- /dev/null +++ b/admin/neo4jimporter/pom.xml @@ -1,1 +1,18 @@ - + + 4.0.0 + org.lambdacomplex.contractdashboard + neo4jimporter + 0.0.1-SNAPSHOT + + + org.neo4j + neo4j + 1.5 + + + postgresql + postgresql + 9.0-801.jdbc4 + + + --- /dev/null +++ b/admin/neo4jimporter/src/main/java/Importer.java @@ -1,1 +1,159 @@ +import java.io.ObjectInputStream.GetField; +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.sql.Statement; +import java.util.HashMap; +import java.util.Map; + +import org.neo4j.graphdb.DynamicRelationshipType; +import org.neo4j.graphdb.GraphDatabaseService; +import org.neo4j.graphdb.Node; +import org.neo4j.graphdb.index.BatchInserterIndex; +import org.neo4j.graphdb.index.BatchInserterIndexProvider; +import org.neo4j.helpers.collection.MapUtil; +import org.neo4j.kernel.impl.batchinsert.BatchInserter; +import org.neo4j.kernel.impl.batchinsert.BatchInserterImpl; +import org.neo4j.index.impl.lucene.*; + +public class Importer { + + public static void main(String[] argv) { + BatchInserter inserter = new BatchInserterImpl("target/neo4jdb-batchinsert"); + BatchInserterIndexProvider indexProvider = new LuceneBatchInserterIndexProvider(inserter); + BatchInserterIndex labels = indexProvider.nodeIndex("labels", MapUtil.stringMap("type", "exact")); + labels.setCacheCapacity("Label", 100000); + + + + System.out.println("-------- PostgreSQL " + + "JDBC Connection Testing ------------"); + + try { + + Class.forName("org.postgresql.Driver"); + + } catch (ClassNotFoundException e) { + + System.out.println("Where is your PostgreSQL JDBC Driver? " + + "Include in your library path!"); + e.printStackTrace(); + + } + + System.out.println("PostgreSQL JDBC Driver Registered!"); + + Connection conn = null; + + try { + + conn = DriverManager.getConnection( + "jdbc:postgresql://127.0.0.1:5432/contractDashboard", + "postgres", "snmc"); + + } catch (SQLException e) { + + System.out.println("Connection Failed! Check output console"); + e.printStackTrace(); + + } + + if (conn != null) { + System.out.println("You made it, take control your database now!"); + } else { + System.out.println("Failed to make connection!"); + } + try { + // Print all warnings + for (SQLWarning warn = conn.getWarnings(); warn != null; warn = warn.getNextWarning()) { + System.out.println("SQL Warning:"); + System.out.println("State : " + warn.getSQLState()); + System.out.println("Message: " + warn.getMessage()); + System.out.println("Error : " + warn.getErrorCode()); + } + + // Get a statement from the connection + Statement stmt = conn.createStatement(); + + // Execute the query + ResultSet rs = stmt.executeQuery("SELECT contractnotice.\"agencyName\", " + + " contractnotice.\"supplierABN\",contractnotice.\"supplierName\",sum(value) as sum " + + "FROM public.contractnotice where contractnotice.\"agencyName\" != 'Department of Defence'" + + " AND contractnotice.\"agencyName\" != 'Defence Materiel Organisation' GROUP BY contractnotice.\"agencyName\", " + + " contractnotice.\"supplierABN\",contractnotice.\"supplierName\""); + String previousAgency = ""; +GraphDatabaseService gds = inserter.getGraphDbService(); +HashMap supplierIDs = new HashMap(); +HashMap agencyIDs = new HashMap(); + + // Loop through the result set + while (rs.next()) { + long supplierID, agencyID; + String supplierKey; + if (agencyIDs.get(rs.getString("agencyName")) == null) { + Node myNode = gds.createNode(); + myNode.setProperty("Label", rs.getString("agencyName")); + myNode.setProperty("type", "agency"); + agencyIDs.put(rs.getString("agencyName"), myNode.getId()); + if (myNode.getId() %100 == 0) { + System.out.println("Agency "+myNode.getId()); +} + } + agencyID = agencyIDs.get(rs.getString("agencyName")); + + + if (rs.getString("supplierABN") != "0" && rs.getString("supplierABN") != "") { + supplierKey = rs.getString("supplierABN"); + } else { + supplierKey = rs.getString("supplierName"); + } + // inject some data + if (supplierIDs.get(supplierKey) == null) { + Node myNode = gds.createNode(); + myNode.setProperty("Label", rs.getString("supplierName")); + myNode.setProperty("type", "supplier"); + supplierIDs.put(supplierKey, myNode.getId()); + if (myNode.getId() %1000 == 0) { + System.out.println("Supplier "+myNode.getId()); +} + } + supplierID = supplierIDs.get(supplierKey); + + + long rel = inserter.createRelationship(agencyID, supplierID, + DynamicRelationshipType.withName("KNOWS"), null); + inserter.setRelationshipProperty(rel, "Weight", rs.getDouble("sum")); + + } + // Close the result set, statement and the connection + rs.close(); + stmt.close(); + conn.close(); + } catch (SQLException se) { + System.out.println("SQL Exception:"); + + // Loop through the SQL Exceptions + while (se != null) { + System.out.println("State : " + se.getSQLState()); + System.out.println("Message: " + se.getMessage()); + System.out.println("Error : " + se.getErrorCode()); + + se = se.getNextException(); + } + } +//make the changes visible for reading, use this sparsely, requires IO! + labels.flush(); + +// Make sure to shut down the index provider + indexProvider.shutdown(); + inserter.shutdown(); + } + + +} --- /dev/null +++ b/admin/neo4jimporter/src/main/java/JDBCExample.java @@ -1,1 +1,50 @@ - +import java.sql.DriverManager; +import java.sql.Connection; +import java.sql.SQLException; + +public class JDBCExample { + + public static void main(String[] argv) { + + System.out.println("-------- PostgreSQL " + + "JDBC Connection Testing ------------"); + + try { + + Class.forName("org.postgresql.Driver"); + + } catch (ClassNotFoundException e) { + + System.out.println("Where is your PostgreSQL JDBC Driver? " + + "Include in your library path!"); + e.printStackTrace(); + return; + + } + + System.out.println("PostgreSQL JDBC Driver Registered!"); + + Connection connection = null; + + try { + + connection = DriverManager.getConnection( + "jdbc:postgresql://127.0.0.1:5432/contractDashboard", "postgres", + "snmc"); + + } catch (SQLException e) { + + System.out.println("Connection Failed! Check output console"); + e.printStackTrace(); + return; + + } + + if (connection != null) { + System.out.println("You made it, take control your database now!"); + } else { + System.out.println("Failed to make connection!"); + } + } + +} --- a/admin/partialdata/01Jan1970to01Jan1970val0to16000.xls +++ /dev/null @@ -1,4 +1,1 @@ -Advanced Search - -CN ID Title Agency Publish Date Category Contract Start Date Contract End Date Value (AUD) ATM ID Supplier Name LastUpdated -There are no results that match your selection. + --- a/admin/partialdata/01Jan1970to01Jan1970valto.xls +++ /dev/null @@ -1,4 +1,1 @@ -Advanced Search - -CN ID Title Agency Publish Date Category Contract Start Date Contract End Date Value (AUD) ATM ID Supplier Name LastUpdated -There are no results that match your selection. + --- a/admin/partialdata/07Jun2008to09Jun2008valto.xls +++ /dev/null @@ -1,4 +1,1 @@ -Advanced Search - -CN ID Title Agency Publish Date Category Contract Start Date Contract End Date Value (AUD) ATM ID Supplier Name LastUpdated -There are no results that match your selection. + --- a/admin/partialdata/12May2008to14May2008val0to8000.xls +++ /dev/null @@ -1,4 +1,1 @@ -Advanced Search - -CN ID Title Agency Publish Date Category Contract Start Date Contract End Date Value (AUD) ATM ID Supplier Name LastUpdated -There are no results that match your selection. + --- a/admin/partialdata/14Aug2007to18Aug2007valto.xls +++ /dev/null @@ -1,4 +1,1 @@ -Advanced Search -CN ID Title Agency Publish Date Category Contract Start Date Contract End Date Value (AUD) ATM ID Supplier Name LastUpdated -There are no results that match your selection. --- a/admin/partialdata/14Aug2007to22Aug2007valto.xls +++ /dev/null @@ -1,4 +1,1 @@ -Advanced Search -CN ID Title Agency Publish Date Category Contract Start Date Contract End Date Value (AUD) ATM ID Supplier Name LastUpdated -There are no results that match your selection. --- a/admin/partialdata/14Aug2007to29Aug2007valto.xls +++ /dev/null @@ -1,4 +1,1 @@ -Advanced Search -CN ID Title Agency Publish Date Category Contract Start Date Contract End Date Value (AUD) ATM ID Supplier Name LastUpdated -There are no results that match your selection. --- a/admin/partialdata/14Nov2007to18Nov2007valto.xls +++ b/admin/partialdata/14Nov2007to18Nov2007valto.xls @@ -254,7 +254,7 @@ ="CN46513" "Secure LAN facilities for ICON RFT project" ="Department of Agriculture Fisheries and Forestry" 15-Nov-07 ="Insurance and retirement services" 06-Nov-07 31-May-08 26290.12 ="" ="MBITS - Managed Business IT Solutions" 15-Nov-07 02:02 PM ="CN46515" "Business Analyst" ="Department of Agriculture Fisheries and Forestry" 15-Nov-07 ="Management advisory services" 01-Nov-07 01-Feb-08 14960.00 ="" ="Dialog Information Technology" 15-Nov-07 02:02 PM ="CN46517-A1" "Provision of recruitment services for the 2009 Traineeship Programme." ="Department of Agriculture Fisheries and Forestry" 15-Nov-07 ="Human resources services" 31-Oct-07 29-Feb-08 18053.00 ="" ="Ross Human Directions Limited" 15-Nov-07 02:03 PM -="CN46518" "To facilitate negotiations and implement Resource Sharing agreements in Australia's Tuna and Billfish fisheries. The consultant activities are as follows:1. Review existing options (research & interpretation)2. Consultation with stakeholders to identify views and positions (facilitation)3. Collate data, analyse data and prepare draft revised agreements between parties (research)4. Consultations to present, discuss and refine agreements between parties (facilitation)5. Further develop/refine agreements and implementation capabilities6. Consultation to finalise agreements and implementation capabilities7. Written report to Government on matters arising from the agreement and implementation.The key output of these activities will be revised recommendations for resource sharing arrangement in the WTBF and the ETBF based on successful stakeholder consultation." ="Department of Agriculture Fisheries and Forestry" 15-Nov-07 ="Management advisory services" 25-Oct-07 25-Oct-08 10843.69 ="" ="Ewan Colquhoun, RidgePartners" 15-Nov-07 02:03 PM +="CN46518" "To facilitate negotiations and implement Resource Sharing agreements in Australia's Tuna and Billfish fisheries. " ="Department of Agriculture Fisheries and Forestry" 15-Nov-07 ="Management advisory services" 25-Oct-07 25-Oct-08 10843.69 ="" ="Ewan Colquhoun, RidgePartners" 15-Nov-07 02:03 PM ="CN46519" "Sample Analysis - Foreign Certificate Audit" ="Department of Agriculture Fisheries and Forestry" 15-Nov-07 ="Management and Business Professionals and Administrative Services" 30-Oct-07 30-Apr-08 50000.00 ="" ="National Measurement Institute" 15-Nov-07 02:03 PM ="CN46520" "Sample Analysis - Foreign Certificate Audit" ="Department of Agriculture Fisheries and Forestry" 15-Nov-07 ="Management and Business Professionals and Administrative Services" 30-Oct-07 30-Apr-08 20000.00 ="" ="Silliker Microtech Pty Ltd" 15-Nov-07 02:03 PM ="CN46521" "Assessing the feasibility of stereo video and evaluating monitoring options for the southern bluefin tuna farm sector" ="Department of Agriculture Fisheries and Forestry" 15-Nov-07 ="Management advisory services" 01-Jul-07 31-Dec-07 22000.00 ="" ="Australian Southern Bluefin Tuna Industry Association" 15-Nov-07 02:03 PM --- a/admin/partialdata/15Sep2007to16Sep2007valto.xls +++ /dev/null @@ -1,4 +1,1 @@ -Advanced Search -CN ID Title Agency Publish Date Category Contract Start Date Contract End Date Value (AUD) ATM ID Supplier Name LastUpdated -There are no results that match your selection. --- a/admin/partialdata/22Aug2007to30Aug2007valto.xls +++ /dev/null @@ -1,4 +1,1 @@ -Advanced Search -CN ID Title Agency Publish Date Category Contract Start Date Contract End Date Value (AUD) ATM ID Supplier Name LastUpdated -There are no results that match your selection. --- a/admin/partialdata/29Aug2007to02Sep2007valto.xls +++ /dev/null @@ -1,4 +1,1 @@ -Advanced Search -CN ID Title Agency Publish Date Category Contract Start Date Contract End Date Value (AUD) ATM ID Supplier Name LastUpdated -There are no results that match your selection. --- a/admin/partialdata/import.php +++ b/admin/partialdata/import.php @@ -1,9 +1,13 @@ "; + flush(); $row = 1; + $success = 0; + $dupes = 0; $handle = fopen($fpath, "r"); //"t" mode string translates windows line breaks to unix $datamapping0507 = array( @@ -16,7 +20,8 @@ "Title" => "description", "Category" => "category", "ATM ID" => "atmID", - "LastUpdated" => "", + "Supplier Name" => "supplierName", + "LastUpdated" => "amendDate", "" => "" ); $headers; @@ -32,7 +37,7 @@ "value", "atmID", "supplierName", - "LastUpdated" + "amendDate" ); if ($tablename == "contractnotice") { $contractNoticeInsertQ = 'INSERT INTO contractnotice ("' . implode('" , "', $contractNoticeFields) . '") VALUES ( '; @@ -50,7 +55,7 @@ } elseif ($row > 3) { if ($num > count($datamapping0507)) { - die("Error in data import; data mapping fields out of bounds or changed
" . $fname . print_r($data)); + die("Error in data import; data mapping fields out of bounds or changed
" . $fname . "data:" .$num. print_r($data ,true). "mapping:" . count($datamapping0507). print_r($datamapping0507 ,true)); } $contractNoticeInsert = Array(); $contractNoticeInsert[] = $fpath; @@ -98,6 +103,7 @@ $contractNoticeInsertQ->execute($contractNoticeInsert); $errors = $conn->errorInfo(); if ($errors[1] == 7 && strpos($errors[2], "duplicate key")) { + $dupes++; } elseif ($errors[1] == 0) { $success++; @@ -116,6 +122,9 @@ $row++; } fclose($handle); + echo " $dupes duplicate records
"; + echo " $success records successfully created
"; + flush(); return $success; } $path = './'; @@ -127,8 +136,9 @@ if ($dhandle) { // loop through all of the files while (false !== ($fname = readdir($dhandle))) { - if (($fname != '.') && ($fname != '..')) { + if (($fname != '.') && ($fname != '..') && (!isset($_REQUEST["filter"]) || strpos($fname,$_REQUEST["filter"]) != false)) { echo "$fname " . filesize($path . $fname) . " " . date("c", filemtime($path . $fname)) . "
"; + processFile($path . $fname, "contractnotice"); } } } @@ -136,11 +146,9 @@ else { $success = 0; $fname = $_REQUEST["fname"]; - echo " ============== $fname ==============
"; - flush(); + $success+= processFile($path . $fname, "contractnotice"); - echo "
$success records successfully created"; - flush(); + } ?> --- /dev/null +++ b/admin/partialdata/importamendments.php @@ -1,1 +1,329 @@ - + Database temporarily unavailable: "; + echo curl_errno($ch) . " " . curl_error($ch); + + echo $url; + echo "
"; + } + curl_close($ch); + return $page; +} + + +function getTextFromTHNode($Node, $Text = "") { + if ($Node->tagName == null) + return $Text.$Node->textContent; + +if ($Node->tagName != "td") { + $Node = $Node->firstChild; + if ($Node != null) + $Text = getTextFromTHNode($Node, $Text); + + while($Node->nextSibling != null) { + $Text = getTextFromTHNode($Node->nextSibling, $Text); + $Node = $Node->nextSibling; + } +} + return $Text; +} + +function getTextFromNode($Node, $Text = "") { + if ($Node->tagName == null) + return $Text.$Node->textContent; +if ($Node->tagName != "th" && $Node->tagName != "span") { + $Node = $Node->firstChild; + if ($Node != null) + $Text = getTextFromNode($Node, $Text); + + while($Node->nextSibling != null) { + $Text = getTextFromNode($Node->nextSibling, $Text); + $Node = $Node->nextSibling; + } +} + return $Text; +} +function dom_to_array($root) +{ + $result = array(); + + if ($root->hasAttributes()) + { + $attrs = $root->attributes; + + foreach ($attrs as $i => $attr) + $result[$attr->name] = $attr->value; + } + + $children = $root->childNodes; +if ($root->childNodes) { + if ($children->length == 1) + { + $child = $children->item(0); + + if ($child->nodeType == XML_TEXT_NODE) + { + $result['_value'] = $child->nodeValue; + + if (count($result) == 1) + return $result['_value']; + else + return $result; + } + } + + $group = array(); + + for($i = 0; $i < $children->length; $i++) + { + $child = $children->item($i); + + if (!isset($result[$child->nodeName])) + $result[$child->nodeName] = dom_to_array($child); + else + { + if (!isset($group[$child->nodeName])) + { + $tmp = $result[$child->nodeName]; + $result[$child->nodeName] = array($tmp); + $group[$child->nodeName] = 1; + } + + $result[$child->nodeName][] = dom_to_array($child); + } + } +} + + return $result; +} + +function importCN($cnid) { + global $conn; + $CN = str_replace("-A", "00",$cnid); + // check if already complete + $query = 'Select "parentCN" from contractnotice + where "CNID" = :CNID'; + $query = $conn->prepare($query); + $query->bindParam(":CNID", $CN); + $query->execute(); + $r = $query->fetch(PDO::FETCH_ASSOC); + if ($r['parentCN'] == NULL) { +$site = "https://www.tenders.gov.au/"; +$searchResult = phpQuery::newDocument(getURL("https://www.tenders.gov.au/?event=public.advancedsearch.keyword&keyword=CN".$cnid)); +//echo "https://www.tenders.gov.au/?event=public.advancedsearch.keyword&keyword=CN".$cnid; +$url = ""; +foreach(pq('a') as $a) { + if (strpos($a->getAttribute("href"),"public.cn.view") >0 ) { + //echo $a->getAttribute("href"); + $url = $a->getAttribute("href"); + break; + } +} +$cn = phpQuery::newDocument(getURL($site.$url)); + $datamapping0711 = array( + "Agency" => "agencyName", + "Parent CN" => "parentCN", + "CN ID" => "CNID", + "Publish Date" => "publishDate", + "Amendment Date" => "amendDate", + "Status" => "", + "StartDate" => "contractStart", + "EndDate" => "contractEnd", + "Contract Value (AUD)" => "value", + "Description" => "description", + "Agency Reference ID" => "agencyID", + "Category" => "category", + "Procurement Method" => "procurementMethod", + "ATM ID" => "atmID", + "SON ID" => "SONID", + "Confidentiality - Contract" => "confidentialityContract", + "Confidentiality Reason(s) - Contract" => "confidentialityContractReason", + "Confidentiality - Outputs" => "confidentialityOutputs", + "Confidentiality Reason(s) - Outputs" => "confidentialityOutputsReason", + "Consultancy" => "consultancy", + "Consultancy Reason(s)" => "consultancyReason", + "Amendment Reason" => "amendmentReason", + "Name" => "supplierName", + "Postal Address" => "supplierAddress", + "Town/City" => "supplierCity", + "Postcode" => "supplierPostcode", + "Country" => "supplierCountry", + "ABN Exempt" => "supplierABNExempt", + "ABN" => "supplierABN", + "Branch" => "contactBranch", + "Division" => "contactDivision", + "Office Postcode" => "contactPostcode" + ); +$cnFields = Array(); +foreach(pq('tr') as $tr) { + $tra = dom_to_array($tr); + if (is_array($tra['th'])) { + $fieldName = trim(getTextFromTHNode($tr)); + } else { + $fieldName = trim(str_replace("/th>","",$tra['th'])); + } + $fieldValue = trim(print_r($tra['td'],true)); + if ($fieldName == "State/Territory" || $fieldName == "Contact Name" + || $fieldName == "Contact Phone" || $fieldName == "Contact Email" + ||$fieldName == "Amendments") { + // do nothing + } else if ($fieldName == "Contract Period") { + $contractPeriod = explode("to",$fieldValue); + $cnFields["contractStart"] = trim($contractPeriod[0]); + $cnFields["contractEnd"] = trim($contractPeriod[1]); + } else { + $fieldName = $datamapping0711[$fieldName]; + + if ($fieldName == "parentCN" || $fieldName == "CNID") { + if (is_array($tra['td'])) { + $fieldValue = trim(getTextFromNode($tr)); + } + $fieldValue = substr($fieldValue, 2); // take off the "CN" prefix + $fieldValue = str_replace("-A", "00", $fieldValue); // make amendments really big numbers + } elseif ($fieldName == "description") { + + if (is_array($tra['td'])) $fieldValue = print_r($tra['td']['p'],true); + + } elseif ($fieldName == "value" || $fieldName == "supplierABN") { + if (is_array($tra['td'])) { + $fieldValue = trim(getTextFromNode($tr)); + } + $fieldValue = str_replace(Array("$",","," "), "", $fieldValue); + //if (!is_numeric($fieldValue)) $fieldValue = 0; + if ($fieldValue == "Exempt") $fieldValue = NULL; + } elseif ($fieldName == "amendDate" || $fieldName == "publishDate" || $fieldName == "contractStart" || $fieldName == "contractEnd") { + $fieldValue = date('Y-m-d H:i:s', strtotime($fieldValue)); + } elseif (is_array($tra['td'])) { + $fieldValue = trim(getTextFromNode($tr)); + } + echo $fieldName. " = " .$fieldValue."
\n"; + $cnFields[$fieldName] = $fieldValue; + } +} +if (isset($cnFields[""])) { + $cnFields["description"] .= $cnFields[""]; + unset($cnFields[""]); +} +$cnFields["importFile"] = $url; +$contractNoticeInsertQ = 'INSERT INTO contractnotice ("' . implode('" , "', array_keys($cnFields)) . '") VALUES ( '; + for($key = 0; $key < sizeof($cnFields); $key++) { + $contractNoticeInsertQ.= ($key == 0 ? "" : ", ") . "?"; + } + $contractNoticeInsertQ.= ");"; + //echo $contractNoticeInsertQ; + $contractNoticeInsertQ = $conn->prepare($contractNoticeInsertQ); + $contractNoticeInsertQ->execute(array_values($cnFields)); + $errors = $conn->errorInfo(); + if ($errors[1] == 7 && strpos($errors[2], "duplicate key")) { + echo "Dupe {$cnFields['CNID']}
"; + } + elseif ($errors[1] == 0) { + echo "Success insert {$cnFields['CNID']}
"; + } + else { + foreach ($cnFields as $key => $cnf) { + echo var_dump($key) . $cnf . "
"; + } + echo $cnFields['CNID'] . " failed CN insert.
" . print_r($errors, true) . "
row $row

\n"; + } +$contractNoticeUpdateQ = 'UPDATE contractnotice SET '; +$count = 0; + foreach ($cnFields as $key => $f) { + + $count++; + $contractNoticeUpdateQ.= '"'.$key.'"=? '.($count >= sizeof($cnFields) ? "" : ", "); + } + $contractNoticeUpdateQ.= ' WHERE "CNID"=?;'; + $cnFields[] = $cnFields["CNID"]; + //echo $contractNoticeUpdateQ; + $contractNoticeUpdateQ = $conn->prepare($contractNoticeUpdateQ); + $contractNoticeUpdateQ->execute(array_values($cnFields)); + $errors = $conn->errorInfo(); + if ($errors[1] == 7 && strpos($errors[2], "duplicate key")) { + print_r($errors); + echo "Dupe update {$cnFields['CNID']}
"; + } + elseif ($errors[1] == 0) { + echo "Success update {$cnFields['CNID']}
"; + } + else { + foreach ($cnFields as $key => $cnf) { + echo var_dump($key) . $cnf . "
"; + } + echo $cnFields['CNID'] . " failed CN update.
" . print_r($errors, true) . "
row $row

\n"; + } + } +} +function processFile($fpath, $tablename) +{ + global $conn; + echo " ============== $fpath ==============
"; + + $handle = fopen($fpath, "r"); + flush(); + $row = 1; + + while (($data = fgetcsv($handle, 1000, "\t")) !== false) { + if ($row > 3) { + $data[0] = trim($data[0], "="); + $data[0] = trim($data[0], "\""); + if (strpos($data[0], "-A") > 0) { + echo "Loading {$data[0]} ...
\n"; + importCN(str_replace("CN","",$data[0])); + } + } + flush(); + //echo "
\n"; + + + $row++; + } + fclose($handle); +} +$path = './'; +if ($_REQUEST["fname"] == "") { + echo "Get files from: https://www.tenders.gov.au/?event=public.reports.list
"; + $dhandle = opendir($path); + // define an array to hold the files + $files = array(); + if ($dhandle) { + // loop through all of the files + while (false !== ($fname = readdir($dhandle))) { + if (($fname != '.') && ($fname != '..') && (strpos($fname,".xls")>0)) { + echo "$fname " . filesize($path . $fname) . " " . date("c", filemtime($path . $fname)) . "
"; + processFile($path . $fname, "contractnotice"); + } + } + } +} +else { + $success = 0; + $fname = $_REQUEST["fname"]; + + $success+= processFile($path . $fname, "contractnotice"); + +} + +?> + --- /dev/null +++ b/admin/partialdata/phpQuery-onefile.php @@ -1,1 +1,5702 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT License + * @package phpQuery + */ +// class names for instanceof +// TODO move them as class constants into phpQuery +define('DOMDOCUMENT', 'DOMDocument'); +define('DOMELEMENT', 'DOMElement'); +define('DOMNODELIST', 'DOMNodeList'); +define('DOMNODE', 'DOMNode'); + +/** + * DOMEvent class. + * + * Based on + * @link http://developer.mozilla.org/En/DOM:event + * @author Tobiasz Cudnik + * @package phpQuery + * @todo implement ArrayAccess ? + */ +class DOMEvent { + /** + * Returns a boolean indicating whether the event bubbles up through the DOM or not. + * + * @var unknown_type + */ + public $bubbles = true; + /** + * Returns a boolean indicating whether the event is cancelable. + * + * @var unknown_type + */ + public $cancelable = true; + /** + * Returns a reference to the currently registered target for the event. + * + * @var unknown_type + */ + public $currentTarget; + /** + * Returns detail about the event, depending on the type of event. + * + * @var unknown_type + * @link http://developer.mozilla.org/en/DOM/event.detail + */ + public $detail; // ??? + /** + * Used to indicate which phase of the event flow is currently being evaluated. + * + * NOT IMPLEMENTED + * + * @var unknown_type + * @link http://developer.mozilla.org/en/DOM/event.eventPhase + */ + public $eventPhase; // ??? + /** + * The explicit original target of the event (Mozilla-specific). + * + * NOT IMPLEMENTED + * + * @var unknown_type + */ + public $explicitOriginalTarget; // moz only + /** + * The original target of the event, before any retargetings (Mozilla-specific). + * + * NOT IMPLEMENTED + * + * @var unknown_type + */ + public $originalTarget; // moz only + /** + * Identifies a secondary target for the event. + * + * @var unknown_type + */ + public $relatedTarget; + /** + * Returns a reference to the target to which the event was originally dispatched. + * + * @var unknown_type + */ + public $target; + /** + * Returns the time that the event was created. + * + * @var unknown_type + */ + public $timeStamp; + /** + * Returns the name of the event (case-insensitive). + */ + public $type; + public $runDefault = true; + public $data = null; + public function __construct($data) { + foreach($data as $k => $v) { + $this->$k = $v; + } + if (! $this->timeStamp) + $this->timeStamp = time(); + } + /** + * Cancels the event (if it is cancelable). + * + */ + public function preventDefault() { + $this->runDefault = false; + } + /** + * Stops the propagation of events further along in the DOM. + * + */ + public function stopPropagation() { + $this->bubbles = false; + } +} + + +/** + * DOMDocumentWrapper class simplifies work with DOMDocument. + * + * Know bug: + * - in XHTML fragments,
changes to
+ * + * @todo check XML catalogs compatibility + * @author Tobiasz Cudnik + * @package phpQuery + */ +class DOMDocumentWrapper { + /** + * @var DOMDocument + */ + public $document; + public $id; + /** + * @todo Rewrite as method and quess if null. + * @var unknown_type + */ + public $contentType = ''; + public $xpath; + public $uuid = 0; + public $data = array(); + public $dataNodes = array(); + public $events = array(); + public $eventsNodes = array(); + public $eventsGlobal = array(); + /** + * @TODO iframes support http://code.google.com/p/phpquery/issues/detail?id=28 + * @var unknown_type + */ + public $frames = array(); + /** + * Document root, by default equals to document itself. + * Used by documentFragments. + * + * @var DOMNode + */ + public $root; + public $isDocumentFragment; + public $isXML = false; + public $isXHTML = false; + public $isHTML = false; + public $charset; + public function __construct($markup = null, $contentType = null, $newDocumentID = null) { + if (isset($markup)) + $this->load($markup, $contentType, $newDocumentID); + $this->id = $newDocumentID + ? $newDocumentID + : md5(microtime()); + } + public function load($markup, $contentType = null, $newDocumentID = null) { +// phpQuery::$documents[$id] = $this; + $this->contentType = strtolower($contentType); + if ($markup instanceof DOMDOCUMENT) { + $this->document = $markup; + $this->root = $this->document; + $this->charset = $this->document->encoding; + // TODO isDocumentFragment + } else { + $loaded = $this->loadMarkup($markup); + } + if ($loaded) { +// $this->document->formatOutput = true; + $this->document->preserveWhiteSpace = true; + $this->xpath = new DOMXPath($this->document); + $this->afterMarkupLoad(); + return true; + // remember last loaded document +// return phpQuery::selectDocument($id); + } + return false; + } + protected function afterMarkupLoad() { + if ($this->isXHTML) { + $this->xpath->registerNamespace("html", "http://www.w3.org/1999/xhtml"); + } + } + protected function loadMarkup($markup) { + $loaded = false; + if ($this->contentType) { + self::debug("Load markup for content type {$this->contentType}"); + // content determined by contentType + list($contentType, $charset) = $this->contentTypeToArray($this->contentType); + switch($contentType) { + case 'text/html': + phpQuery::debug("Loading HTML, content type '{$this->contentType}'"); + $loaded = $this->loadMarkupHTML($markup, $charset); + break; + case 'text/xml': + case 'application/xhtml+xml': + phpQuery::debug("Loading XML, content type '{$this->contentType}'"); + $loaded = $this->loadMarkupXML($markup, $charset); + break; + default: + // for feeds or anything that sometimes doesn't use text/xml + if (strpos('xml', $this->contentType) !== false) { + phpQuery::debug("Loading XML, content type '{$this->contentType}'"); + $loaded = $this->loadMarkupXML($markup, $charset); + } else + phpQuery::debug("Could not determine document type from content type '{$this->contentType}'"); + } + } else { + // content type autodetection + if ($this->isXML($markup)) { + phpQuery::debug("Loading XML, isXML() == true"); + $loaded = $this->loadMarkupXML($markup); + if (! $loaded && $this->isXHTML) { + phpQuery::debug('Loading as XML failed, trying to load as HTML, isXHTML == true'); + $loaded = $this->loadMarkupHTML($markup); + } + } else { + phpQuery::debug("Loading HTML, isXML() == false"); + $loaded = $this->loadMarkupHTML($markup); + } + } + return $loaded; + } + protected function loadMarkupReset() { + $this->isXML = $this->isXHTML = $this->isHTML = false; + } + protected function documentCreate($charset, $version = '1.0') { + if (! $version) + $version = '1.0'; + $this->document = new DOMDocument($version, $charset); + $this->charset = $this->document->encoding; +// $this->document->encoding = $charset; + $this->document->formatOutput = true; + $this->document->preserveWhiteSpace = true; + } + protected function loadMarkupHTML($markup, $requestedCharset = null) { + if (phpQuery::$debug) + phpQuery::debug('Full markup load (HTML): '.substr($markup, 0, 250)); + $this->loadMarkupReset(); + $this->isHTML = true; + if (!isset($this->isDocumentFragment)) + $this->isDocumentFragment = self::isDocumentFragmentHTML($markup); + $charset = null; + $documentCharset = $this->charsetFromHTML($markup); + $addDocumentCharset = false; + if ($documentCharset) { + $charset = $documentCharset; + $markup = $this->charsetFixHTML($markup); + } else if ($requestedCharset) { + $charset = $requestedCharset; + } + if (! $charset) + $charset = phpQuery::$defaultCharset; + // HTTP 1.1 says that the default charset is ISO-8859-1 + // @see http://www.w3.org/International/O-HTTP-charset + if (! $documentCharset) { + $documentCharset = 'ISO-8859-1'; + $addDocumentCharset = true; + } + // Should be careful here, still need 'magic encoding detection' since lots of pages have other 'default encoding' + // Worse, some pages can have mixed encodings... we'll try not to worry about that + $requestedCharset = strtoupper($requestedCharset); + $documentCharset = strtoupper($documentCharset); + phpQuery::debug("DOC: $documentCharset REQ: $requestedCharset"); + if ($requestedCharset && $documentCharset && $requestedCharset !== $documentCharset) { + phpQuery::debug("CHARSET CONVERT"); + // Document Encoding Conversion + // http://code.google.com/p/phpquery/issues/detail?id=86 + if (function_exists('mb_detect_encoding')) { + $possibleCharsets = array($documentCharset, $requestedCharset, 'AUTO'); + $docEncoding = mb_detect_encoding($markup, implode(', ', $possibleCharsets)); + if (! $docEncoding) + $docEncoding = $documentCharset; // ok trust the document + phpQuery::debug("DETECTED '$docEncoding'"); + // Detected does not match what document says... + if ($docEncoding !== $documentCharset) { + // Tricky.. + } + if ($docEncoding !== $requestedCharset) { + phpQuery::debug("CONVERT $docEncoding => $requestedCharset"); + $markup = mb_convert_encoding($markup, $requestedCharset, $docEncoding); + $markup = $this->charsetAppendToHTML($markup, $requestedCharset); + $charset = $requestedCharset; + } + } else { + phpQuery::debug("TODO: charset conversion without mbstring..."); + } + } + $return = false; + if ($this->isDocumentFragment) { + phpQuery::debug("Full markup load (HTML), DocumentFragment detected, using charset '$charset'"); + $return = $this->documentFragmentLoadMarkup($this, $charset, $markup); + } else { + if ($addDocumentCharset) { + phpQuery::debug("Full markup load (HTML), appending charset: '$charset'"); + $markup = $this->charsetAppendToHTML($markup, $charset); + } + phpQuery::debug("Full markup load (HTML), documentCreate('$charset')"); + $this->documentCreate($charset); + $return = phpQuery::$debug === 2 + ? $this->document->loadHTML($markup) + : @$this->document->loadHTML($markup); + if ($return) + $this->root = $this->document; + } + if ($return && ! $this->contentType) + $this->contentType = 'text/html'; + return $return; + } + protected function loadMarkupXML($markup, $requestedCharset = null) { + if (phpQuery::$debug) + phpQuery::debug('Full markup load (XML): '.substr($markup, 0, 250)); + $this->loadMarkupReset(); + $this->isXML = true; + // check agains XHTML in contentType or markup + $isContentTypeXHTML = $this->isXHTML(); + $isMarkupXHTML = $this->isXHTML($markup); + if ($isContentTypeXHTML || $isMarkupXHTML) { + self::debug('Full markup load (XML), XHTML detected'); + $this->isXHTML = true; + } + // determine document fragment + if (! isset($this->isDocumentFragment)) + $this->isDocumentFragment = $this->isXHTML + ? self::isDocumentFragmentXHTML($markup) + : self::isDocumentFragmentXML($markup); + // this charset will be used + $charset = null; + // charset from XML declaration @var string + $documentCharset = $this->charsetFromXML($markup); + if (! $documentCharset) { + if ($this->isXHTML) { + // this is XHTML, try to get charset from content-type meta header + $documentCharset = $this->charsetFromHTML($markup); + if ($documentCharset) { + phpQuery::debug("Full markup load (XML), appending XHTML charset '$documentCharset'"); + $this->charsetAppendToXML($markup, $documentCharset); + $charset = $documentCharset; + } + } + if (! $documentCharset) { + // if still no document charset... + $charset = $requestedCharset; + } + } else if ($requestedCharset) { + $charset = $requestedCharset; + } + if (! $charset) { + $charset = phpQuery::$defaultCharset; + } + if ($requestedCharset && $documentCharset && $requestedCharset != $documentCharset) { + // TODO place for charset conversion +// $charset = $requestedCharset; + } + $return = false; + if ($this->isDocumentFragment) { + phpQuery::debug("Full markup load (XML), DocumentFragment detected, using charset '$charset'"); + $return = $this->documentFragmentLoadMarkup($this, $charset, $markup); + } else { + // FIXME ??? + if ($isContentTypeXHTML && ! $isMarkupXHTML) + if (! $documentCharset) { + phpQuery::debug("Full markup load (XML), appending charset '$charset'"); + $markup = $this->charsetAppendToXML($markup, $charset); + } + // see http://pl2.php.net/manual/en/book.dom.php#78929 + // LIBXML_DTDLOAD (>= PHP 5.1) + // does XML ctalogues works with LIBXML_NONET + // $this->document->resolveExternals = true; + // TODO test LIBXML_COMPACT for performance improvement + // create document + $this->documentCreate($charset); + if (phpversion() < 5.1) { + $this->document->resolveExternals = true; + $return = phpQuery::$debug === 2 + ? $this->document->loadXML($markup) + : @$this->document->loadXML($markup); + } else { + /** @link http://pl2.php.net/manual/en/libxml.constants.php */ + $libxmlStatic = phpQuery::$debug === 2 + ? LIBXML_DTDLOAD|LIBXML_DTDATTR|LIBXML_NONET + : LIBXML_DTDLOAD|LIBXML_DTDATTR|LIBXML_NONET|LIBXML_NOWARNING|LIBXML_NOERROR; + $return = $this->document->loadXML($markup, $libxmlStatic); +// if (! $return) +// $return = $this->document->loadHTML($markup); + } + if ($return) + $this->root = $this->document; + } + if ($return) { + if (! $this->contentType) { + if ($this->isXHTML) + $this->contentType = 'application/xhtml+xml'; + else + $this->contentType = 'text/xml'; + } + return $return; + } else { + throw new Exception("Error loading XML markup"); + } + } + protected function isXHTML($markup = null) { + if (! isset($markup)) { + return strpos($this->contentType, 'xhtml') !== false; + } + // XXX ok ? + return strpos($markup, "doctype) && is_object($dom->doctype) +// ? $dom->doctype->publicId +// : self::$defaultDoctype; + } + protected function isXML($markup) { +// return strpos($markup, ']+http-equiv\\s*=\\s*(["|\'])Content-Type\\1([^>]+?)>@i', + $markup, $matches + ); + if (! isset($matches[0])) + return array(null, null); + // get attr 'content' + preg_match('@content\\s*=\\s*(["|\'])(.+?)\\1@', $matches[0], $matches); + if (! isset($matches[0])) + return array(null, null); + return $this->contentTypeToArray($matches[2]); + } + protected function charsetFromHTML($markup) { + $contentType = $this->contentTypeFromHTML($markup); + return $contentType[1]; + } + protected function charsetFromXML($markup) { + $matches; + // find declaration + preg_match('@<'.'?xml[^>]+encoding\\s*=\\s*(["|\'])(.*?)\\1@i', + $markup, $matches + ); + return isset($matches[2]) + ? strtolower($matches[2]) + : null; + } + /** + * Repositions meta[type=charset] at the start of head. Bypasses DOMDocument bug. + * + * @link http://code.google.com/p/phpquery/issues/detail?id=80 + * @param $html + */ + protected function charsetFixHTML($markup) { + $matches = array(); + // find meta tag + preg_match('@\s*]+http-equiv\\s*=\\s*(["|\'])Content-Type\\1([^>]+?)>@i', + $markup, $matches, PREG_OFFSET_CAPTURE + ); + if (! isset($matches[0])) + return; + $metaContentType = $matches[0][0]; + $markup = substr($markup, 0, $matches[0][1]) + .substr($markup, $matches[0][1]+strlen($metaContentType)); + $headStart = stripos($markup, ''); + $markup = substr($markup, 0, $headStart+6).$metaContentType + .substr($markup, $headStart+6); + return $markup; + } + protected function charsetAppendToHTML($html, $charset, $xhtml = false) { + // remove existing meta[type=content-type] + $html = preg_replace('@\s*]+http-equiv\\s*=\\s*(["|\'])Content-Type\\1([^>]+?)>@i', '', $html); + $meta = ''; + if (strpos($html, ')@s', + "{$meta}", + $html + ); + } + } else { + return preg_replace( + '@)@s', + ''.$meta, + $html + ); + } + } + protected function charsetAppendToXML($markup, $charset) { + $declaration = '<'.'?xml version="1.0" encoding="'.$charset.'"?'.'>'; + return $declaration.$markup; + } + public static function isDocumentFragmentHTML($markup) { + return stripos($markup, 'documentFragmentCreate($node, $sourceCharset); +// if ($fake === false) +// throw new Exception("Error loading documentFragment markup"); +// else +// $return = array_merge($return, +// $this->import($fake->root->childNodes) +// ); +// } else { +// $return[] = $this->document->importNode($node, true); +// } +// } +// return $return; +// } else { +// // string markup +// $fake = $this->documentFragmentCreate($source, $sourceCharset); +// if ($fake === false) +// throw new Exception("Error loading documentFragment markup"); +// else +// return $this->import($fake->root->childNodes); +// } + if (is_array($source) || $source instanceof DOMNODELIST) { + // dom nodes + self::debug('Importing nodes to document'); + foreach($source as $node) + $return[] = $this->document->importNode($node, true); + } else { + // string markup + $fake = $this->documentFragmentCreate($source, $sourceCharset); + if ($fake === false) + throw new Exception("Error loading documentFragment markup"); + else + return $this->import($fake->root->childNodes); + } + return $return; + } + /** + * Creates new document fragment. + * + * @param $source + * @return DOMDocumentWrapper + */ + protected function documentFragmentCreate($source, $charset = null) { + $fake = new DOMDocumentWrapper(); + $fake->contentType = $this->contentType; + $fake->isXML = $this->isXML; + $fake->isHTML = $this->isHTML; + $fake->isXHTML = $this->isXHTML; + $fake->root = $fake->document; + if (! $charset) + $charset = $this->charset; +// $fake->documentCreate($this->charset); + if ($source instanceof DOMNODE && !($source instanceof DOMNODELIST)) + $source = array($source); + if (is_array($source) || $source instanceof DOMNODELIST) { + // dom nodes + // load fake document + if (! $this->documentFragmentLoadMarkup($fake, $charset)) + return false; + $nodes = $fake->import($source); + foreach($nodes as $node) + $fake->root->appendChild($node); + } else { + // string markup + $this->documentFragmentLoadMarkup($fake, $charset, $source); + } + return $fake; + } + /** + * + * @param $document DOMDocumentWrapper + * @param $markup + * @return $document + */ + private function documentFragmentLoadMarkup($fragment, $charset, $markup = null) { + // TODO error handling + // TODO copy doctype + // tempolary turn off + $fragment->isDocumentFragment = false; + if ($fragment->isXML) { + if ($fragment->isXHTML) { + // add FAKE element to set default namespace + $fragment->loadMarkupXML('' + .'' + .''.$markup.''); + $fragment->root = $fragment->document->firstChild->nextSibling; + } else { + $fragment->loadMarkupXML(''.$markup.''); + $fragment->root = $fragment->document->firstChild; + } + } else { + $markup2 = phpQuery::$defaultDoctype.''; + $noBody = strpos($markup, 'loadMarkupHTML($markup2); + // TODO resolv body tag merging issue + $fragment->root = $noBody + ? $fragment->document->firstChild->nextSibling->firstChild->nextSibling + : $fragment->document->firstChild->nextSibling->firstChild->nextSibling; + } + if (! $fragment->root) + return false; + $fragment->isDocumentFragment = true; + return true; + } + protected function documentFragmentToMarkup($fragment) { + phpQuery::debug('documentFragmentToMarkup'); + $tmp = $fragment->isDocumentFragment; + $fragment->isDocumentFragment = false; + $markup = $fragment->markup(); + if ($fragment->isXML) { + $markup = substr($markup, 0, strrpos($markup, '')); + if ($fragment->isXHTML) { + $markup = substr($markup, strpos($markup, '')+6); + } + } else { + $markup = substr($markup, strpos($markup, '')+6); + $markup = substr($markup, 0, strrpos($markup, '')); + } + $fragment->isDocumentFragment = $tmp; + if (phpQuery::$debug) + phpQuery::debug('documentFragmentToMarkup: '.substr($markup, 0, 150)); + return $markup; + } + /** + * Return document markup, starting with optional $nodes as root. + * + * @param $nodes DOMNode|DOMNodeList + * @return string + */ + public function markup($nodes = null, $innerMarkup = false) { + if (isset($nodes) && count($nodes) == 1 && $nodes[0] instanceof DOMDOCUMENT) + $nodes = null; + if (isset($nodes)) { + $markup = ''; + if (!is_array($nodes) && !($nodes instanceof DOMNODELIST) ) + $nodes = array($nodes); + if ($this->isDocumentFragment && ! $innerMarkup) + foreach($nodes as $i => $node) + if ($node->isSameNode($this->root)) { + // var_dump($node); + $nodes = array_slice($nodes, 0, $i) + + phpQuery::DOMNodeListToArray($node->childNodes) + + array_slice($nodes, $i+1); + } + if ($this->isXML && ! $innerMarkup) { + self::debug("Getting outerXML with charset '{$this->charset}'"); + // we need outerXML, so we can benefit from + // $node param support in saveXML() + foreach($nodes as $node) + $markup .= $this->document->saveXML($node); + } else { + $loop = array(); + if ($innerMarkup) + foreach($nodes as $node) { + if ($node->childNodes) + foreach($node->childNodes as $child) + $loop[] = $child; + else + $loop[] = $node; + } + else + $loop = $nodes; + self::debug("Getting markup, moving selected nodes (".count($loop).") to new DocumentFragment"); + $fake = $this->documentFragmentCreate($loop); + $markup = $this->documentFragmentToMarkup($fake); + } + if ($this->isXHTML) { + self::debug("Fixing XHTML"); + $markup = self::markupFixXHTML($markup); + } + self::debug("Markup: ".substr($markup, 0, 250)); + return $markup; + } else { + if ($this->isDocumentFragment) { + // documentFragment, html only... + self::debug("Getting markup, DocumentFragment detected"); +// return $this->markup( +//// $this->document->getElementsByTagName('body')->item(0) +// $this->document->root, true +// ); + $markup = $this->documentFragmentToMarkup($this); + // no need for markupFixXHTML, as it's done thought markup($nodes) method + return $markup; + } else { + self::debug("Getting markup (".($this->isXML?'XML':'HTML')."), final with charset '{$this->charset}'"); + $markup = $this->isXML + ? $this->document->saveXML() + : $this->document->saveHTML(); + if ($this->isXHTML) { + self::debug("Fixing XHTML"); + $markup = self::markupFixXHTML($markup); + } + self::debug("Markup: ".substr($markup, 0, 250)); + return $markup; + } + } + } + protected static function markupFixXHTML($markup) { + $markup = self::expandEmptyTag('script', $markup); + $markup = self::expandEmptyTag('select', $markup); + $markup = self::expandEmptyTag('textarea', $markup); + return $markup; + } + public static function debug($text) { + phpQuery::debug($text); + } + /** + * expandEmptyTag + * + * @param $tag + * @param $xml + * @return unknown_type + * @author mjaque at ilkebenson dot com + * @link http://php.net/manual/en/domdocument.savehtml.php#81256 + */ + public static function expandEmptyTag($tag, $xml){ + $indice = 0; + while ($indice< strlen($xml)){ + $pos = strpos($xml, "<$tag ", $indice); + if ($pos){ + $posCierre = strpos($xml, ">", $pos); + if ($xml[$posCierre-1] == "/"){ + $xml = substr_replace($xml, ">", $posCierre-1, 2); + } + $indice = $posCierre; + } + else break; + } + return $xml; + } +} + +/** + * Event handling class. + * + * @author Tobiasz Cudnik + * @package phpQuery + * @static + */ +abstract class phpQueryEvents { + /** + * Trigger a type of event on every matched element. + * + * @param DOMNode|phpQueryObject|string $document + * @param unknown_type $type + * @param unknown_type $data + * + * @TODO exclusive events (with !) + * @TODO global events (test) + * @TODO support more than event in $type (space-separated) + */ + public static function trigger($document, $type, $data = array(), $node = null) { + // trigger: function(type, data, elem, donative, extra) { + $documentID = phpQuery::getDocumentID($document); + $namespace = null; + if (strpos($type, '.') !== false) + list($name, $namespace) = explode('.', $type); + else + $name = $type; + if (! $node) { + if (self::issetGlobal($documentID, $type)) { + $pq = phpQuery::getDocument($documentID); + // TODO check add($pq->document) + $pq->find('*')->add($pq->document) + ->trigger($type, $data); + } + } else { + if (isset($data[0]) && $data[0] instanceof DOMEvent) { + $event = $data[0]; + $event->relatedTarget = $event->target; + $event->target = $node; + $data = array_slice($data, 1); + } else { + $event = new DOMEvent(array( + 'type' => $type, + 'target' => $node, + 'timeStamp' => time(), + )); + } + $i = 0; + while($node) { + // TODO whois + phpQuery::debug("Triggering ".($i?"bubbled ":'')."event '{$type}' on " + ."node \n");//.phpQueryObject::whois($node)."\n"); + $event->currentTarget = $node; + $eventNode = self::getNode($documentID, $node); + if (isset($eventNode->eventHandlers)) { + foreach($eventNode->eventHandlers as $eventType => $handlers) { + $eventNamespace = null; + if (strpos($type, '.') !== false) + list($eventName, $eventNamespace) = explode('.', $eventType); + else + $eventName = $eventType; + if ($name != $eventName) + continue; + if ($namespace && $eventNamespace && $namespace != $eventNamespace) + continue; + foreach($handlers as $handler) { + phpQuery::debug("Calling event handler\n"); + $event->data = $handler['data'] + ? $handler['data'] + : null; + $params = array_merge(array($event), $data); + $return = phpQuery::callbackRun($handler['callback'], $params); + if ($return === false) { + $event->bubbles = false; + } + } + } + } + // to bubble or not to bubble... + if (! $event->bubbles) + break; + $node = $node->parentNode; + $i++; + } + } + } + /** + * Binds a handler to one or more events (like click) for each matched element. + * Can also bind custom events. + * + * @param DOMNode|phpQueryObject|string $document + * @param unknown_type $type + * @param unknown_type $data Optional + * @param unknown_type $callback + * + * @TODO support '!' (exclusive) events + * @TODO support more than event in $type (space-separated) + * @TODO support binding to global events + */ + public static function add($document, $node, $type, $data, $callback = null) { + phpQuery::debug("Binding '$type' event"); + $documentID = phpQuery::getDocumentID($document); +// if (is_null($callback) && is_callable($data)) { +// $callback = $data; +// $data = null; +// } + $eventNode = self::getNode($documentID, $node); + if (! $eventNode) + $eventNode = self::setNode($documentID, $node); + if (!isset($eventNode->eventHandlers[$type])) + $eventNode->eventHandlers[$type] = array(); + $eventNode->eventHandlers[$type][] = array( + 'callback' => $callback, + 'data' => $data, + ); + } + /** + * Enter description here... + * + * @param DOMNode|phpQueryObject|string $document + * @param unknown_type $type + * @param unknown_type $callback + * + * @TODO namespace events + * @TODO support more than event in $type (space-separated) + */ + public static function remove($document, $node, $type = null, $callback = null) { + $documentID = phpQuery::getDocumentID($document); + $eventNode = self::getNode($documentID, $node); + if (is_object($eventNode) && isset($eventNode->eventHandlers[$type])) { + if ($callback) { + foreach($eventNode->eventHandlers[$type] as $k => $handler) + if ($handler['callback'] == $callback) + unset($eventNode->eventHandlers[$type][$k]); + } else { + unset($eventNode->eventHandlers[$type]); + } + } + } + protected static function getNode($documentID, $node) { + foreach(phpQuery::$documents[$documentID]->eventsNodes as $eventNode) { + if ($node->isSameNode($eventNode)) + return $eventNode; + } + } + protected static function setNode($documentID, $node) { + phpQuery::$documents[$documentID]->eventsNodes[] = $node; + return phpQuery::$documents[$documentID]->eventsNodes[ + count(phpQuery::$documents[$documentID]->eventsNodes)-1 + ]; + } + protected static function issetGlobal($documentID, $type) { + return isset(phpQuery::$documents[$documentID]) + ? in_array($type, phpQuery::$documents[$documentID]->eventsGlobal) + : false; + } +} + + +interface ICallbackNamed { + function hasName(); + function getName(); +} +/** + * Callback class introduces currying-like pattern. + * + * Example: + * function foo($param1, $param2, $param3) { + * var_dump($param1, $param2, $param3); + * } + * $fooCurried = new Callback('foo', + * 'param1 is now statically set', + * new CallbackParam, new CallbackParam + * ); + * phpQuery::callbackRun($fooCurried, + * array('param2 value', 'param3 value' + * ); + * + * Callback class is supported in all phpQ