diff --git a/ActividadesWP/v5/galerias/index.php b/ActividadesWP/v5/galerias/index.php new file mode 100644 index 0000000..aa106bd --- /dev/null +++ b/ActividadesWP/v5/galerias/index.php @@ -0,0 +1,150 @@ +getConnection(); + + $galeria = new Galeria($db); + + $stmt = $galeria->gallery_images($id); + + $num = $stmt->rowCount(); + + if($num>0){ + while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){ + extract($row); + + if($imagenes){ + $ilist = unserialize($imagenes); + foreach($ilist as $i){ + array_push($image_ids,$i); + } + } + if($sin_recortar){ + $slist = unserialize($sin_recortar); + foreach($slist as $i){ + array_push($image_ids,$i); + } + } + + } + } + + //Get all images from image_ids array + foreach($image_ids as $image){ + $stmt = $galeria->image($image); + $num = $stmt->rowCount(); + if($num>0){ + while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){ + extract($row); + array_push($images,unserialize($imagedata)); + } + } + } + + $data = array( + 'count' => count($images), + 'result' => array ( + 'images' => $images + ) + ); + + send_response( $data ); + } + + function gallery_list(){ + $database = new Database(); + $db = $database->getConnection(); + + $galeria = new Galeria($db); + + $stmt = $galeria->gallery_list(); + + $num = $stmt->rowCount(); + + if($num>0){ + $galleries_arr=array(); + + while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){ + extract($row); + + $response_item=array( + "title" => $post_title, + "id" => $ID, + "date" => $post_date, + "thumbnail" => $thumbnail + ); + + array_push($galleries_arr, $response_item); + } + } + + $data = array( + 'count' => count($galleries_arr), + 'result' => array ( + 'galleries' => $galleries_arr + ) + ); + + send_response( $data ); + + } + + function send_response( $data ){ + // set response code - 200 OK + header('Content-Type: application/json; charset=utf-8'); + + http_response_code(200); + + echo json_encode( + $data, JSON_UNESCAPED_UNICODE + ); + } \ No newline at end of file diff --git a/ActividadesWP/v5/inc/actividad.php b/ActividadesWP/v5/inc/actividad.php new file mode 100644 index 0000000..127cdaa --- /dev/null +++ b/ActividadesWP/v5/inc/actividad.php @@ -0,0 +1,649 @@ +conn = $db; + } + + /** + * Helper function to get all blogs and their languages + */ + function get_blog_by_locale($locale){ + $r = ''; + switch($locale){ + case "fr_FR": + case "fr": + $r = "wp_4_"; + break; + case "en": + case "en_US": + $r = "wp_2_"; + break; + case "pt": + case "pt-br": + case "pt_br": + case "pt_BR": + $r = "wp_3_"; + break; + case "es": + case "es_ES": + default: + $r = "wp_"; + break; + } + return $r; + } + + function translation_slug( $locale, $id ){ + $sql = "SELECT + P.post_name as slug + FROM wp_posts P + WHERE P.ID = $id"; + return $this->execute_sql( $sql ); + } + + + function translation_list( $year, $month, $last_update, $text, $locale, $termid="ultimas", $all=false, $history=false, $limit=16 ){ //Default last updated + //Check locale and change accordingly to the right DB prefix for that locale + $sql = "SELECT + P.ID, + (SELECT + tt2.description AS translationmeta + FROM wp_posts P2 + LEFT JOIN wp_term_relationships tr ON tr.object_id = P2.ID + LEFT JOIN wp_term_relationships tr2 ON tr2.object_id = P2.ID + LEFT JOIN wp_term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id AND tt.taxonomy = 'language' + INNER JOIN wp_term_taxonomy tt2 ON tr2.term_taxonomy_id = tt2.term_taxonomy_id AND tt2.taxonomy = 'post_translations' + LEFT JOIN wp_terms t ON t.term_id = tr.term_taxonomy_id + WHERE P2.ID=P.ID AND t.slug = '$locale') AS translationmeta, + P.post_title AS title, + P.post_date AS date, + P.post_modified AS modified, + P.post_name AS slug, + WEEKDAY(P.post_date) AS dia, + PMM.meta_value AS mensaje_id, + PMA.meta_value AS mensaje_json + FROM wp_posts P + LEFT JOIN wp_postmeta PMA ON PMA.post_id = P.ID AND PMA.meta_key = 'mensaje_json' + LEFT JOIN wp_postmeta PMM ON PMM.post_id = P.ID AND PMM.meta_key = 'mensaje' + INNER JOIN wp_terms T ON T.slug = '$locale' + INNER JOIN wp_term_relationships TR ON TR.object_id = P.ID AND TR.term_taxonomy_id = T.term_id + WHERE P.post_status = 'publish' + AND P.post_type = 'actividades'"; + if($history){ + $sql .= " + AND PMM.meta_value IS NOT NULL + AND PMM.meta_value != '' + AND PMA.meta_value IS NOT NULL + AND PMA.meta_value != ''"; + } + + if($year!=''){ + $sql .= " AND YEAR(P.post_date) = '$year'"; + if($month!=''){ + $sql .= " AND MONTH(P.post_date) = '$month'"; + } + if($last_update!=''){ + $sql .= " AND UNIX_TIMESTAMP(P.post_modified) > ". $last_update; + } + $sql .= " ORDER BY P.post_date DESC"; + } else { + $sql .= " ORDER BY P.post_date DESC"; + if(!$all){ +if(!$limit){ + $sql .= " LIMIT 16"; +} else { +$sql .= " LIMIT " . $limit; +} + } + } + return $this->execute_sql( $sql ); + } + + function activity_meta($id){ + $sql = "SELECT +PML.meta_value AS lugar, + PMC.meta_value AS city, + PMS.meta_value AS state, + PMCO.meta_value AS country, + PMT2.meta_value AS thumbnail, + PMN.meta_value AS numero_de_estudio_biblico, + PMA.meta_value AS actividad, + PMG.meta_value AS gallery, + PMY.meta_value AS youtube, + #PMU.meta_value AS url_del_mensaje, + PMI.meta_value AS mensaje, + PMJ.meta_value AS mensaje_json, + PMR.meta_value AS 'related_content', + PMRC.meta_value AS 'related_content_count', + PMCK.meta_value AS 'revisado' + FROM wp_posts P +LEFT JOIN wp_postmeta PML ON P.ID = PML.post_id AND PML.meta_key = 'lugar' + LEFT JOIN wp_postmeta PMC ON P.ID = PMC.post_id AND PMC.meta_key = 'city' + LEFT JOIN wp_postmeta PMS ON P.ID = PMS.post_id AND PMS.meta_key = 'state' + LEFT JOIN wp_postmeta PMCO ON P.ID = PMCO.post_id AND PMCO.meta_key = 'country' + LEFT JOIN wp_postmeta PMA ON P.ID = PMA.post_id AND PMA.meta_key = 'actividad' + LEFT JOIN wp_postmeta PMN ON P.ID = PMN.post_id AND PMN.meta_key = 'numero_de_estudio_biblico' + LEFT JOIN wp_postmeta PMG ON P.ID = PMG.post_id AND PMG.meta_key = 'gallery' + LEFT JOIN wp_postmeta PMY ON P.ID = PMY.post_id AND PMY.meta_key = 'youtube' + #LEFT JOIN wp_postmeta PMU ON P.ID = PMU.post_id AND PMU.meta_key = 'url_del_mensaje' + LEFT JOIN wp_postmeta PMI ON P.ID = PMI.post_id AND PMI.meta_key = 'mensaje' + LEFT JOIN wp_postmeta PMJ ON P.ID = PMJ.post_id AND PMJ.meta_key = 'mensaje_json' + LEFT JOIN wp_postmeta PMT ON P.ID = PMT.post_id AND PMT.meta_key = '_thumbnail_id' + LEFT JOIN wp_postmeta PMT2 ON PMT.meta_value = PMT2.post_id AND PMT2.meta_key = '_wp_attached_file' + LEFT JOIN wp_postmeta PMR ON P.ID = PMR.post_id AND PMR.meta_key = 'usar_contenido_relacionado' + LEFT JOIN wp_postmeta PMRC ON P.ID = PMRC.post_id AND PMRC.meta_key = 'contenido_relacionado' + LEFT JOIN wp_postmeta PMCK ON P.ID = PMCK.post_id AND PMCK.meta_key = 'revisado' + WHERE P.post_type = 'actividades' + AND P.post_status = 'publish' + AND P.ID = ".$id; + $data = $this->execute_sql( $sql ); + $response = $data->fetch(PDO::FETCH_ASSOC); + return $response; + } + + /** + * List function + * + * Displays the list of messages with it's pertinent variables + * + */ + function activities_list( $year, $month, $last_update, $text, $locale ){ + $sql = "SELECT + P.ID, + (SELECT + tt2.description AS translationmeta + FROM wp_posts P2 + LEFT JOIN wp_term_relationships tr ON tr.object_id = P2.ID + LEFT JOIN wp_term_relationships tr2 ON tr2.object_id = P2.ID + LEFT JOIN wp_term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id AND tt.taxonomy = 'language' + INNER JOIN wp_term_taxonomy tt2 ON tr2.term_taxonomy_id = tt2.term_taxonomy_id AND tt2.taxonomy = 'post_translations' + LEFT JOIN wp_terms t ON t.term_id = tr.term_taxonomy_id + WHERE P2.ID='$id' AND t.slug = '$locale') AS translationmeta, + P.post_title AS title, + P.post_date AS creation_date, + P.post_modified as last_updated,"; + if($text){ + $sql .= "P.post_content as content,"; + } + $sql .= "LENGTH(P.post_content) as bodylength, + IFNULL(NULLIF(TIME_TO_SEC(MD.duration), '' ), 0) AS duration, + MD.date, + MD.activity AS no_activity, + MD.city, + MD.country, + MD.state, + PMA.meta_value AS thumbnail, + PMAS.meta_value AS meta, + #O.option_value AS translationmeta, + P.post_name as slug + FROM wp_posts P + LEFT JOIN wp_messagedata MD ON P.id = MD.post_id + LEFT JOIN wp_postmeta PM ON PM.post_id = P.ID AND PM.meta_key = '_thumbnail_id' + LEFT JOIN wp_postmeta PMA ON PM.meta_value = PMA.post_id AND PMA.meta_key = '_wp_attached_file' + LEFT JOIN wp_postmeta PMAS ON PM.meta_value = PMAS.post_id AND PMAS.meta_key = '_wp_attachment_metadata' + #LEFT JOIN wp_options O ON O.option_name = CONCAT('msls_',P.ID) + WHERE P.post_type = 'actividades' + AND P.post_status = 'publish'"; + if($year!=''){ + $sql .= " AND YEAR(MD.date) = '$year'"; + } + if($month!=''){ + $sql .= " AND MONTH(MD.date) = '$month'"; + } + if($last_update!=''){ + $sql .= " AND UNIX_TIMESTAMP(P.post_modified) > ". $last_update; + } + $sql .= " ORDER BY P.post_date DESC"; + return $this->execute_sql( $sql ); + } + + /** + * Summary function + */ + function summary($id,$locale){ + + $sql = "SELECT + P.ID, + P.post_title AS title, + P.post_date AS creation_date, + P.post_name AS slug, + P.post_modified AS last_updated, + PMA.meta_value AS activity, + PML.meta_value AS lugar, + PMC.meta_value AS city, + PMS.meta_value AS state, + PMCO.meta_value AS country, + PMN.meta_value AS bible_study + FROM wp_posts P + LEFT JOIN wp_postmeta PMA ON PMA.post_id = P.ID AND PMA.meta_key = 'actividad' + LEFT JOIN wp_postmeta PML ON PML.post_id = P.ID AND PML.meta_key = 'lugar' + LEFT JOIN wp_postmeta PMC ON PMC.post_id = P.ID AND PMC.meta_key = 'city' + LEFT JOIN wp_postmeta PMS ON PMS.post_id = P.ID AND PMS.meta_key = 'state' + LEFT JOIN wp_postmeta PMCO ON PMCO.post_id = P.ID AND PMCO.meta_key = 'country' + LEFT JOIN wp_postmeta PMN ON PMN.post_id = P.ID AND PMN.meta_key = 'numero_de_estudio_biblico' + LEFT JOIN wp_postmeta PMPID ON PMPID.meta_key = 'mensaje' AND PMPID.meta_value = $id + WHERE P.ID = PMPID.post_id + AND P.post_status = 'publish' + AND P.post_type = 'actividades'"; + return $this->execute_sql( $sql ); + } + + + /** + * Detail function + * + * Given an ID returns the message with all details + * + * @param id Int id of the message whose details want to be found. + */ + function detail($id,$locale){ + + $sql = "SELECT + P.ID, + (SELECT + tt2.description AS translationmeta + FROM wp_posts P2 + LEFT JOIN wp_term_relationships tr ON tr.object_id = P2.ID + LEFT JOIN wp_term_relationships tr2 ON tr2.object_id = P2.ID + LEFT JOIN wp_term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id AND tt.taxonomy = 'language' + INNER JOIN wp_term_taxonomy tt2 ON tr2.term_taxonomy_id = tt2.term_taxonomy_id AND tt2.taxonomy = 'post_translations' + LEFT JOIN wp_terms t ON t.term_id = tr.term_taxonomy_id + WHERE P2.ID='$id' AND t.slug = '$locale') AS translationmeta, + P.post_title AS title, + P.post_content AS content, + P.post_date AS creation_date, + PMA.meta_value AS mensaje, + P.post_name AS slug, + P.post_modified AS last_updated + FROM wp_posts P + LEFT JOIN wp_postmeta PMA ON PMA.post_id = P.ID AND PMA.meta_key = 'mensaje' + WHERE P.ID = '$id' LIMIT 1"; + return $this->execute_sql( $sql ); + } + + /** + * Slug function + * + * Given a slug, returns the message with all details + * + * @param slug String Slug of the message whose details want to be found + */ + function detailBySlug($slug,$locale){ + //Check locale and change accordingly to the right DB prefix for that locale + $prefix = $this->get_blog_by_locale( $locale ); + + $sql = "SELECT + P.ID, + (SELECT + tt2.description AS translationmeta + FROM wp_posts P2 + LEFT JOIN wp_term_relationships tr ON tr.object_id = P2.ID + LEFT JOIN wp_term_relationships tr2 ON tr2.object_id = P2.ID + LEFT JOIN wp_term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id AND tt.taxonomy = 'language' + INNER JOIN wp_term_taxonomy tt2 ON tr2.term_taxonomy_id = tt2.term_taxonomy_id AND tt2.taxonomy = 'post_translations' + LEFT JOIN wp_terms t ON t.term_id = tr.term_taxonomy_id + WHERE P2.post_name='$slug' AND t.slug = '$locale') AS translationmeta, + P.post_title AS title, + P.post_content AS content, + P.post_date AS creation_date, + P.post_name AS slug, + PMA.meta_value AS mensaje, + P.post_modified AS last_updated + FROM wp_posts P + LEFT JOIN wp_postmeta PMA ON PMA.post_id = P.ID AND PMA.meta_key = 'mensaje' + WHERE P.post_name='$slug'"; + return $this->execute_sql( $sql ); + } + + /** + * Last update function + * + * Returns the last updated imtestamp for the message passed in via the @id + * + * @param id Int id for whom the last update should be found + */ + function last_update($id){ + $sql = "SELECT + P.post_modified AS last_updated + FROM wp_posts P + WHERE P.ID = '$id'"; + return $this->execute_sql( $sql ); + } + + /** + * Execute SQL function + * + * Executes a generic SQL statement and passes back the result. + * + * @param string sql SQl statement to be executed + * @return + */ + function execute_sql( $sql ){ + $stmt = $this->conn->prepare($sql); + $stmt->execute(); + return $stmt; + } + + /** + * Relevant conferences function + * + * Get all relevant conferences and return + */ + function relevant_conferences(){ + $sql = "SELECT + option_value + FROM wp_options + where option_name = 'options_conference'"; + return $this->execute_sql( $sql ); + } + + function get_post_source($trid){ + $sql = "SELECT + T.element_id AS post_id + FROM wp_icl_translations AS T + WHERE T.trid = '$trid' + AND T.language_code = 'es'"; + return $this->execute_sql( $sql ); + } + + function get_post_interventions($id){ + $sql = "SELECT + PM.meta_value + FROM wp_postmeta AS PM + WHERE PM.post_id = '$id' + AND PM.meta_key = 'intervenciones'"; + return $this->execute_sql( $sql ); + } + + function get_interventions($id,$count){ + $interventions = []; + + for($i=0;$i<$count;$i++){ + $sql = "SELECT + PMT.meta_value AS titulo, + PMF.meta_value AS fecha, + PML.meta_value AS lugar, + PMA.meta_value AS autor, + PMC.meta_value AS texto + FROM wp_postmeta AS PMT + LEFT JOIN wp_postmeta AS PMF ON PMF.post_id = '$id' AND PMF.meta_key = 'intervenciones_".$i."_fecha' + LEFT JOIN wp_postmeta AS PML ON PML.post_id = '$id' AND PML.meta_key = 'intervenciones_".$i."_lugar' + LEFT JOIN wp_postmeta AS PMA ON PMA.post_id = '$id' AND PMA.meta_key = 'intervenciones_".$i."_autor' + LEFT JOIN wp_postmeta AS PMC ON PMC.post_id = '$id' AND PMC.meta_key = 'intervenciones_".$i."_texto' + WHERE PMT.post_id = '$id' + AND PMT.meta_key = 'intervenciones_".$i."_titulo' "; + $data = $this->execute_sql( $sql ); + $response = $data->fetch(PDO::FETCH_ASSOC); + //$interventions[$count] = $response; + array_push($interventions,$response); + } + + return $interventions; + } + + function get_related_content($id,$count){ + $related = []; + + for($i=0;$i<$count;$i++){ + $sql = "SELECT + PM.meta_value AS conference_url + FROM wp_postmeta AS PM + WHERE PM.post_id = '$id' + AND PM.meta_key = 'contenido_relacionado_".$i."_conference_url'"; + $data = $this->execute_sql( $sql ); + $response = $data->fetch(PDO::FETCH_ASSOC); + array_push($related,$response); + } + + return $related; + } + + function get_post_language($id){ + $sql = "SELECT + T.language_code, + T.trid + FROM wp_icl_translations AS T + WHERE T.element_id = '$id' + AND T.element_type = 'post_message'"; + return $this->execute_sql( $sql ); + } + + function get_post_metadata($id){ + $sql = "SELECT + IFNULL(NULLIF(TIME_TO_SEC(MD.duration), '' ), 0) AS duration, + MD.country, + MD.state, + MD.city AS city, + MD.activity AS no_activity + FROM wp_messagedata AS MD + WHERE post_id = '$id'"; + return $this->execute_sql( $sql ); + } + + function get_activity_files($id){ + $sql = "SELECT + PMAR.meta_value AS use_files, + PMNV.meta_value AS videos, + PMNA.meta_value AS audios, + PMNT.meta_value AS textos, + PMNE.meta_value AS enlaces + FROM wp_posts P + LEFT JOIN wp_postmeta PMAR ON P.ID = PMAR.post_id AND PMAR.meta_key = 'usar_archivos' + LEFT JOIN wp_postmeta PMNV ON P.ID = PMNV.post_id AND PMNV.meta_key = 'videos' + LEFT JOIN wp_postmeta PMNA ON P.ID = PMNA.post_id AND PMNA.meta_key = 'audios' + LEFT JOIN wp_postmeta PMNT ON P.ID = PMNT.post_id AND PMNT.meta_key = 'textos' + LEFT JOIN wp_postmeta PMNE ON P.ID = PMNE.post_id AND PMNE.meta_key = 'enlaces' + WHERE P.post_type = 'actividades' + AND P.post_status = 'publish' + AND P.ID = ".$id; + return $this->execute_sql( $sql ); + } + + function get_files( $id, $type, $qty ){ + $t = []; + for($x=0;$x<$qty;$x++){ + $fileSql = $this->get_file_sql($id, $type, $x); + $data = $this->execute_sql( $fileSql ); + $response = $data->fetch(PDO::FETCH_ASSOC); + array_push( $t, $response ); + } + return $t; + } + + function get_file_sql( $id, $type, $idx){ + if($type == 'enlaces'){ + $fname = 'enlace'; + } else { + $fname = 'archivo'; + } + $sql = "SELECT + PMAT.meta_value as title, + PMAD.meta_value as description, + PMAF.meta_value as link, + PF.guid AS file + FROM wp_posts P + LEFT JOIN wp_postmeta PMAT ON PMAT.post_id = P.ID AND PMAT.meta_key = '".$type."_".$idx."_titulo' + LEFT JOIN wp_postmeta PMAD ON PMAD.post_id = P.ID AND PMAD.meta_key = '".$type."_".$idx."_descripcion' + LEFT JOIN wp_postmeta PMAF ON PMAF.post_id = P.ID AND PMAF.meta_key = '".$type."_".$idx."_".$fname."' + LEFT JOIN wp_posts PF ON PF.ID = PMAF.meta_value + WHERE P.ID = $id"; + return $sql; + } + + function get_post_file($id,$locale){ + //Check locale and change accordingly to the right DB prefix for that locale + $prefix = $this->get_blog_by_locale( $locale ); + + $sql = "SELECT + P.guid as url + FROM ".$prefix."posts P + WHERE P.ID = '$id'"; + return $this->execute_sql( $sql ); + } + + function title_search($q,$locale){ + //Check locale and change accordingly to the right DB prefix for that locale + $prefix = $this->get_blog_by_locale( $locale ); + + $sql = "SELECT + P.ID, + P.post_title AS title, + P.post_date AS creation_date, + P.post_modified as last_updated, + O.option_value AS translationmeta, + P.post_name as slug + FROM ".$prefix."posts AS P + LEFT JOIN ".$prefix."options O ON O.option_name = CONCAT('msls_',P.ID) + WHERE P.post_type = 'actividades' + AND P.post_status = 'publish' + AND P.post_title LIKE('%$q%')"; + return $this->execute_sql($sql); + + } + + function content_search($q){ + $sql = "SELECT + P.ID, + P.post_title AS title, + P.post_date AS creation_date, + P.post_modified as last_updated, + IFNULL(NULLIF(TIME_TO_SEC(MD.duration), '' ), 0) AS duration, + MD.date, + MD.activity AS no_activity, + MD.city, + MD.country, + MD.state, + PMA.meta_value AS thumbnail, + P.post_name as slug, + MATCH(P.post_content) AGAINST ('$q' IN NATURAL LANGUAGE MODE) as score, + SUBSTRING(P.post_content, LOCATE('$q', P.post_content) - 20, 300 + LENGTH('$q') + 300) as excerpt + FROM wp_posts P + LEFT JOIN wp_messagedata MD ON P.id = MD.post_id + LEFT JOIN wp_postmeta PM ON PM.post_id = P.ID AND PM.meta_key = '_thumbnail_id' + LEFT JOIN wp_postmeta PMA ON PM.meta_value = PMA.post_id AND PMA.meta_key = '_wp_attached_file' + WHERE P.post_type = 'actividades' + AND P.post_status = 'publish' + AND MATCH(P.post_content) AGAINST ('$q' IN NATURAL LANGUAGE MODE) + ORDER BY score DESC"; + return $this->execute_sql($sql); + } + + function country_summary(){ + $sql = "SELECT + count( P.ID ) as total, + MC.country_name as country, + MC.country_code as country_code + FROM `wp_posts` P + INNER JOIN wp_messagedata MD ON MD.post_id = P.ID + INNER JOIN wp_messagecountries MC ON MC.country_code = MD.country + WHERE `post_status` = 'publish' + AND `post_type` = 'actividades' + AND MC.language_code = 'es' + GROUP BY country_code + ORDER BY country;"; + return $this->execute_sql($sql); + } + + function country_list($c){ + $sql = "SELECT + P.ID, + P.post_title AS title, + P.post_date AS creation_date, + P.post_modified as last_updated, + LENGTH(P.post_content) as bodylength, + IFNULL(NULLIF(TIME_TO_SEC(MD.duration), '' ), 0) AS duration, + MD.date, + MD.activity AS no_activity, + MD.city, + MD.country, + MD.state, + PMA.meta_value AS thumbnail, + P.post_name as slug + FROM wp_posts P + LEFT JOIN wp_messagedata MD ON P.id = MD.post_id + LEFT JOIN wp_postmeta PM ON PM.post_id = P.ID AND PM.meta_key = '_thumbnail_id' + LEFT JOIN wp_postmeta PMA ON PM.meta_value = PMA.post_id AND PMA.meta_key = '_wp_attached_file' + WHERE P.post_type = 'actividades' + AND P.post_status = 'publish' + AND MD.country = '$c' + ORDER BY MD.date DESC"; + return $this->execute_sql($sql); + } + + function year_list( $locale ){ + $sql = "SELECT + COUNT(P.ID) as total, + YEAR(P.post_date) as year, + MONTH(P.post_date) as month + FROM wp_posts P + INNER JOIN wp_terms T ON T.slug = '$locale' + INNER JOIN wp_term_relationships TR ON TR.object_id = P.ID AND TR.term_taxonomy_id = T.term_id + WHERE P.post_type = 'actividades' AND P.post_status = 'publish' + GROUP BY YEAR(P.post_date), MONTH(P.post_date) + ORDER BY YEAR(P.post_date) DESC, MONTH(P.post_date) DESC;"; + return $this->execute_sql($sql); + } + + function year_list_history( $locale ){ + $sql = "SELECT + COUNT(P.ID) as total, + YEAR(P.post_date) as year, + MONTH(P.post_date) as month + FROM wp_posts P + LEFT JOIN wp_postmeta PM ON PM.post_id = P.ID AND PM.meta_key = 'mensaje_json' + INNER JOIN wp_terms T ON T.slug = 'es' + INNER JOIN wp_term_relationships TR ON TR.object_id = P.ID AND TR.term_taxonomy_id = T.term_id + WHERE P.post_type = 'actividades' + AND P.post_status = 'publish' + AND PM.meta_value IS NOT NULL + AND PM.meta_value != '' + GROUP BY YEAR(P.post_date), MONTH(P.post_date) + ORDER BY YEAR(P.post_date) DESC, MONTH(P.post_date) DESC;"; + return $this->execute_sql($sql); + } + + function lgccctv_list( $locale ){ + //Check locale and change accordingly to the right DB prefix for that locale + $prefix = $this->get_blog_by_locale( $locale ); + + $sql = "SELECT + P.ID, + P.post_title AS title, + P.post_date AS creation_date, + P.post_modified as last_updated, + P.post_name as slug, + O.option_value AS translationmeta + FROM ".$prefix."posts P + LEFT JOIN ".$prefix."options O ON O.option_name = CONCAT('msls_',P.ID) + WHERE P.post_type = 'actividades' + AND P.post_status = 'publish'"; + + return $this->execute_sql( $sql ); + } +} \ No newline at end of file diff --git a/ActividadesWP/v5/inc/class-phpass.php b/ActividadesWP/v5/inc/class-phpass.php new file mode 100644 index 0000000..8b8b113 --- /dev/null +++ b/ActividadesWP/v5/inc/class-phpass.php @@ -0,0 +1,276 @@ + in 2004-2006 and placed in +# the public domain. Revised in subsequent years, still public domain. +# +# There's absolutely no warranty. +# +# Please be sure to update the Version line if you edit this file in any way. +# It is suggested that you leave the main version number intact, but indicate +# your project name (after the slash) and add your own revision information. +# +# Please do not change the "private" password hashing method implemented in +# here, thereby making your hashes incompatible. However, if you must, please +# change the hash type identifier (the "$P$") to something different. +# +# Obviously, since this code is in the public domain, the above are not +# requirements (there can be none), but merely suggestions. +# + +/** + * Portable PHP password hashing framework. + * + * @package phpass + * @version 0.3 / WordPress + * @link http://www.openwall.com/phpass/ + * @since 2.5.0 + */ +class PasswordHash { + var $itoa64; + var $iteration_count_log2; + var $portable_hashes; + var $random_state; + + /** + * PHP5 constructor. + */ + function __construct( $iteration_count_log2, $portable_hashes ) + { + $this->itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; + + if ($iteration_count_log2 < 4 || $iteration_count_log2 > 31) + $iteration_count_log2 = 8; + $this->iteration_count_log2 = $iteration_count_log2; + + $this->portable_hashes = $portable_hashes; + + $this->random_state = microtime() . uniqid(rand(), TRUE); // removed getmypid() for compatibility reasons + } + + /** + * PHP4 constructor. + */ + public function PasswordHash( $iteration_count_log2, $portable_hashes ) { + self::__construct( $iteration_count_log2, $portable_hashes ); + } + + function get_random_bytes($count) + { + $output = ''; + if ( @is_readable('/dev/urandom') && + ($fh = @fopen('/dev/urandom', 'rb'))) { + $output = fread($fh, $count); + fclose($fh); + } + + if (strlen($output) < $count) { + $output = ''; + for ($i = 0; $i < $count; $i += 16) { + $this->random_state = + md5(microtime() . $this->random_state); + $output .= + pack('H*', md5($this->random_state)); + } + $output = substr($output, 0, $count); + } + + return $output; + } + + function encode64($input, $count) + { + $output = ''; + $i = 0; + do { + $value = ord($input[$i++]); + $output .= $this->itoa64[$value & 0x3f]; + if ($i < $count) + $value |= ord($input[$i]) << 8; + $output .= $this->itoa64[($value >> 6) & 0x3f]; + if ($i++ >= $count) + break; + if ($i < $count) + $value |= ord($input[$i]) << 16; + $output .= $this->itoa64[($value >> 12) & 0x3f]; + if ($i++ >= $count) + break; + $output .= $this->itoa64[($value >> 18) & 0x3f]; + } while ($i < $count); + + return $output; + } + + function gensalt_private($input) + { + $output = '$P$'; + $output .= $this->itoa64[min($this->iteration_count_log2 + + ((PHP_VERSION >= '5') ? 5 : 3), 30)]; + $output .= $this->encode64($input, 6); + + return $output; + } + + function crypt_private($password, $setting) + { + $output = '*0'; + if (substr($setting, 0, 2) == $output) + $output = '*1'; + + $id = substr($setting, 0, 3); + # We use "$P$", phpBB3 uses "$H$" for the same thing + if ($id != '$P$' && $id != '$H$') + return $output; + + $count_log2 = strpos($this->itoa64, $setting[3]); + if ($count_log2 < 7 || $count_log2 > 30) + return $output; + + $count = 1 << $count_log2; + + $salt = substr($setting, 4, 8); + if (strlen($salt) != 8) + return $output; + + # We're kind of forced to use MD5 here since it's the only + # cryptographic primitive available in all versions of PHP + # currently in use. To implement our own low-level crypto + # in PHP would result in much worse performance and + # consequently in lower iteration counts and hashes that are + # quicker to crack (by non-PHP code). + if (PHP_VERSION >= '5') { + $hash = md5($salt . $password, TRUE); + do { + $hash = md5($hash . $password, TRUE); + } while (--$count); + } else { + $hash = pack('H*', md5($salt . $password)); + do { + $hash = pack('H*', md5($hash . $password)); + } while (--$count); + } + + $output = substr($setting, 0, 12); + $output .= $this->encode64($hash, 16); + + return $output; + } + + function gensalt_extended($input) + { + $count_log2 = min($this->iteration_count_log2 + 8, 24); + # This should be odd to not reveal weak DES keys, and the + # maximum valid value is (2**24 - 1) which is odd anyway. + $count = (1 << $count_log2) - 1; + + $output = '_'; + $output .= $this->itoa64[$count & 0x3f]; + $output .= $this->itoa64[($count >> 6) & 0x3f]; + $output .= $this->itoa64[($count >> 12) & 0x3f]; + $output .= $this->itoa64[($count >> 18) & 0x3f]; + + $output .= $this->encode64($input, 3); + + return $output; + } + + function gensalt_blowfish($input) + { + # This one needs to use a different order of characters and a + # different encoding scheme from the one in encode64() above. + # We care because the last character in our encoded string will + # only represent 2 bits. While two known implementations of + # bcrypt will happily accept and correct a salt string which + # has the 4 unused bits set to non-zero, we do not want to take + # chances and we also do not want to waste an additional byte + # of entropy. + $itoa64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + + $output = '$2a$'; + $output .= chr(ord('0') + $this->iteration_count_log2 / 10); + $output .= chr(ord('0') + $this->iteration_count_log2 % 10); + $output .= '$'; + + $i = 0; + do { + $c1 = ord($input[$i++]); + $output .= $itoa64[$c1 >> 2]; + $c1 = ($c1 & 0x03) << 4; + if ($i >= 16) { + $output .= $itoa64[$c1]; + break; + } + + $c2 = ord($input[$i++]); + $c1 |= $c2 >> 4; + $output .= $itoa64[$c1]; + $c1 = ($c2 & 0x0f) << 2; + + $c2 = ord($input[$i++]); + $c1 |= $c2 >> 6; + $output .= $itoa64[$c1]; + $output .= $itoa64[$c2 & 0x3f]; + } while (1); + + return $output; + } + + function HashPassword($password) + { + if ( strlen( $password ) > 4096 ) { + return '*'; + } + + $random = ''; + + if (CRYPT_BLOWFISH == 1 && !$this->portable_hashes) { + $random = $this->get_random_bytes(16); + $hash = + crypt($password, $this->gensalt_blowfish($random)); + if (strlen($hash) == 60) + return $hash; + } + + if (CRYPT_EXT_DES == 1 && !$this->portable_hashes) { + if (strlen($random) < 3) + $random = $this->get_random_bytes(3); + $hash = + crypt($password, $this->gensalt_extended($random)); + if (strlen($hash) == 20) + return $hash; + } + + if (strlen($random) < 6) + $random = $this->get_random_bytes(6); + $hash = + $this->crypt_private($password, + $this->gensalt_private($random)); + if (strlen($hash) == 34) + return $hash; + + # Returning '*' on error is safe here, but would _not_ be safe + # in a crypt(3)-like function used _both_ for generating new + # hashes and for validating passwords against existing hashes. + return '*'; + } + + function CheckPassword($password, $stored_hash) + { + if ( strlen( $password ) > 4096 ) { + return false; + } + + $hash = $this->crypt_private($password, $stored_hash); + if ($hash[0] == '*') + $hash = crypt($password, $stored_hash); + + return $hash === $stored_hash; + } +} \ No newline at end of file diff --git a/ActividadesWP/v5/inc/conferencia.php b/ActividadesWP/v5/inc/conferencia.php new file mode 100644 index 0000000..16e07bc --- /dev/null +++ b/ActividadesWP/v5/inc/conferencia.php @@ -0,0 +1,449 @@ +conn = $db; + } + + /** + * Helper function to get all blogs and their languages + */ + function get_blog_by_locale($locale){ + $r = ''; + switch($locale){ + case "fr_FR": + case "fr": + $r = "wp_4_"; + break; + case "en": + case "en_US": + $r = "wp_2_"; + break; + case "pt": + case "pt-br": + case "pt_br": + case "pt_BR": + $r = "wp_3_"; + break; + case "es": + case "es_ES": + default: + $r = "wp_"; + break; + } + return $r; + } + + function translation_list( $year, $month, $last_update, $text, $locale, $termid="ultimas" ){ //Default last updated + //Check locale and change accordingly to the right DB prefix for that locale + $prefix = $this->get_blog_by_locale( $locale ); + + $sql = "SELECT + P.ID, + P.post_title AS title, + P.post_date AS creation_date, + P.post_modified as last_updated, + P.post_name as slug,"; + if($text){ + $sql .= "P.post_content as content,"; + } + $sql .= "LENGTH(P.post_content) as bodylength, + O.option_value AS translationmeta + FROM ".$prefix."posts P + LEFT JOIN ".$prefix."options O ON O.option_name = CONCAT('msls_',P.ID)"; + if($year == '' && $month == ''){ + $sql .= " + INNER JOIN ".$prefix."term_relationships AS tr ON (P.ID = tr.object_id) + INNER JOIN ".$prefix."terms AS t ON (t.term_id = tr.term_taxonomy_id)"; + } + $sql .= " + WHERE P.post_type = 'conferencias' + AND P.post_status = 'publish'"; + if($year!=''){ + $sql .= " AND YEAR(P.post_date) = '$year'"; + if($month!=''){ + $sql .= " AND MONTH(P.post_date) = '$month'"; + } + if($last_update!=''){ + $sql .= " AND UNIX_TIMESTAMP(P.post_modified) > ". $last_update; + } + $sql .= " ORDER BY P.post_date DESC"; + } else { + $sql .= " AND t.slug = '$termid'"; + $sql .= " ORDER BY P.post_modified DESC"; + $sql .= " LIMIT 16"; + } + return $this->execute_sql( $sql ); + } + + function conference_meta($id){ + $sql = "SELECT + IFNULL(NULLIF(TIME_TO_SEC(MD.duration), '' ), 0) AS duration, + MD.date, + MD.activity AS no_activity, + MD.city, + MD.country, + MD.state, + MD.private, + PMA.meta_value AS thumbnail, + PMAS.meta_value AS meta + FROM wp_posts P + LEFT JOIN wp_messagedata MD ON P.id = MD.post_id + LEFT JOIN wp_postmeta PM ON PM.post_id = P.ID AND PM.meta_key = '_thumbnail_id' + LEFT JOIN wp_postmeta PMA ON PM.meta_value = PMA.post_id AND PMA.meta_key = '_wp_attached_file' + LEFT JOIN wp_postmeta PMAS ON PM.meta_value = PMAS.post_id AND PMAS.meta_key = '_wp_attachment_metadata' + LEFT JOIN wp_options O ON O.option_name = CONCAT('msls_',P.ID) + WHERE P.post_type = 'conferencias' + AND P.post_status = 'publish' + AND P.ID = ".$id; + $data = $this->execute_sql( $sql ); + $response = $data->fetch(PDO::FETCH_ASSOC); + return $response; + } + + /** + * List function + * + * Displays the list of messages with it's pertinent variables + * + */ + function list( $year, $month, $last_update, $text, $locale ){ + $sql = "SELECT + P.ID, + P.post_title AS title, + P.post_date AS creation_date, + P.post_modified as last_updated,"; + if($text){ + $sql .= "P.post_content as content,"; + } + $sql .= "LENGTH(P.post_content) as bodylength, + IFNULL(NULLIF(TIME_TO_SEC(MD.duration), '' ), 0) AS duration, + MD.date, + MD.activity AS no_activity, + MD.city, + MD.country, + MD.state, + PMA.meta_value AS thumbnail, + PMAS.meta_value AS meta, + O.option_value AS translationmeta, + P.post_name as slug + FROM wp_posts P + LEFT JOIN wp_messagedata MD ON P.id = MD.post_id + LEFT JOIN wp_postmeta PM ON PM.post_id = P.ID AND PM.meta_key = '_thumbnail_id' + LEFT JOIN wp_postmeta PMA ON PM.meta_value = PMA.post_id AND PMA.meta_key = '_wp_attached_file' + LEFT JOIN wp_postmeta PMAS ON PM.meta_value = PMAS.post_id AND PMAS.meta_key = '_wp_attachment_metadata' + LEFT JOIN wp_options O ON O.option_name = CONCAT('msls_',P.ID) + WHERE P.post_type = 'conferencias' + AND P.post_status = 'publish'"; + if($year!=''){ + $sql .= " AND YEAR(MD.date) = '$year'"; + } + if($month!=''){ + $sql .= " AND MONTH(MD.date) = '$month'"; + } + if($last_update!=''){ + $sql .= " AND UNIX_TIMESTAMP(P.post_modified) > ". $last_update; + } + $sql .= " ORDER BY P.post_date DESC"; + return $this->execute_sql( $sql ); + } + + /** + * Detail function + * + * Given an ID returns the message with all details + * + * @param id Int id of the message whose details want to be found. + */ + function detail($id,$locale){ + //Check locale and change accordingly to the right DB prefix for that locale + $prefix = $this->get_blog_by_locale( $locale ); + + $sql = "SELECT + P.ID, + P.post_title AS title, + P.post_content AS content, + P.post_date AS creation_date, + P.post_modified AS last_updated, + O.option_value AS translationmeta, + P.post_name as slug + FROM ".$prefix."posts AS P + LEFT JOIN ".$prefix."options O ON O.option_name = CONCAT('msls_',P.ID) + WHERE P.ID = '$id'"; + return $this->execute_sql( $sql ); + } + + /** + * Slug function + * + * Given a slug, returns the message with all details + * + * @param slug String Slug of the message whose details want to be found + */ + function detailBySlug($slug,$locale){ + //Check locale and change accordingly to the right DB prefix for that locale + $prefix = $this->get_blog_by_locale( $locale ); + + $sql = "SELECT + P.ID, + P.post_title AS title, + P.post_content AS content, + P.post_date AS creation_date, + P.post_modified AS last_updated, + O.option_value AS translationmeta, + P.post_name as slug + FROM ".$prefix."posts AS P + LEFT JOIN ".$prefix."options O ON O.option_name = CONCAT('msls_',P.ID) + WHERE P.post_name = '$slug'"; + return $this->execute_sql( $sql ); + } + + /** + * Last update function + * + * Returns the last updated imtestamp for the message passed in via the @id + * + * @param id Int id for whom the last update should be found + */ + function last_update($id){ + $sql = "SELECT + P.post_modified AS last_updated + FROM wp_posts P + WHERE P.ID = '$id'"; + return $this->execute_sql( $sql ); + } + + /** + * Execute SQL function + * + * Executes a generic SQL statement and passes back the result. + * + * @param string sql SQl statement to be executed + * @return + */ + function execute_sql( $sql ){ + $stmt = $this->conn->prepare($sql); + $stmt->execute(); + return $stmt; + } + + /** + * Relevant conferences function + * + * Get all relevant conferences and return + */ + function relevant_conferences(){ + $sql = "SELECT + option_value + FROM wp_options + where option_name = 'options_conference'"; + return $this->execute_sql( $sql ); + } + + function get_post_source($trid){ + $sql = "SELECT + T.element_id AS post_id + FROM wp_icl_translations AS T + WHERE T.trid = '$trid' + AND T.language_code = 'es'"; + return $this->execute_sql( $sql ); + } + + function get_post_language($id){ + $sql = "SELECT + T.language_code, + T.trid + FROM wp_icl_translations AS T + WHERE T.element_id = '$id' + AND T.element_type = 'post_message'"; + return $this->execute_sql( $sql ); + } + + function get_post_metadata($id){ + $sql = "SELECT + IFNULL(NULLIF(TIME_TO_SEC(MD.duration), '' ), 0) AS duration, + MD.country, + MD.state, + MD.city AS city, + MD.activity AS no_activity + FROM wp_messagedata AS MD + WHERE post_id = '$id'"; + return $this->execute_sql( $sql ); + } + + function get_post_files($id,$locale){ + //Check locale and change accordingly to the right DB prefix for that locale + $prefix = $this->get_blog_by_locale( $locale ); + + $sql = "SELECT + MF.youtube, + MF.video, + MF.audio, + MF.pdf, + MF.pdf_simple, + MF.videofile, + MF.audiofile, + MF.pdffile, + MF.pdfsimplefile + FROM ".$prefix."messagefiles as MF + WHERE MF.post_id = '$id'"; + return $this->execute_sql( $sql ); + } + + function get_post_file($id,$locale){ + //Check locale and change accordingly to the right DB prefix for that locale + $prefix = $this->get_blog_by_locale( $locale ); + + $sql = "SELECT + P.guid as url + FROM ".$prefix."posts P + WHERE P.ID = '$id'"; + return $this->execute_sql( $sql ); + } + + function title_search($q,$locale){ + //Check locale and change accordingly to the right DB prefix for that locale + $prefix = $this->get_blog_by_locale( $locale ); + + $sql = "SELECT + P.ID, + P.post_title AS title, + P.post_date AS creation_date, + P.post_modified as last_updated, + O.option_value AS translationmeta, + P.post_name as slug + FROM ".$prefix."posts AS P + LEFT JOIN ".$prefix."options O ON O.option_name = CONCAT('msls_',P.ID) + WHERE P.post_type = 'conferencias' + AND P.post_status = 'publish' + AND P.post_title LIKE('%$q%')"; + return $this->execute_sql($sql); + + } + + function content_search($q){ + $sql = "SELECT + P.ID, + P.post_title AS title, + P.post_date AS creation_date, + P.post_modified as last_updated, + IFNULL(NULLIF(TIME_TO_SEC(MD.duration), '' ), 0) AS duration, + MD.date, + MD.activity AS no_activity, + MD.city, + MD.country, + MD.state, + PMA.meta_value AS thumbnail, + P.post_name as slug, + MATCH(P.post_content) AGAINST ('$q' IN NATURAL LANGUAGE MODE) as score, + SUBSTRING(P.post_content, LOCATE('$q', P.post_content) - 20, 300 + LENGTH('$q') + 300) as excerpt + FROM wp_posts P + LEFT JOIN wp_messagedata MD ON P.id = MD.post_id + LEFT JOIN wp_postmeta PM ON PM.post_id = P.ID AND PM.meta_key = '_thumbnail_id' + LEFT JOIN wp_postmeta PMA ON PM.meta_value = PMA.post_id AND PMA.meta_key = '_wp_attached_file' + WHERE P.post_type = 'conferencias' + AND P.post_status = 'publish' + AND MATCH(P.post_content) AGAINST ('$q' IN NATURAL LANGUAGE MODE) + ORDER BY score DESC"; + return $this->execute_sql($sql); + } + + function country_summary(){ + $sql = "SELECT + count( P.ID ) as total, + MC.country_name as country, + MC.country_code as country_code + FROM `wp_posts` P + INNER JOIN wp_messagedata MD ON MD.post_id = P.ID + INNER JOIN wp_messagecountries MC ON MC.country_code = MD.country + WHERE `post_status` = 'publish' + AND `post_type` = 'conferencias' + AND MC.language_code = 'es' + GROUP BY country_code + ORDER BY country;"; + return $this->execute_sql($sql); + } + + function country_list($c){ + $sql = "SELECT + P.ID, + P.post_title AS title, + P.post_date AS creation_date, + P.post_modified as last_updated, + LENGTH(P.post_content) as bodylength, + IFNULL(NULLIF(TIME_TO_SEC(MD.duration), '' ), 0) AS duration, + MD.date, + MD.activity AS no_activity, + MD.city, + MD.country, + MD.state, + PMA.meta_value AS thumbnail, + P.post_name as slug + FROM wp_posts P + LEFT JOIN wp_messagedata MD ON P.id = MD.post_id + LEFT JOIN wp_postmeta PM ON PM.post_id = P.ID AND PM.meta_key = '_thumbnail_id' + LEFT JOIN wp_postmeta PMA ON PM.meta_value = PMA.post_id AND PMA.meta_key = '_wp_attached_file' + WHERE P.post_type = 'conferencias' + AND P.post_status = 'publish' + AND MD.country = '$c' + ORDER BY MD.date DESC"; + return $this->execute_sql($sql); + } + + function year_list(){ + $sql = "SELECT + count(ID) as total, + YEAR(post_date) as year, + MONTH(post_date) as month + FROM wp_posts + WHERE `post_status` = 'publish' + AND `post_type` = 'conferencias' + GROUP BY YEAR(post_date), MONTH(post_date) + ORDER BY YEAR(post_date) DESC, MONTH(post_date) DESC;"; + return $this->execute_sql($sql); + } + + function lgccctv_list( $locale ){ + //Check locale and change accordingly to the right DB prefix for that locale + $prefix = $this->get_blog_by_locale( $locale ); + + $sql = "SELECT + P.ID, + P.post_title AS title, + P.post_date AS creation_date, + P.post_modified as last_updated, + P.post_name as slug, + O.option_value AS translationmeta + FROM ".$prefix."posts P + LEFT JOIN ".$prefix."options O ON O.option_name = CONCAT('msls_',P.ID) + WHERE P.post_type = 'conferencias' + AND P.post_status = 'publish'"; + + return $this->execute_sql( $sql ); + } +} \ No newline at end of file diff --git a/ActividadesWP/v5/inc/conferencia.php.old b/ActividadesWP/v5/inc/conferencia.php.old new file mode 100644 index 0000000..4b30161 --- /dev/null +++ b/ActividadesWP/v5/inc/conferencia.php.old @@ -0,0 +1,429 @@ +conn = $db; + } + + /** + * Helper function to get all blogs and their languages + */ + function get_blog_by_locale($locale){ + $r = ''; + switch($locale){ + case "fr_FR": + case "fr": + $r = "wp_4_"; + break; + case "en": + case "en_US": + $r = "wp_2_"; + break; + case "pt": + case "pt-br": + case "pt_br": + case "pt_BR": + $r = "wp_3_"; + break; + case "es": + case "es_ES": + default: + $r = "wp_"; + break; + } + return $r; + } + + function translation_list( $year, $month, $last_update, $text, $locale, $termid="ultimas" ){ //Default last updated + //Check locale and change accordingly to the right DB prefix for that locale + $prefix = $this->get_blog_by_locale( $locale ); + + $sql = "SELECT + P.ID, + P.post_title AS title, + P.post_date AS creation_date, + P.post_modified as last_updated, + P.post_name as slug,"; + if($text){ + $sql .= "P.post_content as content,"; + } + $sql .= "LENGTH(P.post_content) as bodylength, + O.option_value AS translationmeta + FROM ".$prefix."posts P + LEFT JOIN ".$prefix."options O ON O.option_name = CONCAT('msls_',P.ID)"; + if($year == '' && $month == ''){ + $sql .= " + INNER JOIN ".$prefix."term_relationships AS tr ON (P.ID = tr.object_id) + INNER JOIN ".$prefix."terms AS t ON (t.term_id = tr.term_taxonomy_id)"; + } + $sql .= " + WHERE P.post_type = 'conferencias' + AND P.post_status = 'publish'"; + if($year!=''){ + $sql .= " AND YEAR(P.post_date) = '$year'"; + if($month!=''){ + $sql .= " AND MONTH(P.post_date) = '$month'"; + } + if($last_update!=''){ + $sql .= " AND UNIX_TIMESTAMP(P.post_modified) > ". $last_update; + } + $sql .= " ORDER BY P.post_date DESC"; + } else { + $sql .= " AND t.slug = '$termid'"; + $sql .= " ORDER BY P.post_modified DESC"; + $sql .= " LIMIT 16"; + } + return $this->execute_sql( $sql ); + } + + function conference_meta($id){ + $sql = "SELECT + IFNULL(NULLIF(TIME_TO_SEC(MD.duration), '' ), 0) AS duration, + MD.date, + MD.activity AS no_activity, + MD.city, + MD.country, + MD.state, + PMA.meta_value AS thumbnail, + PMAS.meta_value AS meta + FROM wp_posts P + LEFT JOIN wp_messagedata MD ON P.id = MD.post_id + LEFT JOIN wp_postmeta PM ON PM.post_id = P.ID AND PM.meta_key = '_thumbnail_id' + LEFT JOIN wp_postmeta PMA ON PM.meta_value = PMA.post_id AND PMA.meta_key = '_wp_attached_file' + LEFT JOIN wp_postmeta PMAS ON PM.meta_value = PMAS.post_id AND PMAS.meta_key = '_wp_attachment_metadata' + LEFT JOIN wp_options O ON O.option_name = CONCAT('msls_',P.ID) + WHERE P.post_type = 'conferencias' + AND P.post_status = 'publish' + AND P.ID = ".$id; + $data = $this->execute_sql( $sql ); + $response = $data->fetch(PDO::FETCH_ASSOC); + return $response; + } + + /** + * List function + * + * Displays the list of messages with it's pertinent variables + * + */ + function list( $year, $month, $last_update, $text, $locale ){ + $sql = "SELECT + P.ID, + P.post_title AS title, + P.post_date AS creation_date, + P.post_modified as last_updated,"; + if($text){ + $sql .= "P.post_content as content,"; + } + $sql .= "LENGTH(P.post_content) as bodylength, + IFNULL(NULLIF(TIME_TO_SEC(MD.duration), '' ), 0) AS duration, + MD.date, + MD.activity AS no_activity, + MD.city, + MD.country, + MD.state, + PMA.meta_value AS thumbnail, + PMAS.meta_value AS meta, + O.option_value AS translationmeta, + P.post_name as slug + FROM wp_posts P + LEFT JOIN wp_messagedata MD ON P.id = MD.post_id + LEFT JOIN wp_postmeta PM ON PM.post_id = P.ID AND PM.meta_key = '_thumbnail_id' + LEFT JOIN wp_postmeta PMA ON PM.meta_value = PMA.post_id AND PMA.meta_key = '_wp_attached_file' + LEFT JOIN wp_postmeta PMAS ON PM.meta_value = PMAS.post_id AND PMAS.meta_key = '_wp_attachment_metadata' + LEFT JOIN wp_options O ON O.option_name = CONCAT('msls_',P.ID) + WHERE P.post_type = 'conferencias' + AND P.post_status = 'publish'"; + if($year!=''){ + $sql .= " AND YEAR(MD.date) = '$year'"; + } + if($month!=''){ + $sql .= " AND MONTH(MD.date) = '$month'"; + } + if($last_update!=''){ + $sql .= " AND UNIX_TIMESTAMP(P.post_modified) > ". $last_update; + } + $sql .= " ORDER BY P.post_date DESC"; + return $this->execute_sql( $sql ); + } + + /** + * Detail function + * + * Given an ID returns the message with all details + * + * @param id Int id of the message whose details want to be found. + */ + function detail($id,$locale){ + //Check locale and change accordingly to the right DB prefix for that locale + $prefix = $this->get_blog_by_locale( $locale ); + + $sql = "SELECT + P.ID, + P.post_title AS title, + P.post_content AS content, + P.post_date AS creation_date, + P.post_modified AS last_updated, + O.option_value AS translationmeta, + P.post_name as slug + FROM ".$prefix."posts AS P + LEFT JOIN ".$prefix."options O ON O.option_name = CONCAT('msls_',P.ID) + WHERE P.ID = '$id'"; + return $this->execute_sql( $sql ); + } + + /** + * Slug function + * + * Given a slug, returns the message with all details + * + * @param slug String Slug of the message whose details want to be found + */ + function detailBySlug($slug,$locale){ + //Check locale and change accordingly to the right DB prefix for that locale + $prefix = $this->get_blog_by_locale( $locale ); + + $sql = "SELECT + P.ID, + P.post_title AS title, + P.post_content AS content, + P.post_date AS creation_date, + P.post_modified AS last_updated, + O.option_value AS translationmeta, + P.post_name as slug + FROM ".$prefix."posts AS P + LEFT JOIN ".$prefix."options O ON O.option_name = CONCAT('msls_',P.ID) + WHERE P.post_name = '$slug'"; + return $this->execute_sql( $sql ); + } + + /** + * Last update function + * + * Returns the last updated imtestamp for the message passed in via the @id + * + * @param id Int id for whom the last update should be found + */ + function last_update($id){ + $sql = "SELECT + P.post_modified AS last_updated + FROM wp_posts P + WHERE P.ID = '$id'"; + return $this->execute_sql( $sql ); + } + + /** + * Execute SQL function + * + * Executes a generic SQL statement and passes back the result. + * + * @param string sql SQl statement to be executed + * @return + */ + function execute_sql( $sql ){ + $stmt = $this->conn->prepare($sql); + $stmt->execute(); + return $stmt; + } + + /** + * Relevant conferences function + * + * Get all relevant conferences and return + */ + function relevant_conferences(){ + $sql = "SELECT + option_value + FROM wp_options + where option_name = 'options_conference'"; + return $this->execute_sql( $sql ); + } + + function get_post_source($trid){ + $sql = "SELECT + T.element_id AS post_id + FROM wp_icl_translations AS T + WHERE T.trid = '$trid' + AND T.language_code = 'es'"; + return $this->execute_sql( $sql ); + } + + function get_post_language($id){ + $sql = "SELECT + T.language_code, + T.trid + FROM wp_icl_translations AS T + WHERE T.element_id = '$id' + AND T.element_type = 'post_message'"; + return $this->execute_sql( $sql ); + } + + function get_post_metadata($id){ + $sql = "SELECT + IFNULL(NULLIF(TIME_TO_SEC(MD.duration), '' ), 0) AS duration, + MD.country, + MD.state, + MD.city AS city, + MD.activity AS no_activity + FROM wp_messagedata AS MD + WHERE post_id = '$id'"; + return $this->execute_sql( $sql ); + } + + function get_post_files($id,$locale){ + //Check locale and change accordingly to the right DB prefix for that locale + $prefix = $this->get_blog_by_locale( $locale ); + + $sql = "SELECT + MF.youtube, + MF.video, + MF.audio, + MF.pdf, + MF.pdf_simple, + MF.videofile, + MF.audiofile, + MF.pdffile, + MF.pdfsimplefile + FROM ".$prefix."messagefiles as MF + WHERE MF.post_id = '$id'"; + return $this->execute_sql( $sql ); + } + + function get_post_file($id,$locale){ + //Check locale and change accordingly to the right DB prefix for that locale + $prefix = $this->get_blog_by_locale( $locale ); + + $sql = "SELECT + P.guid as url + FROM ".$prefix."posts P + WHERE P.ID = '$id'"; + return $this->execute_sql( $sql ); + } + + function title_search($q,$locale){ + //Check locale and change accordingly to the right DB prefix for that locale + $prefix = $this->get_blog_by_locale( $locale ); + + $sql = "SELECT + P.ID, + P.post_title AS title, + P.post_date AS creation_date, + P.post_modified as last_updated, + O.option_value AS translationmeta, + P.post_name as slug + FROM ".$prefix."posts AS P + LEFT JOIN ".$prefix."options O ON O.option_name = CONCAT('msls_',P.ID) + WHERE P.post_type = 'conferencias' + AND P.post_status = 'publish' + AND P.post_title LIKE('%$q%')"; + return $this->execute_sql($sql); + + } + + function content_search($q){ + $sql = "SELECT + P.ID, + P.post_title AS title, + P.post_date AS creation_date, + P.post_modified as last_updated, + IFNULL(NULLIF(TIME_TO_SEC(MD.duration), '' ), 0) AS duration, + MD.date, + MD.activity AS no_activity, + MD.city, + MD.country, + MD.state, + PMA.meta_value AS thumbnail, + P.post_name as slug, + MATCH(P.post_content) AGAINST ('$q' IN NATURAL LANGUAGE MODE) as score, + SUBSTRING(P.post_content, LOCATE('$q', P.post_content) - 20, 300 + LENGTH('$q') + 300) as excerpt + FROM wp_posts P + LEFT JOIN wp_messagedata MD ON P.id = MD.post_id + LEFT JOIN wp_postmeta PM ON PM.post_id = P.ID AND PM.meta_key = '_thumbnail_id' + LEFT JOIN wp_postmeta PMA ON PM.meta_value = PMA.post_id AND PMA.meta_key = '_wp_attached_file' + WHERE P.post_type = 'conferencias' + AND P.post_status = 'publish' + AND MATCH(P.post_content) AGAINST ('$q' IN NATURAL LANGUAGE MODE) + ORDER BY score DESC"; + return $this->execute_sql($sql); + } + + function country_summary(){ + $sql = "SELECT + count( P.ID ) as total, + MC.country_name as country, + MC.country_code as country_code + FROM `wp_posts` P + INNER JOIN wp_messagedata MD ON MD.post_id = P.ID + INNER JOIN wp_messagecountries MC ON MC.country_code = MD.country + WHERE `post_status` = 'publish' + AND `post_type` = 'conferencias' + AND MC.language_code = 'es' + GROUP BY country_code + ORDER BY country;"; + return $this->execute_sql($sql); + } + + function country_list($c){ + $sql = "SELECT + P.ID, + P.post_title AS title, + P.post_date AS creation_date, + P.post_modified as last_updated, + LENGTH(P.post_content) as bodylength, + IFNULL(NULLIF(TIME_TO_SEC(MD.duration), '' ), 0) AS duration, + MD.date, + MD.activity AS no_activity, + MD.city, + MD.country, + MD.state, + PMA.meta_value AS thumbnail, + P.post_name as slug + FROM wp_posts P + LEFT JOIN wp_messagedata MD ON P.id = MD.post_id + LEFT JOIN wp_postmeta PM ON PM.post_id = P.ID AND PM.meta_key = '_thumbnail_id' + LEFT JOIN wp_postmeta PMA ON PM.meta_value = PMA.post_id AND PMA.meta_key = '_wp_attached_file' + WHERE P.post_type = 'conferencias' + AND P.post_status = 'publish' + AND MD.country = '$c' + ORDER BY MD.date DESC"; + return $this->execute_sql($sql); + } + + function year_list(){ + $sql = "SELECT + count(ID) as total, + YEAR(post_date) as year, + MONTH(post_date) as month + FROM wp_posts + WHERE `post_status` = 'publish' + AND `post_type` = 'conferencias' + GROUP BY YEAR(post_date), MONTH(post_date) + ORDER BY YEAR(post_date) DESC, MONTH(post_date) DESC;"; + return $this->execute_sql($sql); + } +} \ No newline at end of file diff --git a/ActividadesWP/v5/inc/country.php b/ActividadesWP/v5/inc/country.php new file mode 100644 index 0000000..3c0ef4a --- /dev/null +++ b/ActividadesWP/v5/inc/country.php @@ -0,0 +1,40 @@ +conn = $db; + } + + // read products + function read( $lcode = 'es' ){ + + $last_update = ''; + + $sql = "SELECT + country_code, + country_name + FROM wp_messagecountries m + WHERE m.language_code = '$lcode'"; + + $stmt = $this->conn->prepare($sql); + + // execute query + $stmt->execute(); + + return $stmt; + } +} diff --git a/ActividadesWP/v5/inc/db.php b/ActividadesWP/v5/inc/db.php new file mode 100644 index 0000000..18bca43 --- /dev/null +++ b/ActividadesWP/v5/inc/db.php @@ -0,0 +1,30 @@ +conn = null; + + try{ + $this->conn = new PDO("mysql:host=" . $this->host . ";dbname=" . $this->db_name, $this->username, $this->password); + $this->conn->exec("set names utf8"); + }catch(PDOException $exception){ + echo "Connection error: " . $exception->getMessage(); + } + + return $this->conn; + } + + public function closeConnection(){ + $this -> conn = null; + } +} \ No newline at end of file diff --git a/ActividadesWP/v5/inc/epub/EPub.php b/ActividadesWP/v5/inc/epub/EPub.php new file mode 100644 index 0000000..b95ded3 --- /dev/null +++ b/ActividadesWP/v5/inc/epub/EPub.php @@ -0,0 +1,1428 @@ +EPub requires Zip.php at version " . self::REQ_ZIP_VERSION . " or higher.
You can obtain the latest version from http://www.phpclasses.org/browse/package/6110.html.

