- Sky
- Blueberry
- Slate
- Blackcurrant
- Watermelon
- Strawberry
- Orange
- Banana
- Apple
- Emerald
- Chocolate
- Charcoal
-
Content Count
1155 -
Posts on chatbox
22 -
Joined
-
Last visited
-
Days Won
41
Miguel92 last won the day on January 30
Miguel92 had the most liked content!
Community Reputation
525 ExaltadoAbout Miguel92
-
Rank
Lorem Ipsum!
- Birthday 12/06/1992
Información de perfil
-
Sexo
Masculino
-
Localización
En mi casa
Recent Profile Visitors
-
Miguel92 started following Crear copia de seguridad desde la administración, [MOD] Sitemap Administrable v2, ¿Por que a veces el código no funciona? and and 5 others
-
[MOD] Sitemap Administrable v2 Mod original: [Mod] Sitemaps Administrable v1 Autor: @aperpen ¿Qué tiene de nuevo? Administración completa (v1) Administración modificada (v2) Inserción en robots.txt, para google detecte tu sitemap (v1) # Configuraciones: Opción de insertar de forma automática los posts y las fotos que se crean (v1) Opción de actualizar la última modificación de una URL al editar un post o una imagen (v1) # Ver URLs incluídas en el sitemap: Agregar, Editar, Borrar URLs (v1) Los cambios que realices de URLs no se verán reflejados en el sitemap no se verán reflejados hasta que tu lo desees. (v1) Sitemap completo (Url, frecuencia, ultima modificación, prioridad) (v1) URLs principales de tu web, incluídas por defecto. (v1) Restaurar URLs que vienen por defecto en cualquier momento. (v1) # Generar la creación de archivos Sitemap.xml (v2) Robots.txt (v2) La guía de instalación lo haré desde cero, en caso que ya lo tengas instalados, solo deberás reemplazar los fragmentos de códigos, ya que irán en el mismo lugar!1 - Realizan la consulta CREATE TABLE IF NOT EXISTS `w_sitemap` ( `id` int(3) NOT NULL AUTO_INCREMENT, `url` tinytext NOT NULL DEFAULT '', `frecuencia` varchar(15) NOT NULL DEFAULT '', `fecha` int(16) NOT NULL DEFAULT 0, `prioridad` decimal(2,1) NOT NULL DEFAULT 0, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1; ALTER TABLE `w_configuracion` ADD `sm_posts` int(1) NULL DEFAULT '1', ADD `sm_fotos` int(1) NOT NULL DEFAULT '1', ADD `sm_update_p` int(1) NOT NULL DEFAULT '1', ADD `sm_update_f` int(1) NOT NULL DEFAULT '1'; 2 - Abren el inc/class/c.admin.php y buscan la última llave } que cierra la class tsAdmin añaden o reemplazan (solo si lo tienen) /* * Sitemap y SEO administrables */ public function saveConfig(){ global $tsCore; $configuraciones = [ "posts" => empty($_POST['sm_posts']) ? 0 : 1, "fotos" => empty($_POST['sm_fotos']) ? 0 : 1, "update_p" => empty($_POST['sm_update_p']) ? 0 : 1, "update_f" => empty($_POST['sm_update_f']) ? 0 : 1 ]; $columns = $tsCore->setUpdate($configuraciones, "sm_"); if (db_exec([__FILE__, __LINE__], 'query', "UPDATE w_configuracion SET {$columns} WHERE tscript_id = 1")) return true; else exit( show_error('Error al ejecutar la consulta de la línea '.__LINE__.' de '.__FILE__.'.', 'db') ); } 3 - Abren el inc/php/admin.php y buscan: /** MEDALLAS **/ } elseif($action == 'medals') { y arriba añaden o reemplazan (solo si lo tienen) //SITEMAP BY APERPEN } elseif($action == 'sitemap') { if(empty($act)) { // Obtenemos todas las urls de la base de datos $smarty->assign("tsURLs", $tsSiteMap->getURLsBD()); } elseif($act === 'restaurar') { // Restauramos el sitemap if($tsSiteMap->CreateSiteMap()) { $tsCore->redirectTo($tsCore->settings['url'].'/admin/sitemap?save=true'); } } elseif($act === 'generar') { // Generamos el sitemap if($tsSiteMap->generateSiteMap()) { $tsCore->redirectTo($tsCore->settings['url'].'/admin/sitemap?save=true'); } } elseif($act === 'actual') { $smarty->assign("tsURLa", $tsSiteMap->getURLsBD()); } elseif($act === 'borrar') { if($tsSiteMap->removeUrlBD((int)$_GET['id'])) { $tsCore->redirectTo($tsCore->settings['url'].'/admin/sitemap?save=true'); } } elseif($act === 'editar') { if(!empty($_POST['url'])) { if($tsSiteMap->editUrl($_GET['id'], $_POST['url'], $_POST['frecuencia'], $_POST['prioridad'])) { $tsCore->redirectTo($tsCore->settings['url'].'/admin/sitemap?save=true'); } } else $smarty->assign("tsURL", $tsSiteMap->getUrl((int)$_GET['id'])); } elseif($act === 'nueva') { if(!empty($_POST['url'])) { if($tsSiteMap->addURL($_POST['url'], $_POST['frecuencia'], $_POST['prioridad'])) { $tsCore->redirectTo($tsCore->settings['url'].'/admin/sitemap?save=true'); } } } elseif($act === 'config') { if(isset($_POST['sm_posts'])) { if($tsAdmin->saveConfigSitemap()) { $tsCore->redirectTo($tsCore->settings['url'].'/admin/sitemap?save=true'); } } } 4 - Abren el inc/class/c.posts.php y buscan: $tsActividad->setActividad(1, $postID); // SUBIR DE RANGO? $this->subirRango($tsUser->uid); y abajo agregan // Añadimos al sitemap if($tsCore->settings['sm_posts'] === 1) { $CatSeo = db_exec('fetch_assoc', db_exec([__FILE__, __LINE__], 'query', 'SELECT c_seo FROM p_categorias WHERE cid = '.(int)$postData['category']))['c_seo']; $tsSiteMap->addUrlsm($tsCore->settings['url'].'/posts/'.$CatSeo.'/'.$postID.'/'.$tsCore->setSEO($postData['title']).'.html'); } En el mismo archivo en la funcion savePost() arriba de // GUARDAR EN EL HISTORIAL DE MODERACION if(($tsUser->is_admod || $tsUser->permisos['moedpo']) && $tsUser->uid != $data['post_user'] && $_POST['razon']){ añaden esto // Añadimos al sitemap if($tsCore->settings['sm_update_p'] === 1) { $CatSeo = db_exec('fetch_assoc', db_exec([__FILE__, __LINE__], 'query', 'SELECT c_seo FROM p_categorias WHERE cid = '.(int)$postData['category']))['c_seo']; $tsSiteMap->updateLM($tsCore->settings['url'].'/posts/'.$CatSeo.'/'.$post_id.'/'.$tsCore->setSEO($postData['title']).'.html'); } 5 - Abren el c.fotos.php de inc/class y buscan: // AGREGAR AL MONITOR DE LOS USUARIOS QUE ME SIGUEN $tsMonitor->setFollowNotificacion(10, 1, $tsUser->uid, $fid); // ACTIVIDAD $tsActividad->setActividad(9, $fid); y agregan debajo // Añadimos al sitemap if($tsCore->settings['sm_fotos'] === 1) { $tsSiteMap->updateLM($tsCore->settings['url'].'/fotos/'.$tsUser->nick.'/'.$fid.'/'.$tsCore->setSEO($fData['titulo']).'.html'); } y más abajo en la funcion editFoto() buscan // REDIRIGIMOS $url = $tsCore->settings['url'].'/fotos/'.$data['user_name'].'/'.$fid.'/'.$tsCore->setSEO($fData['titulo']).'.html'; añaden esto // Añadimos al sitemap if($tsCore->settings['sm_update_f'] === 1) { $tsSiteMap->updateLM($tsCore->settings['url'].'/fotos/'.$data['user_name'].'/'.$fid.'/'.$tsCore->setSEO($fData['titulo']).'.html'); } 6 - Abren el header.php que está en la raíz de su web y buscan: // Mensajes de usuario include TS_CLASS.'c.mensajes.php' y debajo agregan include TS_CLASS.'c.sitemap.php'; $tsSiteMap = new tsSiteMap(); // Instalación automática a través de parámetros $tsSiteMap->setAuto(); 7 - Si quieren lo hacen (PASO 5) 8 - Abren el themes/TUTEMA/templates/t.admin.tpl y buscan: {elseif $tsAction == 'rangos'} {include file='admin_mods/m.admin_rangos.tpl'} y abajo agregan {elseif $tsAction == 'sitemap'} {include file='admin_mods/m.admin_sitemap.tpl'} 9 - Abren el themes/TUTEMA/templates/admin_mods/m.admin_sidemenu.tpl y buscan: <h4>Control de Usuarios</h4> <ul class="cat-list"> <li id="a_users"><span class="cat-title"><a href="{$tsConfig.url}/admin/users">Todos los Usuarios</a></span></li> <li id="a_sesiones"><span class="cat-title"><a href="{$tsConfig.url}/admin/sesiones">Sesiones</a></span></li> <li id="a_nicks"><span class="cat-title"><a href="{$tsConfig.url}/admin/nicks">Cambios de Nicks</a></span></li> <li id="a_rangos"><span class="cat-title"><a href="{$tsConfig.url}/admin/rangos">Rangos de Usuarios</a></span></li> </ul> y debajo añaden <h4>SEO</h4> <ul class="cat-list"> <li id="a_cats"><span class="cat-title"><a href="{$tsConfig.url}/admin/sitemap">Sitemap</a></span></li> </ul> 10 - Suben los archivos a sus carpetas correspondientes c.sitemap.php -> inc/class m.admin_sitemap.tpl (smarty 3.x) o (smarty 4.x) -> themes/TUTEMA/templates/admin_mods 11 - Para acabar, este paso en la v2 esta cambiado, por lo cual no requiere de crea un archivo en la raíz de su web que se llame install.php Lo pueden ejecutar de 3 formas Solo crea el Sitemap.xml https://suweb.com/?sitemap=true&uid=1 Solo crea el Robots.txt https://suweb.com/?robots=true&uid=1 Crea el Sitemap.xml y Robots.txt https://suweb.com/?sitemap=true&robots=true&uid=1 Cualquier error dejen el comentario y el tipo de error! Sugerencias o dudas también.
-
smiles [Extra] Wysibb nuevos SMILES
Miguel92 replied to Miguel92's topic in Actualizaciones individuales de PHPost Risus's EXTRAS
Agregando a la columnas post_body(p_posts), c_body(p_comentarios) COLLATE utf8mb4_unicode_ci quedando algo parecido a esto `post_body` text COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', habrá sido como eso tu solución? -
¿Por que a veces el código no funciona? A cuantos les habrá pasa de que han copiado el código de un topic de PHPost y este le da problemas, aunque este bien realizado, hace poco descubrí una manera de interceptar ese símbolo vació ( U+FEFF ) y que no es un espacio, aun nadie sabe de donde salió, ya tiene su historia. Ahora se preguntarán como lo identifico si no deja espacio y no se ve, tal vez algún editor tenga una extensión para ver dicho carácter, en caso contrario pueden acceder a https://regex101.com/ es una pagina para realizar pruebas de Regex, pero ese no es el caso, el editor que tiene identifica ese caracter lo cual le puede ser de ayuda para borrar y que no tengan errores en su código. Un ejemplo rápido en uno de mis topic aparece Un ejemplo este fragmento que pertenece al topic mencionado # Redes sociales $red__social = []; foreach ($_POST["red"] as $llave => $id) $red__social[$llave] = $tsCore->setSecure($tsCore->parseBadWords($id), true); y lo pegan en el campo "TEST STRING" de la página mencionada... Otra manera sin usar otro sitio es crear un nuevo topic que no publicarán, pero usaran el bbcode y allí verán puntos rojos dependiendo de cuantos caracteres existan.
-
Pienso exactamente lo mismo! (excluyendo anime y hentai)
-
smiles [Extra] Wysibb nuevos SMILES
Miguel92 replied to Miguel92's topic in Actualizaciones individuales de PHPost Risus's EXTRAS
un poco tarde la respuesta jajaja...lo había creado así por que en la base de datos si usas el smile directamente te devolvía ??? para evitar eso, lo habia creado así...ahora tengo otra forma más tarde haré la v2 -
Mostrar titulo de los posts Anterior y Siguiente v2
Miguel92 posted a topic in Actualizaciones individuales de PHPost Risus's Complementos
Bueno como dice el titulo "Mostrar titulo de los posts Anterior y Siguiente v2", ya que este es una actualización mejorada! Topic de la v1 Básicamente se puede realizar tranquilamente desde cero: 1 - Buscan en inc/class/c.posts.php y van hasta la última llave } /* OBTENER LOS TITULOS DE LOS POSTS ANTERIOR/SIGUIENTE */ public function getTitles($from) { global $tsCore; $pid = (int)$_GET["post_id"]; $pid = $from ? $pid - 1 : $pid + 1; $opt = $from ? "<" : ">"; if($pid < 0) return false; // Post $sql = db_exec([__FILE__, __LINE__], "query", "SELECT post_id, post_title, c_seo FROM p_posts LEFT JOIN p_categorias ON post_category = cid WHERE post_id = {$pid}"); // Existe? if(db_exec('num_rows', $sql) === 0) { $sql = db_exec([__FILE__, __LINE__], "query", "SELECT post_id FROM p_posts WHERE post_id {$opt} {$pid} ORDER BY post_id DESC LIMIT 1"); } $data = db_exec('fetch_assoc', $sql); if(!empty($data)) { $data["post_title"] = $tsCore->setSEO($data["post_title"]); $data["post_url"] = "{$tsCore->settings["url"]}/posts/{$data["c_seo"]}/{$data["post_id"]}/{$data["post_title"]}.html"; } return !empty($data) ? $data : false; } 2 - En inc/php/posts.php buscan $tsPages['autor'] = $tsPost['post_user']; y debajo agregan $smarty->assign("tsAnterior", $tsPosts->getTitles(true)); $smarty->assign("tsSiguente", $tsPosts->getTitles(false)); 3 - Luego buscan en tema/templates/modules/m.posts_content.tpl y buscan {if $tsPost.user_firma && $tsConfig.c_allow_firma} y arriba agregan (o donde deseen), obviamente ustedes lo tendrían que adaptar a su theme... Pero si usan bootstrap no tiene que hacer tantos cambios. <div class="post-antsig"> <div class="post-anterior"> <a href="{$tsAnterior.post_url}" class="d-flex justify-content-start align-items-center"> <div class="icon ml-2"> <!-- Acá puede ir un icono o imagen, deciden ustedes --> <i class="icon-angle-left"></i> </div> <div class="titulo"> <small class="text-uppercase">No te piedas</small> <span>{$tsAnterior.post_title|truncate:34}</span> </div> </a> </div> <div class="post-siguiente"> <a href="{$tsSiguente.post_url}" class="d-flex justify-content-end align-items-center t-end"> <div class="titulo"> <small class="text-uppercase">A continuación</small> <span>{$tsSiguente.post_title|truncate:34}</span> </div> <div class="icon mr-2"> <!-- Acá puede ir un icono o imagen, deciden ustedes --> <i class="icon-angle-right"></i> </div> </a> </div> </div> Así quedaría terminado! -
Instalador automático de themes! Es completamente básico y no requiere de mucha instalación. 1 - Abren header.php y al final agregan include TS_ROOT . "/inc/InstallAutomaticTheme.php"; 2 - Descargan "InstallAutomaticTheme.php" y lo agregan en inc/ y listo todos los themes que agregues en "themes" y que contengan el archivo "install.php" los va a instalar, primero comprobará si lo tienen instalado en caso que si lo tengan, no lo va a agregar otra vez.
-
jajaja tienes razón...
-
Hola a todos, no se si les interesa, pero les dejó este mod! (No sé si era la idea que tenía) Mod iniciado por: KMario19 Topic: [Desarrollo] BBCode file para archivos No lo he encontrado terminado, así que supongo que para usar este mod, deben tener: [SECCIÓN] Archivos V1.2 [SECCIÓN] Archivos V2 [SECCIÓN] Archivos v2.2 (Actualizado a 1.3) [ZIP] Topic: Sección archivos v2.2 Iniciamos con la instalación 1 - Buscamos en .htaccess y buscamos RewriteRule ^mod-history/([A-Za-z0-9_-]+)/ inc/php/mod-history.php?ver=$1 [QSA,L] debajo agregaremos # Descargar RewriteRule ^download/([0-9_-]+)$ inc/php/download.php?id=$1 [QSA,L] 2 - Luego vamos a inc/class/c.core.php y buscamos public function setMenciones($html) { arriba de la función (también puede ir arriba de la última }) # Extraemos el nombre del archivo public function parseFiles($content) { preg_match_all('/\[file\=(\d+)\]/i', $content, $files); foreach ($files[0] as $id => $file) { $dato = db_exec('fetch_assoc', db_exec([__FILE__, __LINE__], 'query', "SELECT file_id, f_nombre, f_descargas, f_ext FROM a_files WHERE file_id = {$files[1][$id]} LIMIT 1")); if($dato["file_id"] > 0) { $replace = "<a href=\"{$this->settings["url"]}/download/{$dato["file_id"]}\">{$dato["f_nombre"]}.{$dato["f_ext"]} <span style=\"color:#aaa\">{$dato["f_descargas"]} descargas</span>"; } else $replace = "<span style=\"color:#f00\">Archivo eliminado...</span>"; $content = str_replace($file, $replace, $content); } return $content; } 3 - Después buscamos en inc/class/c.posts.php $postData['user_firma'] = $tsCore->parseBadWords($tsCore->parseBBCodeFirma($postData['user_firma']),true); arriba agregamos $postData['post_body'] = $tsCore->parsefiles($postData['post_body']); 4 - Subimos este archivo "download.php" en inc/php 5 - Luego en tema/js/wysibb.js buscan smilebox: "Emoticonos", y debajo pegan file: "Descargar archivo", un poco más abajo buscan modal_link_title: "Insertar enlace", y arriba agregan modal_link_id: "Inserta el ID del archivo", luego buscan strike,sup,sub,| y a lado agregan ,file más abajo buscan img : { y arriba pegan (en buttonHTML lo pueden definir ustedes) file : { title: CURLANG.file, buttonHTML: '<span class="fa-solid fa-paperclip"></span>', // Pueden agregar imagen o lo que deseen modal: { title: CURLANG.modal_link_id, width: "500px", tabs: [ { input: [ {param: "FILE",title:CURLANG.modal_link_id} ] } ] }, transform : { '<a href="{FILE}">{FILE}</a>':"[file={FILE}]" } }, bueno, eso todo... espero no olvidarme de nada!
-
Modal con nuevo diseño
Miguel92 posted a topic in Actualizaciones individuales de PHPost Risus's EXTRAS
Hola a todos esto lo pueden aplicar si lo desean, es una modificación completa del mydialog que trae en tema/js/acciones.js, es bastante "viejo"(por decirlo de alguna forma), lo que hice fue quitar el código que tenía y que no hacía nada, mejore la parte del footer del modal al agregar los botones, ahora se puede entender mejor... Algunas capturas de como va a quedar... (Esto puede llegar a cambiar si es que exista un elemento css que modifique el existente) El modal es sus 3 versiones "Default", "Pequeño" y "Grande" Modal alerta Modal reintentar y error Bueno, a lo que vinieron jajaja 1 - Buscan en js/acciones.js var mydialog = { ... TODO EL CODIGO .. } document.onkeydown = function(e){ key = (e==null)?event.keyCode:e.which; if(key == 27) mydialog.close(); }; y lo reemplazan por /* MyDialog 1.0 */ var mydialog = new function() { // Opciones por defecto this.options = { fixed: true, size: '' }, this.close_button = true, this.mask_close = true, this.class_aux = '', // Generamos la plantilla this.template = `<div id="dialog"> <div id="title"></div> <div id="cuerpo"> <div id="procesando"><div id="mensaje"></div></div> <div id="modalBody"></div> </div> <div id="buttons"></div> </div>`, // Iniciamos this.show = () => { // Agregamos al body $("#mydialog").html(this.template); // Agregamos clases, si contiene if(!empty(this.class_aux) || !empty(this.options.size)) { $('#mydialog').addClass(this.class_aux + ' ' + this.options.size) } // Opciones de la mascara $("#mydialog").prepend('<div id="mask"></div>') if(this.mask_close) $("#mydialog > #mask").click(() => this.close()) // Agregamos los extras if(this.options.fixed) $("body").attr("modal-open", true) $('#mydialog #dialog').fadeIn('fast'); // Botón cerrar if(this.close_button) { $('#mydialog #dialog').append('<span class="close_dialog" onclick="mydialog.close()">×</span>'); } }, this.close = () => { $('#mydialog #dialog, #mydialog #mask').fadeOut('fast', () => $(this).remove()); if(this.options.fixed) $("body").removeAttr("modal-open") this.procesando_fin(); }, this.center = () => { var centrado = $("#dialog"); centrado.css({ 'left': Math.round($(window).width() / 2) - Math.round(centrado.width() / 2), 'top': Math.round($(window).height() / 2) - Math.round(centrado.height() / 2) }) }, this.title = string => $("#title").html(string) this.body = string => $("#modalBody").html(string), this.buttons = (all, display1, val1, action1, enabled1, focus1, display2, val2, action2, enabled2, focus2) => { var buttons_add = $("#buttons") // Con este mostramos los botones if(all === true) { // Accion close" var close = 'mydialog.close()' if(action1 === 'close') action1 = close; if(action2 === 'close' || !val2) action2 = close; if(!val2) { val2 = 'Cancelar'; enabled2 = true; } // Mostramos boton 1 if(display1) buttons_add.append(`<input type="button" class="mBtn btnOk" onclick="${action1}" value="${val1}"` + (enabled1 ? '' : ' disabled') + `>`) // Mostramos boton 2 if(display2) buttons_add.append(`<input type="button" class="mBtn btnCancel" onclick="${action2}" value="${val2}"` + (enabled2 ? '' : ' disabled') + `>`) // Enfocamos if(focus1) $('#mydialog #buttons .mBtn.btnOk').focus(); else if(focus2) $('#mydialog #buttons .mBtn.btnCancel').focus(); } else buttons_add.remove() }, this.alert = (title, body, reload) => { this.class_aux = 'modal-alert' this.close_button = false this.show(); this.title(title); this.body(body); this.buttons(true, true, 'Aceptar', 'mydialog.close();' + (reload ? 'location.reload();' : ''), true, true, false); this.center(); }, this.error_500 = fun_reintentar => { mydialog.procesando_inicio('Procesando...', 'Reintentando'); setTimeout(() => { mydialog.procesando_fin(); mydialog.show(); mydialog.title('Error'); mydialog.body('Error al intentar procesar lo solicitado'); mydialog.buttons(true, true, 'Reintentar', 'mydialog.close();'+fun_reintentar, true, true, true, 'Cancelar', 'close', true, false); mydialog.center(); }, 2000); }, this.procesando_inicio = (value, title) => { if(!this.is_show){ this.show(); this.title(title); this.buttons(false); this.center(); } $('#mydialog #procesando #mensaje').html('<img src="'+global_data.img+'images/loading_bar.gif" />'); $('#mydialog #procesando').fadeIn('fast'); }, this.procesando_fin = () => $('#mydialog #procesando').fadeOut('fast') } document.onkeydown = function(e){ key = (e==null)?event.keyCode:e.which; if(key == 27) mydialog.close(); }; 2 - En estilo.css buscan todos los #mask, #mydialog que existan y lo borran, ya que puede interferir con el nuevo estilo... Pero si quieren evitarlo pueden incluirlo directamente en extras.css o phpost.css body[modal-open=true] { overflow: hidden; } #mydialog #mask { width: 100%; height: 100vh; position: fixed; top: 0; left: 0; z-index: 1; background-color: rgba(50, 50, 50, .7); } #mydialog #dialog { --radius: 0.375rem; --shadow: 0 0 .5rem rgba(49, 49, 49, .3); --bordermodal: 1px solid rgba(150, 150, 150, .3); background-color: var(--base-color-body); color: var(--base-color-texto); border: var(--bordermodal); z-index: 99; position: fixed; width: 560px; box-shadow: var(--shadow); border-radius: var(--radius)!important; } #mydialog.small #dialog { width: 300px; } #mydialog.large #dialog { width: 700px; } #mydialog #dialog .close_dialog { --whlh: 1.2rem; position: absolute; top: 0.76rem; right: 0.66rem; display: grid; width: var(--whlh); height: var(--whlh); color: white; background-color: red; place-items: center; line-height: 1rem; font-size: var(--whlh); cursor: pointer; border-radius: .32rem; } #mydialog #dialog #title { display: block; padding: 0.82rem 1rem; font-weight: 600; border-bottom: var(--bordermodal); position: relative; } #mydialog #dialog #mensaje img { position: relative; margin: 1rem auto; display: block; } #mydialog #dialog #modalBody { padding: 1rem; max-height: 320px; overflow-y: auto; } #mydialog #dialog #buttons { display: flex; justify-content: space-around; align-items: center; padding: .654rem 0; border-top: var(--bordermodal); width: 100%; } #mydialog #dialog #buttons .mBtn { padding: .6rem 1.4rem; } #mydialog.modal-alert #dialog #title, #mydialog.modal-alert #dialog #buttons { border: none; padding: 1rem; } #mydialog.modal-alert #dialog #modalBody { padding: 0.4rem 1rem; } #mydialog.modal-alert #dialog #buttons { display: block; text-align: right; } Nota: Para activar el modal "pequeño" o "grande" deben buscar el modal que quieren modificar y buscan mydialog.show(true); y arriba agregan mydialog.options = { size: 'tipo del modal' // Tipos: small o large } Eso sería todo! -
Crear copia de seguridad desde la administración
Miguel92 posted a topic in Actualizaciones individuales de PHPost Risus's Complementos
Bueno como ya había mencionado, ya esta la "herramienta" para crear copias de seguridad completa o parcial de la base de datos y podrás restaurar dicho copia, el problema será que no tengas acceso a la administración del sitio y allí necesitarás una herramienta externa pero que funcione dentro del sitio. Solo tengo que hacerle algunos cambios a la herramienta que ya tengo creada desde hace 1 año. Capturas: Antes de comenzar, si tienes Ejecutar SQL desde la administración [Arreglado] tendrás que quitarlo o eliminar archivos Bueno comencemos con la integración, los archivos para descargar están al final. 1 - Este archivo "c.database.php" y lo agregan a 2 - En inc/php/admin.php buscamos /** NOTICIAS **/ } elseif($action == 'news'){ arriba agregarán } elseif($action == 'execute' OR $action == 'backup') { # Incluimos el archivo necesario include("../class/c.database.php"); $tsDataBase = new tsDataBase(); # Todas las opciones de la copia de seguridad if($action == 'backup') { if(empty($act)) { $smarty->assign('tsListBackup', $tsDataBase->listBackup()); # Creamos el backup completo } elseif($act === 'new_backup') { if(!empty($_POST["nombre_copia"])) { if($tsDataBase->createBackUp()[0]) $tsCore->redirectTo($tsCore->settings['url'].'/admin/backup?save=true'); else $smarty->assign("tsError", $tsDataBase->createBackUp()[1]); } # Creamos el backup seleccionando tablas } elseif($act === 'new_backup_select') { $smarty->assign('tsTablas', $tsDataBase->show_tables()); if(!empty($_POST["nombre_copia"])) { if($tsDataBase->seletedTables()[0]) $tsCore->redirectTo($tsCore->settings['url'].'/admin/backup?save=true'); else $smarty->assign("tsError", $tsDataBase->seletedTables()[1]); } # Descargamos el fichero } elseif($act === 'download') { if(isset($_GET["code"])) { $smarty->assign('tsDownload', $tsDataBase->downloader()); } } } 3 - Ahora en inc/php/ajax/ajax.php buscan 'admin-badwords-delete' => array('n' => 4, 'p' => ''), debajo agregan 'admin-eliminar-sql' => array('n' => 4, 'p' => ''), 'admin-restaurar-sql' => array('n' => 4, 'p' => ''), 'admin-ejecutar-sql' => array('n' => 4, 'p' => ''), más abajo buscan include("../class/c.admin.php"); $tsAdmin = new tsAdmin(); y agregan if($action === 'admin-eliminar-sql' OR $action === 'admin-restaurar-sql' OR $action === 'admin-ejecutar-sql') { include("../class/c.database.php"); $dbase = new tsDataBase(); } por último buscan default: die('0: Este archivo no existe.'); break; y arriba agregan case 'admin-eliminar-sql': echo $dbase->delete_file_sql(); break; case 'admin-restaurar-sql': echo $dbase->restore_file_sql(); break; case 'admin-ejecutar-sql': echo $dbase->executeSQL(); break; 4 - Ahora en tema/templates/t.admin.tpl buscan {include file='admin_mods/m.admin_rangos.tpl'} y debajo pegan {elseif $tsAction == 'execute' || $tsAction == 'backup'} {include file='admin_mods/m.admin_database.tpl'} 5 - En tema/templates/admin_mods/m.admin_sidemenu.tpl buscan <h4>Configuración de PHPost</h4> y arriba agregan <h4>Seguridad</h4> <ul class="cat-list"> <li id="a_configs"><span class="cat-title"><a href="{$tsConfig.url}/admin/execute">Ejecutar consultas</a></span></li> <li id="a_main"><span class="cat-title"><a href="{$tsConfig.url}/admin/backup">Crear copia</a></span></li> </ul> 6 - Este archivo "m.admin_database.tpl" y lo agregan a tema/templates/admin_mods/ 7 - Por último en tema/ja/admin.js al final del archivo agregan /** * Database * para ejecutar consultas y crear copias */ var database = new function() { this.execute = () => { var SQL = 'sql=' + $("#sql").val(); $.post(global_data.url + '/admin-ejecutar-sql.php', SQL, h => { switch (h.charAt(0)) { case '0': mydialog.alert('Error', h.substring(3), false) break; case '1': mydialog.alert('Bien', h.substring(3), true) break; } }) }, this.delete = (id, file, gew) => { if(!gew) { mydialog.show() mydialog.title('Eliminar') mydialog.body(`Estas seguro que quieres eliminar este archivo: ${file}`) mydialog.buttons(true, true, 'Borrar SQL', `database.delete(${id}, '${file}', true)`, true, false, true, 'Cancelar', 'close', true, true); /*mydialog.buttons([ {mostrar:true,texto:'Borrar SQL',accion:`database.delete(${id}, '${file}', true)`,activo:true}, {mostrar:true,texto:'Cancelar',accion:'cerrar',activo:true} ]); */ mydialog.center() } else { $.post(global_data.url + '/admin-eliminar-sql.php', {id,file}, e => { switch (e.charAt(0)) { case '0': mydialog.alert('Error', e.substring(3)); break; case '1': mydialog.close(); $("#sql" + id).remove(); break; } }) } }, this.restore = (file, gew) => { if(!gew) { mydialog.show() mydialog.title('Restaurar') mydialog.body(`Estas seguro que quieres restaurar esta copia: ${file}`) mydialog.buttons(true, true, 'Restaurar SQL', `database.restore('${file}', true)`, true, false, true, 'Cancelar', 'close', true, true); /*mydialog.buttons([ {mostrar:true,texto:'Restaurar SQL',accion:`database.restore('${file}', true)`,activo:true}, {mostrar:true,texto:'Cancelar',accion:'cerrar',activo:true} ]);*/ mydialog.center() } else { mydialog.procesando_inicio('', "Espere"); mydialog.buttons(false); mydialog.center() $.post(global_data.url + '/admin-restaurar-sql.php', {restore: file}, e => { switch (e.charAt(0)) { case '0': mydialog.procesando_fin(); mydialog.alert('Error', e.substring(3), false); break; case '1': mydialog.procesando_fin(); mydialog.alert('Bien', e.substring(3), false); break; } }) } } } Descargar los archivos "-#- Justo aquí -#-" En caso que tengan problemas al querer crear las copias de seguridad, comprueben que se haya creado la carpeta "database" en files/ y que tenga los permisos 0777 aplicados, en caso contrario deberán crearlo y darle los permisos correspondientes -
Bueno lo que trate de hacer es simplificar un poco, quieres agregar una imagen a "rangos", "categorías" o "medallas" y no quieres entrar desde el FTP o CPanel, bueno con esta herramienta deberías poder realizar esta tarea desde la administración de tu sitio. Les mostraré algunas imágenes, pero no esta realizado con el default, si no que es una versión que estoy realizando. Bueno comenzamos... 1 - En inc/class/c.admin.php lo pueden agregar al final o donde quieran. # Obtenemos todas las imagenes de la carpeta public function obtener_paquete($dir) { global $tsCore, $smarty; # Aplicamos los permisos si no los tiene foreach (["cat", "med", "ran"] as $carpeta) chmod($smarty->template_dir["images"] . 'icons/' . $carpeta, 0777); # Creamos un arreglo $data = []; # Buscamos en la carpeta... $carpeta = $smarty->template_dir["images"] . 'icons/' . $dir; $imagenes = opendir( $carpeta ); # Recorremos la carpeta while ($icono = readdir($imagenes)) { if($icono != '.' && $icono != '..'): # Obtenemos información del archivo $inf = getimagesize($carpeta . '/' . $icono); $arr = [ "hash" => substr(md5(explode('.', $icono)[0]), 0, 6), "icon" => explode('.', $icono)[0], "url" => $tsCore->settings["images"] . '/icons/' . $dir . '/' .$icono, "width" => $inf[0], "height" => $inf[1], "type" => $inf["mime"] ]; if(isset($_GET["size"]) or isset($_GET["type"])) { if(intval($_GET["size"]) === $inf[0] or 'image/'.$_GET["type"] === $inf["mime"]) { array_push($data, $arr); } } else array_push($data, $arr); endif; } closedir( $imagenes ); # Retornamos el arreglo return $data; } public function eliminar_icono_paquete() { global $tsCore, $smarty; # Buscamos en la carpeta... $carpeta = $smarty->template_dir["images"] . 'icons/' . $tsCore->setSecure($_POST["path"]); # Eliminamos si son la misma imagen con difente tamaño foreach($this->obtener_paquete($_POST["path"]) as $eliminar) { if($eliminar["hash"] === $_POST["hash"]) { if($_POST["path"] === 'med') { $sizes = [16, 32]; foreach ($sizes as $size) { $nimg = "{$eliminar["icon"]}_{$size}." . substr($eliminar["type"], 6); unlink($carpeta . '/' . $nimg); } return true; } else { $nimg = "{$carpeta}/{$eliminar["icon"]}." . substr($eliminar["type"], 6); return (unlink($nimg)) ? true : false; } } } } public function subir_icono() { global $smarty; # Mover a... $mover = $smarty->template_dir["images"] . 'icons/' . $_POST["path"] . DIRECTORY_SEPARATOR; // if (($_FILES["file"]["type"] == "image/jpg") || ($_FILES["file"]["type"] == "image/png") || ($_FILES["file"]["type"] == "image/gif")) { # Agregamos la imagen, si existe, esta será reemplazada por la nueva return (move_uploaded_file($_FILES["file"]["tmp_name"], $mover . $_FILES['file']['name'])) ? '1: Imagen agregada correctamente...' : '0: No se pudo subir la imagen!'; } else return false; } Este código es para Smarty 4, si no lo tienes actualizado, lo que debes hacer es lo siguiente, buscas esto $smarty->template_dir["images"] . 'icons/' y lo reemplazas por TS_ROOT . '/themes/' . $tsCore->settings["tema"]['t_path'] . '/images/icons/' y borrar el de las funciones, excepto el que lleva $tsCore, allí solo eliminas , $smarty global $smarty; 2 - En inc/php/admin.php buscan } elseif($action == 'creditos'){ y arriba agregan # PACKS } elseif($action == 'packs') { $smarty->assign('tsDir', $_GET["path"]); if($act === 'abrir') { $smarty->assign('tsPack', $tsAdmin->obtener_paquete($_GET["path"])); } 3 - En inc/php/ajax/ajax.admin.php buscan 'admin-badwords-delete' => array('n' => 4, 'p' => ''), y debajo pegan 'admin-eliminar-icono' => array('n' => 4, 'p' => ''), 'admin-subir-icono' => array('n' => 4, 'p' => ''), más abajo default: die('0: Este archivo no existe.'); break; arriba agregan case 'admin-eliminar-icono': echo $tsAdmin->eliminar_icono_paquete(); break; case 'admin-subir-icono': echo $tsAdmin->subir_icono(); break; 4 - En tema/templates/admin_mods/ crean un archivo llamado "m.admin_packs.tpl" y dentro agregan, les recuerdo que lo pueden adaptar a su theme <div class="boxy-title"> <h3>Control de paquetes de imagenes</h3> </div> <div id="res" class="boxy-content"> <p class="alerts ok">Desde aquí podrás ver, agregar, eliminar las imagenes e iconos que estan guardados en "<a href="{$tsConfig.url}/admin/packs?act=abrir&path=ran">ran</a>", "<a href="{$tsConfig.url}/admin/packs?act=abrir&path=med">med</a>", "<a href="{$tsConfig.url}/admin/packs?act=abrir&path=cat">cat</a>".</p> {if $tsSave}<div class="alerts ok">Tus cambios han sido guardados.</div>{/if} <hr class="separator"> {if $tsAct === ''} <div style="display:grid;gap:10px;grid-template-columns: repeat(3, 1fr);"> <a href="{$tsConfig.url}/admin/packs?act=abrir&path=cat" class="block text-center"> <img width="140" height="140" src="{$tsConfig.images}/category.svg" alt="Categorías"> <strong style="margin-top:4px;display: block;">Categorías</strong> </a> <a href="{$tsConfig.url}/admin/packs?act=abrir&path=med" class="block text-center"> <img width="140" height="140" src="{$tsConfig.images}/award.svg" alt="Medallas"> <strong style="margin-top:4px;display: block;">Medallas</strong> </a> <a href="{$tsConfig.url}/admin/packs?act=abrir&path=ran" class="block text-center"> <img width="140" height="140" src="{$tsConfig.images}/ran.svg" alt="Rangos"> <strong style="margin-top:4px;display: block;">Rangos</strong> </a> </div> {elseif $tsAct === 'abrir'} {if $tsDir === 'med' || $tsDir === 'ran'} <span>Filtros:</span> {if $tsDir === 'med'} <a href="{$tsConfig.url}/admin/packs?act=abrir&path=med" style="text-align:center;">Todos</a> - <a href="{$tsConfig.url}/admin/packs?act=abrir&path=med&size=16" style="text-align:center;">16x16</a> - <a href="{$tsConfig.url}/admin/packs?act=abrir&path=med&size=32" style="text-align:center;">32x32</a> {/if} {if $tsDir === 'ran'} <a href="{$tsConfig.url}/admin/packs?act=abrir&path=ran" style="text-align:center;">Todos</a> - <a href="{$tsConfig.url}/admin/packs?act=abrir&path=ran&type=gif" style="text-align:center;">GIF</a> - <a href="{$tsConfig.url}/admin/packs?act=abrir&path=ran&type=png" style="text-align:center;">PNG</a> {/if} {/if} <table class="admin_table"> <thead> <tr> <th>Icono</th> <th>Nombre</th> <th>Dimensiones</th> <th>Tipo</th> <th>Acciones</th> </tr> </thead> {foreach $tsPack item=ic} <tr class="{$ic.hash}"> <td style="text-align:center;"><img src="{$ic.url}" alt="{$ic.icon}"></td> <td style="width: max-content">{$ic.icon}</td> <td>{$ic.width}x{$ic.height}</td> <td>{$ic.type}</td> <td class="admin_actions flex jcsaround aicenter"> <a href="javascript:packs.borrar('{$tsDir}', '{$ic.hash}')" title="Eliminar"><i class="fas fa-trash"></i></a> </td> </tr> {/foreach} </table> <hr class="separator"> <div style="text-align:center;"> <a href="{$tsConfig.url}/admin/packs?act=agregar&path={$tsDir}" class="mBtn">Agregar icono en {$tsDir}</a> </div> {elseif $tsAct === 'agregar'} <form method="post" enctype="multipart/form-data"> <input type="hidden" name="path" id="path" value="{$tsDir}"> <div class="form-line"> <label for="image">Sube una imagen...</label> <input type="file" class="form-control-file" name="image" id="image"> </div> <p><a href="javascript:packs.subir()" class="mBtn btnOk">Agregar</a></p> </form> {/if} </div> 5 - En tema/templates/admin_mods/m.admin_sidemenu.tpl buscan <li id="a_badwords"><span class="cat-title"><a href="{$tsConfig.url}/admin/badwords">Censuras</a></span></li> y debajo agregan <li id="a_main"><span class="cat-title"><a href="{$tsConfig.url}/admin/packs">Control de iconos</a></span></li> 6 - En tema/js/admin.js al final del archivo agregan /** * Control de paquete * para agregar, editar y eliminar iconos */ var packs = new function() { this.reload = path => location.href = global_data.url + '/admin/packs?act=abrir&path=' + path, this.subir = () => { var formData = new FormData(); formData.append('file', $('#image')[0].files[0]); formData.append('path', $('#path').val()); $.ajax({ url: global_data.url + '/admin-subir-icono.php', type: 'post', data: formData, contentType: false, processData: false, success: response => { switch(response.charAt(0)) { case '0': mydialog.alert('Error', response.substring(3), false); mydialog.center(); break; case '1': mydialog.show() mydialog.title('Bien!') mydialog.body(response.substring(3)) mydialog.buttons(true, true, 'Continuar', 'packs.reload(' + carpeta + ')', true, false, false); /*mydialog.buttons({mostrar:true,texto:'Continuar',accion:`packs.reload('${path}')`,activo:true});*/ mydialog.center() break; } } }); return false; }, this.borrar = (carpeta, hash, status) => { if(!status) { mydialog.show() mydialog.title('¿Deseas eliminar ' + (carpeta == 'med' ? 'estos iconos' : 'este icono') + '?') mydialog.body('Esto eliminará el/los iconos de su tema') mydialog.buttons(true, true, 'Continuar', 'packs.borrar(' + carpeta + ', ' + hash + ', true)', true, false, true, 'No', 'close', true, true); /*mydialog.buttons([ {mostrar:true,texto:'Continuar',accion:`packs.borrar('${carpeta}', '${hash}', true)`,activo:true}, {mostrar:true,texto:'No',accion:'cerrar',activo:true} ]);*/ mydialog.center() } else { var params = ['path=' + carpeta, 'hash=' + hash].join('&') $.post(global_data.url + '/admin-eliminar-icono.php', params, del => { mydialog.close(); if(del) { if(carpeta === 'med') { $("tr." + hash).each( (inx, trh) => trh.remove()) } else $("tr." + hash).remove() } }) } } } 7 - Suben estas 3 imágenes a tema/images/ Para la próxima le quiero agregar un paginador, y la subida de múltiples imágenes... NOTA: Para que funciones correctamente, el complemento le asignará a las carpetas ran, cat y med los permisos necesarios para que funcione, en caso que tenga error o no suba las imágenes a dichas carpetas lo que deben hacer es darle permisos 0777 manualmente a las carpetas mencionadas.
-
Mover categorías [Mejorado]
Miguel92 posted a topic in Actualizaciones individuales de PHPost Risus's EXTRAS
En este caso se usará CDN para que sea mejor 1 - En inc/class/c.admin.php buscamos function saveOrden() { ... todo ... } y lo reemplazamos por public function saveOrden() { global $tsCore; # $ordenado = []; # Obtenemos lista con el nuevo orden $nuevo_orden = 1; foreach (explode(',', $_POST["cats"]) as $orden) { db_exec([__FILE__, __LINE__], 'query', "UPDATE p_categorias SET c_orden = ".$nuevo_orden." WHERE cid = ".$orden); array_push($ordenado, $nuevo_orden); $nuevo_orden++; } } 2 - En inc/php/ajax/ajax.admin.php buscan 'admin-badwords-delete' => array('n' => 4, 'p' => ''), y debajo agregan 'admin-ordenar-categorias' => array('n' => 4, 'p' => ''), más abajo buscan case 'admin-badwords-delete': //<--- echo $tsAdmin->deleteBadWord(); //---> break; y debajo agregan case 'admin-ordenar-categorias': //<--- echo $tsAdmin->saveOrden(); //---> break; 3 - Luego en tema/templates/admin_mods/m.admin_cats.tpl y buscamos, puedes eliminar jquery.tablednd.js si quieres <script type="text/javascript" src="{$tsConfig.js}/jquery.tablednd.js"></script> y lo reemplazamos por, se usa la condicional ya que solo es donde se muestra la lista de categorías {if $tsAct == ''} <script src="https://cdn.jsdelivr.net/npm/[email protected]/Sortable.min.js"></script> {/if} abajo de eso buscamos <script type="text/javascript"> // {literal} $(function(){ // {/literal} {if $tsAct == ''} {literal} $('#cats_orden').tableDnD({ onDrop: function(table, row) { $.ajax({ type: 'post', url: global_data.url + '/admin/cats?ajax=true&ordenar=true', cache: false, data: $.tableDnD.serialize() }); } }); // {/literal} {/if} {literal} $('#cats_orden').tableDnD({ onDrop: function(table, row) { $.ajax({ type: 'post', url: global_data.url + '/admin/cats?ajax=true&ordenar=true&t=cat', cache: false, data: $.tableDnD.serialize() }); } }); // $('#cat_img').change(function(){ var cssi = $("#cat_img option:selected").css('background'); $('#c_icon').css({"background" : cssi}); }); // }); //{/literal} </script> y lo reemplazamos por {if $tsAct == '' || $tsAct == 'editar' || $tsAct == 'nueva'} <script> $(() => { /* {if $tsAct == ''} */ new Sortable(document.getElementById('cats_orden'), { animation: 150, dragClass: "arrastrar", // Clase que puedes modificar selectedClass: "seleccionado", // Clase que puedes modificar store: { // Guardar orden set: sortable => $.post(global_data.url + '/admin-ordenar-categorias.php', 'cats=' + sortable.toArray().join(',')) } }); /* {/if} */ $('#cat_img').on('change', () => { $('#c_icon').css({ "background": $("#cat_img option:selected").css('background') }) }); }) </script> {/if} más abajo buscan y le borran id="cats_orden" de <table cellpadding="0" cellspacing="0" border="0" width="500" align="center" class="admin_table" id="cats_orden"> un poco más abajo buscan y le añaden id="cats_orden" a <tbody> abajo buscan <tr id="{$c.cid}"> y lo reemplazan por <tr id="{$c.cid}" data-id="{$c.cid}"> Si quieres puedes añadir estas líneas en tema/css/admin.css .arrastrar { background-color: #EEE; } .seleccionado { background-color: #CCC; } Si quieres obtener más información sobre el complemento "SortableJS", puedes acceder a la página que contiene la documentación para que puedas hacer los cambios que desees! -
Subir avatar mejorado
Miguel92 posted a topic in Actualizaciones individuales de PHPost Risus's EXTRAS
En este caso se usará CDN para que sea mejor 1 - En tema/templates/modules/m.cuenta_sidebar.tpl y reemplazamos todo por esto <div class="sidebar-tabs clearbeta"> <h3>Mi Avatar</h3> <div class="avatar-big-cont"> <div style="display: none" class="avatar-loading"></div> <img width="120" height="120" alt="" src="{$tsConfig.url}/files/avatar/{if $tsPerfil.p_avatar}{$tsPerfil.user_id}_120{else}avatar{/if}.jpg?t={$smarty.now}" class="avatar-big" id="avatar-img"/> </div> <ul class="change-avatar" id="change"> <li class="local-file" id="pc" style="width: 50%;text-align:center;"><span>Local</span></li> <li class="url-file" id="url" style="width: 50%;text-align:center;"><span>Url</span></li> </ul> <div class="clearfix"></div> <a href="javascript:avatar.subir()" class="avatar-next edit" >Editar</a> </div> <div class="clearfix"></div> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/croppr.min.css" integrity="sha256-Bbkel8+0sOmrvX75oDwNElgbmrAP+Pw+XXKKUwoKiVE=" crossorigin="anonymous"> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/croppr.min.js" integrity="sha256-VPADQYvd0gjLaeduvmP9/UZAdNW3D2sJieeJ3a3PX64=" crossorigin="anonymous"></script> <script src="{$tsConfig.js}/subir-avatar.js?{$smarty.now}"></script> 2 - Creamos un archivo llamado "subir-avatar.js" y lo agregamos en tema/js const next = $(".avatar-next"); const sizeImg = 120; function cambiarFile(){ const input = $('#file-avatar')[0]; if(input.files && input.files[0]) { let name_file = decodeURIComponent(input.files[0].name); document.querySelector(".drop-message").innerHTML = name_file; next.removeClass('btn-disabled') } } $("#url-avatar").on('keyup', () => { if($("#url-avatar").val().length > 5) next.removeClass('btn-disabled') }) $("#change > li, #change > li span").on('click', event => { const block = $("#change") block.attr('class', '') var tipo = event.target.textContent if(tipo === 'Local') { block.html(`<div id="drop-region"> <input type="file" name="local" id="file-avatar" onchange="return cambiarFile();" class="browse"/> <div class="drop-message"> Arrastra y suelta la imagen o haz clic para subir </div> </div>`) } else { block.html(`<div style="margin: 0 auto 10px auto;"> <input type="text" name="url" autocomplete="off" id="url-avatar" placeholder="Url de la imagen" class="browse form-control"/> </div>`) } }) var avatar = { uid: false, key: false, ext: false, informacion: '', current: false, success: false, subir: async () => { $(".avatar-loading").show().css('display', 'flex'); inputs = [].slice.call(document.querySelectorAll(".browse")) inputs.forEach(input => { const datoUrl = new FormData(); datoUrl.append('url', (input.name == 'url') ? input.value : input.files[0]) if(!empty(input.value)) { fetch(global_data.url + '/upload-avatar.php', { method: 'POST', body: datoUrl }) .then(response => response.json()) .then(blobData => { avatar.subida_exitosa(blobData) }); } }) }, subida_exitosa: rsp => { if (rsp.error == 'success') avatar.success = true; else if (rsp.msg) { avatar.key = rsp.key; avatar.ext = rsp.ext; avatar.cortar(rsp.msg); } else cuenta.enviar_alerta(rsp.error, 0); $(".avatar-loading").hide(); }, cortar: img => { img = img + '?t=' + new Date(); mydialog.show(true); mydialog.title("Cortar avatar"); mydialog.body(`<img class="avatar-cortar" src="${img}" />`); mydialog.buttons(true, true, 'Cortar', "avatar.guardar()", true, false, true, 'Cancelar', 'close', true, true); /*mydialog.buttons([ {mostrar: true, texto: 'Cortar', accion: `avatar.guardar()`, activo: true}, {mostrar: true, texto: 'Cancelar', accion: 'cerrar', activo: true} ]);*/ mydialog.center(); $("#avatar-img, #avatar-menu").attr("src", img).on('load', () => { var croppr = new Croppr('.avatar-cortar', { aspectRatio: 1, // Mantemos el tamanio cuadrado 1:1 maxSize: { width: sizeImg, // Tamano por defecto height: sizeImg // Tamano por defecto }, // Enviamos las coordenadas para cortar la imagen // Tiene la funcion onCropEnd ya que es como va a quedar onCropEnd: data => avatar.informacion = data, }); }); }, recargar: () => $("#avatar-img").attr("src", avatar.current + '?r' + new Date()), guardar: () => { if (empty(avatar.informacion)) cuenta.enviar_alerta('Debes seleccionar una parte de la foto', 0); else { const coordenadas = new FormData(); coordenadas.append('key', avatar.key) coordenadas.append('ext', avatar.ext) coordenadas.append('x', avatar.informacion.x) coordenadas.append('y', avatar.informacion.y) coordenadas.append('w', avatar.informacion.width) coordenadas.append('h', avatar.informacion.height) fetch(global_data.url + '/upload-crop.php', { method: 'POST', body: coordenadas }) .then(response => response.json()) .then(blobData => { if(blobData.error == "success") { mydialog.body("Tu avatar se ha creado correctamente, ahora espera que recargue la página"); setTimeout(() => location.reload(), 1200); mydialog.buttons(false) } }); } } } 3 - Luego en tema/js/cuenta.js buscar¿ var avatar = { ..... y borran todo hasta el final del archivo 4 - Luego van a inc/php/ajax.upload.php y lo reemplazan por esto <?php if ( ! defined('TS_HEADER')) exit('No se permite el acceso directo al script'); /** * Controlador AJAX * * @name ajax.upload.php * @author PHPost Team */ /**********************************\ * (VARIABLES POR DEFAULT) * \*********************************/ // NIVELES DE ACCESO Y PLANTILLAS DE CADA ACCIÓN $files = array( 'upload-avatar' => array('n' => 2, 'p' => ''), 'upload-crop' => array('n' => 2, 'p' => ''), 'upload-images' => array('n' => 2, 'p' => ''), ); /**********************************\ * (VARIABLES LOCALES ESTE ARCHIVO) * \*********************************/ // REDEFINIR VARIABLES $tsPage = 'php_files/p.upload.'.$files[$action]['p']; $tsLevel = $files[$action]['n']; $tsAjax = empty($files[$action]['p']) ? 1 : 0; /**********************************\ * (INSTRUCCIONES DE CODIGO) * \*********************************/ // DEPENDE EL NIVEL $tsLevelMsg = $tsCore->setLevel($tsLevel, true); if($tsLevelMsg != 1) { echo '0: '.$tsLevelMsg['mensaje']; die();} // CLASE require('../class/c.upload.php'); $tsUpload = new tsUpload(); // CODIGO switch($action){ case 'upload-avatar': // <-- $tsUpload->image_scale = true; $tsUpload->image_size['w'] = 640; $tsUpload->image_size['h'] = 480; // $tsUpload->file_url = $_POST['url']; // $result = $tsUpload->newUpload(3); echo json_encode($result); // --> break; case 'upload-crop': // <-- echo json_encode($tsUpload->cropAvatar($tsUser->uid)); // PARA EL PERFIL db_exec(array(__FILE__, __LINE__), 'query', 'UPDATE u_perfil SET p_avatar = 1 WHERE user_id = ' . $tsUser->uid); // --> break; case 'upload-images': echo json_encode($tsUpload->newUpload(1)); break; } Eso es todo...-
- 2
-
-
- jquery
- javascript
-
(and 2 more)
Tagged with:
-
Mejorar la sección "Cuenta"
Miguel92 posted a topic in Actualizaciones individuales de PHPost Risus's EXTRAS
Esto le va a gustar ya que vamos a simplificar un poco más lo que sería la sección de cuenta, y será bastante largo, y en mi caso le he quitado el porcentaje que se muestra en cuenta y varias opciones que ningún usuario se toma el tiempo en completar, como por ejemplo "Intereses y preferencias" 1 - En .htaccess buscamos RewriteRule ^cuenta.php$ inc/php/cuenta.php [QSA,L] y debajo agregamos RewriteRule ^cuenta/([A-Za-z0-9_-]+)$ inc/php/cuenta.php?accion=$1 [QSA,L] 2 - En tema/templates/t.cuenta.tpl y reemplazamos el contenido por esto {include file='sections/main_header.tpl'} <script src="{$tsConfig.js}/cuenta.js?{$smarty.now}"></script> <script> $(document).ready(() => { avatar.uid = '{$tsUser->uid}'; avatar.current = '{$tsConfig.url}/files/avatar/{if $tsPerfil.p_avatar}{$tsPerfil.user_id}{else}avatar{/if}.jpg'; }); </script> <div class="tabbed-d"> <div class="floatL"> <div id="alerta_guarda"></div> <ul class="menu-tab"> <li{if $tsAccion == ''} class="active"{/if}><a href="{$tsConfig.url}/cuenta/">Cuenta</a></li> <li{if $tsAccion == 'perfil'} class="active"{/if}><a href="{$tsConfig.url}/cuenta/perfil">Perfil</a></li> <li{if $tsAccion == 'block'} class="active"{/if}><a href="{$tsConfig.url}/cuenta/block">Bloqueados</a></li> <li{if $tsAccion == 'clave'} class="active"{/if}><a href="{$tsConfig.url}/cuenta/clave">Cambiar Clave</a></li> <li{if $tsAccion == 'nick'} class="active"{/if}><a href="{$tsConfig.url}/cuenta/nick">Cambiar Nick</a></li> <li{if $tsAccion == 'config'} class="active"{/if}><a href="{$tsConfig.url}/cuenta/config">Privacidad</a></li> </ul> <a name="alert-cuenta"></a> <form class="horizontal" method="post" name="editarcuenta"> <input type="hidden" name="pagina" value="{$tsAccion}"> {include file="modules/m.cuenta_$tsAccion.tpl"} </form> </div> <div class="floatR"> {include file='modules/m.cuenta_sidebar.tpl'} </div> </div> <div style="clear:both"></div> {include file='sections/main_footer.tpl'} 3 - Luego acceden a tema/templates/modules/ y buscan todos los m.cuenta_*.tpl y le quitan (al inicio del archivo) style="display:none" también (7 el numero puede variar, dependiendo de la sección) <div class="alert-cuenta cuenta-7"></div> y luego en los divs con la clase .buttons lo reemplazan por <div class="buttons"> <input type="button" value="Guardar" onclick="cuenta.guardar_datos()" class="mBtn btnOk"> </div> 4 - En inc/php/cuenta.php buscan } elseif($action == 'desactivate'){ if(!empty($_POST['validar'])) echo $tsCuenta->desCuenta(); } y debajo agregan $smarty->assign("tsAccion", $_GET["accion"]); 5 - Luego inc/class/c.cuenta.php en la funcion "savePerfil()" cambian $save = $_POST['save']; por $save = $_POST['pagina']; dentro del switch hacen lo siguiente, cambian el número por el nombre - case 1 -> case '' - case 2 -> case 'perfil' - case 6 -> case 'clave' - case 7 -> case 'config' - case 8 -> case 'nick' luego eliminan estos - case 3: ...todo hasta el break... break; - case 4: ...todo hasta el break... break; - case 5: ...todo hasta el break... break; más abajo buscamos y borramos // COMPROBAR PORCENTAJE $total = array(5,8,9,8,9); // CAMPOS EN CADA CATEGORIA $tid = $save - 1; if($save > 1 && $save < 6){ $total[$tid] = $this->getPorcentTotal($perfilData, $total[$tid]); if($save == 1) $total[$tid] = $total[$tid] - 2; $porcen = db_exec('fetch_assoc', db_exec(array(__FILE__, __LINE__), 'query', 'SELECT p_total FROM u_perfil WHERE user_id = \''.$tsUser->uid.'\' LIMIT 1')); $porcen = unserialize($porcen['p_total']); $porcen[$tid] = $total[$tid]; $porcenNow = $this->getPorcentVal($porcen); $porcen = serialize($porcen); db_exec(array(__FILE__, __LINE__), 'query', 'UPDATE u_perfil SET p_total = \''.$porcen.'\' WHERE user_id = \''.$tsUser->uid.'\''); } justo debajo de eso seleccionan // ACTUALIZAR if($save == 1) { db_exec(array(__FILE__, __LINE__), 'query', 'UPDATE u_miembros SET user_email = \''.$tsCore->setSecure($perfilData['email'], true).'\' WHERE user_id = \''.$tsUser->uid.'\''); array_splice($perfilData, 0, 1); // HACK $updates = $tsCore->getIUP($perfilData, 'user_'); if(!db_exec(array(__FILE__, __LINE__), 'query', 'UPDATE u_perfil SET '.$updates.' WHERE user_id = \''.$tsUser->uid.'\'')) return array('error' => show_error('Error al ejecutar la consulta de la línea '.__LINE__.' de '.__FILE__.'.', 'db')); } else { $updates = $tsCore->getIUP($perfilData, 'p_'); if(!db_exec(array(__FILE__, __LINE__), 'query', 'UPDATE u_perfil SET '.$updates.' WHERE user_id = \''.$tsUser->uid.'\'')) return array('error' => show_error('Error al ejecutar la consulta de la línea '.__LINE__.' de '.__FILE__.'.', 'db')); } // if(is_array($msg_return)) return $msg_return; else return array('porc' => $porcenNow); y lo reemplazan por // ACTUALIZAR if($save == '' or $save == 'perfil' or $save == 'config') { if($save == '') { db_exec([__FILE__, __LINE__], "query", "UPDATE u_miembros SET user_email = '{$perfilData['email']}' WHERE user_id = " . $tsUser->uid); array_splice($perfilData, 0, 1); } $updates = $tsCore->getIUP($perfilData, ($save == '' ? 'user_' : 'p_')); $msg_return = (db_exec([__FILE__, __LINE__], "query", "UPDATE u_perfil SET {$updates} WHERE user_id = " . $tsUser->uid)) ? array("error" => "Los cambios fueron aceptados y serán aplicados.") : die(show_error('Error al ejecutar la consulta de la línea '.__LINE__.' de '.__FILE__.'.', 'Base de datos')); } // return $msg_return; 6 - Crean un archivo llamado ajax.cuenta.php en inc/php/ajax y agregan lo siguiente <?php if ( ! defined('TS_HEADER')) exit('No se permite el acceso directo al script'); /** * Controlador AJAX * * @name ajax.cuenta.php * @author Miguel92 */ $files = [ 'cuenta-guardar' => ['n' => 2, 'p' => ''], ]; // REDEFINIR VARIABLES $tsPage = 'ajax/p.cuenta.'.$files[$action]['p']; $tsLevel = $files[$action]['n']; $tsAjax = empty($files[$action]['p']) ? 1 : 0; // DEPENDE EL NIVEL $tsLevelMsg = $tsCore->setLevel($tsLevel, true); if($tsLevelMsg != 1): echo '0: '.$tsLevelMsg['mensaje']; die(); endif; // CLASE require("../class/c.cuenta.php"); $tsCuenta = new tsCuenta(); // CODIGO switch($action){ case 'cuenta-guardar': echo json_encode($tsCuenta->savePerfil()); break; } 7 - En tema/templates/modules/m.cuenta_cuenta.tpl lo renombran a m.cuenta_.tpl 8 - En tema/templates/modules/m.cuenta_perfil.tpl y reemplazan el contenido por esto, y aplica este Redes sociales en perfil [Mejorado][Simplificado][Sugerencia] <div class="content-tabs perfil"> <fieldset> <div class="field"> <label for="nombrez">Nombre completo</label> <input type="text" value="{$tsPerfil.p_nombre}" maxlength="60" name="nombrez" id="nombrez" class="text cuenta-save-2" style="width:230px"> </div> <div class="field"> <label for="sitio">Mensaje Personal</label> <textarea value="" maxlength="60" name="mensaje" id="mensaje" class="cuenta-save-2">{$tsPerfil.p_mensaje}</textarea> </div> <div class="field"> <label for="sitio">Sitio Web</label> <input type="text" value="{$tsPerfil.p_sitio}" maxlength="60" name="sitio" id="sitio" class="text cuenta-save-2" style="width:230px"> </div> <div class="field"> <label for="red">Redes sociales</label> <div style="display:grid;grid-template-columns: repeat(2, 1fr);gap: 10px;"> {foreach $tsPerfil.redes key=name item=red} <div style="display:flex;justify-content: flex-start;align-items: center;"> <div class="icon"> <img src="{$tsConfig.images}/icons/{$name}.png" width="16" height="16" /> </div> <input type="text" class="text cuenta-save-2" value="{$tsPerfil.p_socials.$name}" placeholder="{$red}" name="red[{$name}]"> </div> {/foreach} </div> </div> <div class="field"> <label>Me gustaría</label> <div class="input-fake"> <ul> {foreach from=$tsPData.gustos key=val item=text} <li><input type="checkbox" name="g_{$val}" class="cuenta-save-2" value="1"{if $tsPerfil.p_gustos.$val == 1} checked{/if}>{$text}</li> {/foreach} </ul> </div> </div> <div class="field"> <label for="estado">Estado Civil</label> <div class="input-fake"> <select class="cuenta-save-2" name="estado" id="estado"> {foreach from=$tsPData.estado key=val item=text} <option value="{$val}"{if $tsPerfil.p_estado == $val} selected{/if}>{$text}</option> {/foreach} </select> </div> </div> <div class="buttons"> <input type="button" value="Guardar" onclick="cuenta.guardar_datos()" class="mBtn btnOk"> </div> </fieldset> <div class="clearfix"></div> </div> 9 - Ahora se viene lo genial, busca en tema/js/cuenta.js , justo antes que empieza var avatar = { var cuenta = {... HASTA ... } y lo reemplazas por var cuenta = { alerta: (alerta) => { $(".alert-cuenta").show(); $("#alerta_guarda").html(`<div style="background:#FFFFCC;text-align:center;margin-bottom: 10px;"><p style="display: block;font-size: 16px;padding: 10px 0;">${alerta}</p></div>`) window.scrollTo(0, 0) // Despues de 5s quitamos el alerta setTimeout(() => $("#alerta_guarda").html(''), 5000) }, chgpais: () => { // Campo pais const pais = $("select[name=pais]").val(); const estado = $("select[name=estado]"); if(empty(pais)) estado.addClass('disabled').attr('disabled', 'disabled').val(''); else { //Obtengo las estados $(estado).html(''); $('#loading').fadeIn(250); $.get(global_data.url + '/registro-geo.php', 'pais_code=' + pais, h => { if(h.charAt(0) === '1') estado.append(h.substring(3)).removeAttr('disabled').val('').focus(); $('#loading').fadeOut(250); }) } }, guardar_datos: () => { $('#loading').slideDown(250); $.ajax({ type: 'post', url: global_data.url + '/cuenta-guardar.php', data: $("form[name=editarcuenta]").serialize(), dataType: 'json', success: response => cuenta.alerta(response.error) }); } } Eso sería todo, espero no olvidarme de ningún paso.