Jump to content

kicken

Gurus
  • Posts

    4,704
  • Joined

  • Last visited

  • Days Won

    179

Community Answers

  1. kicken's post in Get SplObjectStorage by key was marked as the answer   
    You could still make a guid map if you wanted to after you know what the GUID is.

    private function addConnection($client, $guid) { $this->clientList[$client]['guid']=$guid; $this->guidMap[$guid] = $client; } private function findConnectionByGuid($guid) { return isset($this->guidMap[$guid])?$this->guidMap[$guid]:null; } If there are not a lot of clients I'd probably just stick with the loop, but use a foreach to make it simpler.

    private function findConnectionByGuid($guid) { foreach ($this->socketClients as $client){ if ($this->socketClients[$client]['guid'] == $guid){ return $client; } } return null; } That way things are kept simple with only one member variable tracking the list of clients.
  2. kicken's post in Can I use SSL over port 25? was marked as the answer   
    Unless you use port 465 (SMTPS) then you need to determine whether your application supports STARTTLS or not as that's what is needed to enable encryption on the other ports.
     
    In general it's up to your SMTP client to request that encryption be enabled by issuing a STARTTLS command. Only SMTPS provided encryption from the get-go and as mentioned that has been deprecated (though still supported in places).
     
    Regarding your initial concerns for privacy, keep in mind that even if you can get SSL working for delivering email to the GMAIL servers it may be transmitted to it's final destination over a plain-text channel. If the final address is somewhere other than google then the message will need to be forwarded and not all servers support encrypted server-to-server communication so the message would then be sent in plain text. Google tracks some statistics about this if you're interested.
  3. kicken's post in HTTP server with two hosts and same port was marked as the answer   
    Here's that example. To try and simulate your bi-direction traffic plus having a timed job I coded up a little Red-light/Green-light system. The server accepts clients and sends them random red or green light messages. When a client sees a green-light it fakes moving and stops when it gets a red-light. Periodically it also sends the server how far it's moved and it's name. The server periodically lists the players and their distance. There is pretty much no error handling (such as for disconnects) in the code, I'll leave that as an exercise to the reader.
     
    JSONStream.php - Sends and receives json documents via a socket stream.

    <?php namespace Kicken\RLGL; use Evenement\EventEmitterInterface; use Evenement\EventEmitterTrait; use React\Stream\DuplexStreamInterface; class JSONStream implements EventEmitterInterface { use EventEmitterTrait; private $socket; private $buffer; public function __construct(DuplexStreamInterface $socket){ $this->socket = $socket; $this->buffer = ''; $this->socket->on('data', function($data){ $this->buffer .= $data; $this->parseBuffer(); }); } public function send($structure){ $json = json_encode($structure); $this->socket->write($json."\r\n"); } private function parseBuffer(){ $eol = strpos($this->buffer, "\r\n"); while ($eol !== false){ $json = substr($this->buffer, 0, $eol); $this->buffer = substr($this->buffer, $eol + 2); $data = json_decode($json, true); if (json_last_error() == JSON_ERROR_NONE){ $this->emit('data', [$data]); } $eol = strpos($this->buffer, "\r\n"); } } } server.php - Short script to act as the server. Listens on port 1337 for connections and listens for info messages from each client. Sends light messages periodically. 

    <?php require 'vendor/autoload.php'; require 'JSONStream.php'; $port = isset($argv[1])?$argv[1]:1337; $clientList = new SplObjectStorage(); $loop = new \React\EventLoop\StreamSelectLoop(); $socket = new React\Socket\Server($loop); $socket->on('connection', function (\React\Socket\ConnectionInterface $client) use (&$clientList){ $client = new \Kicken\RLGL\JSONStream($client); $clientList->attach($client, []); $client->on('data', function($data) use (&$clientList, $client){ if ($data['message'] == 'info'){ $clientList[$client] = $data['info']; } }); echo "New connection accepted.\r\n"; }); $loop->addPeriodicTimer(5, function () use ($clientList){ $color = mt_rand(1,2) == 1?'red':'green'; echo "Sending {$color} light.\r\n"; /** @var \Kicken\RLGL\JSONStream $client */ foreach ($clientList as $client){ $client->send([ 'message' => 'light' , 'color' => $color ]); } }); $loop->addPeriodicTimer(60, function() use ($clientList){ echo "Current results:\r\n"; foreach ($clientList as $client){ $info = $clientList[$client]; if (!empty($info)){ echo "{$info['name']} has travelled {$info['distance']} feet.\r\n"; } } }); $socket->listen($port, '0.0.0.0'); $loop->run(); client.php - Connects to the server and listens for light messages. Periodically tells the server how far it has travelled. 

    <?php require 'vendor/autoload.php'; require 'JSONStream.php'; $server = isset($argv[1])?$argv[1]:'127.0.0.1'; $port = isset($argv[2])?$argv[2]:1337; /** @var \Kicken\RLGL\JSONStream $client */ $client = null; $clientInfo = [ 'name' => getRandomName() , 'speed' => getRandomSpeed() , 'traveled' => 0 , 'moving' => false , 'movingStartTime' => null ]; $loop = new \React\EventLoop\StreamSelectLoop(); $socket = new \React\SocketClient\TcpConnector($loop); $socket->create($server, $port)->then(function ($stream) use (&$client, &$clientInfo){ $client = new \Kicken\RLGL\JSONStream($stream); sendClientInfo(); $client->on('data', function ($data) use (&$clientInfo){ if ($data['message'] == 'light'){ if ($data['color'] == 'green' && !$clientInfo['moving']){ $clientInfo['moving'] = true; $clientInfo['movingStartTime'] = time(); echo "Received green light!\r\n"; } else if ($data['color'] == 'red' && $clientInfo['moving']){ $movingTime = time() - $clientInfo['movingStartTime']; $distance = $movingTime * $clientInfo['speed']; $clientInfo['traveled'] += $distance; $clientInfo['moving'] = false; $clientInfo['movingStartTime'] = null; echo "Received Red light! Total distance = {$distance} feet.\r\n"; } } }); }); $loop->addPeriodicTimer(15, 'sendClientInfo'); $loop->run(); function sendClientInfo(){ global $client, $clientInfo; $infoToSend = [ 'name' => $clientInfo['name'] , 'distance' => $clientInfo['traveled'] ]; echo "Updating server with data.\r\n"; $client->send(['message' => 'info', 'info' => $infoToSend]); } function getRandomName(){ static $names = ['Edmundo', 'Roxane', 'Evelynn', 'Isaias', 'Buena', 'Evan', 'Katharina', 'Darnell', 'Sharyl', 'Malka', 'Sharla', 'Delena', 'Leah', 'Marnie', 'Tammi', 'Joanna', 'Marva', 'Karyn', 'Kristal', 'Jayson']; shuffle($names); return $names[0]; } function getRandomSpeed(){ return mt_rand(1, 100) / 100; }
  4. kicken's post in Is this SVN set up properly? I don't think I'm in Trunk. was marked as the answer   
    Use svn move to move the files. Eg:

    svn move addFile.php addUser.php alertmanagement.php ... trunk/ After the commit just rename your working copy folder to move it out of the way so you can check out a new copy.
    daniel@daniel:~/NetBeansProjects$ mv development.xxxx.com development.xxxx.com-old daniel@daniel:~/NetBeansProjects$ svn co svn://development.xxxx.com/trunk development.xxxx.com
  5. kicken's post in php form builder class, render in Twig was marked as the answer   
    You need to return your HTML string from your renderForm function, not try to print it. Your use of sprintf does nothing, that line is basically the same as just doing $form = $html which is pointless.
     
    Once you return the HTML from renderForm you also need to return it from your buildForm method. That will then let you assign it to your $newform variable and pass it to twig.
  6. kicken's post in Creating object only once in a function was marked as the answer   
    You can only initialize a static variable to a constant value. Initialize it to null then check in the function if it's null and if so create the object.
     

    function dm(){ static $logger = null; if($logger == null){ $logger = new \Monolog\Logger('my_logger'); $logger->pushHandler(new \Monolog\Handler\StreamHandler(__DIR__."/../logs/client.log")); } $logger->addInfo('Hello'); }
  7. kicken's post in Front End Scripts (dependency) Managers? was marked as the answer   
    The tools work essentially the same way composer does. You use them to install what you need via a few commands in a terminal. Once the libraries are installed you'd link them in your code like normal (script or link tags).
     
    Install NodeJS to get the npm tool. Install Bower using the command npm install -g bower
     
    Create a bower.json file in your project root such as:

    { "name": "example", "private": true, "ignore": [ "**/.*", "node_modules", "bower_components", "test", "tests" ], "dependencies": { "jquery": "^3.1.1" } } Then use bower to install your libraries via bower install. It'll stick all your libraries under bower_components directory which you can then link to, for example:
    <script type="text/javascript" src="/bower_components/jquery/dist/jquery.min.js"></script> Gulp is not necessary, but can be useful to combine/copy/minify the library files. I'll generally use it to combine the libraries into a single vendor.css / vendor.js file and copy them to my web root.
  8. kicken's post in Can't find file? was marked as the answer   
    define creates constants which you reference without quotes elsewhere in the script, such as:

    require(MYSQL); You would have to define your MYSQL constant to include the specific file you need however, or concatenate it to the constant in the require, as you cannot require an entire directory. 

    define('MYSQL', 'd:/wamp\www/includes/Connect_login.php');
  9. kicken's post in Similar queries was marked as the answer   
    If you consider $staff_id = NULL to mean all records and non-null to mean a single record with that ID then you can handle it by simply binding the value twice.
     

    $staff_id = 34; $query = "SELECT fname, lname, city, email, cell FROM staff WHERE ? IS NULL OR staff_id=?"; $stmt = $con->prepare($query); $stmt->bind_param('ii',$staff_id, $staff_id); $stmt->execute(); $stmt->bind_result($fname, $lname, $city, $email, $cell); $stmt->store_result(); $stmt->close();
  10. kicken's post in Shell Zip Complete or Error? was marked as the answer   
    You need to check the return value of the command you executed, which is provided to you through the third parameter to exec ($return_var).
     
    The manual page for zip lists a bunch of possible return codes, but the one you're interested in is:
    So you'd have something like this:

    exec('cd /websites/N2eGK46OjC/; zip -r -o /call/remote_skeleton.zip *', $output, $return); if ($return !== 0){ //Error encountered trigger_error("Error running command", E_USER_ERROR); } else { //Success } Once you know if it failed or was successful you could pass back some JSON to your javascript using json_encode containing whatever data you need.
  11. kicken's post in Microsoft browers and checkbox form elements? was marked as the answer   
    Using for...in with an array (or array-like object) is not preferred. There is no guarantee over the order items will be iterated in and in the case of an array-like object it may include other properties you do not want.
     
    Use a regular for loop with a numeric index.
     

    for(var i=0; i<_form.elements.length; i++){ console.log(_form.elements[i].type + ' : ' + _form.elements[i].name); }
  12. kicken's post in unable to get the correct sub total time was marked as the answer   
    You cannot use the date/strtotime functions to deal with a duration. They are for dealing with an absolute time. What you've done might happen to work for a period less than 24-hours but will fail for more than that. Crossing the 24-hour mark will result in an increase to the date and reset the hours back to 0.
     
    Probably the simplest thing to do would be to have your query just return a total number of seconds rather than a formatted duration. Then you can write a function to take those seconds and format it for display.
     

    function formatDuration($sec){ $h = floor($sec/(60*60)); $sec -= $h*(60*60); $m = floor($sec/60); $sec -= $m*60; return sprintf("%02d:%02d:%02d", $h, $m, $sec); } That would give you a simple HH:mm:ss display for your durations. If you do a little searching you can find all sorts of duration formatting functions. 
    Then in your code you change the query to return seconds and use normal math to sum them and the function to display the result.

    $query = " SELECT hours_id, member_id, member_name, team, time_in, time_out, TIME_TO_SEC(TIMEDIFF(time_out, time_in)) AS totalhours FROM hours where time_in LIKE '%".$chk."%' and member_id = '".$usr."' "; $total_time = 0; while($row = mysql_fetch_assoc($result)){ $total_time += $row['totalhours']; //... echo"<td><font color='white'>" .formatDuration($row['totalhours'])." Hrs</font></td>"; }
  13. kicken's post in best way to store login hours? was marked as the answer   
    I would recommend using one table with two columns. There's no good way to join your two tables in order to get the duration between the time-in and time-out records. A single table means you don't have to duplicate the other fields either.
     

    CREATE TABLE timelog ( id int NOT NULL AUTO_INCREMENT PRIMARY KEY, member_id int NOT NULL, time_in DATETIME NOT NULL, time_out DATETIME NULL ); When someone wants to clock in, you insert a new row with the time_in value set to the current time and time_out NULL.
    INSERT INTO timelog (member_id, time_in) values (1, UTC_TIMESTAMP()) When they clock out, you'd update the row's time_out value with the current timestamp
    UPDATE timelog SET time_out=UTC_TIMESTAMP() WHERE member_id=1 AND time_out IS NULL You'll need to check when doing a clock-in that there is no existing record with a NULL time_out column. In other words, prevent someone from clocking in twice without clocking out first. 
    Then to get your monthly hours tally you'd use a query like I showed above.

    SELECT member_id, SEC_TO_TIME(SUM(TIME_TO_SEC(TIMEDIFF(time_out, time_in)))) duration FROM timelog WHERE time_in >= '2016-06-01 00:00:00' AND time_in < '2016-07-01 00:00:00' GROUP BY member_id Fiddle
  14. kicken's post in UPDATE from SELECT was marked as the answer   
    You can use joins in an update just like you do in a select. If you check the manual page for the UPDATE syntax you can get an idea of how it works.
     
    This should work for your query:

    UPDATE community AS c LEFT JOIN block AS b ON b.community_id = c.community_id LEFT JOIN lot AS l ON l.block_id = b.block_id LEFT JOIN `schedule` AS s ON s.lot_id = l.lot_id LEFT JOIN days_to_order AS d ON c.days_to_order_id = d.days_to_order_id SET l.order_by_date = DATE_SUB(s.schedule_date, INTERVAL d.days_to_order DAY) WHERE s.reschedule_date IS NULL AND l.order_by_date IS NOT NULL AND l.lot_type_id > 2 AND s.schedule_date IS NOT NULL AND c.community_type < 3 AND l.active = 1 AND l.order_by_date > s.schedule_date
  15. kicken's post in SQL max size was marked as the answer   
    If you want to store a large amount of text in a column, then you'd do as the error suggests and use the TEXT data type. This type stores the text in a separate location from the row and then just stores a pointer to it within the row itself.
     
    That said, you could also re-evaluate how big you need the columns to be. For example if your 500 word block of text had an average word length of 6 characters, you'd be using only about 3,500 characters total meaning you could make your columns 4,000 characters long rather than 8,000.
     
    You could also re-design your DB so you have more rows but less columns. For example:

    create table result ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY , userhash VARCHAR(50) NOT NULL , resultNumber INT , ready VARCHAR(3) NOT NULL , result VARCHAR(8000) NOT NULL ) Instead of 3 ready/result columns, you have 3 rows, each with a single ready/result column plus a column indicating the result number (1, 2, 3...). This is known as normalization and is generally a good idea. If you find yourself having a bunch of numbered columns in a table, that is a good sign you should re-think that design. 
    Think about your design now. What happens if next month you need to add a 4th result? You'd have to add more columns, which could cause all kinds of problems. All the existing rows would have to be expanded to include the new columns. Your queries may break if you are doing something like SELECT * due to the new columns. You might fail to add the columns do to the row size limit you already discovered.
     
    With the alternate row based design you just add another row with resultNumber=4, no problems at all. There's no limit to the number of results you could potentially have with the alternate design. If you want to have a limit, you enforce it in your code. If you need to raise the limit later, it's a simple code change, not a whole database refactor.
  16. kicken's post in Jquery Clone was marked as the answer   
    A better way to approach this problem is to avoid the use of the ID's and onchange attribute entirely. You can do this by listening to the change event on the parent rows container, and when it occurs finding the elements you need in the dom of the appropriate row.
     
    This is assuming the fields used in the change event are also duplicated in each row. I'm assuming that due to their incrementing IDs also. Take this fiddle as an example:
     

    /** * Create a clone of the row template and add it to the #rows container. */ function cloneRow(){ //Clone the entire row var $clone = $('#rowsec').clone(); //Clear the input values. Customize this if needed $clone.find('input').val(0); //Remove the ID so there's only one in the dom. $clone.removeAttr('id'); //Add it to the rows container $('#rows').append($clone); } /** * Handle a change event. Within the function `this` refers to the input that changed * We can use jQuery to find the other inputs based on the changed input * then run the calculations. */ function compute(){ var $row = $(this).closest('.row'); var $floor = $row.find('[name=floor]'); var $length = $row.find('[name=length]'); var $width = $row.find('[name=width]'); var $sqft = $row.find('[name=sqft]'); //Do your calculations $sqft.val($length.val() * $width.val()); } //Clone row when button is clicked $('#clone').click(cloneRow); //Handle change events in each row $('#rows').on('change', 'input', compute); <button id="clone"> Clone Row </button> <div id="rows"> <div class="row" id="rowsec"> <div class="col-md-2 col-sm-3 col-lg-1 nopadding"> <input class="form-control input-sm nopadding" type="text" placeholder="Floor" maxlength="4" name="floor"> </div> <div class="col-md-2 col-sm-3 col-lg-1 nopadding"> <input class="form-control input-sm nopadding" type="text" placeholder="Length" maxlength="4" name="length"> </div> <div class="col-md-2 col-sm-3 col-lg-1 nopadding"> <input class="form-control input-sm nopadding" type="text" placeholder="Width" maxlength="4" name="width"> </div> <div class="col-md-2 col-sm-3 col-lg-1 nopadding"> <input class="form-control input-sm nopadding" type="text" placeholder="Sqft" maxlength="4" name="sqft"> </div> </div> </div>
  17. kicken's post in Jquery - orientationchange event issue was marked as the answer   
    Usually if adding an alert fixes a problem it is due to a race condition.
     
    Most likely in this case, the browser is firing the event and your code is running before it updated it's state with the new width and height information. You can work around it by wrapping the function in a timeout to delay it while the browser updates it's state.
     
    Alternatively, have you tried using the resize event rather than the orientation event? I think that would be more appropriate as it would also handle cases on a desktop of the user just resizing their browser window.
     

    //cache $(window) to save some function calls. var $window = $(window); $window.on("resize",function(){ $('div.myDia1').dialog( "option", "width", $window.width()-25); $('div.myDia1').dialog( "option", "height", $window.height()-25 ); });
  18. kicken's post in Javascript: How to retrieve the computed value of an input was marked as the answer   
    The .val() method will give you the value of the input, regardless of whether it was set by code or typed in by the user.
     
    If you're adding any number formatting to the cost such as commas or dollar signs then you'll need to remove that formatting before reading the value out and trying to use it to calculate the total.
     
    You'll also need to reset your runningTotal to zero each time before trying to calculate the total. Other than missing this, your code looks fine as is.
     
    Your code works fine with the runningTotal reset and fixing the syntax problems (assuming copy/paste error). See the fiddle
     
    When you post code try and make sure it's syntatically correct/complete. Also it helps if you describe why you think something isn't working rather than just saying what you think the problem is. What did you think that .val() was not working to get the computed values? What kind of problem were you seeing?
  19. kicken's post in mysqld.exe unable to be deleted was marked as the answer   
    You could also just boot into windows safe mode and delete the file. Mysql shouldn't be started up when you boot into safe mode.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.