"); + } + include_once("EPubChapterSplitter.class.php"); + + $this->docRoot = $_SERVER["DOCUMENT_ROOT"] . "/"; + + $this->zip = new Zip(); + $this->zip->addFile("application/epub+zip", "mimetype"); + $this->zip->addDirectory("META-INF/"); + + $this->content = "\n\n\t\n\t\t\n\t\n\n"; + + $this->zip->addFile($this->content, "META-INF/container.xml"); + $this->content = NULL; + $this->opf_manifest = "\t\t\n"; + $this->chapterCount = 0; + + $this->isGdInstalled = extension_loaded('gd') && function_exists('gd_info'); + } + + /** + * Class destructor + * + * @return void + */ + function __destruct() { + $this->zip = NULL; + $this->title = ""; + $this->author = ""; + $this->publisher = ""; + $this->publishDate = 0; + $this->bookId = ""; + $this->opf_manifest = ""; + $this->opf_spine = ""; + $this->ncx_navmap = ""; + $this->opf = ""; + $this->ncx = ""; + $this->chapterCount = 0; + $this->subject = ""; + $this->coverage = ""; + $this->relation = ""; + $this->generator = ""; + } + + /** + * + * @param String $fileName Filename to use for the file, must be unique for the book. + * @param String $fileId Unique identifier for the file. + * @param String $fileData File data + * @param String $mimetype file mime type + * @return bool $success + */ + function addFile($fileName, $fileId, $fileData, $mimetype) { + if ($this->isFinalized || array_key_exists($fileName, $this->fileList)) { + return FALSE; + } + $fileName = preg_replace('#\\\#i', "/", $fileName); + $fileName = preg_replace('#^[/\.]+#i', "", $fileName); + $this->zip->addFile($fileData, $fileName); + $this->fileList[$fileName] = $fileName; + $this->opf_manifest .= "\t\t\n"; + return TRUE; + } + + /** + * Add a CSS file to the book. + * + * @param String $fileName Filename to use for the CSS file, must be unique for the book. + * @param String $fileId Unique identifier for the file. + * @param String $fileData CSS data + * @param int $externalReferences How to handle external references, EPub::EXTERNAL_REF_IGNORE, EPub::EXTERNAL_REF_ADD or EPub::EXTERNAL_REF_REMOVE_IMAGES? See documentation for processCSSExternalReferences for explanation. Default is EPub::EXTERNAL_REF_IGNORE. + * @param String $baseDir Default is "", meaning it is pointing to the document root. NOT used if $externalReferences is set to EPub::EXTERNAL_REF_IGNORE. + * + * @return bool $success + */ + function addCSSFile($fileName, $fileId, $fileData, $externalReferences = EPub::EXTERNAL_REF_IGNORE, $baseDir = "") { + if ($this->isFinalized || array_key_exists($fileName, $this->fileList)) { + return FALSE; + } + $fileName = preg_replace('#\\\#i', "/", $fileName); + $fileName = preg_replace('#^[/\.]+#i', "", $fileName); + + $cssDir = pathinfo($fileName); + $cssDir = preg_replace('#^[/\.]+#i', "", $cssDir["dirname"] . "/"); + if (!empty($cssDir)) { + $cssDir = preg_replace('#[^/]+/#i', "../", $cssDir); + } + + if ($externalReferences !== EPub::EXTERNAL_REF_IGNORE) { + $this->processCSSExternalReferences($fileData, $externalReferences, $baseDir, $cssDir); + } + + $this->zip->addFile($fileData, $fileName); + $this->fileList[$fileName] = $fileName; + $this->opf_manifest .= "\t\t\n"; + return TRUE; + } + + /** + * Add a chapter to the book, as a chapter should not exceed 250kB, you can parse an array with multiple parts as $chapterData. + * These will still only show up as a single chapter in the book TOC. + * + * @param String $chapterName Name of the chapter, will be use din the TOC + * @param String $fileName Filename to use for the chapter, must be unique for the book. + * @param String $chapter Chapter text in XHTML or array $chapterData valid XHTML data for the chapter. File should NOT exceed 250kB. + * @param Bool $autoSplit Should the chapter be split if it exceeds the default split size? Default=FALSE, only used if $chapterData is a String. + * @param int $externalReferences How to handle external references, EPub::EXTERNAL_REF_IGNORE, EPub::EXTERNAL_REF_ADD or EPub::EXTERNAL_REF_REMOVE_IMAGES? See documentation for processChapterExternalReferences for explanation. Default is EPub::EXTERNAL_REF_IGNORE. + * @param String $baseDir Default is "", meaning it is pointing to the document root. NOT used if $externalReferences is set to EPub::EXTERNAL_REF_IGNORE. + * @return bool $success + */ + function addChapter($chapterName, $fileName, $chapterData, $autoSplit = FALSE, $externalReferences = EPub::EXTERNAL_REF_IGNORE, $baseDir = "") { + if ($this->isFinalized) { + return FALSE; + } + $fileName = preg_replace('#\\\#i', "/", $fileName); + $fileName = preg_replace('#^[/\.]+#i', "", $fileName); + + $htmlDir = pathinfo($fileName); + $htmlDir = preg_replace('#^[/\.]+#i', "", $htmlDir["dirname"] . "/"); + + $chapter = $chapterData; + if ($autoSplit && is_string($chapterData) && mb_strlen($chapterData) > $this->splitDefaultSize) { + $splitter = new EPubChapterSplitter(); + + $chapterArray = $splitter->splitChapter($chapterData); + if (count($chapterArray) > 1) { + $chapter = $chapterArray; + } + } + + if (!empty($chapter) && is_string($chapter)) { + if ($externalReferences !== EPub::EXTERNAL_REF_IGNORE) { + $this->processChapterExternalReferences($chapter, $externalReferences, $baseDir, $htmlDir); + } + + $this->zip->addFile($chapter, $fileName); + $this->fileList[$fileName] = $fileName; + $this->chapterCount++; + $this->opf_manifest .= "\t\tchapterCount . "\" href=\"" . $fileName . "\" media-type=\"application/xhtml+xml\" />\n"; + $this->opf_spine .= "\t\tchapterCount . "\" />\n"; + $this->ncx_navmap .= "\n\t\tchapterCount . "\" playOrder=\"" . $this->chapterCount . "\">\n\t\t\t" . $chapterName . "\n\t\t\t\n\t\t\n"; + } else if (is_array($chapter)) { + $partCount = 0; + $this->chapterCount++; + + $oneChapter = each($chapter); + while ($oneChapter) { + list($k, $v) = $oneChapter; + $c = $v; + if ($externalReferences !== EPub::EXTERNAL_REF_IGNORE) { + $this->processChapterExternalReferences($c, $externalReferences, $baseDir); + } + $partCount++; + $this->zip->addFile($c, $fileName . "-" . $partCount); + $this->fileList[$fileName . "-" . $partCount] = $fileName . "-" . $partCount; + + $this->opf_manifest .= "\t\tchapterCount . "-" . $partCount . "\" href=\"" . $fileName . "-" . $partCount . "\" media-type=\"application/xhtml+xml\" />\n"; + + $this->opf_spine .= "\t\tchapterCount . "-" . $partCount . "\" />\n"; + $oneChapter = each($chapter); + } + + $this->ncx_navmap .= "\n\t\tchapterCount . "-1\" playOrder=\"" . $this->chapterCount . "\">\n\t\t\t" . $chapterName . "\n\t\t\t\n\t\t\n"; + } + return TRUE; + } + + /** + * Process external references from a HTML to the book. The chapter itself is not stored. + * the HTML is scanned for <link..., <style..., and <img tags. + * Embedded CSS styles and links will also be processed. + * Script tags are not processed, as scripting should be avoided in e-books. + * + * EPub keeps track of added files, and duplicate files referenced across multiple + * chapters, are only added once. + * + * If the $doc is a string, it is assumed to be the content of an HTML file, + * else is it assumes to be a DOMDocument. + * + * Basedir is the root dir the HTML is supposed to "live" in, used to resolve + * relative references such as <img src="../images/image.png"/> + * + * $externalReferences determins how the function will handle external references. + * + * @param mixed $doc (referenced) + * @param int $externalReferences How to handle external references, EPub::EXTERNAL_REF_IGNORE, EPub::EXTERNAL_REF_ADD or EPub::EXTERNAL_REF_REMOVE_IMAGES? Default is EPub::EXTERNAL_REF_ADD. + * @param String $baseDir Default is "", meaning it is pointing to the document root. + * @param String $htmlDir The path to the parent HTML file's directory from the root of the archive. + * + * @return Bool FALSE if uncuccessful (book is finalized or $externalReferences == EXTERNAL_REF_IGNORE). + */ + protected function processChapterExternalReferences(&$doc, $externalReferences = EPub::EXTERNAL_REF_ADD, $baseDir = "", $htmlDir = "") { + if ($this->isFinalized || $externalReferences === EPub::EXTERNAL_REF_IGNORE) { + return FALSE; + } + + $backPath = preg_replace('#[^/]+/#i', "../", $htmlDir); + $isDocAString = is_string($doc); + $xmlDoc = NULL; + + if ($isDocAString) { + $xmlDoc = new DOMDocument(); + @$xmlDoc->loadHTML($doc); + } else { + $xmlDoc = $doc; + } + + $this->processChapterStyles($xmlDoc, $externalReferences, $baseDir, $htmlDir); + $this->processChapterLinks($xmlDoc, $externalReferences, $baseDir, $htmlDir, $backPath); + $this->processChapterImages($xmlDoc, $externalReferences, $baseDir, $htmlDir, $backPath); + + if ($isDocAString) { + $html = $xmlDoc->saveXML(); + + $head = $xmlDoc->getElementsByTagName("head"); + $body = $xmlDoc->getElementsByTagName("body"); + + $xml = new DOMDocument('1.0', "utf-8"); + $xml->lookupPrefix("http://www.w3.org/1999/xhtml"); + $xml->preserveWhiteSpace = FALSE; + $xml->formatOutput = TRUE; + + $xml2Doc = new DOMDocument('1.0', "utf-8"); + $xml2Doc->lookupPrefix("http://www.w3.org/1999/xhtml"); + $xml2Doc->loadXML("\n\n\n\n"); + $html = $xml2Doc->getElementsByTagName("html")->item(0); + $html->appendChild($xml2Doc->importNode($head->item(0), TRUE)); + $html->appendChild($xml2Doc->importNode($body->item(0), TRUE)); + + // force pretty printing and correct formatting, should not be needed, but it is. + $xml->loadXML($xml2Doc->saveXML()); + $doc = $xml->saveXML(); + } + return TRUE; + } + + /** + * Process images referenced from an CSS file to the book. + * + * $externalReferences determins how the function will handle external references. + * + * @param String $cssFile (referenced) + * @param int $externalReferences How to handle external references, EPub::EXTERNAL_REF_IGNORE, EPub::EXTERNAL_REF_ADD or EPub::EXTERNAL_REF_REMOVE_IMAGES? Default is EPub::EXTERNAL_REF_ADD. + * @param String $baseDir Default is "", meaning it is pointing to the document root. + * @param String $cssDir The of the CSS file's directory from the root of the archive. + * + * @return Bool FALSE if uncuccessful (book is finalized or $externalReferences == EXTERNAL_REF_IGNORE). + */ + protected function processCSSExternalReferences(&$cssFile, $externalReferences = EPub::EXTERNAL_REF_ADD, $baseDir = "", $cssDir = "") { + if ($this->isFinalized || $externalReferences === EPub::EXTERNAL_REF_IGNORE) { + return FALSE; + } + + $backPath = preg_replace('#[^/]+/#i', "../", $cssDir); + preg_match_all('#url\s*\([\'\"\s]*(.+?)[\'\"\s]*\)#im', $cssFile, $imgs, PREG_SET_ORDER); + + $itemCount = count($imgs); + for ($idx = 0; $idx < $itemCount; $idx++) { + $img = $imgs[$idx]; + if ($externalReferences === EPub::EXTERNAL_REF_REMOVE_IMAGES || $externalReferences === EPub::EXTERNAL_REF_REPLACE_IMAGES) { + $cssFile = str_replace($img[0], "", $cssFile); + } else { + $source = $img[1]; + + $pathData = pathinfo($source); + $internalSrc = $pathData['basename']; + $internalPath = ""; + $isSourceExternal = FALSE; + + if ($this->resolveImage($source, $internalPath, $internalSrc, $isSourceExternal, $baseDir, $cssDir, $backPath)) { + $cssFile = str_replace($img[0], "url('" . $backPath . $internalPath . "')", $cssFile); + } else if ($isSourceExternal) { + $cssFile = str_replace($img[0], "", $cssFile); // External image is missing + } // else do nothing, if the image is local, and missing, assume it's been generated. + } + } + return TRUE; + } + + /** + * Process style tags in a DOMDocument. Styles will be passed as CSS files and reinserted into the document. + * + * @param DOMDocument $xmlDoc (referenced) + * @param int $externalReferences How to handle external references, EPub::EXTERNAL_REF_IGNORE, EPub::EXTERNAL_REF_ADD or EPub::EXTERNAL_REF_REMOVE_IMAGES? Default is EPub::EXTERNAL_REF_ADD. + * @param String $baseDir Default is "", meaning it is pointing to the document root. + * @param String $htmlDir The path to the parent HTML file's directory from the root of the archive. + * + * @return Bool FALSE if uncuccessful (book is finalized or $externalReferences == EXTERNAL_REF_IGNORE). + */ + protected function processChapterStyles(&$xmlDoc, $externalReferences = EPub::EXTERNAL_REF_ADD, $baseDir = "", $htmlDir = "") { + if ($this->isFinalized || $externalReferences === EPub::EXTERNAL_REF_IGNORE) { + return FALSE; + } + // process inlined CSS styles in style tags. + $styles = $xmlDoc->getElementsByTagName("style"); + $styleCount = $styles->length; + for ($styleIdx = 0; $styleIdx < $styleCount; $styleIdx++) { + $style = $styles->item($styleIdx); + $styleData = $style->nodeValue; + + $styleData = preg_replace('#[/\*\s]*\<\!\[CDATA\[[\s\*/]*#im', "", $styleData); + $styleData = preg_replace('#[/\*\s]*\]\]\>[\s\*/]*#im', "", $styleData); + + $this->processCSSExternalReferences($styleData, $externalReferences, $baseDir, $htmlDir); + $style->nodeValue = "\n" . trim($styleData) . "\n"; + } + return TRUE; + } + + /** + * Process link tags in a DOMDocument. Linked files will be loaded into the archive, and the link src will be rewritten to point to that location. + * Link types text/css will be passed as CSS files. + * + * @param DOMDocument $xmlDoc (referenced) + * @param int $externalReferences How to handle external references, EPub::EXTERNAL_REF_IGNORE, EPub::EXTERNAL_REF_ADD or EPub::EXTERNAL_REF_REMOVE_IMAGES? Default is EPub::EXTERNAL_REF_ADD. + * @param String $baseDir Default is "", meaning it is pointing to the document root. + * @param String $htmlDir The path to the parent HTML file's directory from the root of the archive. + * @param String $backPath The path to get back to the root of the archive from $htmlDir. + * + * @return Bool FALSE if uncuccessful (book is finalized or $externalReferences == EXTERNAL_REF_IGNORE). + */ + protected function processChapterLinks(&$xmlDoc, $externalReferences = EPub::EXTERNAL_REF_ADD, $baseDir = "", $htmlDir = "", $backPath = "") { + if ($this->isFinalized || $externalReferences === EPub::EXTERNAL_REF_IGNORE) { + return FALSE; + } + // process link tags. + $links = $xmlDoc->getElementsByTagName("link"); + $linkCount = $links->length; + for ($linkIdx = 0; $linkIdx < $linkCount; $linkIdx++) { + $link = $links->item($linkIdx); + $source = $link->attributes->getNamedItem("href")->nodeValue; + $sourceData = NULL; + + $pathData = pathinfo($source); + $internalSrc = $pathData['basename']; + + if (preg_match('#^(http|ftp)s?://#i', $source) == 1) { + $urlinfo = parse_url($source); + + if (strpos($urlinfo['path'], $baseDir."/") !== FALSE) { + $internalSrc = substr($urlinfo['path'], strpos($urlinfo['path'], $baseDir."/") + strlen($basedir) + 1); + } + + @$sourceData = file_get_contents($source); + } else if (strpos($source, "/") === 0) { + @$sourceData = file_get_contents($this->docRoot . $source); + } else { + @$sourceData = file_get_contents($this->docRoot . $baseDir . "/" . $source); + } + + if (!empty($sourceData)) { + if (!array_key_exists($internalSrc, $this->fileList)) { + $mime = $link->attributes->getNamedItem("type")->nodeValue; + if (empty($mime)) { + $mime = "text/plain"; + } + if ($mime == "text/css") { + $this->processCSSExternalReferences($sourceData, $externalReferences, $baseDir, $htmlDir); + $this->addCSSFile($internalSrc, $internalSrc, $sourceData, EPub::EXTERNAL_REF_IGNORE, $baseDir); + $link->setAttribute("href", $backPath . $internalSrc); + } else { + $this->addFile($internalSrc, $internalSrc, $sourceData, $mime); + } + $this->fileList[$internalSrc] = $source; + } else { + $link->setAttribute("href", $backPath . $internalSrc); + } + } // else do nothing, if the link is local, and missing, assume it's been generated. + } + return TRUE; + } + + /** + * Process img tags in a DOMDocument. + * $externalReferences will determine what will happen to these images, and the img src will be rewritten accordingly. + * + * @param DOMDocument $xmlDoc (referenced) + * @param int $externalReferences How to handle external references, EPub::EXTERNAL_REF_IGNORE, EPub::EXTERNAL_REF_ADD or EPub::EXTERNAL_REF_REMOVE_IMAGES? Default is EPub::EXTERNAL_REF_ADD. + * @param String $baseDir Default is "", meaning it is pointing to the document root. + * @param String $htmlDir The path to the parent HTML file's directory from the root of the archive. + * @param String $backPath The path to get back to the root of the archive from $htmlDir. + * + * @return Bool FALSE if uncuccessful (book is finalized or $externalReferences == EXTERNAL_REF_IGNORE). + */ + protected function processChapterImages(&$xmlDoc, $externalReferences = EPub::EXTERNAL_REF_ADD, $baseDir = "", $htmlDir = "", $backPath = "") { + if ($this->isFinalized || $externalReferences === EPub::EXTERNAL_REF_IGNORE) { + return FALSE; + } + // process img tags. + $postProcDomElememts = array(); + $images = $xmlDoc->getElementsByTagName("img"); + $itemCount = $images->length; + for ($idx = 0; $idx < $itemCount; $idx++) { + $img = $images->item($idx); + if ($externalReferences === EPub::EXTERNAL_REF_REMOVE_IMAGES) { + $postProcDomElememts[] = $img; + } else if ($externalReferences === EPub::EXTERNAL_REF_REPLACE_IMAGES) { + $postProcDomElememts[] = array($img, $this->createDomFragment($xmlDoc, "[image]")); + } else { + $source = $img->attributes->getNamedItem("src")->nodeValue; + + $pathData = pathinfo($source); + $internalSrc = $pathData['basename']; + $internalPath = ""; + $isSourceExternal = FALSE; + + if ($this->resolveImage($source, $internalPath, $internalSrc, $isSourceExternal, $baseDir, $htmlDir, $backPath)) { + $img->setAttribute("src", $backPath . $internalPath); + } else if ($isSourceExternal) { + $postProcDomElememts[] = $img; // External image is missing + } // else do nothing, if the image is local, and missing, assume it's been generated. + } + } + + foreach ($postProcDomElememts as $target) { + if (is_array($target)) { + $target[0]->parentNode->replaceChild($target[1], $target[0]); + } else { + $target->parentNode->removeChild($target); + } + } + return TRUE; + } + + /** + * Resolve an image src and determine it's target location and add it to the book. + * + * @param String $source Image Source link. + * @param String $internalPath (referenced) Return value, will be set to the target path and name in the book. + * @param String $internalSrc (referenced) Return value, will be set to the target name in the book. + * @param String $isSourceExternal (referenced) Return value, will be set to TRUE if the image originated from a full URL. + * @param String $baseDir Default is "", meaning it is pointing to the document root. + * @param String $htmlDir The path to the parent HTML file's directory from the root of the archive. + * @param String $backPath The path to get back to the root of the archive from $htmlDir. + */ + protected function resolveImage($source, &$internalPath, &$internalSrc, &$isSourceExternal, $baseDir = "", $htmlDir = "", $backPath = "") { + if ($this->isFinalized) { + return FALSE; + } + $imageData = NULL; + + if (preg_match('#^(http|ftp)s?://#i', $source) == 1) { + $urlinfo = parse_url($source); + + if (strpos($urlinfo['path'], $baseDir."/") !== FALSE) { + $internalSrc = substr($urlinfo['path'], strpos($urlinfo['path'], $baseDir."/") + strlen($basedir) + 1); + } + $internalPath = $urlinfo["scheme"] . "/" . $urlinfo["host"] . "/" . pathinfo($urlinfo["path"], PATHINFO_DIRNAME); + $isSourceExternal = TRUE; + $imageData = $this->getImage($source); + } else if (strpos($source, "/") === 0) { + $internalPath = pathinfo($source, PATHINFO_DIRNAME); + $imageData = $this->getImage($this->docRoot . $source); + } else { + $internalPath = $htmlDir . "/" . preg_replace('#^[/\.]+#', '', pathinfo($source, PATHINFO_DIRNAME)); + $imageData = $this->getImage($this->docRoot . $baseDir . "/" . $source); + } + if ($imageData !== FALSE) { + $internalPath = Zip::getRelativePath("images/" . $internalPath . "/" . $internalSrc); + if (!array_key_exists($internalPath, $this->fileList)) { + $this->addFile($internalPath, "i_" . $internalSrc, $imageData['image'], $imageData['mime']); + $this->fileList[$internalPath] = $source; + } + return TRUE; + } + return FALSE; + } + + /** + * Add a cover image to the book. + * + * The styling and structure of the generated XHTML is heavily inspired by the XHTML generated by Calibre. + * + * @param String $fileName Filename to use for the image, must be unique for the book. + * @param String $imageData Binary image data + * @param String $mimetype Image mimetype, such as "image/jpeg" or "image/png". + * @return bool $success + */ + function setCoverImage($fileName, $imageData = NULL, $mimetype = NULL) { + if ($this->isFinalized || $this->isCoverImageSet || array_key_exists("CoverPage.html", $this->fileList)) { + return FALSE; + } + + if ($imageData == NULL) { // assume $fileName is the valig file path. + $image = $this->getImage($this->docRoot . $fileName); + $imageData = $image['image']; + $mimetype = $image['mime']; + } + $path = pathinfo($this->docRoot . $fileName); + $imgPath = "images/" . $path["basename"]; + + $coverPage = "\n\n\t\n\t\t\n\t\tCover Image\n\t\t\n\t\n\t\n\t\t
\n\t\t\t\"Cover\n\t\t
\n\t\n\n"; + + $this->zip->addFile($coverPage, "CoverPage.html"); + $this->zip->addFile($imageData, $imgPath); + $this->fileList["CoverPage.html"] = "CoverPage.html"; + $this->fileList[$imgPath] = $fileName; + + $this->opf_manifest = "\t\t\n" . $this->opf_manifest; + $this->opf_manifest = "\t\t\n" . $this->opf_manifest; + $this->opf_spine = "\t\t\n" . $this->opf_spine; + $this->opf_guide .= "\t\t\n"; + $this->ncx_navmap = "\n\t\t\n\t\t\tCover\n\t\t\t\n\t\t\n" . $this->ncx_navmap; + + $this->isCoverImageSet = TRUE; + return TRUE; + } + + /** + * Get Book Chapter count. + * + * @access public + * @return number of chapters + */ + function getChapterCount() { + return $this->chapterCount; + } + + /** + * Book title, mandatory. + * + * Used for the dc:title metadata parameter in the OPF file as well as the DocTitle attribute in the NCX file. + * + * @param string $title + * @access public + * @return bool $success + */ + function setTitle($title) { + if ($this->isFinalized) { + return FALSE; + } + $this->title = $title; + return TRUE; + } + + /** + * Get Book title. + * + * @access public + * @return $title + */ + function getTitle() { + return $this->title; + } + + /** + * Book language, mandatory + * + * Use the RFC3066 Language codes, such as "en", "da", "fr" etc. + * Defaults to "en". + * + * Used for the dc:language metadata parameter in the OPF file. + * + * @param string $language + * @access public + * @return bool $success + */ + function setLanguage($language) { + if ($this->isFinalized || mb_strlen($language) != 2) { + return FALSE; + } + $this->language = $language; + return TRUE; + } + + /** + * Get Book language. + * + * @access public + * @return $language + */ + function getLanguage() { + return $this->language; + } + + /** + * Unique book identifier, mandatory. + * Use the URI, or ISBN if available. + * + * An unambiguous reference to the resource within a given context. + * + * Recommended best practice is to identify the resource by means of a + * string conforming to a formal identification system. + * + * Used for the dc:identifier metadata parameter in the OPF file, as well + * as dtb:uid in the NCX file. + * + * Identifier type should only be: + * EPub::IDENTIFIER_URI + * EPub::IDENTIFIER_ISBN + * EPub::IDENTIFIER_UUID + * + * @param string $identifier + * @param string $identifierType + * @access public + * @return bool $success + */ + function setIdentifier($identifier, $identifierType) { + if ($this->isFinalized || ($identifierType !== EPub::IDENTIFIER_URI && $identifierType !== EPub::IDENTIFIER_ISBN && $identifierType !== EPub::IDENTIFIER_UUID)) { + return FALSE; + } + $this->identifier = $identifier; + $this->identifierType = $identifierType; + return TRUE; + } + + /** + * Get Book identifier. + * + * @access public + * @return $identifier + */ + function getIdentifier() { + return $this->identifier; + } + + /** + * Get Book identifierType. + * + * @access public + * @return $identifierType + */ + function getIdentifierType() { + return $this->identifierType; + } + + /** + * Book description, optional. + * + * An account of the resource. + * + * Description may include but is not limited to: an abstract, a table of + * contents, a graphical representation, or a free-text account of the + * resource. + * + * Used for the dc:source metadata parameter in the OPF file + * + * @param string $description + * @access public + * @return bool $success + */ + function setDescription($description) { + if ($this->isFinalized) { + return FALSE; + } + $this->description = $description; + return TRUE; + } + + /** + * Get Book description. + * + * @access public + * @return $description + */ + function getDescription() { + return $this->description; + } + + /** + * Book author or creator, optional. + * The $authorSortKey is basically how the name is to be sorted, usually + * it's "Lastname, First names" where the $author is the straight + * "Firstnames Lastname" + * + * An entity primarily responsible for making the resource. + * + * Examples of a Creator include a person, an organization, or a service. + * Typically, the name of a Creator should be used to indicate the entity. + * + * Used for the dc:creator metadata parameter in the OPF file and the + * docAuthor attribure in the NCX file. + * The sort key is used for the opf:file-as attribute in dc:creator. + * + * @param string $author + * @param string $authorSortKey + * @access public + * @return bool $success + */ + function setAuthor($author, $authorSortKey) { + if ($this->isFinalized) { + return FALSE; + } + $this->author = $author; + $this->authorSortKey = $authorSortKey; + return TRUE; + } + + /** + * Get Book author. + * + * @access public + * @return $author + */ + function getAuthor() { + return $this->author; + } + + /** + * Publisher Information, optional. + * + * An entity responsible for making the resource available. + * + * Examples of a Publisher include a person, an organization, or a service. + * Typically, the name of a Publisher should be used to indicate the entity. + * + * Used for the dc:publisher and dc:relation metadata parameters in the OPF file. + * + * @param string $publisherName + * @param string $publisherURL + * @access public + * @return bool $success + */ + function setPublisher($publisherName, $publisherURL) { + if ($this->isFinalized) { + return FALSE; + } + $this->publisherName = $publisherName; + $this->publisherURL = $publisherURL; + return TRUE; + } + + /** + * Get Book publisherName. + * + * @access public + * @return $publisherName + */ + function getPublisherName() { + return $this->publisherName; + } + + /** + * Get Book publisherURL. + * + * @access public + * @return $publisherURL + */ + function getPublisherURL() { + return $this->publisherURL; + } + + /** + * Release date, optional. If left blank, the time of the finalization will + * be used. + * + * A point or period of time associated with an event in the lifecycle of + * the resource. + * + * Date may be used to express temporal information at any level of + * granularity. Recommended best practice is to use an encoding scheme, + * such as the W3CDTF profile of ISO 8601 [W3CDTF]. + * + * Used for the dc:date metadata parameter in the OPF file + * + * @param long $timestamp + * @access public + * @return bool $success + */ + function setDate($timestamp) { + if ($this->isFinalized) { + return FALSE; + } + $this->date = $timestamp; + return TRUE; + } + + /** + * Get Book date. + * + * @access public + * @return $date + */ + function getDate() { + return $this->date; + } + + /** + * Book (copy)rights, optional. + * + * Information about rights held in and over the resource. + * + * Typically, rights information includes a statement about various + * property rights associated with the resource, including intellectual + * property rights. + * + * Used for the dc:rights metadata parameter in the OPF file + * + * @param string $rightsText + * @access public + * @return bool $success + */ + function setRights($rightsText) { + if ($this->isFinalized) { + return FALSE; + } + $this->rights = $rightsText; + return TRUE; + } + + /** + * Get Book rights. + * + * @access public + * @return $rights + */ + function getRights() { + return $this->rights; + } + + /** + * Set book Subject. + * + * The topic of the resource. + * + * Typically, the subject will be represented using keywords, key phrases, + * or classification codes. Recommended best practice is to use a + * controlled vocabulary. To describe the spatial or temporal topic of the + * resource, use the Coverage element. + * + * @param String $subject + */ + function setSubject($subject) { + if ($this->isFinalized) { + return; + } + $this->subject = $subject; + } + + /** + * Get the book subject. + * + * @return String The Subject. + */ + function getSubject() { + return $this->subject; + } + + /** + * Book source URL, optional. + * + * A related resource from which the described resource is derived. + * + * The described resource may be derived from the related resource in whole + * or in part. Recommended best practice is to identify the related + * resource by means of a string conforming to a formal identification system. + * + * Used for the dc:source metadata parameter in the OPF file + * + * @param string $sourceURL + * @access public + * @return bool $success + */ + function setSourceURL($sourceURL) { + if ($this->isFinalized) { + return FALSE; + } + $this->sourceURL = $sourceURL; + return TRUE; + } + + /** + * Get Book sourceURL. + * + * @access public + * @return $sourceURL + */ + function getSourceURL() { + return $this->sourceURL; + } + + /** + * Coverage, optional. + * + * The spatial or temporal topic of the resource, the spatial applicability + * of the resource, or the jurisdiction under which the resource is relevant. + * + * Spatial topic and spatial applicability may be a named place or a location + * specified by its geographic coordinates. Temporal topic may be a named + * period, date, or date range. A jurisdiction may be a named administrative + * entity or a geographic place to which the resource applies. Recommended + * best practice is to use a controlled vocabulary such as the Thesaurus of + * Geographic Names [TGN]. Where appropriate, named places or time periods + * can be used in preference to numeric identifiers such as sets of + * coordinates or date ranges. + * + * Used for the dc:coverage metadata parameter in the OPF file + * + * @param string $coverage + * @access public + * @return bool $success + */ + function setCoverage($coverage) { + if ($this->isFinalized) { + return FALSE; + } + $this->coverage = $coverage; + return TRUE; + } + + /** + * Get Book coverage. + * + * @access public + * @return $coverage + */ + function getCoverage() { + return $this->coverage; + } + + /** + * Set book Relation. + * + * A related resource. + * + * Recommended best practice is to identify the related resource by means + * of a string conforming to a formal identification system. + * + * @param String $relation + */ + function setRelation($relation) { + if ($this->isFinalized) { + return; + } + $this->relation = $relation; + } + + /** + * Get the book relation. + * + * @return String The relation. + */ + function getRelation() { + return $this->relation; + } + + /** + * Set book Generator. + * + * The generator is a meta tag added to the ncx file, it is not visible + * from within the book, but is a kind of electronic watermark. + * + * @param String $generator + */ + function setGenerator($generator) { + if ($this->isFinalized) { + return; + } + $this->generator = $generator; + } + + /** + * Get the book relation. + * + * @return String The generator identity string. + */ + function getGenerator() { + return $this->generator; + } + + /** + * Set ePub date formate to the short yyyy-mm-dd form, for compliance with + * a bug in EpubCheck, prior to its version 1.1. + * + * The latest version of ePubCheck can be obtained here: + * http://code.google.com/p/epubcheck/ + * + * @access public + * @return bool $success + */ + function setShortDateFormat() { + if ($this->isFinalized) { + return FALSE; + } + $this->dateformat = $this->dateformatShort; + return TRUE; + } + + /** + * @Deprecated + */ + function setIgnoreEmptyBuffer($ignoreEmptyBuffer = TRUE) { + return TRUE; + } + + /** + * Get Book status. + * + * @access public + * @return boolean + */ + function isFinalized() { + return $this->isFinalized; + } + + /** + * Check for mandatory parameters and finalize the e-book. + * Once finalized, the book is locked for further additions. + * + * @return bool $success + */ + function finalize() { + if ($this->isFinalized || $this->chapterCount == 0 || empty($this->title) || empty($this->language)) { + return FALSE; + } + + if (empty($this->identifier) || empty($this->identifierType)) { + $this->setIdentifier($this->createUUID(4), EPub::IDENTIFIER_UUID); + } + + if ($this->date == 0) { + $this->date = time(); + } + + if(empty($this->sourceURL)) { + $this->sourceURL = $this->getCurrentPageURL(); + } + + if(empty($this->publisherURL)) { + $this->sourceURL = $this->getCurrentServerURL(); + } + + // Generate OPF data: + $this->opf = "\n\n\t\n\t\t" + . $this->title . "\n\t\t" + . $this->language . "\n\t\tidentifierType . "\">" + . $this->identifier . "\n"; + + if (!empty($this->description)) { + $this->opf .= "\t\t" . $this->description . "\n"; + } + + if (!empty($this->publisherName)) { + $this->opf .= "\t\t" . $this->publisherName . "\n"; + } + + if (!empty($this->publisherURL)) { + $this->opf .= "\t\t" . $this->publisherURL . "\n"; + } + + if (!empty($this->author)) { + $this->opf .= "\t\tauthorSortKey)) { + $this->opf .= " opf:file-as=\"" . $this->authorSortKey . "\""; + } + $this->opf .= " opf:role=\"aut\">" . $this->author . "\n"; + } + + $this->opf .= "\t\t" . gmdate($this->dateformat, $this->date) . "\n"; + + if (!empty($this->rights)) { + $this->opf .= "\t\t" . $this->rights . "\n"; + } + + if(!empty($this->subject)) { + $this->opf .= "\t\t" . $this->subject . "\n"; + } + + if(!empty($this->coverage)) { + $this->opf .= "\t\t" . $this->coverage . "\n"; + } + + if (!empty($this->sourceURL)) { + $this->opf .= "\t\t" . $this->sourceURL . "\n"; + } + + if(!empty($this->relation)) { + $this->opf .= "\t\t" . $this->relation . "\n"; + } + + if ($this->isCoverImageSet) { + $this->opf .= "\t\t\n"; + } + + if ($this->EPubMark) { + $this->ncx .= "\t\t\n"; + } + if (!empty($this->generator)) { + $this->ncx .= "\t\tgenerator . "\" />\n"; + } + + $this->opf .= "\t\n\n\t\n" . $this->opf_manifest . "\t\n\n\t\n" . $this->opf_spine . "\t\n"; + + if (!empty($this->opf_guide)) { + $this->opf .= "\n\t\n" . $this->opf_guide . "\t\n"; + } + + $this->opf .= "\n"; + + $this->ncx = "\n\n\n\t\n" + . "\t\tidentifier . "\" />\n\t\t\n\t\t\n\t\t\n"; + + if ($this->EPubMark) { + $this->ncx .= "\t\t\n"; + } + if (!empty($this->generator)) { + $this->ncx .= "\t\tgenerator . "\" />\n"; + } + $this->ncx .= "\t\n\n\t\n\t\t" + . $this->title . "\n\t\n\n"; + + if (!empty($this->author)) { + $this->ncx .= "\t\n\t\t" . $this->author . "\n\t\n\n"; + } + + $this->ncx .= "\t\n" . $this->ncx_navmap . "\t\n\n"; + + $this->zip->addFile($this->opf, "book.opf"); + $this->zip->addFile($this->ncx, "book.ncx"); + $this->opf = ""; + $this->ncx = ""; + + $this->isFinalized = TRUE; + return TRUE; + } + + /** + * Return the finalized book. + * + * @return String with the book in binary form. + */ + function getBook() { + if(!$this->isFinalized) { + $this->finalize(); + } + + return $this->zip->getZipData(); + } + + /** + * Return the finalized book. + * + * @return String + */ + function getBookSize() { + if(!$this->isFinalized) { + $this->finalize(); + } + + return $this->zip->getArchiveSize(); + } + + /** + * Send the book as a zip download + * + * Sending will fail if the output buffer is in use. You can override this limit by + * calling setIgnoreEmptyBuffer(TRUE), though the function will still fail if that + * buffer is not empty. + * + * @param String $fileName The name of the book without the .epub at the end. + * @return bool $success + */ + function sendBook($fileName) { + if(!$this->isFinalized) { + $this->finalize(); + } + + if (stripos(strrev($fileName), "bupe.") !== 0) { + $fileName .= ".epub"; + } + + return $this->zip->sendZip($fileName, "application/epub+zip"); + } + + /** + * Generates an UUID. + * + * Default version (4) will generate a random UUID, version 3 will URL based UUID. + * + * Added for convinience + * + * @param $version UUID version to retrieve, See lib.uuid.manual.html for details. + * @return string The formatted uuid + */ + function createUUID($version = 4, $url = NULL) { + include_once("lib.uuid.php"); + return UUID::mint($version, $url, UUID::nsURL); + } + + /** + * Get the url of the current page. + * Example use: Default Source URL + * + * $return Page URL as a string. + */ + function getCurrentPageURL() { + return null; + + $pageURL = 'http'; + if ($_SERVER["HTTPS"] == "on") { + $pageURL .= "s"; + } + $pageURL .= "://" . $_SERVER["SERVER_NAME"]; + if ($_SERVER["SERVER_PORT"] != "80") { + $pageURL .= ":" . $_SERVER["SERVER_PORT"]; + } + $pageURL .= $_SERVER["REQUEST_URI"]; + return $pageURL; + } + + /** + * Get the url of the server. + * Example use: Default Publisher URL + * + * $return Server URL as a string. + */ + function getCurrentServerURL() { + return null; + + $serverURL = 'http'; + if ($_SERVER["HTTPS"] == "on") { + $serverURL .= "s"; + } + $serverURL .= "://" . $_SERVER["SERVER_NAME"]; + if ($_SERVER["SERVER_PORT"] != "80") { + $serverURL .= ":" . $_SERVER["SERVER_PORT"]; + } + return $serverURL . '/'; + } + + /** + * Get an image from a file or url, return it resized if the image exceeds the $maxImageWidth or $maxImageHeight directives. + * + * The return value is an array. + * ['width'] is the width of the image. + * ['height'] is the height of the image. + * ['mime'] is the mime type of the image. Resized images are always in jpeg format. + * ['image'] is the image data. + * + * @param String $source path or url to file. + * $return array + */ + function getImage($source) { + list($width, $height, $type, $attr) = getimagesize($source); + $mime = image_type_to_mime_type($type); + + if ($width == 0 || $height == 0) { + return FALSE; + } + + @$image = file_get_contents($source); + if ($image === FALSE) { + return FALSE; + } + $ratio = 1; + + if ($this->isGdInstalled) { + if ($width > $this->maxImageWidth) { + $ratio = $this->maxImageWidth/$width; + } + if ($height*$ratio > $this->maxImageHeight) { + $ratio = $this->maxImageHeight/$height; + } + if ($ratio < 1) { + $image_o = imagecreatefromstring($image); + $image_p = imagecreatetruecolor($width*$ratio, $height*$ratio); + imagecopyresampled($image_p, $image_o, 0, 0, 0, 0, ($width*$ratio), ($height*$ratio), $width, $height); + ob_start(); + imagejpeg($image_p,NULL,80); + $image = ob_get_contents(); + ob_end_clean(); + imagedestroy($image_o); + imagedestroy($image_p); + $mime = "image/jpeg"; + } + } + $rv = array(); + $rv['width'] = $width*$ratio; + $rv['height'] = $height*$ratio; + $rv['mime'] = $mime; + $rv['image'] = $image; + + return $rv; + } + + /** + * Helper function to create a DOM fragment with given markup. + * + * @author Adam Schmalhofer + * + * @param DOMDocument $dom + * @param String $markup + * @return DOMNode fragment in a node. + */ + protected function createDomFragment($dom, $markup) { + $node = $dom->createDocumentFragment(); + $node->appendXML($markup); + return $node; + } + + /** + * Retrieve an array of file names currently added to the book. + * $key is the filename used in the book + * $value is the original filename, will be the same as $key for most entries + * + * @return array file list + */ + function getFileList() { + return $this->fileList; + } + + /** + * Clean up a path + * If the path starts with a "/", it is deemed absolute and any /../ in the beginning is stripped off. + * The returned path will not end in a "/". + * + * @param String $relPath The path to clean up + * @return String the clean path + * @deprecated Redundant, please use Zip::getRelativePath($relPath) instead. + */ + function relPath($relPath) { + return Zip::getRelativePath($relPath); + } + + /** + * Set default chapter target size. + * Default is 250000 bytes, and minimum is 10240 bytes. + * + * @param $size + * @return void + */ + function setSplitSize($size) { + $this->splitDefaultSize = (int)$size; + if ($size < 10240) { + $this->splitDefaultSize = 10240; // Making the file smaller than 10k is not a good idea. + } + } + + /** + * Get the chapter target size. + * + * @return $size + */ + function getSplitSize() { + return $this->splitDefaultSize; + } +} +?> \ No newline at end of file diff --git a/ActividadesWP/v5/inc/epub/EPubChapterSplitter.class.php b/ActividadesWP/v5/inc/epub/EPubChapterSplitter.class.php new file mode 100644 index 0000000..0107fe6 --- /dev/null +++ b/ActividadesWP/v5/inc/epub/EPubChapterSplitter.class.php @@ -0,0 +1,178 @@ +splitDefaultSize = (int)$size; + if ($size < 10240) { + $this->splitDefaultSize = 10240; // Making the file smaller than 10k is not a good idea. + } + } + + /** + * Get the chapter target size. + * + * @return $size + */ + function getSplitSize() { + return $this->splitDefaultSize; + } + + /** + * Split $chapter into multiple parts. + * + * The search string can either be a regular string or a PHP PECL Regular Expression pattern as defined here: http://www.php.net/manual/en/pcre.pattern.php + * If the search string is a regular string, the matching will be for lines in the HTML starting with the string given + * + * @param String $chapter XHTML file + * @param Bool $splitOnSearchString Split on chapter boundaries, Splitting on search strings disables the split size check. + * @param String $searchString Chapter string to search for can be fixed text, or a regular expression pattern. + * + * @return array with 1 or more parts + */ + function splitChapter($chapter, $splitOnSearchString = false, $searchString = '/^Chapter\\ /i') { + $chapterData = array(); + $isSearchRegexp = $splitOnSearchString && (preg_match('#^(\D|\S|\W).+\1[imsxeADSUXJu]*$#m', $searchString) == 1); + if ($splitOnSearchString && !$isSearchRegexp) { + $searchString = '#^<.+?>' . preg_quote($searchString, '#') . "#"; + } + + if (!$splitOnSearchString && strlen($chapter) <= $this->splitDefaultSize) { + return array($chapter); + } + + $xmlDoc = new DOMDocument(); + @$xmlDoc->loadHTML($chapter); + + $head = $xmlDoc->getElementsByTagName("head"); + $body = $xmlDoc->getElementsByTagName("body"); + + $htmlPos = stripos($chapter, "", $htmlPos); + $newXML = substr($chapter, 0, $htmlEndPos+1) . "\n"; + $headerLength = strlen($newXML); + + $files = array(); + $chapterNames = array(); + $domDepth = 0; + $domPath = array(); + $domClonedPath = array(); + + $curFile = $xmlDoc->createDocumentFragment(); + $files[] = $curFile; + $curParent = $curFile; + $curSize = 0; + + $bodyLen = strlen($xmlDoc->saveXML($body->item(0))); + $headLen = strlen($xmlDoc->saveXML($head->item(0))) + $headerLength; + + $partSize = $this->splitDefaultSize - $headLen; + + if ($bodyLen > $partSize) { + $parts = ceil($bodyLen / $partSize); + $partSize = ($bodyLen / $parts) - $headLen; + } + + $node = $body->item(0)->firstChild; + + do { + $nodeData = $xmlDoc->saveXML($node); + $nodeLen = strlen($nodeData); + + if ($nodeLen > $partSize && $node->hasChildNodes()) { + $domPath[] = $node; + $domClonedPath[] = $node->cloneNode(false); + $domDepth++; + + $node = $node->firstChild; + } + + $node2 = $node->nextSibling; + + if ($node != null && $node->nodeName != "#text") { + $doSplit = false; + if ($splitOnSearchString) { + $doSplit = preg_match($searchString, $nodeData) == 1; + if ($doSplit) { + $chapterNames[] = trim($nodeData); + } + } + + if ($curSize > 0 && ($doSplit || (!$splitOnSearchString && $curSize + $nodeLen > $partSize))) { + $curFile = $xmlDoc->createDocumentFragment(); + $files[] = $curFile; + $curParent = $curFile; + if ($domDepth > 0) { + reset($domPath); + reset($domClonedPath); + $oneDomClonedPath = each($domClonedPath); + while ($oneDomClonedPath) { + list($k, $v) = $oneDomClonedPath; + $newParent = $v->cloneNode(false); + $curParent->appendChild($newParent); + $curParent = $newParent; + $oneDomClonedPath = each($domClonedPath); + } + } + $curSize = strlen($xmlDoc->saveXML($curFile)); + } + $curParent->appendChild($node->cloneNode(true)); + $curSize += $nodeLen; + } + + $node = $node2; + while ($node == null && $domDepth > 0) { + $domDepth--; + $node = end($domPath)->nextSibling; + array_pop($domPath); + array_pop($domClonedPath); + $curParent = $curParent->parentNode; + } + } while ($node != null); + + $curFile = null; + $curSize = 0; + + $xml = new DOMDocument('1.0', $xmlDoc->xmlEncoding); + $xml->lookupPrefix("http://www.w3.org/1999/xhtml"); + $xml->preserveWhiteSpace = false; + $xml->formatOutput = true; + + for ($idx = 0; $idx < count($files); $idx++) { + $xml2Doc = new DOMDocument('1.0', $xmlDoc->xmlEncoding); + $xml2Doc->lookupPrefix("http://www.w3.org/1999/xhtml"); + $xml2Doc->loadXML($newXML); + $html = $xml2Doc->getElementsByTagName("html")->item(0); + $html->appendChild($xml2Doc->importNode($head->item(0), true)); + $body = $xml2Doc->createElement("body"); + $html->appendChild($body); + $body->appendChild($xml2Doc->importNode($files[$idx], true)); + + // force pretty printing and correct formatting, should not be needed, but it is. + $xml->loadXML($xml2Doc->saveXML()); + + $chapterData[$splitOnSearchString ? $chapterNames[$idx] : $idx] = $xml->saveXML(); + } + + return $chapterData; + } +} +?> \ No newline at end of file diff --git a/ActividadesWP/v5/inc/epub/Zip.class.php b/ActividadesWP/v5/inc/epub/Zip.class.php new file mode 100644 index 0000000..b66a585 --- /dev/null +++ b/ActividadesWP/v5/inc/epub/Zip.class.php @@ -0,0 +1,583 @@ +zipFile = tmpfile(); + } else { + $this->zipData = ""; + } + } + + function __destruct() { + if (!is_null($this->zipFile)) { + fclose($this->zipFile); + } + $this->zipData = NULL; + } + + /** + * Set Zip archive comment. + * + * @param String $newComment New comment. NULL to clear. + * @return bool $success + */ + public function setComment($newComment = NULL) { + if ($this->isFinalized) { + return FALSE; + } + $this->zipComment = $newComment; + + return TRUE; + } + + /** + * Set zip file to write zip data to. + * This will cause all present and future data written to this class to be written to this file. + * This can be used at any time, even after the Zip Archive have been finalized. Any previous file will be closed. + * Warning: If the given file already exists, it will be overwritten. + * + * @param String $fileName + * @return bool $success + */ + public function setZipFile($fileName) { + if (file_exists($fileName)) { + unlink ($fileName); + } + $fd=fopen($fileName, "x+b"); + if (!is_null($this->zipFile)) { + rewind($this->zipFile); + while(!feof($this->zipFile)) { + fwrite($fd, fread($this->zipFile, $this->streamChunkSize)); + } + + fclose($this->zipFile); + } else { + fwrite($fd, $this->zipData); + $this->zipData = NULL; + } + $this->zipFile = $fd; + + return TRUE; + } + + /** + * Add an empty directory entry to the zip archive. + * Basically this is only used if an empty directory is added. + * + * @param String $directoryPath Directory Path and name to be added to the archive. + * @param int $timestamp (Optional) Timestamp for the added directory, if omitted or set to 0, the current time will be used. + * @param String $fileComment (Optional) Comment to be added to the archive for this directory. To use fileComment, timestamp must be given. + * @return bool $success + */ + public function addDirectory($directoryPath, $timestamp = 0, $fileComment = NULL) { + if ($this->isFinalized) { + return FALSE; + } + $this->buildZipEntry($directoryPath, $fileComment, "\x00\x00", "\x00\x00", $timestamp, "\x00\x00\x00\x00", 0, 0, 16); + + return TRUE; + } + + /** + * Add a file to the archive at the specified location and file name. + * + * @param String $data File data. + * @param String $filePath Filepath and name to be used in the archive. + * @param int $timestamp (Optional) Timestamp for the added file, if omitted or set to 0, the current time will be used. + * @param String $fileComment (Optional) Comment to be added to the archive for this file. To use fileComment, timestamp must be given. + * @return bool $success + */ + public function addFile($data, $filePath, $timestamp = 0, $fileComment = NULL) { + if ($this->isFinalized) { + return FALSE; + } + + $gzType = "\x08\x00"; // Compression type 8 = deflate + $gpFlags = "\x02\x00"; // General Purpose bit flags for compression type 8 it is: 0=Normal, 1=Maximum, 2=Fast, 3=super fast compression. + $dataLength = strlen($data); + $fileCRC32 = pack("V", crc32($data)); + + $gzData = gzcompress($data); + $gzData = substr( substr($gzData, 0, strlen($gzData) - 4), 2); // gzcompress adds a 2 byte header and 4 byte CRC we can't use. + // The 2 byte header does contain useful data, though in this case the 2 parameters we'd be interrested in will always be 8 for compression type, and 2 for General purpose flag. + $gzLength = strlen($gzData); + + if ($gzLength >= $dataLength) { + $gzLength = $dataLength; + $gzData = $data; + $gzType = "\x00\x00"; // Compression type 0 = stored + $gpFlags = "\x00\x00"; // Compression type 0 = stored + } + + if (is_null($this->zipFile) && ($this->offset + $gzLength) > $this->zipMemoryThreshold) { + $this->zipFile = tmpfile(); + fwrite($this->zipFile, $this->zipData); + $this->zipData = NULL; + } + + $this->buildZipEntry($filePath, $fileComment, $gpFlags, $gzType, $timestamp, $fileCRC32, $gzLength, $dataLength, 32); + if (is_null($this->zipFile)) { + $this->zipData .= $gzData; + } else { + fwrite($this->zipFile, $gzData); + } + return TRUE; + } + + /** + * Add the content to a directory. + * + * @author Adam Schmalhofer + * @author A. Grandt + * + * @param String $realPath Path on the file system. + * @param String $zipPath Filepath and name to be used in the archive. + * @param bool $zipPath Add content recursively, default is TRUE. + */ + public function addDirectoryContent($realPath, $zipPath, $recursive = TRUE) { + $iter = new DirectoryIterator($realPath); + foreach ($iter as $file) { + if ($file->isDot()) { + continue; + } + $newRealPath = $file->getPathname(); + $newZipPath = self::pathJoin($zipPath, $file->getFilename()); + if ($file->isFile()) { + $this->addLargeFile($newRealPath, $newZipPath); + } else if ($recursive === TRUE) { + $this->addDirectoryContent($newRealPath, $newZipPath, $recursive); + } + } + } + + /** + * Add a file to the archive at the specified location and file name. + * + * @param String $dataFile File name/path. + * @param String $filePath Filepath and name to be used in the archive. + * @param int $timestamp (Optional) Timestamp for the added file, if omitted or set to 0, the current time will be used. + * @param String $fileComment (Optional) Comment to be added to the archive for this file. To use fileComment, timestamp must be given. + * @return bool $success + */ + public function addLargeFile($dataFile, $filePath, $timestamp = 0, $fileComment = NULL) { + if ($this->isFinalized) { + return FALSE; + } + + $this->openStream($filePath, $timestamp, $fileComment); + + $fh = fopen($dataFile, "rb"); + while(!feof($fh)) { + $this->addStreamData(fread($fh, $this->streamChunkSize)); + } + fclose($fh); + + $this->closeStream(); + + return TRUE; + } + + /** + * Create a stream to be used for large entries. + * + * @param String $filePath Filepath and name to be used in the archive. + * @param int $timestamp (Optional) Timestamp for the added file, if omitted or set to 0, the current time will be used. + * @param String $fileComment (Optional) Comment to be added to the archive for this file. To use fileComment, timestamp must be given. + * @return bool $success + */ + public function openStream($filePath, $timestamp = 0, $fileComment = NULL) { + if ($this->isFinalized) { + return FALSE; + } + + if (is_null($this->zipFile)) { + $this->zipFile = tmpfile(); + fwrite($this->zipFile, $this->zipData); + $this->zipData = NULL; + } + + if (strlen($this->streamFilePath) > 0) { + closeStream(); + } + $this->streamFile = tempnam(sys_get_temp_dir(), 'Zip'); + $this->streamData = gzopen($this->streamFile, "w9"); + $this->streamFilePath = $filePath; + $this->streamTimestamp = $timestamp; + $this->streamFileComment = $fileComment; + $this->streamFileLength = 0; + + return TRUE; + } + + /** + * Add data to the open stream. + * + * @param String $data + * @return $length bytes added or FALSE if the archive is finalized or there are no open stream. + */ + public function addStreamData($data) { + if ($this->isFinalized || strlen($this->streamFilePath) == 0) { + return FALSE; + } + + $length = gzwrite($this->streamData, $data, strlen($data)); + if ($length != strlen($data)) { + print "

Length mismatch

\n"; + } + $this->streamFileLength += $length; + + return $length; + } + + /** + * Close the current stream. + * + * @return bool $success + */ + public function closeStream() { + if ($this->isFinalized || strlen($this->streamFilePath) == 0) { + return FALSE; + } + + fflush($this->streamData); + gzclose($this->streamData); + + $gzType = "\x08\x00"; // Compression type 8 = deflate + $gpFlags = "\x02\x00"; // General Purpose bit flags for compression type 8 it is: 0=Normal, 1=Maximum, 2=Fast, 3=super fast compression. + + $file_handle = fopen($this->streamFile, "rb"); + $stats = fstat($file_handle); + $eof = $stats['size']; + + fseek($file_handle, $eof-8); + $fileCRC32 = fread($file_handle, 4); + $dataLength = $this->streamFileLength;//$gzl[1]; + + $gzLength = $eof-10; + $eof -= 9; + + fseek($file_handle, 10); + + $this->buildZipEntry($this->streamFilePath, $this->streamFileComment, $gpFlags, $gzType, $this->streamTimestamp, $fileCRC32, $gzLength, $dataLength, 32); + while(!feof($file_handle)) { + fwrite($this->zipFile, fread($file_handle, $this->streamChunkSize)); + } + + unlink($this->streamFile); + $this->streamFile = NULL; + $this->streamData = NULL; + $this->streamFilePath = NULL; + $this->streamTimestamp = NULL; + $this->streamFileComment = NULL; + $this->streamFileLength = 0; + + return TRUE; + } + + /** + * Close the archive. + * A closed archive can no longer have new files added to it. + * + * @return bool $success + */ + public function finalize() { + if(!$this->isFinalized) { + if (strlen($this->streamFilePath) > 0) { + $this->closeStream(); + } + $cd = implode("", $this->cdRec); + + $cdRec = $cd . $this->endOfCentralDirectory + . pack("v", sizeof($this->cdRec)) + . pack("v", sizeof($this->cdRec)) + . pack("V", strlen($cd)) + . pack("V", $this->offset); + if (!is_null($this->zipComment)) { + $cdRec .= pack("v", strlen($this->zipComment)) . $this->zipComment; + } else { + $cdRec .= "\x00\x00"; + } + + if (is_null($this->zipFile)) { + $this->zipData .= $cdRec; + } else { + fwrite($this->zipFile, $cdRec); + fflush($this->zipFile); + } + $this->isFinalized = TRUE; + $cd = NULL; + $this->cdRec = NULL; + + return TRUE; + } + return FALSE; + } + + /** + * Get the handle ressource for the archive zip file. + * If the zip haven't been finalized yet, this will cause it to become finalized + * + * @return zip file handle + */ + public function getZipFile() { + if(!$this->isFinalized) { + $this->finalize(); + } + if (is_null($this->zipFile)) { + $this->zipFile = tmpfile(); + fwrite($this->zipFile, $this->zipData); + $this->zipData = NULL; + } + rewind($this->zipFile); + + return $this->zipFile; + } + + /** + * Get the zip file contents + * If the zip haven't been finalized yet, this will cause it to become finalized + * + * @return zip data + */ + public function getZipData() { + if(!$this->isFinalized) { + $this->finalize(); + } + if (is_null($this->zipFile)) { + return $this->zipData; + } else { + rewind($this->zipFile); + $filestat = fstat($this->zipFile); + return fread($this->zipFile, $filestat['size']); + } + } + + /** + * Send the archive as a zip download + * + * @param String $fileName The name of the Zip archive, ie. "archive.zip". + * @param String $contentType Content mime type. Optional, defailts to "application/zip". + * @return bool $success + */ + function sendZip($fileName, $contentType = "application/zip") { + if(!$this->isFinalized) { + $this->finalize(); + } + + if (!headers_sent($headerFile, $headerLine) or die("

Error: Unable to send file $fileName. HTML Headers have already been sent from $headerFile in line $headerLine

")) { + if ((ob_get_contents() === FALSE || ob_get_contents() == '') or die("\n

Error: Unable to send file $fileName.epub. Output buffer contains the following text (typically warnings or errors):
" . ob_get_contents() . "

")) { + if (ini_get('zlib.output_compression')) { + ini_set('zlib.output_compression', 'Off'); + } + + header('Pragma: public'); + header("Last-Modified: " . gmdate("D, d M Y H:i:s T")); + header("Expires: 0"); + header("Accept-Ranges: bytes"); + header("Connection: close"); + header("Content-Type: " . $contentType); + header('Content-Disposition: attachment; filename="' . $fileName . '";' ); + header("Content-Transfer-Encoding: binary"); + header("Content-Length: ". $this->getArchiveSize()); + + if (is_null($this->zipFile)) { + echo $this->zipData; + } else { + rewind($this->zipFile); + + while(!feof($this->zipFile)) { + echo fread($this->zipFile, $this->streamChunkSize); + } + } + } + return TRUE; + } + return FALSE; + } + + /** + * Return the current size of the archive + * + * @return $size Size of the archive + */ + public function getArchiveSize() { + if (is_null($this->zipFile)) { + return strlen($this->zipData); + } + $filestat = fstat($this->zipFile); + + return $filestat['size']; + } + + /** + * Calculate the 2 byte dostime used in the zip entries. + * + * @param int $timestamp + * @return 2-byte encoded DOS Date + */ + private function getDosTime($timestamp = 0) { + $timestamp = (int)$timestamp; + $date = ($timestamp == 0 ? getdate() : getDate($timestamp)); + if ($date["year"] >= 1980) { + return pack("V", (($date["mday"] + ($date["mon"] << 5) + (($date["year"]-1980) << 9)) << 16) | + (($date["seconds"] >> 1) + ($date["minutes"] << 5) + ($date["hours"] << 11))); + } + return "\x00\x00\x00\x00"; + } + + /** + * Build the Zip file structures + * + * @param String $filePath + * @param String $fileComment + * @param String $gpFlags + * @param String $gzType + * @param int $timestamp + * @param string $fileCRC32 + * @param int $gzLength + * @param int $dataLength + * @param integer $extFileAttr 16 for directories, 32 for files. + */ + private function buildZipEntry($filePath, $fileComment, $gpFlags, $gzType, $timestamp, $fileCRC32, $gzLength, $dataLength, $extFileAttr) { + $filePath = str_replace("\\", "/", $filePath); + $fileCommentLength = (is_null($fileComment) ? 0 : strlen($fileComment)); + $dosTime = $this->getDosTime($timestamp); + + $zipEntry = $this->localFileHeader; + $zipEntry .= "\x14\x00"; // Version needed to extract + $zipEntry .= $gpFlags . $gzType . $dosTime. $fileCRC32; + $zipEntry .= pack("VV", $gzLength, $dataLength); + $zipEntry .= pack("v", strlen($filePath) ); // File name length + $zipEntry .= "\x00\x00"; // Extra field length + $zipEntry .= $filePath; // FileName . Extra field + + if (is_null($this->zipFile)) { + $this->zipData .= $zipEntry; + } else { + fwrite($this->zipFile, $zipEntry); + } + + $cdEntry = $this->centralFileHeader; + $cdEntry .= "\x00\x00"; // Made By Version + $cdEntry .= "\x14\x00"; // Version Needed to extract + $cdEntry .= $gpFlags . $gzType . $dosTime. $fileCRC32; + $cdEntry .= pack("VV", $gzLength, $dataLength); + $cdEntry .= pack("v", strlen($filePath)); // Filename length + $cdEntry .= "\x00\x00"; // Extra field length + $cdEntry .= pack("v", $fileCommentLength); // File comment length + $cdEntry .= "\x00\x00"; // Disk number start + $cdEntry .= "\x00\x00"; // internal file attributes + $cdEntry .= pack("V", $extFileAttr ); // External file attributes + $cdEntry .= pack("V", $this->offset ); // Relative offset of local header + $cdEntry .= $filePath; // FileName . Extra field + if (!is_null($fileComment)) { + $cdEntry .= $fileComment; // Comment + } + + $this->cdRec[] = $cdEntry; + $this->offset += strlen($zipEntry) + $gzLength; + } + + /** + * Join $file to $dir path, and clean up any excess slashes. + * + * @param String $dir + * @param String $file + */ + public static function pathJoin($dir, $file) { + if (empty($dir) || empty($file)) { + return self::getRelativePath($dir . $file); + } + return self::getRelativePath($dir . '/' . $file); + } + + /** + * Clean up a path, removing any unnecessary elements such as /./, // or redundant ../ segments. + * If the path starts with a "/", it is deemed an absolute path and any /../ in the beginning is stripped off. + * The returned path will not end in a "/". + * + * @param String $relPath The path to clean up + * @return String the clean path + */ + public static function getRelativePath($path) { + $path = preg_replace("#/+\.?/+#", "/", str_replace("\\", "/", $path)); + $dirs = explode("/", rtrim(preg_replace('#^(\./)+#', '', $path), '/')); + + $offset = 0; + $sub = 0; + $subOffset = 0; + $root = ""; + + if (empty($dirs[0])) { + $root = "/"; + $dirs = array_splice($dirs, 1); + } else if (preg_match("#[A-Za-z]:#", $dirs[0])) { + $root = strtoupper($dirs[0]) . "/"; + $dirs = array_splice($dirs, 1); + } + + $newDirs = array(); + foreach($dirs as $dir) { + if ($dir !== "..") { + $subOffset--; + $newDirs[++$offset] = $dir; + } else { + $subOffset++; + if (--$offset < 0) { + $offset = 0; + if ($subOffset > $sub) { + $sub++; + } + } + } + } + + if (empty($root)) { + $root = str_repeat("../", $sub); + } + return $root . implode("/", array_slice($newDirs, 0, $offset)); + } +} +?> \ No newline at end of file diff --git a/ActividadesWP/v5/inc/galeria.php b/ActividadesWP/v5/inc/galeria.php new file mode 100644 index 0000000..7994e65 --- /dev/null +++ b/ActividadesWP/v5/inc/galeria.php @@ -0,0 +1,76 @@ +conn = $db; + } + + /** + * List function + * + * Displays the list of messages with it's pertinent variables + * + */ + function gallery_list(){ + $sql = "SELECT + P.ID, + P.post_title, + P.post_date, + P2.guid AS thumbnail + FROM wp_posts P + LEFT JOIN wp_postmeta PM ON PM.post_id = P.id AND PM.meta_key = '_thumbnail_id' + LEFT JOIN wp_posts P2 ON PM.meta_value = P2.ID + WHERE P.post_type = 'galeria' AND P.post_status = 'publish' + ORDER BY P.post_date DESC"; + return $this->execute_sql( $sql ); + } + + function gallery_images($id){ + $sql = "SELECT DISTINCT + PMI.meta_value AS imagenes, + PMS.meta_value AS sin_recortar + FROM wp_postmeta PM + INNER JOIN wp_postmeta PMI ON PMI.post_id = PM.post_id AND PMI.meta_key = 'imagenes' + INNER JOIN wp_postmeta PMS ON PMS.post_id = PM.post_id AND PMS.meta_key = 'sin_recortar' + WHERE PM.post_id = $id"; + return $this->execute_sql( $sql ); + } + + function image($image_id){ + $sql = "SELECT meta_value AS imagedata FROM wp_postmeta WHERE post_id = $image_id AND meta_key = '_wp_attachment_metadata'"; + return $this->execute_sql( $sql ); + } + + /** + * Execute SQL function + * + * Executes a generic SQL statement and passes back the result. + * + * @param string sql SQl statement to be executed + * @return + */ + function execute_sql( $sql ){ + $stmt = $this->conn->prepare($sql); + $stmt->execute(); + return $stmt; + } + +} \ No newline at end of file diff --git a/ActividadesWP/v5/inc/helpers.php b/ActividadesWP/v5/inc/helpers.php new file mode 100644 index 0000000..8612ea1 --- /dev/null +++ b/ActividadesWP/v5/inc/helpers.php @@ -0,0 +1,261 @@ +', $pee ); + $last_pee = array_pop( $pee_parts ); + $pee = ''; + $i = 0; + + foreach ( $pee_parts as $pee_part ) { + $start = strpos( $pee_part, ''; + + $pee .= substr( $pee_part, 0, $start ) . $name; + $i++; + } + + $pee .= $last_pee; + } + // Change multiple
s into two line breaks, which will turn into paragraphs. + $pee = preg_replace( '|\s*|', "\n\n", $pee ); + + $allblocks = '(?:table|thead|tfoot|caption|col|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|form|map|area|blockquote|address|math|style|p|h[1-6]|hr|fieldset|legend|section|article|aside|hgroup|header|footer|nav|figure|figcaption|details|menu|summary)'; + + // Add a double line break above block-level opening tags. + $pee = preg_replace( '!(<' . $allblocks . '[\s/>])!', "\n\n$1", $pee ); + + // Add a double line break below block-level closing tags. + $pee = preg_replace( '!()!', "$1\n\n", $pee ); + + // Add a double line break after hr tags, which are self closing. + $pee = preg_replace( '!()!', "$1\n\n", $pee ); + + // Standardize newline characters to "\n". + $pee = str_replace( array( "\r\n", "\r" ), "\n", $pee ); + + // Find newlines in all elements and add placeholders. + $pee = wp_replace_in_html_tags( $pee, array( "\n" => ' ' ) ); + + // Collapse line breaks before and after ', $pee ); + } + + /* + * Collapse line breaks inside elements, before and elements + * so they don't get autop'd. + */ + if ( strpos( $pee, '' ) !== false ) { + $pee = preg_replace( '|(]*>)\s*|', '$1', $pee ); + $pee = preg_replace( '|\s*|', '', $pee ); + $pee = preg_replace( '%\s*(]*>)\s*%', '$1', $pee ); + } + + /* + * Collapse line breaks inside