Merge branch 'more-tests+speedups' into 'dev'

More tests + speed improvements

See merge request hubzilla/core!2243
This commit is contained in:
Mario
2025-11-20 20:49:55 +00:00
10 changed files with 451 additions and 48 deletions

View File

@@ -696,10 +696,9 @@ class Profiles extends \Zotlabs\Web\Controller {
$show_presence = ['show_presence', t('Reveal my online status'), $show_presence_val, '', [t('No'), t('Yes')]];
}
$extra_fields = array();
$q = q("select * from profdef where true");
if($q) {
$extra_fields = array();
foreach($q as $qq) {
$mine = q("select v from profext where k = '%s' and hash = '%s' and channel_id = %d limit 1",
dbesc($qq['field_name']),
@@ -833,6 +832,8 @@ class Profiles extends \Zotlabs\Web\Controller {
);
if($r) {
$profiles = '';
$tpl = get_markup_template('profile_entry.tpl');
foreach($r as $rr) {
$profiles .= replace_macros($tpl, array(

View File

@@ -10,11 +10,140 @@
namespace Zotlabs\Tests\Unit;
use phpmock\phpunit\PHPMock;
use PHPUnit\Framework\Attributes\Before;
class CreateIdentityTest extends UnitTestCase {
use PHPMock;
//
// Static private key used by the openssl stubs.
//
private const PRVKEY = <<<'PRVKEY'
-----BEGIN PRIVATE KEY-----
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
0UH3yDnLoPuCvHeX2WAXdyWob6vBOA==
-----END PRIVATE KEY-----
PRVKEY;
//
// Static public key corresponding to self::PRVKEY, used by the
// openssl_stubs
//
private const PUBKEY = <<<'PUBKEY'
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvIcMderJEy61sNlpW00h
1lF3KRVKV48heeClWtJ/rJql4yHSaAtC1ce1SS9fLX66evbAXy3ClKm8iPQ9We/P
F6jzijyWj4w2CMB5GSX/mDq7z0D/eaAI0kcBQTcTSMypMr9vttgqJV9WWDT3uqw+
VwxXV7Aic8UzMduv/rl4j3tx5EP319WUiTNqnBgXZpffCm1zONo3fi3q5kpZuRL0
d28aYpXzyKt1kOBQe31OUVHt57imhVYZfpLVI7kp4tAxfbbRp5KDj5v0F0ElvwGy
N+5KX5G3KhCRiMdJ1mBLFWeXE7PeJQSvxIhCD5CTTgoSjjzuzsqd/WNUJdze9q+p
9xQzzGasQio1/kCPGmJLJhqpsvHF+YiMPgIP86w3wWwqAbO1imS/QgdqTMWT1/7T
mLx22JMK/vIyZ5ZlOjOF/tBBi0Ls2iBwfl1uLRm1ILfXc2kwX7byWxmE5cFENLe+
C3gzFLL7gsU9rLx5lTMg+mNWFT6OLZZUeNe9AN4muziXWeMpI/wAabEaAc6F67Cp
Vv/VKhFbEB9S7rddzDC3vsSfVypa/Sqq+EBmMeTqIT5+PBMpVVA+/O2wzef44+pE
NFFB3eoCswxl+S22A75OtJ1MuCh7D5rCMR7ptLWCt4YQ9kgxfOPjZzbvJEkm25+Z
ZAjxDyWHEoxQr8oS6Fg1Lz8CAwEAAQ==
-----END PUBLIC KEY-----
PUBKEY;
private bool $queueworker_started = false;
public function test_empty_args() {
#[Before]
public function setup_openssl_mocks(): void {
//
// The `create_identity` function will call `Crypto::new_keypair()`,
// which again will call `openssl_pkey_new`, to create a new
// private/public keypair for the channel. While this is safe to call
// from the code under test, it's also slow.
//
// Since we don't really care about the cryptography here, we can make
// the tests run a bit faster by stubbing the slow function call and
// return a sentinel value instead of actually generaing the keys.
//
$openssl_pkey_new =
$this->getFunctionMock('Zotlabs\Lib', 'openssl_pkey_new')
->expects($this->any())
->willReturn('openssl_pkey_result');
//
// Since we have stubbed `openssl_pkey_new` we also need to mock the
// call to `openssl_pkey_export` that is used to get the private key
// from the result of `openssl_pkey_new`.
//
// As this function returns the value in a output param, we need to
// replace it with a callback function to simulate it.
//
$openssl_pkey_export =
$this->getFunctionMock('Zotlabs\Lib', 'openssl_pkey_export')
->expects($this->any())
->willReturnCallback(function (string $result, string &$response): bool {
$this->assertEquals('openssl_pkey_result', $result);
$response = self::PRVKEY;
return true;
});
//
// Finally we also need to stub the `openssl_pkey_get_details` function
// used to retrevive the public key from the `openssl_pkey_new` result.
//
$openssl_pkey_get_details =
$this->getFunctionMock('Zotlabs\Lib', 'openssl_pkey_get_details')
->expects($this->any())
->with($this->identicalTo('openssl_pkey_result'))
->willReturn([ 'key' => self::PUBKEY ]);
}
public function test_empty_args_fails_with_an_error_message() {
insert_hook('proc_run', [$this, 'proc_run_hook']);
$result = create_identity([]);
$this->assertEquals(

View File

@@ -0,0 +1,118 @@
<?php
/*
* SPDX-FileCopyrightText: 2025 The Hubzilla Community
* SPDX-FileContributor: Harald Eilertsen <haraldei@anduin.net>
*
* SPDX-License-Identifier: MIT
*/
namespace Zotlabs\Tests\Unit\Lib;
use PHPUnit\Framework\Attributes\TestWith;
use Zotlabs\Lib\Zotfinger;
use Zotlabs\Tests\Unit\UnitTestCase;
use phpmock\phpunit\PHPMock;
class ZotfingerTest extends UnitTestCase
{
// Import PHPMock methods into this class
use PHPMock;
#[TestWith([null])]
#[TestWith([false])]
#[TestWith([''])]
public function testShouldReturnFalseOnNoResource($resource): void
{
$this->assertFalse(Zotfinger::exec($resource));
}
public function testShouldReturnFalseIfResourceNotFound(): void
{
//
// Mock z_post_url to prevent it fram connecting to an actual remote site,
// and so that we can control what it should return.
//
// Here we simulate a request that return 404 Not Found.
//
$mock = $this->getFunctionMock('Zotlabs\Lib', 'z_post_url')
->expects($this->once())
->willReturn([
'return_code' => 404,
'success' => false,
]);
$this->assertFalse(Zotfinger::exec('https://example.test/some-resource'));
}
public function testShouldReturnBodyIfResourceFound(): void
{
//
// Mock z_post_url to prevent it fram connecting to an actual remote site,
// and so that we can control what it should return.
//
// Here we simulate a request returning 200 OK and some data
//
$mock = $this->getFunctionMock('Zotlabs\Lib', 'z_post_url')
->expects($this->once())
->willReturn([
'return_code' => 200,
'success' => true,
'body' => '{"subject":"acct:user@example.test"}',
]);
//
// Initialize some $_SERVER superglobal values needed by HTTPSig:
//
$_SERVER['REQUEST_METHOD'] = 'GET';
$_SERVER['REQUEST_URI'] = 'some_uri';
$_SERVER['CONTENT_TYPE'] = 'application/json';
$_SERVER['CONTENT_LENGTH'] = 42;
$result = Zotfinger::exec('https://example.test/some-resource');
//
// Verify that the json payload has been decoded
//
$this->assertIsArray($result['data']);
$this->assertArrayHasKey('subject', $result['data']);
$this->assertEquals('acct:user@example.test', $result['data']['subject']);
}
public function testThatRequestFromChannelIsSigned(): void
{
//
// Mock z_post_url to prevent it fram connecting to an actual remote site,
// and so that we can control what it should return.
//
// Here we simulate a request returning 200 OK and some data
//
$mock = $this->getFunctionMock('Zotlabs\Lib', 'z_post_url')
->expects($this->once())
->willReturn([
'return_code' => 200,
'success' => true,
'body' => '{"subject":"acct:user@example.test"}',
]);
//
// Initialize some $_SERVER superglobal values needed by HTTPSig:
//
$_SERVER['REQUEST_METHOD'] = 'GET';
$_SERVER['REQUEST_URI'] = 'some_uri';
$_SERVER['CONTENT_TYPE'] = 'application/json';
$_SERVER['CONTENT_LENGTH'] = 42;
$channel = $this->fixtures['channel'][0];
$testresult = Zotfinger::exec('https://example.test/some-resource', $channel);
//
// Verify that the json payload has been decoded
//
$this->assertIsArray($testresult['data']);
$this->assertArrayHasKey('subject', $testresult['data']);
$this->assertEquals('acct:user@example.test', $testresult['data']['subject']);
}
}

View File

@@ -76,13 +76,6 @@ class MagicTest extends TestCase {
'xchan_hash' => 'foreign hash',
]);
// Create the channel the foreign observer wants to access
$result = create_identity([
'account_id' => $this->fixtures['account'][0]['account_id'],
'nickname' => 'testuser',
'name' => 'Trish Testuser',
]);
// Shortcut the permission checks, by saying this observer is allowed
// the delegate privilege over the target channel
insert_hook('perm_is_allowed', function (array &$perm) {
@@ -101,18 +94,20 @@ class MagicTest extends TestCase {
// assertions after the redirect is thrown.
$this->stub_goaway();
$channel = $this->fixtures['channel'][1];
try {
// Send a request to get delegate privileges for the `testuser` channel
// on the local hub.
$this->get('magic', [
'bdest' => bin2hex($dest_url),
'delegate' => 'testuser@hubzilla.test']
);
'delegate' => channel_reddress($channel)
]);
} catch (RedirectException $e) {
$this->assertEquals($dest_url, $e->getMessage());
$this->assertEquals($result['channel']['channel_id'], App::$channel['channel_id']);
$this->assertEquals($channel['channel_id'], App::$channel['channel_id']);
$this->assertEquals($original_session, $_SESSION['delegate_push']);
$this->assertEquals($result['channel']['channel_id'], $_SESSION['delegate_channel']);
$this->assertEquals($channel['channel_id'], $_SESSION['delegate_channel']);
$this->assertEquals('foreign hash', $_SESSION['delegate']);
$this->assertEquals($this->fixtures['account'][0]['account_id'], $_SESSION['account_id']);
}

View File

@@ -0,0 +1,100 @@
<?php
/*
* SPDX-FileCopyrightText: 2025 The Hubzilla Community
* SPDX-FileContributor: Harald Eilertsen <haraldei@anduin.net>
*
* SPDX-License-Identifier: MIT
*/
namespace Zotlabs\Tests\Unit\Module;
use App;
use PDOStatement;
/**
* Tests for the Profiles module
*/
class ProfilesTest extends TestCase
{
public function testDisplaysProfileEditFormIfMultiProfilesDisabled(): void {
// Set up the channel we'll be making the request for
$channel = $this->fixtures['channel'][0];
App::set_channel($channel);
// And set up the default profile
$this->createDefaultProfile($channel);
// Replace calls to 'local_channel' and make sure they return
// the id of the current channel.
$local_channel_mock =
$this->getFunctionMock('Zotlabs\Module', 'local_channel')
->expects($this->any())
->willReturn($channel['channel_id']);
// Replace calls to 'feature_enabled', and make it unconditionally
// return true. This is called by the Profiles module to check that
// multiple profiles are enabled.
$feature_enabled_mock =
$this->getFunctionMock('Zotlabs\Module', 'feature_enabled')
->expects($this->any())
->willReturn(false);
// Simulate a GET request to the module
$this->get('profiles');
// Check that the rendered page has the expected entry.
$this->assertPageContains('<form id="profile-edit-form"');
}
public function testListDefaultProfileWithNoArgs(): void {
// Set up the channel we'll be making the request for
$channel = $this->fixtures['channel'][0];
App::set_channel($channel);
// And set up the default profile
$this->createDefaultProfile($channel);
// Replace calls to 'local_channel' and make sure they return
// the id of the current channel.
$local_channel_mock =
$this->getFunctionMock('Zotlabs\Module', 'local_channel')
->expects($this->any())
->willReturn($channel['channel_id']);
// Replace calls to 'feature_enabled', and make it unconditionally
// return true. This is called by the Profiles module to check that
// multiple profiles are enabled.
$feature_enabled_mock =
$this->getFunctionMock('Zotlabs\Module', 'feature_enabled')
->expects($this->once())
->willReturn(true);
// Simulate a GET request to the module
$this->get('profiles');
// Check that the rendered page has the expected entry.
$this->assertPageContains('Default Profile');
}
/**
* Helper function to create the default profile for a channel
*
* @param array $channel An associative array containing the channel.
*/
private function createDefaultProfile(array $channel): void {
$res = profile_store_lowlevel([
'aid' => intval($channel['channel_account_id']),
'uid' => intval($channel['channel_id']),
'profile_guid' => random_string(),
'profile_name' => t('Default Profile'),
'is_default' => 1,
'publish' => true,
'fullname' => $channel['channel_name'],
'photo' => z_root() . "/photo/profile/l/{$channel['channel_id']}",
'thumb' => z_root() . "/photo/profile/m/{$channel['channel_id']}"
]);
$this->assertInstanceOf(PDOStatement::class, $res);
$this->assertEquals('00000', $res->errorCode());
}
}

View File

@@ -0,0 +1,60 @@
---
hubloc:
- # sys channel
hubloc_guid: uGp_IvDBQ7b_-s3HV7IehysbKFyx1w0oG4dm1Q3-trFlnw01H-rJhNRQ8QNdDRSiolJmIMizCiexogrHy3_kpg
hubloc_guid_sig: sha256.bawP2sNBcfnjpKx2OCMlISbLJBByejs0KkbWcKvFj_vfQ_TnKvTZ9PvfxPz0puUkSqaJVskwz7mY59d56aRqc3kTCniuuR_3L8padNElwkyqoPLgIBQlffeqoa0ax0R_kF667_MmlUj6F6RyQHuCNeElWRfy0LW4SzIsn72ogHevvbOa5gh27jDcjUqkY5C0i8wyxEHzI5Ue4zNwJ7JS6WETZVL_z2WgFemKagZ8SWNVdFQfHCmhJ-scBZZK9rM0rdLf1O9HjkxgdvzImSHH3ODT-qOfE-IKwlum0hCUJqmGwOQAHTydRHKn-pdEHX1eFE_Y15lwBPToyQW1zTso9PPzwRXKqJkrqapO6hqerRCWqI5dtgE_6Up3AFolWCU82h5to0Y5LT2iEvMids9x64laGKNw-bzdYpJtKZZqgxejchIuYoqZZJp4ivGzHeJktBveTCluP2lRXw2W1TupMOVADlfUGPFMTYj2LPPIp3CTD6RsSZobh9VvT22J1SzwwTFvHG2VoZbezOPKvWj-PHRb3iBTSYoQAgL8ecI4oWnn9HK-KHwUsoWOtIXDSKVRiySun3AXGjI8iIVI7ORk7-33aVrxuVuh76_ni7LEadFFGClbxZtzoM44QizkPDHVS4rYl1fsuYDbxr93FvG7_QCBsOzgfWgE2eN65poE7mU
hubloc_hash: de3-bhcFpdY5PZ-ef4vy-6PpSeGrEHB8DNQFC6uP9lG-RkPaMceUMdvIRYHvHIvRzjJ0RPII2sJ1ffz4ATQOHQ
hubloc_id_url: https://hubzilla.test/channel/sys
hubloc_addr: sys@hubzilla.test
hubloc_primary: 1
hubloc_url: https://hubzilla.test
hubloc_url_sig: sha256.ORRyOWqsjER4i_Vx2HN5u_4u6djHb7NDEixTssCK9L-tpfBcbDmJD32pVgQvGs4UPexqlvIj7AwE-_fju2xlc_ZaI7UfII20Re0DWYfZR5xiexPxSbxtoUu-VuHoFNLjfnAwvj3Xleg_TQ4UBc5ap1_F0B7FsctOpx6P9ot_0tD7qDmyeiyU3OCCqDhAUASRYoXbkxzAZCSMHHT0Dnjz0IDJ8avi2FvrUns-ThKypxqyXzPz1Ie-Fz9XzdTCohrXUFixcIhIkUBtrL_pUe-Al6SVjICTqtoXNITqN5DEQLDEX5ObFiVotKZztg_IJxx6bzVta6e-9_Wu3ikM4DwFM-i_Lyybxoc745BnKVtZUfk4X3HF4_z0JLFW9YobcLzKU4KJgP4fMbmjEznqk4UXB_pGm-EgW90vou18Yi0_m4pGvQJgW2xRgioEDUNrkcBo6O_ej8Y71hsDfkv6SDNxqC-eZ6YFLYN5cJ2TKS05GXYCMdOrmtvH4TMEyxbwe0lfZa5eBSZby2qp26Ler51kft-VaZeXDowtK5Qr6Gg3YNCYHjBdeJz_ks9M9JUJqV-SHsRV2mC9OnFxkMGIzV1oRhn91wgJKMDJn6tEZDCXHVCcuC-4l7GstKRT-UbpqtkV__NYWuE9L3yvwXEDT9FXBw0hljBIn5EsG2CPkvFrf0U
hubloc_site_id: xJFCfYhhPGPqHeDsNQKjaY9EdS0iLJmV5lvuR3rFi09LOwwt0uN6adhJND5gyzs-3EEILSG_OY7zPAUKSnMa6w
hubloc_host: hubzilla.test
hubloc_callback: https://hubzilla.test/zot
hubloc_sitekey: |
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAquJ4YP2qctsfxG2nTmGU
/yIojix38qGkDyEarmtLUfn7Rm+sg1zT1IjW3Zvw/q4rmK8zfC9doCFR6Z9zU6/v
XlFDCY+EJ2vdw5U+D/OijvnDLABkOS1iKRII9225olh1ZbB2QpLq3tC1SbE04Wy6
fTuyehBrufrvqDXX+CyUYYbCiVtMv01v6Lr8Qc498afASlOJd2spoGcppeNlqL8u
6Ipf+fMoo89oIn5JOk3aLvKu+33i1NbVzC3NrVRjWV+D7MQgCroDAYHujNA1Kkuw
QxYlxy+exeSnHD6YzZ1lAFHZSc+xPXQVc6wCFMuruk9KymrGNh5V4lFoU+Bm1bLw
5berLIpQn8jKffZulSPeWcPw0cBQWgKMk3uEW1H6vJggepjunnjINDW7RvP7Thma
wVmU45EUeL3uzZR2JO+gX+Ay3oLCBTNCFrIa1U/cgrdXgTLBKT6JVfLaVPWMxqfA
n7f9e9DryEcB2pIq1l1CfUPMZdSYCI3pAT53io4imaUsB2HzWO39Ie1fGaHOo1Mk
MCSny0ySLRTGeefYJur3LCCyGkxpxGxFzqmCG2oF0UdQgw6rf8ENjojG3KyGNeYO
fkOd1kzv22NI8Zs+LEJQdkXWz16EeP8ZViZZ3lnG2lViFXAK3f4/U/fpuLCuMUi7
pDhncIFqrTPRozFWL0xbPAsCAwEAAQ==
-----END PUBLIC KEY-----
hubloc_network: zot6
hubloc_updated: 2025-11-19T21:27:19
- # test channel
hubloc_guid: "NTHCKiCblxvlLxdlu5SpOqoC_EWtKFqHEg6nc2Ps5X_UGJAfPBzENdOagS_IBC75RIQNtAYizZeobnpv0CEinA"
hubloc_guid_sig: "sha256.cLzCjVb_kgDUsXg-SM2qnn-DQ55cRcXlbPeigeWtnT_pjlCD7Pg6trcLa12s3iPup4dudG9MIZkjuwBUUBv25mVER9w97NGYCqLx1OGFbjuuAuZJzYHMZLiWSfv4PNzjvkB4sOAsCY6CBCcpg6rno55FxFhJNz10zTYkaqJQbS2zKnBnxqseXEwULKDgBbU8yapP1BX505FedcJR3MyVMYg0teiINOFywTjKQHOm_Pe6mmU_wblOy7eWLfoWXU9lq_Z9D47UTgeJd0IB89btcF0WsfyUhg3NNLE_kpfk2Ow-DBO9Joz64qoBe8Ri68pnom5LPgGTWwGWJnSud123ZfTDLzFg1h9sFMcJMiMzvJnvFm4puKKu4K0jYNkAp0DROnaqadreACU5y_vOQyCT0aiicIX3uPkKGhNbwSjcquOylzricqgaZeK6iOOb_iHRLuQd4lJgYShr9xqBk2LU31QnWO3QUmBVlVPpM26YeoulmwVsoOSxC7QcLjYmQCgYpGOUaWWxGlJSwDyvm4DKiG88hp_clzN4MDilycVmS_JvmYxsw1Do_RDeDRxq0xLnqtBZpnafEjm-LXkZGVYJ5kqvEtl3DmPai2Wzrnyb24XxGmAhOZo1NvfjrvRWtFN-uNXLHKDZEcEqogmiqMUd20XMh1YGLqH2IsvbPyYShXo"
hubloc_hash: "LAOCZBv-Cj6QVab_EpMFV6HIDmsUSDybKfSnH9I5cwYAkar4UvBcsj9ofsaIejYLTfgMy9BcGPWjy9-7Uk7rlQ"
hubloc_id_url: https://hubzilla.test/channel/test
hubloc_addr: test@hubzilla.test
hubloc_primary: 1
hubloc_url: https://hubzilla.test
hubloc_url_sig: sha256.t8AdUv_uurSc1RMM5lHuifGxceSLuX6-fT5I4KflJg16qO6u1dUuAVcH1pWA0rYIi0J9LL0rSCAfGgwa53wx5-C8Vt1TfMVoz0xyUTFJLd6FeLKRrYKQBj2Bos1VjHlXKj3Pn1455dacvDTXhg7t1WISaBMdzNlPQrTQnZPgNEy7cnPVmLkHuu5SVtYtT3mFiZXXUbaK4nFuw3lR83WVauCFIiKm8kcFSWtsLJzTMlx2NDOxTO-IMiSYXU4KwhcxmzLOqWQrT_vBDJNrny3jm79lIu5DJDCJdoVp2pwL72c3Esi5NhUKMPG7dyH4tKev5Ug3z4MUEaF_DvtDMgC0hAEtE3sE6wzqp4Fg6zLLE7V3wZI5cOpdjeL8-3TJokKJoUCDwKUwcLMyd9vbJKDN5QPtVKguLb7-QCfFZHA-xEoZlBW5gRptan9fTE3-3jRJF0PIywOM9YpwbLWaaUikQ8BHkS_pCVjAM7wiFfJzD6ocQhz5mKC-HQsABCck_jYzzjHzE4lfVziPN3arS_1tPFwDFsdk7Q04gOJ2F--DRBqY6R_iajZq0aDQgXelFk4B_BVU2N8zaom-0djQw16RPWchzMk8A1ablZ53P-D5IlWaJhL8BUEUtrKCrAqh6ecoQGYBwGitIy2FP2M0qfDiyTxkqnx31lW04Uk2tOFtJWI
hubloc_site_id: xJFCfYhhPGPqHeDsNQKjaY9EdS0iLJmV5lvuR3rFi09LOwwt0uN6adhJND5gyzs-3EEILSG_OY7zPAUKSnMa6w
hubloc_host: hubzilla.test
hubloc_callback: https://hubzilla.test/zot
hubloc_sitekey: |
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAquJ4YP2qctsfxG2nTmGU
/yIojix38qGkDyEarmtLUfn7Rm+sg1zT1IjW3Zvw/q4rmK8zfC9doCFR6Z9zU6/v
XlFDCY+EJ2vdw5U+D/OijvnDLABkOS1iKRII9225olh1ZbB2QpLq3tC1SbE04Wy6
fTuyehBrufrvqDXX+CyUYYbCiVtMv01v6Lr8Qc498afASlOJd2spoGcppeNlqL8u
6Ipf+fMoo89oIn5JOk3aLvKu+33i1NbVzC3NrVRjWV+D7MQgCroDAYHujNA1Kkuw
QxYlxy+exeSnHD6YzZ1lAFHZSc+xPXQVc6wCFMuruk9KymrGNh5V4lFoU+Bm1bLw
5berLIpQn8jKffZulSPeWcPw0cBQWgKMk3uEW1H6vJggepjunnjINDW7RvP7Thma
wVmU45EUeL3uzZR2JO+gX+Ay3oLCBTNCFrIa1U/cgrdXgTLBKT6JVfLaVPWMxqfA
n7f9e9DryEcB2pIq1l1CfUPMZdSYCI3pAT53io4imaUsB2HzWO39Ie1fGaHOo1Mk
MCSny0ySLRTGeefYJur3LCCyGkxpxGxFzqmCG2oF0UdQgw6rf8ENjojG3KyGNeYO
fkOd1kzv22NI8Zs+LEJQdkXWz16EeP8ZViZZ3lnG2lViFXAK3f4/U/fpuLCuMUi7
pDhncIFqrTPRozFWL0xbPAsCAwEAAQ==
-----END PUBLIC KEY-----
hubloc_network: zot6
hubloc_updated: 2025-11-19T21:57:19

View File

@@ -1,6 +1,6 @@
<div id="{{$field.0}}_container" class="clearfix onoffswitch checkbox mb-3">
<label for="id_{{$field.0}}">{{$field.1}}{{if $field.6}}<sup class="required zuiqmid"> {{$field.6}}</sup>{{/if}}</label>
<div class="float-end"><input type="checkbox" name="{{$field.0}}" id="id_{{$field.0}}" value="1" {{if $field.2}}checked="checked"{{/if}} {{if $field.5}}{{$field.5}}{{/if}} /><label class="switchlabel" for='id_{{$field.0}}'> <span class="onoffswitch-inner" data-on='{{if $field.4}}{{$field.4.1}}{{/if}}' data-off='{{if $field.4}}{{$field.4.0}}{{/if}}'></span><span class="onoffswitch-switch"></span></label></div>
<label for="id_{{$field.0}}">{{$field.1}}{{if isset($field.6)}}<sup class="required zuiqmid"> {{$field.6}}</sup>{{/if}}</label>
<div class="float-end"><input type="checkbox" name="{{$field.0}}" id="id_{{$field.0}}" value="1" {{if $field.2}}checked="checked"{{/if}} {{$field.5|default:''}} ><label class="switchlabel" for='id_{{$field.0}}'> <span class="onoffswitch-inner" data-on='{{if $field.4}}{{$field.4.1}}{{/if}}' data-off='{{if $field.4}}{{$field.4.0}}{{/if}}'></span><span class="onoffswitch-switch"></span></label></div>
<small class="form-text text-muted">{{$field.3}}</small>
</div>
{{*

View File

@@ -11,7 +11,7 @@
{{if isset($field.5)}}{{$field.5}}{{/if}}
>
<small id="help_{{$field.0}}" class="form-text text-muted">
{{$field.3}}
{{$field.3|default:''}}
</small>
</div>
{{*

View File

@@ -1,5 +1,5 @@
<div class="mb-3">
<label for="id_{{$field.0}}">{{$field.1}}</label>
<textarea class="form-control" name="{{$field.0}}" id="id_{{$field.0}}" {{if $field.4}}{{$field.4}}{{/if}} >{{$field.2}}</textarea>
<small class="form-text text-muted">{{$field.3}}</small>
<textarea class="form-control" name="{{$field.0}}" id="id_{{$field.0}}" {{$field.4|default:''}}>{{$field.2}}</textarea>
<small class="form-text text-muted">{{$field.3|default:''}}</small>
</div>

View File

@@ -225,7 +225,7 @@
{{/if}}
{{if $fields.address || $fields.locality || $fields.postal_code || $fields.region || $fields.country_name || $fields.hometown}}
{{if isset($fields.address) || isset($fields.locality) || isset($fields.postal_code) || isset($fields.region) || isset($fields.country_name) || isset($fields.hometown)}}
<div class="panel">
<div class="section-subtitle-wrapper" role="tab" id="location">
<h3>
@@ -236,27 +236,27 @@
</div>
<div id="location-collapse" class="panel-collapse collapse" data-bs-parent="#profile-edit-wrapper" role="tabpanel" aria-labelledby="location">
<div class="section-content-tools-wrapper">
{{if $fields.address}}
{{if $fields.address|default:false}}
{{include file="field_input.tpl" field=$address}}
{{/if}}
{{if $fields.locality}}
{{if $fields.locality|default:false}}
{{include file="field_input.tpl" field=$locality}}
{{/if}}
{{if $fields.postal_code}}
{{if $fields.postal_code|default:false}}
{{include file="field_input.tpl" field=$postal_code}}
{{/if}}
{{if $fields.region}}
{{if $fields.region|default:false}}
{{include file="field_input.tpl" field=$region}}
{{/if}}
{{if $fields.country_name}}
{{if $fields.country_name|default:false}}
{{include file="field_input.tpl" field=$country_name}}
{{/if}}
{{if $fields.hometown}}
{{if $fields.hometown|default:false}}
{{include file="field_input.tpl" field=$hometown}}
{{/if}}
@@ -281,7 +281,7 @@
</div>
<div id="relation-collapse" class="panel-collapse collapse" data-bs-parent="#profile-edit-wrapper" role="tabpanel" aria-labelledby="relation">
<div class="section-content-tools-wrapper">
{{if $fields.marital }}
{{if $fields.marital|default:false }}
<div id="profile-edit-marital-wrapper" class="mb-3 field" >
<label id="profile-edit-marital-label" for="profile-edit-marital" ><span class="heart"><i class="bi fa-heart"></i>&nbsp;</span>{{$lbl_marital}}</label>
{{if $advanced}}
@@ -292,16 +292,16 @@
</div>
<div class="clear"></div>
{{if $fields.partner}}
{{if isset($fields.partner)}}
{{include file="field_input.tpl" field=$with}}
{{/if}}
{{if $fields.howlong}}
{{if isset($fields.howlong)}}
{{include file="field_input.tpl" field=$howlong}}
{{/if}}
{{/if}}
{{if $fields.sexual}}
{{if isset($fields.sexual)}}
<div id="profile-edit-sexual-wrapper" class="mb-3 field" >
<label id="profile-edit-sexual-label" for="sexual-select" >{{$lbl_sexual}}</label>
{{if $advanced}}
@@ -321,7 +321,7 @@
</div>
</div>
{{/if}}
{{if $fields.keywords || $fields.politic || $fields.religion || $fields.about || $fields.contact || $fields.homepage || $fields.interest || $fields.likes || $fields.dislikes || $fields.channels || $fields.music || $fields.book || $fields.tv || $fields.film || $fields.romance || $fields.employment || $fields.education || $extra_fields}}
{{if isset($fields.keywords) || isset($fields.politic) || isset($fields.religion) || isset($fields.about) || isset($fields.contact) || isset($fields.homepage) || isset($fields.interest) || isset($fields.likes) || isset($fields.dislikes) || isset($fields.channels) || isset($fields.music) || isset($fields.book) || isset($fields.tv) || isset($fields.film) || isset($fields.romance) || isset($fields.employment) || isset($fields.education) || isset($extra_fields)}}
<div class="panel">
<div class="section-subtitle-wrapper" role="tab" id="miscellaneous">
<h3>
@@ -332,71 +332,71 @@
</div>
<div id="miscellaneous-collapse" class="panel-collapse collapse" data-bs-parent="#profile-edit-wrapper" role="tabpanel" aria-labelledby="miscellaneous">
<div class="section-content-tools-wrapper">
{{if $fields.homepage}}
{{if isset($fields.homepage)}}
{{include file="field_input.tpl" field=$homepage}}
{{/if}}
{{if $fields.keywords}}
{{if isset($fields.keywords)}}
{{include file="field_input.tpl" field=$keywords}}
{{/if}}
{{if $fields.politic}}
{{if isset($fields.politic)}}
{{include file="field_input.tpl" field=$politic}}
{{/if}}
{{if $fields.religion}}
{{if isset($fields.religion)}}
{{include file="field_input.tpl" field=$religion}}
{{/if}}
{{if $fields.about}}
{{if isset($fields.about)}}
{{include file="field_textarea.tpl" field=$about}}
{{/if}}
{{if $fields.contact}}
{{if isset($fields.contact)}}
{{include file="field_textarea.tpl" field=$contact}}
{{/if}}
{{if $fields.interest}}
{{if isset($fields.interest)}}
{{include file="field_textarea.tpl" field=$interest}}
{{/if}}
{{if $fields.likes}}
{{if isset($fields.likes)}}
{{include file="field_textarea.tpl" field=$likes}}
{{/if}}
{{if $fields.dislikes}}
{{if isset($fields.dislikes)}}
{{include file="field_textarea.tpl" field=$dislikes}}
{{/if}}
{{if $fields.channels}}
{{if isset($fields.channels)}}
{{include file="field_textarea.tpl" field=$channels}}
{{/if}}
{{if $fields.music}}
{{if isset($fields.music)}}
{{include file="field_textarea.tpl" field=$music}}
{{/if}}
{{if $fields.book}}
{{if isset($fields.book)}}
{{include file="field_textarea.tpl" field=$book}}
{{/if}}
{{if $fields.tv}}
{{if isset($fields.tv)}}
{{include file="field_textarea.tpl" field=$tv}}
{{/if}}
{{if $fields.film}}
{{if isset($fields.film)}}
{{include file="field_textarea.tpl" field=$film}}
{{/if}}
{{if $fields.romance}}
{{if isset($fields.romance)}}
{{include file="field_textarea.tpl" field=$romance}}
{{/if}}
{{if $fields.employment}}
{{if isset($fields.employment)}}
{{include file="field_textarea.tpl" field=$employ}}
{{/if}}
{{if $fields.education}}
{{if isset($fields.education)}}
{{include file="field_textarea.tpl" field=$education}}
{{/if}}