I've successfully used APNS-PHP to send PNs - it's great!
However, I'm a little stuck on how to add it to a Code Igniter project
(inside a controller that will be called from command-line).
Calling:
require_once APPPATH.'/third_party/ApnsPHP/Autoload.php';
Results in errors:
Fatal error: Uncaught exception 'Exception' with message 'Class file
'XXXXXXX/application/third_party/CI/DB/mysql/result.php' does not
exists' in XXXXXXX/application/third_party/ApnsPHP/Autoload.php:49
I'm assuming it's some kind of autoloading conflict? But I'm not
really sure!
Any help would be brilliant - I've trawled Google without much luck!
Here's the line I've being trying to use inside the function:
require_once APPPATH.'/third_party/ApnsPHP/Autoload.php';
Here's the __autoload function I've added for loading Ion Auth's libs:
function __autoload($class)
{
if (strpos($class, 'CI_') !== 0)
{
if (file_exists($file = APPPATH.'core/'.$class.EXT))
{
include $file;
}
else if (file_exists($file = APPPATH.'libraries/'.$class.EXT))
{
include $file;
}
else if (file_exists($file = APPPATH.'core/base_controllers/'.$class.EXT))
{
include $file;
}
}
}
With no other changes to the library, this works for me. It sidesteps CI a bit, but still allows you to load in APNS-PHP as a model:
<?php
if(!defined('BASEPATH')) exit('No direct script access allowed');
class Notification_model extends CI_Model {
protected $apnsDir = '';
// -----------------------------------------------
/**
* Setup some basic stuffs
* #param void
* #return void
* #access public
*/
public function __construct() {
parent::__construct();
/* get all the APNS files */
$this->apnsDir = $_SERVER['DOCUMENT_ROOT'].'/application/third_party/ApnsPHP/';
$this->_apns_req();
return;
} /* /__construct() */
// -----------------------------------------------
/**
* Will send the actual iOS notification to the user
* #param $token string iOS device token
* #param $msg string
* #param $attrs array Key/value pairs to be sent as meta with APN
* #return void
* #access public
*/
private function send_ios($token=null, $msg=null, $attrs=array()) {
if(!$token || !$msg) return;
// Instantiate a new ApnsPHP_Push object
$push = new ApnsPHP_Push(
ApnsPHP_Abstract::ENVIRONMENT_SANDBOX,
$this->apnsDir.'SSL/server_certificates_bundle_sandbox.pem'
);
// Set the Provider Certificate passphrase
// $push->setProviderCertificatePassphrase('tablecan29');
// Set the Root Certificate Autority to verify the Apple remote peer
$push->setRootCertificationAuthority($this->apnsDir.'SSL/entrust_root_certification_authority.pem');
// Connect to the Apple Push Notification Service
$push->connect();
// Instantiate a new Message with a single recipient
$message = new ApnsPHP_Message($token);
// Set a custom identifier. To get back this identifier use the getCustomIdentifier() method
// over a ApnsPHP_Message object retrieved with the getErrors() message.
$message->setCustomIdentifier("Message-Badge-3");
// Set badge icon to "3"
// $message->setBadge(0);
// Set a simple welcome text
$message->setText($msg);
// Play the default sound
$message->setSound();
// Set custom properties
if( is_array($attrs) && count($attrs) )
{
foreach( $attrs as $attr_key => $attr_val )
{
$message->setCustomProperty($attr_key, $attr_val);
}
}
// Set the expiry value - in seconds
$message->setExpiry(120);
// Add the message to the message queue
$push->add($message);
// Send all messages in the message queue
$push->send();
// Disconnect from the Apple Push Notification Service
$push->disconnect();
// Examine the error message container
// $aErrorQueue = $push->getErrors();
// if (!empty($aErrorQueue)) {
// var_dump($aErrorQueue);
// }
return TRUE;
} /* /send_ios() */
// -----------------------------------------------
private function _apns_req() {
require_once $this->apnsDir.'Abstract.php';
require_once $this->apnsDir.'Exception.php';
require_once $this->apnsDir.'Feedback.php';
require_once $this->apnsDir.'Message.php';
require_once $this->apnsDir.'Log/Interface.php';
require_once $this->apnsDir.'Log/Embedded.php';
require_once $this->apnsDir.'Message/Custom.php';
require_once $this->apnsDir.'Message/Exception.php';
require_once $this->apnsDir.'Push.php';
require_once $this->apnsDir.'Push/Exception.php';
require_once $this->apnsDir.'Push/Server.php';
require_once $this->apnsDir.'Push/Server/Exception.php';
return;
} /* /_apns_req() */
} /* /Notification_model{} */
/* End of file notification_model.php */
/* Location: ./application/models/notification_model.php */
Example usage:
$this->load->model('notification_model');
$this->notification_model->send_ios($token, 'Test Message', array('custom_var' => 'val'));
Related
I'm desperately trying to check whether an "unknown" protobuf payload wrapped within an Any is some specific type (Heartbeat) and unpack it to a Heartbeat object using the code below. Both Heartbeat and StatusChanged are valid generated Protobuf classes.
/* <external service> */
$event = (new StatusChanged)->setId("testId");
$any = new Any;
$any->pack($event);
$protobufBinaryAny = $any->serializeToString();
/* </external service> */
/* $protobufBinaryAny is the incoming binary data */
$anyEvent = new Any();
$anyEvent->mergeFromString($protobufBinaryAny);
if ($anyEvent->is(Heartbeat::class)) {
$this->processHeartbeat($anyEvent->unpack());
} else {
throw new UnknownMessageTypeException($anyEvent->getTypeUrl());
}
When running the following code, I'd expect it to throw a UnknownMessageTypeException, however, I get this:
Call to a member function getFullName() on null.
This error happens at $data->is(Heartbeat::class), since the Heartbeat class obviously couldn't be found in the DescriptorPool.
/**
* Google\Protobuf\Any
* https://github.com/protocolbuffers/protobuf/blob/440a156e1cd5c783d8d64eef81a93b1df3d78b60/php/src/Google/Protobuf/Any.php#L315-L323
*/
class Any {
public function is($klass)
{
$pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
$desc = $pool->getDescriptorByClassName($klass);
$fully_qualifed_name = $desc->getFullName();
$type_url = GPBUtil::TYPE_URL_PREFIX.substr(
$fully_qualifed_name, 1, strlen($fully_qualifed_name));
return $this->type_url === $type_url;
}
}
However, when explicitly initializing the Heartbeat before, it's working, since Heartbeat is now in the DescriptorPool.
foreach ([
\GPBMetadata\Heartbeat::class,
\GPBMetadata\StatusChanged::class,
] as $klass) {
$klass::initOnce();
}
But this manual initialization thing just feels wrong. Am I supposed to do it like that, or did I just miss a fancy autoloading-feature in the non-existing PHP docs?
For the time being, I wrote an autoloader for this case, but it still just feels not right:
trait HandlesProtobufMessages
{
function initializeProtobufMessages()
{
/** #var \Composer\Autoload\ClassLoader */
$loader = require(__DIR__.'/../../vendor/autoload.php');
$classes = array_filter(array_keys($loader->getClassMap()), function ($className) {
$namespace = "GPBMetadata\\";
return substr($className, 0, strlen($namespace)) === $namespace;
});
foreach ($classes as $class) {
$class::initOnce();
}
}
}
Maybe you have more insights into this protobuf jungle and can help me out here, would be glad!
Thank you in advance
How to add eventListener to swiftmailer send event?
Every time i send email i create a file and attach it to email, and after sending i want to unlink that file. How to do that?
Thanks.
file_put_contents($path, implode(";\r\n", $result));
$message = (new \Swift_Message('VAT checking result !'))
->setFrom('vah#gmail.com')
->setTo($vat->getEmail())
->setBody(
'Hello, ...' ,'text/')
->attach(\Swift_Attachment::fromPath($path));
// START send result email
$mailer = $this->container->get('mailer');
$listener = $this->container->get('app.service.send_email_listener');
$listener->setPathToFile($path);
$mailer->registerPlugin($listener);
$mailer->send( $message );
// END send email to admin
//unlink($path); email will not be sent
I tried to register listener like that
app.service.send_email_listener:
class: AppBundle\Listener\SendEmailListener
public: true
tags:
- { name: swiftmailer.plugin }
this is listener class :
namespace AppBundle\Listener;
use \Swift_Events_SendListener as base;
class SendEmailListener implements base
{
private $pathToFile;
public function setPathToFile($path)
{
$this->pathToFile = $path;
}
public function getPathToFile($path)
{
return $this->pathToFile;
}
/**
* Invoked immediately before the Message is sent.
*
* #param \Swift_Events_SendEvent $evt
*/
public function beforeSendPerformed(\Swift_Events_SendEvent $evt)
{
}
/**
* Invoked immediately after the Message is sent.
*
* #param \Swift_Events_SendEvent $evt
*/
public function sendPerformed(\Swift_Events_SendEvent $evt)
{
if($this->pathToFile){
unlink($this->pathToFile);
}
}
}
EDIT
It executes the method, but swift is not able to stream the file , beacuse the the file is unlinked before the sending is end...
This is from dev_logs:
[2018-05-24 20:40:18] php.CRITICAL: Uncaught Exception: Unable to open file for reading [C:\Users\\projects\vat\web\vatfiles\122.txt] {"exception":"[object] (Swift_IoException(code: 0): Unable to open file for reading [C:\\Users\\\projects\\vat\\web\\vatfiles\\122.txt] at C:\\Users\\projects\\vat\\vendor\\swiftmailer\\swiftmailer\\lib\\classes\\Swift\\ByteStream\\FileByteStream.php:144)"} []
As an alternative to using a Swiftmailer Plugin, I recommend using the __destruct magic method in your service/controller that utilizes the file(s). __destruct will be called when the object is released and will unlink any of the declared paths.
namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class YourController extends Controller
{
private $paths = [];
public function someAction()
{
$this->paths[] = $path;
file_put_contents($path, implode(";\r\n", $result));
$message = (new \Swift_Message('VAT checking result !'))
->setFrom('vah#gmail.com')
->setTo($vat->getEmail())
->setBody('Hello, ...' ,'text/')
->attach(\Swift_Attachment::fromPath($path));
$mailer = $this->container->get('mailer');
$mailer->send( $message );
return $this->redirectToRoute('some_route');
}
public function __destruct()
{
if ($this->paths) {
array_map('unlink', $this->paths);
}
}
}
NOTE: This approach may not work if you use a spool to send
emails, as the
email will not be sent until the thresholds have been met for the
spool.
Symfony 2.3+ will automatically register the Swiftmailer plugin when you tag a service with swiftmailer.plugin. So there is no need to call $mailer->registerPlugin($listener);, where swiftmailer will simply ignore duplicate plugin registrations.
Trying to understand how to share my session data between my App and my chat server (Ratchet). I thought using Symfony & Memcache would be easy enough but I just can't seem to get it working.
I am trying to get the user_id out of the session for when somebody sends a message to the chat it will insert the user_id into the database (Chat->onMessage).
Can somebody point me in the right direction?
Flow:
config.php is included on every page
When user logs into the website it executes the $login->processLogin() method
I start my chat server via command line (php server.php)
config.php
<?php
use MyApp\Login;
use MyApp\Session as MySession;
# Define backslash or forward slash for *NIX and IIS systems.
define('DS', DIRECTORY_SEPARATOR);
# Attempt to determine the full-server path to the 'root' folder in order to reduce the possibility of path problems.
define('BASE_PATH', realpath(dirname(__FILE__)).DS);
# Define the complete path to the root of the domain we are at (ie. /home/user/domain.com) (does't end in a slash)
define('ROOT_PATH', $_SERVER['DOCUMENT_ROOT']);
# Define where cookies may be active. ('/' means the entire domain)
define('COOKIE_PATH', '/');
# Name sessions. (needs to be alphanumeric with no periods[.]- can't be solely digits; must contain at least one letter)
define('SESSIONS_NAME', 'SiteUser');
# Get the Session Class.
require_once BASE_PATH.'modules'.DS.'Session'.DS.'Session.php';
# Check if there is a session id set the the $sesh_id variable.
$sesh_id=((isset($sesh_id)) ? $sesh_id : NULL);
# Create a new session object, thus starting a new session.
$mysession=MySession::getInstance(NULL, NULL, NULL, $sesh_id);
Login
<?php
namespace MyApp;
use Exception;
# Make sure the script is not accessed directly.
if(!defined('BASE_PATH'))
{
exit('No direct script access allowed');
}
# Get the User Class
require_once BASE_PATH.'modules'.DS.'Login'.DS.'User.php';
/**
* Class Login
*
* The Login Class is used to login in and out users as well as checking various login privileges.
*/
class Login extends User
{
/**
* processLogin
*
* Checks if the Login has been submitted and processes it.
*
* #access public
*/
public function processLogin()
{
if($this->isLoggedIn()===TRUE)
{
header("location: main.php");
die;
}
# Check if the form has been submitted.
if($_SERVER['REQUEST_METHOD']=='POST')
{
try
{
try
{
$this->setLoginSessions($this->getID(), TRUE);
header("location: main.php");
}
catch(Exception $e)
{
throw $e;
}
}
catch(Exception $e)
{
throw $e;
}
}
}
/**
* Checks if user is logged in or not. Returns TRUE if logged in, FALSE if not.
*
* #return bool
*/
public function isLoggedIn()
{
global $mysession;
$symfony_session=$mysession->symfony_session;
//if(!isset($_SESSION['user_logged_in']))
if(!$symfony_session->has('user_id'))
{
# Check if we have a cookie
if(isset($_COOKIE['cookie_id']))
{
try
{
$this->setID($_COOKIE['cookie_id']);
}
catch(Exception $e)
{
unset($_COOKIE['user_ip']);
unset($_COOKIE['athenticate']);
unset($_COOKIE['cookie_id']);
return FALSE;
}
}
else
{
return FALSE;
}
}
//elseif($_SESSION['user_logged_in']===TRUE)
if($symfony_session->get('user_logged_in')===TRUE)
{
return TRUE;
}
return FALSE;
}
/**
* Sets the login sessions.
*
* #param null $user_id
* #param null $logged_in
* #param bool $secure
* #throws Exception
*/
public function setLoginSessions($user_id=NULL, $logged_in=NULL, $secure=FALSE)
{
global $mysession;
$symfony_session=$mysession->symfony_session;
# Check if the user is logged in.
if($this->isLoggedIn()===TRUE)
{
if($user_id===NULL)
{
try
{
# Get the User's data.
$this->findUserData();
$user_id=$this->getID();
$logged_in=TRUE;
}
catch(Exception $e)
{
throw $e;
}
}
}
$symfony_session->set('user_id', $user_id);
$symfony_session->set('user_logged_in', $logged_in);
/*
# Set the User's login sessions.
$_SESSION['user_id']=$user_id;
$_SESSION['user_logged_in']=$logged_in;
*/
}
}
Session
<?php
namespace MyApp;
use Memcache;
use Symfony\Component\HttpFoundation\Session\Session as SymfonySession;
use Symfony\Component\HttpFoundation\Session\Storage\Handler;
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
use Symfony\Component\HttpFoundation\Session\Storage\Handler\MemcacheSessionHandler;
/**
* Class Session
*
* The Session class is used to access and manipulate Sessions and data stored in them.
*/
class Session
{
private static $session;
private $message=FALSE;
private $sessname=FALSE;
public $symfony_session;
/**
* Session constructor.
*
* Safely calls session_start().
* Also enables sessions to span sub domains. It names the session (which is necessary for
* session_set_cookie_params() to work). If calling this class before setting.php, $sessname (the session name) AND
* $cookiepath (the path for cookies) MUST be defined.
*
* #param null $sessname
* #param null $cookiepath
* #param bool $secure
* #param null $sesh_id
*/
public function __construct($sessname=NULL, $cookiepath=NULL, $secure=FALSE, $sesh_id=NULL)
{
require_once BASE_PATH.'vendor'.DS.'autoload.php';
$memcache=new Memcache;
$memcache->connect(DOMAIN_NAME, 11211);
$storage=new NativeSessionStorage(array(), new Handler\MemcacheSessionHandler($memcache));
$symfony_session=new SymfonySession($storage);
# Check if a session ID was passed.
if($sesh_id!==NULL)
{
//session_id($sesh_id);
$symfony_session->setId($sesh_id);
}
# Is a session already started?
//if(!isset($_SESSION['s_set']))
if(!$symfony_session->has('s_set'))
{
# If we haven't been given a session name, we will give it one.
if(empty($cookiepath))
{
# Set the default cookie path be the root of the site.
$cookiepath=DS;
# Check if the cookie path was defined in settings.php.
if(defined('COOKIE_PATH'))
{
# Check if the defined path is blank.
if(COOKIE_PATH!='')
{
# If the cookie path has been defined in settings.php, we'll use that path.
$cookiepath=COOKIE_PATH;
}
}
}
//session_set_cookie_params($life, $cookiepath, '.'.DOMAIN_NAME, $secure);
/*
* Read the current save path for the session files and append our own directory to this path.
* Note: In order to make that platform independent, we need to check for the file-seperator first.
* Now we check if the directory already has been created, if not, create one.
* Then we set the new path for the session files.
*/
# Get the session save path.
$save_path=session_save_path();
# Find out if our custom_session folder exists. If not, let's make it.
if(!is_dir(BASE_PATH.'../custom_sessions'.DS.'.'))
{
mkdir(BASE_PATH.'../custom_sessions', 0755);
}
# Is our custom_sessions folder the session save path? If not, let's make it so.
if($save_path!==BASE_PATH.'../custom_sessions')
{
//session_save_path(BASE_PATH.'../custom_sessions');
# How do I set the save path in Symfony?
}
# If we haven't been given a session name, we will give it one.
if(empty($sessname))
{
# Set the default session name.
$sessname='PHPSESSID';
# Check if the session name was defined in settings.php.
if(defined('SESSIONS_NAME'))
{
# Check if the defined name is blank.
if(SESSIONS_NAME!='')
{
# If the session name has been defined in settings.php, we'll give the session that name.
$sessname=SESSIONS_NAME;
}
}
}
$storage->setOptions(array(
'cookie_domain'=>'.'.DOMAIN_NAME,
'cookie_lifetime'=>0,
'cookie_path'=>$cookiepath,
'cookie_secure'=>$secure,
'name'=>$sessname
));
//$this->setSessname($sessname);
# Name the session.
//session_name($this->getSessname());
# Session must be started before anything.
//session_start();
//$session->setName($this->getSessname());
$symfony_session->start();
# Set the s_set session so we can tell if session_start has been called already.
//$_SESSION['s_set']=1;
$symfony_session->set('s_set', 1);
}
$this->symfony_session=$symfony_session;
print_r($symfony_session);exit;
}
/**
* getSessname
*
* Returns the data member $sessname.
*
* #access public
*/
public function getSessname()
{
return $this->sessname;
}
/**
* Sets the data member $sessname. If an empty value is passed, the data member will
* be set with FALSE. Returns the set data member value.
*
* #param $sessname
* #return bool
*/
public function setSessname($sessname)
{
# Clean it up...
$sessname=trim($sessname);
# Check if the passed value is now empty.
if(empty($sessname))
{
# Explicitly set the data member to false.
$sessname=FALSE;
}
# Set the data member.
$this->sessname=$sessname;
# Return the data member after it has gone through the get method.
return $this->getSessname();
}
/**
* Gets the singleton instance of this class.
*
* #param null $sessname
* #param null $cookiepath
* #param bool $secure
* #param null $sesh_id
* #return Session
*/
public static function getInstance($sessname=NULL, $cookiepath=NULL, $secure=FALSE, $sesh_id=NULL)
{
if(!self::$session)
{
self::$session=new Session($sessname, $cookiepath, $secure, $sesh_id);
}
return self::$session;
}
}
server.php
<?php
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use Ratchet\Session\SessionProvider;
use Symfony\Component\HttpFoundation\Session\Storage\Handler;
use MyApp\Chat;
$port="8080";
# Change to this directory.
chdir(dirname(__FILE__));
# Need this for the database insert.
if(!defined('DOMAIN_NAME'))
{
define('DOMAIN_NAME', 'example.dev');
}
require_once '../../includes/lonconfig.php';
require_once '../../vendor/autoload.php';
$memcache=new Memcache;
$memcache->connect(DOMAIN_NAME, 11211);
$session=new SessionProvider(
new Chat,
new Handler\MemcacheSessionHandler($memcache)
);
$server=IoServer::factory(
new HttpServer(
new WsServer($session)
),
$port,
DOMAIN_NAME
);
$server->run();
Chat
<?php
namespace MyApp;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
class Chat implements MessageComponentInterface
{
protected $clients=array();
public function onOpen(ConnectionInterface $conn)
{
# get the cookies
$cookies=(string)$conn->WebSocket->request->getHeader('Cookie');
# Returns only PHPSESSID (not SiteUser).
//var_dump($cookies);exit;
$this->clients[$conn->resourceId]=$conn;
echo "New connection! ({$conn->resourceId})\n";
}
/**
* #param ConnectionInterface $conn
* #param string $data
*/
public function onMessage(ConnectionInterface $conn, $data)
{
$database=$this->dbh;
$data=json_decode($data, TRUE);
if(isset($data['data']) && count($data['data'])!=0)
{
require_once BASE_PATH.'vendor'.DS.'autoload.php';
$memcache=new Memcache;
$memcache->connect(DOMAIN_NAME, 11211);
$storage=new NativeSessionStorage(array(), new Handler\MemcacheSessionHandler($memcache));
$session=new SymfonySession($storage);
$type=$data['type'];
$user_id=$conn->Session->get('user_id');
$return=NULL;
if($type=="send" && isset($data['data']['type']) && $user_name!=-1)
{
$msg=htmlspecialchars($data['data']['msg']);
$date=new DateTime;
$date->setTimezone(new DateTimeZone(TIMEZONE));
if($data['data']['type']=='text')
{
echo 'test 4';exit;
$database->query('SELECT `id`, `user_id`, `msg`, `type` FROM `chat` ORDER BY `id` DESC LIMIT 1', array());
$lastMsg=$database->statement->fetch(PDO::FETCH_OBJ);
if($lastMsg->user_id==$user_id && (strlen($lastMsg->msg)<=100 || strlen($lastMsg->msg)+strlen($msg)<=100))
{
# Append message.
$msg=$lastMsg->msg."<br/>".$msg;
$database->query('UPDATE `chat` SET `msg`=:msg, `posted`=NOW() WHERE `id`=:lastmsg', array(
':msg'=>$msg,
':lastmsg'=>$lastMsg->id
));
$return=array(
"id"=>$lastMsg->id,
"name"=>$user_name['staffname'],
"type"=>"text",
"msg"=>$msg,
"posted"=>$date->format("Y-m-d H:i:sP"),
"append"=>TRUE
);
}
else
{
$database->query('INSERT INTO `chat` (`user_id`, `msg`, `type`, `posted`) VALUES (?, ?, "text", NOW())', array(
$user_id,
$msg
));
# Get last insert ID.
$get_chat_id=$database->lastInsertId();
$return=array(
"id"=>$get_chat_id,
"name"=>$user_name['staffname'],
"type"=>"text",
"msg"=>$msg,
"posted"=>$date->format("Y-m-d H:i:sP")
);
}
}
foreach($this->clients as $client)
{
$this->send($client, "single", $return);
}
}
elseif($type=="fetch")
{
# Fetch previous messages.
$this->fetchMessages($conn, $data['data']['id']);
}
}
}
}
You shouldn't actually share that data over all parts of your application.
If you open the tutorial of Ratchet, you will find a part about pushServers.
This allows you to push to a certain channel or $user_id(in your case)
This makes you able to not save or transfer the data in the two parts and will facilitate you to have a streamlined workflow.
I personally use the pushServer in multiple channels, they are split up into:
All users online (sendBroadcast)
All users in a group (sendGroup)
All users following a tag (sendTag)
To other users(sendToUser)
I hope this already gives you an idea on how to solve your problem, otherwise feel free to ask.
On Owncloud 8.1 using the owncloud command line, I create a new test app:
ocdev startapp MyApp --email mail#example.com --author "Your Name" --description "My first app" --owncloud 8
The app is working, I can add it in the owncloud control panel.
Now I'd like to write to a file, so I use one example from the owncloud documentation:
https://doc.owncloud.org/server/8.1/developer_manual/app/filesystem.html
[Edit] I started over and now, I don't know if I omitted something, but "myapp" comes with no "application.php" file.
So I create it at /var/www/core/apps/myapp/appinfo/application.php :
<?php
namespace OCA\MyApp\AppInfo;
use \OCP\AppFramework\App;
use \OCA\MyApp\Storage\AuthorStorage;
class Application extends App {
public function __construct(array $urlParams=array()){
parent::__construct('myapp', $urlParams);
$container = $this->getContainer();
/**
* Storage Layer
*/
$container->registerService('AuthorStorage', function($c) {
return new AuthorStorage($c->query('RootStorage'));
});
$container->registerService('RootStorage', function($c) {
return $c->query('ServerContainer')->getRootFolder();
});
}
}
Then I create a file called /var/www/core/apps/myapp/storage/AuthorStorage.php with:
<?php
namespace OCA\MyApp\Storage;
class AuthorStorage {
private $storage;
public function __construct($storage){
$this->storage = $storage;
}
public function writeTxt($content) {
// check if file exists and write to it if possible
try {
try {
$file = $this->storage->get('/myfile.txt');
} catch(\OCP\Files\NotFoundException $e) {
$this->storage->touch('/myfile.txt');
$file = $this->storage->get('/myfile.txt');
}
// the id can be accessed by $file->getId();
$file->putContent($content);
} catch(\OCP\Files\NotPermittedException $e) {
// you have to create this exception by yourself ;)
throw new StorageException('Cant write to file');
}
}
}
The sample app already gives me a route to the index function in the pagecontroller.php
['name' => 'page#index', 'url' => '/', 'verb' => 'GET']
How do I call the function "writeTxt" from there?
Based on http://php.net/manual/en/language.oop5.basic.php
I tried:
use \OCA\MyApp\Storage\AuthorStorage;
and
public function index() {
//added part
$a = new AuthorStorage();
$a->writeTxt('test');
//original part
$params = ['user' => $this->userId];
return new TemplateResponse('myapp', 'main', $params); //templates/main.php
}
After running I get a "Class 'OCA\MyApp\Storage\AuthorStorage' not found at /var/www/core/apps/myapp/controller/pagecontroller.php#44"
Even with the help of use \OCA\MyApp\Storage\AuthorStorage; ( ClassNotFoundException: Attempted to load class... Symfony ) it doesn't seem to help.
Thanks
Time has gone by, so I'm posting an answer to my question for owncloud 9.
Here are the steps to a basic script with read, write, copy file ability.
"application.php" has definitively been removed from the example. It was not a bug.
Following:
https://doc.owncloud.org/server/9.0/developer_manual/app/startapp.html
Generate the demo "MyApp" app:
ocdev startapp MyApp --email mail#example.com --author "Your Name" --description "My first app" --owncloud 9
Edit the file myapp/controller/pagecontroller.php
<?php
/**
* ownCloud - myapp
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* #author Your Name <mail#example.com>
* #copyright Your Name 2016
*/
namespace OCA\MyApp\Controller;
use OCP\IRequest;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Controller;
use OCP\Files\IRootFolder;
use OC\Files\Storage\Temporary;
class PageController extends Controller {
private $userId;
private $storage;
private $userstorage;
public function __construct($AppName, IRequest $request, IRootFolder $storage, $UserId){
parent::__construct($AppName, $request);
$this->storage = $storage;
$this->userId = $UserId;
$this->userstorage = $this->storage->get($this->userId.'/files/');
}
/**
* CAUTION: the #Stuff turns off security checks; for this page no admin is
* required and no CSRF check. If you don't know what CSRF is, read
* it up in the docs or you might create a security hole. This is
* basically the only required method to add this exemption, don't
* add it to any other method if you don't exactly know what it does
*
* #NoAdminRequired
* #NoCSRFRequired
*/
public function index() {
$listedudossier = $this->userstorage->getDirectoryListing();
//list all items in the root directory
//and copies the files in an directory called old
//the directory "old" is not script created
foreach ($listedudossier as $value) {
if ( $value->getType() == 'file' ){
$value->copy($this->userId.'/files/old/'.$value->getName());
//also works
//$value->copy($this->userstorage->getPath().'/old/'.$value->getName());
}
}
$params = ['listedudossier' => $listedudossier ];
return new TemplateResponse('myapp', 'main', $params); // templates/main.php
}
/**
* Simply method that posts back the payload of the request
* #NoAdminRequired
*/
public function doEcho($echo) {
//creates a file
$this->userstorage->newFile('myfile2.txt');
//opens a file, adds inputbox content and saves the file
$file = $this->userstorage->get('myfile.txt');
$contenu = $file->getContent();
$file->putContent($contenu.$echo);
return new DataResponse(['echo' => $echo]);
}
}
You also need to edit the myapp/templates/part.content.php
<p>Hello World <?php p($_['user']) ?></p>
<p><button id="hello">click me</button></p>
<p><textarea id="echo-content">
Send this as ajax
</textarea></p>
<p><button id="echo">Send ajax request</button></p>
Ajax response: <div id="echo-result"></div>
<p>listedudossier:<p> <?php
foreach ($_['listedudossier'] as $file) {
echo "type:".$file->getType();
echo "<p>";
echo "nom:".$file->getName();
echo "<p>";
echo "modif:".$file->getMTime();
echo "<p>";
}
From here you can test the code in a development environment:
https://github.com/owncloud/ocdev/blob/master/README.rst#installation
I would like to use YUI compressor with minify PHP rather than the default JSmin. Does anyone have experience setting this up?
Right now I am using the groupsConfig.php to combine the JS.
return array(
'jsAll' => array('//contenido/themes/bam/assets/js/jquery.js', '//contenido/themes/bam/assets/js/modernizr.js','//contenido/themes/bam/assets/js/imgpreload.js', '//contenido/themes/bam/assets/js/imgpreload.js', '//contenido/themes/bam/assets/js/history.js','//contenido/themes/bam/assets/js/ajaxify.js', '//contenido/themes/bam/assets/js/isotope.js'),
'jsHome' => array('//contenido/themes/bam/assets/js/easing.js','//contenido/themes/bam/assets/js/scrollable.js', '//contenido/themes/bam/assets/js/home.js'),
'cssAll' => array('//contenido/themes/bam/bam.css'),
);
As it says on the homepage:
Uses an enhanced port of Douglas Crockford's JSMin library and custom classes to minify CSS and HTML
I have the following code in config.php, but I get a 500 error when trying to view the combined js file:
function yuiJs($js) {
require_once '/lib/Minify/YUICompressor.php';
Minify_YUICompressor::$jarFile = '/lib/yuicompressor-2.4.2.jar';
Minify_YUICompressor::$tempDir = '/temp';
return Minify_YUICompressor::minifyJs($js);
}
$min_serveOptions['minifiers']['application/x-javascript'] = 'yuiJs';
It also appears that there are several lines in lib/Minify/YUICompressor.php that need to be configured, and I'm not sure if I'm doing it right:
class Minify_YUICompressor {
/**
* Filepath of the YUI Compressor jar file. This must be set before
* calling minifyJs() or minifyCss().
*
* #var string
*/
public static $jarFile = '../yuicompressor-2.4.2.jar';
/**
* Writable temp directory. This must be set before calling minifyJs()
* or minifyCss().
*
* #var string
*/
public static $tempDir = '../../temp/';
/**
* Filepath of "java" executable (may be needed if not in shell's PATH)
*
* #var string
*/
public static $javaExecutable = 'java';
I had the same problem on windows. It seems jar file needs to be executable in order to run yui compressor. So, i have to remove excutable check from YUICompressor.php
#132
private static function _prepare()
{
if (! is_file(self::$jarFile)) {
throw new Exception('Minify_YUICompressor : $jarFile('.self::$jarFile.') is not a valid file.');
}
// if (! is_executable(self::$jarFile)) {
// throw new Exception('Minify_YUICompressor : $jarFile('.self::$jarFile.') is not executable.');
// }
if (! is_dir(self::$tempDir)) {
throw new Exception('Minify_YUICompressor : $tempDir('.self::$tempDir.') is not a valid direcotry.');
}
if (! is_writable(self::$tempDir)) {
throw new Exception('Minify_YUICompressor : $tempDir('.self::$tempDir.') is not writable.');
}
}
and that works fine.