Jump to content
  • Sky
  • Blueberry
  • Slate
  • Blackcurrant
  • Watermelon
  • Strawberry
  • Orange
  • Banana
  • Apple
  • Emerald
  • Chocolate
  • Charcoal

Leaderboard


Popular Content

Showing content with the highest reputation since 02/08/22 in all areas

  1. 4 points
    Hola a [email protected], os dejo unas capturas de un tema que se está desarrollando, dejad vuestros comentarios aquí o en mi foro de que os parece, que cambiar o incluir. Gracias y saludos. Se han actualizado todas las librerías del sistema, ya que las versiones anteriores tenían riesgos conocidos en la seguridad que ponen en peligro los sitios web con esas versiones al público. Se ha creado un nuevo diseño versión Dark, la cual hemos llamado Cerberus. Funcionalidad completa con php 8.1.6 y anteriores, dejando la retrocompatibilidad con todas las versiones de php hasta ahora conocidas. Se han modificado y re estilizado los esquemas agregando un diseño mejorado, limpio y responsivo, que es lo más importante para un sitio web de actualidad. Se han corregido muchísimos errores en la actualización del sistema, ya que la versión anterior Risus 1.3 tenía bastantes errores que ya se han corregido y otros debido a todas las actualizaciones de librerías y repositorios de terceros. Algunas funcionalidades y mejoras fueron agregadas para darle un toque más parecido a lo que buscan los usuarios que usan Risus. Se ha mejorado el sistema en rendimiento y funcionalidad, colocando nuevas rutinas, funciones y correcciones de cosas que no funcionaban según reportes de usuarios.
  2. 4 points
    @Isidro, @Mari0x compro el foro, si lo quieres vender yo lo compro y le doy una nueva vida, mandarme lo que sea y podemos llegar a un acuerdo.
  3. 3 points
    Hola queridos PHPosteros, después de un tiempo vengo a traer un poco mas de información con respecto al proyecto. Hoja de Ruta Para definir un camino tenemos que saber hacia adonde vamos. PHPost seguirá el camino del "Social Community Script" posicionándose como la plataforma por excelencia para crear sitios de alto trafico comunicativo y social. ¿Como? Desarrollando un script ligero, seguro, actualizado, escalable y por supuesto, amigable al usuario final. ¿Que nos permite realizar el script actualmente (usuario final)? *Crear/Editar/Eliminar/Compartir = CEEC Crear una cuenta de usuario Modificar perfil de usuario + avatar + portada + bio CEEC Post que contengan texto + imágenes + links CEEC Shouts/Estados en portada CEEC Comentarios en post, shouts/estados Enviar mensajes privados a otros usuarios Puntuar post Subir fotos CEEC las llamadas comunidades o grupos Administrador CEE Usuarios Aplicar BAN por IP Subir e instalar themes CEE Categorías de publicaciones CEE todos los post CEE Rangos de usuarios por evento o personalizado etc... Esto de forma nativa y en su versión 1.3 Entonces... ¿Que esperamos del script a futuro? Esperamos desarrollar e implementar varias mejoras de seguridad y autorización 2FA nativo Social Login nativo Gestión de mods y themes desde la administración del sitio Sistema de licencias de instalación Mejoras visuales Nueva imagen de portada Disposición de publicaciones en home Re-diseño de la administración Modo oscuro nativo Diseño full responsive Y mucho mas... Para poder realizar todo esto precisamos de su ayuda, ya que este proyecto es en su mayor parte echo por ustedes. ¿Que precisamos actualmente? ... Diseño de nuevo logotipo para PHPost (abierto a concurso) Ideas de diseño para el home default y sus distintas secciones Mods actuales que deberían ser nativos (podes dejarnos una lista en comentarios) Actualización de nombres de rango default (podes dejarnos una lista en comentarios) Ademas contanos... ¿En que proyectos usarías la plataforma de PHPost? ¿Crees que en PHPost puede haber comercio de mods y themes? ¿Tuviste o tenes alguna web echa con PHPost? Recuerden que pueden visitar nuestra comunidad oficial en Discord https://discord.gg/8FDs5tRCHv
  4. 3 points
    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.
  5. 3 points
    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.
  6. 2 points
    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!
  7. 2 points
    Este "mod" es dual ya que tiene el login y registro, esta realizado de forma que al ingresar a al sitio tengas que registrarte o loguearte de forma obligatoria...una vista previa de como quedará Bueno comencemos 1 - En header.php buscamos define('TS_TEMA', $tsTema); y debajo agregamos # El tipo de inicio define('INICIO_DUAL', TRUE); 2 - Buscamos en index.php // Checamos... if($tsCore->settings['c_allow_portal'] == 1 && $tsUser->is_member == true && $_GET['do'] == 'portal') { // Portal/mi include('inc/php/portal.php'); } else { // Home include('inc/php/posts.php'); } y la reemplazamos por /** * Dependiendo de la configuración * Solo aplicará el dual si ambos son "TRUE" */ if(INICIO_DUAL AND !$tsUser->is_member) include 'inc/php/dual.php'; else { // Checamos... if(intval($tsCore->settings['c_allow_portal']) == 1 && $tsUser->is_member == true && $_GET['do'] == 'portal') { // Portal/mi include('inc/php/portal.php'); } else { // Home include('inc/php/posts.php'); } } 3 - Descargan los archivos y los ponen en las rutas correspondientes * dual.php en inc/php/ * dual.css en tema/css/ * dual.js en tema/js/ * t.dual.tpl en tema/templates/ 4 - Ir a inc/class/c.registro.php y buscan $tsData = array( 'user_nick' => $tsCore->parseBadWords($_POST['nick']), 'user_password' => $tsCore->parseBadWords($_POST['password']), 'user_email' => $_POST['email'], 'user_dia' => $_POST['dia'], 'user_mes' => $_POST['mes'], 'user_anio' => $_POST['anio'], 'user_sexo' => $_POST['sexo'] == 'f' ? '0' : 1, 'user_pais' => strtoupper($_POST['pais']), 'user_estado' => $_POST['estado'], 'user_terminos' => $_POST['terminos'], 'user_captcha' => $_POST['g-recaptcha-response'], 'user_registro' => time(), ); y la reemplazan por $tsData = array( 'user_nick' => $tsCore->parseBadWords($_POST['nick']), 'user_password' => $tsCore->parseBadWords($_POST['password']), 'user_email' => $_POST['email'], 'user_sexo' => $_POST['sexo'] == 'f' ? '0' : 1, 'user_terminos' => $_POST['terminos'], 'user_captcha' => $_POST['response'], 'user_registro' => time(), ); un poco más abajo buscan /** reCAPTCHA **/ $recaptcha = 'https://www.google.com/recaptcha/api/siteverify?secret=' . $tsCore->settings['skey'] . '&response=' . $tsData['user_captcha'] . '&remoteip=' . $tsCore->getIP(); // Obtener respuesta $response = file_get_contents($recaptcha); // Extraer resultado $ext1 = explode('"success":', $response); $ext2 = explode(',', $ext1[1]); // Comprobar resultado $valid = trim($ext2[0]); // Devolver respuesta si es incorrecta if ($valid == 'false') { return 'recaptcha: No hemos podido validar tu humanidad'; } y la reemplazan por /** * Comprobamos el recaptcha v3 */ $response = $tsCore->reCaptcha($tsData['user_captcha']); if (!$response) return 'recaptcha: No hemos podido validar tu humanidad'; más abajo buscamos // INSERTAMOS EL PERFIL db_exec(array(__FILE__, __LINE__), 'query', 'INSERT INTO `u_perfil` (`user_id`, `user_dia`, `user_mes`, `user_ano`, `user_pais`, `user_estado`, `user_sexo`) VALUES (\''.(int)$tsData['user_id'].'\', \''.(int)$tsData['user_dia'].'\', \''.(int)$tsData['user_mes'].'\', \''.(int)$tsData['user_anio'].'\', \''.$tsCore->setSecure($tsData['user_pais']).'\', \''.$tsCore->setSecure($tsData['user_estado']).'\', \''.(int)$tsData['user_sexo'].'\')'); db_exec(array(__FILE__, __LINE__), 'query', 'INSERT INTO `u_portal` (`user_id`) VALUES (\''.$tsData['user_id'].'\')'); y la reemplazamos por db_exec([__FILE__, __LINE__], "query", "INSERT INTO u_perfil (user_id, p_avatar, user_sexo) VALUES({$tsData['user_id']}, 1, {$tsData['user_sexo']})"); db_exec([__FILE__, __LINE__], "query", "INSERT INTO u_portal (user_id) VALUES({$tsData['user_id']})"); # Generamos automaticamente un avatar $avatar = "https://ui-avatars.com/api/?name=$1&background=random&size=160&font-size=0.60&bold=true&length=2"; $copy = "../../files/avatar/$2_$3.jpg"; $sizes = [50, 120]; foreach ($sizes as $size) { copy( str_replace('$1', $tsData['user_nick'], $avatar), str_replace(['$2', '$3'], [$tsData['user_id'], $size], $copy) ) } 5 - Luego en inc/class/c.core.php buscamos /* getIP */ function getIP(){ y arriba agregamos # Función para comprobar reCaptcha v3 public function reCaptcha(string $publico = '') { $http = http_build_query([ 'secret' => $this->settings["skey"], 'response' => $publico, 'remoteip' => $this->getIP() ]); $init = curl_init(); curl_setopt($init, CURLOPT_URL, "https://www.google.com/recaptcha/api/siteverify"); curl_setopt($init, CURLOPT_POST, 1); curl_setopt($init, CURLOPT_POSTFIELDS, $http); curl_setopt($init, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($init); curl_close($init); return json_decode($response, true); } Y eso sería todo, espero no olvidarme de nada! Cualquier problema o duda comenten!
  8. 2 points
    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...
  9. 2 points
    Hola, lo que pides es lo que te deja Miguel y no es feo, si hubieras dejado más detalles de lo que pides, url de tu web (tu caso localhost), el tema que usas... , pues Miguel te lo hubiese adaptado a tu tema, todos los mods están basados en el diseño default, hacer el mod para todos los temas y que cada uno quiere una cosa es una locura. Te ha dejado lo más importante, ahora tú lo único que tienes que hacer es adaptarle el diseño al tema que utilizas y ponerlo a tu gusto. Saludos
  10. 1 point
    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
  11. 1 point
  12. 1 point
    Buenas hoy les voy a compartí un tema que hice hace un tiempo: 99% Responsive no tiene la sección fotos Web Demo USER: demo PASS: demo123 la instalación debe hacerse desde 0 con todo el script porque modifique varias cosas en el backend pero no recuerdo ya que no documente Descargar espero les sirva no recuerdo si me falta alguna consulta pero cualquier error avisan en los comentarios
  13. 1 point
    Queridos amigos, voy a estar dando alojamiento VPS gratis a los que quieran crear una web con PHPost
  14. 1 point
  15. 1 point
    Hay que tomar ideas de las nuevas webs y redes sociales y actualizar tanto el proyecto como el rumbo de este foro
  16. 1 point
    Bueno aqui les dejo a pedido de un user.. La verdad que no me quedo muy claro lo que me pedia. Ya que era poder poner los modulos d elos top user, tops posts, comentarios, No se si lo queria que sea dentro de los post ya que no hay mucho espacio.. Hasi que lo agregue en el lado lateral.. Use el theme de gonzalo V5 asi que para otros temas esto puede cambiar el estylo.. Comenzamos.. En el archivo c.posts.php buscamos : /* lalala */ Y agregamos arriba: /* Top Post General*/ function act_tpost(){ global $tsUser, $tsCore; $query = mysql_query("SELECT p.post_id, p.post_category, p.post_title, p.post_puntos, c.c_seo FROM p_posts AS p LEFT JOIN p_categorias AS c ON c.cid = p.post_category WHERE p.post_status = 0 ORDER BY p.post_puntos DESC LIMIT 10"); $data = result_array($query); // return $data; } /* Top User General*/ function act_tuser(){ global $tsUser, $tsCore; $query = mysql_query("SELECT SUM(p.post_puntos) AS total, u.user_id, u.user_name, u.user_baneado, u.user_posts, u.user_activo FROM p_posts AS p LEFT JOIN u_miembros AS u ON p.post_user = u.user_id WHERE p.post_status = 0 AND u.user_activo = 1 AND u.user_baneado = 0 GROUP BY p.post_user ORDER BY total DESC LIMIT 10"); $data = result_array($query); // return $data; } /* Ultimos TOP comentarios General*/ function act_cuser(){ global $tsUser, $tsCore; $query = mysql_query("SELECT SUM(p.post_comments) AS total, u.user_id, u.user_name, u.user_baneado, u.user_posts, u.user_activo FROM p_posts AS p LEFT JOIN u_miembros AS u ON p.post_user = u.user_id WHERE p.post_status = 0 AND u.user_activo = 1 AND u.user_baneado = 0 GROUP BY p.post_user ORDER BY total DESC LIMIT 10"); $data = result_array($query); // return $data; } /* Ultimos comentarios*/ function act_comuser(){ global $tsUser, $tsCore; $query = mysql_query("SELECT * FROM p_comentarios AS c LEFT JOIN u_miembros AS u ON c.c_user = u.user_id LEFT JOIN p_posts AS p ON p.post_id = c.c_post_id LEFT JOIN p_categorias AS ca ON ca.cid = p.post_category WHERE p.post_status = 0 AND u.user_baneado = 0 AND u.user_activo = 1 ORDER BY c.cid DESC LIMIT 10"); $data = result_array($query); // return $data; } EN el Archivo posts.php Buscamos: // DATOS DEL AUTOR $smarty->assign("tsAutor",$tsPosts->getAutor($tsPost['post_user'])); Y Agregamos abajo: // DATOS TOP POSTS, TOP USUARIOS, TOP COMENTADOR, ULTIMOS COMENTARIOS... $smarty->assign("tsPostpv",$tsPosts->act_tpost()); $smarty->assign("tsUserpv",$tsPosts->act_tuser()); $smarty->assign("tsCompv",$tsPosts->act_cuser()); $smarty->assign("tsComupv",$tsPosts->act_comuser()); En el archivo m.posts_autor.tpl buscamos al final: {/if} y Agregamos despues {include file='modules/m.top_posts_general.tpl'} Agregamos esto a su extras.css #box-top-post{width:100%;height:auto;overflow: hidden; border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;-webkit-border-radius:5px 5px 0 0;-o-border-radius:5px 5px 0 0;} .top-p-g h3{padding: 5px 0 5px 0;color:#FFF;font-weight:bold;font-size:16px;border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;-webkit-border-radius:5px 5px 0 0;-o-border-radius:5px 5px 0 0;} #box-top-post ul li{font-family: Helvetica,Arial;display:block;padding:3px 0 3px 0;}.top-p-g{width:100%;background:#00608A;text-align:center;} #box-top-post ul li a{font-weight: 600;color:#A6A6A6;}.ver-mas-v{background:#EAF7FF;text-align:center;padding: 3px 0 3px 0;border-top:1px solid #81BBE0;}.ver-mas-v a{color:#005CA5;} Y Subimos el archivo m.top_posts_general.tpl a modules/ http://www.mediafire.com/?mkomrn866tmf2k8 Les dejo el archivo + las instruciones en txt para los que lo necesiten.. Espero que les sea de utilidad.. (Los tops son con los datos genrales) Hasta la Proxima..
  17. 1 point
    Que buen mod amigo!
  18. 1 point
    Hola, en mi foro está el archivo de la demo, subes todos los archivos, en el archivo config pones los datos de tu servidor y en la base de datos en la tabla w_configuracion pones la url y demás. Con eso tienes una instalación desde cero ya con la sección de videos instalada. Saludos
  19. 1 point
    Nueva sección de juegos en pruebas, torneos con premios con dinero y tarjetas regalo AliExpress. https://phpost.es/arcade.php
  20. 1 point
    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.
  21. 1 point
  22. 1 point
    Redes sociales en perfil Mejorado y simplificado Esto es una forma mucho más rápida y sencilla de poder añadir redes sociales a su sitio 1 - En inc/class/c.cuenta.php debajo de class tsCuenta { agregan lo siguiente (solo agregan las redes desde aquí y nada más, ya no tienen que agregar más líneas) # Redes sociales disponibles /** * Si van a agregar más debe ser así 'nombre_minuscula => 'nombre_inicial_mayuscula', */ var $redes = [ 'facebook' => 'Facebook', 'twitter' => 'Twitter', 'instagram' => 'Instagram', 'youtube' => 'Youtube', 'twitch' => 'Twitch', ]; Luego un poco más abajo buscamos private function unData($data) $data['p_socials'] = unserialize($data['p_socials']); $data['p_socials']['f'] = $data['p_socials'][0]; $data['p_socials']['t'] = $data['p_socials'][1]; y la reemplazamos por $data["redes"] = $this->redes; $data['p_socials'] = json_decode($data['p_socials'], true); foreach ($this->redes as $name => $valor) $data['p_socials'][$name]; Luego un poco más abajo buscamos function loadHeadInfo($user_id) $data['p_socials'] = unserialize($data['p_socials']); $data['p_socials']['f'] = $data['p_socials'][0]; $data['p_socials']['t'] = $data['p_socials'][1]; y la reemplazamos por $data['p_socials'] = json_decode($data['p_socials'], true); foreach ($this->redes as $name => $valor) $data['p_socials'][$name]; Más abajo buscan // EXTERNAS $facebook = $tsCore->setSecure($tsCore->parseBadWords($_POST['facebook']), true); $twitter = $tsCore->setSecure($tsCore->parseBadWords($_POST['twitter']), true); y la reemplazan por # Redes sociales $red__social = []; foreach ($_POST["red"] as $llave => $id) $red__social[$llave] = $tsCore->setSecure($tsCore->parseBadWords($id), true); allí mismo buscan 'socials' => serialize(array($facebook,$twitter)), y la reemplazan por 'socials' => json_encode($red__social), 2 - Luego en inc/php/perfil.php buscan $smarty->assign("tsInfo",$tsInfo); y debajo agregan $smarty->assign("tsRedes", $tsCuenta->redes); 3 - Despues en tema/templates/modules/m.cuenta_perfil_me.tpl buscan <div class="field"> <label for="ft">Redes sociales</label> <img src="{$tsConfig.default}/images/icons/facebook.png" width="16" height="16" style="margin:5px; float:left" /> <strong>facebook.com/</strong><input type="text" value="{$tsPerfil.p_socials.f}" maxlength="64" name="facebook" id="ft" class="text cuenta-save-2" style="width:204px"><br /> <img src="{$tsConfig.default}/images/icons/twitter.png" width="16" height="16" style="margin:8px 5px 5px 160px; float:left" /> <strong>twitter.com/</strong><input type="text" value="{$tsPerfil.p_socials.t}" maxlength="64" name="twitter" id="ft2" class="text cuenta-save-2" style="margin-top:3px; width:204px"><br /> </div> y la reemplazan por <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> NOTA: En esta parte "{$tsConfig.images}/icons/{$name}.png", deben agregar el icono de la red social que utilicen. Por que "{$name}.png" seria igual a esto "facebook.png", etc. 4 - Por último en tema/templates/modules/m.perfil_sidebar.tpl y arriba de <div style="margin-bottom: 10px"> {$tsConfig.ads_300} </div> agregan esto (En realidad lo pueden poner donde ustedes quieran) {if $tsInfo.p_socials != ''} {foreach $tsRedes key=name item=red} {if $tsInfo.p_socials.$name !== ''} <a class="sitio {$name}" target="_blank" href="https://{$name}.{if $name == 'twitch'}tv{else}com{/if}/{$tsInfo.p_socials.$name}" title="{$red}"><img height="14" width="14" alt="{$name}" src="{$tsConfig.images}/icons/{$name}.png"/></a> {/if} {/foreach} </div> {/if} NOTA: Les debo los iconos de instagram, youtube y twitch Eso sería todo.
  23. 1 point
    Esto es básicamente para el administrador principal con el user_id 1, para evitar que otro administrador meta mano. 1 - En inc/class/c.admin.php buscamos /* saveConfigs() */ function saveConfig() { y arriba agregaremos (Actualizado 25.02.22) # Ejecutamos las consultas! public function executeSQL() { global $tsCore, $tsUser; # Solo administrador principal if($tsUser->is_member AND $tsUser->is_admod === 1 AND intval($tsUser->uid) === 1) { # Cosultas $sqlList = []; $lines = explode("\n", $_POST['sql']); foreach($lines as $sql) { $sql = htmlspecialchars_decode($sql); $sql = str_replace("'", '"', $sql); # Quitamos ; solo si lo tiene if(preg_match("/(.*);/", $sql)) $sql = substr(trim($sql), 0, strlen($sql) - 1); array_push($sqlList, db_exec([__FILE__, __LINE__], 'query', $sql)); } return in_array(true, $sqlList) ? '1: Se ejecut&oacute; correctamente.' : '0: Hubo un error al ejecutar la/s sentencia/s'; } return '0: Solo el administrador principal puede.'; } 2 - En inc/php/ajax/ajax.admin.php buscamos (Actualizado 25.02.22) 'admin-badwords-delete' => array('n' => 4, 'p' => ''), debajo pegamos 'admin-ejecutar-sql' => array('n' => 4, 'p' => ''), más abajo buscamos default: die('0: Este archivo no existe.'); break; y arriba pegamos case 'admin-ejecutar-sql': echo $tsAdmin->executeSQL(); break; 3 - En inc/php/admin.php si tienen agregado esto, bórrenlo, ya no se usará (Actualizado 25.02.22) } elseif($action == 'execute') { if($tsAdmin->executeSQL()) $tsCore->redirectTo($url); else $smarty->assign("tsError", $tsAdmin->executeSQL()); 4 - Luego en tema/templates/t.admin.tpl y buscamos {elseif $tsAction == 'configs'} {include file='admin_mods/m.admin_configs.tpl'} y debajo pegamos {elseif $tsAction == 'execute'} {include file='admin_mods/m.admin_execute.tpl'} 5 - En tema/templates/admin_mods/m.admin_sidemenu.tpl buscamos <h4>Configuración de PHPost</h4> y arriba pegamos <li id="a_execute"><span class="cat-title"><a href="{$tsConfig.url}/admin/execute">Ejecutar consultas </a></span></li> 6 - En tema/templates/admin_mods/ crearemos un archivo llamado m.admin_execute.tpl y agregaremos esto (Actualizado 25.02.22) <div class="boxy-title"> <h3>Administrar Base de datos</h3> </div> <div id="res" class="boxy-content"> {if $tsSave}<div class="alerts ok">Tus cambios han sido guardados.</div>{/if} {if $tsError}<div class="alerts error">Hubo problemas al ejecutar las sentencias.</div>{/if} <h4>Desde aquí tu puedes <u>generar las consultas</u>, antes de hacerlo, comprueba de que este correctamente.</h4> <form method="post" autocomplete="off"> <legend>Consultas</legend> <textarea name="sql" id="sql" cols="30" rows="10" placeholder="EJ: ALTER TABLE w_configuracion ADD privado INT(11) NOT DEFAULT 0;"></textarea> <small style="display:block"><i>Siempre cada consulta debe terminar en ; (punto y coma)</i></small> <input type="button" onclick="database.execute();" value="Enviar consulta" class="mBtn btnOk"/> </form> </div> 7 - En tema/js/admin.js al final del archivo agregan (Actualizado 25.02.22) /** * Database * para ejecutar consultas y crear copias */ var database = new function() { this.execute = () => { $.post(global_data.url + '/admin-ejecutar-sql.php', 'sql=' + $("#sql").val(), 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; } }) } } Eso sería todo, pero úsenlo con mucho cuidado ya que podrían afectar la base de datos, ejemplo quieren eliminar a un usuario y si colocan su id los eliminará a ustedes.. NOTA: Estoy creando algo que incluye esta función, lo cual ustedes van a poder ejecutar consultas, crear copias de seguridad de su base de datos y descargar dicha copia, pero debo averiguar un poco más...
  24. 1 point
    Para las comunidades en el archivo comunidades.php busca $tsLevel = 0; // NIVEL DE ACCESO A ESTA PAGINA. => VER FAQs cambia el valor numérico por: 0: Desde visitantes en adelante. 1: Solo visitantes. 2: Solo miembros. 3: Solo moderadores. 4: Solo administradores.
  25. 1 point
    A partir del punto 4 es válido también para smarty 3
  • Patrocinador



    ×